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