Fix potential segfault on malloc failure
[u/mdw/putty] / windlg.c
CommitLineData
374330e2 1#include <windows.h>
2#include <commctrl.h>
3#include <commdlg.h>
4#include <winsock.h>
5#include <stdio.h>
6#include <stdlib.h>
7
374330e2 8#include "ssh.h"
bea1ef5f 9#include "putty.h"
374330e2 10#include "win_res.h"
11
14963b8f 12#define NPANELS 8
13#define MAIN_NPANELS 8
14#define RECONF_NPANELS 5
374330e2 15
16static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
17
c5e9c988 18static char **events = NULL;
19static int nevents = 0, negsize = 0;
20
374330e2 21static HWND logbox = NULL, abtbox = NULL;
22
23static char hex[16] = "0123456789ABCDEF";
24
25static void mungestr(char *in, char *out) {
26 int candot = 0;
27
28 while (*in) {
29 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
30 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
31 *out++ = '%';
32 *out++ = hex[((unsigned char)*in) >> 4];
33 *out++ = hex[((unsigned char)*in) & 15];
34 } else
35 *out++ = *in;
36 in++;
37 candot = 1;
38 }
39 *out = '\0';
40 return;
41}
42
43static void unmungestr(char *in, char *out) {
374330e2 44 while (*in) {
45 if (*in == '%' && in[1] && in[2]) {
46 int i, j;
47
48 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
49 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
50
51 *out++ = (i<<4) + j;
52 in += 3;
53 } else
54 *out++ = *in++;
55 }
56 *out = '\0';
57 return;
58}
59
60static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
61 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
62}
63
64static void wppi(HKEY key, LPCTSTR name, int value) {
65 RegSetValueEx(key, name, 0, REG_DWORD,
66 (CONST BYTE *)&value, sizeof(value));
67}
68
69static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
70 LPTSTR val, int len) {
71 DWORD type, size;
72 size = len;
73
74 if (key == NULL ||
75 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
76 type != REG_SZ) {
77 strncpy(val, def, len);
78 val[len-1] = '\0';
79 }
80}
81
82static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
83 DWORD type, val, size;
84 size = sizeof(val);
85
86 if (key == NULL ||
87 RegQueryValueEx(key, name, 0, &type,
88 (BYTE *)&val, &size) != ERROR_SUCCESS ||
89 size != sizeof(val) || type != REG_DWORD)
90 *i = def;
91 else
92 *i = val;
93}
94
374330e2 95static HINSTANCE hinst;
96
1cd246bb 97static int readytogo;
98
374330e2 99static void save_settings (char *section, int do_host) {
100 int i;
101 HKEY subkey1, sesskey;
102 char *p;
103
104 p = malloc(3*strlen(section)+1);
105 mungestr(section, p);
106
107 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
108 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
374330e2 109 sesskey = NULL;
110 }
111
112 free(p);
113 RegCloseKey(subkey1);
114
115 wppi (sesskey, "Present", 1);
116 if (do_host) {
117 wpps (sesskey, "HostName", cfg.host);
118 wppi (sesskey, "PortNumber", cfg.port);
119 wpps (sesskey, "Protocol",
5e1a8e27 120 cfg.protocol == PROT_SSH ? "ssh" :
121 cfg.protocol == PROT_TELNET ? "telnet" : "raw" );
374330e2 122 }
123 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
9ef49106 124 wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
374330e2 125 wpps (sesskey, "TerminalType", cfg.termtype);
126 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
127 {
37508af4 128 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 129 p = buf;
37508af4 130 q = cfg.environmt;
374330e2 131 while (*q) {
132 while (*q) {
133 int c = *q++;
134 if (c == '=' || c == ',' || c == '\\')
135 *p++ = '\\';
136 if (c == '\t')
137 c = '=';
138 *p++ = c;
139 }
140 *p++ = ',';
141 q++;
142 }
143 *p = '\0';
144 wpps (sesskey, "Environment", buf);
145 }
146 wpps (sesskey, "UserName", cfg.username);
fef97f43 147 wppi (sesskey, "NoPTY", cfg.nopty);
bea1ef5f 148 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
9697bfd2 149 cfg.cipher == CIPHER_DES ? "des" : "3des");
ccbfb941 150 wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
374330e2 151 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
152 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
153 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
154 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
155 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
156 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
c5e9c988 157 wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
158 wppi (sesskey, "AltF4", cfg.alt_f4);
159 wppi (sesskey, "AltSpace", cfg.alt_space);
5bc238bb 160 wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
374330e2 161 wppi (sesskey, "ScrollbackLines", cfg.savelines);
162 wppi (sesskey, "DECOriginMode", cfg.dec_om);
163 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
fef97f43 164 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
374330e2 165 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
166 wppi (sesskey, "TermWidth", cfg.width);
167 wppi (sesskey, "TermHeight", cfg.height);
168 wpps (sesskey, "Font", cfg.font);
169 wppi (sesskey, "FontIsBold", cfg.fontisbold);
14963b8f 170 wppi (sesskey, "FontCharSet", cfg.fontcharset);
374330e2 171 wppi (sesskey, "FontHeight", cfg.fontheight);
172 wppi (sesskey, "FontVTMode", cfg.vtmode);
173 wppi (sesskey, "TryPalette", cfg.try_palette);
174 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
175 for (i=0; i<22; i++) {
176 char buf[20], buf2[30];
177 sprintf(buf, "Colour%d", i);
178 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
179 cfg.colours[i][1], cfg.colours[i][2]);
180 wpps (sesskey, buf, buf2);
181 }
182 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
183 for (i=0; i<256; i+=32) {
184 char buf[20], buf2[256];
185 int j;
186 sprintf(buf, "Wordness%d", i);
187 *buf2 = '\0';
188 for (j=i; j<i+32; j++) {
189 sprintf(buf2+strlen(buf2), "%s%d",
190 (*buf2 ? "," : ""), cfg.wordness[j]);
191 }
192 wpps (sesskey, buf, buf2);
193 }
14963b8f 194 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
d3d16feb 195 wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
14963b8f 196 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
374330e2 197
198 RegCloseKey(sesskey);
199}
200
201static void del_session (char *section) {
202 HKEY subkey1;
203 char *p;
204
205 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
206 return;
207
208 p = malloc(3*strlen(section)+1);
209 mungestr(section, p);
210 RegDeleteKey(subkey1, p);
211 free(p);
212
213 RegCloseKey(subkey1);
214}
215
216static void load_settings (char *section, int do_host) {
217 int i;
218 HKEY subkey1, sesskey;
219 char *p;
e277c42d 220 char prot[10];
374330e2 221
222 p = malloc(3*strlen(section)+1);
223 mungestr(section, p);
9816085c 224
225 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
374330e2 226 sesskey = NULL;
9816085c 227 } else {
228 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
229 sesskey = NULL;
230 }
231 RegCloseKey(subkey1);
374330e2 232 }
233
234 free(p);
374330e2 235
e277c42d 236 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
237 gppi (sesskey, "PortNumber", default_port, &cfg.port);
238 gpps (sesskey, "Protocol", "default", prot, 10);
239 if (!strcmp(prot, "ssh"))
240 cfg.protocol = PROT_SSH;
241 else if (!strcmp(prot, "telnet"))
f25da523 242 cfg.protocol = PROT_TELNET;
5e1a8e27 243 else if (!strcmp(prot, "raw"))
244 cfg.protocol = PROT_RAW;
e277c42d 245 else
246 cfg.protocol = default_protocol;
247
374330e2 248 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
9ef49106 249 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
374330e2 250 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
251 sizeof(cfg.termtype));
252 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
253 sizeof(cfg.termspeed));
254 {
37508af4 255 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 256 gpps (sesskey, "Environment", "", buf, sizeof(buf));
257 p = buf;
37508af4 258 q = cfg.environmt;
374330e2 259 while (*p) {
260 while (*p && *p != ',') {
261 int c = *p++;
262 if (c == '=')
263 c = '\t';
264 if (c == '\\')
265 c = *p++;
266 *p++ = c;
267 }
268 if (*p == ',') p++;
269 *q++ = '\0';
270 }
271 *q = '\0';
272 }
273 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
fef97f43 274 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
bea1ef5f 275 {
276 char cipher[10];
277 gpps (sesskey, "Cipher", "3des", cipher, 10);
278 if (!strcmp(cipher, "blowfish"))
279 cfg.cipher = CIPHER_BLOWFISH;
9697bfd2 280 else if (!strcmp(cipher, "des"))
281 cfg.cipher = CIPHER_DES;
bea1ef5f 282 else
283 cfg.cipher = CIPHER_3DES;
284 }
ccbfb941 285 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
374330e2 286 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
287 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
288 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
289 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
290 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
291 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
c5e9c988 292 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
293 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
294 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
5bc238bb 295 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
374330e2 296 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
297 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
298 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
fef97f43 299 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
374330e2 300 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
301 gppi (sesskey, "TermWidth", 80, &cfg.width);
302 gppi (sesskey, "TermHeight", 24, &cfg.height);
303 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
304 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
14963b8f 305 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
374330e2 306 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
307 gppi (sesskey, "FontVTMode", VT_POORMAN, &cfg.vtmode);
308 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
309 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
310 for (i=0; i<22; i++) {
311 static char *defaults[] = {
312 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
313 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
314 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
315 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
316 "85,255,255", "187,187,187", "255,255,255"
317 };
318 char buf[20], buf2[30];
319 sprintf(buf, "Colour%d", i);
320 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
321 sscanf(buf2, "%d,%d,%d", &cfg.colours[i][0],
322 &cfg.colours[i][1], &cfg.colours[i][2]);
323 }
324 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
325 for (i=0; i<256; i+=32) {
326 static char *defaults[] = {
327 "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",
328 "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",
329 "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",
330 "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",
331 "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",
332 "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",
333 "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",
334 "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"
335 };
336 char buf[20], buf2[256], *p;
337 int j;
338 sprintf(buf, "Wordness%d", i);
339 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
340 p = buf2;
341 for (j=i; j<i+32; j++) {
342 char *q = p;
343 while (*p && *p != ',') p++;
344 if (*p == ',') *p++ = '\0';
345 cfg.wordness[j] = atoi(q);
346 }
347 }
14963b8f 348 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
d3d16feb 349 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
14963b8f 350 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
351
374330e2 352 RegCloseKey(sesskey);
353}
354
355static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
356 BOOL ok;
357 int n;
358 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
359 if (ok)
360 *result = n;
361}
362
363static int CALLBACK LogProc (HWND hwnd, UINT msg,
364 WPARAM wParam, LPARAM lParam) {
365 int i;
366
367 switch (msg) {
368 case WM_INITDIALOG:
c5e9c988 369 for (i=0; i<nevents; i++)
374330e2 370 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
c5e9c988 371 0, (LPARAM)events[i]);
374330e2 372 return 1;
373/* case WM_CTLCOLORDLG: */
374/* return (int) GetStockObject (LTGRAY_BRUSH); */
375 case WM_COMMAND:
376 switch (LOWORD(wParam)) {
377 case IDOK:
378 logbox = NULL;
379 DestroyWindow (hwnd);
380 return 0;
381 }
382 return 0;
383 case WM_CLOSE:
384 logbox = NULL;
385 DestroyWindow (hwnd);
386 return 0;
387 }
388 return 0;
389}
390
d57835ab 391static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
392 WPARAM wParam, LPARAM lParam) {
393 switch (msg) {
394 case WM_INITDIALOG:
395 return 1;
396 case WM_COMMAND:
397 switch (LOWORD(wParam)) {
398 case IDOK:
399 abtbox = NULL;
400 DestroyWindow (hwnd);
401 return 0;
402 }
403 return 0;
404 case WM_CLOSE:
405 abtbox = NULL;
406 DestroyWindow (hwnd);
407 return 0;
408 }
409 return 0;
410}
411
374330e2 412static int CALLBACK AboutProc (HWND hwnd, UINT msg,
413 WPARAM wParam, LPARAM lParam) {
414 switch (msg) {
415 case WM_INITDIALOG:
067a15ea 416 SetDlgItemText (hwnd, IDA_VERSION, ver);
374330e2 417 return 1;
418/* case WM_CTLCOLORDLG: */
419/* return (int) GetStockObject (LTGRAY_BRUSH); */
420/* case WM_CTLCOLORSTATIC: */
421/* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
422/* return (int) GetStockObject (LTGRAY_BRUSH); */
423 case WM_COMMAND:
424 switch (LOWORD(wParam)) {
425 case IDOK:
426 abtbox = NULL;
427 DestroyWindow (hwnd);
428 return 0;
429 case IDA_LICENCE:
430 EnableWindow(hwnd, 0);
431 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
d57835ab 432 NULL, LicenceProc);
374330e2 433 EnableWindow(hwnd, 1);
434 return 0;
435 }
436 return 0;
437 case WM_CLOSE:
438 abtbox = NULL;
439 DestroyWindow (hwnd);
440 return 0;
441 }
442 return 0;
443}
444
445static int GeneralPanelProc (HWND hwnd, UINT msg,
446 WPARAM wParam, LPARAM lParam) {
447 switch (msg) {
448 case WM_INITDIALOG:
449 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
450 return 1;
451/* case WM_CTLCOLORDLG: */
452/* return (int) GetStockObject (LTGRAY_BRUSH); */
453/* case WM_CTLCOLORSTATIC: */
454/* case WM_CTLCOLORBTN: */
455/* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
456/* return (int) GetStockObject (LTGRAY_BRUSH); */
457 case WM_CLOSE:
458 DestroyWindow (hwnd);
459 return 1;
460 }
461 return 0;
462}
463
464static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
465 WPARAM wParam, LPARAM lParam) {
466 int i;
467
468 switch (msg) {
469 case WM_INITDIALOG:
470 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
471 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
472 for (i = 0; i < nsessions; i++)
473 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
474 0, (LPARAM) (sessions[i]));
5e1a8e27 475 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
476 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
477 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
374330e2 478 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
9ef49106 479 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
374330e2 480 break;
1cd246bb 481 case WM_LBUTTONUP:
482 /*
483 * Button release should trigger WM_OK if there was a
484 * previous double click on the session list.
485 */
486 ReleaseCapture();
487 if (readytogo)
488 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
489 break;
374330e2 490 case WM_COMMAND:
491 switch (LOWORD(wParam)) {
492 case IDC0_PROTTELNET:
493 case IDC0_PROTSSH:
5e1a8e27 494 case IDC0_PROTRAW:
374330e2 495 if (HIWORD(wParam) == BN_CLICKED ||
496 HIWORD(wParam) == BN_DOUBLECLICKED) {
497 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
5e1a8e27 498 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
499 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
374330e2 500 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
501 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
502 cfg.port = i ? 22 : 23;
503 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
504 }
505 }
506 break;
507 case IDC0_HOST:
508 if (HIWORD(wParam) == EN_CHANGE)
509 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
510 sizeof(cfg.host)-1);
511 break;
512 case IDC0_PORT:
513 if (HIWORD(wParam) == EN_CHANGE)
514 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
515 break;
516 case IDC0_CLOSEEXIT:
517 if (HIWORD(wParam) == BN_CLICKED ||
518 HIWORD(wParam) == BN_DOUBLECLICKED)
519 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
520 break;
9ef49106 521 case IDC0_CLOSEWARN:
522 if (HIWORD(wParam) == BN_CLICKED ||
523 HIWORD(wParam) == BN_DOUBLECLICKED)
524 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
525 break;
374330e2 526 case IDC0_SESSEDIT:
527 if (HIWORD(wParam) == EN_CHANGE)
528 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
529 (WPARAM) -1, 0);
530 break;
531 case IDC0_SESSSAVE:
532 if (HIWORD(wParam) == BN_CLICKED ||
533 HIWORD(wParam) == BN_DOUBLECLICKED) {
534 /*
535 * Save a session
536 */
537 char str[2048];
538 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
539 if (!*str) {
540 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
541 LB_GETCURSEL, 0, 0);
542 if (n == LB_ERR) {
543 MessageBeep(0);
544 break;
545 }
546 strcpy (str, sessions[n]);
547 }
548 save_settings (str, !!strcmp(str, "Default Settings"));
549 get_sesslist (FALSE);
550 get_sesslist (TRUE);
551 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
552 0, 0);
553 for (i = 0; i < nsessions; i++)
554 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
555 0, (LPARAM) (sessions[i]));
556 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
557 (WPARAM) -1, 0);
558 }
559 break;
560 case IDC0_SESSLIST:
561 case IDC0_SESSLOAD:
562 if (LOWORD(wParam) == IDC0_SESSLOAD &&
563 HIWORD(wParam) != BN_CLICKED &&
564 HIWORD(wParam) != BN_DOUBLECLICKED)
565 break;
566 if (LOWORD(wParam) == IDC0_SESSLIST &&
567 HIWORD(wParam) != LBN_DBLCLK)
568 break;
569 {
570 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
571 LB_GETCURSEL, 0, 0);
572 if (n == LB_ERR) {
573 MessageBeep(0);
574 break;
575 }
576 load_settings (sessions[n],
577 !!strcmp(sessions[n], "Default Settings"));
578 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
579 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
5e1a8e27 580 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
374330e2 581 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
5e1a8e27 582 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
374330e2 583 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
9ef49106 584 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
374330e2 585 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
586 (WPARAM) -1, 0);
587 }
588 if (LOWORD(wParam) == IDC0_SESSLIST) {
589 /*
590 * A double-click on a saved session should
591 * actually start the session, not just load it.
592 * Unless it's Default Settings or some other
593 * host-less set of saved settings.
594 */
1cd246bb 595 if (*cfg.host) {
596 readytogo = TRUE;
597 SetCapture(hwnd);
598 }
374330e2 599 }
600 break;
601 case IDC0_SESSDEL:
602 if (HIWORD(wParam) == BN_CLICKED ||
603 HIWORD(wParam) == BN_DOUBLECLICKED) {
604 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
605 LB_GETCURSEL, 0, 0);
606 if (n == LB_ERR || n == 0) {
607 MessageBeep(0);
608 break;
609 }
610 del_session(sessions[n]);
611 get_sesslist (FALSE);
612 get_sesslist (TRUE);
613 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
614 0, 0);
615 for (i = 0; i < nsessions; i++)
616 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
617 0, (LPARAM) (sessions[i]));
618 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
619 (WPARAM) -1, 0);
620 }
621 }
622 }
623 return GeneralPanelProc (hwnd, msg, wParam, lParam);
624}
625
626static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
627 WPARAM wParam, LPARAM lParam) {
628 switch (msg) {
629 case WM_INITDIALOG:
630 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
631 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
632 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
633 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
634 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
635 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
636 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
637 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
c5e9c988 638 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
639 cfg.nethack_keypad ? IDC1_KPNH :
374330e2 640 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
c5e9c988 641 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
642 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
5bc238bb 643 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
374330e2 644 break;
645 case WM_COMMAND:
646 if (HIWORD(wParam) == BN_CLICKED ||
647 HIWORD(wParam) == BN_DOUBLECLICKED)
648 switch (LOWORD(wParam)) {
649 case IDC1_DEL008:
650 case IDC1_DEL127:
651 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
652 break;
653 case IDC1_HOMETILDE:
654 case IDC1_HOMERXVT:
655 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
656 break;
657 case IDC1_FUNCTILDE:
658 case IDC1_FUNCLINUX:
659 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
660 break;
661 case IDC1_KPNORMAL:
662 case IDC1_KPAPPLIC:
663 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
c5e9c988 664 cfg.nethack_keypad = FALSE;
665 break;
666 case IDC1_KPNH:
667 cfg.app_keypad = FALSE;
668 cfg.nethack_keypad = TRUE;
374330e2 669 break;
670 case IDC1_CURNORMAL:
671 case IDC1_CURAPPLIC:
672 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
673 break;
c5e9c988 674 case IDC1_ALTF4:
675 if (HIWORD(wParam) == BN_CLICKED ||
676 HIWORD(wParam) == BN_DOUBLECLICKED)
677 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
678 break;
679 case IDC1_ALTSPACE:
680 if (HIWORD(wParam) == BN_CLICKED ||
681 HIWORD(wParam) == BN_DOUBLECLICKED)
682 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
683 break;
5bc238bb 684 case IDC1_LDISCTERM:
685 if (HIWORD(wParam) == BN_CLICKED ||
686 HIWORD(wParam) == BN_DOUBLECLICKED)
687 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
688 break;
374330e2 689 }
690 }
691 return GeneralPanelProc (hwnd, msg, wParam, lParam);
692}
693
694static void fmtfont (char *buf) {
695 sprintf (buf, "Font: %s, ", cfg.font);
696 if (cfg.fontisbold)
697 strcat(buf, "bold, ");
698 if (cfg.fontheight == 0)
699 strcat (buf, "default height");
700 else
701 sprintf (buf+strlen(buf), "%d-%s",
702 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
703 (cfg.fontheight < 0 ? "pixel" : "point"));
704}
705
706static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
707 WPARAM wParam, LPARAM lParam) {
708 CHOOSEFONT cf;
709 LOGFONT lf;
710 char fontstatic[256];
711
712 switch (msg) {
713 case WM_INITDIALOG:
714 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
715 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
716 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
fef97f43 717 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
374330e2 718 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
719 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
720 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
721 fmtfont (fontstatic);
722 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
723 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
724 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
725 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
726 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
727 IDC2_VTPOORMAN);
728 break;
729 case WM_COMMAND:
730 switch (LOWORD(wParam)) {
731 case IDC2_WRAPMODE:
732 if (HIWORD(wParam) == BN_CLICKED ||
733 HIWORD(wParam) == BN_DOUBLECLICKED)
734 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
735 break;
736 case IDC2_WINNAME:
737 if (HIWORD(wParam) == BN_CLICKED ||
738 HIWORD(wParam) == BN_DOUBLECLICKED)
739 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
740 break;
741 case IDC2_DECOM:
742 if (HIWORD(wParam) == BN_CLICKED ||
743 HIWORD(wParam) == BN_DOUBLECLICKED)
744 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
745 break;
fef97f43 746 case IDC2_LFHASCR:
747 if (HIWORD(wParam) == BN_CLICKED ||
748 HIWORD(wParam) == BN_DOUBLECLICKED)
749 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
750 break;
374330e2 751 case IDC2_ROWSEDIT:
752 if (HIWORD(wParam) == EN_CHANGE)
753 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
754 break;
755 case IDC2_COLSEDIT:
756 if (HIWORD(wParam) == EN_CHANGE)
757 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
758 break;
759 case IDC2_SAVEEDIT:
760 if (HIWORD(wParam) == EN_CHANGE)
761 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
762 break;
763 case IDC2_CHOOSEFONT:
764 lf.lfHeight = cfg.fontheight;
765 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
766 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
767 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
14963b8f 768 lf.lfCharSet = cfg.fontcharset;
374330e2 769 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
770 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
771 lf.lfQuality = DEFAULT_QUALITY;
772 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
773 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
774 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
775
776 cf.lStructSize = sizeof(cf);
777 cf.hwndOwner = hwnd;
778 cf.lpLogFont = &lf;
779 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
780 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
781
782 if (ChooseFont (&cf)) {
783 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
784 cfg.font[sizeof(cfg.font)-1] = '\0';
785 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
14963b8f 786 cfg.fontcharset = lf.lfCharSet;
374330e2 787 cfg.fontheight = lf.lfHeight;
788 fmtfont (fontstatic);
789 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
790 }
791 break;
792 case IDC2_VTXWINDOWS:
793 case IDC2_VTOEMANSI:
794 case IDC2_VTOEMONLY:
795 case IDC2_VTPOORMAN:
796 cfg.vtmode =
797 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
798 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
799 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
800 VT_POORMAN);
801 break;
802 }
803 break;
804 }
805 return GeneralPanelProc (hwnd, msg, wParam, lParam);
806}
807
808static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
809 WPARAM wParam, LPARAM lParam) {
810 int i;
811
812 switch (msg) {
813 case WM_INITDIALOG:
814 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
815 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
816 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
817 {
37508af4 818 char *p = cfg.environmt;
374330e2 819 while (*p) {
820 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
821 (LPARAM) p);
822 p += strlen(p)+1;
823 }
824 }
825 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
826 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
827 break;
828 case WM_COMMAND:
829 switch (LOWORD(wParam)) {
830 case IDC3_TTEDIT:
831 if (HIWORD(wParam) == EN_CHANGE)
832 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
833 sizeof(cfg.termtype)-1);
834 break;
835 case IDC3_TSEDIT:
836 if (HIWORD(wParam) == EN_CHANGE)
837 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
838 sizeof(cfg.termspeed)-1);
839 break;
840 case IDC3_LOGEDIT:
841 if (HIWORD(wParam) == EN_CHANGE)
842 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
843 sizeof(cfg.username)-1);
844 break;
845 case IDC3_EMBSD:
846 case IDC3_EMRFC:
847 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
848 break;
849 case IDC3_ENVADD:
850 if (HIWORD(wParam) == BN_CLICKED ||
851 HIWORD(wParam) == BN_DOUBLECLICKED) {
37508af4 852 char str[sizeof(cfg.environmt)];
374330e2 853 char *p;
854 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
855 if (!*str) {
856 MessageBeep(0);
857 break;
858 }
859 p = str + strlen(str);
860 *p++ = '\t';
861 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
862 if (!*p) {
863 MessageBeep(0);
864 break;
865 }
37508af4 866 p = cfg.environmt;
374330e2 867 while (*p) {
868 while (*p) p++;
869 p++;
870 }
37508af4 871 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
374330e2 872 strcpy (p, str);
873 p[strlen(str)+1] = '\0';
874 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
875 0, (LPARAM)str);
876 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
877 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
878 } else {
879 MessageBox(hwnd, "Environment too big", "PuTTY Error",
880 MB_OK | MB_ICONERROR);
881 }
882 }
883 break;
884 case IDC3_ENVREMOVE:
885 if (HIWORD(wParam) != BN_CLICKED &&
886 HIWORD(wParam) != BN_DOUBLECLICKED)
887 break;
888 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
889 if (i == LB_ERR)
890 MessageBeep (0);
891 else {
892 char *p, *q;
893
894 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
895 i, 0);
37508af4 896 p = cfg.environmt;
374330e2 897 while (i > 0) {
898 if (!*p)
899 goto disaster;
900 while (*p) p++;
901 p++;
902 i--;
903 }
904 q = p;
905 if (!*p)
906 goto disaster;
907 while (*p) p++;
908 p++;
909 while (*p) {
910 while (*p)
911 *q++ = *p++;
912 *q++ = *p++;
913 }
914 *q = '\0';
915 disaster:;
916 }
917 break;
918 }
919 break;
920 }
921 return GeneralPanelProc (hwnd, msg, wParam, lParam);
922}
923
924static int CALLBACK SshProc (HWND hwnd, UINT msg,
925 WPARAM wParam, LPARAM lParam) {
926 switch (msg) {
927 case WM_INITDIALOG:
928 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
929 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
fef97f43 930 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
9697bfd2 931 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
bea1ef5f 932 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
9697bfd2 933 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
934
bea1ef5f 935 IDC3_CIPHER3DES);
ccbfb941 936 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
374330e2 937 break;
938 case WM_COMMAND:
939 switch (LOWORD(wParam)) {
940 case IDC3_TTEDIT:
941 if (HIWORD(wParam) == EN_CHANGE)
942 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
943 sizeof(cfg.termtype)-1);
944 break;
945 case IDC3_LOGEDIT:
946 if (HIWORD(wParam) == EN_CHANGE)
947 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
948 sizeof(cfg.username)-1);
949 break;
fef97f43 950 case IDC3_NOPTY:
951 if (HIWORD(wParam) == BN_CLICKED ||
952 HIWORD(wParam) == BN_DOUBLECLICKED)
953 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
954 break;
bea1ef5f 955 case IDC3_CIPHER3DES:
956 case IDC3_CIPHERBLOWF:
9697bfd2 957 case IDC3_CIPHERDES:
bea1ef5f 958 if (HIWORD(wParam) == BN_CLICKED ||
959 HIWORD(wParam) == BN_DOUBLECLICKED) {
960 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
961 cfg.cipher = CIPHER_3DES;
962 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
963 cfg.cipher = CIPHER_BLOWFISH;
9697bfd2 964 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
965 cfg.cipher = CIPHER_DES;
bea1ef5f 966 }
967 break;
ccbfb941 968 case IDC3_AUTHTIS:
969 if (HIWORD(wParam) == BN_CLICKED ||
970 HIWORD(wParam) == BN_DOUBLECLICKED)
971 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
972 break;
374330e2 973 }
974 break;
975 }
976 return GeneralPanelProc (hwnd, msg, wParam, lParam);
977}
978
979static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
980 WPARAM wParam, LPARAM lParam) {
981 int i;
982
983 switch (msg) {
984 case WM_INITDIALOG:
985 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
986 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
987 {
988 static int tabs[4] = {25, 61, 96, 128};
989 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
990 (LPARAM) tabs);
991 }
992 for (i=0; i<256; i++) {
993 char str[100];
994 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
995 (i>=0x21 && i != 0x7F) ? i : ' ',
996 cfg.wordness[i]);
997 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
998 (LPARAM) str);
999 }
1000 break;
1001 case WM_COMMAND:
1002 switch (LOWORD(wParam)) {
1003 case IDC4_MBWINDOWS:
1004 case IDC4_MBXTERM:
1005 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1006 break;
1007 case IDC4_CCSET:
1008 {
1009 BOOL ok;
1010 int i;
1011 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1012
1013 if (!ok)
1014 MessageBeep (0);
1015 else {
1016 for (i=0; i<256; i++)
1017 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1018 i, 0)) {
1019 char str[100];
1020 cfg.wordness[i] = n;
1021 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1022 LB_DELETESTRING, i, 0);
1023 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1024 (i>=0x21 && i != 0x7F) ? i : ' ',
1025 cfg.wordness[i]);
1026 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1027 LB_INSERTSTRING, i,
1028 (LPARAM)str);
1029 }
1030 }
1031 }
1032 break;
1033 }
1034 break;
1035 }
1036 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1037}
1038
1039static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1040 WPARAM wParam, LPARAM lParam) {
1041 static const char *const colours[] = {
1042 "Default Foreground", "Default Bold Foreground",
1043 "Default Background", "Default Bold Background",
1044 "Cursor Text", "Cursor Colour",
1045 "ANSI Black", "ANSI Black Bold",
1046 "ANSI Red", "ANSI Red Bold",
1047 "ANSI Green", "ANSI Green Bold",
1048 "ANSI Yellow", "ANSI Yellow Bold",
1049 "ANSI Blue", "ANSI Blue Bold",
1050 "ANSI Magenta", "ANSI Magenta Bold",
1051 "ANSI Cyan", "ANSI Cyan Bold",
1052 "ANSI White", "ANSI White Bold"
1053 };
1054 static const int permanent[] = {
1055 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1056 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1057 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1058 };
1059 switch (msg) {
1060 case WM_INITDIALOG:
1061 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1062 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1063 {
1064 int i;
1065 for (i=0; i<22; i++)
1066 if (cfg.bold_colour || permanent[i])
1067 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1068 (LPARAM) colours[i]);
1069 }
1070 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1071 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1072 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1073 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1074 break;
1075 case WM_COMMAND:
1076 switch (LOWORD(wParam)) {
1077 case IDC5_BOLDCOLOUR:
1078 if (HIWORD(wParam) == BN_CLICKED ||
1079 HIWORD(wParam) == BN_DOUBLECLICKED) {
1080 int n, i;
1081 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1082 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1083 if (cfg.bold_colour && n!=22) {
1084 for (i=0; i<22; i++)
1085 if (!permanent[i])
1086 SendDlgItemMessage (hwnd, IDC5_LIST,
1087 LB_INSERTSTRING, i,
1088 (LPARAM) colours[i]);
1089 } else if (!cfg.bold_colour && n!=12) {
1090 for (i=22; i-- ;)
1091 if (!permanent[i])
1092 SendDlgItemMessage (hwnd, IDC5_LIST,
1093 LB_DELETESTRING, i, 0);
1094 }
1095 }
1096 break;
1097 case IDC5_PALETTE:
1098 if (HIWORD(wParam) == BN_CLICKED ||
1099 HIWORD(wParam) == BN_DOUBLECLICKED)
1100 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1101 break;
1102 case IDC5_LIST:
1103 if (HIWORD(wParam) == LBN_DBLCLK ||
1104 HIWORD(wParam) == LBN_SELCHANGE) {
1105 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1106 0, 0);
1107 if (!cfg.bold_colour)
1108 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1109 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1110 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1111 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1112 }
1113 break;
1114 case IDC5_CHANGE:
1115 if (HIWORD(wParam) == BN_CLICKED ||
1116 HIWORD(wParam) == BN_DOUBLECLICKED) {
1117 static CHOOSECOLOR cc;
1118 static DWORD custom[16] = {0}; /* zero initialisers */
1119 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1120 0, 0);
1121 if (!cfg.bold_colour)
1122 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1123 cc.lStructSize = sizeof(cc);
1124 cc.hwndOwner = hwnd;
1125 cc.hInstance = hinst;
1126 cc.lpCustColors = custom;
1127 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1128 cfg.colours[i][2]);
1129 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1130 if (ChooseColor(&cc)) {
1131 cfg.colours[i][0] =
1132 (unsigned char) (cc.rgbResult & 0xFF);
1133 cfg.colours[i][1] =
1134 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1135 cfg.colours[i][2] =
1136 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1137 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1138 FALSE);
1139 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1140 FALSE);
1141 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1142 FALSE);
1143 }
1144 }
1145 break;
1146 }
1147 break;
1148 }
1149 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1150}
1151
14963b8f 1152static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
1153 WPARAM wParam, LPARAM lParam) {
1154 switch (msg) {
1155 case WM_INITDIALOG:
d3d16feb 1156 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1157 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1158 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1159 IDC6_NOXLAT);
14963b8f 1160 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1161 case WM_COMMAND:
1162 switch (LOWORD(wParam)) {
d3d16feb 1163 case IDC6_NOXLAT:
1164 case IDC6_KOI8WIN1251:
1165 case IDC6_88592WIN1250:
1166 cfg.xlat_enablekoiwin =
1167 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1168 cfg.xlat_88592w1250 =
1169 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
14963b8f 1170 break;
1171 case IDC6_CAPSLOCKCYR:
1172 if (HIWORD(wParam) == BN_CLICKED ||
1173 HIWORD(wParam) == BN_DOUBLECLICKED) {
1174 cfg.xlat_capslockcyr =
1175 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1176 }
1177 break;
1178 }
1179 }
1180 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1181}
1182
374330e2 1183static DLGPROC panelproc[NPANELS] = {
1184 ConnectionProc, KeyboardProc, TerminalProc,
14963b8f 1185 TelnetProc, SshProc, SelectionProc, ColourProc, LanguageProc
374330e2 1186};
1187static char *panelids[NPANELS] = {
1188 MAKEINTRESOURCE(IDD_PANEL0),
1189 MAKEINTRESOURCE(IDD_PANEL1),
1190 MAKEINTRESOURCE(IDD_PANEL2),
1191 MAKEINTRESOURCE(IDD_PANEL3),
1192 MAKEINTRESOURCE(IDD_PANEL35),
1193 MAKEINTRESOURCE(IDD_PANEL4),
14963b8f 1194 MAKEINTRESOURCE(IDD_PANEL5),
1195 MAKEINTRESOURCE(IDD_PANEL6)
374330e2 1196};
14963b8f 1197
374330e2 1198static char *names[NPANELS] = {
14963b8f 1199 "Connection", "Keyboard", "Terminal", "Telnet",
1200 "SSH", "Selection", "Colours", "Language"
374330e2 1201};
1202
14963b8f 1203static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1204static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
374330e2 1205
1206static int GenericMainDlgProc (HWND hwnd, UINT msg,
1207 WPARAM wParam, LPARAM lParam,
1208 int npanels, int *panelnums, HWND *page) {
1209 HWND hw;
1210
1211 switch (msg) {
1212 case WM_INITDIALOG:
1213 { /* centre the window */
1214 RECT rs, rd;
1215
1216 hw = GetDesktopWindow();
1217 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1218 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1219 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1220 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1221 }
1222 *page = NULL;
1223 { /* initialise the tab control */
1224 TC_ITEMHEADER tab;
1225 int i;
1226
1227 hw = GetDlgItem (hwnd, IDC_TAB);
1228 for (i=0; i<npanels; i++) {
1229 tab.mask = TCIF_TEXT;
1230 tab.pszText = names[panelnums[i]];
1231 TabCtrl_InsertItem (hw, i, &tab);
1232 }
1233/* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1234 hwnd, panelproc[panelnums[0]]);*/
1235 *page = CreateDialog (hinst, panelids[panelnums[0]],
1236 hwnd, panelproc[panelnums[0]]);
1237 SetWindowLong (*page, GWL_EXSTYLE,
1238 GetWindowLong (*page, GWL_EXSTYLE) |
1239 WS_EX_CONTROLPARENT);
1240 }
1241 SetFocus (*page);
1242 return 0;
1243 case WM_NOTIFY:
1244 if (LOWORD(wParam) == IDC_TAB &&
1245 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1246 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1247 if (*page)
1248 DestroyWindow (*page);
1249/* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1250 hwnd, panelproc[panelnums[i]]);*/
1251 *page = CreateDialog (hinst, panelids[panelnums[i]],
1252 hwnd, panelproc[panelnums[i]]);
1253 SetWindowLong (*page, GWL_EXSTYLE,
1254 GetWindowLong (*page, GWL_EXSTYLE) |
1255 WS_EX_CONTROLPARENT);
1256 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1257 return 0;
1258 }
1259 break;
1260/* case WM_CTLCOLORDLG: */
1261/* return (int) GetStockObject (LTGRAY_BRUSH); */
1262 case WM_COMMAND:
1263 switch (LOWORD(wParam)) {
1264 case IDOK:
1265 if (*cfg.host)
1266 EndDialog (hwnd, 1);
1267 else
1268 MessageBeep (0);
1269 return 0;
1270 case IDCANCEL:
1271 EndDialog (hwnd, 0);
1272 return 0;
1273 }
1274 return 0;
1275 case WM_CLOSE:
1276 EndDialog (hwnd, 0);
1277 return 0;
1278 }
1279 return 0;
1280}
1281
1282static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1283 WPARAM wParam, LPARAM lParam) {
1284#if 0
1285 HWND hw;
1286 int i;
1287#endif
1288 static HWND page = NULL;
1289
1290 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1291#if 0
1292 /*
1293 * If the Connection panel is active and the Session List
1294 * box is selected, we treat a press of Open to have an
1295 * implicit press of Load preceding it.
1296 */
1297 hw = GetDlgItem (hwnd, IDC_TAB);
1298 i = TabCtrl_GetCurSel(hw);
1299 if (panelproc[mainp[i]] == ConnectionProc &&
1300 page && implicit_load_ok) {
1301 SendMessage (page, WM_COMMAND,
1302 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1303 }
1304#endif
1305 }
1306 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1307 EnableWindow(hwnd, 0);
1308 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1309 GetParent(hwnd), AboutProc);
1310 EnableWindow(hwnd, 1);
1311 }
1312 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1313 MAIN_NPANELS, mainp, &page);
1314}
1315
1316static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1317 WPARAM wParam, LPARAM lParam) {
1318 static HWND page;
1319 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1320 RECONF_NPANELS, reconfp, &page);
1321}
1322
0a4aa984 1323void get_sesslist(int allocate) {
374330e2 1324 static char *buffer;
1325 int buflen, bufsize, i, ret;
1326 char otherbuf[2048];
1327 char *p;
1328 HKEY subkey1;
1329
1330 if (allocate) {
1331 if (RegCreateKey(HKEY_CURRENT_USER,
1332 puttystr, &subkey1) != ERROR_SUCCESS)
1333 return;
1334
1335 buflen = bufsize = 0;
1336 buffer = NULL;
1337 i = 0;
1338 do {
1339 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1340 if (ret == ERROR_SUCCESS) {
1341 bufsize = buflen + 2048;
1342 buffer = srealloc(buffer, bufsize);
1343 unmungestr(otherbuf, buffer+buflen);
1344 buflen += strlen(buffer+buflen)+1;
1345 }
1346 } while (ret == ERROR_SUCCESS);
1347 buffer = srealloc(buffer, buflen+1);
1348 buffer[buflen] = '\0';
1349
1350 p = buffer;
1351 nsessions = 1; /* "Default Settings" counts as one */
1352 while (*p) {
1353 if (strcmp(p, "Default Settings"))
1354 nsessions++;
1355 while (*p) p++;
1356 p++;
1357 }
1358
1359 sessions = smalloc(nsessions * sizeof(char *));
1360 sessions[0] = "Default Settings";
1361 p = buffer;
1362 i = 1;
1363 while (*p) {
1364 if (strcmp(p, "Default Settings"))
1365 sessions[i++] = p;
1366 while (*p) p++;
1367 p++;
1368 }
1369 } else {
1370 sfree (buffer);
1371 sfree (sessions);
1372 }
1373}
1374
1375int do_config (void) {
1376 int ret;
1377
1378 get_sesslist(TRUE);
1379 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1380 get_sesslist(FALSE);
1381
1382 return ret;
1383}
1384
1385int do_reconfig (HWND hwnd) {
1386 Config backup_cfg;
1387 int ret;
1388
1389 backup_cfg = cfg; /* structure copy */
1390 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1391 if (!ret)
1392 cfg = backup_cfg; /* structure copy */
1393 return ret;
1394}
1395
1396void do_defaults (char *session) {
1397 if (session)
1398 load_settings (session, TRUE);
1399 else
1400 load_settings ("Default Settings", FALSE);
1401}
1402
c5e9c988 1403void logevent (char *string) {
1404 if (nevents >= negsize) {
374330e2 1405 negsize += 64;
c5e9c988 1406 events = srealloc (events, negsize * sizeof(*events));
374330e2 1407 }
c5e9c988 1408 events[nevents] = smalloc(1+strlen(string));
1409 strcpy (events[nevents], string);
1410 nevents++;
374330e2 1411 if (logbox)
1412 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1413 0, (LPARAM)string);
1414}
1415
c5e9c988 1416void showeventlog (HWND hwnd) {
374330e2 1417 if (!logbox) {
1418 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1419 hwnd, LogProc);
1420 ShowWindow (logbox, SW_SHOWNORMAL);
1421 }
1422}
1423
1424void showabout (HWND hwnd) {
1425 if (!abtbox) {
1426 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1427 hwnd, AboutProc);
1428 ShowWindow (abtbox, SW_SHOWNORMAL);
1429 }
1430}
1431
1432void verify_ssh_host_key(char *host, struct RSAKey *key) {
1433 char *keystr, *otherstr, *mungedhost;
1434 int len;
1435 HKEY rkey;
1436
1437 /*
1438 * Format the key into a string.
1439 */
1440 len = rsastr_len(key);
1441 keystr = malloc(len);
1442 if (!keystr)
1443 fatalbox("Out of memory");
1444 rsastr_fmt(keystr, key);
1445
1446 /*
1447 * Now read a saved key in from the registry and see what it
1448 * says.
1449 */
1450 otherstr = malloc(len);
1451 mungedhost = malloc(3*strlen(host)+1);
1452 if (!otherstr || !mungedhost)
1453 fatalbox("Out of memory");
1454
1455 mungestr(host, mungedhost);
1456
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)
1464 exit(0);
1465 } else {
1466 DWORD readlen = len;
1467 DWORD type;
1468 int ret;
1469
1470 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1471 &type, otherstr, &readlen);
1472
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)
1485 exit(0);
1486 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1487 strlen(keystr)+1);
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?",
1493 "PuTTY: New Host",
1494 MB_ICONWARNING | MB_YESNO) == IDNO)
1495 exit(0);
1496 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1497 strlen(keystr)+1);
1498 }
1499
1500 RegCloseKey(rkey);
1501 }
1502}