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