Abandon the tab control in favour of a tree view
[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,
948 IDC_AUTHTIS,
949 IDC_PKSTATIC,
950 IDC_PKEDIT,
951 IDC_PKBUTTON,
952 IDC_SSHPROTSTATIC,
953 IDC_SSHPROT1,
954 IDC_SSHPROT2,
955 IDC_AGENTFWD,
956 IDC_CMDSTATIC,
957 IDC_CMDEDIT,
c96a8fef 958 sshpanelend,
959
960 selectionpanelstart,
927d4fc5 961 IDC_TITLE_SELECTION,
962 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
963 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
964 IDC_MBSTATIC,
965 IDC_MBWINDOWS,
966 IDC_MBXTERM,
967 IDC_CCSTATIC,
968 IDC_CCLIST,
969 IDC_CCSET,
970 IDC_CCSTATIC2,
971 IDC_CCEDIT,
c96a8fef 972 selectionpanelend,
973
974 colourspanelstart,
927d4fc5 975 IDC_TITLE_COLOURS,
976 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
977 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
978 IDC_BOLDCOLOUR,
979 IDC_PALETTE,
980 IDC_STATIC,
981 IDC_LIST,
982 IDC_RSTATIC,
983 IDC_GSTATIC,
984 IDC_BSTATIC,
985 IDC_RVALUE,
986 IDC_GVALUE,
987 IDC_BVALUE,
988 IDC_CHANGE,
c96a8fef 989 colourspanelend,
990
991 translationpanelstart,
927d4fc5 992 IDC_TITLE_TRANSLATION,
993 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
994 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
995 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
996 IDC_XLATSTATIC,
997 IDC_NOXLAT,
998 IDC_KOI8WIN1251,
999 IDC_88592WIN1250,
1000 IDC_CAPSLOCKCYR,
1001 IDC_VTSTATIC,
1002 IDC_VTXWINDOWS,
1003 IDC_VTOEMANSI,
1004 IDC_VTOEMONLY,
1005 IDC_VTPOORMAN,
c96a8fef 1006 translationpanelend,
1007
1008 controlendvalue
1009};
1010
1011static const char *const colours[] = {
1012 "Default Foreground", "Default Bold Foreground",
1013 "Default Background", "Default Bold Background",
1014 "Cursor Text", "Cursor Colour",
1015 "ANSI Black", "ANSI Black Bold",
1016 "ANSI Red", "ANSI Red Bold",
1017 "ANSI Green", "ANSI Green Bold",
1018 "ANSI Yellow", "ANSI Yellow Bold",
1019 "ANSI Blue", "ANSI Blue Bold",
1020 "ANSI Magenta", "ANSI Magenta Bold",
1021 "ANSI Cyan", "ANSI Cyan Bold",
1022 "ANSI White", "ANSI White Bold"
1023};
1024static const int permcolour[] = {
1025 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1026 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1027 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1028};
1029
1030static void fmtfont (char *buf) {
1031 sprintf (buf, "Font: %s, ", cfg.font);
1032 if (cfg.fontisbold)
1033 strcat(buf, "bold, ");
1034 if (cfg.fontheight == 0)
1035 strcat (buf, "default height");
1036 else
1037 sprintf (buf+strlen(buf), "%d-%s",
1038 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
1039 (cfg.fontheight < 0 ? "pixel" : "point"));
1040}
1041
1042static void init_dlg_ctrls(HWND hwnd) {
1043 int i;
1044 char fontstatic[256];
1045
927d4fc5 1046 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1047 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
1048 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
c96a8fef 1049 for (i = 0; i < nsessions; i++)
927d4fc5 1050 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
c96a8fef 1051 0, (LPARAM) (sessions[i]));
927d4fc5 1052 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1053 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1054 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1055 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
1056
1057 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1058 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1059 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1060 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1061 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCXTERM,
1062 cfg.funky_type == 0 ? IDC_FUNCTILDE :
1063 cfg.funky_type == 1 ? IDC_FUNCLINUX :
1064 cfg.funky_type == 2 ? IDC_FUNCXTERM :
1065 cfg.funky_type == 3 ? IDC_FUNCVT400 :
1066 IDC_FUNCTILDE );
1067 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1068 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1069 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1070 cfg.nethack_keypad ? IDC_KPNH :
1071 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1072 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1073 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1074 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1075 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
1076
1077 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1078 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1079 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1080 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1081 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1082 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
c96a8fef 1083 fmtfont (fontstatic);
927d4fc5 1084 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1085 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1086 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1087 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
1088
1089 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1090 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1091 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1092 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1093 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
1094 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1095 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1096
1097 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1098 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1099 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
c96a8fef 1100 {
1101 char *p = cfg.environmt;
1102 while (*p) {
927d4fc5 1103 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
c96a8fef 1104 (LPARAM) p);
1105 p += strlen(p)+1;
1106 }
374330e2 1107 }
927d4fc5 1108 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1109 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
1110
1111 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1112 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1113 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
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
1155 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592WIN1250,
1156 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
1157 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
1158 IDC_NOXLAT);
1159 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1160 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
1161 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
1162 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
1163 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
1164 IDC_VTPOORMAN);
374330e2 1165}
1166
c96a8fef 1167static void hide(HWND hwnd, int hide, int minid, int maxid) {
1168 int i;
1169 for (i = minid; i < maxid; i++) {
1170 HWND ctl = GetDlgItem(hwnd, i);
1171 if (ctl) {
1172 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1173 }
1174 }
1175}
6584031a 1176
927d4fc5 1177struct treeview_faff {
1178 HWND treeview;
1179 HTREEITEM lastat[4];
1180};
1181
1182static HTREEITEM treeview_insert(struct treeview_faff *faff,
1183 int level, char *text) {
1184 TVINSERTSTRUCT ins;
1185 int i;
1186 HTREEITEM newitem;
1187 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
1188 ins.hInsertAfter = faff->lastat[level];
1189 ins.DUMMYUNIONNAME.item.mask = TVIF_TEXT;
1190 ins.DUMMYUNIONNAME.item.pszText = text;
1191 newitem = TreeView_InsertItem(faff->treeview, &ins);
1192 if (level > 0)
1193 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
1194 faff->lastat[level] = newitem;
1195 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
1196 return newitem;
1197}
1198
c96a8fef 1199/*
1200 * This _huge_ function is the configuration box.
1201 */
1202static int GenericMainDlgProc (HWND hwnd, UINT msg,
1203 WPARAM wParam, LPARAM lParam,
1204 int dlgtype) {
927d4fc5 1205 HWND hw, treeview;
1206 struct treeview_faff tvfaff;
1207 HTREEITEM hsession;
c96a8fef 1208 OPENFILENAME of;
1209 char filename[sizeof(cfg.keyfile)];
1210 CHOOSEFONT cf;
1211 LOGFONT lf;
1212 char fontstatic[256];
374330e2 1213 int i;
1214
1215 switch (msg) {
1216 case WM_INITDIALOG:
c96a8fef 1217 SetWindowLong(hwnd, GWL_USERDATA, 0);
1218 /*
1219 * Centre the window.
1220 */
1221 { /* centre the window */
1222 RECT rs, rd;
1223
1224 hw = GetDesktopWindow();
1225 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1226 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1227 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1228 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1229 }
1230
1231 /*
927d4fc5 1232 * Create the tree view.
c96a8fef 1233 */
1234 {
1235 RECT r;
1236 WPARAM font;
927d4fc5 1237 HWND tvstatic;
c96a8fef 1238
927d4fc5 1239 r.left = 3; r.right = r.left + 75;
1240 r.top = 3; r.bottom = r.top + 10;
c96a8fef 1241 MapDialogRect(hwnd, &r);
927d4fc5 1242 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1243 WS_CHILD | WS_VISIBLE,
1244 r.left, r.top,
1245 r.right-r.left, r.bottom-r.top,
1246 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
c96a8fef 1247 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
927d4fc5 1248 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1249
1250 r.left = 3; r.right = r.left + 75;
1251 r.top = 13; r.bottom = r.top + 196;
1252 MapDialogRect(hwnd, &r);
1253 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1254 WS_CHILD | WS_VISIBLE |
1255 WS_TABSTOP | TVS_HASLINES |
1256 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1257 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1258 r.left, r.top,
1259 r.right-r.left, r.bottom-r.top,
1260 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1261 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1262 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1263 tvfaff.treeview = treeview;
1264 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
c96a8fef 1265 }
1266
1267 /*
1268 * Create the various panelfuls of controls.
1269 */
1270
927d4fc5 1271 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
c96a8fef 1272 {
1273 struct ctlpos cp;
927d4fc5 1274 ctlposinit(&cp, hwnd, 80, 3, 13);
1275 bartitle(&cp, "Basic options for your PuTTY session",
1276 IDC_TITLE_SESSION);
c96a8fef 1277 if (dlgtype == 0) {
927d4fc5 1278 beginbox(&cp, "Specify your connection by host name",
1279 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
c96a8fef 1280 multiedit(&cp,
927d4fc5 1281 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1282 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
c96a8fef 1283 if (backends[2].backend == NULL) {
1284 /* this is PuTTYtel, so only two protocols available */
927d4fc5 1285 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1286 "&Raw", IDC_PROTRAW,
1287 "&Telnet", IDC_PROTTELNET, NULL);
c96a8fef 1288 } else {
927d4fc5 1289 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1290 "&Raw", IDC_PROTRAW,
1291 "&Telnet", IDC_PROTTELNET,
d4dcbf56 1292#ifdef FWHACK
c96a8fef 1293 "SS&H/hack",
d4dcbf56 1294#else
c96a8fef 1295 "SS&H",
d4dcbf56 1296#endif
927d4fc5 1297 IDC_PROTSSH, NULL);
c96a8fef 1298 }
927d4fc5 1299 endbox(&cp);
1300 beginbox(&cp, "Load, save or delete a stored session",
1301 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
c96a8fef 1302 sesssaver(&cp, "Stor&ed Sessions",
927d4fc5 1303 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1304 "&Load", IDC_SESSLOAD,
1305 "&Save", IDC_SESSSAVE,
1306 "&Delete", IDC_SESSDEL, NULL);
1307 endbox(&cp);
c96a8fef 1308 }
927d4fc5 1309 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
1310 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1311 endbox(&cp);
c96a8fef 1312
927d4fc5 1313 hsession = treeview_insert(&tvfaff, 0, "Session");
c96a8fef 1314 }
1315
927d4fc5 1316 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
c96a8fef 1317 {
1318 struct ctlpos cp;
927d4fc5 1319 ctlposinit(&cp, hwnd, 80, 3, 13);
1320 bartitle(&cp, "Options controlling the terminal emulation",
1321 IDC_TITLE_TERMINAL);
1322 beginbox(&cp, "Set the size of the terminal window",
1323 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
1324 multiedit(&cp,
1325 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1326 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
1327 NULL);
1328 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
1329 endbox(&cp);
1330 beginbox(&cp, "Set the font used in the terminal window",
1331 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
1332 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1333 endbox(&cp);
1334 beginbox(&cp, "Set various terminal options",
1335 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3);
1336 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1337 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1338 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1339 checkbox(&cp, "&Beep enabled", IDC_BEEP);
1340 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
1341 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1342 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1343 endbox(&cp);
1344
1345 treeview_insert(&tvfaff, 0, "Terminal");
c96a8fef 1346 }
1347
927d4fc5 1348 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
c96a8fef 1349 {
1350 struct ctlpos cp;
927d4fc5 1351 ctlposinit(&cp, hwnd, 80, 3, 13);
1352 bartitle(&cp, "Options controlling the effects of keys",
1353 IDC_TITLE_KEYBOARD);
1354 beginbox(&cp, "Change the sequences sent by:",
1355 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
1356 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
1357 "Control-&H", IDC_DEL008,
1358 "Control-&? (127)", IDC_DEL127, NULL);
1359 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
1360 "&Standard", IDC_HOMETILDE,
1361 "&rxvt", IDC_HOMERXVT, NULL);
1362 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
1363 "&VT400", IDC_FUNCTILDE,
1364 "&Linux", IDC_FUNCLINUX,
1365 "&Xterm R6", IDC_FUNCXTERM,
1366 "&VT400", IDC_FUNCVT400, NULL);
1367 endbox(&cp);
1368 beginbox(&cp, "Change the initial state of:",
1369 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
1370 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1371 "&Normal", IDC_CURNORMAL,
1372 "A&pplication", IDC_CURAPPLIC, NULL);
1373 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1374 "Nor&mal", IDC_KPNORMAL,
1375 "Appl&ication", IDC_KPAPPLIC,
1376 "N&etHack", IDC_KPNH, NULL);
1377 endbox(&cp);
1378
1379 treeview_insert(&tvfaff, 1, "Keyboard");
c96a8fef 1380 }
1381
927d4fc5 1382 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
c96a8fef 1383 {
1384 struct ctlpos cp;
927d4fc5 1385 ctlposinit(&cp, hwnd, 80, 3, 13);
1386 bartitle(&cp, "Options controlling PuTTY's window",
1387 IDC_TITLE_WINDOW);
1388 beginbox(&cp, "Adjust the use of the window title",
1389 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
c96a8fef 1390 if (dlgtype == 0)
1391 multiedit(&cp,
927d4fc5 1392 "Initial window &title:", IDC_WINTITLE,
1393 IDC_WINEDIT, 100, NULL);
1394 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1395 endbox(&cp);
1396 beginbox(&cp, "Adjust the use of the cursor",
1397 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
1398 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1399 endbox(&cp);
1400 beginbox(&cp, "Control the scrollback in the window",
1401 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3);
1402 staticedit(&cp, "Lines of &scrollback",
1403 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1404 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1405 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1406 endbox(&cp);
1407 beginbox(&cp, NULL, IDC_BOX_WINDOW4, 0);
1408 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1409 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1410 checkbox(&cp, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE);
1411 endbox(&cp);
1412
1413 treeview_insert(&tvfaff, 0, "Window");
c96a8fef 1414 }
1415
927d4fc5 1416 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
c96a8fef 1417 {
1418 struct ctlpos cp;
927d4fc5 1419 ctlposinit(&cp, hwnd, 80, 3, 13);
1420 bartitle(&cp, "Options controlling character set translation",
1421 IDC_TITLE_TRANSLATION);
1422 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1423 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
1424 radiobig(&cp,
1425 "Handling of line drawing characters:", IDC_VTSTATIC,
1426 "Font has &XWindows encoding", IDC_VTXWINDOWS,
1427 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1428 "Use font in O&EM mode only", IDC_VTOEMONLY,
1429 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1430 IDC_VTPOORMAN, NULL);
1431 endbox(&cp);
1432 beginbox(&cp, "Enable character set translation on received data",
1433 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
1434 radiobig(&cp,
1435 "Character set translation:", IDC_XLATSTATIC,
1436 "&None", IDC_NOXLAT,
1437 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
1438 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250, NULL);
1439 endbox(&cp);
1440 beginbox(&cp, "Enable character set translation on input data",
1441 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
1442 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
1443 IDC_CAPSLOCKCYR);
1444 endbox(&cp);
1445
1446 treeview_insert(&tvfaff, 1, "Translation");
c96a8fef 1447 }
1448
927d4fc5 1449 /* The Selection panel. Accelerators used: [acgo] wxst */
c96a8fef 1450 {
1451 struct ctlpos cp;
927d4fc5 1452 ctlposinit(&cp, hwnd, 80, 3, 13);
1453 bartitle(&cp, "Options controlling copy and paste",
1454 IDC_TITLE_SELECTION);
1455 beginbox(&cp, "Control which mouse button does which thing",
1456 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
1457 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1458 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1459 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1460 NULL);
1461 endbox(&cp);
1462 beginbox(&cp, "Control the select-one-word-at-a-time mode",
1463 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
1464 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1465 "&Set", IDC_CCSET, IDC_CCEDIT,
1466 "&to class", IDC_CCSTATIC2);
1467 endbox(&cp);
1468
1469 treeview_insert(&tvfaff, 1, "Selection");
c96a8fef 1470 }
1471
927d4fc5 1472 /* The Colours panel. Accelerators used: [acgo] blum */
c96a8fef 1473 {
1474 struct ctlpos cp;
927d4fc5 1475 ctlposinit(&cp, hwnd, 80, 3, 13);
1476 bartitle(&cp, "Options controlling use of colours",
1477 IDC_TITLE_COLOURS);
1478 beginbox(&cp, "General options for colour usage",
1479 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
1480 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
1481 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1482 endbox(&cp);
1483 beginbox(&cp, "Adjust the precise colours PuTTY displays",
1484 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
1485 colouredit(&cp, "Select a colo&ur and then click to modify it:",
1486 IDC_STATIC, IDC_LIST,
1487 "&Modify...", IDC_CHANGE,
1488 "Red:", IDC_RSTATIC, IDC_RVALUE,
1489 "Green:", IDC_GSTATIC, IDC_GVALUE,
1490 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1491 endbox(&cp);
1492
1493 treeview_insert(&tvfaff, 1, "Colours");
c96a8fef 1494 }
1495
927d4fc5 1496 /* The Connection panel. Accelerators used: [acgo] tuk */
1497 {
1498 struct ctlpos cp;
1499 ctlposinit(&cp, hwnd, 80, 3, 13);
1500 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
1501 if (dlgtype == 0) {
1502 beginbox(&cp, "Data to send to the server",
1503 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
1504 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
1505 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
1506 endbox(&cp);
1507 }
1508 beginbox(&cp, "Sending of null packets to keep session active",
1509 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
1510 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
1511 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
1512 endbox(&cp);
1513
1514 treeview_insert(&tvfaff, 0, "Connection");
1515 }
1516
1517 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
c96a8fef 1518 {
1519 struct ctlpos cp;
927d4fc5 1520 ctlposinit(&cp, hwnd, 80, 3, 13);
1521 if (dlgtype == 0) {
1522 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
1523 beginbox(&cp, "Data to send to the server",
1524 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
1525 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
1526 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1527 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1528 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1529 IDC_ENVLIST,
1530 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1531 endbox(&cp);
1532 beginbox(&cp, "Telnet protocol adjustments",
1533 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
1534 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1535 "&BSD (commonplace)", IDC_EMBSD,
1536 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1537 endbox(&cp);
1538
1539 treeview_insert(&tvfaff, 1, "Telnet");
1540 }
c96a8fef 1541 }
1542
927d4fc5 1543 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
c96a8fef 1544 {
1545 struct ctlpos cp;
927d4fc5 1546 ctlposinit(&cp, hwnd, 80, 3, 13);
1547 if (dlgtype == 0) {
1548 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1549 beginbox(&cp, "Data to send to the server",
1550 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1551 multiedit(&cp,
1552 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1553 NULL);
1554 endbox(&cp);
1555 beginbox(&cp, "Authentication options",
1556 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1557 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1558 IDC_AUTHTIS);
1559 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1560 editbutton(&cp, "Private &key file for authentication:",
1561 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1562 endbox(&cp);
1563 beginbox(&cp, "Protocol options",
1564 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1565 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1566 radioline(&cp, "Preferred SSH protocol version:",
1567 IDC_SSHPROTSTATIC, 2,
1568 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1569 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1570 "&3DES", IDC_CIPHER3DES,
1571 "&Blowfish", IDC_CIPHERBLOWF,
1572 "&DES", IDC_CIPHERDES, NULL);
1573 endbox(&cp);
1574
1575 treeview_insert(&tvfaff, 1, "SSH");
1576 }
c96a8fef 1577 }
1578
1579 init_dlg_ctrls(hwnd);
1580
927d4fc5 1581 /*
1582 * Hide all the controls to start with.
1583 */
c96a8fef 1584 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
927d4fc5 1585
1586 /*
1587 * Put the treeview selection on to the Session panel. This
1588 * should also cause unhiding of the relevant controls.
1589 */
1590 TreeView_SelectItem(treeview, hsession);
c96a8fef 1591
1592 /*
1593 * Set focus into the first available control.
1594 */
1595 {
1596 HWND ctl;
927d4fc5 1597 ctl = GetDlgItem(hwnd, IDC_HOST);
1598 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
c96a8fef 1599 SetFocus(ctl);
9d01fc92 1600 }
c96a8fef 1601
1602 SetWindowLong(hwnd, GWL_USERDATA, 1);
1603 return 0;
1cd246bb 1604 case WM_LBUTTONUP:
1605 /*
1606 * Button release should trigger WM_OK if there was a
1607 * previous double click on the session list.
1608 */
1609 ReleaseCapture();
1610 if (readytogo)
c96a8fef 1611 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1cd246bb 1612 break;
c96a8fef 1613 case WM_NOTIFY:
927d4fc5 1614 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1615 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1616 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1617 TVITEM item;
c96a8fef 1618 char buffer[64];
927d4fc5 1619 item.hItem = i;
c96a8fef 1620 item.pszText = buffer;
1621 item.cchTextMax = sizeof(buffer);
927d4fc5 1622 item.mask = TVIF_TEXT;
1623 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
c96a8fef 1624 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
927d4fc5 1625 if (!strcmp(buffer, "Session"))
1626 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
c96a8fef 1627 if (!strcmp(buffer, "Keyboard"))
1628 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1629 if (!strcmp(buffer, "Terminal"))
1630 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1631 if (!strcmp(buffer, "Window"))
1632 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
927d4fc5 1633 if (!strcmp(buffer, "Connection"))
1634 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
c96a8fef 1635 if (!strcmp(buffer, "Telnet"))
1636 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1637 if (!strcmp(buffer, "SSH"))
1638 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1639 if (!strcmp(buffer, "Selection"))
1640 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1641 if (!strcmp(buffer, "Colours"))
1642 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1643 if (!strcmp(buffer, "Translation"))
1644 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1645
1646 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1647 return 0;
1648 }
1649 break;
374330e2 1650 case WM_COMMAND:
c96a8fef 1651 /*
1652 * Only process WM_COMMAND once the dialog is fully formed.
1653 */
1654 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1655 case IDOK:
1656 if (*cfg.host)
1657 EndDialog (hwnd, 1);
1658 else
1659 MessageBeep (0);
1660 return 0;
1661 case IDCANCEL:
1662 EndDialog (hwnd, 0);
1663 return 0;
927d4fc5 1664 case IDC_PROTTELNET:
1665 case IDC_PROTSSH:
1666 case IDC_PROTRAW:
374330e2 1667 if (HIWORD(wParam) == BN_CLICKED ||
1668 HIWORD(wParam) == BN_DOUBLECLICKED) {
927d4fc5 1669 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1670 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
5e1a8e27 1671 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
374330e2 1672 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1673 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1674 cfg.port = i ? 22 : 23;
927d4fc5 1675 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
374330e2 1676 }
1677 }
1678 break;
927d4fc5 1679 case IDC_HOST:
374330e2 1680 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1681 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
374330e2 1682 sizeof(cfg.host)-1);
1683 break;
927d4fc5 1684 case IDC_PORT:
374330e2 1685 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1686 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
374330e2 1687 break;
927d4fc5 1688 case IDC_SESSEDIT:
6584031a 1689 if (HIWORD(wParam) == EN_CHANGE) {
927d4fc5 1690 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1691 (WPARAM) -1, 0);
927d4fc5 1692 GetDlgItemText (hwnd, IDC_SESSEDIT,
6584031a 1693 savedsession, sizeof(savedsession)-1);
1694 savedsession[sizeof(savedsession)-1] = '\0';
1695 }
374330e2 1696 break;
927d4fc5 1697 case IDC_SESSSAVE:
374330e2 1698 if (HIWORD(wParam) == BN_CLICKED ||
1699 HIWORD(wParam) == BN_DOUBLECLICKED) {
1700 /*
1701 * Save a session
1702 */
1703 char str[2048];
927d4fc5 1704 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
374330e2 1705 if (!*str) {
927d4fc5 1706 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1707 LB_GETCURSEL, 0, 0);
1708 if (n == LB_ERR) {
1709 MessageBeep(0);
1710 break;
1711 }
1712 strcpy (str, sessions[n]);
1713 }
a9422f39 1714 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
374330e2 1715 get_sesslist (FALSE);
1716 get_sesslist (TRUE);
927d4fc5 1717 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
374330e2 1718 0, 0);
1719 for (i = 0; i < nsessions; i++)
927d4fc5 1720 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
374330e2 1721 0, (LPARAM) (sessions[i]));
927d4fc5 1722 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1723 (WPARAM) -1, 0);
1724 }
1725 break;
927d4fc5 1726 case IDC_SESSLIST:
1727 case IDC_SESSLOAD:
1728 if (LOWORD(wParam) == IDC_SESSLOAD &&
374330e2 1729 HIWORD(wParam) != BN_CLICKED &&
1730 HIWORD(wParam) != BN_DOUBLECLICKED)
1731 break;
927d4fc5 1732 if (LOWORD(wParam) == IDC_SESSLIST &&
374330e2 1733 HIWORD(wParam) != LBN_DBLCLK)
1734 break;
1735 {
927d4fc5 1736 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1737 LB_GETCURSEL, 0, 0);
1738 if (n == LB_ERR) {
1739 MessageBeep(0);
1740 break;
1741 }
1742 load_settings (sessions[n],
a9422f39 1743 !!strcmp(sessions[n], "Default Settings"),
1744 &cfg);
c96a8fef 1745 init_dlg_ctrls(hwnd);
374330e2 1746 }
927d4fc5 1747 if (LOWORD(wParam) == IDC_SESSLIST) {
374330e2 1748 /*
1749 * A double-click on a saved session should
1750 * actually start the session, not just load it.
1751 * Unless it's Default Settings or some other
1752 * host-less set of saved settings.
1753 */
1cd246bb 1754 if (*cfg.host) {
1755 readytogo = TRUE;
1756 SetCapture(hwnd);
1757 }
374330e2 1758 }
1759 break;
927d4fc5 1760 case IDC_SESSDEL:
374330e2 1761 if (HIWORD(wParam) == BN_CLICKED ||
1762 HIWORD(wParam) == BN_DOUBLECLICKED) {
927d4fc5 1763 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
374330e2 1764 LB_GETCURSEL, 0, 0);
1765 if (n == LB_ERR || n == 0) {
1766 MessageBeep(0);
1767 break;
1768 }
d1622aed 1769 del_settings(sessions[n]);
374330e2 1770 get_sesslist (FALSE);
1771 get_sesslist (TRUE);
927d4fc5 1772 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
374330e2 1773 0, 0);
1774 for (i = 0; i < nsessions; i++)
927d4fc5 1775 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
374330e2 1776 0, (LPARAM) (sessions[i]));
927d4fc5 1777 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
374330e2 1778 (WPARAM) -1, 0);
1779 }
927d4fc5 1780 case IDC_PINGEDIT:
ec55b220 1781 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1782 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
ec55b220 1783 break;
927d4fc5 1784 case IDC_DEL008:
1785 case IDC_DEL127:
c96a8fef 1786 if (HIWORD(wParam) == BN_CLICKED ||
1787 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1788 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
c96a8fef 1789 break;
927d4fc5 1790 case IDC_HOMETILDE:
1791 case IDC_HOMERXVT:
c96a8fef 1792 if (HIWORD(wParam) == BN_CLICKED ||
1793 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1794 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
c96a8fef 1795 break;
927d4fc5 1796 case IDC_FUNCXTERM:
c96a8fef 1797 if (HIWORD(wParam) == BN_CLICKED ||
1798 HIWORD(wParam) == BN_DOUBLECLICKED)
c9def1b8 1799 cfg.funky_type = 2;
c96a8fef 1800 break;
927d4fc5 1801 case IDC_FUNCVT400:
ec55b220 1802 if (HIWORD(wParam) == BN_CLICKED ||
1803 HIWORD(wParam) == BN_DOUBLECLICKED)
1804 cfg.funky_type = 3;
1805 break;
927d4fc5 1806 case IDC_FUNCTILDE:
1807 case IDC_FUNCLINUX:
c96a8fef 1808 if (HIWORD(wParam) == BN_CLICKED ||
1809 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1810 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
c96a8fef 1811 break;
927d4fc5 1812 case IDC_KPNORMAL:
1813 case IDC_KPAPPLIC:
c96a8fef 1814 if (HIWORD(wParam) == BN_CLICKED ||
1815 HIWORD(wParam) == BN_DOUBLECLICKED) {
927d4fc5 1816 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
c5e9c988 1817 cfg.nethack_keypad = FALSE;
c96a8fef 1818 }
1819 break;
927d4fc5 1820 case IDC_KPNH:
c96a8fef 1821 if (HIWORD(wParam) == BN_CLICKED ||
1822 HIWORD(wParam) == BN_DOUBLECLICKED) {
c5e9c988 1823 cfg.app_keypad = FALSE;
1824 cfg.nethack_keypad = TRUE;
374330e2 1825 }
c96a8fef 1826 break;
927d4fc5 1827 case IDC_CURNORMAL:
1828 case IDC_CURAPPLIC:
c96a8fef 1829 if (HIWORD(wParam) == BN_CLICKED ||
1830 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1831 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
c96a8fef 1832 break;
927d4fc5 1833 case IDC_ALTF4:
c96a8fef 1834 if (HIWORD(wParam) == BN_CLICKED ||
1835 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1836 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
c96a8fef 1837 break;
927d4fc5 1838 case IDC_ALTSPACE:
c96a8fef 1839 if (HIWORD(wParam) == BN_CLICKED ||
1840 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1841 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
c96a8fef 1842 break;
927d4fc5 1843 case IDC_LDISCTERM:
c96a8fef 1844 if (HIWORD(wParam) == BN_CLICKED ||
1845 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1846 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
c96a8fef 1847 break;
927d4fc5 1848 case IDC_SCROLLKEY:
c96a8fef 1849 if (HIWORD(wParam) == BN_CLICKED ||
1850 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1851 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
c96a8fef 1852 break;
927d4fc5 1853 case IDC_WRAPMODE:
374330e2 1854 if (HIWORD(wParam) == BN_CLICKED ||
1855 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1856 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
374330e2 1857 break;
927d4fc5 1858 case IDC_DECOM:
374330e2 1859 if (HIWORD(wParam) == BN_CLICKED ||
1860 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1861 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
374330e2 1862 break;
927d4fc5 1863 case IDC_LFHASCR:
fef97f43 1864 if (HIWORD(wParam) == BN_CLICKED ||
1865 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1866 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
fef97f43 1867 break;
927d4fc5 1868 case IDC_ROWSEDIT:
374330e2 1869 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1870 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
374330e2 1871 break;
927d4fc5 1872 case IDC_COLSEDIT:
374330e2 1873 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1874 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
374330e2 1875 break;
927d4fc5 1876 case IDC_SAVEEDIT:
374330e2 1877 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1878 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
374330e2 1879 break;
927d4fc5 1880 case IDC_CHOOSEFONT:
374330e2 1881 lf.lfHeight = cfg.fontheight;
1882 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1883 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1884 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
14963b8f 1885 lf.lfCharSet = cfg.fontcharset;
374330e2 1886 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1887 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1888 lf.lfQuality = DEFAULT_QUALITY;
1889 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1890 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1891 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1892
1893 cf.lStructSize = sizeof(cf);
1894 cf.hwndOwner = hwnd;
1895 cf.lpLogFont = &lf;
1896 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1897 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1898
1899 if (ChooseFont (&cf)) {
1900 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1901 cfg.font[sizeof(cfg.font)-1] = '\0';
1902 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
14963b8f 1903 cfg.fontcharset = lf.lfCharSet;
374330e2 1904 cfg.fontheight = lf.lfHeight;
1905 fmtfont (fontstatic);
927d4fc5 1906 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
374330e2 1907 }
1908 break;
927d4fc5 1909 case IDC_BEEP:
c96a8fef 1910 if (HIWORD(wParam) == BN_CLICKED ||
1911 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1912 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
c96a8fef 1913 break;
927d4fc5 1914 case IDC_BLINKTEXT:
9ca5da42 1915 if (HIWORD(wParam) == BN_CLICKED ||
1916 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1917 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
9ca5da42 1918 break;
927d4fc5 1919 case IDC_BCE:
c96a8fef 1920 if (HIWORD(wParam) == BN_CLICKED ||
1921 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1922 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
c96a8fef 1923 break;
927d4fc5 1924 case IDC_WINNAME:
c96a8fef 1925 if (HIWORD(wParam) == BN_CLICKED ||
1926 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1927 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
c96a8fef 1928 break;
927d4fc5 1929 case IDC_BLINKCUR:
9ca5da42 1930 if (HIWORD(wParam) == BN_CLICKED ||
1931 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1932 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
9ca5da42 1933 break;
927d4fc5 1934 case IDC_SCROLLBAR:
9ca5da42 1935 if (HIWORD(wParam) == BN_CLICKED ||
1936 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1937 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
9ca5da42 1938 break;
927d4fc5 1939 case IDC_LOCKSIZE:
9ca5da42 1940 if (HIWORD(wParam) == BN_CLICKED ||
1941 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1942 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
9ca5da42 1943 break;
927d4fc5 1944 case IDC_WINEDIT:
9ca5da42 1945 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1946 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
9ca5da42 1947 sizeof(cfg.wintitle)-1);
1948 break;
927d4fc5 1949 case IDC_CLOSEEXIT:
ec55b220 1950 if (HIWORD(wParam) == BN_CLICKED ||
1951 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1952 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
ec55b220 1953 break;
927d4fc5 1954 case IDC_CLOSEWARN:
ec55b220 1955 if (HIWORD(wParam) == BN_CLICKED ||
1956 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 1957 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
ec55b220 1958 break;
927d4fc5 1959 case IDC_TTEDIT:
374330e2 1960 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1961 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
374330e2 1962 sizeof(cfg.termtype)-1);
1963 break;
927d4fc5 1964 case IDC_TSEDIT:
374330e2 1965 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 1966 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
374330e2 1967 sizeof(cfg.termspeed)-1);
1968 break;
927d4fc5 1969 case IDC_LOGEDIT:
1970 if (HIWORD(wParam) == EN_CHANGE)
1971 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
374330e2 1972 sizeof(cfg.username)-1);
1973 break;
927d4fc5 1974 case IDC_EMBSD:
1975 case IDC_EMRFC:
1976 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
374330e2 1977 break;
927d4fc5 1978 case IDC_ENVADD:
374330e2 1979 if (HIWORD(wParam) == BN_CLICKED ||
1980 HIWORD(wParam) == BN_DOUBLECLICKED) {
37508af4 1981 char str[sizeof(cfg.environmt)];
374330e2 1982 char *p;
927d4fc5 1983 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
374330e2 1984 if (!*str) {
1985 MessageBeep(0);
1986 break;
1987 }
1988 p = str + strlen(str);
1989 *p++ = '\t';
927d4fc5 1990 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
374330e2 1991 if (!*p) {
1992 MessageBeep(0);
1993 break;
1994 }
37508af4 1995 p = cfg.environmt;
374330e2 1996 while (*p) {
1997 while (*p) p++;
1998 p++;
1999 }
37508af4 2000 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
374330e2 2001 strcpy (p, str);
2002 p[strlen(str)+1] = '\0';
927d4fc5 2003 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
374330e2 2004 0, (LPARAM)str);
927d4fc5 2005 SetDlgItemText (hwnd, IDC_VAREDIT, "");
2006 SetDlgItemText (hwnd, IDC_VALEDIT, "");
374330e2 2007 } else {
2008 MessageBox(hwnd, "Environment too big", "PuTTY Error",
2009 MB_OK | MB_ICONERROR);
2010 }
2011 }
2012 break;
927d4fc5 2013 case IDC_ENVREMOVE:
374330e2 2014 if (HIWORD(wParam) != BN_CLICKED &&
2015 HIWORD(wParam) != BN_DOUBLECLICKED)
2016 break;
927d4fc5 2017 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
374330e2 2018 if (i == LB_ERR)
2019 MessageBeep (0);
2020 else {
2021 char *p, *q;
2022
927d4fc5 2023 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
374330e2 2024 i, 0);
37508af4 2025 p = cfg.environmt;
374330e2 2026 while (i > 0) {
2027 if (!*p)
2028 goto disaster;
2029 while (*p) p++;
2030 p++;
2031 i--;
2032 }
2033 q = p;
2034 if (!*p)
2035 goto disaster;
2036 while (*p) p++;
2037 p++;
2038 while (*p) {
2039 while (*p)
2040 *q++ = *p++;
2041 *q++ = *p++;
2042 }
2043 *q = '\0';
2044 disaster:;
2045 }
2046 break;
927d4fc5 2047 case IDC_NOPTY:
fef97f43 2048 if (HIWORD(wParam) == BN_CLICKED ||
2049 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 2050 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
fef97f43 2051 break;
927d4fc5 2052 case IDC_AGENTFWD:
979310f1 2053 if (HIWORD(wParam) == BN_CLICKED ||
2054 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 2055 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
979310f1 2056 break;
927d4fc5 2057 case IDC_CIPHER3DES:
2058 case IDC_CIPHERBLOWF:
2059 case IDC_CIPHERDES:
bea1ef5f 2060 if (HIWORD(wParam) == BN_CLICKED ||
2061 HIWORD(wParam) == BN_DOUBLECLICKED) {
927d4fc5 2062 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
bea1ef5f 2063 cfg.cipher = CIPHER_3DES;
927d4fc5 2064 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
bea1ef5f 2065 cfg.cipher = CIPHER_BLOWFISH;
927d4fc5 2066 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
9697bfd2 2067 cfg.cipher = CIPHER_DES;
bea1ef5f 2068 }
2069 break;
927d4fc5 2070 case IDC_SSHPROT1:
2071 case IDC_SSHPROT2:
adf799dd 2072 if (HIWORD(wParam) == BN_CLICKED ||
2073 HIWORD(wParam) == BN_DOUBLECLICKED) {
927d4fc5 2074 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
adf799dd 2075 cfg.sshprot = 1;
927d4fc5 2076 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
adf799dd 2077 cfg.sshprot = 2;
2078 }
2079 break;
927d4fc5 2080 case IDC_AUTHTIS:
ccbfb941 2081 if (HIWORD(wParam) == BN_CLICKED ||
2082 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 2083 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
ccbfb941 2084 break;
927d4fc5 2085 case IDC_PKEDIT:
7cca0d81 2086 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 2087 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
7cca0d81 2088 sizeof(cfg.keyfile)-1);
2089 break;
927d4fc5 2090 case IDC_CMDEDIT:
4c73ca1f 2091 if (HIWORD(wParam) == EN_CHANGE)
927d4fc5 2092 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
4c73ca1f 2093 sizeof(cfg.remote_cmd)-1);
2094 break;
927d4fc5 2095 case IDC_PKBUTTON:
7cca0d81 2096 memset(&of, 0, sizeof(of));
2097#ifdef OPENFILENAME_SIZE_VERSION_400
2098 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2099#else
2100 of.lStructSize = sizeof(of);
2101#endif
2102 of.hwndOwner = hwnd;
2103 of.lpstrFilter = "All Files\0*\0\0\0";
2104 of.lpstrCustomFilter = NULL;
2105 of.nFilterIndex = 1;
2106 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
2107 of.nMaxFile = sizeof(filename);
2108 of.lpstrFileTitle = NULL;
2109 of.lpstrInitialDir = NULL;
2110 of.lpstrTitle = "Select Public Key File";
2111 of.Flags = 0;
2112 if (GetOpenFileName(&of)) {
2113 strcpy(cfg.keyfile, filename);
927d4fc5 2114 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
7cca0d81 2115 }
2116 break;
927d4fc5 2117 case IDC_MBWINDOWS:
2118 case IDC_MBXTERM:
2119 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
374330e2 2120 break;
927d4fc5 2121 case IDC_CCSET:
374330e2 2122 {
2123 BOOL ok;
2124 int i;
927d4fc5 2125 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
374330e2 2126
2127 if (!ok)
2128 MessageBeep (0);
2129 else {
2130 for (i=0; i<256; i++)
927d4fc5 2131 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
374330e2 2132 i, 0)) {
2133 char str[100];
2134 cfg.wordness[i] = n;
927d4fc5 2135 SendDlgItemMessage (hwnd, IDC_CCLIST,
374330e2 2136 LB_DELETESTRING, i, 0);
2137 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2138 (i>=0x21 && i != 0x7F) ? i : ' ',
2139 cfg.wordness[i]);
927d4fc5 2140 SendDlgItemMessage (hwnd, IDC_CCLIST,
374330e2 2141 LB_INSERTSTRING, i,
2142 (LPARAM)str);
2143 }
2144 }
2145 }
2146 break;
927d4fc5 2147 case IDC_BOLDCOLOUR:
374330e2 2148 if (HIWORD(wParam) == BN_CLICKED ||
2149 HIWORD(wParam) == BN_DOUBLECLICKED) {
2150 int n, i;
927d4fc5 2151 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2152 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
374330e2 2153 if (cfg.bold_colour && n!=22) {
2154 for (i=0; i<22; i++)
c96a8fef 2155 if (!permcolour[i])
927d4fc5 2156 SendDlgItemMessage (hwnd, IDC_LIST,
374330e2 2157 LB_INSERTSTRING, i,
2158 (LPARAM) colours[i]);
2159 } else if (!cfg.bold_colour && n!=12) {
2160 for (i=22; i-- ;)
c96a8fef 2161 if (!permcolour[i])
927d4fc5 2162 SendDlgItemMessage (hwnd, IDC_LIST,
374330e2 2163 LB_DELETESTRING, i, 0);
2164 }
2165 }
2166 break;
927d4fc5 2167 case IDC_PALETTE:
374330e2 2168 if (HIWORD(wParam) == BN_CLICKED ||
2169 HIWORD(wParam) == BN_DOUBLECLICKED)
927d4fc5 2170 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
374330e2 2171 break;
927d4fc5 2172 case IDC_LIST:
374330e2 2173 if (HIWORD(wParam) == LBN_DBLCLK ||
2174 HIWORD(wParam) == LBN_SELCHANGE) {
927d4fc5 2175 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
374330e2 2176 0, 0);
2177 if (!cfg.bold_colour)
2178 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
927d4fc5 2179 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2180 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2181 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
374330e2 2182 }
2183 break;
927d4fc5 2184 case IDC_CHANGE:
374330e2 2185 if (HIWORD(wParam) == BN_CLICKED ||
2186 HIWORD(wParam) == BN_DOUBLECLICKED) {
2187 static CHOOSECOLOR cc;
2188 static DWORD custom[16] = {0}; /* zero initialisers */
927d4fc5 2189 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
374330e2 2190 0, 0);
2191 if (!cfg.bold_colour)
2192 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2193 cc.lStructSize = sizeof(cc);
2194 cc.hwndOwner = hwnd;
1d470ad2 2195 cc.hInstance = (HWND)hinst;
374330e2 2196 cc.lpCustColors = custom;
2197 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2198 cfg.colours[i][2]);
2199 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2200 if (ChooseColor(&cc)) {
2201 cfg.colours[i][0] =
2202 (unsigned char) (cc.rgbResult & 0xFF);
2203 cfg.colours[i][1] =
2204 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2205 cfg.colours[i][2] =
2206 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
927d4fc5 2207 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
374330e2 2208 FALSE);
927d4fc5 2209 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
374330e2 2210 FALSE);
927d4fc5 2211 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
374330e2 2212 FALSE);
2213 }
2214 }
2215 break;
927d4fc5 2216 case IDC_NOXLAT:
2217 case IDC_KOI8WIN1251:
2218 case IDC_88592WIN1250:
d3d16feb 2219 cfg.xlat_enablekoiwin =
927d4fc5 2220 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
d3d16feb 2221 cfg.xlat_88592w1250 =
927d4fc5 2222 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
14963b8f 2223 break;
927d4fc5 2224 case IDC_CAPSLOCKCYR:
14963b8f 2225 if (HIWORD(wParam) == BN_CLICKED ||
2226 HIWORD(wParam) == BN_DOUBLECLICKED) {
2227 cfg.xlat_capslockcyr =
927d4fc5 2228 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
14963b8f 2229 }
2230 break;
927d4fc5 2231 case IDC_VTXWINDOWS:
2232 case IDC_VTOEMANSI:
2233 case IDC_VTOEMONLY:
2234 case IDC_VTPOORMAN:
c9def1b8 2235 cfg.vtmode =
927d4fc5 2236 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2237 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2238 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
c9def1b8 2239 VT_POORMAN);
2240 break;
14963b8f 2241 }
374330e2 2242 return 0;
2243 case WM_CLOSE:
2244 EndDialog (hwnd, 0);
2245 return 0;
c9def1b8 2246
2247 /* Grrr Explorer will maximize Dialogs! */
2248 case WM_SIZE:
2249 if (wParam == SIZE_MAXIMIZED)
2250 force_normal(hwnd);
2251 return 0;
374330e2 2252 }
2253 return 0;
2254}
2255
2256static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2257 WPARAM wParam, LPARAM lParam) {
374330e2 2258 static HWND page = NULL;
2259
2260 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
374330e2 2261 }
c96a8fef 2262 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
374330e2 2263 EnableWindow(hwnd, 0);
2264 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2265 GetParent(hwnd), AboutProc);
2266 EnableWindow(hwnd, 1);
9a70ac47 2267 SetActiveWindow(hwnd);
374330e2 2268 }
c96a8fef 2269 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
374330e2 2270}
2271
2272static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2273 WPARAM wParam, LPARAM lParam) {
2274 static HWND page;
c96a8fef 2275 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
374330e2 2276}
2277
374330e2 2278int do_config (void) {
2279 int ret;
2280
2281 get_sesslist(TRUE);
6584031a 2282 savedsession[0] = '\0';
374330e2 2283 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2284 get_sesslist(FALSE);
2285
2286 return ret;
2287}
2288
2289int do_reconfig (HWND hwnd) {
2290 Config backup_cfg;
2291 int ret;
2292
2293 backup_cfg = cfg; /* structure copy */
2294 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2295 if (!ret)
2296 cfg = backup_cfg; /* structure copy */
c9def1b8 2297 else
2298 force_normal(hwnd);
2299
374330e2 2300 return ret;
2301}
2302
c5e9c988 2303void logevent (char *string) {
2304 if (nevents >= negsize) {
374330e2 2305 negsize += 64;
c5e9c988 2306 events = srealloc (events, negsize * sizeof(*events));
374330e2 2307 }
c5e9c988 2308 events[nevents] = smalloc(1+strlen(string));
2309 strcpy (events[nevents], string);
2310 nevents++;
9ad90448 2311 if (logbox) {
2312 int count;
374330e2 2313 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2314 0, (LPARAM)string);
9ad90448 2315 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
989b10e9 2316 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
9ad90448 2317 }
374330e2 2318}
2319
c5e9c988 2320void showeventlog (HWND hwnd) {
374330e2 2321 if (!logbox) {
2322 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2323 hwnd, LogProc);
2324 ShowWindow (logbox, SW_SHOWNORMAL);
2325 }
2326}
2327
2328void showabout (HWND hwnd) {
2329 if (!abtbox) {
2330 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2331 hwnd, AboutProc);
2332 ShowWindow (abtbox, SW_SHOWNORMAL);
2333 }
2334}
2335
d4857987 2336void verify_ssh_host_key(char *host, int port, char *keytype,
d5859615 2337 char *keystr, char *fingerprint) {
2338 int ret;
374330e2 2339
d5859615 2340 static const char absentmsg[] =
2341 "The server's host key is not cached in the registry. You\n"
2342 "have no guarantee that the server is the computer you\n"
2343 "think it is.\n"
2344 "The server's key fingerprint is:\n"
2345 "%s\n"
2346 "If you trust this host, hit Yes to add the key to\n"
2347 "PuTTY's cache and carry on connecting.\n"
2348 "If you do not trust this host, hit No to abandon the\n"
2349 "connection.\n";
2350
2351 static const char wrongmsg[] =
2352 "WARNING - POTENTIAL SECURITY BREACH!\n"
2353 "\n"
2354 "The server's host key does not match the one PuTTY has\n"
2355 "cached in the registry. This means that either the\n"
2356 "server administrator has changed the host key, or you\n"
2357 "have actually connected to another computer pretending\n"
2358 "to be the server.\n"
2359 "The new key fingerprint is:\n"
2360 "%s\n"
2361 "If you were expecting this change and trust the new key,\n"
2362 "hit Yes to update PuTTY's cache and continue connecting.\n"
2363 "If you want to carry on connecting but without updating\n"
2364 "the cache, hit No.\n"
2365 "If you want to abandon the connection completely, hit\n"
2366 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2367 "choice.\n";
2368
2369 static const char mbtitle[] = "PuTTY Security Alert";
de3df031 2370
d5859615 2371
2372 char message[160+ /* sensible fingerprint max size */
2373 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2374 sizeof(absentmsg) : sizeof(wrongmsg))];
de3df031 2375
2376 /*
d5859615 2377 * Verify the key against the registry.
de3df031 2378 */
d4857987 2379 ret = verify_host_key(host, port, keytype, keystr);
d5859615 2380
2381 if (ret == 0) /* success - key matched OK */
2382 return;
2383 if (ret == 2) { /* key was different */
2384 int mbret;
2385 sprintf(message, wrongmsg, fingerprint);
2386 mbret = MessageBox(NULL, message, mbtitle,
2387 MB_ICONWARNING | MB_YESNOCANCEL);
2388 if (mbret == IDYES)
d4857987 2389 store_host_key(host, port, keytype, keystr);
d5859615 2390 if (mbret == IDCANCEL)
2391 exit(0);
de3df031 2392 }
d5859615 2393 if (ret == 1) { /* key was absent */
2394 int mbret;
2395 sprintf(message, absentmsg, fingerprint);
2396 mbret = MessageBox(NULL, message, mbtitle,
2397 MB_ICONWARNING | MB_YESNO);
2398 if (mbret == IDNO)
2399 exit(0);
d4857987 2400 store_host_key(host, port, keytype, keystr);
de3df031 2401 }
de3df031 2402}