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