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