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