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