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