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