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