Robert de Bath's big patch:
[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
182#define DLGWIDTH 168
183#define STATICHEIGHT 8
184#define CHECKBOXHEIGHT 8
185#define RADIOHEIGHT 8
186#define EDITHEIGHT 12
187#define COMBOHEIGHT 12
188#define PUSHBTNHEIGHT 14
189
190struct ctlpos {
191 HWND hwnd;
d4dcbf56 192 WPARAM font;
193 int ypos, width;
c96a8fef 194 int xoff, yoff;
d4dcbf56 195};
196
c96a8fef 197static void ctlposinit(struct ctlpos *cp, HWND hwnd,
198 int sideborder, int topborder) {
199 RECT r, r2;
d4dcbf56 200 cp->hwnd = hwnd;
d4dcbf56 201 cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);
202 cp->ypos = GAPBETWEEN;
203 GetClientRect(hwnd, &r);
c96a8fef 204 r2.left = r2.top = 0;
205 r2.right = 4;
206 r2.bottom = 8;
207 MapDialogRect(hwnd, &r2);
208 cp->width = (r.right * 4) / (r2.right) - 2*GAPBETWEEN;
209 cp->xoff = sideborder;
210 cp->width -= 2*sideborder;
211 cp->yoff = topborder;
d4dcbf56 212}
213
75cab814 214static void doctl(struct ctlpos *cp, RECT r,
215 char *wclass, int wstyle, int exstyle,
216 char *wtext, int wid) {
d4dcbf56 217 HWND ctl;
218 /*
219 * Note nonstandard use of RECT. This is deliberate: by
220 * transforming the width and height directly we arrange to
221 * have all supposedly same-sized controls really same-sized.
222 */
223
c96a8fef 224 r.left += cp->xoff;
225 r.top += cp->yoff;
226 MapDialogRect(cp->hwnd, &r);
d4dcbf56 227
228 ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,
229 r.left, r.top, r.right, r.bottom,
230 cp->hwnd, (HMENU)wid, hinst, NULL);
231 SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));
232}
233
234/*
235 * Some edit boxes. Each one has a static above it. The percentages
236 * of the horizontal space are provided.
237 */
75cab814 238static void multiedit(struct ctlpos *cp, ...) {
d4dcbf56 239 RECT r;
240 va_list ap;
241 int percent, xpos;
242
243 percent = xpos = 0;
244 va_start(ap, cp);
245 while (1) {
246 char *text;
247 int staticid, editid, pcwidth;
248 text = va_arg(ap, char *);
249 if (!text)
250 break;
251 staticid = va_arg(ap, int);
252 editid = va_arg(ap, int);
253 pcwidth = va_arg(ap, int);
254
255 r.left = xpos + GAPBETWEEN;
256 percent += pcwidth;
257 xpos = (cp->width + GAPBETWEEN) * percent / 100;
258 r.right = xpos - r.left;
259
260 r.top = cp->ypos; r.bottom = STATICHEIGHT;
261 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
262 text, staticid);
263 r.top = cp->ypos + 8 + GAPWITHIN; r.bottom = EDITHEIGHT;
264 doctl(cp, r, "EDIT",
265 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
266 WS_EX_CLIENTEDGE,
267 "", editid);
268 }
269 va_end(ap);
270 cp->ypos += 8+GAPWITHIN+12+GAPBETWEEN;
271}
272
273/*
274 * A set of radio buttons on the same line, with a static above
275 * them. `nacross' dictates how many parts the line is divided into
276 * (you might want this not to equal the number of buttons if you
277 * needed to line up some 2s and some 3s to look good in the same
278 * panel).
279 */
75cab814 280static void radioline(struct ctlpos *cp,
281 char *text, int id, int nacross, ...) {
d4dcbf56 282 RECT r;
283 va_list ap;
284 int group;
285 int i;
286
287 r.left = GAPBETWEEN; r.top = cp->ypos;
288 r.right = cp->width; r.bottom = STATICHEIGHT;
289 cp->ypos += r.bottom + GAPWITHIN;
290 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
291 va_start(ap, nacross);
292 group = WS_GROUP;
293 i = 0;
294 while (1) {
295 char *btext;
296 int bid;
297 btext = va_arg(ap, char *);
298 if (!btext)
299 break;
300 bid = va_arg(ap, int);
301 r.left = GAPBETWEEN + i * (cp->width+GAPBETWEEN)/nacross;
302 r.right = (i+1) * (cp->width+GAPBETWEEN)/nacross - r.left;
303 r.top = cp->ypos; r.bottom = RADIOHEIGHT;
304 doctl(cp, r, "BUTTON",
305 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
306 0,
307 btext, bid);
308 group = 0;
309 i++;
310 }
311 va_end(ap);
312 cp->ypos += r.bottom + GAPBETWEEN;
313}
314
315/*
316 * A set of radio buttons on multiple lines, with a static above
317 * them.
318 */
75cab814 319static void radiobig(struct ctlpos *cp, char *text, int id, ...) {
d4dcbf56 320 RECT r;
321 va_list ap;
322 int group;
323
324 r.left = GAPBETWEEN; r.top = cp->ypos;
325 r.right = cp->width; r.bottom = STATICHEIGHT;
326 cp->ypos += r.bottom + GAPWITHIN;
327 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
328 va_start(ap, id);
329 group = WS_GROUP;
330 while (1) {
331 char *btext;
332 int bid;
333 btext = va_arg(ap, char *);
334 if (!btext)
335 break;
336 bid = va_arg(ap, int);
337 r.left = GAPBETWEEN; r.top = cp->ypos;
338 r.right = cp->width; r.bottom = STATICHEIGHT;
339 cp->ypos += r.bottom + GAPWITHIN;
340 doctl(cp, r, "BUTTON",
341 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
342 0,
343 btext, bid);
344 group = 0;
345 }
346 va_end(ap);
347 cp->ypos += GAPBETWEEN - GAPWITHIN;
348}
349
350/*
351 * A single standalone checkbox.
352 */
75cab814 353static void checkbox(struct ctlpos *cp, char *text, int id) {
d4dcbf56 354 RECT r;
355
356 r.left = GAPBETWEEN; r.top = cp->ypos;
357 r.right = cp->width; r.bottom = CHECKBOXHEIGHT;
358 cp->ypos += r.bottom + GAPBETWEEN;
359 doctl(cp, r, "BUTTON",
360 BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,
361 text, id);
362}
363
364/*
365 * A button on the right hand side, with a static to its left.
366 */
75cab814 367static void staticbtn(struct ctlpos *cp, char *stext, int sid,
368 char *btext, int bid) {
d4dcbf56 369 const int height = (PUSHBTNHEIGHT > STATICHEIGHT ?
370 PUSHBTNHEIGHT : STATICHEIGHT);
371 RECT r;
372 int lwid, rwid, rpos;
373
374 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
375 lwid = rpos - 2*GAPBETWEEN;
376 rwid = cp->width + GAPBETWEEN - rpos;
377
378 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
379 r.right = lwid; r.bottom = STATICHEIGHT;
380 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
381
382 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
383 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
384 doctl(cp, r, "BUTTON",
385 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
386 0,
387 btext, bid);
388
389 cp->ypos += height + GAPBETWEEN;
390}
391
392/*
393 * An edit control on the right hand side, with a static to its left.
394 */
ec55b220 395static void staticedit(struct ctlpos *cp, char *stext,
396 int sid, int eid, int percentedit) {
d4dcbf56 397 const int height = (EDITHEIGHT > STATICHEIGHT ?
398 EDITHEIGHT : STATICHEIGHT);
399 RECT r;
400 int lwid, rwid, rpos;
401
ec55b220 402 rpos = GAPBETWEEN + (100-percentedit) * (cp->width + GAPBETWEEN) / 100;
d4dcbf56 403 lwid = rpos - 2*GAPBETWEEN;
404 rwid = cp->width + GAPBETWEEN - rpos;
405
406 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
407 r.right = lwid; r.bottom = STATICHEIGHT;
408 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
409
410 r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2;
411 r.right = rwid; r.bottom = EDITHEIGHT;
412 doctl(cp, r, "EDIT",
413 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
414 WS_EX_CLIENTEDGE,
415 "", eid);
416
417 cp->ypos += height + GAPBETWEEN;
418}
419
420/*
421 * A tab-control substitute when a real tab control is unavailable.
422 */
75cab814 423static void ersatztab(struct ctlpos *cp, char *stext, int sid,
424 int lid, int s2id) {
d4dcbf56 425 const int height = (COMBOHEIGHT > STATICHEIGHT ?
426 COMBOHEIGHT : STATICHEIGHT);
427 RECT r;
428 int bigwid, lwid, rwid, rpos;
429 static const int BIGGAP = 15;
430 static const int MEDGAP = 3;
431
432 bigwid = cp->width + 2*GAPBETWEEN - 2*BIGGAP;
433 cp->ypos += MEDGAP;
434 rpos = BIGGAP + (bigwid + BIGGAP) / 2;
435 lwid = rpos - 2*BIGGAP;
436 rwid = bigwid + BIGGAP - rpos;
437
438 r.left = BIGGAP; r.top = cp->ypos + (height-STATICHEIGHT)/2;
439 r.right = lwid; r.bottom = STATICHEIGHT;
440 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
441
442 r.left = rpos; r.top = cp->ypos + (height-COMBOHEIGHT)/2;
443 r.right = rwid; r.bottom = COMBOHEIGHT*10;
444 doctl(cp, r, "COMBOBOX",
445 WS_CHILD | WS_VISIBLE | WS_TABSTOP |
446 CBS_DROPDOWNLIST | CBS_HASSTRINGS,
447 WS_EX_CLIENTEDGE,
448 "", lid);
449
450 cp->ypos += height + MEDGAP + GAPBETWEEN;
451
452 r.left = GAPBETWEEN; r.top = cp->ypos;
453 r.right = cp->width; r.bottom = 2;
454 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
455 0, "", s2id);
456}
457
458/*
459 * A static line, followed by an edit control on the left hand side
460 * and a button on the right.
461 */
75cab814 462static void editbutton(struct ctlpos *cp, char *stext, int sid,
463 int eid, char *btext, int bid) {
d4dcbf56 464 const int height = (EDITHEIGHT > PUSHBTNHEIGHT ?
465 EDITHEIGHT : PUSHBTNHEIGHT);
466 RECT r;
467 int lwid, rwid, rpos;
468
469 r.left = GAPBETWEEN; r.top = cp->ypos;
470 r.right = cp->width; r.bottom = STATICHEIGHT;
471 cp->ypos += r.bottom + GAPWITHIN;
472 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
473
474 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
475 lwid = rpos - 2*GAPBETWEEN;
476 rwid = cp->width + GAPBETWEEN - rpos;
477
478 r.left = GAPBETWEEN; r.top = cp->ypos + (height-EDITHEIGHT)/2;
479 r.right = lwid; r.bottom = EDITHEIGHT;
480 doctl(cp, r, "EDIT",
481 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
482 WS_EX_CLIENTEDGE,
483 "", eid);
484
485 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
486 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
487 doctl(cp, r, "BUTTON",
488 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
489 0,
490 btext, bid);
491
492 cp->ypos += height + GAPBETWEEN;
493}
494
495/*
496 * Special control which was hard to describe generically: the
497 * session-saver assembly. A static; below that an edit box; below
498 * that a list box. To the right of the list box, a column of
499 * buttons.
500 */
75cab814 501static void sesssaver(struct ctlpos *cp, char *text,
502 int staticid, int editid, int listid, ...) {
d4dcbf56 503 RECT r;
504 va_list ap;
505 int lwid, rwid, rpos;
506 int y;
507 const int LISTDEFHEIGHT = 66;
508
509 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
510 lwid = rpos - 2*GAPBETWEEN;
511 rwid = cp->width + GAPBETWEEN - rpos;
512
513 /* The static control. */
514 r.left = GAPBETWEEN; r.top = cp->ypos;
515 r.right = lwid; r.bottom = STATICHEIGHT;
516 cp->ypos += r.bottom + GAPWITHIN;
517 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
518
519 /* The edit control. */
520 r.left = GAPBETWEEN; r.top = cp->ypos;
521 r.right = lwid; r.bottom = EDITHEIGHT;
522 cp->ypos += r.bottom + GAPWITHIN;
523 doctl(cp, r, "EDIT",
524 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
525 WS_EX_CLIENTEDGE,
27be4452 526 "", editid);
d4dcbf56 527
528 /*
529 * The buttons (we should hold off on the list box until we
530 * know how big the buttons are).
531 */
532 va_start(ap, listid);
533 y = cp->ypos;
534 while (1) {
535 char *btext = va_arg(ap, char *);
536 int bid;
537 if (!btext) break;
538 bid = va_arg(ap, int);
539 r.left = rpos; r.top = y;
540 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
541 y += r.bottom + GAPWITHIN;
542 doctl(cp, r, "BUTTON",
543 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
544 0,
545 btext, bid);
546 }
547
548 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
549 y -= cp->ypos;
550 y -= GAPWITHIN;
551 if (y < LISTDEFHEIGHT) y = LISTDEFHEIGHT;
552 r.left = GAPBETWEEN; r.top = cp->ypos;
553 r.right = lwid; r.bottom = y;
554 cp->ypos += y + GAPBETWEEN;
555 doctl(cp, r, "LISTBOX",
d57a8a6d 556 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
a84ca2f5 557 LBS_NOTIFY | LBS_HASSTRINGS,
d4dcbf56 558 WS_EX_CLIENTEDGE,
559 "", listid);
560}
561
562/*
563 * Another special control: the environment-variable setter. A
564 * static line first; then a pair of edit boxes with associated
565 * statics, and two buttons; then a list box.
566 */
75cab814 567static void envsetter(struct ctlpos *cp, char *stext, int sid,
568 char *e1stext, int e1sid, int e1id,
569 char *e2stext, int e2sid, int e2id,
570 int listid,
571 char *b1text, int b1id, char *b2text, int b2id) {
d4dcbf56 572 RECT r;
573 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
574 STATICHEIGHT :
575 EDITHEIGHT > PUSHBTNHEIGHT ?
576 EDITHEIGHT : PUSHBTNHEIGHT);
577 const static int percents[] = { 20, 35, 10, 25 };
578 int i, j, xpos, percent;
579 const int LISTHEIGHT = 42;
580
581 /* The static control. */
582 r.left = GAPBETWEEN; r.top = cp->ypos;
583 r.right = cp->width; r.bottom = STATICHEIGHT;
584 cp->ypos += r.bottom + GAPWITHIN;
585 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
586
587 /* The statics+edits+buttons. */
588 for (j = 0; j < 2; j++) {
589 percent = 10;
590 for (i = 0; i < 4; i++) {
591 xpos = (cp->width + GAPBETWEEN) * percent / 100;
592 r.left = xpos + GAPBETWEEN;
593 percent += percents[i];
594 xpos = (cp->width + GAPBETWEEN) * percent / 100;
595 r.right = xpos - r.left;
596 r.top = cp->ypos;
597 r.bottom = (i==0 ? STATICHEIGHT :
598 i==1 ? EDITHEIGHT :
599 PUSHBTNHEIGHT);
600 r.top += (height-r.bottom)/2;
601 if (i==0) {
602 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
603 j==0 ? e1stext : e2stext, j==0 ? e1sid : e2sid);
604 } else if (i==1) {
605 doctl(cp, r, "EDIT",
606 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
607 WS_EX_CLIENTEDGE,
608 "", j==0 ? e1id : e2id);
609 } else if (i==3) {
610 doctl(cp, r, "BUTTON",
611 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
612 0,
613 j==0 ? b1text : b2text, j==0 ? b1id : b2id);
614 }
615 }
616 cp->ypos += height + GAPWITHIN;
617 }
618
619 /* The list box. */
620 r.left = GAPBETWEEN; r.top = cp->ypos;
621 r.right = cp->width; r.bottom = LISTHEIGHT;
622 cp->ypos += r.bottom + GAPBETWEEN;
623 doctl(cp, r, "LISTBOX",
624 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
625 LBS_USETABSTOPS,
626 WS_EX_CLIENTEDGE,
627 "", listid);
628}
629
630/*
631 * Yet another special control: the character-class setter. A
632 * static, then a list, then a line containing a
633 * button-and-static-and-edit.
634 */
75cab814 635static void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
636 char *btext, int bid, int eid, char *s2text, int s2id) {
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[] = { 30, 40, 30 };
643 int i, xpos, percent;
644 const int LISTHEIGHT = 66;
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 list box. */
653 r.left = GAPBETWEEN; r.top = cp->ypos;
654 r.right = cp->width; r.bottom = LISTHEIGHT;
655 cp->ypos += r.bottom + GAPWITHIN;
656 doctl(cp, r, "LISTBOX",
657 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
658 LBS_USETABSTOPS,
659 WS_EX_CLIENTEDGE,
660 "", listid);
661
662 /* The button+static+edit. */
663 percent = xpos = 0;
664 for (i = 0; i < 3; i++) {
665 r.left = xpos + GAPBETWEEN;
666 percent += percents[i];
667 xpos = (cp->width + GAPBETWEEN) * percent / 100;
668 r.right = xpos - r.left;
669 r.top = cp->ypos;
670 r.bottom = (i==0 ? PUSHBTNHEIGHT :
671 i==1 ? STATICHEIGHT :
672 EDITHEIGHT);
673 r.top += (height-r.bottom)/2;
674 if (i==0) {
675 doctl(cp, r, "BUTTON",
676 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
677 0, btext, bid);
678 } else if (i==1) {
679 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER,
680 0, s2text, s2id);
681 } else if (i==2) {
682 doctl(cp, r, "EDIT",
683 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
684 WS_EX_CLIENTEDGE, "", eid);
685 }
686 }
687 cp->ypos += height + GAPBETWEEN;
688}
689
690/*
691 * A special control (horrors!). The colour editor. A static line;
692 * then on the left, a list box, and on the right, a sequence of
693 * two-part statics followed by a button.
694 */
75cab814 695static void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
696 char *btext, int bid, ...) {
d4dcbf56 697 RECT r;
698 int y;
699 va_list ap;
700 int lwid, rwid, rpos;
701 const int LISTHEIGHT = 66;
702
703 /* The static control. */
704 r.left = GAPBETWEEN; r.top = cp->ypos;
705 r.right = cp->width; r.bottom = STATICHEIGHT;
706 cp->ypos += r.bottom + GAPWITHIN;
707 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
708
709 rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3;
710 lwid = rpos - 2*GAPBETWEEN;
711 rwid = cp->width + GAPBETWEEN - rpos;
712
713 /* The list box. */
714 r.left = GAPBETWEEN; r.top = cp->ypos;
715 r.right = lwid; r.bottom = LISTHEIGHT;
716 doctl(cp, r, "LISTBOX",
717 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
718 LBS_USETABSTOPS,
719 WS_EX_CLIENTEDGE,
720 "", listid);
721
722 /* The statics. */
723 y = cp->ypos;
724 va_start(ap, bid);
725 while (1) {
726 char *ltext;
727 int lid, rid;
728 ltext = va_arg(ap, char *);
729 if (!ltext) break;
730 lid = va_arg(ap, int);
731 rid = va_arg(ap, int);
732 r.top = y; r.bottom = STATICHEIGHT;
733 y += r.bottom + GAPWITHIN;
734 r.left = rpos; r.right = rwid/2;
735 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid);
736 r.left = rpos + r.right; r.right = rwid - r.right;
737 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "", rid);
738 }
739 va_end(ap);
740
741 /* The button. */
742 r.top = y + 2*GAPWITHIN; r.bottom = PUSHBTNHEIGHT;
743 r.left = rpos; r.right = rwid;
744 doctl(cp, r, "BUTTON",
745 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
746 0, btext, bid);
747
748 cp->ypos += LISTHEIGHT + GAPBETWEEN;
749}
750
c96a8fef 751static char savedsession[2048];
752
753enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TAB, controlstartvalue,
754
755 connectionpanelstart,
756 IDC0_HOSTSTATIC,
757 IDC0_HOST,
758 IDC0_PORTSTATIC,
759 IDC0_PORT,
760 IDC0_PROTSTATIC,
761 IDC0_PROTRAW,
762 IDC0_PROTTELNET,
763 IDC0_PROTSSH,
764 IDC0_SESSSTATIC,
765 IDC0_SESSEDIT,
766 IDC0_SESSLIST,
767 IDC0_SESSLOAD,
768 IDC0_SESSSAVE,
769 IDC0_SESSDEL,
ec55b220 770 IDC0_PINGSTATIC,
771 IDC0_PINGEDIT,
c96a8fef 772 connectionpanelend,
773
774 keyboardpanelstart,
775 IDC1_DELSTATIC,
776 IDC1_DEL008,
777 IDC1_DEL127,
778 IDC1_HOMESTATIC,
779 IDC1_HOMETILDE,
780 IDC1_HOMERXVT,
781 IDC1_FUNCSTATIC,
782 IDC1_FUNCTILDE,
783 IDC1_FUNCLINUX,
784 IDC1_FUNCXTERM,
ec55b220 785 IDC1_FUNCVT400,
c96a8fef 786 IDC1_KPSTATIC,
787 IDC1_KPNORMAL,
788 IDC1_KPAPPLIC,
789 IDC1_KPNH,
790 IDC1_CURSTATIC,
791 IDC1_CURNORMAL,
792 IDC1_CURAPPLIC,
793 IDC1_ALTF4,
794 IDC1_ALTSPACE,
795 IDC1_LDISCTERM,
796 IDC1_SCROLLKEY,
797 keyboardpanelend,
798
799 terminalpanelstart,
800 IDC2_WRAPMODE,
801 IDC2_DECOM,
802 IDC2_DIMSTATIC,
803 IDC2_ROWSSTATIC,
804 IDC2_ROWSEDIT,
805 IDC2_COLSSTATIC,
806 IDC2_COLSEDIT,
807 IDC2_SAVESTATIC,
808 IDC2_SAVEEDIT,
809 IDC2_FONTSTATIC,
810 IDC2_CHOOSEFONT,
811 IDC2_LFHASCR,
812 IDC2_BEEP,
813 IDC2_BCE,
814 IDC2_BLINKTEXT,
815 terminalpanelend,
816
817 windowpanelstart,
818 IDC3_WINNAME,
819 IDC3_BLINKCUR,
820 IDC3_SCROLLBAR,
821 IDC3_LOCKSIZE,
822 IDC3_WINTITLE,
823 IDC3_WINEDIT,
ec55b220 824 IDC3_CLOSEEXIT,
825 IDC3_CLOSEWARN,
c96a8fef 826 windowpanelend,
827
828 telnetpanelstart,
829 IDC4_TTSTATIC,
830 IDC4_TTEDIT,
831 IDC4_TSSTATIC,
832 IDC4_TSEDIT,
833 IDC4_LOGSTATIC,
834 IDC4_LOGEDIT,
835 IDC4_ENVSTATIC,
836 IDC4_VARSTATIC,
837 IDC4_VAREDIT,
838 IDC4_VALSTATIC,
839 IDC4_VALEDIT,
840 IDC4_ENVLIST,
841 IDC4_ENVADD,
842 IDC4_ENVREMOVE,
843 IDC4_EMSTATIC,
844 IDC4_EMBSD,
845 IDC4_EMRFC,
846 telnetpanelend,
847
848 sshpanelstart,
849 IDC5_TTSTATIC,
850 IDC5_TTEDIT,
851 IDC5_LOGSTATIC,
852 IDC5_LOGEDIT,
853 IDC5_NOPTY,
854 IDC5_CIPHERSTATIC,
855 IDC5_CIPHER3DES,
856 IDC5_CIPHERBLOWF,
857 IDC5_CIPHERDES,
858 IDC5_AUTHTIS,
859 IDC5_PKSTATIC,
860 IDC5_PKEDIT,
861 IDC5_PKBUTTON,
862 IDC5_SSHPROTSTATIC,
863 IDC5_SSHPROT1,
864 IDC5_SSHPROT2,
865 IDC5_AGENTFWD,
866 IDC5_CMDSTATIC,
867 IDC5_CMDEDIT,
868 sshpanelend,
869
870 selectionpanelstart,
871 IDC6_MBSTATIC,
872 IDC6_MBWINDOWS,
873 IDC6_MBXTERM,
874 IDC6_CCSTATIC,
875 IDC6_CCLIST,
876 IDC6_CCSET,
877 IDC6_CCSTATIC2,
878 IDC6_CCEDIT,
879 selectionpanelend,
880
881 colourspanelstart,
882 IDC7_BOLDCOLOUR,
883 IDC7_PALETTE,
884 IDC7_STATIC,
885 IDC7_LIST,
886 IDC7_RSTATIC,
887 IDC7_GSTATIC,
888 IDC7_BSTATIC,
889 IDC7_RVALUE,
890 IDC7_GVALUE,
891 IDC7_BVALUE,
892 IDC7_CHANGE,
893 colourspanelend,
894
895 translationpanelstart,
896 IDC8_XLATSTATIC,
897 IDC8_NOXLAT,
898 IDC8_KOI8WIN1251,
899 IDC8_88592WIN1250,
900 IDC8_CAPSLOCKCYR,
901 IDC8_VTSTATIC,
902 IDC8_VTXWINDOWS,
903 IDC8_VTOEMANSI,
904 IDC8_VTOEMONLY,
905 IDC8_VTPOORMAN,
906 translationpanelend,
907
908 controlendvalue
909};
910
911static const char *const colours[] = {
912 "Default Foreground", "Default Bold Foreground",
913 "Default Background", "Default Bold Background",
914 "Cursor Text", "Cursor Colour",
915 "ANSI Black", "ANSI Black Bold",
916 "ANSI Red", "ANSI Red Bold",
917 "ANSI Green", "ANSI Green Bold",
918 "ANSI Yellow", "ANSI Yellow Bold",
919 "ANSI Blue", "ANSI Blue Bold",
920 "ANSI Magenta", "ANSI Magenta Bold",
921 "ANSI Cyan", "ANSI Cyan Bold",
922 "ANSI White", "ANSI White Bold"
923};
924static const int permcolour[] = {
925 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
926 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
927 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
928};
929
930static void fmtfont (char *buf) {
931 sprintf (buf, "Font: %s, ", cfg.font);
932 if (cfg.fontisbold)
933 strcat(buf, "bold, ");
934 if (cfg.fontheight == 0)
935 strcat (buf, "default height");
936 else
937 sprintf (buf+strlen(buf), "%d-%s",
938 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
939 (cfg.fontheight < 0 ? "pixel" : "point"));
940}
941
942static void init_dlg_ctrls(HWND hwnd) {
943 int i;
944 char fontstatic[256];
945
946 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
947 SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
948 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
949 for (i = 0; i < nsessions; i++)
950 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
951 0, (LPARAM) (sessions[i]));
952 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
953 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
954 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
ec55b220 955 SetDlgItemInt (hwnd, IDC0_PINGEDIT, cfg.ping_interval, FALSE);
c96a8fef 956
957 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
958 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
959 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
960 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
961 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
ec55b220 962 cfg.funky_type == 0 ? IDC1_FUNCTILDE :
963 cfg.funky_type == 1 ? IDC1_FUNCLINUX :
964 cfg.funky_type == 2 ? IDC1_FUNCXTERM :
965 cfg.funky_type == 3 ? IDC1_FUNCVT400 :
966 IDC1_FUNCTILDE );
c96a8fef 967 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
968 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
969 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
970 cfg.nethack_keypad ? IDC1_KPNH :
971 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
972 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
973 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
974 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
975 CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
976
977 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
978 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
979 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
980 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
981 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
982 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
983 fmtfont (fontstatic);
984 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
985 CheckDlgButton (hwnd, IDC2_BEEP, cfg.beep);
986 CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
987 CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
988
989 SetDlgItemText (hwnd, IDC3_WINEDIT, cfg.wintitle);
990 CheckDlgButton (hwnd, IDC3_WINNAME, cfg.win_name_always);
991 CheckDlgButton (hwnd, IDC3_BLINKCUR, cfg.blink_cur);
992 CheckDlgButton (hwnd, IDC3_SCROLLBAR, cfg.scrollbar);
993 CheckDlgButton (hwnd, IDC3_LOCKSIZE, cfg.locksize);
ec55b220 994 CheckDlgButton (hwnd, IDC3_CLOSEEXIT, cfg.close_on_exit);
995 CheckDlgButton (hwnd, IDC3_CLOSEWARN, cfg.warn_on_close);
c96a8fef 996
997 SetDlgItemText (hwnd, IDC4_TTEDIT, cfg.termtype);
998 SetDlgItemText (hwnd, IDC4_TSEDIT, cfg.termspeed);
999 SetDlgItemText (hwnd, IDC4_LOGEDIT, cfg.username);
1000 {
1001 char *p = cfg.environmt;
1002 while (*p) {
1003 SendDlgItemMessage (hwnd, IDC4_ENVLIST, LB_ADDSTRING, 0,
1004 (LPARAM) p);
1005 p += strlen(p)+1;
1006 }
374330e2 1007 }
c96a8fef 1008 CheckRadioButton (hwnd, IDC4_EMBSD, IDC4_EMRFC,
1009 cfg.rfc_environ ? IDC4_EMRFC : IDC4_EMBSD);
1010
1011 SetDlgItemText (hwnd, IDC5_TTEDIT, cfg.termtype);
1012 SetDlgItemText (hwnd, IDC5_LOGEDIT, cfg.username);
1013 CheckDlgButton (hwnd, IDC5_NOPTY, cfg.nopty);
1014 CheckDlgButton (hwnd, IDC5_AGENTFWD, cfg.agentfwd);
1015 CheckRadioButton (hwnd, IDC5_CIPHER3DES, IDC5_CIPHERDES,
1016 cfg.cipher == CIPHER_BLOWFISH ? IDC5_CIPHERBLOWF :
1017 cfg.cipher == CIPHER_DES ? IDC5_CIPHERDES :
1018 IDC5_CIPHER3DES);
1019 CheckRadioButton (hwnd, IDC5_SSHPROT1, IDC5_SSHPROT2,
1020 cfg.sshprot == 1 ? IDC5_SSHPROT1 : IDC5_SSHPROT2);
1021 CheckDlgButton (hwnd, IDC5_AUTHTIS, cfg.try_tis_auth);
1022 SetDlgItemText (hwnd, IDC5_PKEDIT, cfg.keyfile);
1023 SetDlgItemText (hwnd, IDC5_CMDEDIT, cfg.remote_cmd);
1024
1025 CheckRadioButton (hwnd, IDC6_MBWINDOWS, IDC6_MBXTERM,
1026 cfg.mouse_is_xterm ? IDC6_MBXTERM : IDC6_MBWINDOWS);
1027 {
1028 static int tabs[4] = {25, 61, 96, 128};
1029 SendDlgItemMessage (hwnd, IDC6_CCLIST, LB_SETTABSTOPS, 4,
1030 (LPARAM) tabs);
1031 }
1032 for (i=0; i<256; i++) {
1033 char str[100];
1034 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1035 (i>=0x21 && i != 0x7F) ? i : ' ',
1036 cfg.wordness[i]);
1037 SendDlgItemMessage (hwnd, IDC6_CCLIST, LB_ADDSTRING, 0,
1038 (LPARAM) str);
1039 }
1040
1041 CheckDlgButton (hwnd, IDC7_BOLDCOLOUR, cfg.bold_colour);
1042 CheckDlgButton (hwnd, IDC7_PALETTE, cfg.try_palette);
1043 {
1044 int i;
1045 for (i=0; i<22; i++)
1046 if (cfg.bold_colour || permcolour[i])
1047 SendDlgItemMessage (hwnd, IDC7_LIST, LB_ADDSTRING, 0,
1048 (LPARAM) colours[i]);
1049 }
1050 SendDlgItemMessage (hwnd, IDC7_LIST, LB_SETCURSEL, 0, 0);
1051 SetDlgItemInt (hwnd, IDC7_RVALUE, cfg.colours[0][0], FALSE);
1052 SetDlgItemInt (hwnd, IDC7_GVALUE, cfg.colours[0][1], FALSE);
1053 SetDlgItemInt (hwnd, IDC7_BVALUE, cfg.colours[0][2], FALSE);
1054
1055 CheckRadioButton (hwnd, IDC8_NOXLAT, IDC8_88592WIN1250,
1056 cfg.xlat_88592w1250 ? IDC8_88592WIN1250 :
1057 cfg.xlat_enablekoiwin ? IDC8_KOI8WIN1251 :
1058 IDC8_NOXLAT);
1059 CheckDlgButton (hwnd, IDC8_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1060 CheckRadioButton (hwnd, IDC8_VTXWINDOWS, IDC8_VTPOORMAN,
1061 cfg.vtmode == VT_XWINDOWS ? IDC8_VTXWINDOWS :
1062 cfg.vtmode == VT_OEMANSI ? IDC8_VTOEMANSI :
1063 cfg.vtmode == VT_OEMONLY ? IDC8_VTOEMONLY :
1064 IDC8_VTPOORMAN);
374330e2 1065}
1066
c96a8fef 1067static void hide(HWND hwnd, int hide, int minid, int maxid) {
1068 int i;
1069 for (i = minid; i < maxid; i++) {
1070 HWND ctl = GetDlgItem(hwnd, i);
1071 if (ctl) {
1072 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1073 }
1074 }
1075}
6584031a 1076
c96a8fef 1077/*
1078 * This _huge_ function is the configuration box.
1079 */
1080static int GenericMainDlgProc (HWND hwnd, UINT msg,
1081 WPARAM wParam, LPARAM lParam,
1082 int dlgtype) {
1083 HWND hw, tabctl;
1084 TC_ITEMHEADER tab;
1085 OPENFILENAME of;
1086 char filename[sizeof(cfg.keyfile)];
1087 CHOOSEFONT cf;
1088 LOGFONT lf;
1089 char fontstatic[256];
374330e2 1090 int i;
1091
1092 switch (msg) {
1093 case WM_INITDIALOG:
c96a8fef 1094 SetWindowLong(hwnd, GWL_USERDATA, 0);
1095 /*
1096 * Centre the window.
1097 */
1098 { /* centre the window */
1099 RECT rs, rd;
1100
1101 hw = GetDesktopWindow();
1102 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1103 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1104 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1105 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1106 }
1107
1108 /*
1109 * Create the tab control.
1110 */
1111 {
1112 RECT r;
1113 WPARAM font;
1114
1115 r.left = 3; r.right = r.left + 174;
1116 r.top = 3; r.bottom = r.top + 193;
1117 MapDialogRect(hwnd, &r);
1118 tabctl = CreateWindowEx(0, WC_TABCONTROL, "",
1119 WS_CHILD | WS_VISIBLE |
1120 WS_TABSTOP | TCS_MULTILINE,
1121 r.left, r.top,
1122 r.right-r.left, r.bottom-r.top,
1123 hwnd, (HMENU)IDCX_TAB, hinst, NULL);
1124 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1125 SendMessage(tabctl, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1126 }
1127
1128 /*
1129 * Create the various panelfuls of controls.
1130 */
1131
1132 i = 0;
1133
1134 /* The Connection panel. Accelerators used: [aco] dehlnprstwx */
1135 {
1136 struct ctlpos cp;
1137 ctlposinit(&cp, hwnd, 6, 30);
1138 if (dlgtype == 0) {
1139 multiedit(&cp,
1140 "Host &Name", IDC0_HOSTSTATIC, IDC0_HOST, 75,
1141 "&Port", IDC0_PORTSTATIC, IDC0_PORT, 25, NULL);
1142 if (backends[2].backend == NULL) {
1143 /* this is PuTTYtel, so only two protocols available */
1144 radioline(&cp, "Protocol:", IDC0_PROTSTATIC, 3,
1145 "&Raw", IDC0_PROTRAW,
1146 "&Telnet", IDC0_PROTTELNET, NULL);
1147 } else {
1148 radioline(&cp, "Protocol:", IDC0_PROTSTATIC, 3,
1149 "&Raw", IDC0_PROTRAW,
1150 "&Telnet", IDC0_PROTTELNET,
d4dcbf56 1151#ifdef FWHACK
c96a8fef 1152 "SS&H/hack",
d4dcbf56 1153#else
c96a8fef 1154 "SS&H",
d4dcbf56 1155#endif
c96a8fef 1156 IDC0_PROTSSH, NULL);
1157 }
1158 sesssaver(&cp, "Stor&ed Sessions",
1159 IDC0_SESSSTATIC, IDC0_SESSEDIT, IDC0_SESSLIST,
1160 "&Load", IDC0_SESSLOAD,
1161 "&Save", IDC0_SESSSAVE,
1162 "&Delete", IDC0_SESSDEL, NULL);
1163 }
ec55b220 1164 staticedit(&cp, "Keepalive inter&val (minutes)",
1165 IDC0_PINGSTATIC, IDC0_PINGEDIT, 25);
c96a8fef 1166
1167 tab.mask = TCIF_TEXT; tab.pszText = "Connection";
1168 TabCtrl_InsertItem (tabctl, i++, &tab);
1169 }
1170
1171 /* The Keyboard panel. Accelerators used: [aco] 4?ehiklmnprsuvxy */
1172 {
1173 struct ctlpos cp;
1174 ctlposinit(&cp, hwnd, 6, 30);
1175 radioline(&cp, "Action of Backspace:", IDC1_DELSTATIC, 2,
1176 "Control-&H", IDC1_DEL008,
1177 "Control-&? (127)", IDC1_DEL127, NULL);
1178 radioline(&cp, "Action of Home and End:", IDC1_HOMESTATIC, 2,
1179 "&Standard", IDC1_HOMETILDE,
1180 "&rxvt", IDC1_HOMERXVT, NULL);
ec55b220 1181 radioline(&cp, "Function key and keypad layout:", IDC1_FUNCSTATIC, 4,
c96a8fef 1182 "&VT400", IDC1_FUNCTILDE,
1183 "&Linux", IDC1_FUNCLINUX,
ec55b220 1184 "&Xterm R6", IDC1_FUNCXTERM,
1185 "&VT400", IDC1_FUNCVT400, NULL);
c96a8fef 1186 radioline(&cp, "Initial state of cursor keys:", IDC1_CURSTATIC, 2,
1187 "&Normal", IDC1_CURNORMAL,
1188 "A&pplication", IDC1_CURAPPLIC, NULL);
1189 radioline(&cp, "Initial state of numeric keypad:", IDC1_KPSTATIC, 3,
1190 "Nor&mal", IDC1_KPNORMAL,
1191 "Appl&ication", IDC1_KPAPPLIC,
1192 "N&etHack", IDC1_KPNH, NULL);
1193 checkbox(&cp, "ALT-F&4 is special (closes window)", IDC1_ALTF4);
1194 checkbox(&cp, "ALT-Space is special (S&ystem menu)", IDC1_ALTSPACE);
1195 checkbox(&cp, "&Use local terminal line discipline", IDC1_LDISCTERM);
1196 checkbox(&cp, "Reset scrollback on &keypress", IDC1_SCROLLKEY);
1197
1198 tab.mask = TCIF_TEXT; tab.pszText = "Keyboard";
1199 TabCtrl_InsertItem (tabctl, i++, &tab);
1200 }
1201
ec55b220 1202 /* The Terminal panel. Accelerators used: [aco] dghlmnprsvw */
c96a8fef 1203 {
1204 struct ctlpos cp;
1205 ctlposinit(&cp, hwnd, 6, 30);
1206 multiedit(&cp,
1207 "&Rows", IDC2_ROWSSTATIC, IDC2_ROWSEDIT, 33,
1208 "Colu&mns", IDC2_COLSSTATIC, IDC2_COLSEDIT, 33,
1209 "&Scrollback", IDC2_SAVESTATIC, IDC2_SAVEEDIT, 33,
1210 NULL);
1211 staticbtn(&cp, "", IDC2_FONTSTATIC, "C&hange...", IDC2_CHOOSEFONT);
1212 checkbox(&cp, "Auto &wrap mode initially on", IDC2_WRAPMODE);
1213 checkbox(&cp, "&DEC Origin Mode initially on", IDC2_DECOM);
1214 checkbox(&cp, "Implicit CR in every &LF", IDC2_LFHASCR);
1215 checkbox(&cp, "Bee&p enabled", IDC2_BEEP);
1216 checkbox(&cp, "Use Back&ground colour erase", IDC2_BCE);
1217 checkbox(&cp, "Enable bli&nking text", IDC2_BLINKTEXT);
1218 tab.mask = TCIF_TEXT; tab.pszText = "Terminal";
1219 TabCtrl_InsertItem (tabctl, i++, &tab);
1220 }
1221
1222 /* The Window panel. Accelerators used: [aco] bikty */
1223 {
1224 struct ctlpos cp;
1225 ctlposinit(&cp, hwnd, 6, 30);
1226 if (dlgtype == 0)
1227 multiedit(&cp,
1228 "Initial window &title:", IDC3_WINTITLE,
1229 IDC3_WINEDIT, 100, NULL);
1230 checkbox(&cp, "Avoid ever using &icon title", IDC3_WINNAME);
1231 checkbox(&cp, "&Blinking cursor", IDC3_BLINKCUR);
1232 checkbox(&cp, "Displa&y scrollbar", IDC3_SCROLLBAR);
1233 checkbox(&cp, "Loc&k Window size", IDC3_LOCKSIZE);
ec55b220 1234 checkbox(&cp, "Close Window on E&xit", IDC3_CLOSEEXIT);
1235 checkbox(&cp, "&Warn on Close", IDC3_CLOSEWARN);
c96a8fef 1236 tab.mask = TCIF_TEXT; tab.pszText = "Window";
1237 TabCtrl_InsertItem (tabctl, i++, &tab);
1238 }
1239
1240 /* The Telnet panel. Accelerators used: [aco] bdflrstuv */
1241 {
1242 struct ctlpos cp;
1243 ctlposinit(&cp, hwnd, 6, 30);
1244 if (dlgtype == 0) {
ec55b220 1245 staticedit(&cp, "Terminal-&type string", IDC4_TTSTATIC, IDC4_TTEDIT, 50);
1246 staticedit(&cp, "Terminal-&speed string", IDC4_TSSTATIC, IDC4_TSEDIT, 50);
1247 staticedit(&cp, "Auto-login &username", IDC4_LOGSTATIC, IDC4_LOGEDIT, 50);
c96a8fef 1248 envsetter(&cp, "Environment variables:", IDC4_ENVSTATIC,
1249 "&Variable", IDC4_VARSTATIC, IDC4_VAREDIT,
1250 "Va&lue", IDC4_VALSTATIC, IDC4_VALEDIT,
1251 IDC4_ENVLIST,
1252 "A&dd", IDC4_ENVADD, "&Remove", IDC4_ENVREMOVE);
1253 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC4_EMSTATIC, 2,
1254 "&BSD (commonplace)", IDC4_EMBSD,
1255 "R&FC 1408 (unusual)", IDC4_EMRFC, NULL);
1256 tab.mask = TCIF_TEXT; tab.pszText = "Telnet";
1257 TabCtrl_InsertItem (tabctl, i++, &tab);
1258 }
1259 }
1260
1261 /* The SSH panel. Accelerators used: [aco] 123abdkmprtuw */
1262 {
1263 struct ctlpos cp;
1264 ctlposinit(&cp, hwnd, 6, 30);
1265 if (dlgtype == 0) {
ec55b220 1266 staticedit(&cp, "Terminal-&type string", IDC5_TTSTATIC, IDC5_TTEDIT, 50);
1267 staticedit(&cp, "Auto-login &username", IDC5_LOGSTATIC, IDC5_LOGEDIT, 50);
c96a8fef 1268 multiedit(&cp,
1269 "&Remote command:", IDC5_CMDSTATIC, IDC5_CMDEDIT, 100,
1270 NULL);
1271 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC5_NOPTY);
1272 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1273 IDC5_AUTHTIS);
1274 checkbox(&cp, "Allow &agent forwarding", IDC5_AGENTFWD);
1275 editbutton(&cp, "Private &key file for authentication:",
1276 IDC5_PKSTATIC, IDC5_PKEDIT, "Bro&wse...", IDC5_PKBUTTON);
1277 radioline(&cp, "Preferred SSH protocol version:",
1278 IDC5_SSHPROTSTATIC, 2,
1279 "&1", IDC5_SSHPROT1, "&2", IDC5_SSHPROT2, NULL);
1280 radioline(&cp, "Preferred encryption algorithm:", IDC5_CIPHERSTATIC, 3,
1281 "&3DES", IDC5_CIPHER3DES,
1282 "&Blowfish", IDC5_CIPHERBLOWF,
1283 "&DES", IDC5_CIPHERDES, NULL);
1284 tab.mask = TCIF_TEXT; tab.pszText = "SSH";
1285 TabCtrl_InsertItem (tabctl, i++, &tab);
1286 }
1287 }
1288
1289 /* The Selection panel. Accelerators used: [aco] stwx */
1290 {
1291 struct ctlpos cp;
1292 ctlposinit(&cp, hwnd, 6, 30);
1293 radiobig(&cp, "Action of mouse buttons:", IDC6_MBSTATIC,
1294 "&Windows (Right pastes, Middle extends)", IDC6_MBWINDOWS,
1295 "&xterm (Right extends, Middle pastes)", IDC6_MBXTERM,
1296 NULL);
1297 charclass(&cp, "Character classes:", IDC6_CCSTATIC, IDC6_CCLIST,
1298 "&Set", IDC6_CCSET, IDC6_CCEDIT,
1299 "&to class", IDC6_CCSTATIC2);
1300 tab.mask = TCIF_TEXT; tab.pszText = "Selection";
1301 TabCtrl_InsertItem (tabctl, i++, &tab);
1302 }
1303
1304 /* The Colours panel. Accelerators used: [aco] bmlu */
1305 {
1306 struct ctlpos cp;
1307 ctlposinit(&cp, hwnd, 6, 30);
1308 checkbox(&cp, "&Bolded text is a different colour", IDC7_BOLDCOLOUR);
1309 checkbox(&cp, "Attempt to use &logical palettes", IDC7_PALETTE);
1310 colouredit(&cp, "Select a colo&ur and click to modify it:",
1311 IDC7_STATIC, IDC7_LIST,
1312 "&Modify...", IDC7_CHANGE,
1313 "Red:", IDC7_RSTATIC, IDC7_RVALUE,
1314 "Green:", IDC7_GSTATIC, IDC7_GVALUE,
1315 "Blue:", IDC7_BSTATIC, IDC7_BVALUE, NULL);
1316 tab.mask = TCIF_TEXT; tab.pszText = "Colours";
1317 TabCtrl_InsertItem (tabctl, i++, &tab);
1318 }
1319
1320 /* The Translation panel. Accelerators used: [aco] beiknpsx */
1321 {
1322 struct ctlpos cp;
1323 ctlposinit(&cp, hwnd, 6, 30);
1324 radiobig(&cp,
1325 "Handling of VT100 line drawing characters:", IDC8_VTSTATIC,
1326 "Font has &XWindows encoding", IDC8_VTXWINDOWS,
1327 "Use font in &both ANSI and OEM modes", IDC8_VTOEMANSI,
1328 "Use font in O&EM mode only", IDC8_VTOEMONLY,
1329 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1330 IDC8_VTPOORMAN, NULL);
1331 radiobig(&cp,
1332 "Character set translation:", IDC8_XLATSTATIC,
1333 "&None", IDC8_NOXLAT,
1334 "&KOI8 / Win-1251", IDC8_KOI8WIN1251,
1335 "&ISO-8859-2 / Win-1250", IDC8_88592WIN1250, NULL);
1336 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch", IDC8_CAPSLOCKCYR);
1337 tab.mask = TCIF_TEXT; tab.pszText = "Translation";
1338 TabCtrl_InsertItem (tabctl, i++, &tab);
1339 }
1340
1341 init_dlg_ctrls(hwnd);
1342
1343 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1344 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1345
1346 /*
1347 * Set focus into the first available control.
1348 */
1349 {
1350 HWND ctl;
1351 ctl = GetDlgItem(hwnd, IDC0_HOST);
ec55b220 1352 if (!ctl) ctl = GetDlgItem(hwnd, IDC0_PINGEDIT);
c96a8fef 1353 SetFocus(ctl);
9d01fc92 1354 }
c96a8fef 1355
1356 SetWindowLong(hwnd, GWL_USERDATA, 1);
1357 return 0;
1cd246bb 1358 case WM_LBUTTONUP:
1359 /*
1360 * Button release should trigger WM_OK if there was a
1361 * previous double click on the session list.
1362 */
1363 ReleaseCapture();
1364 if (readytogo)
c96a8fef 1365 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1cd246bb 1366 break;
c96a8fef 1367 case WM_NOTIFY:
1368 if (LOWORD(wParam) == IDCX_TAB &&
1369 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1370 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1371 TCITEM item;
1372 char buffer[64];
1373 item.pszText = buffer;
1374 item.cchTextMax = sizeof(buffer);
1375 item.mask = TCIF_TEXT;
1376 TabCtrl_GetItem(((LPNMHDR)lParam)->hwndFrom, i, &item);
1377 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1378 if (!strcmp(buffer, "Connection"))
1379 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1380 if (!strcmp(buffer, "Keyboard"))
1381 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1382 if (!strcmp(buffer, "Terminal"))
1383 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1384 if (!strcmp(buffer, "Window"))
1385 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1386 if (!strcmp(buffer, "Telnet"))
1387 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1388 if (!strcmp(buffer, "SSH"))
1389 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1390 if (!strcmp(buffer, "Selection"))
1391 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1392 if (!strcmp(buffer, "Colours"))
1393 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1394 if (!strcmp(buffer, "Translation"))
1395 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1396
1397 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1398 return 0;
1399 }
1400 break;
374330e2 1401 case WM_COMMAND:
c96a8fef 1402 /*
1403 * Only process WM_COMMAND once the dialog is fully formed.
1404 */
1405 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1406 case IDOK:
1407 if (*cfg.host)
1408 EndDialog (hwnd, 1);
1409 else
1410 MessageBeep (0);
1411 return 0;
1412 case IDCANCEL:
1413 EndDialog (hwnd, 0);
1414 return 0;
1415 case IDC0_PROTTELNET:
1416 case IDC0_PROTSSH:
1417 case IDC0_PROTRAW:
374330e2 1418 if (HIWORD(wParam) == BN_CLICKED ||
1419 HIWORD(wParam) == BN_DOUBLECLICKED) {
c96a8fef 1420 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
1421 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
5e1a8e27 1422 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
374330e2 1423 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1424 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1425 cfg.port = i ? 22 : 23;
c96a8fef 1426 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
374330e2 1427 }
1428 }
1429 break;
c96a8fef 1430 case IDC0_HOST:
374330e2 1431 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1432 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
374330e2 1433 sizeof(cfg.host)-1);
1434 break;
c96a8fef 1435 case IDC0_PORT:
374330e2 1436 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1437 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
374330e2 1438 break;
c96a8fef 1439 case IDC0_SESSEDIT:
6584031a 1440 if (HIWORD(wParam) == EN_CHANGE) {
c96a8fef 1441 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
374330e2 1442 (WPARAM) -1, 0);
c96a8fef 1443 GetDlgItemText (hwnd, IDC0_SESSEDIT,
6584031a 1444 savedsession, sizeof(savedsession)-1);
1445 savedsession[sizeof(savedsession)-1] = '\0';
1446 }
374330e2 1447 break;
c96a8fef 1448 case IDC0_SESSSAVE:
374330e2 1449 if (HIWORD(wParam) == BN_CLICKED ||
1450 HIWORD(wParam) == BN_DOUBLECLICKED) {
1451 /*
1452 * Save a session
1453 */
1454 char str[2048];
c96a8fef 1455 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
374330e2 1456 if (!*str) {
c96a8fef 1457 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
374330e2 1458 LB_GETCURSEL, 0, 0);
1459 if (n == LB_ERR) {
1460 MessageBeep(0);
1461 break;
1462 }
1463 strcpy (str, sessions[n]);
1464 }
a9422f39 1465 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
374330e2 1466 get_sesslist (FALSE);
1467 get_sesslist (TRUE);
c96a8fef 1468 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
374330e2 1469 0, 0);
1470 for (i = 0; i < nsessions; i++)
c96a8fef 1471 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
374330e2 1472 0, (LPARAM) (sessions[i]));
c96a8fef 1473 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
374330e2 1474 (WPARAM) -1, 0);
1475 }
1476 break;
c96a8fef 1477 case IDC0_SESSLIST:
1478 case IDC0_SESSLOAD:
1479 if (LOWORD(wParam) == IDC0_SESSLOAD &&
374330e2 1480 HIWORD(wParam) != BN_CLICKED &&
1481 HIWORD(wParam) != BN_DOUBLECLICKED)
1482 break;
c96a8fef 1483 if (LOWORD(wParam) == IDC0_SESSLIST &&
374330e2 1484 HIWORD(wParam) != LBN_DBLCLK)
1485 break;
1486 {
c96a8fef 1487 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
374330e2 1488 LB_GETCURSEL, 0, 0);
1489 if (n == LB_ERR) {
1490 MessageBeep(0);
1491 break;
1492 }
1493 load_settings (sessions[n],
a9422f39 1494 !!strcmp(sessions[n], "Default Settings"),
1495 &cfg);
c96a8fef 1496 init_dlg_ctrls(hwnd);
374330e2 1497 }
c96a8fef 1498 if (LOWORD(wParam) == IDC0_SESSLIST) {
374330e2 1499 /*
1500 * A double-click on a saved session should
1501 * actually start the session, not just load it.
1502 * Unless it's Default Settings or some other
1503 * host-less set of saved settings.
1504 */
1cd246bb 1505 if (*cfg.host) {
1506 readytogo = TRUE;
1507 SetCapture(hwnd);
1508 }
374330e2 1509 }
1510 break;
c96a8fef 1511 case IDC0_SESSDEL:
374330e2 1512 if (HIWORD(wParam) == BN_CLICKED ||
1513 HIWORD(wParam) == BN_DOUBLECLICKED) {
c96a8fef 1514 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
374330e2 1515 LB_GETCURSEL, 0, 0);
1516 if (n == LB_ERR || n == 0) {
1517 MessageBeep(0);
1518 break;
1519 }
d1622aed 1520 del_settings(sessions[n]);
374330e2 1521 get_sesslist (FALSE);
1522 get_sesslist (TRUE);
c96a8fef 1523 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
374330e2 1524 0, 0);
1525 for (i = 0; i < nsessions; i++)
c96a8fef 1526 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
374330e2 1527 0, (LPARAM) (sessions[i]));
c96a8fef 1528 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
374330e2 1529 (WPARAM) -1, 0);
1530 }
ec55b220 1531 case IDC0_PINGEDIT:
1532 if (HIWORD(wParam) == EN_CHANGE)
1533 MyGetDlgItemInt (hwnd, IDC0_PINGEDIT, &cfg.ping_interval);
1534 break;
c96a8fef 1535 case IDC1_DEL008:
1536 case IDC1_DEL127:
1537 if (HIWORD(wParam) == BN_CLICKED ||
1538 HIWORD(wParam) == BN_DOUBLECLICKED)
1539 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
1540 break;
1541 case IDC1_HOMETILDE:
1542 case IDC1_HOMERXVT:
1543 if (HIWORD(wParam) == BN_CLICKED ||
1544 HIWORD(wParam) == BN_DOUBLECLICKED)
1545 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
1546 break;
1547 case IDC1_FUNCXTERM:
1548 if (HIWORD(wParam) == BN_CLICKED ||
1549 HIWORD(wParam) == BN_DOUBLECLICKED)
c9def1b8 1550 cfg.funky_type = 2;
c96a8fef 1551 break;
ec55b220 1552 case IDC1_FUNCVT400:
1553 if (HIWORD(wParam) == BN_CLICKED ||
1554 HIWORD(wParam) == BN_DOUBLECLICKED)
1555 cfg.funky_type = 3;
1556 break;
c96a8fef 1557 case IDC1_FUNCTILDE:
1558 case IDC1_FUNCLINUX:
1559 if (HIWORD(wParam) == BN_CLICKED ||
1560 HIWORD(wParam) == BN_DOUBLECLICKED)
1561 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
1562 break;
1563 case IDC1_KPNORMAL:
1564 case IDC1_KPAPPLIC:
1565 if (HIWORD(wParam) == BN_CLICKED ||
1566 HIWORD(wParam) == BN_DOUBLECLICKED) {
1567 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
c5e9c988 1568 cfg.nethack_keypad = FALSE;
c96a8fef 1569 }
1570 break;
1571 case IDC1_KPNH:
1572 if (HIWORD(wParam) == BN_CLICKED ||
1573 HIWORD(wParam) == BN_DOUBLECLICKED) {
c5e9c988 1574 cfg.app_keypad = FALSE;
1575 cfg.nethack_keypad = TRUE;
374330e2 1576 }
c96a8fef 1577 break;
1578 case IDC1_CURNORMAL:
1579 case IDC1_CURAPPLIC:
1580 if (HIWORD(wParam) == BN_CLICKED ||
1581 HIWORD(wParam) == BN_DOUBLECLICKED)
1582 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
1583 break;
1584 case IDC1_ALTF4:
1585 if (HIWORD(wParam) == BN_CLICKED ||
1586 HIWORD(wParam) == BN_DOUBLECLICKED)
1587 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
1588 break;
1589 case IDC1_ALTSPACE:
1590 if (HIWORD(wParam) == BN_CLICKED ||
1591 HIWORD(wParam) == BN_DOUBLECLICKED)
1592 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
1593 break;
1594 case IDC1_LDISCTERM:
1595 if (HIWORD(wParam) == BN_CLICKED ||
1596 HIWORD(wParam) == BN_DOUBLECLICKED)
1597 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
1598 break;
1599 case IDC1_SCROLLKEY:
1600 if (HIWORD(wParam) == BN_CLICKED ||
1601 HIWORD(wParam) == BN_DOUBLECLICKED)
1602 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
1603 break;
1604 case IDC2_WRAPMODE:
374330e2 1605 if (HIWORD(wParam) == BN_CLICKED ||
1606 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1607 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
374330e2 1608 break;
c96a8fef 1609 case IDC2_DECOM:
374330e2 1610 if (HIWORD(wParam) == BN_CLICKED ||
1611 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1612 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
374330e2 1613 break;
c96a8fef 1614 case IDC2_LFHASCR:
fef97f43 1615 if (HIWORD(wParam) == BN_CLICKED ||
1616 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1617 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
fef97f43 1618 break;
c96a8fef 1619 case IDC2_ROWSEDIT:
374330e2 1620 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1621 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
374330e2 1622 break;
c96a8fef 1623 case IDC2_COLSEDIT:
374330e2 1624 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1625 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
374330e2 1626 break;
c96a8fef 1627 case IDC2_SAVEEDIT:
374330e2 1628 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1629 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
374330e2 1630 break;
c96a8fef 1631 case IDC2_CHOOSEFONT:
374330e2 1632 lf.lfHeight = cfg.fontheight;
1633 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1634 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1635 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
14963b8f 1636 lf.lfCharSet = cfg.fontcharset;
374330e2 1637 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1638 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1639 lf.lfQuality = DEFAULT_QUALITY;
1640 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1641 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1642 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1643
1644 cf.lStructSize = sizeof(cf);
1645 cf.hwndOwner = hwnd;
1646 cf.lpLogFont = &lf;
1647 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1648 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1649
1650 if (ChooseFont (&cf)) {
1651 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1652 cfg.font[sizeof(cfg.font)-1] = '\0';
1653 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
14963b8f 1654 cfg.fontcharset = lf.lfCharSet;
374330e2 1655 cfg.fontheight = lf.lfHeight;
1656 fmtfont (fontstatic);
c96a8fef 1657 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
374330e2 1658 }
1659 break;
c96a8fef 1660 case IDC2_BEEP:
1661 if (HIWORD(wParam) == BN_CLICKED ||
1662 HIWORD(wParam) == BN_DOUBLECLICKED)
1663 cfg.beep = IsDlgButtonChecked (hwnd, IDC2_BEEP);
1664 break;
1665 case IDC2_BLINKTEXT:
9ca5da42 1666 if (HIWORD(wParam) == BN_CLICKED ||
1667 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1668 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
9ca5da42 1669 break;
c96a8fef 1670 case IDC2_BCE:
1671 if (HIWORD(wParam) == BN_CLICKED ||
1672 HIWORD(wParam) == BN_DOUBLECLICKED)
1673 cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
1674 break;
1675 case IDC3_WINNAME:
1676 if (HIWORD(wParam) == BN_CLICKED ||
1677 HIWORD(wParam) == BN_DOUBLECLICKED)
1678 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC3_WINNAME);
1679 break;
1680 case IDC3_BLINKCUR:
9ca5da42 1681 if (HIWORD(wParam) == BN_CLICKED ||
1682 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1683 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC3_BLINKCUR);
9ca5da42 1684 break;
c96a8fef 1685 case IDC3_SCROLLBAR:
9ca5da42 1686 if (HIWORD(wParam) == BN_CLICKED ||
1687 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1688 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC3_SCROLLBAR);
9ca5da42 1689 break;
c96a8fef 1690 case IDC3_LOCKSIZE:
9ca5da42 1691 if (HIWORD(wParam) == BN_CLICKED ||
1692 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1693 cfg.locksize = IsDlgButtonChecked (hwnd, IDC3_LOCKSIZE);
9ca5da42 1694 break;
c96a8fef 1695 case IDC3_WINEDIT:
9ca5da42 1696 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1697 GetDlgItemText (hwnd, IDC3_WINEDIT, cfg.wintitle,
9ca5da42 1698 sizeof(cfg.wintitle)-1);
1699 break;
ec55b220 1700 case IDC3_CLOSEEXIT:
1701 if (HIWORD(wParam) == BN_CLICKED ||
1702 HIWORD(wParam) == BN_DOUBLECLICKED)
1703 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC3_CLOSEEXIT);
1704 break;
1705 case IDC3_CLOSEWARN:
1706 if (HIWORD(wParam) == BN_CLICKED ||
1707 HIWORD(wParam) == BN_DOUBLECLICKED)
1708 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC3_CLOSEWARN);
1709 break;
c96a8fef 1710 case IDC4_TTEDIT:
374330e2 1711 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1712 GetDlgItemText (hwnd, IDC4_TTEDIT, cfg.termtype,
374330e2 1713 sizeof(cfg.termtype)-1);
1714 break;
c96a8fef 1715 case IDC4_TSEDIT:
374330e2 1716 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1717 GetDlgItemText (hwnd, IDC4_TSEDIT, cfg.termspeed,
374330e2 1718 sizeof(cfg.termspeed)-1);
1719 break;
c96a8fef 1720 case IDC4_LOGEDIT:
1721 if (HIWORD(wParam) == EN_CHANGE) {
1722 GetDlgItemText (hwnd, IDC4_LOGEDIT, cfg.username,
374330e2 1723 sizeof(cfg.username)-1);
c96a8fef 1724 cfg.username[sizeof(cfg.username)-1] = '\0';
1725 SetWindowLong(hwnd, GWL_USERDATA, 0);
1726 SetDlgItemText (hwnd, IDC5_LOGEDIT, cfg.username);
1727 SetWindowLong(hwnd, GWL_USERDATA, 1);
1728 }
374330e2 1729 break;
c96a8fef 1730 case IDC4_EMBSD:
1731 case IDC4_EMRFC:
1732 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC4_EMRFC);
374330e2 1733 break;
c96a8fef 1734 case IDC4_ENVADD:
374330e2 1735 if (HIWORD(wParam) == BN_CLICKED ||
1736 HIWORD(wParam) == BN_DOUBLECLICKED) {
37508af4 1737 char str[sizeof(cfg.environmt)];
374330e2 1738 char *p;
c96a8fef 1739 GetDlgItemText (hwnd, IDC4_VAREDIT, str, sizeof(str)-1);
374330e2 1740 if (!*str) {
1741 MessageBeep(0);
1742 break;
1743 }
1744 p = str + strlen(str);
1745 *p++ = '\t';
c96a8fef 1746 GetDlgItemText (hwnd, IDC4_VALEDIT, p, sizeof(str)-1-(p-str));
374330e2 1747 if (!*p) {
1748 MessageBeep(0);
1749 break;
1750 }
37508af4 1751 p = cfg.environmt;
374330e2 1752 while (*p) {
1753 while (*p) p++;
1754 p++;
1755 }
37508af4 1756 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
374330e2 1757 strcpy (p, str);
1758 p[strlen(str)+1] = '\0';
c96a8fef 1759 SendDlgItemMessage (hwnd, IDC4_ENVLIST, LB_ADDSTRING,
374330e2 1760 0, (LPARAM)str);
c96a8fef 1761 SetDlgItemText (hwnd, IDC4_VAREDIT, "");
1762 SetDlgItemText (hwnd, IDC4_VALEDIT, "");
374330e2 1763 } else {
1764 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1765 MB_OK | MB_ICONERROR);
1766 }
1767 }
1768 break;
c96a8fef 1769 case IDC4_ENVREMOVE:
374330e2 1770 if (HIWORD(wParam) != BN_CLICKED &&
1771 HIWORD(wParam) != BN_DOUBLECLICKED)
1772 break;
c96a8fef 1773 i = SendDlgItemMessage (hwnd, IDC4_ENVLIST, LB_GETCURSEL, 0, 0);
374330e2 1774 if (i == LB_ERR)
1775 MessageBeep (0);
1776 else {
1777 char *p, *q;
1778
c96a8fef 1779 SendDlgItemMessage (hwnd, IDC4_ENVLIST, LB_DELETESTRING,
374330e2 1780 i, 0);
37508af4 1781 p = cfg.environmt;
374330e2 1782 while (i > 0) {
1783 if (!*p)
1784 goto disaster;
1785 while (*p) p++;
1786 p++;
1787 i--;
1788 }
1789 q = p;
1790 if (!*p)
1791 goto disaster;
1792 while (*p) p++;
1793 p++;
1794 while (*p) {
1795 while (*p)
1796 *q++ = *p++;
1797 *q++ = *p++;
1798 }
1799 *q = '\0';
1800 disaster:;
1801 }
1802 break;
c96a8fef 1803 case IDC5_TTEDIT:
374330e2 1804 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1805 GetDlgItemText (hwnd, IDC5_TTEDIT, cfg.termtype,
374330e2 1806 sizeof(cfg.termtype)-1);
1807 break;
c96a8fef 1808 case IDC5_LOGEDIT:
1809 if (HIWORD(wParam) == EN_CHANGE) {
1810 GetDlgItemText (hwnd, IDC5_LOGEDIT, cfg.username,
374330e2 1811 sizeof(cfg.username)-1);
c96a8fef 1812 cfg.username[sizeof(cfg.username)-1] = '\0';
1813 SetWindowLong(hwnd, GWL_USERDATA, 0);
1814 SetDlgItemText (hwnd, IDC4_LOGEDIT, cfg.username);
1815 SetWindowLong(hwnd, GWL_USERDATA, 1);
1816 }
374330e2 1817 break;
c96a8fef 1818 case IDC5_NOPTY:
fef97f43 1819 if (HIWORD(wParam) == BN_CLICKED ||
1820 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1821 cfg.nopty = IsDlgButtonChecked (hwnd, IDC5_NOPTY);
fef97f43 1822 break;
c96a8fef 1823 case IDC5_AGENTFWD:
979310f1 1824 if (HIWORD(wParam) == BN_CLICKED ||
1825 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1826 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC5_AGENTFWD);
979310f1 1827 break;
c96a8fef 1828 case IDC5_CIPHER3DES:
1829 case IDC5_CIPHERBLOWF:
1830 case IDC5_CIPHERDES:
bea1ef5f 1831 if (HIWORD(wParam) == BN_CLICKED ||
1832 HIWORD(wParam) == BN_DOUBLECLICKED) {
c96a8fef 1833 if (IsDlgButtonChecked (hwnd, IDC5_CIPHER3DES))
bea1ef5f 1834 cfg.cipher = CIPHER_3DES;
c96a8fef 1835 else if (IsDlgButtonChecked (hwnd, IDC5_CIPHERBLOWF))
bea1ef5f 1836 cfg.cipher = CIPHER_BLOWFISH;
c96a8fef 1837 else if (IsDlgButtonChecked (hwnd, IDC5_CIPHERDES))
9697bfd2 1838 cfg.cipher = CIPHER_DES;
bea1ef5f 1839 }
1840 break;
c96a8fef 1841 case IDC5_SSHPROT1:
1842 case IDC5_SSHPROT2:
adf799dd 1843 if (HIWORD(wParam) == BN_CLICKED ||
1844 HIWORD(wParam) == BN_DOUBLECLICKED) {
c96a8fef 1845 if (IsDlgButtonChecked (hwnd, IDC5_SSHPROT1))
adf799dd 1846 cfg.sshprot = 1;
c96a8fef 1847 else if (IsDlgButtonChecked (hwnd, IDC5_SSHPROT2))
adf799dd 1848 cfg.sshprot = 2;
1849 }
1850 break;
c96a8fef 1851 case IDC5_AUTHTIS:
ccbfb941 1852 if (HIWORD(wParam) == BN_CLICKED ||
1853 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1854 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC5_AUTHTIS);
ccbfb941 1855 break;
c96a8fef 1856 case IDC5_PKEDIT:
7cca0d81 1857 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1858 GetDlgItemText (hwnd, IDC5_PKEDIT, cfg.keyfile,
7cca0d81 1859 sizeof(cfg.keyfile)-1);
1860 break;
c96a8fef 1861 case IDC5_CMDEDIT:
4c73ca1f 1862 if (HIWORD(wParam) == EN_CHANGE)
c96a8fef 1863 GetDlgItemText (hwnd, IDC5_CMDEDIT, cfg.remote_cmd,
4c73ca1f 1864 sizeof(cfg.remote_cmd)-1);
1865 break;
c96a8fef 1866 case IDC5_PKBUTTON:
7cca0d81 1867 memset(&of, 0, sizeof(of));
1868#ifdef OPENFILENAME_SIZE_VERSION_400
1869 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1870#else
1871 of.lStructSize = sizeof(of);
1872#endif
1873 of.hwndOwner = hwnd;
1874 of.lpstrFilter = "All Files\0*\0\0\0";
1875 of.lpstrCustomFilter = NULL;
1876 of.nFilterIndex = 1;
1877 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1878 of.nMaxFile = sizeof(filename);
1879 of.lpstrFileTitle = NULL;
1880 of.lpstrInitialDir = NULL;
1881 of.lpstrTitle = "Select Public Key File";
1882 of.Flags = 0;
1883 if (GetOpenFileName(&of)) {
1884 strcpy(cfg.keyfile, filename);
c96a8fef 1885 SetDlgItemText (hwnd, IDC5_PKEDIT, cfg.keyfile);
7cca0d81 1886 }
1887 break;
c96a8fef 1888 case IDC6_MBWINDOWS:
1889 case IDC6_MBXTERM:
1890 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC6_MBXTERM);
374330e2 1891 break;
c96a8fef 1892 case IDC6_CCSET:
374330e2 1893 {
1894 BOOL ok;
1895 int i;
c96a8fef 1896 int n = GetDlgItemInt (hwnd, IDC6_CCEDIT, &ok, FALSE);
374330e2 1897
1898 if (!ok)
1899 MessageBeep (0);
1900 else {
1901 for (i=0; i<256; i++)
c96a8fef 1902 if (SendDlgItemMessage (hwnd, IDC6_CCLIST, LB_GETSEL,
374330e2 1903 i, 0)) {
1904 char str[100];
1905 cfg.wordness[i] = n;
c96a8fef 1906 SendDlgItemMessage (hwnd, IDC6_CCLIST,
374330e2 1907 LB_DELETESTRING, i, 0);
1908 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1909 (i>=0x21 && i != 0x7F) ? i : ' ',
1910 cfg.wordness[i]);
c96a8fef 1911 SendDlgItemMessage (hwnd, IDC6_CCLIST,
374330e2 1912 LB_INSERTSTRING, i,
1913 (LPARAM)str);
1914 }
1915 }
1916 }
1917 break;
c96a8fef 1918 case IDC7_BOLDCOLOUR:
374330e2 1919 if (HIWORD(wParam) == BN_CLICKED ||
1920 HIWORD(wParam) == BN_DOUBLECLICKED) {
1921 int n, i;
c96a8fef 1922 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC7_BOLDCOLOUR);
1923 n = SendDlgItemMessage (hwnd, IDC7_LIST, LB_GETCOUNT, 0, 0);
374330e2 1924 if (cfg.bold_colour && n!=22) {
1925 for (i=0; i<22; i++)
c96a8fef 1926 if (!permcolour[i])
1927 SendDlgItemMessage (hwnd, IDC7_LIST,
374330e2 1928 LB_INSERTSTRING, i,
1929 (LPARAM) colours[i]);
1930 } else if (!cfg.bold_colour && n!=12) {
1931 for (i=22; i-- ;)
c96a8fef 1932 if (!permcolour[i])
1933 SendDlgItemMessage (hwnd, IDC7_LIST,
374330e2 1934 LB_DELETESTRING, i, 0);
1935 }
1936 }
1937 break;
c96a8fef 1938 case IDC7_PALETTE:
374330e2 1939 if (HIWORD(wParam) == BN_CLICKED ||
1940 HIWORD(wParam) == BN_DOUBLECLICKED)
c96a8fef 1941 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC7_PALETTE);
374330e2 1942 break;
c96a8fef 1943 case IDC7_LIST:
374330e2 1944 if (HIWORD(wParam) == LBN_DBLCLK ||
1945 HIWORD(wParam) == LBN_SELCHANGE) {
c96a8fef 1946 int i = SendDlgItemMessage (hwnd, IDC7_LIST, LB_GETCURSEL,
374330e2 1947 0, 0);
1948 if (!cfg.bold_colour)
1949 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
c96a8fef 1950 SetDlgItemInt (hwnd, IDC7_RVALUE, cfg.colours[i][0], FALSE);
1951 SetDlgItemInt (hwnd, IDC7_GVALUE, cfg.colours[i][1], FALSE);
1952 SetDlgItemInt (hwnd, IDC7_BVALUE, cfg.colours[i][2], FALSE);
374330e2 1953 }
1954 break;
c96a8fef 1955 case IDC7_CHANGE:
374330e2 1956 if (HIWORD(wParam) == BN_CLICKED ||
1957 HIWORD(wParam) == BN_DOUBLECLICKED) {
1958 static CHOOSECOLOR cc;
1959 static DWORD custom[16] = {0}; /* zero initialisers */
c96a8fef 1960 int i = SendDlgItemMessage (hwnd, IDC7_LIST, LB_GETCURSEL,
374330e2 1961 0, 0);
1962 if (!cfg.bold_colour)
1963 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1964 cc.lStructSize = sizeof(cc);
1965 cc.hwndOwner = hwnd;
1d470ad2 1966 cc.hInstance = (HWND)hinst;
374330e2 1967 cc.lpCustColors = custom;
1968 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1969 cfg.colours[i][2]);
1970 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1971 if (ChooseColor(&cc)) {
1972 cfg.colours[i][0] =
1973 (unsigned char) (cc.rgbResult & 0xFF);
1974 cfg.colours[i][1] =
1975 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1976 cfg.colours[i][2] =
1977 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
c96a8fef 1978 SetDlgItemInt (hwnd, IDC7_RVALUE, cfg.colours[i][0],
374330e2 1979 FALSE);
c96a8fef 1980 SetDlgItemInt (hwnd, IDC7_GVALUE, cfg.colours[i][1],
374330e2 1981 FALSE);
c96a8fef 1982 SetDlgItemInt (hwnd, IDC7_BVALUE, cfg.colours[i][2],
374330e2 1983 FALSE);
1984 }
1985 }
1986 break;
c96a8fef 1987 case IDC8_NOXLAT:
1988 case IDC8_KOI8WIN1251:
1989 case IDC8_88592WIN1250:
d3d16feb 1990 cfg.xlat_enablekoiwin =
c96a8fef 1991 IsDlgButtonChecked (hwnd, IDC8_KOI8WIN1251);
d3d16feb 1992 cfg.xlat_88592w1250 =
c96a8fef 1993 IsDlgButtonChecked (hwnd, IDC8_88592WIN1250);
14963b8f 1994 break;
c96a8fef 1995 case IDC8_CAPSLOCKCYR:
14963b8f 1996 if (HIWORD(wParam) == BN_CLICKED ||
1997 HIWORD(wParam) == BN_DOUBLECLICKED) {
1998 cfg.xlat_capslockcyr =
c96a8fef 1999 IsDlgButtonChecked (hwnd, IDC8_CAPSLOCKCYR);
14963b8f 2000 }
2001 break;
c96a8fef 2002 case IDC8_VTXWINDOWS:
2003 case IDC8_VTOEMANSI:
2004 case IDC8_VTOEMONLY:
2005 case IDC8_VTPOORMAN:
c9def1b8 2006 cfg.vtmode =
c96a8fef 2007 (IsDlgButtonChecked (hwnd, IDC8_VTXWINDOWS) ? VT_XWINDOWS :
2008 IsDlgButtonChecked (hwnd, IDC8_VTOEMANSI) ? VT_OEMANSI :
2009 IsDlgButtonChecked (hwnd, IDC8_VTOEMONLY) ? VT_OEMONLY :
c9def1b8 2010 VT_POORMAN);
2011 break;
14963b8f 2012 }
374330e2 2013 return 0;
2014 case WM_CLOSE:
2015 EndDialog (hwnd, 0);
2016 return 0;
c9def1b8 2017
2018 /* Grrr Explorer will maximize Dialogs! */
2019 case WM_SIZE:
2020 if (wParam == SIZE_MAXIMIZED)
2021 force_normal(hwnd);
2022 return 0;
374330e2 2023 }
2024 return 0;
2025}
2026
2027static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2028 WPARAM wParam, LPARAM lParam) {
374330e2 2029 static HWND page = NULL;
2030
2031 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
374330e2 2032 }
c96a8fef 2033 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
374330e2 2034 EnableWindow(hwnd, 0);
2035 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2036 GetParent(hwnd), AboutProc);
2037 EnableWindow(hwnd, 1);
9a70ac47 2038 SetActiveWindow(hwnd);
374330e2 2039 }
c96a8fef 2040 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
374330e2 2041}
2042
2043static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2044 WPARAM wParam, LPARAM lParam) {
2045 static HWND page;
c96a8fef 2046 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
374330e2 2047}
2048
374330e2 2049int do_config (void) {
2050 int ret;
2051
2052 get_sesslist(TRUE);
6584031a 2053 savedsession[0] = '\0';
374330e2 2054 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2055 get_sesslist(FALSE);
2056
2057 return ret;
2058}
2059
2060int do_reconfig (HWND hwnd) {
2061 Config backup_cfg;
2062 int ret;
2063
2064 backup_cfg = cfg; /* structure copy */
2065 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2066 if (!ret)
2067 cfg = backup_cfg; /* structure copy */
c9def1b8 2068 else
2069 force_normal(hwnd);
2070
374330e2 2071 return ret;
2072}
2073
c5e9c988 2074void logevent (char *string) {
2075 if (nevents >= negsize) {
374330e2 2076 negsize += 64;
c5e9c988 2077 events = srealloc (events, negsize * sizeof(*events));
374330e2 2078 }
c5e9c988 2079 events[nevents] = smalloc(1+strlen(string));
2080 strcpy (events[nevents], string);
2081 nevents++;
9ad90448 2082 if (logbox) {
2083 int count;
374330e2 2084 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2085 0, (LPARAM)string);
9ad90448 2086 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
989b10e9 2087 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
9ad90448 2088 }
374330e2 2089}
2090
c5e9c988 2091void showeventlog (HWND hwnd) {
374330e2 2092 if (!logbox) {
2093 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2094 hwnd, LogProc);
2095 ShowWindow (logbox, SW_SHOWNORMAL);
2096 }
2097}
2098
2099void showabout (HWND hwnd) {
2100 if (!abtbox) {
2101 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2102 hwnd, AboutProc);
2103 ShowWindow (abtbox, SW_SHOWNORMAL);
2104 }
2105}
2106
d4857987 2107void verify_ssh_host_key(char *host, int port, char *keytype,
d5859615 2108 char *keystr, char *fingerprint) {
2109 int ret;
374330e2 2110
d5859615 2111 static const char absentmsg[] =
2112 "The server's host key is not cached in the registry. You\n"
2113 "have no guarantee that the server is the computer you\n"
2114 "think it is.\n"
2115 "The server's key fingerprint is:\n"
2116 "%s\n"
2117 "If you trust this host, hit Yes to add the key to\n"
2118 "PuTTY's cache and carry on connecting.\n"
2119 "If you do not trust this host, hit No to abandon the\n"
2120 "connection.\n";
2121
2122 static const char wrongmsg[] =
2123 "WARNING - POTENTIAL SECURITY BREACH!\n"
2124 "\n"
2125 "The server's host key does not match the one PuTTY has\n"
2126 "cached in the registry. This means that either the\n"
2127 "server administrator has changed the host key, or you\n"
2128 "have actually connected to another computer pretending\n"
2129 "to be the server.\n"
2130 "The new key fingerprint is:\n"
2131 "%s\n"
2132 "If you were expecting this change and trust the new key,\n"
2133 "hit Yes to update PuTTY's cache and continue connecting.\n"
2134 "If you want to carry on connecting but without updating\n"
2135 "the cache, hit No.\n"
2136 "If you want to abandon the connection completely, hit\n"
2137 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2138 "choice.\n";
2139
2140 static const char mbtitle[] = "PuTTY Security Alert";
de3df031 2141
d5859615 2142
2143 char message[160+ /* sensible fingerprint max size */
2144 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2145 sizeof(absentmsg) : sizeof(wrongmsg))];
de3df031 2146
2147 /*
d5859615 2148 * Verify the key against the registry.
de3df031 2149 */
d4857987 2150 ret = verify_host_key(host, port, keytype, keystr);
d5859615 2151
2152 if (ret == 0) /* success - key matched OK */
2153 return;
2154 if (ret == 2) { /* key was different */
2155 int mbret;
2156 sprintf(message, wrongmsg, fingerprint);
2157 mbret = MessageBox(NULL, message, mbtitle,
2158 MB_ICONWARNING | MB_YESNOCANCEL);
2159 if (mbret == IDYES)
d4857987 2160 store_host_key(host, port, keytype, keystr);
d5859615 2161 if (mbret == IDCANCEL)
2162 exit(0);
de3df031 2163 }
d5859615 2164 if (ret == 1) { /* key was absent */
2165 int mbret;
2166 sprintf(message, absentmsg, fingerprint);
2167 mbret = MessageBox(NULL, message, mbtitle,
2168 MB_ICONWARNING | MB_YESNO);
2169 if (mbret == IDNO)
2170 exit(0);
d4857987 2171 store_host_key(host, port, keytype, keystr);
de3df031 2172 }
de3df031 2173}