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