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