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