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