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