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