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