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].name != 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.funky_type);
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, "BlinkCur", cfg.blink_cur);
166 wppi (sesskey, "Beep", cfg.beep);
167 wppi (sesskey, "ScrollbackLines", cfg.savelines);
168 wppi (sesskey, "DECOriginMode", cfg.dec_om);
169 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
170 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
171 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
172 wppi (sesskey, "TermWidth", cfg.width);
173 wppi (sesskey, "TermHeight", cfg.height);
174 wpps (sesskey, "Font", cfg.font);
175 wppi (sesskey, "FontIsBold", cfg.fontisbold);
176 wppi (sesskey, "FontCharSet", cfg.fontcharset);
177 wppi (sesskey, "FontHeight", cfg.fontheight);
178 wppi (sesskey, "FontVTMode", cfg.vtmode);
179 wppi (sesskey, "TryPalette", cfg.try_palette);
180 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
181 for (i=0; i<22; i++) {
182 char buf[20], buf2[30];
183 sprintf(buf, "Colour%d", i);
184 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
185 cfg.colours[i][1], cfg.colours[i][2]);
186 wpps (sesskey, buf, buf2);
188 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
189 for (i=0; i<256; i+=32) {
190 char buf[20], buf2[256];
192 sprintf(buf, "Wordness%d", i);
194 for (j=i; j<i+32; j++) {
195 sprintf(buf2+strlen(buf2), "%s%d",
196 (*buf2 ? "," : ""), cfg.wordness[j]);
198 wpps (sesskey, buf, buf2);
200 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
201 wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
202 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
203 wppi (sesskey, "ScrollBar", cfg.scrollbar);
204 wppi (sesskey, "ScrollOnKey", cfg.scroll_on_key);
205 wppi (sesskey, "LockSize", cfg.locksize);
206 wppi (sesskey, "BCE", cfg.bce);
207 wppi (sesskey, "BlinkText", cfg.blinktext);
209 RegCloseKey(sesskey);
212 static void del_session (char *section) {
216 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
219 p = malloc(3*strlen(section)+1);
220 mungestr(section, p);
221 RegDeleteKey(subkey1, p);
224 RegCloseKey(subkey1);
227 static void load_settings (char *section, int do_host) {
229 HKEY subkey1, sesskey;
233 p = malloc(3*strlen(section)+1);
234 mungestr(section, p);
236 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
239 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
242 RegCloseKey(subkey1);
247 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
248 gppi (sesskey, "PortNumber", default_port, &cfg.port);
250 gpps (sesskey, "Protocol", "default", prot, 10);
251 cfg.protocol = default_protocol;
252 for (i = 0; backends[i].name != NULL; i++)
253 if (!strcmp(prot, backends[i].name)) {
254 cfg.protocol = backends[i].protocol;
258 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
259 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
260 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
261 sizeof(cfg.termtype));
262 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
263 sizeof(cfg.termspeed));
265 char buf[2*sizeof(cfg.environmt)], *p, *q;
266 gpps (sesskey, "Environment", "", buf, sizeof(buf));
270 while (*p && *p != ',') {
283 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
284 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
287 gpps (sesskey, "Cipher", "3des", cipher, 10);
288 if (!strcmp(cipher, "blowfish"))
289 cfg.cipher = CIPHER_BLOWFISH;
290 else if (!strcmp(cipher, "des"))
291 cfg.cipher = CIPHER_DES;
293 cfg.cipher = CIPHER_3DES;
295 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
296 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
297 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
298 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
299 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
300 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
301 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
302 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
303 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
304 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
305 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
306 gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
307 gppi (sesskey, "Beep", 1, &cfg.beep);
308 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
309 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
310 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
311 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
312 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
313 gppi (sesskey, "TermWidth", 80, &cfg.width);
314 gppi (sesskey, "TermHeight", 24, &cfg.height);
315 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
316 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
317 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
318 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
319 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
320 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
321 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
322 for (i=0; i<22; i++) {
323 static char *defaults[] = {
324 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
325 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
326 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
327 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
328 "85,255,255", "187,187,187", "255,255,255"
330 char buf[20], buf2[30];
332 sprintf(buf, "Colour%d", i);
333 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
334 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
335 cfg.colours[i][0] = c0;
336 cfg.colours[i][1] = c1;
337 cfg.colours[i][2] = c2;
340 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
341 for (i=0; i<256; i+=32) {
342 static char *defaults[] = {
343 "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",
344 "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",
345 "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",
346 "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",
347 "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",
348 "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",
349 "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",
350 "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"
352 char buf[20], buf2[256], *p;
354 sprintf(buf, "Wordness%d", i);
355 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
357 for (j=i; j<i+32; j++) {
359 while (*p && *p != ',') p++;
360 if (*p == ',') *p++ = '\0';
361 cfg.wordness[j] = atoi(q);
364 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
365 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
366 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
367 gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
368 gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
369 gppi (sesskey, "LockSize", 0, &cfg.locksize);
370 gppi (sesskey, "BCE", 0, &cfg.bce);
371 gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
373 RegCloseKey(sesskey);
376 static void force_normal(HWND hwnd)
378 static int recurse = 0;
385 wp.length = sizeof(wp);
386 if (GetWindowPlacement(hwnd, &wp))
388 wp.showCmd = SW_SHOWNORMAL;
389 SetWindowPlacement(hwnd, &wp);
394 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
397 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
402 static int CALLBACK LogProc (HWND hwnd, UINT msg,
403 WPARAM wParam, LPARAM lParam) {
408 for (i=0; i<nevents; i++)
409 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
410 0, (LPARAM)events[i]);
412 /* case WM_CTLCOLORDLG: */
413 /* return (int) GetStockObject (LTGRAY_BRUSH); */
415 switch (LOWORD(wParam)) {
418 DestroyWindow (hwnd);
424 DestroyWindow (hwnd);
430 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
431 WPARAM wParam, LPARAM lParam) {
436 switch (LOWORD(wParam)) {
439 DestroyWindow (hwnd);
445 DestroyWindow (hwnd);
451 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
452 WPARAM wParam, LPARAM lParam) {
455 SetDlgItemText (hwnd, IDA_VERSION, ver);
457 /* case WM_CTLCOLORDLG: */
458 /* return (int) GetStockObject (LTGRAY_BRUSH); */
459 /* case WM_CTLCOLORSTATIC: */
460 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
461 /* return (int) GetStockObject (LTGRAY_BRUSH); */
463 switch (LOWORD(wParam)) {
466 DestroyWindow (hwnd);
469 EnableWindow(hwnd, 0);
470 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
472 EnableWindow(hwnd, 1);
478 DestroyWindow (hwnd);
484 static int GeneralPanelProc (HWND hwnd, UINT msg,
485 WPARAM wParam, LPARAM lParam) {
488 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
490 /* case WM_CTLCOLORDLG: */
491 /* return (int) GetStockObject (LTGRAY_BRUSH); */
492 /* case WM_CTLCOLORSTATIC: */
493 /* case WM_CTLCOLORBTN: */
494 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
495 /* return (int) GetStockObject (LTGRAY_BRUSH); */
497 DestroyWindow (hwnd);
503 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
504 WPARAM wParam, LPARAM lParam) {
509 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
510 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
511 for (i = 0; i < nsessions; i++)
512 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
513 0, (LPARAM) (sessions[i]));
514 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
515 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
516 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
517 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
518 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
522 * Button release should trigger WM_OK if there was a
523 * previous double click on the session list.
527 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
530 switch (LOWORD(wParam)) {
531 case IDC0_PROTTELNET:
534 if (HIWORD(wParam) == BN_CLICKED ||
535 HIWORD(wParam) == BN_DOUBLECLICKED) {
536 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
537 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
538 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
539 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
540 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
541 cfg.port = i ? 22 : 23;
542 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
547 if (HIWORD(wParam) == EN_CHANGE)
548 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
552 if (HIWORD(wParam) == EN_CHANGE)
553 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
556 if (HIWORD(wParam) == BN_CLICKED ||
557 HIWORD(wParam) == BN_DOUBLECLICKED)
558 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
561 if (HIWORD(wParam) == BN_CLICKED ||
562 HIWORD(wParam) == BN_DOUBLECLICKED)
563 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
566 if (HIWORD(wParam) == EN_CHANGE)
567 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
571 if (HIWORD(wParam) == BN_CLICKED ||
572 HIWORD(wParam) == BN_DOUBLECLICKED) {
577 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
579 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
585 strcpy (str, sessions[n]);
587 save_settings (str, !!strcmp(str, "Default Settings"));
588 get_sesslist (FALSE);
590 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
592 for (i = 0; i < nsessions; i++)
593 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
594 0, (LPARAM) (sessions[i]));
595 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
601 if (LOWORD(wParam) == IDC0_SESSLOAD &&
602 HIWORD(wParam) != BN_CLICKED &&
603 HIWORD(wParam) != BN_DOUBLECLICKED)
605 if (LOWORD(wParam) == IDC0_SESSLIST &&
606 HIWORD(wParam) != LBN_DBLCLK)
609 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
615 load_settings (sessions[n],
616 !!strcmp(sessions[n], "Default Settings"));
617 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
618 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
619 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
620 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
621 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
622 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
623 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
624 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
627 if (LOWORD(wParam) == IDC0_SESSLIST) {
629 * A double-click on a saved session should
630 * actually start the session, not just load it.
631 * Unless it's Default Settings or some other
632 * host-less set of saved settings.
641 if (HIWORD(wParam) == BN_CLICKED ||
642 HIWORD(wParam) == BN_DOUBLECLICKED) {
643 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
645 if (n == LB_ERR || n == 0) {
649 del_session(sessions[n]);
650 get_sesslist (FALSE);
652 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
654 for (i = 0; i < nsessions; i++)
655 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
656 0, (LPARAM) (sessions[i]));
657 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
662 return GeneralPanelProc (hwnd, msg, wParam, lParam);
665 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
666 WPARAM wParam, LPARAM lParam) {
669 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
670 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
671 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
672 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
673 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
675 (cfg.funky_type==2 ? IDC1_FUNCXTERM
678 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
679 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
680 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
681 cfg.nethack_keypad ? IDC1_KPNH :
682 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
683 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
684 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
685 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
686 CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
689 if (HIWORD(wParam) == BN_CLICKED ||
690 HIWORD(wParam) == BN_DOUBLECLICKED)
691 switch (LOWORD(wParam)) {
694 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
698 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
705 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
709 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
710 cfg.nethack_keypad = FALSE;
713 cfg.app_keypad = FALSE;
714 cfg.nethack_keypad = TRUE;
718 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
721 if (HIWORD(wParam) == BN_CLICKED ||
722 HIWORD(wParam) == BN_DOUBLECLICKED)
723 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
726 if (HIWORD(wParam) == BN_CLICKED ||
727 HIWORD(wParam) == BN_DOUBLECLICKED)
728 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
731 if (HIWORD(wParam) == BN_CLICKED ||
732 HIWORD(wParam) == BN_DOUBLECLICKED)
733 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
736 if (HIWORD(wParam) == BN_CLICKED ||
737 HIWORD(wParam) == BN_DOUBLECLICKED)
738 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
742 return GeneralPanelProc (hwnd, msg, wParam, lParam);
745 static void fmtfont (char *buf) {
746 sprintf (buf, "Font: %s, ", cfg.font);
748 strcat(buf, "bold, ");
749 if (cfg.fontheight == 0)
750 strcat (buf, "default height");
752 sprintf (buf+strlen(buf), "%d-%s",
753 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
754 (cfg.fontheight < 0 ? "pixel" : "point"));
757 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
758 WPARAM wParam, LPARAM lParam) {
761 char fontstatic[256];
765 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
766 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
767 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
768 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
769 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
770 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
771 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
772 fmtfont (fontstatic);
773 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
774 CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
775 CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
776 CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
777 CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
778 CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
779 CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
782 switch (LOWORD(wParam)) {
784 if (HIWORD(wParam) == BN_CLICKED ||
785 HIWORD(wParam) == BN_DOUBLECLICKED)
786 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
789 if (HIWORD(wParam) == BN_CLICKED ||
790 HIWORD(wParam) == BN_DOUBLECLICKED)
791 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
794 if (HIWORD(wParam) == BN_CLICKED ||
795 HIWORD(wParam) == BN_DOUBLECLICKED)
796 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
799 if (HIWORD(wParam) == BN_CLICKED ||
800 HIWORD(wParam) == BN_DOUBLECLICKED)
801 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
804 if (HIWORD(wParam) == EN_CHANGE)
805 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
808 if (HIWORD(wParam) == EN_CHANGE)
809 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
812 if (HIWORD(wParam) == EN_CHANGE)
813 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
815 case IDC2_CHOOSEFONT:
816 lf.lfHeight = cfg.fontheight;
817 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
818 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
819 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
820 lf.lfCharSet = cfg.fontcharset;
821 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
822 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
823 lf.lfQuality = DEFAULT_QUALITY;
824 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
825 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
826 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
828 cf.lStructSize = sizeof(cf);
831 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
832 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
834 if (ChooseFont (&cf)) {
835 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
836 cfg.font[sizeof(cfg.font)-1] = '\0';
837 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
838 cfg.fontcharset = lf.lfCharSet;
839 cfg.fontheight = lf.lfHeight;
840 fmtfont (fontstatic);
841 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
845 if (HIWORD(wParam) == BN_CLICKED ||
846 HIWORD(wParam) == BN_DOUBLECLICKED)
847 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
850 if (HIWORD(wParam) == BN_CLICKED ||
851 HIWORD(wParam) == BN_DOUBLECLICKED)
852 cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
855 if (HIWORD(wParam) == BN_CLICKED ||
856 HIWORD(wParam) == BN_DOUBLECLICKED)
857 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
860 if (HIWORD(wParam) == BN_CLICKED ||
861 HIWORD(wParam) == BN_DOUBLECLICKED)
862 cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
865 if (HIWORD(wParam) == BN_CLICKED ||
866 HIWORD(wParam) == BN_DOUBLECLICKED)
867 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
870 if (HIWORD(wParam) == BN_CLICKED ||
871 HIWORD(wParam) == BN_DOUBLECLICKED)
872 cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
877 return GeneralPanelProc (hwnd, msg, wParam, lParam);
880 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
881 WPARAM wParam, LPARAM lParam) {
886 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
887 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
888 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
890 char *p = cfg.environmt;
892 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
897 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
898 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
901 switch (LOWORD(wParam)) {
903 if (HIWORD(wParam) == EN_CHANGE)
904 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
905 sizeof(cfg.termtype)-1);
908 if (HIWORD(wParam) == EN_CHANGE)
909 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
910 sizeof(cfg.termspeed)-1);
913 if (HIWORD(wParam) == EN_CHANGE)
914 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
915 sizeof(cfg.username)-1);
919 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
922 if (HIWORD(wParam) == BN_CLICKED ||
923 HIWORD(wParam) == BN_DOUBLECLICKED) {
924 char str[sizeof(cfg.environmt)];
926 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
931 p = str + strlen(str);
933 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
943 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
945 p[strlen(str)+1] = '\0';
946 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
948 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
949 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
951 MessageBox(hwnd, "Environment too big", "PuTTY Error",
952 MB_OK | MB_ICONERROR);
957 if (HIWORD(wParam) != BN_CLICKED &&
958 HIWORD(wParam) != BN_DOUBLECLICKED)
960 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
966 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
993 return GeneralPanelProc (hwnd, msg, wParam, lParam);
996 static int CALLBACK SshProc (HWND hwnd, UINT msg,
997 WPARAM wParam, LPARAM lParam) {
1000 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
1001 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
1002 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
1003 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
1004 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
1005 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
1008 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
1011 switch (LOWORD(wParam)) {
1013 if (HIWORD(wParam) == EN_CHANGE)
1014 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1015 sizeof(cfg.termtype)-1);
1018 if (HIWORD(wParam) == EN_CHANGE)
1019 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1020 sizeof(cfg.username)-1);
1023 if (HIWORD(wParam) == BN_CLICKED ||
1024 HIWORD(wParam) == BN_DOUBLECLICKED)
1025 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1027 case IDC3_CIPHER3DES:
1028 case IDC3_CIPHERBLOWF:
1029 case IDC3_CIPHERDES:
1030 if (HIWORD(wParam) == BN_CLICKED ||
1031 HIWORD(wParam) == BN_DOUBLECLICKED) {
1032 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1033 cfg.cipher = CIPHER_3DES;
1034 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1035 cfg.cipher = CIPHER_BLOWFISH;
1036 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1037 cfg.cipher = CIPHER_DES;
1041 if (HIWORD(wParam) == BN_CLICKED ||
1042 HIWORD(wParam) == BN_DOUBLECLICKED)
1043 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1048 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1051 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1052 WPARAM wParam, LPARAM lParam) {
1057 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1058 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1060 static int tabs[4] = {25, 61, 96, 128};
1061 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1064 for (i=0; i<256; i++) {
1066 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1067 (i>=0x21 && i != 0x7F) ? i : ' ',
1069 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1074 switch (LOWORD(wParam)) {
1075 case IDC4_MBWINDOWS:
1077 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1083 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1088 for (i=0; i<256; i++)
1089 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1092 cfg.wordness[i] = n;
1093 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1094 LB_DELETESTRING, i, 0);
1095 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1096 (i>=0x21 && i != 0x7F) ? i : ' ',
1098 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1108 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1111 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1112 WPARAM wParam, LPARAM lParam) {
1113 static const char *const colours[] = {
1114 "Default Foreground", "Default Bold Foreground",
1115 "Default Background", "Default Bold Background",
1116 "Cursor Text", "Cursor Colour",
1117 "ANSI Black", "ANSI Black Bold",
1118 "ANSI Red", "ANSI Red Bold",
1119 "ANSI Green", "ANSI Green Bold",
1120 "ANSI Yellow", "ANSI Yellow Bold",
1121 "ANSI Blue", "ANSI Blue Bold",
1122 "ANSI Magenta", "ANSI Magenta Bold",
1123 "ANSI Cyan", "ANSI Cyan Bold",
1124 "ANSI White", "ANSI White Bold"
1126 static const int permanent[] = {
1127 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1128 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1129 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1133 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1134 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1137 for (i=0; i<22; i++)
1138 if (cfg.bold_colour || permanent[i])
1139 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1140 (LPARAM) colours[i]);
1142 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1143 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1144 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1145 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1148 switch (LOWORD(wParam)) {
1149 case IDC5_BOLDCOLOUR:
1150 if (HIWORD(wParam) == BN_CLICKED ||
1151 HIWORD(wParam) == BN_DOUBLECLICKED) {
1153 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1154 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1155 if (cfg.bold_colour && n!=22) {
1156 for (i=0; i<22; i++)
1158 SendDlgItemMessage (hwnd, IDC5_LIST,
1160 (LPARAM) colours[i]);
1161 } else if (!cfg.bold_colour && n!=12) {
1164 SendDlgItemMessage (hwnd, IDC5_LIST,
1165 LB_DELETESTRING, i, 0);
1170 if (HIWORD(wParam) == BN_CLICKED ||
1171 HIWORD(wParam) == BN_DOUBLECLICKED)
1172 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1175 if (HIWORD(wParam) == LBN_DBLCLK ||
1176 HIWORD(wParam) == LBN_SELCHANGE) {
1177 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1179 if (!cfg.bold_colour)
1180 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1181 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1182 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1183 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1187 if (HIWORD(wParam) == BN_CLICKED ||
1188 HIWORD(wParam) == BN_DOUBLECLICKED) {
1189 static CHOOSECOLOR cc;
1190 static DWORD custom[16] = {0}; /* zero initialisers */
1191 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1193 if (!cfg.bold_colour)
1194 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1195 cc.lStructSize = sizeof(cc);
1196 cc.hwndOwner = hwnd;
1197 cc.hInstance = (HWND)hinst;
1198 cc.lpCustColors = custom;
1199 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1201 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1202 if (ChooseColor(&cc)) {
1204 (unsigned char) (cc.rgbResult & 0xFF);
1206 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1208 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1209 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1211 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1213 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1221 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1224 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1225 WPARAM wParam, LPARAM lParam) {
1228 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1229 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1230 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1232 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1233 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1234 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1235 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1236 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1239 switch (LOWORD(wParam)) {
1241 case IDC6_KOI8WIN1251:
1242 case IDC6_88592WIN1250:
1243 cfg.xlat_enablekoiwin =
1244 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1245 cfg.xlat_88592w1250 =
1246 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1248 case IDC6_CAPSLOCKCYR:
1249 if (HIWORD(wParam) == BN_CLICKED ||
1250 HIWORD(wParam) == BN_DOUBLECLICKED) {
1251 cfg.xlat_capslockcyr =
1252 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1255 case IDC2_VTXWINDOWS:
1256 case IDC2_VTOEMANSI:
1257 case IDC2_VTOEMONLY:
1258 case IDC2_VTPOORMAN:
1260 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1261 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1262 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1267 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1270 static DLGPROC panelproc[NPANELS] = {
1271 ConnectionProc, KeyboardProc, TerminalProc,
1272 TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1274 static char *panelids[NPANELS] = {
1275 MAKEINTRESOURCE(IDD_PANEL0),
1276 MAKEINTRESOURCE(IDD_PANEL1),
1277 MAKEINTRESOURCE(IDD_PANEL2),
1278 MAKEINTRESOURCE(IDD_PANEL3),
1279 MAKEINTRESOURCE(IDD_PANEL35),
1280 MAKEINTRESOURCE(IDD_PANEL4),
1281 MAKEINTRESOURCE(IDD_PANEL5),
1282 MAKEINTRESOURCE(IDD_PANEL6)
1285 static char *names[NPANELS] = {
1286 "Connection", "Keyboard", "Terminal", "Telnet",
1287 "SSH", "Selection", "Colours", "Translation"
1290 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1291 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1293 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1294 WPARAM wParam, LPARAM lParam,
1295 int npanels, int *panelnums, HWND *page) {
1300 { /* centre the window */
1303 hw = GetDesktopWindow();
1304 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1305 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1306 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1307 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1310 { /* initialise the tab control */
1314 hw = GetDlgItem (hwnd, IDC_TAB);
1315 for (i=0; i<npanels; i++) {
1316 tab.mask = TCIF_TEXT;
1317 tab.pszText = names[panelnums[i]];
1318 TabCtrl_InsertItem (hw, i, &tab);
1320 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1321 hwnd, panelproc[panelnums[0]]);*/
1322 *page = CreateDialog (hinst, panelids[panelnums[0]],
1323 hwnd, panelproc[panelnums[0]]);
1324 SetWindowLong (*page, GWL_EXSTYLE,
1325 GetWindowLong (*page, GWL_EXSTYLE) |
1326 WS_EX_CONTROLPARENT);
1331 if (LOWORD(wParam) == IDC_TAB &&
1332 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1333 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1335 DestroyWindow (*page);
1336 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1337 hwnd, panelproc[panelnums[i]]);*/
1338 *page = CreateDialog (hinst, panelids[panelnums[i]],
1339 hwnd, panelproc[panelnums[i]]);
1340 SetWindowLong (*page, GWL_EXSTYLE,
1341 GetWindowLong (*page, GWL_EXSTYLE) |
1342 WS_EX_CONTROLPARENT);
1343 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1347 /* case WM_CTLCOLORDLG: */
1348 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1350 switch (LOWORD(wParam)) {
1353 EndDialog (hwnd, 1);
1358 EndDialog (hwnd, 0);
1363 EndDialog (hwnd, 0);
1366 /* Grrr Explorer will maximize Dialogs! */
1368 if (wParam == SIZE_MAXIMIZED)
1375 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1376 WPARAM wParam, LPARAM lParam) {
1381 static HWND page = NULL;
1383 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1386 * If the Connection panel is active and the Session List
1387 * box is selected, we treat a press of Open to have an
1388 * implicit press of Load preceding it.
1390 hw = GetDlgItem (hwnd, IDC_TAB);
1391 i = TabCtrl_GetCurSel(hw);
1392 if (panelproc[mainp[i]] == ConnectionProc &&
1393 page && implicit_load_ok) {
1394 SendMessage (page, WM_COMMAND,
1395 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1399 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1400 EnableWindow(hwnd, 0);
1401 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1402 GetParent(hwnd), AboutProc);
1403 EnableWindow(hwnd, 1);
1405 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1406 MAIN_NPANELS, mainp, &page);
1409 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1410 WPARAM wParam, LPARAM lParam) {
1412 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1413 RECONF_NPANELS, reconfp, &page);
1416 void get_sesslist(int allocate) {
1417 static char *buffer;
1418 int buflen, bufsize, i, ret;
1419 char otherbuf[2048];
1424 if (RegCreateKey(HKEY_CURRENT_USER,
1425 puttystr, &subkey1) != ERROR_SUCCESS)
1428 buflen = bufsize = 0;
1432 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1433 if (ret == ERROR_SUCCESS) {
1434 bufsize = buflen + 2048;
1435 buffer = srealloc(buffer, bufsize);
1436 unmungestr(otherbuf, buffer+buflen);
1437 buflen += strlen(buffer+buflen)+1;
1439 } while (ret == ERROR_SUCCESS);
1440 buffer = srealloc(buffer, buflen+1);
1441 buffer[buflen] = '\0';
1444 nsessions = 1; /* "Default Settings" counts as one */
1446 if (strcmp(p, "Default Settings"))
1452 sessions = smalloc(nsessions * sizeof(char *));
1453 sessions[0] = "Default Settings";
1457 if (strcmp(p, "Default Settings"))
1468 int do_config (void) {
1472 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1473 get_sesslist(FALSE);
1478 int do_reconfig (HWND hwnd) {
1482 backup_cfg = cfg; /* structure copy */
1483 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1485 cfg = backup_cfg; /* structure copy */
1492 void do_defaults (char *session) {
1494 load_settings (session, TRUE);
1496 load_settings ("Default Settings", FALSE);
1499 void logevent (char *string) {
1500 if (nevents >= negsize) {
1502 events = srealloc (events, negsize * sizeof(*events));
1504 events[nevents] = smalloc(1+strlen(string));
1505 strcpy (events[nevents], string);
1508 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1512 void showeventlog (HWND hwnd) {
1514 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1516 ShowWindow (logbox, SW_SHOWNORMAL);
1520 void showabout (HWND hwnd) {
1522 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1524 ShowWindow (abtbox, SW_SHOWNORMAL);
1528 void verify_ssh_host_key(char *host, char *keystr) {
1529 char *otherstr, *mungedhost;
1533 len = 1 + strlen(keystr);
1536 * Now read a saved key in from the registry and see what it
1539 otherstr = smalloc(len);
1540 mungedhost = smalloc(3*strlen(host)+1);
1541 if (!otherstr || !mungedhost)
1542 fatalbox("Out of memory");
1544 mungestr(host, mungedhost);
1546 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1547 &rkey) != ERROR_SUCCESS) {
1548 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1549 "in the registry. There is thus no way to tell\n"
1550 "if the remote host is what you think it is.\n"
1551 "Connect anyway?", "PuTTY Problem",
1552 MB_ICONWARNING | MB_YESNO) == IDNO)
1555 DWORD readlen = len;
1559 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1560 &type, otherstr, &readlen);
1562 if (ret == ERROR_MORE_DATA ||
1563 (ret == ERROR_SUCCESS && type == REG_SZ &&
1564 strcmp(otherstr, keystr))) {
1565 if (MessageBox(NULL,
1566 "This host's host key is different from the\n"
1567 "one cached in the registry! Someone may be\n"
1568 "impersonating this host for malicious reasons;\n"
1569 "alternatively, the host key may have changed\n"
1570 "due to sloppy system administration.\n"
1571 "Replace key in registry and connect?",
1572 "PuTTY: Security Warning",
1573 MB_ICONWARNING | MB_YESNO) == IDNO)
1575 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1577 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1578 if (MessageBox(NULL,
1579 "This host's host key is not cached in the\n"
1580 "registry. Do you want to add it to the cache\n"
1581 "and carry on connecting?",
1583 MB_ICONWARNING | MB_YESNO) == IDNO)
1585 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,