19 #define MAIN_NPANELS 8
20 #define RECONF_NPANELS 5
22 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
24 static char **events = NULL;
25 static int nevents = 0, negsize = 0;
27 static HWND logbox = NULL, abtbox = NULL;
29 static char hex[16] = "0123456789ABCDEF";
31 static void mungestr(char *in, char *out) {
35 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
36 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
38 *out++ = hex[((unsigned char)*in) >> 4];
39 *out++ = hex[((unsigned char)*in) & 15];
49 static void unmungestr(char *in, char *out) {
51 if (*in == '%' && in[1] && in[2]) {
54 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
55 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
66 static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
67 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
70 static void wppi(HKEY key, LPCTSTR name, int value) {
71 RegSetValueEx(key, name, 0, REG_DWORD,
72 (CONST BYTE *)&value, sizeof(value));
75 static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
76 LPTSTR val, int len) {
81 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
83 strncpy(val, def, len);
88 static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
89 DWORD type, val, size;
93 RegQueryValueEx(key, name, 0, &type,
94 (BYTE *)&val, &size) != ERROR_SUCCESS ||
95 size != sizeof(val) || type != REG_DWORD)
101 static HINSTANCE hinst;
103 static int readytogo;
105 static void save_settings (char *section, int do_host) {
107 HKEY subkey1, sesskey;
110 p = malloc(3*strlen(section)+1);
111 mungestr(section, p);
113 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
114 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
119 RegCloseKey(subkey1);
121 wppi (sesskey, "Present", 1);
123 wpps (sesskey, "HostName", cfg.host);
124 wppi (sesskey, "PortNumber", cfg.port);
126 for (i = 0; backends[i].name != NULL; i++)
127 if (backends[i].protocol == cfg.protocol) {
128 p = backends[i].name;
131 wpps (sesskey, "Protocol", p);
133 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
134 wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
135 wpps (sesskey, "TerminalType", cfg.termtype);
136 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
138 char buf[2*sizeof(cfg.environmt)], *p, *q;
144 if (c == '=' || c == ',' || c == '\\')
154 wpps (sesskey, "Environment", buf);
156 wpps (sesskey, "UserName", cfg.username);
157 wppi (sesskey, "NoPTY", cfg.nopty);
158 wppi (sesskey, "AgentFwd", cfg.agentfwd);
159 wpps (sesskey, "RemoteCmd", cfg.remote_cmd);
160 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
161 cfg.cipher == CIPHER_DES ? "des" : "3des");
162 wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
163 wppi (sesskey, "SshProt", cfg.sshprot);
164 wpps (sesskey, "PublicKeyFile", cfg.keyfile);
165 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
166 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
167 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
168 wppi (sesskey, "LinuxFunctionKeys", cfg.funky_type);
169 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
170 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
171 wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
172 wppi (sesskey, "AltF4", cfg.alt_f4);
173 wppi (sesskey, "AltSpace", cfg.alt_space);
174 wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
175 wppi (sesskey, "BlinkCur", cfg.blink_cur);
176 wppi (sesskey, "Beep", cfg.beep);
177 wppi (sesskey, "ScrollbackLines", cfg.savelines);
178 wppi (sesskey, "DECOriginMode", cfg.dec_om);
179 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
180 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
181 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
182 wppi (sesskey, "TermWidth", cfg.width);
183 wppi (sesskey, "TermHeight", cfg.height);
184 wpps (sesskey, "Font", cfg.font);
185 wppi (sesskey, "FontIsBold", cfg.fontisbold);
186 wppi (sesskey, "FontCharSet", cfg.fontcharset);
187 wppi (sesskey, "FontHeight", cfg.fontheight);
188 wppi (sesskey, "FontVTMode", cfg.vtmode);
189 wppi (sesskey, "TryPalette", cfg.try_palette);
190 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
191 for (i=0; i<22; i++) {
192 char buf[20], buf2[30];
193 sprintf(buf, "Colour%d", i);
194 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
195 cfg.colours[i][1], cfg.colours[i][2]);
196 wpps (sesskey, buf, buf2);
198 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
199 for (i=0; i<256; i+=32) {
200 char buf[20], buf2[256];
202 sprintf(buf, "Wordness%d", i);
204 for (j=i; j<i+32; j++) {
205 sprintf(buf2+strlen(buf2), "%s%d",
206 (*buf2 ? "," : ""), cfg.wordness[j]);
208 wpps (sesskey, buf, buf2);
210 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
211 wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
212 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
213 wppi (sesskey, "ScrollBar", cfg.scrollbar);
214 wppi (sesskey, "ScrollOnKey", cfg.scroll_on_key);
215 wppi (sesskey, "LockSize", cfg.locksize);
216 wppi (sesskey, "BCE", cfg.bce);
217 wppi (sesskey, "BlinkText", cfg.blinktext);
219 RegCloseKey(sesskey);
222 static void del_session (char *section) {
226 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
229 p = malloc(3*strlen(section)+1);
230 mungestr(section, p);
231 RegDeleteKey(subkey1, p);
234 RegCloseKey(subkey1);
237 static void load_settings (char *section, int do_host) {
239 HKEY subkey1, sesskey;
243 p = malloc(3*strlen(section)+1);
244 mungestr(section, p);
246 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
249 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
252 RegCloseKey(subkey1);
257 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
258 gppi (sesskey, "PortNumber", default_port, &cfg.port);
260 gpps (sesskey, "Protocol", "default", prot, 10);
261 cfg.protocol = default_protocol;
262 for (i = 0; backends[i].name != NULL; i++)
263 if (!strcmp(prot, backends[i].name)) {
264 cfg.protocol = backends[i].protocol;
268 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
269 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
270 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
271 sizeof(cfg.termtype));
272 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
273 sizeof(cfg.termspeed));
275 char buf[2*sizeof(cfg.environmt)], *p, *q;
276 gpps (sesskey, "Environment", "", buf, sizeof(buf));
280 while (*p && *p != ',') {
293 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
294 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
295 gppi (sesskey, "AgentFwd", 0, &cfg.agentfwd);
296 gpps (sesskey, "RemoteCmd", "", cfg.remote_cmd, sizeof(cfg.remote_cmd));
299 gpps (sesskey, "Cipher", "3des", cipher, 10);
300 if (!strcmp(cipher, "blowfish"))
301 cfg.cipher = CIPHER_BLOWFISH;
302 else if (!strcmp(cipher, "des"))
303 cfg.cipher = CIPHER_DES;
305 cfg.cipher = CIPHER_3DES;
307 gppi (sesskey, "SshProt", 1, &cfg.sshprot);
308 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
309 gpps (sesskey, "PublicKeyFile", "", cfg.keyfile, sizeof(cfg.keyfile));
310 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
311 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
312 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
313 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
314 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
315 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
316 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
317 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
318 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
319 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
320 gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
321 gppi (sesskey, "Beep", 1, &cfg.beep);
322 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
323 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
324 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
325 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
326 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
327 gppi (sesskey, "TermWidth", 80, &cfg.width);
328 gppi (sesskey, "TermHeight", 24, &cfg.height);
329 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
330 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
331 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
332 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
333 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
334 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
335 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
336 for (i=0; i<22; i++) {
337 static char *defaults[] = {
338 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
339 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
340 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
341 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
342 "85,255,255", "187,187,187", "255,255,255"
344 char buf[20], buf2[30];
346 sprintf(buf, "Colour%d", i);
347 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
348 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
349 cfg.colours[i][0] = c0;
350 cfg.colours[i][1] = c1;
351 cfg.colours[i][2] = c2;
354 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
355 for (i=0; i<256; i+=32) {
356 static char *defaults[] = {
357 "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",
358 "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",
359 "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",
360 "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",
361 "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",
362 "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",
363 "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",
364 "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"
366 char buf[20], buf2[256], *p;
368 sprintf(buf, "Wordness%d", i);
369 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
371 for (j=i; j<i+32; j++) {
373 while (*p && *p != ',') p++;
374 if (*p == ',') *p++ = '\0';
375 cfg.wordness[j] = atoi(q);
378 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
379 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
380 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
381 gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
382 gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
383 gppi (sesskey, "LockSize", 0, &cfg.locksize);
384 gppi (sesskey, "BCE", 0, &cfg.bce);
385 gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
387 RegCloseKey(sesskey);
390 static void force_normal(HWND hwnd)
392 static int recurse = 0;
399 wp.length = sizeof(wp);
400 if (GetWindowPlacement(hwnd, &wp))
402 wp.showCmd = SW_SHOWNORMAL;
403 SetWindowPlacement(hwnd, &wp);
408 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
411 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
416 static int CALLBACK LogProc (HWND hwnd, UINT msg,
417 WPARAM wParam, LPARAM lParam) {
422 for (i=0; i<nevents; i++)
423 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
424 0, (LPARAM)events[i]);
426 /* case WM_CTLCOLORDLG: */
427 /* return (int) GetStockObject (LTGRAY_BRUSH); */
429 switch (LOWORD(wParam)) {
432 DestroyWindow (hwnd);
435 if (HIWORD(wParam) == BN_CLICKED ||
436 HIWORD(wParam) == BN_DOUBLECLICKED) {
439 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
440 LB_GETSELCOUNT, 0, 0);
441 selitems = malloc(selcount * sizeof(int));
443 int count = SendDlgItemMessage(hwnd, IDN_LIST,
445 selcount, (LPARAM)selitems);
449 static unsigned char sel_nl[] = SEL_NL;
452 for (i = 0; i < count; i++)
453 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
455 clipdata = malloc(size);
458 for (i = 0; i < count; i++) {
459 char *q = events[selitems[i]];
460 int qlen = strlen(q);
463 memcpy(p, sel_nl, sizeof(sel_nl));
466 write_clip(clipdata, size);
478 DestroyWindow (hwnd);
484 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
485 WPARAM wParam, LPARAM lParam) {
490 switch (LOWORD(wParam)) {
493 DestroyWindow (hwnd);
499 DestroyWindow (hwnd);
505 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
506 WPARAM wParam, LPARAM lParam) {
509 SetDlgItemText (hwnd, IDA_VERSION, ver);
511 /* case WM_CTLCOLORDLG: */
512 /* return (int) GetStockObject (LTGRAY_BRUSH); */
513 /* case WM_CTLCOLORSTATIC: */
514 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
515 /* return (int) GetStockObject (LTGRAY_BRUSH); */
517 switch (LOWORD(wParam)) {
520 DestroyWindow (hwnd);
523 EnableWindow(hwnd, 0);
524 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
526 EnableWindow(hwnd, 1);
527 SetActiveWindow(hwnd);
533 DestroyWindow (hwnd);
539 static int GeneralPanelProc (HWND hwnd, UINT msg,
540 WPARAM wParam, LPARAM lParam) {
543 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
545 /* case WM_CTLCOLORDLG: */
546 /* return (int) GetStockObject (LTGRAY_BRUSH); */
547 /* case WM_CTLCOLORSTATIC: */
548 /* case WM_CTLCOLORBTN: */
549 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
550 /* return (int) GetStockObject (LTGRAY_BRUSH); */
552 DestroyWindow (hwnd);
558 static char savedsession[2048];
560 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
561 WPARAM wParam, LPARAM lParam) {
566 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
567 SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
568 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
569 for (i = 0; i < nsessions; i++)
570 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
571 0, (LPARAM) (sessions[i]));
572 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
573 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
574 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
575 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
576 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
580 * Button release should trigger WM_OK if there was a
581 * previous double click on the session list.
585 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
588 switch (LOWORD(wParam)) {
589 case IDC0_PROTTELNET:
592 if (HIWORD(wParam) == BN_CLICKED ||
593 HIWORD(wParam) == BN_DOUBLECLICKED) {
594 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
595 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
596 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
597 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
598 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
599 cfg.port = i ? 22 : 23;
600 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
605 if (HIWORD(wParam) == EN_CHANGE)
606 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
610 if (HIWORD(wParam) == EN_CHANGE)
611 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
614 if (HIWORD(wParam) == BN_CLICKED ||
615 HIWORD(wParam) == BN_DOUBLECLICKED)
616 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
619 if (HIWORD(wParam) == BN_CLICKED ||
620 HIWORD(wParam) == BN_DOUBLECLICKED)
621 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
624 if (HIWORD(wParam) == EN_CHANGE) {
625 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
627 GetDlgItemText (hwnd, IDC0_SESSEDIT,
628 savedsession, sizeof(savedsession)-1);
629 savedsession[sizeof(savedsession)-1] = '\0';
633 if (HIWORD(wParam) == BN_CLICKED ||
634 HIWORD(wParam) == BN_DOUBLECLICKED) {
639 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
641 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
647 strcpy (str, sessions[n]);
649 save_settings (str, !!strcmp(str, "Default Settings"));
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,
663 if (LOWORD(wParam) == IDC0_SESSLOAD &&
664 HIWORD(wParam) != BN_CLICKED &&
665 HIWORD(wParam) != BN_DOUBLECLICKED)
667 if (LOWORD(wParam) == IDC0_SESSLIST &&
668 HIWORD(wParam) != LBN_DBLCLK)
671 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
677 load_settings (sessions[n],
678 !!strcmp(sessions[n], "Default Settings"));
679 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
680 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
681 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
682 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
683 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
684 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
685 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
686 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
689 if (LOWORD(wParam) == IDC0_SESSLIST) {
691 * A double-click on a saved session should
692 * actually start the session, not just load it.
693 * Unless it's Default Settings or some other
694 * host-less set of saved settings.
703 if (HIWORD(wParam) == BN_CLICKED ||
704 HIWORD(wParam) == BN_DOUBLECLICKED) {
705 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
707 if (n == LB_ERR || n == 0) {
711 del_session(sessions[n]);
712 get_sesslist (FALSE);
714 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
716 for (i = 0; i < nsessions; i++)
717 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
718 0, (LPARAM) (sessions[i]));
719 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
724 return GeneralPanelProc (hwnd, msg, wParam, lParam);
727 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
728 WPARAM wParam, LPARAM lParam) {
731 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
732 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
733 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
734 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
735 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
737 (cfg.funky_type==2 ? IDC1_FUNCXTERM
740 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
741 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
742 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
743 cfg.nethack_keypad ? IDC1_KPNH :
744 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
745 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
746 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
747 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
748 CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
751 if (HIWORD(wParam) == BN_CLICKED ||
752 HIWORD(wParam) == BN_DOUBLECLICKED)
753 switch (LOWORD(wParam)) {
756 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
760 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
767 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
771 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
772 cfg.nethack_keypad = FALSE;
775 cfg.app_keypad = FALSE;
776 cfg.nethack_keypad = TRUE;
780 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
783 if (HIWORD(wParam) == BN_CLICKED ||
784 HIWORD(wParam) == BN_DOUBLECLICKED)
785 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
788 if (HIWORD(wParam) == BN_CLICKED ||
789 HIWORD(wParam) == BN_DOUBLECLICKED)
790 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
793 if (HIWORD(wParam) == BN_CLICKED ||
794 HIWORD(wParam) == BN_DOUBLECLICKED)
795 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
798 if (HIWORD(wParam) == BN_CLICKED ||
799 HIWORD(wParam) == BN_DOUBLECLICKED)
800 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
804 return GeneralPanelProc (hwnd, msg, wParam, lParam);
807 static void fmtfont (char *buf) {
808 sprintf (buf, "Font: %s, ", cfg.font);
810 strcat(buf, "bold, ");
811 if (cfg.fontheight == 0)
812 strcat (buf, "default height");
814 sprintf (buf+strlen(buf), "%d-%s",
815 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
816 (cfg.fontheight < 0 ? "pixel" : "point"));
819 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
820 WPARAM wParam, LPARAM lParam) {
823 char fontstatic[256];
827 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
828 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
829 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
830 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
831 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
832 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
833 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
834 fmtfont (fontstatic);
835 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
836 CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
837 CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
838 CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
839 CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
840 CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
841 CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
844 switch (LOWORD(wParam)) {
846 if (HIWORD(wParam) == BN_CLICKED ||
847 HIWORD(wParam) == BN_DOUBLECLICKED)
848 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
851 if (HIWORD(wParam) == BN_CLICKED ||
852 HIWORD(wParam) == BN_DOUBLECLICKED)
853 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
856 if (HIWORD(wParam) == BN_CLICKED ||
857 HIWORD(wParam) == BN_DOUBLECLICKED)
858 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
861 if (HIWORD(wParam) == BN_CLICKED ||
862 HIWORD(wParam) == BN_DOUBLECLICKED)
863 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
866 if (HIWORD(wParam) == EN_CHANGE)
867 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
870 if (HIWORD(wParam) == EN_CHANGE)
871 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
874 if (HIWORD(wParam) == EN_CHANGE)
875 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
877 case IDC2_CHOOSEFONT:
878 lf.lfHeight = cfg.fontheight;
879 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
880 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
881 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
882 lf.lfCharSet = cfg.fontcharset;
883 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
884 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
885 lf.lfQuality = DEFAULT_QUALITY;
886 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
887 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
888 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
890 cf.lStructSize = sizeof(cf);
893 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
894 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
896 if (ChooseFont (&cf)) {
897 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
898 cfg.font[sizeof(cfg.font)-1] = '\0';
899 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
900 cfg.fontcharset = lf.lfCharSet;
901 cfg.fontheight = lf.lfHeight;
902 fmtfont (fontstatic);
903 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
907 if (HIWORD(wParam) == BN_CLICKED ||
908 HIWORD(wParam) == BN_DOUBLECLICKED)
909 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
912 if (HIWORD(wParam) == BN_CLICKED ||
913 HIWORD(wParam) == BN_DOUBLECLICKED)
914 cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
917 if (HIWORD(wParam) == BN_CLICKED ||
918 HIWORD(wParam) == BN_DOUBLECLICKED)
919 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
922 if (HIWORD(wParam) == BN_CLICKED ||
923 HIWORD(wParam) == BN_DOUBLECLICKED)
924 cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
927 if (HIWORD(wParam) == BN_CLICKED ||
928 HIWORD(wParam) == BN_DOUBLECLICKED)
929 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
932 if (HIWORD(wParam) == BN_CLICKED ||
933 HIWORD(wParam) == BN_DOUBLECLICKED)
934 cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
939 return GeneralPanelProc (hwnd, msg, wParam, lParam);
942 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
943 WPARAM wParam, LPARAM lParam) {
948 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
949 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
950 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
952 char *p = cfg.environmt;
954 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
959 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
960 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
963 switch (LOWORD(wParam)) {
965 if (HIWORD(wParam) == EN_CHANGE)
966 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
967 sizeof(cfg.termtype)-1);
970 if (HIWORD(wParam) == EN_CHANGE)
971 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
972 sizeof(cfg.termspeed)-1);
975 if (HIWORD(wParam) == EN_CHANGE)
976 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
977 sizeof(cfg.username)-1);
981 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
984 if (HIWORD(wParam) == BN_CLICKED ||
985 HIWORD(wParam) == BN_DOUBLECLICKED) {
986 char str[sizeof(cfg.environmt)];
988 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
993 p = str + strlen(str);
995 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
1005 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1007 p[strlen(str)+1] = '\0';
1008 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
1010 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
1011 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
1013 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1014 MB_OK | MB_ICONERROR);
1018 case IDC3_ENVREMOVE:
1019 if (HIWORD(wParam) != BN_CLICKED &&
1020 HIWORD(wParam) != BN_DOUBLECLICKED)
1022 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
1028 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
1055 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1058 static int CALLBACK SshProc (HWND hwnd, UINT msg,
1059 WPARAM wParam, LPARAM lParam) {
1061 char filename[sizeof(cfg.keyfile)];
1065 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
1066 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
1067 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
1068 CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd);
1069 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
1070 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
1071 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
1073 CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2,
1074 cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2);
1075 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
1076 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1079 switch (LOWORD(wParam)) {
1081 if (HIWORD(wParam) == EN_CHANGE)
1082 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1083 sizeof(cfg.termtype)-1);
1086 if (HIWORD(wParam) == EN_CHANGE)
1087 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1088 sizeof(cfg.username)-1);
1091 if (HIWORD(wParam) == BN_CLICKED ||
1092 HIWORD(wParam) == BN_DOUBLECLICKED)
1093 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1096 if (HIWORD(wParam) == BN_CLICKED ||
1097 HIWORD(wParam) == BN_DOUBLECLICKED)
1098 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD);
1100 case IDC3_CIPHER3DES:
1101 case IDC3_CIPHERBLOWF:
1102 case IDC3_CIPHERDES:
1103 if (HIWORD(wParam) == BN_CLICKED ||
1104 HIWORD(wParam) == BN_DOUBLECLICKED) {
1105 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1106 cfg.cipher = CIPHER_3DES;
1107 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1108 cfg.cipher = CIPHER_BLOWFISH;
1109 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1110 cfg.cipher = CIPHER_DES;
1115 if (HIWORD(wParam) == BN_CLICKED ||
1116 HIWORD(wParam) == BN_DOUBLECLICKED) {
1117 if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1))
1119 else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2))
1124 if (HIWORD(wParam) == BN_CLICKED ||
1125 HIWORD(wParam) == BN_DOUBLECLICKED)
1126 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1129 if (HIWORD(wParam) == EN_CHANGE)
1130 GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile,
1131 sizeof(cfg.keyfile)-1);
1135 * FIXME: this crashes. Find out why.
1137 memset(&of, 0, sizeof(of));
1138 #ifdef OPENFILENAME_SIZE_VERSION_400
1139 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1141 of.lStructSize = sizeof(of);
1143 of.hwndOwner = hwnd;
1144 of.lpstrFilter = "All Files\0*\0\0\0";
1145 of.lpstrCustomFilter = NULL;
1146 of.nFilterIndex = 1;
1147 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1148 of.nMaxFile = sizeof(filename);
1149 of.lpstrFileTitle = NULL;
1150 of.lpstrInitialDir = NULL;
1151 of.lpstrTitle = "Select Public Key File";
1153 if (GetOpenFileName(&of)) {
1154 strcpy(cfg.keyfile, filename);
1155 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1161 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1164 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1165 WPARAM wParam, LPARAM lParam) {
1170 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1171 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1173 static int tabs[4] = {25, 61, 96, 128};
1174 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1177 for (i=0; i<256; i++) {
1179 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1180 (i>=0x21 && i != 0x7F) ? i : ' ',
1182 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1187 switch (LOWORD(wParam)) {
1188 case IDC4_MBWINDOWS:
1190 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1196 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1201 for (i=0; i<256; i++)
1202 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1205 cfg.wordness[i] = n;
1206 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1207 LB_DELETESTRING, i, 0);
1208 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1209 (i>=0x21 && i != 0x7F) ? i : ' ',
1211 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1221 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1224 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1225 WPARAM wParam, LPARAM lParam) {
1226 static const char *const colours[] = {
1227 "Default Foreground", "Default Bold Foreground",
1228 "Default Background", "Default Bold Background",
1229 "Cursor Text", "Cursor Colour",
1230 "ANSI Black", "ANSI Black Bold",
1231 "ANSI Red", "ANSI Red Bold",
1232 "ANSI Green", "ANSI Green Bold",
1233 "ANSI Yellow", "ANSI Yellow Bold",
1234 "ANSI Blue", "ANSI Blue Bold",
1235 "ANSI Magenta", "ANSI Magenta Bold",
1236 "ANSI Cyan", "ANSI Cyan Bold",
1237 "ANSI White", "ANSI White Bold"
1239 static const int permanent[] = {
1240 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1241 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1242 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1246 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1247 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1250 for (i=0; i<22; i++)
1251 if (cfg.bold_colour || permanent[i])
1252 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1253 (LPARAM) colours[i]);
1255 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1256 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1257 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1258 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1261 switch (LOWORD(wParam)) {
1262 case IDC5_BOLDCOLOUR:
1263 if (HIWORD(wParam) == BN_CLICKED ||
1264 HIWORD(wParam) == BN_DOUBLECLICKED) {
1266 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1267 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1268 if (cfg.bold_colour && n!=22) {
1269 for (i=0; i<22; i++)
1271 SendDlgItemMessage (hwnd, IDC5_LIST,
1273 (LPARAM) colours[i]);
1274 } else if (!cfg.bold_colour && n!=12) {
1277 SendDlgItemMessage (hwnd, IDC5_LIST,
1278 LB_DELETESTRING, i, 0);
1283 if (HIWORD(wParam) == BN_CLICKED ||
1284 HIWORD(wParam) == BN_DOUBLECLICKED)
1285 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1288 if (HIWORD(wParam) == LBN_DBLCLK ||
1289 HIWORD(wParam) == LBN_SELCHANGE) {
1290 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1292 if (!cfg.bold_colour)
1293 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1294 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1295 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1296 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1300 if (HIWORD(wParam) == BN_CLICKED ||
1301 HIWORD(wParam) == BN_DOUBLECLICKED) {
1302 static CHOOSECOLOR cc;
1303 static DWORD custom[16] = {0}; /* zero initialisers */
1304 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1306 if (!cfg.bold_colour)
1307 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1308 cc.lStructSize = sizeof(cc);
1309 cc.hwndOwner = hwnd;
1310 cc.hInstance = (HWND)hinst;
1311 cc.lpCustColors = custom;
1312 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1314 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1315 if (ChooseColor(&cc)) {
1317 (unsigned char) (cc.rgbResult & 0xFF);
1319 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1321 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1322 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1324 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1326 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1334 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1337 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1338 WPARAM wParam, LPARAM lParam) {
1341 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1342 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1343 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1345 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1346 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1347 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1348 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1349 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1352 switch (LOWORD(wParam)) {
1354 case IDC6_KOI8WIN1251:
1355 case IDC6_88592WIN1250:
1356 cfg.xlat_enablekoiwin =
1357 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1358 cfg.xlat_88592w1250 =
1359 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1361 case IDC6_CAPSLOCKCYR:
1362 if (HIWORD(wParam) == BN_CLICKED ||
1363 HIWORD(wParam) == BN_DOUBLECLICKED) {
1364 cfg.xlat_capslockcyr =
1365 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1368 case IDC2_VTXWINDOWS:
1369 case IDC2_VTOEMANSI:
1370 case IDC2_VTOEMONLY:
1371 case IDC2_VTPOORMAN:
1373 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1374 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1375 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1380 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1383 static DLGPROC panelproc[NPANELS] = {
1384 ConnectionProc, KeyboardProc, TerminalProc,
1385 TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1387 static char *panelids[NPANELS] = {
1388 MAKEINTRESOURCE(IDD_PANEL0),
1389 MAKEINTRESOURCE(IDD_PANEL1),
1390 MAKEINTRESOURCE(IDD_PANEL2),
1391 MAKEINTRESOURCE(IDD_PANEL3),
1392 MAKEINTRESOURCE(IDD_PANEL35),
1393 MAKEINTRESOURCE(IDD_PANEL4),
1394 MAKEINTRESOURCE(IDD_PANEL5),
1395 MAKEINTRESOURCE(IDD_PANEL6)
1398 static char *names[NPANELS] = {
1399 "Connection", "Keyboard", "Terminal", "Telnet",
1400 "SSH", "Selection", "Colours", "Translation"
1403 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1404 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1406 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1407 WPARAM wParam, LPARAM lParam,
1408 int npanels, int *panelnums, HWND *page) {
1413 { /* centre the window */
1416 hw = GetDesktopWindow();
1417 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1418 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1419 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1420 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1423 { /* initialise the tab control */
1427 hw = GetDlgItem (hwnd, IDC_TAB);
1428 for (i=0; i<npanels; i++) {
1429 tab.mask = TCIF_TEXT;
1430 tab.pszText = names[panelnums[i]];
1431 TabCtrl_InsertItem (hw, i, &tab);
1433 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1434 hwnd, panelproc[panelnums[0]]);*/
1435 *page = CreateDialog (hinst, panelids[panelnums[0]],
1436 hwnd, panelproc[panelnums[0]]);
1437 SetWindowLong (*page, GWL_EXSTYLE,
1438 GetWindowLong (*page, GWL_EXSTYLE) |
1439 WS_EX_CONTROLPARENT);
1444 if (LOWORD(wParam) == IDC_TAB &&
1445 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1446 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1448 DestroyWindow (*page);
1449 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1450 hwnd, panelproc[panelnums[i]]);*/
1451 *page = CreateDialog (hinst, panelids[panelnums[i]],
1452 hwnd, panelproc[panelnums[i]]);
1453 SetWindowLong (*page, GWL_EXSTYLE,
1454 GetWindowLong (*page, GWL_EXSTYLE) |
1455 WS_EX_CONTROLPARENT);
1456 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1460 /* case WM_CTLCOLORDLG: */
1461 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1463 switch (LOWORD(wParam)) {
1466 EndDialog (hwnd, 1);
1471 EndDialog (hwnd, 0);
1476 EndDialog (hwnd, 0);
1479 /* Grrr Explorer will maximize Dialogs! */
1481 if (wParam == SIZE_MAXIMIZED)
1488 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1489 WPARAM wParam, LPARAM lParam) {
1494 static HWND page = NULL;
1496 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1499 * If the Connection panel is active and the Session List
1500 * box is selected, we treat a press of Open to have an
1501 * implicit press of Load preceding it.
1503 hw = GetDlgItem (hwnd, IDC_TAB);
1504 i = TabCtrl_GetCurSel(hw);
1505 if (panelproc[mainp[i]] == ConnectionProc &&
1506 page && implicit_load_ok) {
1507 SendMessage (page, WM_COMMAND,
1508 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1512 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1513 EnableWindow(hwnd, 0);
1514 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1515 GetParent(hwnd), AboutProc);
1516 EnableWindow(hwnd, 1);
1517 SetActiveWindow(hwnd);
1519 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1520 MAIN_NPANELS, mainp, &page);
1523 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1524 WPARAM wParam, LPARAM lParam) {
1526 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1527 RECONF_NPANELS, reconfp, &page);
1530 void get_sesslist(int allocate) {
1531 static char *buffer;
1532 int buflen, bufsize, i, ret;
1533 char otherbuf[2048];
1538 if (RegCreateKey(HKEY_CURRENT_USER,
1539 puttystr, &subkey1) != ERROR_SUCCESS)
1542 buflen = bufsize = 0;
1546 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1547 if (ret == ERROR_SUCCESS) {
1548 bufsize = buflen + 2048;
1549 buffer = srealloc(buffer, bufsize);
1550 unmungestr(otherbuf, buffer+buflen);
1551 buflen += strlen(buffer+buflen)+1;
1553 } while (ret == ERROR_SUCCESS);
1554 buffer = srealloc(buffer, buflen+1);
1555 buffer[buflen] = '\0';
1558 nsessions = 1; /* "Default Settings" counts as one */
1560 if (strcmp(p, "Default Settings"))
1566 sessions = smalloc(nsessions * sizeof(char *));
1567 sessions[0] = "Default Settings";
1571 if (strcmp(p, "Default Settings"))
1582 int do_config (void) {
1586 savedsession[0] = '\0';
1587 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1588 get_sesslist(FALSE);
1593 int do_reconfig (HWND hwnd) {
1597 backup_cfg = cfg; /* structure copy */
1598 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1600 cfg = backup_cfg; /* structure copy */
1607 void do_defaults (char *session) {
1609 load_settings (session, TRUE);
1611 load_settings ("Default Settings", FALSE);
1614 void logevent (char *string) {
1615 if (nevents >= negsize) {
1617 events = srealloc (events, negsize * sizeof(*events));
1619 events[nevents] = smalloc(1+strlen(string));
1620 strcpy (events[nevents], string);
1624 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1626 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1627 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1631 void showeventlog (HWND hwnd) {
1633 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1635 ShowWindow (logbox, SW_SHOWNORMAL);
1639 void showabout (HWND hwnd) {
1641 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1643 ShowWindow (abtbox, SW_SHOWNORMAL);
1647 void verify_ssh_host_key(char *host, char *keystr) {
1648 char *otherstr, *mungedhost;
1652 len = 1 + strlen(keystr);
1655 * Now read a saved key in from the registry and see what it
1658 otherstr = smalloc(len);
1659 mungedhost = smalloc(3*strlen(host)+1);
1660 if (!otherstr || !mungedhost)
1661 fatalbox("Out of memory");
1663 mungestr(host, mungedhost);
1665 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1666 &rkey) != ERROR_SUCCESS) {
1667 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1668 "in the registry. There is thus no way to tell\n"
1669 "if the remote host is what you think it is.\n"
1670 "Connect anyway?", "PuTTY Problem",
1671 MB_ICONWARNING | MB_YESNO) == IDNO)
1674 DWORD readlen = len;
1678 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1679 &type, otherstr, &readlen);
1681 if (ret == ERROR_MORE_DATA ||
1682 (ret == ERROR_SUCCESS && type == REG_SZ &&
1683 strcmp(otherstr, keystr))) {
1684 if (MessageBox(NULL,
1685 "This host's host key is different from the\n"
1686 "one cached in the registry! Someone may be\n"
1687 "impersonating this host for malicious reasons;\n"
1688 "alternatively, the host key may have changed\n"
1689 "due to sloppy system administration.\n"
1690 "Replace key in registry and connect?",
1691 "PuTTY: Security Warning",
1692 MB_ICONWARNING | MB_YESNO) == IDNO)
1694 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1696 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1697 if (MessageBox(NULL,
1698 "This host's host key is not cached in the\n"
1699 "registry. Do you want to add it to the cache\n"
1700 "and carry on connecting?",
1702 MB_ICONWARNING | MB_YESNO) == IDNO)
1704 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1713 * Recursively delete a registry key and everything under it.
1715 static void registry_recursive_remove(HKEY key) {
1717 char name[MAX_PATH+1];
1721 while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) {
1722 if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {
1723 registry_recursive_remove(subkey);
1724 RegCloseKey(subkey);
1726 RegDeleteKey(key, name);
1731 * Destroy all registry information associated with PuTTY.
1733 void registry_cleanup(void) {
1736 char name[MAX_PATH+1];
1739 * Open the main PuTTY registry key and remove everything in it.
1741 if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) == ERROR_SUCCESS) {
1742 registry_recursive_remove(key);
1746 * Now open the parent key and remove the PuTTY main key. Once
1747 * we've done that, see if the parent key has any other
1750 if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT,
1751 &key) == ERROR_SUCCESS) {
1752 RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);
1753 ret = RegEnumKey(key, 0, name, sizeof(name));
1756 * If the parent key had no other children, we must delete
1757 * it in its turn. That means opening the _grandparent_
1760 if (ret != ERROR_SUCCESS) {
1761 if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,
1762 &key) == ERROR_SUCCESS) {
1763 RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);