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