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