Re-enable copying the Event Log. (rev 1.39 [r661] accidentally disabled it)
[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
9ca5da42 19#define NPANELS 9
20#define MAIN_NPANELS 9
21#define RECONF_NPANELS 6
374330e2 22
c5e9c988 23static char **events = NULL;
24static int nevents = 0, negsize = 0;
25
374330e2 26static HWND logbox = NULL, abtbox = NULL;
27
d1622aed 28static void gpps(void *handle, char *name, char *def, char *val, int len) {
29 if (!read_setting_s(handle, name, val, len)) {
374330e2 30 strncpy(val, def, len);
31 val[len-1] = '\0';
32 }
33}
34
d1622aed 35static void gppi(void *handle, char *name, int def, int *i) {
36 *i = read_setting_i(handle, name, def);
374330e2 37}
38
374330e2 39static HINSTANCE hinst;
40
1cd246bb 41static int readytogo;
42
374330e2 43static void save_settings (char *section, int do_host) {
44 int i;
374330e2 45 char *p;
d1622aed 46 void *sesskey;
374330e2 47
d1622aed 48 sesskey = open_settings_w(section);
49 if (!sesskey)
50 return;
374330e2 51
d1622aed 52 write_setting_i (sesskey, "Present", 1);
374330e2 53 if (do_host) {
d1622aed 54 write_setting_s (sesskey, "HostName", cfg.host);
55 write_setting_i (sesskey, "PortNumber", cfg.port);
89ee5268 56 p = "raw";
a721b9eb 57 for (i = 0; backends[i].name != NULL; i++)
89ee5268 58 if (backends[i].protocol == cfg.protocol) {
59 p = backends[i].name;
60 break;
61 }
d1622aed 62 write_setting_s (sesskey, "Protocol", p);
374330e2 63 }
d1622aed 64 write_setting_i (sesskey, "CloseOnExit", !!cfg.close_on_exit);
65 write_setting_i (sesskey, "WarnOnClose", !!cfg.warn_on_close);
66 write_setting_s (sesskey, "TerminalType", cfg.termtype);
67 write_setting_s (sesskey, "TerminalSpeed", cfg.termspeed);
374330e2 68 {
37508af4 69 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 70 p = buf;
37508af4 71 q = cfg.environmt;
374330e2 72 while (*q) {
73 while (*q) {
74 int c = *q++;
75 if (c == '=' || c == ',' || c == '\\')
76 *p++ = '\\';
77 if (c == '\t')
78 c = '=';
79 *p++ = c;
80 }
81 *p++ = ',';
82 q++;
83 }
84 *p = '\0';
d1622aed 85 write_setting_s (sesskey, "Environment", buf);
374330e2 86 }
d1622aed 87 write_setting_s (sesskey, "UserName", cfg.username);
88 write_setting_i (sesskey, "NoPTY", cfg.nopty);
89 write_setting_i (sesskey, "AgentFwd", cfg.agentfwd);
90 write_setting_s (sesskey, "RemoteCmd", cfg.remote_cmd);
91 write_setting_s (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
9697bfd2 92 cfg.cipher == CIPHER_DES ? "des" : "3des");
d1622aed 93 write_setting_i (sesskey, "AuthTIS", cfg.try_tis_auth);
94 write_setting_i (sesskey, "SshProt", cfg.sshprot);
95 write_setting_s (sesskey, "PublicKeyFile", cfg.keyfile);
4c73ca1f 96 write_setting_s (sesskey, "RemoteCommand", cfg.remote_cmd);
d1622aed 97 write_setting_i (sesskey, "RFCEnviron", cfg.rfc_environ);
98 write_setting_i (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
99 write_setting_i (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
100 write_setting_i (sesskey, "LinuxFunctionKeys", cfg.funky_type);
101 write_setting_i (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
102 write_setting_i (sesskey, "ApplicationKeypad", cfg.app_keypad);
103 write_setting_i (sesskey, "NetHackKeypad", cfg.nethack_keypad);
104 write_setting_i (sesskey, "AltF4", cfg.alt_f4);
105 write_setting_i (sesskey, "AltSpace", cfg.alt_space);
106 write_setting_i (sesskey, "LdiscTerm", cfg.ldisc_term);
107 write_setting_i (sesskey, "BlinkCur", cfg.blink_cur);
108 write_setting_i (sesskey, "Beep", cfg.beep);
109 write_setting_i (sesskey, "ScrollbackLines", cfg.savelines);
110 write_setting_i (sesskey, "DECOriginMode", cfg.dec_om);
111 write_setting_i (sesskey, "AutoWrapMode", cfg.wrap_mode);
112 write_setting_i (sesskey, "LFImpliesCR", cfg.lfhascr);
113 write_setting_i (sesskey, "WinNameAlways", cfg.win_name_always);
9ca5da42 114 write_setting_s (sesskey, "WinTitle", cfg.wintitle);
d1622aed 115 write_setting_i (sesskey, "TermWidth", cfg.width);
116 write_setting_i (sesskey, "TermHeight", cfg.height);
117 write_setting_s (sesskey, "Font", cfg.font);
118 write_setting_i (sesskey, "FontIsBold", cfg.fontisbold);
119 write_setting_i (sesskey, "FontCharSet", cfg.fontcharset);
120 write_setting_i (sesskey, "FontHeight", cfg.fontheight);
121 write_setting_i (sesskey, "FontVTMode", cfg.vtmode);
122 write_setting_i (sesskey, "TryPalette", cfg.try_palette);
123 write_setting_i (sesskey, "BoldAsColour", cfg.bold_colour);
374330e2 124 for (i=0; i<22; i++) {
125 char buf[20], buf2[30];
126 sprintf(buf, "Colour%d", i);
127 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
128 cfg.colours[i][1], cfg.colours[i][2]);
d1622aed 129 write_setting_s (sesskey, buf, buf2);
374330e2 130 }
d1622aed 131 write_setting_i (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
374330e2 132 for (i=0; i<256; i+=32) {
133 char buf[20], buf2[256];
134 int j;
135 sprintf(buf, "Wordness%d", i);
136 *buf2 = '\0';
137 for (j=i; j<i+32; j++) {
138 sprintf(buf2+strlen(buf2), "%s%d",
139 (*buf2 ? "," : ""), cfg.wordness[j]);
140 }
d1622aed 141 write_setting_s (sesskey, buf, buf2);
374330e2 142 }
d1622aed 143 write_setting_i (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
144 write_setting_i (sesskey, "88592Xlat", cfg.xlat_88592w1250);
145 write_setting_i (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
146 write_setting_i (sesskey, "ScrollBar", cfg.scrollbar);
147 write_setting_i (sesskey, "ScrollOnKey", cfg.scroll_on_key);
148 write_setting_i (sesskey, "LockSize", cfg.locksize);
149 write_setting_i (sesskey, "BCE", cfg.bce);
150 write_setting_i (sesskey, "BlinkText", cfg.blinktext);
151
152 close_settings_w(sesskey);
374330e2 153}
154
155static void load_settings (char *section, int do_host) {
156 int i;
e277c42d 157 char prot[10];
d1622aed 158 void *sesskey;
374330e2 159
d1622aed 160 sesskey = open_settings_r(section);
374330e2 161
e277c42d 162 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
163 gppi (sesskey, "PortNumber", default_port, &cfg.port);
89ee5268 164
e277c42d 165 gpps (sesskey, "Protocol", "default", prot, 10);
89ee5268 166 cfg.protocol = default_protocol;
a721b9eb 167 for (i = 0; backends[i].name != NULL; i++)
89ee5268 168 if (!strcmp(prot, backends[i].name)) {
169 cfg.protocol = backends[i].protocol;
170 break;
171 }
e277c42d 172
374330e2 173 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
9ef49106 174 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
374330e2 175 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
176 sizeof(cfg.termtype));
177 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
178 sizeof(cfg.termspeed));
179 {
37508af4 180 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 181 gpps (sesskey, "Environment", "", buf, sizeof(buf));
182 p = buf;
29b611b7 183 q = cfg.environmt;
374330e2 184 while (*p) {
185 while (*p && *p != ',') {
186 int c = *p++;
187 if (c == '=')
188 c = '\t';
189 if (c == '\\')
190 c = *p++;
29b611b7 191 *q++ = c;
374330e2 192 }
193 if (*p == ',') p++;
194 *q++ = '\0';
195 }
196 *q = '\0';
197 }
198 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
fef97f43 199 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
979310f1 200 gppi (sesskey, "AgentFwd", 0, &cfg.agentfwd);
6abbf9e3 201 gpps (sesskey, "RemoteCmd", "", cfg.remote_cmd, sizeof(cfg.remote_cmd));
bea1ef5f 202 {
203 char cipher[10];
204 gpps (sesskey, "Cipher", "3des", cipher, 10);
205 if (!strcmp(cipher, "blowfish"))
206 cfg.cipher = CIPHER_BLOWFISH;
9697bfd2 207 else if (!strcmp(cipher, "des"))
208 cfg.cipher = CIPHER_DES;
bea1ef5f 209 else
210 cfg.cipher = CIPHER_3DES;
211 }
adf799dd 212 gppi (sesskey, "SshProt", 1, &cfg.sshprot);
ccbfb941 213 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
7cca0d81 214 gpps (sesskey, "PublicKeyFile", "", cfg.keyfile, sizeof(cfg.keyfile));
4c73ca1f 215 gpps (sesskey, "RemoteCommand", "", cfg.remote_cmd,
216 sizeof(cfg.remote_cmd));
374330e2 217 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
218 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
219 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
c9def1b8 220 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type);
374330e2 221 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
222 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
c5e9c988 223 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
224 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
225 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
5bc238bb 226 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
217dceef 227 gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
2a25a1b4 228 gppi (sesskey, "Beep", 1, &cfg.beep);
374330e2 229 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
230 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
231 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
fef97f43 232 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
374330e2 233 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
9ca5da42 234 gpps (sesskey, "WinTitle", "", cfg.wintitle, sizeof(cfg.wintitle));
374330e2 235 gppi (sesskey, "TermWidth", 80, &cfg.width);
236 gppi (sesskey, "TermHeight", 24, &cfg.height);
237 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
238 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
14963b8f 239 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
374330e2 240 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
2a7bfc6e 241 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
374330e2 242 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
243 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
244 for (i=0; i<22; i++) {
245 static char *defaults[] = {
246 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
247 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
248 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
249 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
250 "85,255,255", "187,187,187", "255,255,255"
251 };
252 char buf[20], buf2[30];
1d470ad2 253 int c0, c1, c2;
374330e2 254 sprintf(buf, "Colour%d", i);
255 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
1d470ad2 256 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
257 cfg.colours[i][0] = c0;
258 cfg.colours[i][1] = c1;
259 cfg.colours[i][2] = c2;
260 }
374330e2 261 }
262 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
263 for (i=0; i<256; i+=32) {
264 static char *defaults[] = {
265 "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",
266 "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",
267 "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",
268 "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",
269 "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",
270 "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",
271 "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",
272 "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"
273 };
274 char buf[20], buf2[256], *p;
275 int j;
276 sprintf(buf, "Wordness%d", i);
277 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
278 p = buf2;
279 for (j=i; j<i+32; j++) {
280 char *q = p;
281 while (*p && *p != ',') p++;
282 if (*p == ',') *p++ = '\0';
283 cfg.wordness[j] = atoi(q);
284 }
285 }
14963b8f 286 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
d3d16feb 287 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
14963b8f 288 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
c9def1b8 289 gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar);
290 gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key);
291 gppi (sesskey, "LockSize", 0, &cfg.locksize);
292 gppi (sesskey, "BCE", 0, &cfg.bce);
293 gppi (sesskey, "BlinkText", 0, &cfg.blinktext);
14963b8f 294
d1622aed 295 close_settings_r(sesskey);
374330e2 296}
297
c9def1b8 298static void force_normal(HWND hwnd)
299{
300static int recurse = 0;
301
302 WINDOWPLACEMENT wp;
303
304 if(recurse) return;
305 recurse = 1;
306
307 wp.length = sizeof(wp);
308 if (GetWindowPlacement(hwnd, &wp))
309 {
310 wp.showCmd = SW_SHOWNORMAL;
311 SetWindowPlacement(hwnd, &wp);
312 }
313 recurse = 0;
314}
315
374330e2 316static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
317 BOOL ok;
318 int n;
319 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
320 if (ok)
321 *result = n;
322}
323
324static int CALLBACK LogProc (HWND hwnd, UINT msg,
325 WPARAM wParam, LPARAM lParam) {
326 int i;
327
328 switch (msg) {
329 case WM_INITDIALOG:
c5e9c988 330 for (i=0; i<nevents; i++)
374330e2 331 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
c5e9c988 332 0, (LPARAM)events[i]);
374330e2 333 return 1;
374330e2 334 case WM_COMMAND:
335 switch (LOWORD(wParam)) {
336 case IDOK:
337 logbox = NULL;
338 DestroyWindow (hwnd);
339 return 0;
989b10e9 340 case IDN_COPY:
341 if (HIWORD(wParam) == BN_CLICKED ||
342 HIWORD(wParam) == BN_DOUBLECLICKED) {
343 int selcount;
344 int *selitems;
345 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
346 LB_GETSELCOUNT, 0, 0);
347 selitems = malloc(selcount * sizeof(int));
348 if (selitems) {
349 int count = SendDlgItemMessage(hwnd, IDN_LIST,
350 LB_GETSELITEMS,
351 selcount, (LPARAM)selitems);
352 int i;
353 int size;
354 char *clipdata;
355 static unsigned char sel_nl[] = SEL_NL;
356
357 size = 0;
358 for (i = 0; i < count; i++)
359 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
360
361 clipdata = malloc(size);
362 if (clipdata) {
363 char *p = clipdata;
364 for (i = 0; i < count; i++) {
365 char *q = events[selitems[i]];
366 int qlen = strlen(q);
367 memcpy(p, q, qlen);
368 p += qlen;
369 memcpy(p, sel_nl, sizeof(sel_nl));
370 p += sizeof(sel_nl);
371 }
372 write_clip(clipdata, size);
373 term_deselect();
374 free(clipdata);
375 }
376 free(selitems);
377 }
378 }
379 return 0;
374330e2 380 }
381 return 0;
382 case WM_CLOSE:
383 logbox = NULL;
384 DestroyWindow (hwnd);
385 return 0;
386 }
387 return 0;
388}
389
d57835ab 390static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
391 WPARAM wParam, LPARAM lParam) {
392 switch (msg) {
393 case WM_INITDIALOG:
394 return 1;
395 case WM_COMMAND:
396 switch (LOWORD(wParam)) {
397 case IDOK:
97749503 398 EndDialog(hwnd, 1);
d57835ab 399 return 0;
400 }
401 return 0;
402 case WM_CLOSE:
97749503 403 EndDialog(hwnd, 1);
d57835ab 404 return 0;
405 }
406 return 0;
407}
408
374330e2 409static int CALLBACK AboutProc (HWND hwnd, UINT msg,
410 WPARAM wParam, LPARAM lParam) {
411 switch (msg) {
412 case WM_INITDIALOG:
067a15ea 413 SetDlgItemText (hwnd, IDA_VERSION, ver);
374330e2 414 return 1;
374330e2 415 case WM_COMMAND:
416 switch (LOWORD(wParam)) {
417 case IDOK:
418 abtbox = NULL;
419 DestroyWindow (hwnd);
420 return 0;
421 case IDA_LICENCE:
422 EnableWindow(hwnd, 0);
423 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
d57835ab 424 NULL, LicenceProc);
374330e2 425 EnableWindow(hwnd, 1);
9a70ac47 426 SetActiveWindow(hwnd);
374330e2 427 return 0;
428 }
429 return 0;
430 case WM_CLOSE:
431 abtbox = NULL;
432 DestroyWindow (hwnd);
433 return 0;
434 }
435 return 0;
436}
437
d4dcbf56 438/* ----------------------------------------------------------------------
439 * Routines to self-manage the controls in a dialog box.
440 */
441
442#define GAPBETWEEN 3
443#define GAPWITHIN 1
444#define DLGWIDTH 168
445#define STATICHEIGHT 8
446#define CHECKBOXHEIGHT 8
447#define RADIOHEIGHT 8
448#define EDITHEIGHT 12
449#define COMBOHEIGHT 12
450#define PUSHBTNHEIGHT 14
451
452struct ctlpos {
453 HWND hwnd;
454 LONG units;
455 WPARAM font;
456 int ypos, width;
457};
458
459/* Used on self-constructed dialogs. */
75cab814 460static void ctlposinit(struct ctlpos *cp, HWND hwnd) {
d4dcbf56 461 RECT r;
462 cp->hwnd = hwnd;
463 cp->units = GetWindowLong(hwnd, GWL_USERDATA);
464 cp->font = GetWindowLong(hwnd, DWL_USER);
465 cp->ypos = GAPBETWEEN;
466 GetClientRect(hwnd, &r);
467 cp->width = (r.right * 4) / (cp->units & 0xFFFF) - 2*GAPBETWEEN;
468}
469
470/* Used on kosher dialogs. */
75cab814 471static void ctlposinit2(struct ctlpos *cp, HWND hwnd) {
d4dcbf56 472 RECT r;
473 cp->hwnd = hwnd;
474 r.left = r.top = 0;
475 r.right = 4;
476 r.bottom = 8;
477 MapDialogRect(hwnd, &r);
478 cp->units = (r.bottom << 16) | r.right;
479 cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);
480 cp->ypos = GAPBETWEEN;
481 GetClientRect(hwnd, &r);
482 cp->width = (r.right * 4) / (cp->units & 0xFFFF) - 2*GAPBETWEEN;
483}
484
75cab814 485static void doctl(struct ctlpos *cp, RECT r,
486 char *wclass, int wstyle, int exstyle,
487 char *wtext, int wid) {
d4dcbf56 488 HWND ctl;
489 /*
490 * Note nonstandard use of RECT. This is deliberate: by
491 * transforming the width and height directly we arrange to
492 * have all supposedly same-sized controls really same-sized.
493 */
494
495 /* MapDialogRect, or its near equivalent. */
496 r.left = (r.left * (cp->units & 0xFFFF)) / 4;
497 r.right = (r.right * (cp->units & 0xFFFF)) / 4;
498 r.top = (r.top * ((cp->units>>16) & 0xFFFF)) / 8;
499 r.bottom = (r.bottom * ((cp->units>>16) & 0xFFFF)) / 8;
500
501 ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,
502 r.left, r.top, r.right, r.bottom,
503 cp->hwnd, (HMENU)wid, hinst, NULL);
504 SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));
505}
506
507/*
508 * Some edit boxes. Each one has a static above it. The percentages
509 * of the horizontal space are provided.
510 */
75cab814 511static void multiedit(struct ctlpos *cp, ...) {
d4dcbf56 512 RECT r;
513 va_list ap;
514 int percent, xpos;
515
516 percent = xpos = 0;
517 va_start(ap, cp);
518 while (1) {
519 char *text;
520 int staticid, editid, pcwidth;
521 text = va_arg(ap, char *);
522 if (!text)
523 break;
524 staticid = va_arg(ap, int);
525 editid = va_arg(ap, int);
526 pcwidth = va_arg(ap, int);
527
528 r.left = xpos + GAPBETWEEN;
529 percent += pcwidth;
530 xpos = (cp->width + GAPBETWEEN) * percent / 100;
531 r.right = xpos - r.left;
532
533 r.top = cp->ypos; r.bottom = STATICHEIGHT;
534 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
535 text, staticid);
536 r.top = cp->ypos + 8 + GAPWITHIN; r.bottom = EDITHEIGHT;
537 doctl(cp, r, "EDIT",
538 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
539 WS_EX_CLIENTEDGE,
540 "", editid);
541 }
542 va_end(ap);
543 cp->ypos += 8+GAPWITHIN+12+GAPBETWEEN;
544}
545
546/*
547 * A set of radio buttons on the same line, with a static above
548 * them. `nacross' dictates how many parts the line is divided into
549 * (you might want this not to equal the number of buttons if you
550 * needed to line up some 2s and some 3s to look good in the same
551 * panel).
552 */
75cab814 553static void radioline(struct ctlpos *cp,
554 char *text, int id, int nacross, ...) {
d4dcbf56 555 RECT r;
556 va_list ap;
557 int group;
558 int i;
559
560 r.left = GAPBETWEEN; r.top = cp->ypos;
561 r.right = cp->width; r.bottom = STATICHEIGHT;
562 cp->ypos += r.bottom + GAPWITHIN;
563 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
564 va_start(ap, nacross);
565 group = WS_GROUP;
566 i = 0;
567 while (1) {
568 char *btext;
569 int bid;
570 btext = va_arg(ap, char *);
571 if (!btext)
572 break;
573 bid = va_arg(ap, int);
574 r.left = GAPBETWEEN + i * (cp->width+GAPBETWEEN)/nacross;
575 r.right = (i+1) * (cp->width+GAPBETWEEN)/nacross - r.left;
576 r.top = cp->ypos; r.bottom = RADIOHEIGHT;
577 doctl(cp, r, "BUTTON",
578 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
579 0,
580 btext, bid);
581 group = 0;
582 i++;
583 }
584 va_end(ap);
585 cp->ypos += r.bottom + GAPBETWEEN;
586}
587
588/*
589 * A set of radio buttons on multiple lines, with a static above
590 * them.
591 */
75cab814 592static void radiobig(struct ctlpos *cp, char *text, int id, ...) {
d4dcbf56 593 RECT r;
594 va_list ap;
595 int group;
596
597 r.left = GAPBETWEEN; r.top = cp->ypos;
598 r.right = cp->width; r.bottom = STATICHEIGHT;
599 cp->ypos += r.bottom + GAPWITHIN;
600 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
601 va_start(ap, id);
602 group = WS_GROUP;
603 while (1) {
604 char *btext;
605 int bid;
606 btext = va_arg(ap, char *);
607 if (!btext)
608 break;
609 bid = va_arg(ap, int);
610 r.left = GAPBETWEEN; r.top = cp->ypos;
611 r.right = cp->width; r.bottom = STATICHEIGHT;
612 cp->ypos += r.bottom + GAPWITHIN;
613 doctl(cp, r, "BUTTON",
614 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
615 0,
616 btext, bid);
617 group = 0;
618 }
619 va_end(ap);
620 cp->ypos += GAPBETWEEN - GAPWITHIN;
621}
622
623/*
624 * A single standalone checkbox.
625 */
75cab814 626static void checkbox(struct ctlpos *cp, char *text, int id) {
d4dcbf56 627 RECT r;
628
629 r.left = GAPBETWEEN; r.top = cp->ypos;
630 r.right = cp->width; r.bottom = CHECKBOXHEIGHT;
631 cp->ypos += r.bottom + GAPBETWEEN;
632 doctl(cp, r, "BUTTON",
633 BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,
634 text, id);
635}
636
637/*
638 * A button on the right hand side, with a static to its left.
639 */
75cab814 640static void staticbtn(struct ctlpos *cp, char *stext, int sid,
641 char *btext, int bid) {
d4dcbf56 642 const int height = (PUSHBTNHEIGHT > STATICHEIGHT ?
643 PUSHBTNHEIGHT : STATICHEIGHT);
644 RECT r;
645 int lwid, rwid, rpos;
646
647 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
648 lwid = rpos - 2*GAPBETWEEN;
649 rwid = cp->width + GAPBETWEEN - rpos;
650
651 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
652 r.right = lwid; r.bottom = STATICHEIGHT;
653 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
654
655 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
656 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
657 doctl(cp, r, "BUTTON",
658 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
659 0,
660 btext, bid);
661
662 cp->ypos += height + GAPBETWEEN;
663}
664
665/*
666 * An edit control on the right hand side, with a static to its left.
667 */
75cab814 668static void staticedit(struct ctlpos *cp, char *stext, int sid, int eid) {
d4dcbf56 669 const int height = (EDITHEIGHT > STATICHEIGHT ?
670 EDITHEIGHT : STATICHEIGHT);
671 RECT r;
672 int lwid, rwid, rpos;
673
674 rpos = GAPBETWEEN + (cp->width + GAPBETWEEN) / 2;
675 lwid = rpos - 2*GAPBETWEEN;
676 rwid = cp->width + GAPBETWEEN - rpos;
677
678 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
679 r.right = lwid; r.bottom = STATICHEIGHT;
680 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
681
682 r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2;
683 r.right = rwid; r.bottom = EDITHEIGHT;
684 doctl(cp, r, "EDIT",
685 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
686 WS_EX_CLIENTEDGE,
687 "", eid);
688
689 cp->ypos += height + GAPBETWEEN;
690}
691
692/*
693 * A tab-control substitute when a real tab control is unavailable.
694 */
75cab814 695static void ersatztab(struct ctlpos *cp, char *stext, int sid,
696 int lid, int s2id) {
d4dcbf56 697 const int height = (COMBOHEIGHT > STATICHEIGHT ?
698 COMBOHEIGHT : STATICHEIGHT);
699 RECT r;
700 int bigwid, lwid, rwid, rpos;
701 static const int BIGGAP = 15;
702 static const int MEDGAP = 3;
703
704 bigwid = cp->width + 2*GAPBETWEEN - 2*BIGGAP;
705 cp->ypos += MEDGAP;
706 rpos = BIGGAP + (bigwid + BIGGAP) / 2;
707 lwid = rpos - 2*BIGGAP;
708 rwid = bigwid + BIGGAP - rpos;
709
710 r.left = BIGGAP; r.top = cp->ypos + (height-STATICHEIGHT)/2;
711 r.right = lwid; r.bottom = STATICHEIGHT;
712 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
713
714 r.left = rpos; r.top = cp->ypos + (height-COMBOHEIGHT)/2;
715 r.right = rwid; r.bottom = COMBOHEIGHT*10;
716 doctl(cp, r, "COMBOBOX",
717 WS_CHILD | WS_VISIBLE | WS_TABSTOP |
718 CBS_DROPDOWNLIST | CBS_HASSTRINGS,
719 WS_EX_CLIENTEDGE,
720 "", lid);
721
722 cp->ypos += height + MEDGAP + GAPBETWEEN;
723
724 r.left = GAPBETWEEN; r.top = cp->ypos;
725 r.right = cp->width; r.bottom = 2;
726 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
727 0, "", s2id);
728}
729
730/*
731 * A static line, followed by an edit control on the left hand side
732 * and a button on the right.
733 */
75cab814 734static void editbutton(struct ctlpos *cp, char *stext, int sid,
735 int eid, char *btext, int bid) {
d4dcbf56 736 const int height = (EDITHEIGHT > PUSHBTNHEIGHT ?
737 EDITHEIGHT : PUSHBTNHEIGHT);
738 RECT r;
739 int lwid, rwid, rpos;
740
741 r.left = GAPBETWEEN; r.top = cp->ypos;
742 r.right = cp->width; r.bottom = STATICHEIGHT;
743 cp->ypos += r.bottom + GAPWITHIN;
744 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
745
746 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
747 lwid = rpos - 2*GAPBETWEEN;
748 rwid = cp->width + GAPBETWEEN - rpos;
749
750 r.left = GAPBETWEEN; r.top = cp->ypos + (height-EDITHEIGHT)/2;
751 r.right = lwid; r.bottom = EDITHEIGHT;
752 doctl(cp, r, "EDIT",
753 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
754 WS_EX_CLIENTEDGE,
755 "", eid);
756
757 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
758 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
759 doctl(cp, r, "BUTTON",
760 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
761 0,
762 btext, bid);
763
764 cp->ypos += height + GAPBETWEEN;
765}
766
767/*
768 * Special control which was hard to describe generically: the
769 * session-saver assembly. A static; below that an edit box; below
770 * that a list box. To the right of the list box, a column of
771 * buttons.
772 */
75cab814 773static void sesssaver(struct ctlpos *cp, char *text,
774 int staticid, int editid, int listid, ...) {
d4dcbf56 775 RECT r;
776 va_list ap;
777 int lwid, rwid, rpos;
778 int y;
779 const int LISTDEFHEIGHT = 66;
780
781 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
782 lwid = rpos - 2*GAPBETWEEN;
783 rwid = cp->width + GAPBETWEEN - rpos;
784
785 /* The static control. */
786 r.left = GAPBETWEEN; r.top = cp->ypos;
787 r.right = lwid; r.bottom = STATICHEIGHT;
788 cp->ypos += r.bottom + GAPWITHIN;
789 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
790
791 /* The edit control. */
792 r.left = GAPBETWEEN; r.top = cp->ypos;
793 r.right = lwid; r.bottom = EDITHEIGHT;
794 cp->ypos += r.bottom + GAPWITHIN;
795 doctl(cp, r, "EDIT",
796 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
797 WS_EX_CLIENTEDGE,
27be4452 798 "", editid);
d4dcbf56 799
800 /*
801 * The buttons (we should hold off on the list box until we
802 * know how big the buttons are).
803 */
804 va_start(ap, listid);
805 y = cp->ypos;
806 while (1) {
807 char *btext = va_arg(ap, char *);
808 int bid;
809 if (!btext) break;
810 bid = va_arg(ap, int);
811 r.left = rpos; r.top = y;
812 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
813 y += r.bottom + GAPWITHIN;
814 doctl(cp, r, "BUTTON",
815 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
816 0,
817 btext, bid);
818 }
819
820 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
821 y -= cp->ypos;
822 y -= GAPWITHIN;
823 if (y < LISTDEFHEIGHT) y = LISTDEFHEIGHT;
824 r.left = GAPBETWEEN; r.top = cp->ypos;
825 r.right = lwid; r.bottom = y;
826 cp->ypos += y + GAPBETWEEN;
827 doctl(cp, r, "LISTBOX",
d57a8a6d 828 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
829 LBS_STANDARD | LBS_HASSTRINGS,
d4dcbf56 830 WS_EX_CLIENTEDGE,
831 "", listid);
832}
833
834/*
835 * Another special control: the environment-variable setter. A
836 * static line first; then a pair of edit boxes with associated
837 * statics, and two buttons; then a list box.
838 */
75cab814 839static void envsetter(struct ctlpos *cp, char *stext, int sid,
840 char *e1stext, int e1sid, int e1id,
841 char *e2stext, int e2sid, int e2id,
842 int listid,
843 char *b1text, int b1id, char *b2text, int b2id) {
d4dcbf56 844 RECT r;
845 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
846 STATICHEIGHT :
847 EDITHEIGHT > PUSHBTNHEIGHT ?
848 EDITHEIGHT : PUSHBTNHEIGHT);
849 const static int percents[] = { 20, 35, 10, 25 };
850 int i, j, xpos, percent;
851 const int LISTHEIGHT = 42;
852
853 /* The static control. */
854 r.left = GAPBETWEEN; r.top = cp->ypos;
855 r.right = cp->width; r.bottom = STATICHEIGHT;
856 cp->ypos += r.bottom + GAPWITHIN;
857 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
858
859 /* The statics+edits+buttons. */
860 for (j = 0; j < 2; j++) {
861 percent = 10;
862 for (i = 0; i < 4; i++) {
863 xpos = (cp->width + GAPBETWEEN) * percent / 100;
864 r.left = xpos + GAPBETWEEN;
865 percent += percents[i];
866 xpos = (cp->width + GAPBETWEEN) * percent / 100;
867 r.right = xpos - r.left;
868 r.top = cp->ypos;
869 r.bottom = (i==0 ? STATICHEIGHT :
870 i==1 ? EDITHEIGHT :
871 PUSHBTNHEIGHT);
872 r.top += (height-r.bottom)/2;
873 if (i==0) {
874 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
875 j==0 ? e1stext : e2stext, j==0 ? e1sid : e2sid);
876 } else if (i==1) {
877 doctl(cp, r, "EDIT",
878 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
879 WS_EX_CLIENTEDGE,
880 "", j==0 ? e1id : e2id);
881 } else if (i==3) {
882 doctl(cp, r, "BUTTON",
883 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
884 0,
885 j==0 ? b1text : b2text, j==0 ? b1id : b2id);
886 }
887 }
888 cp->ypos += height + GAPWITHIN;
889 }
890
891 /* The list box. */
892 r.left = GAPBETWEEN; r.top = cp->ypos;
893 r.right = cp->width; r.bottom = LISTHEIGHT;
894 cp->ypos += r.bottom + GAPBETWEEN;
895 doctl(cp, r, "LISTBOX",
896 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
897 LBS_USETABSTOPS,
898 WS_EX_CLIENTEDGE,
899 "", listid);
900}
901
902/*
903 * Yet another special control: the character-class setter. A
904 * static, then a list, then a line containing a
905 * button-and-static-and-edit.
906 */
75cab814 907static void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
908 char *btext, int bid, int eid, char *s2text, int s2id) {
d4dcbf56 909 RECT r;
910 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
911 STATICHEIGHT :
912 EDITHEIGHT > PUSHBTNHEIGHT ?
913 EDITHEIGHT : PUSHBTNHEIGHT);
914 const static int percents[] = { 30, 40, 30 };
915 int i, xpos, percent;
916 const int LISTHEIGHT = 66;
917
918 /* The static control. */
919 r.left = GAPBETWEEN; r.top = cp->ypos;
920 r.right = cp->width; r.bottom = STATICHEIGHT;
921 cp->ypos += r.bottom + GAPWITHIN;
922 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
923
924 /* The list box. */
925 r.left = GAPBETWEEN; r.top = cp->ypos;
926 r.right = cp->width; r.bottom = LISTHEIGHT;
927 cp->ypos += r.bottom + GAPWITHIN;
928 doctl(cp, r, "LISTBOX",
929 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
930 LBS_USETABSTOPS,
931 WS_EX_CLIENTEDGE,
932 "", listid);
933
934 /* The button+static+edit. */
935 percent = xpos = 0;
936 for (i = 0; i < 3; i++) {
937 r.left = xpos + GAPBETWEEN;
938 percent += percents[i];
939 xpos = (cp->width + GAPBETWEEN) * percent / 100;
940 r.right = xpos - r.left;
941 r.top = cp->ypos;
942 r.bottom = (i==0 ? PUSHBTNHEIGHT :
943 i==1 ? STATICHEIGHT :
944 EDITHEIGHT);
945 r.top += (height-r.bottom)/2;
946 if (i==0) {
947 doctl(cp, r, "BUTTON",
948 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
949 0, btext, bid);
950 } else if (i==1) {
951 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER,
952 0, s2text, s2id);
953 } else if (i==2) {
954 doctl(cp, r, "EDIT",
955 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
956 WS_EX_CLIENTEDGE, "", eid);
957 }
958 }
959 cp->ypos += height + GAPBETWEEN;
960}
961
962/*
963 * A special control (horrors!). The colour editor. A static line;
964 * then on the left, a list box, and on the right, a sequence of
965 * two-part statics followed by a button.
966 */
75cab814 967static void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
968 char *btext, int bid, ...) {
d4dcbf56 969 RECT r;
970 int y;
971 va_list ap;
972 int lwid, rwid, rpos;
973 const int LISTHEIGHT = 66;
974
975 /* The static control. */
976 r.left = GAPBETWEEN; r.top = cp->ypos;
977 r.right = cp->width; r.bottom = STATICHEIGHT;
978 cp->ypos += r.bottom + GAPWITHIN;
979 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
980
981 rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3;
982 lwid = rpos - 2*GAPBETWEEN;
983 rwid = cp->width + GAPBETWEEN - rpos;
984
985 /* The list box. */
986 r.left = GAPBETWEEN; r.top = cp->ypos;
987 r.right = lwid; r.bottom = LISTHEIGHT;
988 doctl(cp, r, "LISTBOX",
989 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
990 LBS_USETABSTOPS,
991 WS_EX_CLIENTEDGE,
992 "", listid);
993
994 /* The statics. */
995 y = cp->ypos;
996 va_start(ap, bid);
997 while (1) {
998 char *ltext;
999 int lid, rid;
1000 ltext = va_arg(ap, char *);
1001 if (!ltext) break;
1002 lid = va_arg(ap, int);
1003 rid = va_arg(ap, int);
1004 r.top = y; r.bottom = STATICHEIGHT;
1005 y += r.bottom + GAPWITHIN;
1006 r.left = rpos; r.right = rwid/2;
1007 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid);
1008 r.left = rpos + r.right; r.right = rwid - r.right;
1009 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "", rid);
1010 }
1011 va_end(ap);
1012
1013 /* The button. */
1014 r.top = y + 2*GAPWITHIN; r.bottom = PUSHBTNHEIGHT;
1015 r.left = rpos; r.right = rwid;
1016 doctl(cp, r, "BUTTON",
1017 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
1018 0, btext, bid);
1019
1020 cp->ypos += LISTHEIGHT + GAPBETWEEN;
1021}
1022
374330e2 1023static int GeneralPanelProc (HWND hwnd, UINT msg,
1024 WPARAM wParam, LPARAM lParam) {
1025 switch (msg) {
d4dcbf56 1026 case WM_SETFONT:
1027 {
1028 HFONT hfont = (HFONT)wParam;
1029 HFONT oldfont;
1030 HDC hdc;
1031 TEXTMETRIC tm;
1032 LONG units;
1033
1034 hdc = GetDC(hwnd);
1035 oldfont = SelectObject(hdc, hfont);
1036 GetTextMetrics(hdc, &tm);
1037 units = (tm.tmHeight << 16) | tm.tmAveCharWidth;
1038 SelectObject(hdc, oldfont);
1039 DeleteDC(hdc);
1040 SetWindowLong(hwnd, GWL_USERDATA, units);
1041 SetWindowLong(hwnd, DWL_USER, wParam);
1042 }
1043 return 0;
374330e2 1044 case WM_INITDIALOG:
1045 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1046 return 1;
374330e2 1047 case WM_CLOSE:
1048 DestroyWindow (hwnd);
1049 return 1;
1050 }
1051 return 0;
1052}
1053
6584031a 1054static char savedsession[2048];
1055
374330e2 1056static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
1057 WPARAM wParam, LPARAM lParam) {
1058 int i;
d4dcbf56 1059 struct ctlpos cp;
22b26f24 1060 enum { controlstartvalue = 1000,
1061 IDC_HOSTSTATIC,
1062 IDC_HOST,
1063 IDC_PORTSTATIC,
1064 IDC_PORT,
1065 IDC_PROTSTATIC,
1066 IDC_PROTRAW,
1067 IDC_PROTTELNET,
1068 IDC_PROTSSH,
1069 IDC_SESSSTATIC,
1070 IDC_SESSEDIT,
1071 IDC_SESSLIST,
1072 IDC_SESSLOAD,
1073 IDC_SESSSAVE,
1074 IDC_SESSDEL,
1075 IDC_CLOSEEXIT,
1076 IDC_CLOSEWARN
1077 };
374330e2 1078
1079 switch (msg) {
1080 case WM_INITDIALOG:
d4dcbf56 1081 /* Accelerators used: [aco] dehlnprstwx */
1082 ctlposinit(&cp, hwnd);
1083 multiedit(&cp,
22b26f24 1084 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1085 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
1086 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1087 "&Raw", IDC_PROTRAW,
1088 "&Telnet", IDC_PROTTELNET,
d4dcbf56 1089#ifdef FWHACK
1090 "SS&H/hack",
1091#else
1092 "SS&H",
1093#endif
22b26f24 1094 IDC_PROTSSH, NULL);
d4dcbf56 1095 sesssaver(&cp, "Stor&ed Sessions",
22b26f24 1096 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1097 "&Load", IDC_SESSLOAD,
1098 "&Save", IDC_SESSSAVE,
1099 "&Delete", IDC_SESSDEL, NULL);
1100 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1101 checkbox(&cp, "&Warn on Close", IDC_CLOSEWARN);
1102
1103 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1104 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
1105 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
374330e2 1106 for (i = 0; i < nsessions; i++)
22b26f24 1107 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
374330e2 1108 0, (LPARAM) (sessions[i]));
22b26f24 1109 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1110 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1111 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1112 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1113 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
374330e2 1114 break;
1cd246bb 1115 case WM_LBUTTONUP:
1116 /*
1117 * Button release should trigger WM_OK if there was a
1118 * previous double click on the session list.
1119 */
1120 ReleaseCapture();
1121 if (readytogo)
1122 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
1123 break;
374330e2 1124 case WM_COMMAND:
1125 switch (LOWORD(wParam)) {
22b26f24 1126 case IDC_PROTTELNET:
1127 case IDC_PROTSSH:
1128 case IDC_PROTRAW:
374330e2 1129 if (HIWORD(wParam) == BN_CLICKED ||
1130 HIWORD(wParam) == BN_DOUBLECLICKED) {
22b26f24 1131 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1132 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
5e1a8e27 1133 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
374330e2 1134 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1135 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1136 cfg.port = i ? 22 : 23;
22b26f24 1137 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
374330e2 1138 }
1139 }
1140 break;
22b26f24 1141 case IDC_HOST:
374330e2 1142 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1143 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
374330e2 1144 sizeof(cfg.host)-1);
1145 break;
22b26f24 1146 case IDC_PORT:
374330e2 1147 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1148 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
374330e2 1149 break;
22b26f24 1150 case IDC_CLOSEEXIT:
374330e2 1151 if (HIWORD(wParam) == BN_CLICKED ||
1152 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1153 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
374330e2 1154 break;
22b26f24 1155 case IDC_CLOSEWARN:
9ef49106 1156 if (HIWORD(wParam) == BN_CLICKED ||
1157 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1158 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
9ef49106 1159 break;
22b26f24 1160 case IDC_SESSEDIT:
6584031a 1161 if (HIWORD(wParam) == EN_CHANGE) {
22b26f24 1162 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1163 (WPARAM) -1, 0);
22b26f24 1164 GetDlgItemText (hwnd, IDC_SESSEDIT,
6584031a 1165 savedsession, sizeof(savedsession)-1);
1166 savedsession[sizeof(savedsession)-1] = '\0';
1167 }
374330e2 1168 break;
22b26f24 1169 case IDC_SESSSAVE:
374330e2 1170 if (HIWORD(wParam) == BN_CLICKED ||
1171 HIWORD(wParam) == BN_DOUBLECLICKED) {
1172 /*
1173 * Save a session
1174 */
1175 char str[2048];
22b26f24 1176 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
374330e2 1177 if (!*str) {
22b26f24 1178 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1179 LB_GETCURSEL, 0, 0);
1180 if (n == LB_ERR) {
1181 MessageBeep(0);
1182 break;
1183 }
1184 strcpy (str, sessions[n]);
1185 }
1186 save_settings (str, !!strcmp(str, "Default Settings"));
1187 get_sesslist (FALSE);
1188 get_sesslist (TRUE);
22b26f24 1189 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
374330e2 1190 0, 0);
1191 for (i = 0; i < nsessions; i++)
22b26f24 1192 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
374330e2 1193 0, (LPARAM) (sessions[i]));
22b26f24 1194 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1195 (WPARAM) -1, 0);
1196 }
1197 break;
22b26f24 1198 case IDC_SESSLIST:
1199 case IDC_SESSLOAD:
1200 if (LOWORD(wParam) == IDC_SESSLOAD &&
374330e2 1201 HIWORD(wParam) != BN_CLICKED &&
1202 HIWORD(wParam) != BN_DOUBLECLICKED)
1203 break;
22b26f24 1204 if (LOWORD(wParam) == IDC_SESSLIST &&
374330e2 1205 HIWORD(wParam) != LBN_DBLCLK)
1206 break;
1207 {
22b26f24 1208 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1209 LB_GETCURSEL, 0, 0);
1210 if (n == LB_ERR) {
1211 MessageBeep(0);
1212 break;
1213 }
1214 load_settings (sessions[n],
1215 !!strcmp(sessions[n], "Default Settings"));
22b26f24 1216 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1217 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1218 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1219 (cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1220 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW));
1221 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1222 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1223 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1224 (WPARAM) -1, 0);
1225 }
22b26f24 1226 if (LOWORD(wParam) == IDC_SESSLIST) {
374330e2 1227 /*
1228 * A double-click on a saved session should
1229 * actually start the session, not just load it.
1230 * Unless it's Default Settings or some other
1231 * host-less set of saved settings.
1232 */
1cd246bb 1233 if (*cfg.host) {
1234 readytogo = TRUE;
1235 SetCapture(hwnd);
1236 }
374330e2 1237 }
1238 break;
22b26f24 1239 case IDC_SESSDEL:
374330e2 1240 if (HIWORD(wParam) == BN_CLICKED ||
1241 HIWORD(wParam) == BN_DOUBLECLICKED) {
22b26f24 1242 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1243 LB_GETCURSEL, 0, 0);
1244 if (n == LB_ERR || n == 0) {
1245 MessageBeep(0);
1246 break;
1247 }
d1622aed 1248 del_settings(sessions[n]);
374330e2 1249 get_sesslist (FALSE);
1250 get_sesslist (TRUE);
22b26f24 1251 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
374330e2 1252 0, 0);
1253 for (i = 0; i < nsessions; i++)
22b26f24 1254 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
374330e2 1255 0, (LPARAM) (sessions[i]));
22b26f24 1256 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1257 (WPARAM) -1, 0);
1258 }
1259 }
1260 }
1261 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1262}
1263
1264static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
d4dcbf56 1265 WPARAM wParam, LPARAM lParam) {
1266 struct ctlpos cp;
22b26f24 1267 enum { controlstartvalue = 1000,
1268 IDC_DELSTATIC,
1269 IDC_DEL008,
1270 IDC_DEL127,
1271 IDC_HOMESTATIC,
1272 IDC_HOMETILDE,
1273 IDC_HOMERXVT,
1274 IDC_FUNCSTATIC,
1275 IDC_FUNCTILDE,
1276 IDC_FUNCLINUX,
1277 IDC_FUNCXTERM,
1278 IDC_KPSTATIC,
1279 IDC_KPNORMAL,
1280 IDC_KPAPPLIC,
1281 IDC_KPNH,
1282 IDC_CURSTATIC,
1283 IDC_CURNORMAL,
1284 IDC_CURAPPLIC,
1285 IDC_ALTF4,
1286 IDC_ALTSPACE,
1287 IDC_LDISCTERM,
1288 IDC_SCROLLKEY
1289 };
1290
374330e2 1291 switch (msg) {
1292 case WM_INITDIALOG:
d4dcbf56 1293 /* Accelerators used: [aco] 4?ehiklmnprsuvxy */
1294 ctlposinit(&cp, hwnd);
22b26f24 1295 radioline(&cp, "Action of Backspace:", IDC_DELSTATIC, 2,
1296 "Control-&H", IDC_DEL008,
1297 "Control-&? (127)", IDC_DEL127, NULL);
1298 radioline(&cp, "Action of Home and End:", IDC_HOMESTATIC, 2,
1299 "&Standard", IDC_HOMETILDE,
1300 "&rxvt", IDC_HOMERXVT, NULL);
1301 radioline(&cp, "Function key and keypad layout:", IDC_FUNCSTATIC, 3,
1302 "&VT400", IDC_FUNCTILDE,
1303 "&Linux", IDC_FUNCLINUX,
1304 "&Xterm R6", IDC_FUNCXTERM, NULL);
1305 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1306 "&Normal", IDC_CURNORMAL,
1307 "A&pplication", IDC_CURAPPLIC, NULL);
1308 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1309 "Nor&mal", IDC_KPNORMAL,
1310 "Appl&ication", IDC_KPAPPLIC,
1311 "N&etHack", IDC_KPNH, NULL);
1312 checkbox(&cp, "ALT-F&4 is special (closes window)", IDC_ALTF4);
1313 checkbox(&cp, "ALT-Space is special (S&ystem menu)", IDC_ALTSPACE);
1314 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1315 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1316
1317 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1318 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1319 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1320 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1321 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCXTERM,
c9def1b8 1322 cfg.funky_type ?
22b26f24 1323 (cfg.funky_type==2 ? IDC_FUNCXTERM
1324 : IDC_FUNCLINUX )
1325 : IDC_FUNCTILDE);
1326 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1327 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1328 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1329 cfg.nethack_keypad ? IDC_KPNH :
1330 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1331 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1332 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1333 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1334 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
374330e2 1335 break;
1336 case WM_COMMAND:
1337 if (HIWORD(wParam) == BN_CLICKED ||
1338 HIWORD(wParam) == BN_DOUBLECLICKED)
1339 switch (LOWORD(wParam)) {
22b26f24 1340 case IDC_DEL008:
1341 case IDC_DEL127:
1342 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
374330e2 1343 break;
22b26f24 1344 case IDC_HOMETILDE:
1345 case IDC_HOMERXVT:
1346 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
374330e2 1347 break;
22b26f24 1348 case IDC_FUNCXTERM:
c9def1b8 1349 cfg.funky_type = 2;
1350 break;
22b26f24 1351 case IDC_FUNCTILDE:
1352 case IDC_FUNCLINUX:
1353 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
374330e2 1354 break;
22b26f24 1355 case IDC_KPNORMAL:
1356 case IDC_KPAPPLIC:
1357 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
c5e9c988 1358 cfg.nethack_keypad = FALSE;
1359 break;
22b26f24 1360 case IDC_KPNH:
c5e9c988 1361 cfg.app_keypad = FALSE;
1362 cfg.nethack_keypad = TRUE;
374330e2 1363 break;
22b26f24 1364 case IDC_CURNORMAL:
1365 case IDC_CURAPPLIC:
1366 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
374330e2 1367 break;
22b26f24 1368 case IDC_ALTF4:
c5e9c988 1369 if (HIWORD(wParam) == BN_CLICKED ||
1370 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1371 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
c5e9c988 1372 break;
22b26f24 1373 case IDC_ALTSPACE:
c5e9c988 1374 if (HIWORD(wParam) == BN_CLICKED ||
1375 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1376 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
c5e9c988 1377 break;
22b26f24 1378 case IDC_LDISCTERM:
5bc238bb 1379 if (HIWORD(wParam) == BN_CLICKED ||
1380 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1381 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
5bc238bb 1382 break;
22b26f24 1383 case IDC_SCROLLKEY:
217dceef 1384 if (HIWORD(wParam) == BN_CLICKED ||
1385 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1386 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
217dceef 1387 break;
374330e2 1388 }
1389 }
1390 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1391}
1392
1393static void fmtfont (char *buf) {
1394 sprintf (buf, "Font: %s, ", cfg.font);
1395 if (cfg.fontisbold)
1396 strcat(buf, "bold, ");
1397 if (cfg.fontheight == 0)
1398 strcat (buf, "default height");
1399 else
1400 sprintf (buf+strlen(buf), "%d-%s",
1401 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
1402 (cfg.fontheight < 0 ? "pixel" : "point"));
1403}
1404
1405static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
1406 WPARAM wParam, LPARAM lParam) {
d4dcbf56 1407 struct ctlpos cp;
374330e2 1408 CHOOSEFONT cf;
1409 LOGFONT lf;
1410 char fontstatic[256];
22b26f24 1411 enum { controlstartvalue = 1000,
1412 IDC_WRAPMODE,
1413 IDC_DECOM,
1414 IDC_DIMSTATIC,
1415 IDC_ROWSSTATIC,
1416 IDC_ROWSEDIT,
1417 IDC_COLSSTATIC,
1418 IDC_COLSEDIT,
1419 IDC_SAVESTATIC,
1420 IDC_SAVEEDIT,
1421 IDC_FONTSTATIC,
1422 IDC_CHOOSEFONT,
1423 IDC_LFHASCR,
1424 IDC_BEEP,
1425 IDC_BCE,
1426 IDC_BLINKTEXT
1427 };
374330e2 1428
1429 switch (msg) {
1430 case WM_INITDIALOG:
d4dcbf56 1431 /* Accelerators used: [aco] dghlmnprsw */
1432 ctlposinit(&cp, hwnd);
1433 multiedit(&cp,
22b26f24 1434 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 33,
1435 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 33,
1436 "&Scrollback", IDC_SAVESTATIC, IDC_SAVEEDIT, 33,
d4dcbf56 1437 NULL);
22b26f24 1438 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1439 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1440 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1441 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1442 checkbox(&cp, "Bee&p enabled", IDC_BEEP);
1443 checkbox(&cp, "Use Back&ground colour erase", IDC_BCE);
1444 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1445
1446 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1447 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1448 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1449 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1450 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1451 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
374330e2 1452 fmtfont (fontstatic);
22b26f24 1453 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1454 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1455 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1456 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
374330e2 1457 break;
1458 case WM_COMMAND:
1459 switch (LOWORD(wParam)) {
22b26f24 1460 case IDC_WRAPMODE:
374330e2 1461 if (HIWORD(wParam) == BN_CLICKED ||
1462 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1463 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
374330e2 1464 break;
22b26f24 1465 case IDC_DECOM:
374330e2 1466 if (HIWORD(wParam) == BN_CLICKED ||
1467 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1468 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
374330e2 1469 break;
22b26f24 1470 case IDC_LFHASCR:
fef97f43 1471 if (HIWORD(wParam) == BN_CLICKED ||
1472 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1473 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
fef97f43 1474 break;
22b26f24 1475 case IDC_ROWSEDIT:
374330e2 1476 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1477 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
374330e2 1478 break;
22b26f24 1479 case IDC_COLSEDIT:
374330e2 1480 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1481 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
374330e2 1482 break;
22b26f24 1483 case IDC_SAVEEDIT:
374330e2 1484 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1485 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
374330e2 1486 break;
22b26f24 1487 case IDC_CHOOSEFONT:
374330e2 1488 lf.lfHeight = cfg.fontheight;
1489 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1490 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1491 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
14963b8f 1492 lf.lfCharSet = cfg.fontcharset;
374330e2 1493 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1494 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1495 lf.lfQuality = DEFAULT_QUALITY;
1496 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1497 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1498 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1499
1500 cf.lStructSize = sizeof(cf);
1501 cf.hwndOwner = hwnd;
1502 cf.lpLogFont = &lf;
1503 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1504 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1505
1506 if (ChooseFont (&cf)) {
1507 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1508 cfg.font[sizeof(cfg.font)-1] = '\0';
1509 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
14963b8f 1510 cfg.fontcharset = lf.lfCharSet;
374330e2 1511 cfg.fontheight = lf.lfHeight;
1512 fmtfont (fontstatic);
22b26f24 1513 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
374330e2 1514 }
1515 break;
22b26f24 1516 case IDC_BEEP:
c9def1b8 1517 if (HIWORD(wParam) == BN_CLICKED ||
1518 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1519 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
c9def1b8 1520 break;
22b26f24 1521 case IDC_BLINKTEXT:
c9def1b8 1522 if (HIWORD(wParam) == BN_CLICKED ||
1523 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1524 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
c9def1b8 1525 break;
22b26f24 1526 case IDC_BCE:
c9def1b8 1527 if (HIWORD(wParam) == BN_CLICKED ||
1528 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1529 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
c9def1b8 1530 break;
374330e2 1531 }
1532 break;
1533 }
1534 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1535}
1536
9ca5da42 1537static int CALLBACK WindowProc (HWND hwnd, UINT msg,
1538 WPARAM wParam, LPARAM lParam) {
d4dcbf56 1539 struct ctlpos cp;
22b26f24 1540 enum { controlstartvalue = 1000,
1541 IDC_WINNAME,
1542 IDC_BLINKCUR,
1543 IDC_SCROLLBAR,
1544 IDC_LOCKSIZE,
1545 IDC_WINTITLE,
1546 IDC_WINEDIT
1547 };
1548
9ca5da42 1549 switch (msg) {
1550 case WM_INITDIALOG:
d4dcbf56 1551 /* Accelerators used: [aco] bikty */
1552 ctlposinit(&cp, hwnd);
1553 multiedit(&cp,
22b26f24 1554 "Initial window &title:", IDC_WINTITLE, IDC_WINEDIT, 100,
d4dcbf56 1555 NULL);
22b26f24 1556 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1557 checkbox(&cp, "&Blinking cursor", IDC_BLINKCUR);
1558 checkbox(&cp, "Displa&y scrollbar", IDC_SCROLLBAR);
1559 checkbox(&cp, "Loc&k Window size", IDC_LOCKSIZE);
1560
1561 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1562 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1563 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1564 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1565 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
9ca5da42 1566 break;
1567 case WM_COMMAND:
1568 switch (LOWORD(wParam)) {
22b26f24 1569 case IDC_WINNAME:
9ca5da42 1570 if (HIWORD(wParam) == BN_CLICKED ||
1571 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1572 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
9ca5da42 1573 break;
22b26f24 1574 case IDC_BLINKCUR:
9ca5da42 1575 if (HIWORD(wParam) == BN_CLICKED ||
1576 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1577 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
9ca5da42 1578 break;
22b26f24 1579 case IDC_SCROLLBAR:
9ca5da42 1580 if (HIWORD(wParam) == BN_CLICKED ||
1581 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1582 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
9ca5da42 1583 break;
22b26f24 1584 case IDC_LOCKSIZE:
9ca5da42 1585 if (HIWORD(wParam) == BN_CLICKED ||
1586 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1587 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
9ca5da42 1588 break;
22b26f24 1589 case IDC_WINEDIT:
9ca5da42 1590 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1591 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
9ca5da42 1592 sizeof(cfg.wintitle)-1);
1593 break;
1594 }
1595 break;
1596 }
1597 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1598}
1599
374330e2 1600static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
1601 WPARAM wParam, LPARAM lParam) {
1602 int i;
d4dcbf56 1603 struct ctlpos cp;
22b26f24 1604 enum { controlstartvalue = 1000,
1605 IDC_TTSTATIC,
1606 IDC_TTEDIT,
1607 IDC_TSSTATIC,
1608 IDC_TSEDIT,
1609 IDC_LOGSTATIC,
1610 IDC_LOGEDIT,
1611 IDC_ENVSTATIC,
1612 IDC_VARSTATIC,
1613 IDC_VAREDIT,
1614 IDC_VALSTATIC,
1615 IDC_VALEDIT,
1616 IDC_ENVLIST,
1617 IDC_ENVADD,
1618 IDC_ENVREMOVE,
1619 IDC_EMSTATIC,
1620 IDC_EMBSD,
1621 IDC_EMRFC
1622 };
374330e2 1623
1624 switch (msg) {
1625 case WM_INITDIALOG:
d4dcbf56 1626 /* Accelerators used: [aco] bdflrstuv */
1627 ctlposinit(&cp, hwnd);
22b26f24 1628 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT);
1629 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT);
1630 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT);
1631 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1632 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1633 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1634 IDC_ENVLIST,
1635 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1636 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1637 "&BSD (commonplace)", IDC_EMBSD,
1638 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1639
1640 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1641 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1642 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
374330e2 1643 {
37508af4 1644 char *p = cfg.environmt;
374330e2 1645 while (*p) {
22b26f24 1646 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
374330e2 1647 (LPARAM) p);
1648 p += strlen(p)+1;
1649 }
1650 }
22b26f24 1651 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1652 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
374330e2 1653 break;
1654 case WM_COMMAND:
1655 switch (LOWORD(wParam)) {
22b26f24 1656 case IDC_TTEDIT:
374330e2 1657 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1658 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
374330e2 1659 sizeof(cfg.termtype)-1);
1660 break;
22b26f24 1661 case IDC_TSEDIT:
374330e2 1662 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1663 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
374330e2 1664 sizeof(cfg.termspeed)-1);
1665 break;
22b26f24 1666 case IDC_LOGEDIT:
374330e2 1667 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1668 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
374330e2 1669 sizeof(cfg.username)-1);
1670 break;
22b26f24 1671 case IDC_EMBSD:
1672 case IDC_EMRFC:
1673 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
374330e2 1674 break;
22b26f24 1675 case IDC_ENVADD:
374330e2 1676 if (HIWORD(wParam) == BN_CLICKED ||
1677 HIWORD(wParam) == BN_DOUBLECLICKED) {
37508af4 1678 char str[sizeof(cfg.environmt)];
374330e2 1679 char *p;
22b26f24 1680 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
374330e2 1681 if (!*str) {
1682 MessageBeep(0);
1683 break;
1684 }
1685 p = str + strlen(str);
1686 *p++ = '\t';
22b26f24 1687 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
374330e2 1688 if (!*p) {
1689 MessageBeep(0);
1690 break;
1691 }
37508af4 1692 p = cfg.environmt;
374330e2 1693 while (*p) {
1694 while (*p) p++;
1695 p++;
1696 }
37508af4 1697 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
374330e2 1698 strcpy (p, str);
1699 p[strlen(str)+1] = '\0';
22b26f24 1700 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
374330e2 1701 0, (LPARAM)str);
22b26f24 1702 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1703 SetDlgItemText (hwnd, IDC_VALEDIT, "");
374330e2 1704 } else {
1705 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1706 MB_OK | MB_ICONERROR);
1707 }
1708 }
1709 break;
22b26f24 1710 case IDC_ENVREMOVE:
374330e2 1711 if (HIWORD(wParam) != BN_CLICKED &&
1712 HIWORD(wParam) != BN_DOUBLECLICKED)
1713 break;
22b26f24 1714 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
374330e2 1715 if (i == LB_ERR)
1716 MessageBeep (0);
1717 else {
1718 char *p, *q;
1719
22b26f24 1720 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
374330e2 1721 i, 0);
37508af4 1722 p = cfg.environmt;
374330e2 1723 while (i > 0) {
1724 if (!*p)
1725 goto disaster;
1726 while (*p) p++;
1727 p++;
1728 i--;
1729 }
1730 q = p;
1731 if (!*p)
1732 goto disaster;
1733 while (*p) p++;
1734 p++;
1735 while (*p) {
1736 while (*p)
1737 *q++ = *p++;
1738 *q++ = *p++;
1739 }
1740 *q = '\0';
1741 disaster:;
1742 }
1743 break;
1744 }
1745 break;
1746 }
1747 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1748}
1749
1750static int CALLBACK SshProc (HWND hwnd, UINT msg,
1751 WPARAM wParam, LPARAM lParam) {
d4dcbf56 1752 struct ctlpos cp;
7cca0d81 1753 OPENFILENAME of;
1754 char filename[sizeof(cfg.keyfile)];
22b26f24 1755 enum { controlstartvalue = 1000,
1756 IDC_TTSTATIC,
1757 IDC_TTEDIT,
1758 IDC_LOGSTATIC,
1759 IDC_LOGEDIT,
1760 IDC_NOPTY,
1761 IDC_CIPHERSTATIC,
1762 IDC_CIPHER3DES,
1763 IDC_CIPHERBLOWF,
1764 IDC_CIPHERDES,
1765 IDC_AUTHTIS,
1766 IDC_PKSTATIC,
1767 IDC_PKEDIT,
1768 IDC_PKBUTTON,
1769 IDC_SSHPROTSTATIC,
1770 IDC_SSHPROT1,
1771 IDC_SSHPROT2,
1772 IDC_AGENTFWD,
1773 IDC_CMDSTATIC,
1774 IDC_CMDEDIT
1775 };
7cca0d81 1776
374330e2 1777 switch (msg) {
1778 case WM_INITDIALOG:
d4dcbf56 1779 /* Accelerators used: [aco] 123abdkmprtuw */
1780 ctlposinit(&cp, hwnd);
22b26f24 1781 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT);
1782 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT);
d4dcbf56 1783 multiedit(&cp,
22b26f24 1784 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
d4dcbf56 1785 NULL);
22b26f24 1786 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
d4dcbf56 1787 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
22b26f24 1788 IDC_AUTHTIS);
1789 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
d4dcbf56 1790 editbutton(&cp, "Private &key file for authentication:",
22b26f24 1791 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
d4dcbf56 1792 radioline(&cp, "Preferred SSH protocol version:",
22b26f24 1793 IDC_SSHPROTSTATIC, 2,
1794 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1795 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1796 "&3DES", IDC_CIPHER3DES,
1797 "&Blowfish", IDC_CIPHERBLOWF,
1798 "&DES", IDC_CIPHERDES, NULL);
1799
1800 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1801 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1802 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
1803 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
1804 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
1805 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
1806 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
1807 IDC_CIPHER3DES);
1808 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
1809 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
1810 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
1811 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1812 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
374330e2 1813 break;
1814 case WM_COMMAND:
1815 switch (LOWORD(wParam)) {
22b26f24 1816 case IDC_TTEDIT:
374330e2 1817 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1818 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
374330e2 1819 sizeof(cfg.termtype)-1);
1820 break;
22b26f24 1821 case IDC_LOGEDIT:
374330e2 1822 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1823 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
374330e2 1824 sizeof(cfg.username)-1);
1825 break;
22b26f24 1826 case IDC_NOPTY:
fef97f43 1827 if (HIWORD(wParam) == BN_CLICKED ||
1828 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1829 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
fef97f43 1830 break;
22b26f24 1831 case IDC_AGENTFWD:
979310f1 1832 if (HIWORD(wParam) == BN_CLICKED ||
1833 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1834 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
979310f1 1835 break;
22b26f24 1836 case IDC_CIPHER3DES:
1837 case IDC_CIPHERBLOWF:
1838 case IDC_CIPHERDES:
bea1ef5f 1839 if (HIWORD(wParam) == BN_CLICKED ||
1840 HIWORD(wParam) == BN_DOUBLECLICKED) {
22b26f24 1841 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
bea1ef5f 1842 cfg.cipher = CIPHER_3DES;
22b26f24 1843 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
bea1ef5f 1844 cfg.cipher = CIPHER_BLOWFISH;
22b26f24 1845 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
9697bfd2 1846 cfg.cipher = CIPHER_DES;
bea1ef5f 1847 }
1848 break;
22b26f24 1849 case IDC_SSHPROT1:
1850 case IDC_SSHPROT2:
adf799dd 1851 if (HIWORD(wParam) == BN_CLICKED ||
1852 HIWORD(wParam) == BN_DOUBLECLICKED) {
22b26f24 1853 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
adf799dd 1854 cfg.sshprot = 1;
22b26f24 1855 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
adf799dd 1856 cfg.sshprot = 2;
1857 }
1858 break;
22b26f24 1859 case IDC_AUTHTIS:
ccbfb941 1860 if (HIWORD(wParam) == BN_CLICKED ||
1861 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 1862 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
ccbfb941 1863 break;
22b26f24 1864 case IDC_PKEDIT:
7cca0d81 1865 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1866 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
7cca0d81 1867 sizeof(cfg.keyfile)-1);
1868 break;
22b26f24 1869 case IDC_CMDEDIT:
4c73ca1f 1870 if (HIWORD(wParam) == EN_CHANGE)
22b26f24 1871 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
4c73ca1f 1872 sizeof(cfg.remote_cmd)-1);
1873 break;
22b26f24 1874 case IDC_PKBUTTON:
7cca0d81 1875 /*
1876 * FIXME: this crashes. Find out why.
1877 */
1878 memset(&of, 0, sizeof(of));
1879#ifdef OPENFILENAME_SIZE_VERSION_400
1880 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1881#else
1882 of.lStructSize = sizeof(of);
1883#endif
1884 of.hwndOwner = hwnd;
1885 of.lpstrFilter = "All Files\0*\0\0\0";
1886 of.lpstrCustomFilter = NULL;
1887 of.nFilterIndex = 1;
1888 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1889 of.nMaxFile = sizeof(filename);
1890 of.lpstrFileTitle = NULL;
1891 of.lpstrInitialDir = NULL;
1892 of.lpstrTitle = "Select Public Key File";
1893 of.Flags = 0;
1894 if (GetOpenFileName(&of)) {
1895 strcpy(cfg.keyfile, filename);
22b26f24 1896 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
7cca0d81 1897 }
1898 break;
374330e2 1899 }
1900 break;
1901 }
1902 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1903}
1904
1905static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1906 WPARAM wParam, LPARAM lParam) {
d4dcbf56 1907 struct ctlpos cp;
374330e2 1908 int i;
22b26f24 1909 enum { controlstartvalue = 1000,
1910 IDC_MBSTATIC,
1911 IDC_MBWINDOWS,
1912 IDC_MBXTERM,
1913 IDC_CCSTATIC,
1914 IDC_CCLIST,
1915 IDC_CCSET,
1916 IDC_CCSTATIC2,
1917 IDC_CCEDIT
1918 };
374330e2 1919
1920 switch (msg) {
1921 case WM_INITDIALOG:
d4dcbf56 1922 /* Accelerators used: [aco] stwx */
1923 ctlposinit(&cp, hwnd);
22b26f24 1924 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1925 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1926 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
d4dcbf56 1927 NULL);
22b26f24 1928 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1929 "&Set", IDC_CCSET, IDC_CCEDIT,
1930 "&to class", IDC_CCSTATIC2);
d4dcbf56 1931
22b26f24 1932 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
1933 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
374330e2 1934 {
1935 static int tabs[4] = {25, 61, 96, 128};
22b26f24 1936 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
374330e2 1937 (LPARAM) tabs);
1938 }
1939 for (i=0; i<256; i++) {
1940 char str[100];
1941 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1942 (i>=0x21 && i != 0x7F) ? i : ' ',
1943 cfg.wordness[i]);
22b26f24 1944 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
374330e2 1945 (LPARAM) str);
1946 }
1947 break;
1948 case WM_COMMAND:
1949 switch (LOWORD(wParam)) {
22b26f24 1950 case IDC_MBWINDOWS:
1951 case IDC_MBXTERM:
1952 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
374330e2 1953 break;
22b26f24 1954 case IDC_CCSET:
374330e2 1955 {
1956 BOOL ok;
1957 int i;
22b26f24 1958 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
374330e2 1959
1960 if (!ok)
1961 MessageBeep (0);
1962 else {
1963 for (i=0; i<256; i++)
22b26f24 1964 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
374330e2 1965 i, 0)) {
1966 char str[100];
1967 cfg.wordness[i] = n;
22b26f24 1968 SendDlgItemMessage (hwnd, IDC_CCLIST,
374330e2 1969 LB_DELETESTRING, i, 0);
1970 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1971 (i>=0x21 && i != 0x7F) ? i : ' ',
1972 cfg.wordness[i]);
22b26f24 1973 SendDlgItemMessage (hwnd, IDC_CCLIST,
374330e2 1974 LB_INSERTSTRING, i,
1975 (LPARAM)str);
1976 }
1977 }
1978 }
1979 break;
1980 }
1981 break;
1982 }
1983 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1984}
1985
1986static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1987 WPARAM wParam, LPARAM lParam) {
1988 static const char *const colours[] = {
1989 "Default Foreground", "Default Bold Foreground",
1990 "Default Background", "Default Bold Background",
1991 "Cursor Text", "Cursor Colour",
1992 "ANSI Black", "ANSI Black Bold",
1993 "ANSI Red", "ANSI Red Bold",
1994 "ANSI Green", "ANSI Green Bold",
1995 "ANSI Yellow", "ANSI Yellow Bold",
1996 "ANSI Blue", "ANSI Blue Bold",
1997 "ANSI Magenta", "ANSI Magenta Bold",
1998 "ANSI Cyan", "ANSI Cyan Bold",
1999 "ANSI White", "ANSI White Bold"
2000 };
2001 static const int permanent[] = {
2002 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
2003 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
2004 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
2005 };
d4dcbf56 2006 struct ctlpos cp;
22b26f24 2007 enum { controlstartvalue = 1000,
2008 IDC_BOLDCOLOUR,
2009 IDC_PALETTE,
2010 IDC_STATIC,
2011 IDC_LIST,
2012 IDC_RSTATIC,
2013 IDC_GSTATIC,
2014 IDC_BSTATIC,
2015 IDC_RVALUE,
2016 IDC_GVALUE,
2017 IDC_BVALUE,
2018 IDC_CHANGE
2019 };
d4dcbf56 2020
374330e2 2021 switch (msg) {
2022 case WM_INITDIALOG:
d4dcbf56 2023 /* Accelerators used: [aco] bmlu */
2024 ctlposinit(&cp, hwnd);
22b26f24 2025 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
2026 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
d4dcbf56 2027 colouredit(&cp, "Select a colo&ur and click to modify it:",
22b26f24 2028 IDC_STATIC, IDC_LIST,
2029 "&Modify...", IDC_CHANGE,
2030 "Red:", IDC_RSTATIC, IDC_RVALUE,
2031 "Green:", IDC_GSTATIC, IDC_GVALUE,
2032 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
2033
2034 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
2035 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
374330e2 2036 {
2037 int i;
2038 for (i=0; i<22; i++)
2039 if (cfg.bold_colour || permanent[i])
22b26f24 2040 SendDlgItemMessage (hwnd, IDC_LIST, LB_ADDSTRING, 0,
374330e2 2041 (LPARAM) colours[i]);
2042 }
22b26f24 2043 SendDlgItemMessage (hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
2044 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
2045 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
2046 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
374330e2 2047 break;
2048 case WM_COMMAND:
2049 switch (LOWORD(wParam)) {
22b26f24 2050 case IDC_BOLDCOLOUR:
374330e2 2051 if (HIWORD(wParam) == BN_CLICKED ||
2052 HIWORD(wParam) == BN_DOUBLECLICKED) {
2053 int n, i;
22b26f24 2054 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2055 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
374330e2 2056 if (cfg.bold_colour && n!=22) {
2057 for (i=0; i<22; i++)
2058 if (!permanent[i])
22b26f24 2059 SendDlgItemMessage (hwnd, IDC_LIST,
374330e2 2060 LB_INSERTSTRING, i,
2061 (LPARAM) colours[i]);
2062 } else if (!cfg.bold_colour && n!=12) {
2063 for (i=22; i-- ;)
2064 if (!permanent[i])
22b26f24 2065 SendDlgItemMessage (hwnd, IDC_LIST,
374330e2 2066 LB_DELETESTRING, i, 0);
2067 }
2068 }
2069 break;
22b26f24 2070 case IDC_PALETTE:
374330e2 2071 if (HIWORD(wParam) == BN_CLICKED ||
2072 HIWORD(wParam) == BN_DOUBLECLICKED)
22b26f24 2073 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
374330e2 2074 break;
22b26f24 2075 case IDC_LIST:
374330e2 2076 if (HIWORD(wParam) == LBN_DBLCLK ||
2077 HIWORD(wParam) == LBN_SELCHANGE) {
22b26f24 2078 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
374330e2 2079 0, 0);
2080 if (!cfg.bold_colour)
2081 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
22b26f24 2082 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2083 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2084 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
374330e2 2085 }
2086 break;
22b26f24 2087 case IDC_CHANGE:
374330e2 2088 if (HIWORD(wParam) == BN_CLICKED ||
2089 HIWORD(wParam) == BN_DOUBLECLICKED) {
2090 static CHOOSECOLOR cc;
2091 static DWORD custom[16] = {0}; /* zero initialisers */
22b26f24 2092 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
374330e2 2093 0, 0);
2094 if (!cfg.bold_colour)
2095 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2096 cc.lStructSize = sizeof(cc);
2097 cc.hwndOwner = hwnd;
1d470ad2 2098 cc.hInstance = (HWND)hinst;
374330e2 2099 cc.lpCustColors = custom;
2100 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2101 cfg.colours[i][2]);
2102 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2103 if (ChooseColor(&cc)) {
2104 cfg.colours[i][0] =
2105 (unsigned char) (cc.rgbResult & 0xFF);
2106 cfg.colours[i][1] =
2107 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2108 cfg.colours[i][2] =
2109 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
22b26f24 2110 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
374330e2 2111 FALSE);
22b26f24 2112 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
374330e2 2113 FALSE);
22b26f24 2114 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
374330e2 2115 FALSE);
2116 }
2117 }
2118 break;
2119 }
2120 break;
2121 }
2122 return GeneralPanelProc (hwnd, msg, wParam, lParam);
2123}
2124
c9def1b8 2125static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
14963b8f 2126 WPARAM wParam, LPARAM lParam) {
d4dcbf56 2127 struct ctlpos cp;
22b26f24 2128 enum { controlstartvalue = 1000,
2129 IDC_XLATSTATIC,
2130 IDC_NOXLAT,
2131 IDC_KOI8WIN1251,
2132 IDC_88592WIN1250,
2133 IDC_CAPSLOCKCYR,
2134 IDC_VTSTATIC,
2135 IDC_VTXWINDOWS,
2136 IDC_VTOEMANSI,
2137 IDC_VTOEMONLY,
2138 IDC_VTPOORMAN
2139 };
d4dcbf56 2140
14963b8f 2141 switch (msg) {
2142 case WM_INITDIALOG:
d4dcbf56 2143 /* Accelerators used: [aco] beiknpsx */
2144 ctlposinit(&cp, hwnd);
2145 radiobig(&cp,
22b26f24 2146 "Handling of VT100 line drawing characters:", IDC_VTSTATIC,
2147 "Font has &XWindows encoding", IDC_VTXWINDOWS,
2148 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
2149 "Use font in O&EM mode only", IDC_VTOEMONLY,
d4dcbf56 2150 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
22b26f24 2151 IDC_VTPOORMAN, NULL);
d4dcbf56 2152 radiobig(&cp,
22b26f24 2153 "Character set translation:", IDC_XLATSTATIC,
2154 "&None", IDC_NOXLAT,
2155 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
2156 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250, NULL);
2157 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch", IDC_CAPSLOCKCYR);
2158
2159 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592WIN1250,
2160 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
2161 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
2162 IDC_NOXLAT);
2163 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
2164 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
2165 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
2166 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
2167 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
2168 IDC_VTPOORMAN);
14963b8f 2169 case WM_COMMAND:
2170 switch (LOWORD(wParam)) {
22b26f24 2171 case IDC_NOXLAT:
2172 case IDC_KOI8WIN1251:
2173 case IDC_88592WIN1250:
d3d16feb 2174 cfg.xlat_enablekoiwin =
22b26f24 2175 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
d3d16feb 2176 cfg.xlat_88592w1250 =
22b26f24 2177 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
14963b8f 2178 break;
22b26f24 2179 case IDC_CAPSLOCKCYR:
14963b8f 2180 if (HIWORD(wParam) == BN_CLICKED ||
2181 HIWORD(wParam) == BN_DOUBLECLICKED) {
2182 cfg.xlat_capslockcyr =
22b26f24 2183 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
14963b8f 2184 }
2185 break;
22b26f24 2186 case IDC_VTXWINDOWS:
2187 case IDC_VTOEMANSI:
2188 case IDC_VTOEMONLY:
2189 case IDC_VTPOORMAN:
c9def1b8 2190 cfg.vtmode =
22b26f24 2191 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2192 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2193 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
c9def1b8 2194 VT_POORMAN);
2195 break;
14963b8f 2196 }
2197 }
2198 return GeneralPanelProc (hwnd, msg, wParam, lParam);
2199}
2200
374330e2 2201static DLGPROC panelproc[NPANELS] = {
9ca5da42 2202 ConnectionProc, KeyboardProc, TerminalProc, WindowProc,
c9def1b8 2203 TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
374330e2 2204};
14963b8f 2205
374330e2 2206static char *names[NPANELS] = {
9ca5da42 2207 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
c9def1b8 2208 "SSH", "Selection", "Colours", "Translation"
374330e2 2209};
2210
9ca5da42 2211static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
2212static int reconfp[RECONF_NPANELS] = { 1, 2, 3, 6, 7, 8};
374330e2 2213
d4dcbf56 2214static HWND makesubdialog(HWND hwnd, int x, int y, int w, int h, int n) {
2215 RECT r;
2216 HWND ret;
2217 WPARAM font;
2218 r.left = x; r.top = y;
2219 r.right = r.left + w; r.bottom = r.top + h;
2220 MapDialogRect(hwnd, &r);
2221 ret = CreateWindowEx(WS_EX_CONTROLPARENT,
2222 WC_DIALOG, "", /* no title */
2223 WS_CHILD | WS_VISIBLE | DS_SETFONT,
2224 r.left, r.top,
2225 r.right-r.left, r.bottom-r.top,
22b26f24 2226 hwnd, (HMENU)IDC_SUBDLG,
d4dcbf56 2227 hinst, NULL);
2228 SetWindowLong (ret, DWL_DLGPROC, (LONG)panelproc[n]);
2229 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
2230 SendMessage (ret, WM_SETFONT, font, MAKELPARAM(0, 0));
2231 SendMessage (ret, WM_INITDIALOG, 0, 0);
2232 return ret;
2233}
2234
374330e2 2235static int GenericMainDlgProc (HWND hwnd, UINT msg,
2236 WPARAM wParam, LPARAM lParam,
2237 int npanels, int *panelnums, HWND *page) {
d4dcbf56 2238 HWND hw, tabctl;
374330e2 2239
2240 switch (msg) {
2241 case WM_INITDIALOG:
2242 { /* centre the window */
2243 RECT rs, rd;
2244
2245 hw = GetDesktopWindow();
2246 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
2247 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
2248 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
2249 rd.right-rd.left, rd.bottom-rd.top, TRUE);
2250 }
d4dcbf56 2251 {
2252 RECT r;
2253 r.left = 3; r.right = r.left + 174;
2254 r.top = 3; r.bottom = r.top + 193;
2255 MapDialogRect(hwnd, &r);
2256 tabctl = CreateWindowEx(0, WC_TABCONTROL, "",
2257 WS_CHILD | WS_VISIBLE |
2258 WS_TABSTOP | TCS_MULTILINE,
2259 r.left, r.top,
2260 r.right-r.left, r.bottom-r.top,
2261 hwnd, (HMENU)IDC_TAB, hinst, NULL);
2262
2263 if (!tabctl) {
2264 struct ctlpos cp;
2265 ctlposinit2(&cp, hwnd);
2266 ersatztab(&cp, "Category:", IDC_TABSTATIC1, IDC_TABLIST,
2267 IDC_TABSTATIC2);
2268 } else {
2269 WPARAM font = SendMessage(hwnd, WM_GETFONT, 0, 0);
2270 SendMessage(tabctl, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
2271 }
2272 }
374330e2 2273 *page = NULL;
d4dcbf56 2274 if (tabctl) { /* initialise the tab control */
374330e2 2275 TC_ITEMHEADER tab;
2276 int i;
2277
374330e2 2278 for (i=0; i<npanels; i++) {
2279 tab.mask = TCIF_TEXT;
2280 tab.pszText = names[panelnums[i]];
d4dcbf56 2281 TabCtrl_InsertItem (tabctl, i, &tab);
374330e2 2282 }
d4dcbf56 2283 } else {
2284 int i;
2285
2286 for (i=0; i<npanels; i++) {
2287 SendDlgItemMessage(hwnd, IDC_TABLIST, CB_ADDSTRING,
2288 0, (LPARAM)names[panelnums[i]]);
2289 }
2290 SendDlgItemMessage(hwnd, IDC_TABLIST, CB_SETCURSEL, 0, 0);
2291 }
2292 *page = makesubdialog(hwnd, 6, 30, 168, 163, panelnums[0]);
374330e2 2293 SetFocus (*page);
2294 return 0;
2295 case WM_NOTIFY:
2296 if (LOWORD(wParam) == IDC_TAB &&
2297 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
2298 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
2299 if (*page)
2300 DestroyWindow (*page);
d4dcbf56 2301 *page = makesubdialog(hwnd, 6, 30, 168, 163, panelnums[i]);
374330e2 2302 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
2303 return 0;
2304 }
2305 break;
374330e2 2306 case WM_COMMAND:
2307 switch (LOWORD(wParam)) {
d4dcbf56 2308 case IDC_TABLIST:
2309 if (HIWORD(wParam) == CBN_SELCHANGE) {
2310 HWND tablist = GetDlgItem (hwnd, IDC_TABLIST);
2311 int i = SendMessage (tablist, CB_GETCURSEL, 0, 0);
2312 if (*page)
2313 DestroyWindow (*page);
2314 *page = makesubdialog(hwnd, 6, 30, 168, 163, panelnums[i]);
2315 SetFocus(tablist); /* ensure focus stays */
2316 return 0;
2317 }
2318 break;
374330e2 2319 case IDOK:
2320 if (*cfg.host)
2321 EndDialog (hwnd, 1);
2322 else
2323 MessageBeep (0);
2324 return 0;
2325 case IDCANCEL:
2326 EndDialog (hwnd, 0);
2327 return 0;
2328 }
2329 return 0;
2330 case WM_CLOSE:
2331 EndDialog (hwnd, 0);
2332 return 0;
c9def1b8 2333
2334 /* Grrr Explorer will maximize Dialogs! */
2335 case WM_SIZE:
2336 if (wParam == SIZE_MAXIMIZED)
2337 force_normal(hwnd);
2338 return 0;
374330e2 2339 }
2340 return 0;
2341}
2342
2343static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2344 WPARAM wParam, LPARAM lParam) {
374330e2 2345 static HWND page = NULL;
2346
2347 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
374330e2 2348 }
2349 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
2350 EnableWindow(hwnd, 0);
2351 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2352 GetParent(hwnd), AboutProc);
2353 EnableWindow(hwnd, 1);
9a70ac47 2354 SetActiveWindow(hwnd);
374330e2 2355 }
2356 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
2357 MAIN_NPANELS, mainp, &page);
2358}
2359
2360static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2361 WPARAM wParam, LPARAM lParam) {
2362 static HWND page;
2363 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
2364 RECONF_NPANELS, reconfp, &page);
2365}
2366
0a4aa984 2367void get_sesslist(int allocate) {
d1622aed 2368 static char otherbuf[2048];
374330e2 2369 static char *buffer;
d1622aed 2370 int buflen, bufsize, i;
2371 char *p, *ret;
2372 void *handle;
374330e2 2373
2374 if (allocate) {
d1622aed 2375
2376 if ((handle = enum_settings_start()) == NULL)
374330e2 2377 return;
2378
2379 buflen = bufsize = 0;
2380 buffer = NULL;
374330e2 2381 do {
d1622aed 2382 ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
2383 if (ret) {
2384 int len = strlen(otherbuf)+1;
2385 if (bufsize < buflen+len) {
2386 bufsize = buflen + len + 2048;
2387 buffer = srealloc(buffer, bufsize);
2388 }
2389 strcpy(buffer+buflen, otherbuf);
374330e2 2390 buflen += strlen(buffer+buflen)+1;
2391 }
d1622aed 2392 } while (ret);
2393 enum_settings_finish(handle);
374330e2 2394 buffer = srealloc(buffer, buflen+1);
2395 buffer[buflen] = '\0';
2396
2397 p = buffer;
2398 nsessions = 1; /* "Default Settings" counts as one */
2399 while (*p) {
2400 if (strcmp(p, "Default Settings"))
2401 nsessions++;
2402 while (*p) p++;
2403 p++;
2404 }
2405
2406 sessions = smalloc(nsessions * sizeof(char *));
2407 sessions[0] = "Default Settings";
2408 p = buffer;
2409 i = 1;
2410 while (*p) {
2411 if (strcmp(p, "Default Settings"))
2412 sessions[i++] = p;
2413 while (*p) p++;
2414 p++;
2415 }
2416 } else {
2417 sfree (buffer);
2418 sfree (sessions);
2419 }
2420}
2421
2422int do_config (void) {
2423 int ret;
2424
2425 get_sesslist(TRUE);
6584031a 2426 savedsession[0] = '\0';
374330e2 2427 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2428 get_sesslist(FALSE);
2429
2430 return ret;
2431}
2432
2433int do_reconfig (HWND hwnd) {
2434 Config backup_cfg;
2435 int ret;
2436
2437 backup_cfg = cfg; /* structure copy */
2438 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2439 if (!ret)
2440 cfg = backup_cfg; /* structure copy */
c9def1b8 2441 else
2442 force_normal(hwnd);
2443
374330e2 2444 return ret;
2445}
2446
2447void do_defaults (char *session) {
2448 if (session)
2449 load_settings (session, TRUE);
2450 else
2451 load_settings ("Default Settings", FALSE);
2452}
2453
c5e9c988 2454void logevent (char *string) {
2455 if (nevents >= negsize) {
374330e2 2456 negsize += 64;
c5e9c988 2457 events = srealloc (events, negsize * sizeof(*events));
374330e2 2458 }
c5e9c988 2459 events[nevents] = smalloc(1+strlen(string));
2460 strcpy (events[nevents], string);
2461 nevents++;
9ad90448 2462 if (logbox) {
2463 int count;
374330e2 2464 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2465 0, (LPARAM)string);
9ad90448 2466 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
989b10e9 2467 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
9ad90448 2468 }
374330e2 2469}
2470
c5e9c988 2471void showeventlog (HWND hwnd) {
374330e2 2472 if (!logbox) {
2473 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2474 hwnd, LogProc);
2475 ShowWindow (logbox, SW_SHOWNORMAL);
2476 }
2477}
2478
2479void showabout (HWND hwnd) {
2480 if (!abtbox) {
2481 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2482 hwnd, AboutProc);
2483 ShowWindow (abtbox, SW_SHOWNORMAL);
2484 }
2485}
2486
d4857987 2487void verify_ssh_host_key(char *host, int port, char *keytype,
d5859615 2488 char *keystr, char *fingerprint) {
2489 int ret;
374330e2 2490
d5859615 2491 static const char absentmsg[] =
2492 "The server's host key is not cached in the registry. You\n"
2493 "have no guarantee that the server is the computer you\n"
2494 "think it is.\n"
2495 "The server's key fingerprint is:\n"
2496 "%s\n"
2497 "If you trust this host, hit Yes to add the key to\n"
2498 "PuTTY's cache and carry on connecting.\n"
2499 "If you do not trust this host, hit No to abandon the\n"
2500 "connection.\n";
2501
2502 static const char wrongmsg[] =
2503 "WARNING - POTENTIAL SECURITY BREACH!\n"
2504 "\n"
2505 "The server's host key does not match the one PuTTY has\n"
2506 "cached in the registry. This means that either the\n"
2507 "server administrator has changed the host key, or you\n"
2508 "have actually connected to another computer pretending\n"
2509 "to be the server.\n"
2510 "The new key fingerprint is:\n"
2511 "%s\n"
2512 "If you were expecting this change and trust the new key,\n"
2513 "hit Yes to update PuTTY's cache and continue connecting.\n"
2514 "If you want to carry on connecting but without updating\n"
2515 "the cache, hit No.\n"
2516 "If you want to abandon the connection completely, hit\n"
2517 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2518 "choice.\n";
2519
2520 static const char mbtitle[] = "PuTTY Security Alert";
de3df031 2521
d5859615 2522
2523 char message[160+ /* sensible fingerprint max size */
2524 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2525 sizeof(absentmsg) : sizeof(wrongmsg))];
de3df031 2526
2527 /*
d5859615 2528 * Verify the key against the registry.
de3df031 2529 */
d4857987 2530 ret = verify_host_key(host, port, keytype, keystr);
d5859615 2531
2532 if (ret == 0) /* success - key matched OK */
2533 return;
2534 if (ret == 2) { /* key was different */
2535 int mbret;
2536 sprintf(message, wrongmsg, fingerprint);
2537 mbret = MessageBox(NULL, message, mbtitle,
2538 MB_ICONWARNING | MB_YESNOCANCEL);
2539 if (mbret == IDYES)
d4857987 2540 store_host_key(host, port, keytype, keystr);
d5859615 2541 if (mbret == IDCANCEL)
2542 exit(0);
de3df031 2543 }
d5859615 2544 if (ret == 1) { /* key was absent */
2545 int mbret;
2546 sprintf(message, absentmsg, fingerprint);
2547 mbret = MessageBox(NULL, message, mbtitle,
2548 MB_ICONWARNING | MB_YESNO);
2549 if (mbret == IDNO)
2550 exit(0);
d4857987 2551 store_host_key(host, port, keytype, keystr);
de3df031 2552 }
de3df031 2553}