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