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