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