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