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