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