13 #define MAIN_NPANELS 8
14 #define RECONF_NPANELS 5
16 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
18 static char **events = NULL;
19 static int nevents = 0, negsize = 0;
21 static HWND logbox = NULL, abtbox = NULL;
23 static char hex[16] = "0123456789ABCDEF";
25 static void mungestr(char *in, char *out) {
29 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
30 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
32 *out++ = hex[((unsigned char)*in) >> 4];
33 *out++ = hex[((unsigned char)*in) & 15];
43 static void unmungestr(char *in, char *out) {
45 if (*in == '%' && in[1] && in[2]) {
48 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
49 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
60 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
61 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
64 static void wppi(HKEY key, LPCTSTR name, int value) {
65 RegSetValueEx(key, name, 0, REG_DWORD,
66 (CONST BYTE *)&value, sizeof(value));
69 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
70 LPTSTR val, int len) {
75 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
77 strncpy(val, def, len);
82 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
83 DWORD type, val, size;
87 RegQueryValueEx(key, name, 0, &type,
88 (BYTE *)&val, &size) != ERROR_SUCCESS ||
89 size != sizeof(val) || type != REG_DWORD)
95 static HINSTANCE hinst;
99 static void save_settings (char *section, int do_host) {
101 HKEY subkey1, sesskey;
104 p = malloc(3*strlen(section)+1);
105 mungestr(section, p);
107 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
108 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
113 RegCloseKey(subkey1);
115 wppi (sesskey, "Present", 1);
117 wpps (sesskey, "HostName", cfg.host);
118 wppi (sesskey, "PortNumber", cfg.port);
120 for (i = 0; backends[i].backend != NULL; i++)
121 if (backends[i].protocol == cfg.protocol) {
122 p = backends[i].name;
125 wpps (sesskey, "Protocol", p);
127 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
128 wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
129 wpps (sesskey, "TerminalType", cfg.termtype);
130 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
132 char buf[2*sizeof(cfg.environmt)], *p, *q;
138 if (c == '=' || c == ',' || c == '\\')
148 wpps (sesskey, "Environment", buf);
150 wpps (sesskey, "UserName", cfg.username);
151 wppi (sesskey, "NoPTY", cfg.nopty);
152 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
153 cfg.cipher == CIPHER_DES ? "des" : "3des");
154 wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
155 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
156 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
157 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
158 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
159 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
160 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
161 wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
162 wppi (sesskey, "AltF4", cfg.alt_f4);
163 wppi (sesskey, "AltSpace", cfg.alt_space);
164 wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
165 wppi (sesskey, "ScrollbackLines", cfg.savelines);
166 wppi (sesskey, "DECOriginMode", cfg.dec_om);
167 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
168 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
169 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
170 wppi (sesskey, "TermWidth", cfg.width);
171 wppi (sesskey, "TermHeight", cfg.height);
172 wpps (sesskey, "Font", cfg.font);
173 wppi (sesskey, "FontIsBold", cfg.fontisbold);
174 wppi (sesskey, "FontCharSet", cfg.fontcharset);
175 wppi (sesskey, "FontHeight", cfg.fontheight);
176 wppi (sesskey, "FontVTMode", cfg.vtmode);
177 wppi (sesskey, "TryPalette", cfg.try_palette);
178 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
179 for (i=0; i<22; i++) {
180 char buf[20], buf2[30];
181 sprintf(buf, "Colour%d", i);
182 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
183 cfg.colours[i][1], cfg.colours[i][2]);
184 wpps (sesskey, buf, buf2);
186 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
187 for (i=0; i<256; i+=32) {
188 char buf[20], buf2[256];
190 sprintf(buf, "Wordness%d", i);
192 for (j=i; j<i+32; j++) {
193 sprintf(buf2+strlen(buf2), "%s%d",
194 (*buf2 ? "," : ""), cfg.wordness[j]);
196 wpps (sesskey, buf, buf2);
198 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
199 wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
200 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
202 RegCloseKey(sesskey);
205 static void del_session (char *section) {
209 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
212 p = malloc(3*strlen(section)+1);
213 mungestr(section, p);
214 RegDeleteKey(subkey1, p);
217 RegCloseKey(subkey1);
220 static void load_settings (char *section, int do_host) {
222 HKEY subkey1, sesskey;
226 p = malloc(3*strlen(section)+1);
227 mungestr(section, p);
229 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
232 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
235 RegCloseKey(subkey1);
240 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
241 gppi (sesskey, "PortNumber", default_port, &cfg.port);
243 gpps (sesskey, "Protocol", "default", prot, 10);
244 cfg.protocol = default_protocol;
245 for (i = 0; backends[i].backend != NULL; i++)
246 if (!strcmp(prot, backends[i].name)) {
247 cfg.protocol = backends[i].protocol;
251 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
252 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
253 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
254 sizeof(cfg.termtype));
255 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
256 sizeof(cfg.termspeed));
258 char buf[2*sizeof(cfg.environmt)], *p, *q;
259 gpps (sesskey, "Environment", "", buf, sizeof(buf));
263 while (*p && *p != ',') {
276 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
277 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
280 gpps (sesskey, "Cipher", "3des", cipher, 10);
281 if (!strcmp(cipher, "blowfish"))
282 cfg.cipher = CIPHER_BLOWFISH;
283 else if (!strcmp(cipher, "des"))
284 cfg.cipher = CIPHER_DES;
286 cfg.cipher = CIPHER_3DES;
288 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
289 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
290 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
291 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
292 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
293 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
294 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
295 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
296 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
297 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
298 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
299 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
300 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
301 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
302 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
303 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
304 gppi (sesskey, "TermWidth", 80, &cfg.width);
305 gppi (sesskey, "TermHeight", 24, &cfg.height);
306 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
307 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
308 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
309 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
310 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
311 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
312 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
313 for (i=0; i<22; i++) {
314 static char *defaults[] = {
315 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
316 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
317 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
318 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
319 "85,255,255", "187,187,187", "255,255,255"
321 char buf[20], buf2[30];
323 sprintf(buf, "Colour%d", i);
324 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
325 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
326 cfg.colours[i][0] = c0;
327 cfg.colours[i][1] = c1;
328 cfg.colours[i][2] = c2;
331 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
332 for (i=0; i<256; i+=32) {
333 static char *defaults[] = {
334 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
335 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
336 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
337 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
338 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
339 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
340 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
341 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
343 char buf[20], buf2[256], *p;
345 sprintf(buf, "Wordness%d", i);
346 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
348 for (j=i; j<i+32; j++) {
350 while (*p && *p != ',') p++;
351 if (*p == ',') *p++ = '\0';
352 cfg.wordness[j] = atoi(q);
355 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
356 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
357 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
359 RegCloseKey(sesskey);
362 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
365 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
370 static int CALLBACK LogProc (HWND hwnd, UINT msg,
371 WPARAM wParam, LPARAM lParam) {
376 for (i=0; i<nevents; i++)
377 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
378 0, (LPARAM)events[i]);
380 /* case WM_CTLCOLORDLG: */
381 /* return (int) GetStockObject (LTGRAY_BRUSH); */
383 switch (LOWORD(wParam)) {
386 DestroyWindow (hwnd);
392 DestroyWindow (hwnd);
398 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
399 WPARAM wParam, LPARAM lParam) {
404 switch (LOWORD(wParam)) {
407 DestroyWindow (hwnd);
413 DestroyWindow (hwnd);
419 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
420 WPARAM wParam, LPARAM lParam) {
423 SetDlgItemText (hwnd, IDA_VERSION, ver);
425 /* case WM_CTLCOLORDLG: */
426 /* return (int) GetStockObject (LTGRAY_BRUSH); */
427 /* case WM_CTLCOLORSTATIC: */
428 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
429 /* return (int) GetStockObject (LTGRAY_BRUSH); */
431 switch (LOWORD(wParam)) {
434 DestroyWindow (hwnd);
437 EnableWindow(hwnd, 0);
438 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
440 EnableWindow(hwnd, 1);
446 DestroyWindow (hwnd);
452 static int GeneralPanelProc (HWND hwnd, UINT msg,
453 WPARAM wParam, LPARAM lParam) {
456 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
458 /* case WM_CTLCOLORDLG: */
459 /* return (int) GetStockObject (LTGRAY_BRUSH); */
460 /* case WM_CTLCOLORSTATIC: */
461 /* case WM_CTLCOLORBTN: */
462 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
463 /* return (int) GetStockObject (LTGRAY_BRUSH); */
465 DestroyWindow (hwnd);
471 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
472 WPARAM wParam, LPARAM lParam) {
477 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
478 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
479 for (i = 0; i < nsessions; i++)
480 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
481 0, (LPARAM) (sessions[i]));
482 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
483 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
484 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
485 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
486 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
490 * Button release should trigger WM_OK if there was a
491 * previous double click on the session list.
495 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
498 switch (LOWORD(wParam)) {
499 case IDC0_PROTTELNET:
502 if (HIWORD(wParam) == BN_CLICKED ||
503 HIWORD(wParam) == BN_DOUBLECLICKED) {
504 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
505 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
506 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
507 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
508 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
509 cfg.port = i ? 22 : 23;
510 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
515 if (HIWORD(wParam) == EN_CHANGE)
516 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
520 if (HIWORD(wParam) == EN_CHANGE)
521 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
524 if (HIWORD(wParam) == BN_CLICKED ||
525 HIWORD(wParam) == BN_DOUBLECLICKED)
526 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
529 if (HIWORD(wParam) == BN_CLICKED ||
530 HIWORD(wParam) == BN_DOUBLECLICKED)
531 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
534 if (HIWORD(wParam) == EN_CHANGE)
535 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
539 if (HIWORD(wParam) == BN_CLICKED ||
540 HIWORD(wParam) == BN_DOUBLECLICKED) {
545 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
547 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
553 strcpy (str, sessions[n]);
555 save_settings (str, !!strcmp(str, "Default Settings"));
556 get_sesslist (FALSE);
558 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
560 for (i = 0; i < nsessions; i++)
561 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
562 0, (LPARAM) (sessions[i]));
563 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
569 if (LOWORD(wParam) == IDC0_SESSLOAD &&
570 HIWORD(wParam) != BN_CLICKED &&
571 HIWORD(wParam) != BN_DOUBLECLICKED)
573 if (LOWORD(wParam) == IDC0_SESSLIST &&
574 HIWORD(wParam) != LBN_DBLCLK)
577 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
583 load_settings (sessions[n],
584 !!strcmp(sessions[n], "Default Settings"));
585 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
586 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
587 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
588 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
589 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
590 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
591 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
592 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
595 if (LOWORD(wParam) == IDC0_SESSLIST) {
597 * A double-click on a saved session should
598 * actually start the session, not just load it.
599 * Unless it's Default Settings or some other
600 * host-less set of saved settings.
609 if (HIWORD(wParam) == BN_CLICKED ||
610 HIWORD(wParam) == BN_DOUBLECLICKED) {
611 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
613 if (n == LB_ERR || n == 0) {
617 del_session(sessions[n]);
618 get_sesslist (FALSE);
620 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
622 for (i = 0; i < nsessions; i++)
623 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
624 0, (LPARAM) (sessions[i]));
625 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
630 return GeneralPanelProc (hwnd, msg, wParam, lParam);
633 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
634 WPARAM wParam, LPARAM lParam) {
637 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
638 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
639 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
640 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
641 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
642 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
643 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
644 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
645 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
646 cfg.nethack_keypad ? IDC1_KPNH :
647 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
648 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
649 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
650 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
653 if (HIWORD(wParam) == BN_CLICKED ||
654 HIWORD(wParam) == BN_DOUBLECLICKED)
655 switch (LOWORD(wParam)) {
658 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
662 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
666 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
670 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
671 cfg.nethack_keypad = FALSE;
674 cfg.app_keypad = FALSE;
675 cfg.nethack_keypad = TRUE;
679 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
682 if (HIWORD(wParam) == BN_CLICKED ||
683 HIWORD(wParam) == BN_DOUBLECLICKED)
684 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
687 if (HIWORD(wParam) == BN_CLICKED ||
688 HIWORD(wParam) == BN_DOUBLECLICKED)
689 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
692 if (HIWORD(wParam) == BN_CLICKED ||
693 HIWORD(wParam) == BN_DOUBLECLICKED)
694 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
698 return GeneralPanelProc (hwnd, msg, wParam, lParam);
701 static void fmtfont (char *buf) {
702 sprintf (buf, "Font: %s, ", cfg.font);
704 strcat(buf, "bold, ");
705 if (cfg.fontheight == 0)
706 strcat (buf, "default height");
708 sprintf (buf+strlen(buf), "%d-%s",
709 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
710 (cfg.fontheight < 0 ? "pixel" : "point"));
713 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
714 WPARAM wParam, LPARAM lParam) {
717 char fontstatic[256];
721 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
722 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
723 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
724 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
725 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
726 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
727 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
728 fmtfont (fontstatic);
729 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
730 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
731 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
732 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
733 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
737 switch (LOWORD(wParam)) {
739 if (HIWORD(wParam) == BN_CLICKED ||
740 HIWORD(wParam) == BN_DOUBLECLICKED)
741 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
744 if (HIWORD(wParam) == BN_CLICKED ||
745 HIWORD(wParam) == BN_DOUBLECLICKED)
746 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
749 if (HIWORD(wParam) == BN_CLICKED ||
750 HIWORD(wParam) == BN_DOUBLECLICKED)
751 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
754 if (HIWORD(wParam) == BN_CLICKED ||
755 HIWORD(wParam) == BN_DOUBLECLICKED)
756 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
759 if (HIWORD(wParam) == EN_CHANGE)
760 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
763 if (HIWORD(wParam) == EN_CHANGE)
764 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
767 if (HIWORD(wParam) == EN_CHANGE)
768 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
770 case IDC2_CHOOSEFONT:
771 lf.lfHeight = cfg.fontheight;
772 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
773 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
774 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
775 lf.lfCharSet = cfg.fontcharset;
776 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
777 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
778 lf.lfQuality = DEFAULT_QUALITY;
779 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
780 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
781 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
783 cf.lStructSize = sizeof(cf);
786 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
787 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
789 if (ChooseFont (&cf)) {
790 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
791 cfg.font[sizeof(cfg.font)-1] = '\0';
792 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
793 cfg.fontcharset = lf.lfCharSet;
794 cfg.fontheight = lf.lfHeight;
795 fmtfont (fontstatic);
796 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
799 case IDC2_VTXWINDOWS:
804 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
805 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
806 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
812 return GeneralPanelProc (hwnd, msg, wParam, lParam);
815 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
816 WPARAM wParam, LPARAM lParam) {
821 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
822 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
823 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
825 char *p = cfg.environmt;
827 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
832 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
833 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
836 switch (LOWORD(wParam)) {
838 if (HIWORD(wParam) == EN_CHANGE)
839 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
840 sizeof(cfg.termtype)-1);
843 if (HIWORD(wParam) == EN_CHANGE)
844 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
845 sizeof(cfg.termspeed)-1);
848 if (HIWORD(wParam) == EN_CHANGE)
849 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
850 sizeof(cfg.username)-1);
854 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
857 if (HIWORD(wParam) == BN_CLICKED ||
858 HIWORD(wParam) == BN_DOUBLECLICKED) {
859 char str[sizeof(cfg.environmt)];
861 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
866 p = str + strlen(str);
868 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
878 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
880 p[strlen(str)+1] = '\0';
881 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
883 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
884 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
886 MessageBox(hwnd, "Environment too big", "PuTTY Error",
887 MB_OK | MB_ICONERROR);
892 if (HIWORD(wParam) != BN_CLICKED &&
893 HIWORD(wParam) != BN_DOUBLECLICKED)
895 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
901 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
928 return GeneralPanelProc (hwnd, msg, wParam, lParam);
931 static int CALLBACK SshProc (HWND hwnd, UINT msg,
932 WPARAM wParam, LPARAM lParam) {
935 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
936 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
937 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
938 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
939 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
940 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
943 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
946 switch (LOWORD(wParam)) {
948 if (HIWORD(wParam) == EN_CHANGE)
949 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
950 sizeof(cfg.termtype)-1);
953 if (HIWORD(wParam) == EN_CHANGE)
954 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
955 sizeof(cfg.username)-1);
958 if (HIWORD(wParam) == BN_CLICKED ||
959 HIWORD(wParam) == BN_DOUBLECLICKED)
960 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
962 case IDC3_CIPHER3DES:
963 case IDC3_CIPHERBLOWF:
965 if (HIWORD(wParam) == BN_CLICKED ||
966 HIWORD(wParam) == BN_DOUBLECLICKED) {
967 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
968 cfg.cipher = CIPHER_3DES;
969 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
970 cfg.cipher = CIPHER_BLOWFISH;
971 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
972 cfg.cipher = CIPHER_DES;
976 if (HIWORD(wParam) == BN_CLICKED ||
977 HIWORD(wParam) == BN_DOUBLECLICKED)
978 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
983 return GeneralPanelProc (hwnd, msg, wParam, lParam);
986 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
987 WPARAM wParam, LPARAM lParam) {
992 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
993 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
995 static int tabs[4] = {25, 61, 96, 128};
996 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
999 for (i=0; i<256; i++) {
1001 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1002 (i>=0x21 && i != 0x7F) ? i : ' ',
1004 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1009 switch (LOWORD(wParam)) {
1010 case IDC4_MBWINDOWS:
1012 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1018 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1023 for (i=0; i<256; i++)
1024 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1027 cfg.wordness[i] = n;
1028 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1029 LB_DELETESTRING, i, 0);
1030 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1031 (i>=0x21 && i != 0x7F) ? i : ' ',
1033 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1043 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1046 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1047 WPARAM wParam, LPARAM lParam) {
1048 static const char *const colours[] = {
1049 "Default Foreground", "Default Bold Foreground",
1050 "Default Background", "Default Bold Background",
1051 "Cursor Text", "Cursor Colour",
1052 "ANSI Black", "ANSI Black Bold",
1053 "ANSI Red", "ANSI Red Bold",
1054 "ANSI Green", "ANSI Green Bold",
1055 "ANSI Yellow", "ANSI Yellow Bold",
1056 "ANSI Blue", "ANSI Blue Bold",
1057 "ANSI Magenta", "ANSI Magenta Bold",
1058 "ANSI Cyan", "ANSI Cyan Bold",
1059 "ANSI White", "ANSI White Bold"
1061 static const int permanent[] = {
1062 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1063 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1064 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1068 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1069 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1072 for (i=0; i<22; i++)
1073 if (cfg.bold_colour || permanent[i])
1074 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1075 (LPARAM) colours[i]);
1077 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1078 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1079 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1080 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1083 switch (LOWORD(wParam)) {
1084 case IDC5_BOLDCOLOUR:
1085 if (HIWORD(wParam) == BN_CLICKED ||
1086 HIWORD(wParam) == BN_DOUBLECLICKED) {
1088 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1089 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1090 if (cfg.bold_colour && n!=22) {
1091 for (i=0; i<22; i++)
1093 SendDlgItemMessage (hwnd, IDC5_LIST,
1095 (LPARAM) colours[i]);
1096 } else if (!cfg.bold_colour && n!=12) {
1099 SendDlgItemMessage (hwnd, IDC5_LIST,
1100 LB_DELETESTRING, i, 0);
1105 if (HIWORD(wParam) == BN_CLICKED ||
1106 HIWORD(wParam) == BN_DOUBLECLICKED)
1107 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1110 if (HIWORD(wParam) == LBN_DBLCLK ||
1111 HIWORD(wParam) == LBN_SELCHANGE) {
1112 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1114 if (!cfg.bold_colour)
1115 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1116 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1117 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1118 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1122 if (HIWORD(wParam) == BN_CLICKED ||
1123 HIWORD(wParam) == BN_DOUBLECLICKED) {
1124 static CHOOSECOLOR cc;
1125 static DWORD custom[16] = {0}; /* zero initialisers */
1126 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1128 if (!cfg.bold_colour)
1129 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1130 cc.lStructSize = sizeof(cc);
1131 cc.hwndOwner = hwnd;
1132 cc.hInstance = (HWND)hinst;
1133 cc.lpCustColors = custom;
1134 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1136 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1137 if (ChooseColor(&cc)) {
1139 (unsigned char) (cc.rgbResult & 0xFF);
1141 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1143 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1144 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1146 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1148 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1156 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1159 static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
1160 WPARAM wParam, LPARAM lParam) {
1163 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1164 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1165 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1167 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1169 switch (LOWORD(wParam)) {
1171 case IDC6_KOI8WIN1251:
1172 case IDC6_88592WIN1250:
1173 cfg.xlat_enablekoiwin =
1174 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1175 cfg.xlat_88592w1250 =
1176 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1178 case IDC6_CAPSLOCKCYR:
1179 if (HIWORD(wParam) == BN_CLICKED ||
1180 HIWORD(wParam) == BN_DOUBLECLICKED) {
1181 cfg.xlat_capslockcyr =
1182 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1187 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1190 static DLGPROC panelproc[NPANELS] = {
1191 ConnectionProc, KeyboardProc, TerminalProc,
1192 TelnetProc, SshProc, SelectionProc, ColourProc, LanguageProc
1194 static char *panelids[NPANELS] = {
1195 MAKEINTRESOURCE(IDD_PANEL0),
1196 MAKEINTRESOURCE(IDD_PANEL1),
1197 MAKEINTRESOURCE(IDD_PANEL2),
1198 MAKEINTRESOURCE(IDD_PANEL3),
1199 MAKEINTRESOURCE(IDD_PANEL35),
1200 MAKEINTRESOURCE(IDD_PANEL4),
1201 MAKEINTRESOURCE(IDD_PANEL5),
1202 MAKEINTRESOURCE(IDD_PANEL6)
1205 static char *names[NPANELS] = {
1206 "Connection", "Keyboard", "Terminal", "Telnet",
1207 "SSH", "Selection", "Colours", "Language"
1210 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1211 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1213 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1214 WPARAM wParam, LPARAM lParam,
1215 int npanels, int *panelnums, HWND *page) {
1220 { /* centre the window */
1223 hw = GetDesktopWindow();
1224 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1225 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1226 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1227 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1230 { /* initialise the tab control */
1234 hw = GetDlgItem (hwnd, IDC_TAB);
1235 for (i=0; i<npanels; i++) {
1236 tab.mask = TCIF_TEXT;
1237 tab.pszText = names[panelnums[i]];
1238 TabCtrl_InsertItem (hw, i, &tab);
1240 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1241 hwnd, panelproc[panelnums[0]]);*/
1242 *page = CreateDialog (hinst, panelids[panelnums[0]],
1243 hwnd, panelproc[panelnums[0]]);
1244 SetWindowLong (*page, GWL_EXSTYLE,
1245 GetWindowLong (*page, GWL_EXSTYLE) |
1246 WS_EX_CONTROLPARENT);
1251 if (LOWORD(wParam) == IDC_TAB &&
1252 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1253 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1255 DestroyWindow (*page);
1256 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1257 hwnd, panelproc[panelnums[i]]);*/
1258 *page = CreateDialog (hinst, panelids[panelnums[i]],
1259 hwnd, panelproc[panelnums[i]]);
1260 SetWindowLong (*page, GWL_EXSTYLE,
1261 GetWindowLong (*page, GWL_EXSTYLE) |
1262 WS_EX_CONTROLPARENT);
1263 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1267 /* case WM_CTLCOLORDLG: */
1268 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1270 switch (LOWORD(wParam)) {
1273 EndDialog (hwnd, 1);
1278 EndDialog (hwnd, 0);
1283 EndDialog (hwnd, 0);
1289 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1290 WPARAM wParam, LPARAM lParam) {
1295 static HWND page = NULL;
1297 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1300 * If the Connection panel is active and the Session List
1301 * box is selected, we treat a press of Open to have an
1302 * implicit press of Load preceding it.
1304 hw = GetDlgItem (hwnd, IDC_TAB);
1305 i = TabCtrl_GetCurSel(hw);
1306 if (panelproc[mainp[i]] == ConnectionProc &&
1307 page && implicit_load_ok) {
1308 SendMessage (page, WM_COMMAND,
1309 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1313 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1314 EnableWindow(hwnd, 0);
1315 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1316 GetParent(hwnd), AboutProc);
1317 EnableWindow(hwnd, 1);
1319 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1320 MAIN_NPANELS, mainp, &page);
1323 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1324 WPARAM wParam, LPARAM lParam) {
1326 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1327 RECONF_NPANELS, reconfp, &page);
1330 void get_sesslist(int allocate) {
1331 static char *buffer;
1332 int buflen, bufsize, i, ret;
1333 char otherbuf[2048];
1338 if (RegCreateKey(HKEY_CURRENT_USER,
1339 puttystr, &subkey1) != ERROR_SUCCESS)
1342 buflen = bufsize = 0;
1346 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1347 if (ret == ERROR_SUCCESS) {
1348 bufsize = buflen + 2048;
1349 buffer = srealloc(buffer, bufsize);
1350 unmungestr(otherbuf, buffer+buflen);
1351 buflen += strlen(buffer+buflen)+1;
1353 } while (ret == ERROR_SUCCESS);
1354 buffer = srealloc(buffer, buflen+1);
1355 buffer[buflen] = '\0';
1358 nsessions = 1; /* "Default Settings" counts as one */
1360 if (strcmp(p, "Default Settings"))
1366 sessions = smalloc(nsessions * sizeof(char *));
1367 sessions[0] = "Default Settings";
1371 if (strcmp(p, "Default Settings"))
1382 int do_config (void) {
1386 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1387 get_sesslist(FALSE);
1392 int do_reconfig (HWND hwnd) {
1396 backup_cfg = cfg; /* structure copy */
1397 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1399 cfg = backup_cfg; /* structure copy */
1403 void do_defaults (char *session) {
1405 load_settings (session, TRUE);
1407 load_settings ("Default Settings", FALSE);
1410 void logevent (char *string) {
1411 if (nevents >= negsize) {
1413 events = srealloc (events, negsize * sizeof(*events));
1415 events[nevents] = smalloc(1+strlen(string));
1416 strcpy (events[nevents], string);
1419 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1423 void showeventlog (HWND hwnd) {
1425 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1427 ShowWindow (logbox, SW_SHOWNORMAL);
1431 void showabout (HWND hwnd) {
1433 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1435 ShowWindow (abtbox, SW_SHOWNORMAL);
1439 void verify_ssh_host_key(char *host, char *keystr) {
1440 char *otherstr, *mungedhost;
1444 len = 1 + strlen(keystr);
1447 * Now read a saved key in from the registry and see what it
1450 otherstr = malloc(len);
1451 mungedhost = malloc(3*strlen(host)+1);
1452 if (!otherstr || !mungedhost)
1453 fatalbox("Out of memory");
1455 mungestr(host, mungedhost);
1457 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1458 &rkey) != ERROR_SUCCESS) {
1459 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1460 "in the registry. There is thus no way to tell\n"
1461 "if the remote host is what you think it is.\n"
1462 "Connect anyway?", "PuTTY Problem",
1463 MB_ICONWARNING | MB_YESNO) == IDNO)
1466 DWORD readlen = len;
1470 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1471 &type, otherstr, &readlen);
1473 if (ret == ERROR_MORE_DATA ||
1474 (ret == ERROR_SUCCESS && type == REG_SZ &&
1475 strcmp(otherstr, keystr))) {
1476 if (MessageBox(NULL,
1477 "This host's host key is different from the\n"
1478 "one cached in the registry! Someone may be\n"
1479 "impersonating this host for malicious reasons;\n"
1480 "alternatively, the host key may have changed\n"
1481 "due to sloppy system administration.\n"
1482 "Replace key in registry and connect?",
1483 "PuTTY: Security Warning",
1484 MB_ICONWARNING | MB_YESNO) == IDNO)
1486 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1488 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1489 if (MessageBox(NULL,
1490 "This host's host key is not cached in the\n"
1491 "registry. Do you want to add it to the cache\n"
1492 "and carry on connecting?",
1494 MB_ICONWARNING | MB_YESNO) == IDNO)
1496 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,