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