Jacob's patch to improve Close On Exit behaviour
[u/mdw/putty] / windlg.c
1 #include <windows.h>
2 #include <commctrl.h>
3 #include <commdlg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <ctype.h>
7
8 #include "ssh.h"
9 #include "putty.h"
10 #include "winstuff.h"
11 #include "win_res.h"
12 #include "storage.h"
13
14 static char **events = NULL;
15 static int nevents = 0, negsize = 0;
16
17 static int readytogo;
18
19 void force_normal(HWND hwnd)
20 {
21 static int recurse = 0;
22
23 WINDOWPLACEMENT wp;
24
25 if(recurse) return;
26 recurse = 1;
27
28 wp.length = sizeof(wp);
29 if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED)
30 {
31 wp.showCmd = SW_SHOWNORMAL;
32 SetWindowPlacement(hwnd, &wp);
33 }
34 recurse = 0;
35 }
36
37 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
38 BOOL ok;
39 int n;
40 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
41 if (ok)
42 *result = n;
43 }
44
45 static int CALLBACK LogProc (HWND hwnd, UINT msg,
46 WPARAM wParam, LPARAM lParam) {
47 int i;
48
49 switch (msg) {
50 case WM_INITDIALOG:
51 for (i=0; i<nevents; i++)
52 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
53 0, (LPARAM)events[i]);
54 return 1;
55 case WM_COMMAND:
56 switch (LOWORD(wParam)) {
57 case IDOK:
58 case IDCANCEL:
59 logbox = NULL;
60 SetActiveWindow(GetParent(hwnd));
61 DestroyWindow (hwnd);
62 return 0;
63 case IDN_COPY:
64 if (HIWORD(wParam) == BN_CLICKED ||
65 HIWORD(wParam) == BN_DOUBLECLICKED) {
66 int selcount;
67 int *selitems;
68 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
69 LB_GETSELCOUNT, 0, 0);
70 if (selcount == 0) { /* don't even try to copy zero items */
71 MessageBeep(0);
72 break;
73 }
74
75 selitems = smalloc(selcount * sizeof(int));
76 if (selitems) {
77 int count = SendDlgItemMessage(hwnd, IDN_LIST,
78 LB_GETSELITEMS,
79 selcount, (LPARAM)selitems);
80 int i;
81 int size;
82 char *clipdata;
83 static unsigned char sel_nl[] = SEL_NL;
84
85 if (count == 0) { /* can't copy zero stuff */
86 MessageBeep(0);
87 break;
88 }
89
90 size = 0;
91 for (i = 0; i < count; i++)
92 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
93
94 clipdata = smalloc(size);
95 if (clipdata) {
96 char *p = clipdata;
97 for (i = 0; i < count; i++) {
98 char *q = events[selitems[i]];
99 int qlen = strlen(q);
100 memcpy(p, q, qlen);
101 p += qlen;
102 memcpy(p, sel_nl, sizeof(sel_nl));
103 p += sizeof(sel_nl);
104 }
105 write_clip(clipdata, size, TRUE);
106 sfree(clipdata);
107 }
108 sfree(selitems);
109
110 for (i = 0; i < nevents; i++)
111 SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
112 FALSE, i);
113 }
114 }
115 return 0;
116 }
117 return 0;
118 case WM_CLOSE:
119 logbox = NULL;
120 SetActiveWindow(GetParent(hwnd));
121 DestroyWindow (hwnd);
122 return 0;
123 }
124 return 0;
125 }
126
127 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
128 WPARAM wParam, LPARAM lParam) {
129 switch (msg) {
130 case WM_INITDIALOG:
131 return 1;
132 case WM_COMMAND:
133 switch (LOWORD(wParam)) {
134 case IDOK:
135 EndDialog(hwnd, 1);
136 return 0;
137 }
138 return 0;
139 case WM_CLOSE:
140 EndDialog(hwnd, 1);
141 return 0;
142 }
143 return 0;
144 }
145
146 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
147 WPARAM wParam, LPARAM lParam) {
148 switch (msg) {
149 case WM_INITDIALOG:
150 SetDlgItemText (hwnd, IDA_VERSION, ver);
151 return 1;
152 case WM_COMMAND:
153 switch (LOWORD(wParam)) {
154 case IDOK:
155 case IDCANCEL:
156 EndDialog(hwnd, TRUE);
157 return 0;
158 case IDA_LICENCE:
159 EnableWindow(hwnd, 0);
160 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
161 NULL, LicenceProc);
162 EnableWindow(hwnd, 1);
163 SetActiveWindow(hwnd);
164 return 0;
165 }
166 return 0;
167 case WM_CLOSE:
168 EndDialog(hwnd, TRUE);
169 return 0;
170 }
171 return 0;
172 }
173
174 /*
175 * Null dialog procedure.
176 */
177 static int CALLBACK NullDlgProc (HWND hwnd, UINT msg,
178 WPARAM wParam, LPARAM lParam) {
179 return 0;
180 }
181
182 static char savedsession[2048];
183
184 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
185
186 sessionpanelstart,
187 IDC_TITLE_SESSION,
188 IDC_BOX_SESSION1,
189 IDC_BOX_SESSION2,
190 IDC_BOX_SESSION3,
191 IDC_HOSTSTATIC,
192 IDC_HOST,
193 IDC_PORTSTATIC,
194 IDC_PORT,
195 IDC_PROTSTATIC,
196 IDC_PROTRAW,
197 IDC_PROTTELNET,
198 IDC_PROTRLOGIN,
199 IDC_PROTSSH,
200 IDC_SESSSTATIC,
201 IDC_SESSEDIT,
202 IDC_SESSLIST,
203 IDC_SESSLOAD,
204 IDC_SESSSAVE,
205 IDC_SESSDEL,
206 IDC_CLOSEEXIT,
207 IDC_COEALWAYS,
208 IDC_COENORMAL,
209 IDC_COENEVER,
210 sessionpanelend,
211
212 loggingpanelstart,
213 IDC_BOX_LOGGING1,
214 IDC_LSTATSTATIC,
215 IDC_LSTATOFF,
216 IDC_LSTATASCII,
217 IDC_LSTATRAW,
218 IDC_LGFSTATIC,
219 IDC_LGFEDIT,
220 IDC_LGFBUTTON,
221 loggingpanelend,
222
223 keyboardpanelstart,
224 IDC_TITLE_KEYBOARD,
225 IDC_BOX_KEYBOARD1,
226 IDC_BOX_KEYBOARD2,
227 IDC_BOX_KEYBOARD3,
228 IDC_DELSTATIC,
229 IDC_DEL008,
230 IDC_DEL127,
231 IDC_HOMESTATIC,
232 IDC_HOMETILDE,
233 IDC_HOMERXVT,
234 IDC_FUNCSTATIC,
235 IDC_FUNCTILDE,
236 IDC_FUNCLINUX,
237 IDC_FUNCXTERM,
238 IDC_FUNCVT400,
239 IDC_KPSTATIC,
240 IDC_KPNORMAL,
241 IDC_KPAPPLIC,
242 IDC_KPNH,
243 IDC_NOAPPLICK,
244 IDC_NOAPPLICC,
245 IDC_CURSTATIC,
246 IDC_CURNORMAL,
247 IDC_CURAPPLIC,
248 IDC_COMPOSEKEY,
249 keyboardpanelend,
250
251 terminalpanelstart,
252 IDC_TITLE_TERMINAL,
253 IDC_BOX_TERMINAL1,
254 IDC_BOX_TERMINAL2,
255 IDC_WRAPMODE,
256 IDC_DECOM,
257 IDC_LFHASCR,
258 IDC_BEEP,
259 IDC_BCE,
260 IDC_BLINKTEXT,
261 IDC_ECHOSTATIC,
262 IDC_ECHOBACKEND,
263 IDC_ECHOYES,
264 IDC_ECHONO,
265 IDC_EDITSTATIC,
266 IDC_EDITBACKEND,
267 IDC_EDITYES,
268 IDC_EDITNO,
269 terminalpanelend,
270
271 windowpanelstart,
272 IDC_TITLE_WINDOW,
273 IDC_BOX_WINDOW1,
274 IDC_BOX_WINDOW2,
275 IDC_BOX_WINDOW3,
276 IDC_ROWSSTATIC,
277 IDC_ROWSEDIT,
278 IDC_COLSSTATIC,
279 IDC_COLSEDIT,
280 IDC_LOCKSIZE,
281 IDC_SCROLLBAR,
282 IDC_CLOSEWARN,
283 IDC_SAVESTATIC,
284 IDC_SAVEEDIT,
285 IDC_ALTF4,
286 IDC_ALTSPACE,
287 IDC_ALTONLY,
288 IDC_SCROLLKEY,
289 IDC_SCROLLDISP,
290 IDC_ALWAYSONTOP,
291 windowpanelend,
292
293 appearancepanelstart,
294 IDC_TITLE_APPEARANCE,
295 IDC_BOX_APPEARANCE1,
296 IDC_BOX_APPEARANCE2,
297 IDC_BOX_APPEARANCE3,
298 IDC_BOX_APPEARANCE4,
299 IDC_CURSORSTATIC,
300 IDC_CURBLOCK,
301 IDC_CURUNDER,
302 IDC_CURVERT,
303 IDC_BLINKCUR,
304 IDC_FONTSTATIC,
305 IDC_CHOOSEFONT,
306 IDC_WINTITLE,
307 IDC_WINEDIT,
308 IDC_WINNAME,
309 IDC_HIDEMOUSE,
310 appearancepanelend,
311
312 connectionpanelstart,
313 IDC_TITLE_CONNECTION,
314 IDC_BOX_CONNECTION1,
315 IDC_BOX_CONNECTION2,
316 IDC_TTSTATIC,
317 IDC_TTEDIT,
318 IDC_LOGSTATIC,
319 IDC_LOGEDIT,
320 IDC_PINGSTATIC,
321 IDC_PINGEDIT,
322 connectionpanelend,
323
324 telnetpanelstart,
325 IDC_TITLE_TELNET,
326 IDC_BOX_TELNET1,
327 IDC_BOX_TELNET2,
328 IDC_TSSTATIC,
329 IDC_TSEDIT,
330 IDC_ENVSTATIC,
331 IDC_VARSTATIC,
332 IDC_VAREDIT,
333 IDC_VALSTATIC,
334 IDC_VALEDIT,
335 IDC_ENVLIST,
336 IDC_ENVADD,
337 IDC_ENVREMOVE,
338 IDC_EMSTATIC,
339 IDC_EMBSD,
340 IDC_EMRFC,
341 telnetpanelend,
342
343 rloginpanelstart,
344 IDC_TITLE_RLOGIN,
345 IDC_BOX_RLOGIN1,
346 IDC_BOX_RLOGIN2,
347 IDC_R_TSSTATIC,
348 IDC_R_TSEDIT,
349 IDC_RLLUSERSTATIC,
350 IDC_RLLUSEREDIT,
351 rloginpanelend,
352
353 sshpanelstart,
354 IDC_TITLE_SSH,
355 IDC_BOX_SSH1,
356 IDC_BOX_SSH2,
357 IDC_BOX_SSH3,
358 IDC_NOPTY,
359 IDC_CIPHERSTATIC,
360 IDC_CIPHER3DES,
361 IDC_CIPHERBLOWF,
362 IDC_CIPHERDES,
363 IDC_BUGGYMAC,
364 IDC_AUTHTIS,
365 IDC_PKSTATIC,
366 IDC_PKEDIT,
367 IDC_PKBUTTON,
368 IDC_SSHPROTSTATIC,
369 IDC_SSHPROT1,
370 IDC_SSHPROT2,
371 IDC_AGENTFWD,
372 IDC_CMDSTATIC,
373 IDC_CMDEDIT,
374 IDC_COMPRESS,
375 sshpanelend,
376
377 selectionpanelstart,
378 IDC_TITLE_SELECTION,
379 IDC_BOX_SELECTION1,
380 IDC_BOX_SELECTION2,
381 IDC_MBSTATIC,
382 IDC_MBWINDOWS,
383 IDC_MBXTERM,
384 IDC_CCSTATIC,
385 IDC_CCLIST,
386 IDC_CCSET,
387 IDC_CCSTATIC2,
388 IDC_CCEDIT,
389 selectionpanelend,
390
391 colourspanelstart,
392 IDC_TITLE_COLOURS,
393 IDC_BOX_COLOURS1,
394 IDC_BOX_COLOURS2,
395 IDC_BOLDCOLOUR,
396 IDC_PALETTE,
397 IDC_COLOURSTATIC,
398 IDC_COLOURLIST,
399 IDC_RSTATIC,
400 IDC_GSTATIC,
401 IDC_BSTATIC,
402 IDC_RVALUE,
403 IDC_GVALUE,
404 IDC_BVALUE,
405 IDC_CHANGE,
406 colourspanelend,
407
408 translationpanelstart,
409 IDC_TITLE_TRANSLATION,
410 IDC_BOX_TRANSLATION1,
411 IDC_BOX_TRANSLATION2,
412 IDC_BOX_TRANSLATION3,
413 IDC_XLATSTATIC,
414 IDC_NOXLAT,
415 IDC_KOI8WIN1251,
416 IDC_88592WIN1250,
417 IDC_88592CP852,
418 IDC_CAPSLOCKCYR,
419 IDC_VTSTATIC,
420 IDC_VTXWINDOWS,
421 IDC_VTOEMANSI,
422 IDC_VTOEMONLY,
423 IDC_VTPOORMAN,
424 translationpanelend,
425
426 tunnelspanelstart,
427 IDC_TITLE_TUNNELS,
428 IDC_BOX_TUNNELS,
429 IDC_X11_FORWARD,
430 IDC_X11_DISPSTATIC,
431 IDC_X11_DISPLAY,
432 tunnelspanelend,
433
434 controlendvalue
435 };
436
437 static const char *const colours[] = {
438 "Default Foreground", "Default Bold Foreground",
439 "Default Background", "Default Bold Background",
440 "Cursor Text", "Cursor Colour",
441 "ANSI Black", "ANSI Black Bold",
442 "ANSI Red", "ANSI Red Bold",
443 "ANSI Green", "ANSI Green Bold",
444 "ANSI Yellow", "ANSI Yellow Bold",
445 "ANSI Blue", "ANSI Blue Bold",
446 "ANSI Magenta", "ANSI Magenta Bold",
447 "ANSI Cyan", "ANSI Cyan Bold",
448 "ANSI White", "ANSI White Bold"
449 };
450 static const int permcolour[] = {
451 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
452 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
453 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
454 };
455
456 static void fmtfont (char *buf) {
457 sprintf (buf, "Font: %s, ", cfg.font);
458 if (cfg.fontisbold)
459 strcat(buf, "bold, ");
460 if (cfg.fontheight == 0)
461 strcat (buf, "default height");
462 else
463 sprintf (buf+strlen(buf), "%d-%s",
464 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
465 (cfg.fontheight < 0 ? "pixel" : "point"));
466 }
467
468 static void init_dlg_ctrls(HWND hwnd) {
469 int i;
470 char fontstatic[256];
471
472 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
473 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
474 {
475 int i, n;
476 n = SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_GETCOUNT, 0, 0);
477 for (i=n; i-- >0 ;)
478 SendDlgItemMessage (hwnd, IDC_SESSLIST,
479 LB_DELETESTRING, i, 0);
480 for (i = 0; i < nsessions; i++)
481 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
482 0, (LPARAM) (sessions[i]));
483 }
484 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
485 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
486 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
487 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET :
488 cfg.protocol==PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW );
489 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
490
491 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
492 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
493 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
494 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
495 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
496 cfg.funky_type == 0 ? IDC_FUNCTILDE :
497 cfg.funky_type == 1 ? IDC_FUNCLINUX :
498 cfg.funky_type == 2 ? IDC_FUNCXTERM :
499 cfg.funky_type == 3 ? IDC_FUNCVT400 :
500 IDC_FUNCTILDE );
501 CheckDlgButton (hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
502 CheckDlgButton (hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
503 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
504 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
505 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
506 cfg.nethack_keypad ? IDC_KPNH :
507 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
508 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
509 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
510 CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
511 CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
512 CheckRadioButton (hwnd, IDC_ECHOBACKEND, IDC_ECHONO,
513 cfg.localecho == LD_BACKEND ? IDC_ECHOBACKEND:
514 cfg.localecho == LD_YES ? IDC_ECHOYES : IDC_ECHONO);
515 CheckRadioButton (hwnd, IDC_EDITBACKEND, IDC_EDITNO,
516 cfg.localedit == LD_BACKEND ? IDC_EDITBACKEND:
517 cfg.localedit == LD_YES ? IDC_EDITYES : IDC_EDITNO);
518 CheckDlgButton (hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
519 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
520 CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
521
522 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
523 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
524 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
525 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
526 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
527 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
528 fmtfont (fontstatic);
529 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
530 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
531 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
532 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
533
534 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
535 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
536 CheckDlgButton (hwnd, IDC_HIDEMOUSE, cfg.hide_mouseptr);
537 CheckRadioButton (hwnd, IDC_CURBLOCK, IDC_CURVERT,
538 cfg.cursor_type==0 ? IDC_CURBLOCK :
539 cfg.cursor_type==1 ? IDC_CURUNDER : IDC_CURVERT);
540 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
541 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
542 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
543 CheckRadioButton (hwnd, IDC_COEALWAYS, IDC_COENEVER,
544 cfg.close_on_exit==COE_NEVER ? IDC_COENEVER :
545 cfg.close_on_exit==COE_NORMAL ? IDC_COENORMAL : IDC_COEALWAYS);
546 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
547
548 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
549 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
550 SetDlgItemText (hwnd, IDC_R_TSEDIT, cfg.termspeed);
551 SetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername);
552 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
553 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
554 CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
555 cfg.logtype == 0 ? IDC_LSTATOFF :
556 cfg.logtype == 1 ? IDC_LSTATASCII :
557 IDC_LSTATRAW);
558 {
559 char *p = cfg.environmt;
560 while (*p) {
561 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
562 (LPARAM) p);
563 p += strlen(p)+1;
564 }
565 }
566 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
567 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
568
569 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
570 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
571 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
572 CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
573 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
574 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
575 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
576 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
577 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
578 IDC_CIPHER3DES);
579 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
580 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
581 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
582 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
583 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
584
585 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
586 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
587 {
588 static int tabs[4] = {25, 61, 96, 128};
589 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
590 (LPARAM) tabs);
591 }
592 for (i=0; i<256; i++) {
593 char str[100];
594 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
595 (i>=0x21 && i != 0x7F) ? i : ' ',
596 cfg.wordness[i]);
597 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
598 (LPARAM) str);
599 }
600
601 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
602 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
603 {
604 int i, n;
605 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
606 for (i=n; i-- >0 ;)
607 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
608 LB_DELETESTRING, i, 0);
609 for (i=0; i<22; i++)
610 if (cfg.bold_colour || permcolour[i])
611 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
612 (LPARAM) colours[i]);
613 }
614 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
615 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
616 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
617 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
618
619 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
620 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
621 cfg.xlat_88592cp852 ? IDC_88592CP852 :
622 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
623 IDC_NOXLAT);
624 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
625 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
626 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
627 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
628 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
629 IDC_VTPOORMAN);
630
631 CheckDlgButton (hwnd, IDC_X11_FORWARD, cfg.x11_forward);
632 SetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display);
633 }
634
635 struct treeview_faff {
636 HWND treeview;
637 HTREEITEM lastat[4];
638 };
639
640 static HTREEITEM treeview_insert(struct treeview_faff *faff,
641 int level, char *text) {
642 TVINSERTSTRUCT ins;
643 int i;
644 HTREEITEM newitem;
645 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
646 ins.hInsertAfter = faff->lastat[level];
647 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
648 #define INSITEM DUMMYUNIONNAME.item
649 #else
650 #define INSITEM item
651 #endif
652 ins.INSITEM.mask = TVIF_TEXT;
653 ins.INSITEM.pszText = text;
654 newitem = TreeView_InsertItem(faff->treeview, &ins);
655 if (level > 0)
656 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
657 faff->lastat[level] = newitem;
658 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
659 return newitem;
660 }
661
662 /*
663 * Create the panelfuls of controls in the configuration box.
664 */
665 static void create_controls(HWND hwnd, int dlgtype, int panel) {
666 if (panel == sessionpanelstart) {
667 /* The Session panel. Accelerators used: [acgo] nprtih elsd w */
668 struct ctlpos cp;
669 ctlposinit(&cp, hwnd, 80, 3, 13);
670 bartitle(&cp, "Basic options for your PuTTY session",
671 IDC_TITLE_SESSION);
672 if (dlgtype == 0) {
673 beginbox(&cp, "Specify your connection by host name",
674 IDC_BOX_SESSION1);
675 multiedit(&cp,
676 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
677 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
678 if (backends[3].backend == NULL) {
679 /* this is PuTTYtel, so only three protocols available */
680 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
681 "&Raw", IDC_PROTRAW,
682 "&Telnet", IDC_PROTTELNET,
683 "Rlog&in", IDC_PROTRLOGIN, NULL);
684 } else {
685 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
686 "&Raw", IDC_PROTRAW,
687 "&Telnet", IDC_PROTTELNET,
688 "Rlog&in", IDC_PROTRLOGIN,
689 #ifdef FWHACK
690 "SS&H/hack",
691 #else
692 "SS&H",
693 #endif
694 IDC_PROTSSH, NULL);
695 }
696 endbox(&cp);
697 beginbox(&cp, "Load, save or delete a stored session",
698 IDC_BOX_SESSION2);
699 sesssaver(&cp, "Sav&ed Sessions",
700 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
701 "&Load", IDC_SESSLOAD,
702 "&Save", IDC_SESSSAVE,
703 "&Delete", IDC_SESSDEL, NULL);
704 endbox(&cp);
705 }
706 beginbox(&cp, NULL, IDC_BOX_SESSION3);
707 radioline(&cp, "At session end, close &window:", IDC_CLOSEEXIT, 3,
708 "Always", IDC_COEALWAYS,
709 "On clean exit", IDC_COENORMAL,
710 "Never", IDC_COENEVER, NULL);
711 endbox(&cp);
712 }
713
714 if (panel == loggingpanelstart) {
715 /* The Logging panel. Accelerators used: [acgo] tplfw */
716 struct ctlpos cp;
717 ctlposinit(&cp, hwnd, 80, 3, 13);
718 bartitle(&cp, "Options controlling session logging",
719 IDC_TITLE_TERMINAL);
720 beginbox(&cp, NULL, IDC_BOX_LOGGING1);
721 radiobig(&cp,
722 "Session logging:", IDC_LSTATSTATIC,
723 "Logging &turned off completely", IDC_LSTATOFF,
724 "Log &printable output only", IDC_LSTATASCII,
725 "&Log all session output", IDC_LSTATRAW, NULL);
726 editbutton(&cp, "Log &file name:",
727 IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
728 IDC_LGFBUTTON);
729 endbox(&cp);
730 }
731
732 if (panel == terminalpanelstart) {
733 /* The Terminal panel. Accelerators used: [acgo] wdlben ht */
734 struct ctlpos cp;
735 ctlposinit(&cp, hwnd, 80, 3, 13);
736 bartitle(&cp, "Options controlling the terminal emulation",
737 IDC_TITLE_TERMINAL);
738 beginbox(&cp, "Set various terminal options",
739 IDC_BOX_TERMINAL1);
740 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
741 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
742 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
743 checkbox(&cp, "&Beep enabled", IDC_BEEP);
744 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
745 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
746 endbox(&cp);
747
748 beginbox(&cp, "Line discipline options",
749 IDC_BOX_TERMINAL2);
750 radioline(&cp, "Local ec&ho:", IDC_ECHOSTATIC, 3,
751 "Auto", IDC_ECHOBACKEND,
752 "Force on", IDC_ECHOYES,
753 "Force off", IDC_ECHONO, NULL);
754 radioline(&cp, "Local line edi&ting:", IDC_EDITSTATIC, 3,
755 "Auto", IDC_EDITBACKEND,
756 "Force on", IDC_EDITYES,
757 "Force off", IDC_EDITNO, NULL);
758 endbox(&cp);
759 }
760
761 if (panel == keyboardpanelstart) {
762 /* The Keyboard panel. Accelerators used: [acgo] h?sr~lxv unpymie t */
763 struct ctlpos cp;
764 ctlposinit(&cp, hwnd, 80, 3, 13);
765 bartitle(&cp, "Options controlling the effects of keys",
766 IDC_TITLE_KEYBOARD);
767 beginbox(&cp, "Change the sequences sent by:",
768 IDC_BOX_KEYBOARD1);
769 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
770 "Control-&H", IDC_DEL008,
771 "Control-&? (127)", IDC_DEL127, NULL);
772 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
773 "&Standard", IDC_HOMETILDE,
774 "&rxvt", IDC_HOMERXVT, NULL);
775 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
776 "ESC[n&~", IDC_FUNCTILDE,
777 "&Linux", IDC_FUNCLINUX,
778 "&Xterm R6", IDC_FUNCXTERM,
779 "&VT400", IDC_FUNCVT400, NULL);
780 endbox(&cp);
781 beginbox(&cp, "Application keypad settings:",
782 IDC_BOX_KEYBOARD2);
783 checkbox(&cp,
784 "Application c&ursor keys totally disabled",
785 IDC_NOAPPLICC);
786 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
787 "&Normal", IDC_CURNORMAL,
788 "A&pplication", IDC_CURAPPLIC, NULL);
789 checkbox(&cp,
790 "Application ke&ypad keys totally disabled",
791 IDC_NOAPPLICK);
792 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
793 "Nor&mal", IDC_KPNORMAL,
794 "Appl&ication", IDC_KPAPPLIC,
795 "N&etHack", IDC_KPNH, NULL);
796 endbox(&cp);
797 beginbox(&cp, "Enable extra keyboard features:",
798 IDC_BOX_KEYBOARD3);
799 checkbox(&cp, "Application and AltGr ac&t as Compose key",
800 IDC_COMPOSEKEY);
801 endbox(&cp);
802 }
803
804 if (panel == windowpanelstart) {
805 /* The Window panel. Accelerators used: [acgo] rmz sdkp w4ylt */
806 struct ctlpos cp;
807 ctlposinit(&cp, hwnd, 80, 3, 13);
808 bartitle(&cp, "Options controlling PuTTY's window",
809 IDC_TITLE_WINDOW);
810 beginbox(&cp, "Set the size of the window",
811 IDC_BOX_WINDOW1);
812 multiedit(&cp,
813 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
814 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
815 NULL);
816 checkbox(&cp, "Lock window size against resi&zing", IDC_LOCKSIZE);
817 endbox(&cp);
818 beginbox(&cp, "Control the scrollback in the window",
819 IDC_BOX_WINDOW2);
820 staticedit(&cp, "Lines of &scrollback",
821 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
822 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
823 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
824 checkbox(&cp, "Reset scrollback on dis&play activity",
825 IDC_SCROLLDISP);
826 endbox(&cp);
827 beginbox(&cp, NULL, IDC_BOX_WINDOW3);
828 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
829 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
830 checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
831 checkbox(&cp, "System menu appears on A&LT alone", IDC_ALTONLY);
832 checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
833 endbox(&cp);
834 }
835
836 if (panel == appearancepanelstart) {
837 /* The Appearance panel. Accelerators used: [acgo] luvb h ti p */
838 struct ctlpos cp;
839 ctlposinit(&cp, hwnd, 80, 3, 13);
840 bartitle(&cp, "Options controlling PuTTY's appearance",
841 IDC_TITLE_APPEARANCE);
842 beginbox(&cp, "Adjust the use of the cursor",
843 IDC_BOX_APPEARANCE1);
844 radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
845 "B&lock", IDC_CURBLOCK,
846 "&Underline", IDC_CURUNDER,
847 "&Vertical line", IDC_CURVERT,
848 NULL);
849 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
850 endbox(&cp);
851 beginbox(&cp, "Set the font used in the terminal window",
852 IDC_BOX_APPEARANCE2);
853 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
854 endbox(&cp);
855 beginbox(&cp, "Adjust the use of the window title",
856 IDC_BOX_APPEARANCE3);
857 multiedit(&cp,
858 "Window &title:", IDC_WINTITLE,
859 IDC_WINEDIT, 100, NULL);
860 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
861 endbox(&cp);
862 beginbox(&cp, "Adjust the use of the mouse pointer",
863 IDC_BOX_APPEARANCE4);
864 checkbox(&cp, "Hide mouse &pointer when typing in window",
865 IDC_HIDEMOUSE);
866 endbox(&cp);
867 }
868
869 if (panel == translationpanelstart) {
870 /* The Translation panel. Accelerators used: [acgo] xbep t s */
871 struct ctlpos cp;
872 ctlposinit(&cp, hwnd, 80, 3, 13);
873 bartitle(&cp, "Options controlling character set translation",
874 IDC_TITLE_TRANSLATION);
875 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
876 IDC_BOX_TRANSLATION1);
877 radiobig(&cp,
878 "Handling of line drawing characters:", IDC_VTSTATIC,
879 "Font has &XWindows encoding", IDC_VTXWINDOWS,
880 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
881 "Use font in O&EM mode only", IDC_VTOEMONLY,
882 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
883 IDC_VTPOORMAN, NULL);
884 endbox(&cp);
885 beginbox(&cp, "Enable character set translation on received data",
886 IDC_BOX_TRANSLATION2);
887 radiobig(&cp,
888 "Character set &translation:", IDC_XLATSTATIC,
889 "None", IDC_NOXLAT,
890 "KOI8 / Win-1251", IDC_KOI8WIN1251,
891 "ISO-8859-2 / Win-1250", IDC_88592WIN1250,
892 "ISO-8859-2 / CP852", IDC_88592CP852, NULL);
893 endbox(&cp);
894 beginbox(&cp, "Enable character set translation on input data",
895 IDC_BOX_TRANSLATION3);
896 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
897 IDC_CAPSLOCKCYR);
898 endbox(&cp);
899 }
900
901 if (panel == selectionpanelstart) {
902 /* The Selection panel. Accelerators used: [acgo] wx hst */
903 struct ctlpos cp;
904 ctlposinit(&cp, hwnd, 80, 3, 13);
905 bartitle(&cp, "Options controlling copy and paste",
906 IDC_TITLE_SELECTION);
907 beginbox(&cp, "Control which mouse button does which thing",
908 IDC_BOX_SELECTION1);
909 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
910 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
911 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
912 NULL);
913 endbox(&cp);
914 beginbox(&cp, "Control the select-one-word-at-a-time mode",
915 IDC_BOX_SELECTION2);
916 charclass(&cp, "C&haracter classes:", IDC_CCSTATIC, IDC_CCLIST,
917 "&Set", IDC_CCSET, IDC_CCEDIT,
918 "&to class", IDC_CCSTATIC2);
919 endbox(&cp);
920 }
921
922 if (panel == colourspanelstart) {
923 /* The Colours panel. Accelerators used: [acgo] blum */
924 struct ctlpos cp;
925 ctlposinit(&cp, hwnd, 80, 3, 13);
926 bartitle(&cp, "Options controlling use of colours",
927 IDC_TITLE_COLOURS);
928 beginbox(&cp, "General options for colour usage",
929 IDC_BOX_COLOURS1);
930 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
931 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
932 endbox(&cp);
933 beginbox(&cp, "Adjust the precise colours PuTTY displays",
934 IDC_BOX_COLOURS2);
935 colouredit(&cp, "Select a colo&ur and then click to modify it:",
936 IDC_COLOURSTATIC, IDC_COLOURLIST,
937 "&Modify...", IDC_CHANGE,
938 "Red:", IDC_RSTATIC, IDC_RVALUE,
939 "Green:", IDC_GSTATIC, IDC_GVALUE,
940 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
941 endbox(&cp);
942 }
943
944 if (panel == connectionpanelstart) {
945 /* The Connection panel. Accelerators used: [acgo] tuk */
946 struct ctlpos cp;
947 ctlposinit(&cp, hwnd, 80, 3, 13);
948 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
949 if (dlgtype == 0) {
950 beginbox(&cp, "Data to send to the server",
951 IDC_BOX_CONNECTION1);
952 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
953 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
954 endbox(&cp);
955 }
956 beginbox(&cp, "Sending of null packets to keep session active",
957 IDC_BOX_CONNECTION2);
958 staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
959 IDC_PINGSTATIC, IDC_PINGEDIT, 20);
960 endbox(&cp);
961 }
962
963 if (panel == telnetpanelstart) {
964 /* The Telnet panel. Accelerators used: [acgo] svldr bf */
965 struct ctlpos cp;
966 ctlposinit(&cp, hwnd, 80, 3, 13);
967 if (dlgtype == 0) {
968 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
969 beginbox(&cp, "Data to send to the server",
970 IDC_BOX_TELNET1);
971 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
972 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
973 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
974 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
975 IDC_ENVLIST,
976 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
977 endbox(&cp);
978 beginbox(&cp, "Telnet protocol adjustments",
979 IDC_BOX_TELNET2);
980 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
981 "&BSD (commonplace)", IDC_EMBSD,
982 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
983 endbox(&cp);
984 }
985 }
986
987 if (panel == rloginpanelstart) {
988 /* The Rlogin panel. Accelerators used: [acgo] sl */
989 struct ctlpos cp;
990 ctlposinit(&cp, hwnd, 80, 3, 13);
991 if (dlgtype == 0) {
992 bartitle(&cp, "Options controlling Rlogin connections", IDC_TITLE_RLOGIN);
993 beginbox(&cp, "Data to send to the server",
994 IDC_BOX_RLOGIN1);
995 staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC, IDC_R_TSEDIT, 50);
996 staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC, IDC_RLLUSEREDIT, 50);
997 endbox(&cp);
998 }
999 }
1000
1001 if (panel == sshpanelstart) {
1002 /* The SSH panel. Accelerators used: [acgo] rmfkw pe123bd i */
1003 struct ctlpos cp;
1004 ctlposinit(&cp, hwnd, 80, 3, 13);
1005 if (dlgtype == 0) {
1006 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1007 beginbox(&cp, "Data to send to the server",
1008 IDC_BOX_SSH1);
1009 multiedit(&cp,
1010 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1011 NULL);
1012 endbox(&cp);
1013 beginbox(&cp, "Authentication options",
1014 IDC_BOX_SSH2);
1015 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1016 IDC_AUTHTIS);
1017 checkbox(&cp, "Allow agent &forwarding", IDC_AGENTFWD);
1018 editbutton(&cp, "Private &key file for authentication:",
1019 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1020 endbox(&cp);
1021 beginbox(&cp, "Protocol options",
1022 IDC_BOX_SSH3);
1023 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1024 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1025 radioline(&cp, "Preferred SSH protocol version:",
1026 IDC_SSHPROTSTATIC, 2,
1027 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1028 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1029 "&3DES", IDC_CIPHER3DES,
1030 "&Blowfish", IDC_CIPHERBLOWF,
1031 "&DES", IDC_CIPHERDES, NULL);
1032 checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1033 IDC_BUGGYMAC);
1034 endbox(&cp);
1035 }
1036 }
1037
1038 if (panel == tunnelspanelstart) {
1039 /* The Tunnels panel. Accelerators used: [acgo] ex */
1040 struct ctlpos cp;
1041 ctlposinit(&cp, hwnd, 80, 3, 13);
1042 if (dlgtype == 0) {
1043 bartitle(&cp, "Options controlling SSH tunnelling",
1044 IDC_TITLE_TUNNELS);
1045 beginbox(&cp, "X11 forwarding options",
1046 IDC_BOX_TUNNELS);
1047 checkbox(&cp, "&Enable X11 forwarding",
1048 IDC_X11_FORWARD);
1049 multiedit(&cp, "&X display location", IDC_X11_DISPSTATIC,
1050 IDC_X11_DISPLAY, 50, NULL);
1051 endbox(&cp);
1052 }
1053 }
1054 }
1055
1056 /*
1057 * This function is the configuration box.
1058 */
1059 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1060 WPARAM wParam, LPARAM lParam,
1061 int dlgtype) {
1062 HWND hw, treeview;
1063 struct treeview_faff tvfaff;
1064 HTREEITEM hsession;
1065 OPENFILENAME of;
1066 char filename[sizeof(cfg.keyfile)];
1067 CHOOSEFONT cf;
1068 LOGFONT lf;
1069 char fontstatic[256];
1070 char portname[32];
1071 struct servent * service;
1072 int i;
1073
1074 switch (msg) {
1075 case WM_INITDIALOG:
1076 readytogo = 0;
1077 SetWindowLong(hwnd, GWL_USERDATA, 0);
1078 /*
1079 * Centre the window.
1080 */
1081 { /* centre the window */
1082 RECT rs, rd;
1083
1084 hw = GetDesktopWindow();
1085 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1086 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1087 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1088 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1089 }
1090
1091 /*
1092 * Create the tree view.
1093 */
1094 {
1095 RECT r;
1096 WPARAM font;
1097 HWND tvstatic;
1098
1099 r.left = 3; r.right = r.left + 75;
1100 r.top = 3; r.bottom = r.top + 10;
1101 MapDialogRect(hwnd, &r);
1102 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1103 WS_CHILD | WS_VISIBLE,
1104 r.left, r.top,
1105 r.right-r.left, r.bottom-r.top,
1106 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1107 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1108 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1109
1110 r.left = 3; r.right = r.left + 75;
1111 r.top = 13; r.bottom = r.top + 206;
1112 MapDialogRect(hwnd, &r);
1113 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1114 WS_CHILD | WS_VISIBLE |
1115 WS_TABSTOP | TVS_HASLINES |
1116 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1117 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1118 r.left, r.top,
1119 r.right-r.left, r.bottom-r.top,
1120 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1121 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1122 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1123 tvfaff.treeview = treeview;
1124 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1125 }
1126
1127 /*
1128 * Set up the tree view contents.
1129 */
1130 hsession = treeview_insert(&tvfaff, 0, "Session");
1131 treeview_insert(&tvfaff, 1, "Logging");
1132 treeview_insert(&tvfaff, 0, "Terminal");
1133 treeview_insert(&tvfaff, 1, "Keyboard");
1134 treeview_insert(&tvfaff, 0, "Window");
1135 treeview_insert(&tvfaff, 1, "Appearance");
1136 treeview_insert(&tvfaff, 1, "Translation");
1137 treeview_insert(&tvfaff, 1, "Selection");
1138 treeview_insert(&tvfaff, 1, "Colours");
1139 treeview_insert(&tvfaff, 0, "Connection");
1140 if (dlgtype == 0) {
1141 treeview_insert(&tvfaff, 1, "Telnet");
1142 treeview_insert(&tvfaff, 1, "Rlogin");
1143 if (backends[3].backend != NULL) {
1144 treeview_insert(&tvfaff, 1, "SSH");
1145 treeview_insert(&tvfaff, 2, "Tunnels");
1146 }
1147 }
1148
1149 /*
1150 * Put the treeview selection on to the Session panel. This
1151 * should also cause creation of the relevant controls.
1152 */
1153 TreeView_SelectItem(treeview, hsession);
1154
1155 /*
1156 * Set focus into the first available control.
1157 */
1158 {
1159 HWND ctl;
1160 ctl = GetDlgItem(hwnd, IDC_HOST);
1161 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1162 SetFocus(ctl);
1163 }
1164
1165 SetWindowLong(hwnd, GWL_USERDATA, 1);
1166 return 0;
1167 case WM_LBUTTONUP:
1168 /*
1169 * Button release should trigger WM_OK if there was a
1170 * previous double click on the session list.
1171 */
1172 ReleaseCapture();
1173 if (readytogo)
1174 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1175 break;
1176 case WM_NOTIFY:
1177 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1178 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1179 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1180 TVITEM item;
1181 int j;
1182 char buffer[64];
1183 item.hItem = i;
1184 item.pszText = buffer;
1185 item.cchTextMax = sizeof(buffer);
1186 item.mask = TVIF_TEXT;
1187 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1188 for (j = controlstartvalue; j < controlendvalue; j++) {
1189 HWND item = GetDlgItem(hwnd, j);
1190 if (item)
1191 DestroyWindow(item);
1192 }
1193 if (!strcmp(buffer, "Session"))
1194 create_controls(hwnd, dlgtype, sessionpanelstart);
1195 if (!strcmp(buffer, "Logging"))
1196 create_controls(hwnd, dlgtype, loggingpanelstart);
1197 if (!strcmp(buffer, "Keyboard"))
1198 create_controls(hwnd, dlgtype, keyboardpanelstart);
1199 if (!strcmp(buffer, "Terminal"))
1200 create_controls(hwnd, dlgtype, terminalpanelstart);
1201 if (!strcmp(buffer, "Window"))
1202 create_controls(hwnd, dlgtype, windowpanelstart);
1203 if (!strcmp(buffer, "Appearance"))
1204 create_controls(hwnd, dlgtype, appearancepanelstart);
1205 if (!strcmp(buffer, "Tunnels"))
1206 create_controls(hwnd, dlgtype, tunnelspanelstart);
1207 if (!strcmp(buffer, "Connection"))
1208 create_controls(hwnd, dlgtype, connectionpanelstart);
1209 if (!strcmp(buffer, "Telnet"))
1210 create_controls(hwnd, dlgtype, telnetpanelstart);
1211 if (!strcmp(buffer, "Rlogin"))
1212 create_controls(hwnd, dlgtype, rloginpanelstart);
1213 if (!strcmp(buffer, "SSH"))
1214 create_controls(hwnd, dlgtype, sshpanelstart);
1215 if (!strcmp(buffer, "Selection"))
1216 create_controls(hwnd, dlgtype, selectionpanelstart);
1217 if (!strcmp(buffer, "Colours"))
1218 create_controls(hwnd, dlgtype, colourspanelstart);
1219 if (!strcmp(buffer, "Translation"))
1220 create_controls(hwnd, dlgtype, translationpanelstart);
1221
1222 init_dlg_ctrls(hwnd);
1223
1224 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1225 return 0;
1226 }
1227 break;
1228 case WM_COMMAND:
1229 /*
1230 * Only process WM_COMMAND once the dialog is fully formed.
1231 */
1232 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1233 case IDOK:
1234 if (*cfg.host)
1235 EndDialog (hwnd, 1);
1236 else
1237 MessageBeep (0);
1238 return 0;
1239 case IDCANCEL:
1240 EndDialog (hwnd, 0);
1241 return 0;
1242 case IDC_PROTTELNET:
1243 case IDC_PROTRLOGIN:
1244 case IDC_PROTSSH:
1245 case IDC_PROTRAW:
1246 if (HIWORD(wParam) == BN_CLICKED ||
1247 HIWORD(wParam) == BN_DOUBLECLICKED) {
1248 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1249 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1250 int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
1251 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN : PROT_RAW ;
1252 if ((cfg.protocol == PROT_SSH && cfg.port != 22) ||
1253 (cfg.protocol == PROT_TELNET && cfg.port != 23) ||
1254 (cfg.protocol == PROT_RLOGIN && cfg.port != 513)) {
1255 cfg.port = i ? 22 : j ? 23 : 513;
1256 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1257 }
1258 }
1259 break;
1260 case IDC_HOST:
1261 if (HIWORD(wParam) == EN_CHANGE)
1262 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1263 sizeof(cfg.host)-1);
1264 break;
1265 case IDC_PORT:
1266 if (HIWORD(wParam) == EN_CHANGE) {
1267 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1268 if (isdigit(portname[0]))
1269 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1270 else {
1271 service = getservbyname(portname, NULL);
1272 if (service) cfg.port = ntohs(service->s_port);
1273 else cfg.port = 0;
1274 }
1275 }
1276 break;
1277 case IDC_SESSEDIT:
1278 if (HIWORD(wParam) == EN_CHANGE) {
1279 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1280 (WPARAM) -1, 0);
1281 GetDlgItemText (hwnd, IDC_SESSEDIT,
1282 savedsession, sizeof(savedsession)-1);
1283 savedsession[sizeof(savedsession)-1] = '\0';
1284 }
1285 break;
1286 case IDC_SESSSAVE:
1287 if (HIWORD(wParam) == BN_CLICKED ||
1288 HIWORD(wParam) == BN_DOUBLECLICKED) {
1289 /*
1290 * Save a session
1291 */
1292 char str[2048];
1293 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1294 if (!*str) {
1295 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1296 LB_GETCURSEL, 0, 0);
1297 if (n == LB_ERR) {
1298 MessageBeep(0);
1299 break;
1300 }
1301 strcpy (str, sessions[n]);
1302 }
1303 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1304 get_sesslist (FALSE);
1305 get_sesslist (TRUE);
1306 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1307 0, 0);
1308 for (i = 0; i < nsessions; i++)
1309 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1310 0, (LPARAM) (sessions[i]));
1311 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1312 (WPARAM) -1, 0);
1313 }
1314 break;
1315 case IDC_SESSLIST:
1316 case IDC_SESSLOAD:
1317 if (LOWORD(wParam) == IDC_SESSLOAD &&
1318 HIWORD(wParam) != BN_CLICKED &&
1319 HIWORD(wParam) != BN_DOUBLECLICKED)
1320 break;
1321 if (LOWORD(wParam) == IDC_SESSLIST &&
1322 HIWORD(wParam) != LBN_DBLCLK)
1323 break;
1324 {
1325 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1326 LB_GETCURSEL, 0, 0);
1327 int isdef;
1328 if (n == LB_ERR) {
1329 MessageBeep(0);
1330 break;
1331 }
1332 isdef = !strcmp(sessions[n], "Default Settings");
1333 load_settings (sessions[n], !isdef, &cfg);
1334 init_dlg_ctrls(hwnd);
1335 if (!isdef)
1336 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1337 else
1338 SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1339 }
1340 if (LOWORD(wParam) == IDC_SESSLIST) {
1341 /*
1342 * A double-click on a saved session should
1343 * actually start the session, not just load it.
1344 * Unless it's Default Settings or some other
1345 * host-less set of saved settings.
1346 */
1347 if (*cfg.host) {
1348 readytogo = TRUE;
1349 SetCapture(hwnd);
1350 }
1351 }
1352 break;
1353 case IDC_SESSDEL:
1354 if (HIWORD(wParam) == BN_CLICKED ||
1355 HIWORD(wParam) == BN_DOUBLECLICKED) {
1356 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1357 LB_GETCURSEL, 0, 0);
1358 if (n == LB_ERR || n == 0) {
1359 MessageBeep(0);
1360 break;
1361 }
1362 del_settings(sessions[n]);
1363 get_sesslist (FALSE);
1364 get_sesslist (TRUE);
1365 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1366 0, 0);
1367 for (i = 0; i < nsessions; i++)
1368 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1369 0, (LPARAM) (sessions[i]));
1370 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1371 (WPARAM) -1, 0);
1372 }
1373 case IDC_PINGEDIT:
1374 if (HIWORD(wParam) == EN_CHANGE)
1375 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1376 break;
1377 case IDC_DEL008:
1378 case IDC_DEL127:
1379 if (HIWORD(wParam) == BN_CLICKED ||
1380 HIWORD(wParam) == BN_DOUBLECLICKED)
1381 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1382 break;
1383 case IDC_HOMETILDE:
1384 case IDC_HOMERXVT:
1385 if (HIWORD(wParam) == BN_CLICKED ||
1386 HIWORD(wParam) == BN_DOUBLECLICKED)
1387 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1388 break;
1389 case IDC_FUNCXTERM:
1390 if (HIWORD(wParam) == BN_CLICKED ||
1391 HIWORD(wParam) == BN_DOUBLECLICKED)
1392 cfg.funky_type = 2;
1393 break;
1394 case IDC_FUNCVT400:
1395 if (HIWORD(wParam) == BN_CLICKED ||
1396 HIWORD(wParam) == BN_DOUBLECLICKED)
1397 cfg.funky_type = 3;
1398 break;
1399 case IDC_FUNCTILDE:
1400 case IDC_FUNCLINUX:
1401 if (HIWORD(wParam) == BN_CLICKED ||
1402 HIWORD(wParam) == BN_DOUBLECLICKED)
1403 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1404 break;
1405 case IDC_KPNORMAL:
1406 case IDC_KPAPPLIC:
1407 if (HIWORD(wParam) == BN_CLICKED ||
1408 HIWORD(wParam) == BN_DOUBLECLICKED) {
1409 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1410 cfg.nethack_keypad = FALSE;
1411 }
1412 break;
1413 case IDC_KPNH:
1414 if (HIWORD(wParam) == BN_CLICKED ||
1415 HIWORD(wParam) == BN_DOUBLECLICKED) {
1416 cfg.app_keypad = FALSE;
1417 cfg.nethack_keypad = TRUE;
1418 }
1419 break;
1420 case IDC_CURNORMAL:
1421 case IDC_CURAPPLIC:
1422 if (HIWORD(wParam) == BN_CLICKED ||
1423 HIWORD(wParam) == BN_DOUBLECLICKED)
1424 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1425 break;
1426 case IDC_NOAPPLICC:
1427 if (HIWORD(wParam) == BN_CLICKED ||
1428 HIWORD(wParam) == BN_DOUBLECLICKED)
1429 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1430 break;
1431 case IDC_NOAPPLICK:
1432 if (HIWORD(wParam) == BN_CLICKED ||
1433 HIWORD(wParam) == BN_DOUBLECLICKED)
1434 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1435 break;
1436 case IDC_ALTF4:
1437 if (HIWORD(wParam) == BN_CLICKED ||
1438 HIWORD(wParam) == BN_DOUBLECLICKED)
1439 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1440 break;
1441 case IDC_ALTSPACE:
1442 if (HIWORD(wParam) == BN_CLICKED ||
1443 HIWORD(wParam) == BN_DOUBLECLICKED)
1444 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1445 break;
1446 case IDC_ALTONLY:
1447 if (HIWORD(wParam) == BN_CLICKED ||
1448 HIWORD(wParam) == BN_DOUBLECLICKED)
1449 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1450 break;
1451 case IDC_ECHOBACKEND:
1452 case IDC_ECHOYES:
1453 case IDC_ECHONO:
1454 if (HIWORD(wParam) == BN_CLICKED ||
1455 HIWORD(wParam) == BN_DOUBLECLICKED) {
1456 if (LOWORD(wParam)==IDC_ECHOBACKEND) cfg.localecho=LD_BACKEND;
1457 if (LOWORD(wParam)==IDC_ECHOYES) cfg.localecho=LD_YES;
1458 if (LOWORD(wParam)==IDC_ECHONO) cfg.localecho=LD_NO;
1459 }
1460 break;
1461 case IDC_EDITBACKEND:
1462 case IDC_EDITYES:
1463 case IDC_EDITNO:
1464 if (HIWORD(wParam) == BN_CLICKED ||
1465 HIWORD(wParam) == BN_DOUBLECLICKED) {
1466 if (LOWORD(wParam)==IDC_EDITBACKEND) cfg.localedit=LD_BACKEND;
1467 if (LOWORD(wParam)==IDC_EDITYES) cfg.localedit=LD_YES;
1468 if (LOWORD(wParam)==IDC_EDITNO) cfg.localedit=LD_NO;
1469 }
1470 break;
1471 case IDC_ALWAYSONTOP:
1472 if (HIWORD(wParam) == BN_CLICKED ||
1473 HIWORD(wParam) == BN_DOUBLECLICKED)
1474 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1475 break;
1476 case IDC_SCROLLKEY:
1477 if (HIWORD(wParam) == BN_CLICKED ||
1478 HIWORD(wParam) == BN_DOUBLECLICKED)
1479 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1480 break;
1481 case IDC_SCROLLDISP:
1482 if (HIWORD(wParam) == BN_CLICKED ||
1483 HIWORD(wParam) == BN_DOUBLECLICKED)
1484 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1485 break;
1486 case IDC_COMPOSEKEY:
1487 if (HIWORD(wParam) == BN_CLICKED ||
1488 HIWORD(wParam) == BN_DOUBLECLICKED)
1489 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1490 break;
1491 case IDC_WRAPMODE:
1492 if (HIWORD(wParam) == BN_CLICKED ||
1493 HIWORD(wParam) == BN_DOUBLECLICKED)
1494 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1495 break;
1496 case IDC_DECOM:
1497 if (HIWORD(wParam) == BN_CLICKED ||
1498 HIWORD(wParam) == BN_DOUBLECLICKED)
1499 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1500 break;
1501 case IDC_LFHASCR:
1502 if (HIWORD(wParam) == BN_CLICKED ||
1503 HIWORD(wParam) == BN_DOUBLECLICKED)
1504 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1505 break;
1506 case IDC_ROWSEDIT:
1507 if (HIWORD(wParam) == EN_CHANGE)
1508 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1509 break;
1510 case IDC_COLSEDIT:
1511 if (HIWORD(wParam) == EN_CHANGE)
1512 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1513 break;
1514 case IDC_SAVEEDIT:
1515 if (HIWORD(wParam) == EN_CHANGE)
1516 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1517 break;
1518 case IDC_CHOOSEFONT:
1519 lf.lfHeight = cfg.fontheight;
1520 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1521 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1522 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1523 lf.lfCharSet = cfg.fontcharset;
1524 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1525 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1526 lf.lfQuality = DEFAULT_QUALITY;
1527 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1528 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1529 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1530
1531 cf.lStructSize = sizeof(cf);
1532 cf.hwndOwner = hwnd;
1533 cf.lpLogFont = &lf;
1534 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1535 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1536
1537 if (ChooseFont (&cf)) {
1538 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1539 cfg.font[sizeof(cfg.font)-1] = '\0';
1540 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1541 cfg.fontcharset = lf.lfCharSet;
1542 cfg.fontheight = lf.lfHeight;
1543 fmtfont (fontstatic);
1544 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1545 }
1546 break;
1547 case IDC_BEEP:
1548 if (HIWORD(wParam) == BN_CLICKED ||
1549 HIWORD(wParam) == BN_DOUBLECLICKED)
1550 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1551 break;
1552 case IDC_BLINKTEXT:
1553 if (HIWORD(wParam) == BN_CLICKED ||
1554 HIWORD(wParam) == BN_DOUBLECLICKED)
1555 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1556 break;
1557 case IDC_BCE:
1558 if (HIWORD(wParam) == BN_CLICKED ||
1559 HIWORD(wParam) == BN_DOUBLECLICKED)
1560 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1561 break;
1562 case IDC_WINNAME:
1563 if (HIWORD(wParam) == BN_CLICKED ||
1564 HIWORD(wParam) == BN_DOUBLECLICKED)
1565 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1566 break;
1567 case IDC_HIDEMOUSE:
1568 if (HIWORD(wParam) == BN_CLICKED ||
1569 HIWORD(wParam) == BN_DOUBLECLICKED)
1570 cfg.hide_mouseptr = IsDlgButtonChecked (hwnd, IDC_HIDEMOUSE);
1571 break;
1572 case IDC_CURBLOCK:
1573 if (HIWORD(wParam) == BN_CLICKED ||
1574 HIWORD(wParam) == BN_DOUBLECLICKED)
1575 cfg.cursor_type = 0;
1576 break;
1577 case IDC_CURUNDER:
1578 if (HIWORD(wParam) == BN_CLICKED ||
1579 HIWORD(wParam) == BN_DOUBLECLICKED)
1580 cfg.cursor_type = 1;
1581 break;
1582 case IDC_CURVERT:
1583 if (HIWORD(wParam) == BN_CLICKED ||
1584 HIWORD(wParam) == BN_DOUBLECLICKED)
1585 cfg.cursor_type = 2;
1586 break;
1587 case IDC_BLINKCUR:
1588 if (HIWORD(wParam) == BN_CLICKED ||
1589 HIWORD(wParam) == BN_DOUBLECLICKED)
1590 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1591 break;
1592 case IDC_SCROLLBAR:
1593 if (HIWORD(wParam) == BN_CLICKED ||
1594 HIWORD(wParam) == BN_DOUBLECLICKED)
1595 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1596 break;
1597 case IDC_LOCKSIZE:
1598 if (HIWORD(wParam) == BN_CLICKED ||
1599 HIWORD(wParam) == BN_DOUBLECLICKED)
1600 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1601 break;
1602 case IDC_WINEDIT:
1603 if (HIWORD(wParam) == EN_CHANGE)
1604 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1605 sizeof(cfg.wintitle)-1);
1606 break;
1607 case IDC_COEALWAYS:
1608 case IDC_COENORMAL:
1609 case IDC_COENEVER:
1610 if (HIWORD(wParam) == BN_CLICKED ||
1611 HIWORD(wParam) == BN_DOUBLECLICKED) {
1612 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_COEALWAYS) ? COE_ALWAYS :
1613 IsDlgButtonChecked (hwnd, IDC_COENORMAL) ? COE_NORMAL :
1614 COE_NEVER;
1615 }
1616 break;
1617 case IDC_CLOSEWARN:
1618 if (HIWORD(wParam) == BN_CLICKED ||
1619 HIWORD(wParam) == BN_DOUBLECLICKED)
1620 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1621 break;
1622 case IDC_TTEDIT:
1623 if (HIWORD(wParam) == EN_CHANGE)
1624 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1625 sizeof(cfg.termtype)-1);
1626 break;
1627 case IDC_LGFEDIT:
1628 if (HIWORD(wParam) == EN_CHANGE)
1629 GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1630 sizeof(cfg.logfilename)-1);
1631 break;
1632 case IDC_LGFBUTTON:
1633 memset(&of, 0, sizeof(of));
1634 #ifdef OPENFILENAME_SIZE_VERSION_400
1635 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1636 #else
1637 of.lStructSize = sizeof(of);
1638 #endif
1639 of.hwndOwner = hwnd;
1640 of.lpstrFilter = "All Files\0*\0\0\0";
1641 of.lpstrCustomFilter = NULL;
1642 of.nFilterIndex = 1;
1643 of.lpstrFile = filename; strcpy(filename, cfg.logfilename);
1644 of.nMaxFile = sizeof(filename);
1645 of.lpstrFileTitle = NULL;
1646 of.lpstrInitialDir = NULL;
1647 of.lpstrTitle = "Select session log file";
1648 of.Flags = 0;
1649 if (GetSaveFileName(&of)) {
1650 strcpy(cfg.logfilename, filename);
1651 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
1652 }
1653 break;
1654 case IDC_LSTATOFF:
1655 case IDC_LSTATASCII:
1656 case IDC_LSTATRAW:
1657 if (HIWORD(wParam) == BN_CLICKED ||
1658 HIWORD(wParam) == BN_DOUBLECLICKED) {
1659 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1660 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1661 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1662 }
1663 break;
1664 case IDC_TSEDIT:
1665 case IDC_R_TSEDIT:
1666 if (HIWORD(wParam) == EN_CHANGE)
1667 GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
1668 sizeof(cfg.termspeed)-1);
1669 break;
1670 case IDC_LOGEDIT:
1671 if (HIWORD(wParam) == EN_CHANGE)
1672 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1673 sizeof(cfg.username)-1);
1674 break;
1675 case IDC_RLLUSEREDIT:
1676 if (HIWORD(wParam) == EN_CHANGE)
1677 GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
1678 sizeof(cfg.localusername)-1);
1679 break;
1680 case IDC_EMBSD:
1681 case IDC_EMRFC:
1682 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1683 break;
1684 case IDC_ENVADD:
1685 if (HIWORD(wParam) == BN_CLICKED ||
1686 HIWORD(wParam) == BN_DOUBLECLICKED) {
1687 char str[sizeof(cfg.environmt)];
1688 char *p;
1689 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1690 if (!*str) {
1691 MessageBeep(0);
1692 break;
1693 }
1694 p = str + strlen(str);
1695 *p++ = '\t';
1696 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1697 if (!*p) {
1698 MessageBeep(0);
1699 break;
1700 }
1701 p = cfg.environmt;
1702 while (*p) {
1703 while (*p) p++;
1704 p++;
1705 }
1706 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1707 strcpy (p, str);
1708 p[strlen(str)+1] = '\0';
1709 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1710 0, (LPARAM)str);
1711 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1712 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1713 } else {
1714 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1715 MB_OK | MB_ICONERROR);
1716 }
1717 }
1718 break;
1719 case IDC_ENVREMOVE:
1720 if (HIWORD(wParam) != BN_CLICKED &&
1721 HIWORD(wParam) != BN_DOUBLECLICKED)
1722 break;
1723 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1724 if (i == LB_ERR)
1725 MessageBeep (0);
1726 else {
1727 char *p, *q;
1728
1729 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1730 i, 0);
1731 p = cfg.environmt;
1732 while (i > 0) {
1733 if (!*p)
1734 goto disaster;
1735 while (*p) p++;
1736 p++;
1737 i--;
1738 }
1739 q = p;
1740 if (!*p)
1741 goto disaster;
1742 while (*p) p++;
1743 p++;
1744 while (*p) {
1745 while (*p)
1746 *q++ = *p++;
1747 *q++ = *p++;
1748 }
1749 *q = '\0';
1750 disaster:;
1751 }
1752 break;
1753 case IDC_NOPTY:
1754 if (HIWORD(wParam) == BN_CLICKED ||
1755 HIWORD(wParam) == BN_DOUBLECLICKED)
1756 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1757 break;
1758 case IDC_COMPRESS:
1759 if (HIWORD(wParam) == BN_CLICKED ||
1760 HIWORD(wParam) == BN_DOUBLECLICKED)
1761 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1762 break;
1763 case IDC_BUGGYMAC:
1764 if (HIWORD(wParam) == BN_CLICKED ||
1765 HIWORD(wParam) == BN_DOUBLECLICKED)
1766 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1767 break;
1768 case IDC_AGENTFWD:
1769 if (HIWORD(wParam) == BN_CLICKED ||
1770 HIWORD(wParam) == BN_DOUBLECLICKED)
1771 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1772 break;
1773 case IDC_CIPHER3DES:
1774 case IDC_CIPHERBLOWF:
1775 case IDC_CIPHERDES:
1776 if (HIWORD(wParam) == BN_CLICKED ||
1777 HIWORD(wParam) == BN_DOUBLECLICKED) {
1778 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1779 cfg.cipher = CIPHER_3DES;
1780 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1781 cfg.cipher = CIPHER_BLOWFISH;
1782 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1783 cfg.cipher = CIPHER_DES;
1784 }
1785 break;
1786 case IDC_SSHPROT1:
1787 case IDC_SSHPROT2:
1788 if (HIWORD(wParam) == BN_CLICKED ||
1789 HIWORD(wParam) == BN_DOUBLECLICKED) {
1790 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1791 cfg.sshprot = 1;
1792 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1793 cfg.sshprot = 2;
1794 }
1795 break;
1796 case IDC_AUTHTIS:
1797 if (HIWORD(wParam) == BN_CLICKED ||
1798 HIWORD(wParam) == BN_DOUBLECLICKED)
1799 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1800 break;
1801 case IDC_PKEDIT:
1802 if (HIWORD(wParam) == EN_CHANGE)
1803 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1804 sizeof(cfg.keyfile)-1);
1805 break;
1806 case IDC_CMDEDIT:
1807 if (HIWORD(wParam) == EN_CHANGE)
1808 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1809 sizeof(cfg.remote_cmd)-1);
1810 break;
1811 case IDC_PKBUTTON:
1812 memset(&of, 0, sizeof(of));
1813 #ifdef OPENFILENAME_SIZE_VERSION_400
1814 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1815 #else
1816 of.lStructSize = sizeof(of);
1817 #endif
1818 of.hwndOwner = hwnd;
1819 of.lpstrFilter = "All Files\0*\0\0\0";
1820 of.lpstrCustomFilter = NULL;
1821 of.nFilterIndex = 1;
1822 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1823 of.nMaxFile = sizeof(filename);
1824 of.lpstrFileTitle = NULL;
1825 of.lpstrInitialDir = NULL;
1826 of.lpstrTitle = "Select Public Key File";
1827 of.Flags = 0;
1828 if (GetOpenFileName(&of)) {
1829 strcpy(cfg.keyfile, filename);
1830 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1831 }
1832 break;
1833 case IDC_MBWINDOWS:
1834 case IDC_MBXTERM:
1835 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1836 break;
1837 case IDC_CCSET:
1838 {
1839 BOOL ok;
1840 int i;
1841 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1842
1843 if (!ok)
1844 MessageBeep (0);
1845 else {
1846 for (i=0; i<256; i++)
1847 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1848 i, 0)) {
1849 char str[100];
1850 cfg.wordness[i] = n;
1851 SendDlgItemMessage (hwnd, IDC_CCLIST,
1852 LB_DELETESTRING, i, 0);
1853 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1854 (i>=0x21 && i != 0x7F) ? i : ' ',
1855 cfg.wordness[i]);
1856 SendDlgItemMessage (hwnd, IDC_CCLIST,
1857 LB_INSERTSTRING, i,
1858 (LPARAM)str);
1859 }
1860 }
1861 }
1862 break;
1863 case IDC_BOLDCOLOUR:
1864 if (HIWORD(wParam) == BN_CLICKED ||
1865 HIWORD(wParam) == BN_DOUBLECLICKED) {
1866 int n, i;
1867 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1868 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1869 if (n != 12+10*cfg.bold_colour) {
1870 for (i=n; i-- >0 ;)
1871 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1872 LB_DELETESTRING, i, 0);
1873 for (i=0; i<22; i++)
1874 if (cfg.bold_colour || permcolour[i])
1875 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1876 LB_ADDSTRING, 0,
1877 (LPARAM) colours[i]);
1878 }
1879 }
1880 break;
1881 case IDC_PALETTE:
1882 if (HIWORD(wParam) == BN_CLICKED ||
1883 HIWORD(wParam) == BN_DOUBLECLICKED)
1884 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1885 break;
1886 case IDC_COLOURLIST:
1887 if (HIWORD(wParam) == LBN_DBLCLK ||
1888 HIWORD(wParam) == LBN_SELCHANGE) {
1889 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1890 0, 0);
1891 if (!cfg.bold_colour)
1892 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1893 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1894 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1895 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1896 }
1897 break;
1898 case IDC_CHANGE:
1899 if (HIWORD(wParam) == BN_CLICKED ||
1900 HIWORD(wParam) == BN_DOUBLECLICKED) {
1901 static CHOOSECOLOR cc;
1902 static DWORD custom[16] = {0}; /* zero initialisers */
1903 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1904 0, 0);
1905 if (!cfg.bold_colour)
1906 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1907 cc.lStructSize = sizeof(cc);
1908 cc.hwndOwner = hwnd;
1909 cc.hInstance = (HWND)hinst;
1910 cc.lpCustColors = custom;
1911 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1912 cfg.colours[i][2]);
1913 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1914 if (ChooseColor(&cc)) {
1915 cfg.colours[i][0] =
1916 (unsigned char) (cc.rgbResult & 0xFF);
1917 cfg.colours[i][1] =
1918 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1919 cfg.colours[i][2] =
1920 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1921 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1922 FALSE);
1923 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1924 FALSE);
1925 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1926 FALSE);
1927 }
1928 }
1929 break;
1930 case IDC_NOXLAT:
1931 case IDC_KOI8WIN1251:
1932 case IDC_88592WIN1250:
1933 case IDC_88592CP852:
1934 cfg.xlat_enablekoiwin =
1935 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1936 cfg.xlat_88592w1250 =
1937 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1938 cfg.xlat_88592cp852 =
1939 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1940 break;
1941 case IDC_CAPSLOCKCYR:
1942 if (HIWORD(wParam) == BN_CLICKED ||
1943 HIWORD(wParam) == BN_DOUBLECLICKED) {
1944 cfg.xlat_capslockcyr =
1945 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1946 }
1947 break;
1948 case IDC_VTXWINDOWS:
1949 case IDC_VTOEMANSI:
1950 case IDC_VTOEMONLY:
1951 case IDC_VTPOORMAN:
1952 cfg.vtmode =
1953 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1954 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1955 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1956 VT_POORMAN);
1957 break;
1958 case IDC_X11_FORWARD:
1959 if (HIWORD(wParam) == BN_CLICKED ||
1960 HIWORD(wParam) == BN_DOUBLECLICKED)
1961 cfg.x11_forward = IsDlgButtonChecked (hwnd, IDC_X11_FORWARD);
1962 break;
1963 case IDC_X11_DISPLAY:
1964 if (HIWORD(wParam) == EN_CHANGE)
1965 GetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display,
1966 sizeof(cfg.x11_display)-1);
1967 break;
1968 }
1969 return 0;
1970 case WM_CLOSE:
1971 EndDialog (hwnd, 0);
1972 return 0;
1973
1974 /* Grrr Explorer will maximize Dialogs! */
1975 case WM_SIZE:
1976 if (wParam == SIZE_MAXIMIZED)
1977 force_normal(hwnd);
1978 return 0;
1979 }
1980 return 0;
1981 }
1982
1983 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1984 WPARAM wParam, LPARAM lParam) {
1985 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1986 }
1987 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1988 EnableWindow(hwnd, 0);
1989 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1990 GetParent(hwnd), AboutProc);
1991 EnableWindow(hwnd, 1);
1992 SetActiveWindow(hwnd);
1993 }
1994 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1995 }
1996
1997 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1998 WPARAM wParam, LPARAM lParam) {
1999 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
2000 }
2001
2002 void defuse_showwindow(void) {
2003 /*
2004 * Work around the fact that the app's first call to ShowWindow
2005 * will ignore the default in favour of the shell-provided
2006 * setting.
2007 */
2008 {
2009 HWND hwnd;
2010 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2011 NULL, NullDlgProc);
2012 ShowWindow(hwnd, SW_HIDE);
2013 DestroyWindow(hwnd);
2014 }
2015 }
2016
2017 int do_config (void) {
2018 int ret;
2019
2020 get_sesslist(TRUE);
2021 savedsession[0] = '\0';
2022 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2023 get_sesslist(FALSE);
2024
2025 return ret;
2026 }
2027
2028 int do_reconfig (HWND hwnd) {
2029 Config backup_cfg;
2030 int ret;
2031
2032 backup_cfg = cfg; /* structure copy */
2033 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2034 if (!ret)
2035 cfg = backup_cfg; /* structure copy */
2036
2037 return ret;
2038 }
2039
2040 void logevent (char *string) {
2041 if (nevents >= negsize) {
2042 negsize += 64;
2043 events = srealloc (events, negsize * sizeof(*events));
2044 }
2045 events[nevents] = smalloc(1+strlen(string));
2046 strcpy (events[nevents], string);
2047 nevents++;
2048 if (logbox) {
2049 int count;
2050 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2051 0, (LPARAM)string);
2052 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2053 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
2054 }
2055 }
2056
2057 void showeventlog (HWND hwnd) {
2058 if (!logbox) {
2059 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2060 hwnd, LogProc);
2061 ShowWindow (logbox, SW_SHOWNORMAL);
2062 }
2063 SetActiveWindow(logbox);
2064 }
2065
2066 void showabout (HWND hwnd) {
2067 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),hwnd, AboutProc);
2068 }
2069
2070 void verify_ssh_host_key(char *host, int port, char *keytype,
2071 char *keystr, char *fingerprint) {
2072 int ret;
2073
2074 static const char absentmsg[] =
2075 "The server's host key is not cached in the registry. You\n"
2076 "have no guarantee that the server is the computer you\n"
2077 "think it is.\n"
2078 "The server's key fingerprint is:\n"
2079 "%s\n"
2080 "If you trust this host, hit Yes to add the key to\n"
2081 "PuTTY's cache and carry on connecting.\n"
2082 "If you do not trust this host, hit No to abandon the\n"
2083 "connection.\n";
2084
2085 static const char wrongmsg[] =
2086 "WARNING - POTENTIAL SECURITY BREACH!\n"
2087 "\n"
2088 "The server's host key does not match the one PuTTY has\n"
2089 "cached in the registry. This means that either the\n"
2090 "server administrator has changed the host key, or you\n"
2091 "have actually connected to another computer pretending\n"
2092 "to be the server.\n"
2093 "The new key fingerprint is:\n"
2094 "%s\n"
2095 "If you were expecting this change and trust the new key,\n"
2096 "hit Yes to update PuTTY's cache and continue connecting.\n"
2097 "If you want to carry on connecting but without updating\n"
2098 "the cache, hit No.\n"
2099 "If you want to abandon the connection completely, hit\n"
2100 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2101 "choice.\n";
2102
2103 static const char mbtitle[] = "PuTTY Security Alert";
2104
2105
2106 char message[160+ /* sensible fingerprint max size */
2107 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2108 sizeof(absentmsg) : sizeof(wrongmsg))];
2109
2110 /*
2111 * Verify the key against the registry.
2112 */
2113 ret = verify_host_key(host, port, keytype, keystr);
2114
2115 if (ret == 0) /* success - key matched OK */
2116 return;
2117 if (ret == 2) { /* key was different */
2118 int mbret;
2119 sprintf(message, wrongmsg, fingerprint);
2120 mbret = MessageBox(NULL, message, mbtitle,
2121 MB_ICONWARNING | MB_YESNOCANCEL);
2122 if (mbret == IDYES)
2123 store_host_key(host, port, keytype, keystr);
2124 if (mbret == IDCANCEL)
2125 exit(0);
2126 }
2127 if (ret == 1) { /* key was absent */
2128 int mbret;
2129 sprintf(message, absentmsg, fingerprint);
2130 mbret = MessageBox(NULL, message, mbtitle,
2131 MB_ICONWARNING | MB_YESNO);
2132 if (mbret == IDNO)
2133 exit(0);
2134 store_host_key(host, port, keytype, keystr);
2135 }
2136 }
2137
2138 /*
2139 * Ask whether to wipe a session log file before writing to it.
2140 * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2141 */
2142 int askappend(char *filename) {
2143 static const char mbtitle[] = "PuTTY Log to File";
2144 static const char msgtemplate[] =
2145 "The session log file \"%.*s\" already exists.\n"
2146 "You can overwrite it with a new session log,\n"
2147 "append your session log to the end of it,\n"
2148 "or disable session logging for this session.\n"
2149 "Hit Yes to wipe the file, No to append to it,\n"
2150 "or Cancel to disable logging.";
2151 char message[sizeof(msgtemplate) + FILENAME_MAX];
2152 int mbret;
2153 sprintf(message, msgtemplate, FILENAME_MAX, filename);
2154
2155 mbret = MessageBox(NULL, message, mbtitle,
2156 MB_ICONQUESTION | MB_YESNOCANCEL);
2157 if (mbret == IDYES)
2158 return 2;
2159 else if (mbret == IDNO)
2160 return 1;
2161 else
2162 return 0;
2163 }