19 static char **events
= NULL
;
20 static int nevents
= 0, negsize
= 0;
22 static HWND logbox
= NULL
, abtbox
= NULL
;
24 static HINSTANCE hinst
;
28 static void force_normal(HWND hwnd
)
30 static int recurse
= 0;
37 wp
.length
= sizeof(wp
);
38 if (GetWindowPlacement(hwnd
, &wp
))
40 wp
.showCmd
= SW_SHOWNORMAL
;
41 SetWindowPlacement(hwnd
, &wp
);
46 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
49 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
54 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
55 WPARAM wParam
, LPARAM lParam
) {
60 for (i
=0; i
<nevents
; i
++)
61 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
62 0, (LPARAM
)events
[i
]);
65 switch (LOWORD(wParam
)) {
71 if (HIWORD(wParam
) == BN_CLICKED
||
72 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
75 selcount
= SendDlgItemMessage(hwnd
, IDN_LIST
,
76 LB_GETSELCOUNT
, 0, 0);
77 selitems
= malloc(selcount
* sizeof(int));
79 int count
= SendDlgItemMessage(hwnd
, IDN_LIST
,
81 selcount
, (LPARAM
)selitems
);
85 static unsigned char sel_nl
[] = SEL_NL
;
87 if (count
== 0) { /* can't copy zero stuff */
93 for (i
= 0; i
< count
; i
++)
94 size
+= strlen(events
[selitems
[i
]]) + sizeof(sel_nl
);
96 clipdata
= malloc(size
);
99 for (i
= 0; i
< count
; i
++) {
100 char *q
= events
[selitems
[i
]];
101 int qlen
= strlen(q
);
104 memcpy(p
, sel_nl
, sizeof(sel_nl
));
107 write_clip(clipdata
, size
, TRUE
);
112 for (i
= 0; i
< nevents
; i
++)
113 SendDlgItemMessage(hwnd
, IDN_LIST
, LB_SETSEL
,
122 DestroyWindow (hwnd
);
128 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
129 WPARAM wParam
, LPARAM lParam
) {
134 switch (LOWORD(wParam
)) {
147 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
148 WPARAM wParam
, LPARAM lParam
) {
151 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
154 switch (LOWORD(wParam
)) {
157 DestroyWindow (hwnd
);
160 EnableWindow(hwnd
, 0);
161 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
163 EnableWindow(hwnd
, 1);
164 SetActiveWindow(hwnd
);
170 DestroyWindow (hwnd
);
176 /* ----------------------------------------------------------------------
177 * Routines to self-manage the controls in a dialog box.
185 #define STATICHEIGHT 8
186 #define CHECKBOXHEIGHT 8
187 #define RADIOHEIGHT 8
188 #define EDITHEIGHT 12
189 #define COMBOHEIGHT 12
190 #define PUSHBTNHEIGHT 14
198 int boxystart
, boxid
, boxtextid
;
202 static void ctlposinit(struct ctlpos
*cp
, HWND hwnd
,
203 int leftborder
, int rightborder
, int topborder
) {
206 cp
->font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
207 cp
->ypos
= topborder
;
208 GetClientRect(hwnd
, &r
);
209 r2
.left
= r2
.top
= 0;
212 MapDialogRect(hwnd
, &r2
);
213 cp
->dlu4inpix
= r2
.right
;
214 cp
->width
= (r
.right
* 4) / (r2
.right
) - 2*GAPBETWEEN
;
215 cp
->xoff
= leftborder
;
216 cp
->width
-= leftborder
+ rightborder
;
219 static void doctl(struct ctlpos
*cp
, RECT r
,
220 char *wclass
, int wstyle
, int exstyle
,
221 char *wtext
, int wid
) {
224 * Note nonstandard use of RECT. This is deliberate: by
225 * transforming the width and height directly we arrange to
226 * have all supposedly same-sized controls really same-sized.
230 MapDialogRect(cp
->hwnd
, &r
);
232 ctl
= CreateWindowEx(exstyle
, wclass
, wtext
, wstyle
,
233 r
.left
, r
.top
, r
.right
, r
.bottom
,
234 cp
->hwnd
, (HMENU
)wid
, hinst
, NULL
);
235 SendMessage(ctl
, WM_SETFONT
, cp
->font
, MAKELPARAM(TRUE
, 0));
239 * A title bar across the top of a sub-dialog.
241 static void bartitle(struct ctlpos
*cp
, char *name
, int id
) {
244 r
.left
= GAPBETWEEN
; r
.right
= cp
->width
;
245 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
246 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
247 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, name
, id
);
251 * Begin a grouping box, with or without a group title.
253 static void beginbox(struct ctlpos
*cp
, char *name
, int idbox
, int idtext
) {
255 cp
->ypos
+= STATICHEIGHT
/2;
256 cp
->boxystart
= cp
->ypos
;
258 cp
->ypos
+= STATICHEIGHT
- (STATICHEIGHT
/2);
260 cp
->width
-= 2*GAPXBOX
;
263 cp
->boxtextid
= idtext
;
268 * End a grouping box.
270 static void endbox(struct ctlpos
*cp
) {
273 cp
->width
+= 2*GAPXBOX
;
274 cp
->ypos
+= GAPYBOX
- GAPBETWEEN
;
275 r
.left
= GAPBETWEEN
; r
.right
= cp
->width
;
276 r
.top
= cp
->boxystart
; r
.bottom
= cp
->ypos
- cp
->boxystart
;
277 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDFRAME
, 0,
282 HFONT oldfont
, dlgfont
;
283 hdc
= GetDC(cp
->hwnd
);
284 dlgfont
= (HFONT
)cp
->font
;
285 oldfont
= SelectObject(hdc
, dlgfont
);
286 GetTextExtentPoint32(hdc
, cp
->boxtext
, strlen(cp
->boxtext
), &s
);
287 SelectObject(hdc
, oldfont
);
289 r
.left
= GAPXBOX
+ GAPBETWEEN
;
290 r
.right
= (s
.cx
* 4 + cp
->dlu4inpix
-1) / cp
->dlu4inpix
;
292 r
.top
= cp
->boxystart
- STATICHEIGHT
/2; r
.bottom
= STATICHEIGHT
;
293 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
294 cp
->boxtext
, cp
->boxtextid
);
300 * Some edit boxes. Each one has a static above it. The percentages
301 * of the horizontal space are provided.
303 static void multiedit(struct ctlpos
*cp
, ...) {
312 int staticid
, editid
, pcwidth
;
313 text
= va_arg(ap
, char *);
316 staticid
= va_arg(ap
, int);
317 editid
= va_arg(ap
, int);
318 pcwidth
= va_arg(ap
, int);
320 r
.left
= xpos
+ GAPBETWEEN
;
322 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
323 r
.right
= xpos
- r
.left
;
325 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
326 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
328 r
.top
= cp
->ypos
+ 8 + GAPWITHIN
; r
.bottom
= EDITHEIGHT
;
330 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
335 cp
->ypos
+= 8+GAPWITHIN
+12+GAPBETWEEN
;
339 * A set of radio buttons on the same line, with a static above
340 * them. `nacross' dictates how many parts the line is divided into
341 * (you might want this not to equal the number of buttons if you
342 * needed to line up some 2s and some 3s to look good in the same
345 static void radioline(struct ctlpos
*cp
,
346 char *text
, int id
, int nacross
, ...) {
352 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
353 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
354 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
355 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
356 va_start(ap
, nacross
);
362 btext
= va_arg(ap
, char *);
365 bid
= va_arg(ap
, int);
366 r
.left
= GAPBETWEEN
+ i
* (cp
->width
+GAPBETWEEN
)/nacross
;
367 r
.right
= (i
+1) * (cp
->width
+GAPBETWEEN
)/nacross
- r
.left
;
368 r
.top
= cp
->ypos
; r
.bottom
= RADIOHEIGHT
;
369 doctl(cp
, r
, "BUTTON",
370 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
377 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
381 * A set of radio buttons on multiple lines, with a static above
384 static void radiobig(struct ctlpos
*cp
, char *text
, int id
, ...) {
389 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
390 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
391 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
392 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
398 btext
= va_arg(ap
, char *);
401 bid
= va_arg(ap
, int);
402 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
403 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
404 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
405 doctl(cp
, r
, "BUTTON",
406 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
412 cp
->ypos
+= GAPBETWEEN
- GAPWITHIN
;
416 * A single standalone checkbox.
418 static void checkbox(struct ctlpos
*cp
, char *text
, int id
) {
421 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
422 r
.right
= cp
->width
; r
.bottom
= CHECKBOXHEIGHT
;
423 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
424 doctl(cp
, r
, "BUTTON",
425 BS_AUTOCHECKBOX
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
, 0,
430 * A button on the right hand side, with a static to its left.
432 static void staticbtn(struct ctlpos
*cp
, char *stext
, int sid
,
433 char *btext
, int bid
) {
434 const int height
= (PUSHBTNHEIGHT
> STATICHEIGHT ?
435 PUSHBTNHEIGHT
: STATICHEIGHT
);
437 int lwid
, rwid
, rpos
;
439 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
440 lwid
= rpos
- 2*GAPBETWEEN
;
441 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
443 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
444 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
445 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
447 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
448 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
449 doctl(cp
, r
, "BUTTON",
450 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
454 cp
->ypos
+= height
+ GAPBETWEEN
;
458 * An edit control on the right hand side, with a static to its left.
460 static void staticedit(struct ctlpos
*cp
, char *stext
,
461 int sid
, int eid
, int percentedit
) {
462 const int height
= (EDITHEIGHT
> STATICHEIGHT ?
463 EDITHEIGHT
: STATICHEIGHT
);
465 int lwid
, rwid
, rpos
;
467 rpos
= GAPBETWEEN
+ (100-percentedit
) * (cp
->width
+ GAPBETWEEN
) / 100;
468 lwid
= rpos
- 2*GAPBETWEEN
;
469 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
471 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
472 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
473 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
475 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
476 r
.right
= rwid
; r
.bottom
= EDITHEIGHT
;
478 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
482 cp
->ypos
+= height
+ GAPBETWEEN
;
486 * A tab-control substitute when a real tab control is unavailable.
488 static void ersatztab(struct ctlpos
*cp
, char *stext
, int sid
,
490 const int height
= (COMBOHEIGHT
> STATICHEIGHT ?
491 COMBOHEIGHT
: STATICHEIGHT
);
493 int bigwid
, lwid
, rwid
, rpos
;
494 static const int BIGGAP
= 15;
495 static const int MEDGAP
= 3;
497 bigwid
= cp
->width
+ 2*GAPBETWEEN
- 2*BIGGAP
;
499 rpos
= BIGGAP
+ (bigwid
+ BIGGAP
) / 2;
500 lwid
= rpos
- 2*BIGGAP
;
501 rwid
= bigwid
+ BIGGAP
- rpos
;
503 r
.left
= BIGGAP
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
504 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
505 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
507 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-COMBOHEIGHT
)/2;
508 r
.right
= rwid
; r
.bottom
= COMBOHEIGHT
*10;
509 doctl(cp
, r
, "COMBOBOX",
510 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
511 CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
515 cp
->ypos
+= height
+ MEDGAP
+ GAPBETWEEN
;
517 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
518 r
.right
= cp
->width
; r
.bottom
= 2;
519 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDHORZ
,
524 * A static line, followed by an edit control on the left hand side
525 * and a button on the right.
527 static void editbutton(struct ctlpos
*cp
, char *stext
, int sid
,
528 int eid
, char *btext
, int bid
) {
529 const int height
= (EDITHEIGHT
> PUSHBTNHEIGHT ?
530 EDITHEIGHT
: PUSHBTNHEIGHT
);
532 int lwid
, rwid
, rpos
;
534 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
535 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
536 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
537 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
539 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
540 lwid
= rpos
- 2*GAPBETWEEN
;
541 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
543 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
544 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
546 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
550 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
551 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
552 doctl(cp
, r
, "BUTTON",
553 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
557 cp
->ypos
+= height
+ GAPBETWEEN
;
561 * Special control which was hard to describe generically: the
562 * session-saver assembly. A static; below that an edit box; below
563 * that a list box. To the right of the list box, a column of
566 static void sesssaver(struct ctlpos
*cp
, char *text
,
567 int staticid
, int editid
, int listid
, ...) {
570 int lwid
, rwid
, rpos
;
572 const int LISTDEFHEIGHT
= 66;
574 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
575 lwid
= rpos
- 2*GAPBETWEEN
;
576 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
578 /* The static control. */
579 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
580 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
581 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
582 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
584 /* The edit control. */
585 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
586 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
587 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
589 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
594 * The buttons (we should hold off on the list box until we
595 * know how big the buttons are).
597 va_start(ap
, listid
);
600 char *btext
= va_arg(ap
, char *);
603 bid
= va_arg(ap
, int);
604 r
.left
= rpos
; r
.top
= y
;
605 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
606 y
+= r
.bottom
+ GAPWITHIN
;
607 doctl(cp
, r
, "BUTTON",
608 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
613 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
616 if (y
< LISTDEFHEIGHT
) y
= LISTDEFHEIGHT
;
617 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
618 r
.right
= lwid
; r
.bottom
= y
;
619 cp
->ypos
+= y
+ GAPBETWEEN
;
620 doctl(cp
, r
, "LISTBOX",
621 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
|
622 LBS_NOTIFY
| LBS_HASSTRINGS
,
628 * Another special control: the environment-variable setter. A
629 * static line first; then a pair of edit boxes with associated
630 * statics, and two buttons; then a list box.
632 static void envsetter(struct ctlpos
*cp
, char *stext
, int sid
,
633 char *e1stext
, int e1sid
, int e1id
,
634 char *e2stext
, int e2sid
, int e2id
,
636 char *b1text
, int b1id
, char *b2text
, int b2id
) {
638 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
640 EDITHEIGHT
> PUSHBTNHEIGHT ?
641 EDITHEIGHT
: PUSHBTNHEIGHT
);
642 const static int percents
[] = { 20, 35, 10, 25 };
643 int i
, j
, xpos
, percent
;
644 const int LISTHEIGHT
= 42;
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
);
652 /* The statics+edits+buttons. */
653 for (j
= 0; j
< 2; j
++) {
655 for (i
= 0; i
< 4; i
++) {
656 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
657 r
.left
= xpos
+ GAPBETWEEN
;
658 percent
+= percents
[i
];
659 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
660 r
.right
= xpos
- r
.left
;
662 r
.bottom
= (i
==0 ? STATICHEIGHT
:
665 r
.top
+= (height
-r
.bottom
)/2;
667 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
668 j
==0 ? e1stext
: e2stext
, j
==0 ? e1sid
: e2sid
);
671 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
673 "", j
==0 ? e1id
: e2id
);
675 doctl(cp
, r
, "BUTTON",
676 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
678 j
==0 ? b1text
: b2text
, j
==0 ? b1id
: b2id
);
681 cp
->ypos
+= height
+ GAPWITHIN
;
685 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
686 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
687 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
688 doctl(cp
, r
, "LISTBOX",
689 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
696 * Yet another special control: the character-class setter. A
697 * static, then a list, then a line containing a
698 * button-and-static-and-edit.
700 static void charclass(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
701 char *btext
, int bid
, int eid
, char *s2text
, int s2id
) {
703 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
705 EDITHEIGHT
> PUSHBTNHEIGHT ?
706 EDITHEIGHT
: PUSHBTNHEIGHT
);
707 const static int percents
[] = { 30, 40, 30 };
708 int i
, xpos
, percent
;
709 const int LISTHEIGHT
= 66;
711 /* The static control. */
712 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
713 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
714 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
715 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
718 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
719 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
720 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
721 doctl(cp
, r
, "LISTBOX",
722 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
727 /* The button+static+edit. */
729 for (i
= 0; i
< 3; i
++) {
730 r
.left
= xpos
+ GAPBETWEEN
;
731 percent
+= percents
[i
];
732 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
733 r
.right
= xpos
- r
.left
;
735 r
.bottom
= (i
==0 ? PUSHBTNHEIGHT
:
736 i
==1 ? STATICHEIGHT
:
738 r
.top
+= (height
-r
.bottom
)/2;
740 doctl(cp
, r
, "BUTTON",
741 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
744 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
748 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
749 WS_EX_CLIENTEDGE
, "", eid
);
752 cp
->ypos
+= height
+ GAPBETWEEN
;
756 * A special control (horrors!). The colour editor. A static line;
757 * then on the left, a list box, and on the right, a sequence of
758 * two-part statics followed by a button.
760 static void colouredit(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
761 char *btext
, int bid
, ...) {
765 int lwid
, rwid
, rpos
;
766 const int LISTHEIGHT
= 66;
768 /* The static control. */
769 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
770 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
771 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
772 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
774 rpos
= GAPBETWEEN
+ 2 * (cp
->width
+ GAPBETWEEN
) / 3;
775 lwid
= rpos
- 2*GAPBETWEEN
;
776 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
779 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
780 r
.right
= lwid
; r
.bottom
= LISTHEIGHT
;
781 doctl(cp
, r
, "LISTBOX",
782 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
793 ltext
= va_arg(ap
, char *);
795 lid
= va_arg(ap
, int);
796 rid
= va_arg(ap
, int);
797 r
.top
= y
; r
.bottom
= STATICHEIGHT
;
798 y
+= r
.bottom
+ GAPWITHIN
;
799 r
.left
= rpos
; r
.right
= rwid
/2;
800 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, ltext
, lid
);
801 r
.left
= rpos
+ r
.right
; r
.right
= rwid
- r
.right
;
802 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_RIGHT
, 0, "", rid
);
807 r
.top
= y
+ 2*GAPWITHIN
; r
.bottom
= PUSHBTNHEIGHT
;
808 r
.left
= rpos
; r
.right
= rwid
;
809 doctl(cp
, r
, "BUTTON",
810 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
813 cp
->ypos
+= LISTHEIGHT
+ GAPBETWEEN
;
816 static char savedsession
[2048];
818 enum { IDCX_ABOUT
= IDC_ABOUT
, IDCX_TVSTATIC
, IDCX_TREEVIEW
, controlstartvalue
,
822 IDC_BOX_SESSION1
, IDC_BOXT_SESSION1
,
823 IDC_BOX_SESSION2
, IDC_BOXT_SESSION2
,
844 IDC_BOX_KEYBOARD1
, IDC_BOXT_KEYBOARD1
,
845 IDC_BOX_KEYBOARD2
, IDC_BOXT_KEYBOARD2
,
868 IDC_BOX_TERMINAL1
, IDC_BOXT_TERMINAL1
,
869 IDC_BOX_TERMINAL2
, IDC_BOXT_TERMINAL2
,
870 IDC_BOX_TERMINAL3
, IDC_BOXT_TERMINAL3
,
890 IDC_BOX_WINDOW1
, IDC_BOXT_WINDOW1
,
891 IDC_BOX_WINDOW2
, IDC_BOXT_WINDOW2
,
892 IDC_BOX_WINDOW3
, IDC_BOXT_WINDOW3
,
907 connectionpanelstart
,
908 IDC_TITLE_CONNECTION
,
909 IDC_BOX_CONNECTION1
, IDC_BOXT_CONNECTION1
,
910 IDC_BOX_CONNECTION2
, IDC_BOXT_CONNECTION2
,
921 IDC_BOX_TELNET1
, IDC_BOXT_TELNET1
,
922 IDC_BOX_TELNET2
, IDC_BOXT_TELNET2
,
940 IDC_BOX_SSH1
, IDC_BOXT_SSH1
,
941 IDC_BOX_SSH2
, IDC_BOXT_SSH2
,
942 IDC_BOX_SSH3
, IDC_BOXT_SSH3
,
962 IDC_BOX_SELECTION1
, IDC_BOXT_SELECTION1
,
963 IDC_BOX_SELECTION2
, IDC_BOXT_SELECTION2
,
976 IDC_BOX_COLOURS1
, IDC_BOXT_COLOURS1
,
977 IDC_BOX_COLOURS2
, IDC_BOXT_COLOURS2
,
991 translationpanelstart
,
992 IDC_TITLE_TRANSLATION
,
993 IDC_BOX_TRANSLATION1
, IDC_BOXT_TRANSLATION1
,
994 IDC_BOX_TRANSLATION2
, IDC_BOXT_TRANSLATION2
,
995 IDC_BOX_TRANSLATION3
, IDC_BOXT_TRANSLATION3
,
1006 translationpanelend
,
1011 static const char *const colours
[] = {
1012 "Default Foreground", "Default Bold Foreground",
1013 "Default Background", "Default Bold Background",
1014 "Cursor Text", "Cursor Colour",
1015 "ANSI Black", "ANSI Black Bold",
1016 "ANSI Red", "ANSI Red Bold",
1017 "ANSI Green", "ANSI Green Bold",
1018 "ANSI Yellow", "ANSI Yellow Bold",
1019 "ANSI Blue", "ANSI Blue Bold",
1020 "ANSI Magenta", "ANSI Magenta Bold",
1021 "ANSI Cyan", "ANSI Cyan Bold",
1022 "ANSI White", "ANSI White Bold"
1024 static const int permcolour
[] = {
1025 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1026 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1027 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1030 static void fmtfont (char *buf
) {
1031 sprintf (buf
, "Font: %s, ", cfg
.font
);
1033 strcat(buf
, "bold, ");
1034 if (cfg
.fontheight
== 0)
1035 strcat (buf
, "default height");
1037 sprintf (buf
+strlen(buf
), "%d-%s",
1038 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1039 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1042 static void init_dlg_ctrls(HWND hwnd
) {
1044 char fontstatic
[256];
1046 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1047 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
1048 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1049 for (i
= 0; i
< nsessions
; i
++)
1050 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1051 0, (LPARAM
) (sessions
[i
]));
1052 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1053 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1054 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
1055 SetDlgItemInt (hwnd
, IDC_PINGEDIT
, cfg
.ping_interval
, FALSE
);
1057 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1058 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1059 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1060 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1061 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCXTERM
,
1062 cfg
.funky_type
== 0 ? IDC_FUNCTILDE
:
1063 cfg
.funky_type
== 1 ? IDC_FUNCLINUX
:
1064 cfg
.funky_type
== 2 ? IDC_FUNCXTERM
:
1065 cfg
.funky_type
== 3 ? IDC_FUNCVT400
:
1067 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1068 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1069 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1070 cfg
.nethack_keypad ? IDC_KPNH
:
1071 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1072 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1073 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1074 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1075 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1077 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1078 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1079 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1080 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1081 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1082 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1083 fmtfont (fontstatic
);
1084 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1085 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1086 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1087 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1089 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1090 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1091 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1092 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1093 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1094 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1095 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1097 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1098 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1099 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1101 char *p
= cfg
.environmt
;
1103 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1108 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1109 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1111 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1112 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1113 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1114 CheckDlgButton (hwnd
, IDC_AGENTFWD
, cfg
.agentfwd
);
1115 CheckRadioButton (hwnd
, IDC_CIPHER3DES
, IDC_CIPHERDES
,
1116 cfg
.cipher
== CIPHER_BLOWFISH ? IDC_CIPHERBLOWF
:
1117 cfg
.cipher
== CIPHER_DES ? IDC_CIPHERDES
:
1119 CheckRadioButton (hwnd
, IDC_SSHPROT1
, IDC_SSHPROT2
,
1120 cfg
.sshprot
== 1 ? IDC_SSHPROT1
: IDC_SSHPROT2
);
1121 CheckDlgButton (hwnd
, IDC_AUTHTIS
, cfg
.try_tis_auth
);
1122 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1123 SetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
);
1125 CheckRadioButton (hwnd
, IDC_MBWINDOWS
, IDC_MBXTERM
,
1126 cfg
.mouse_is_xterm ? IDC_MBXTERM
: IDC_MBWINDOWS
);
1128 static int tabs
[4] = {25, 61, 96, 128};
1129 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_SETTABSTOPS
, 4,
1132 for (i
=0; i
<256; i
++) {
1134 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1135 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1137 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_ADDSTRING
, 0,
1141 CheckDlgButton (hwnd
, IDC_BOLDCOLOUR
, cfg
.bold_colour
);
1142 CheckDlgButton (hwnd
, IDC_PALETTE
, cfg
.try_palette
);
1145 for (i
=0; i
<22; i
++)
1146 if (cfg
.bold_colour
|| permcolour
[i
])
1147 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_ADDSTRING
, 0,
1148 (LPARAM
) colours
[i
]);
1150 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_SETCURSEL
, 0, 0);
1151 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[0][0], FALSE
);
1152 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[0][1], FALSE
);
1153 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[0][2], FALSE
);
1155 CheckRadioButton (hwnd
, IDC_NOXLAT
, IDC_88592WIN1250
,
1156 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
1157 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
1159 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1160 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
1161 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
1162 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
1163 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
1167 static void hide(HWND hwnd
, int hide
, int minid
, int maxid
) {
1169 for (i
= minid
; i
< maxid
; i
++) {
1170 HWND ctl
= GetDlgItem(hwnd
, i
);
1172 ShowWindow(ctl
, hide ? SW_HIDE
: SW_SHOW
);
1177 struct treeview_faff
{
1179 HTREEITEM lastat
[4];
1182 static HTREEITEM
treeview_insert(struct treeview_faff
*faff
,
1183 int level
, char *text
) {
1187 ins
.hParent
= (level
> 0 ? faff
->lastat
[level
-1] : TVI_ROOT
);
1188 ins
.hInsertAfter
= faff
->lastat
[level
];
1189 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
1190 #define INSITEM DUMMYUNIONNAME.item
1192 #define INSITEM item
1194 ins
.INSITEM
.mask
= TVIF_TEXT
;
1195 ins
.INSITEM
.pszText
= text
;
1196 newitem
= TreeView_InsertItem(faff
->treeview
, &ins
);
1198 TreeView_Expand(faff
->treeview
, faff
->lastat
[level
-1], TVE_EXPAND
);
1199 faff
->lastat
[level
] = newitem
;
1200 for (i
= level
+1; i
< 4; i
++) faff
->lastat
[i
] = NULL
;
1205 * This _huge_ function is the configuration box.
1207 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1208 WPARAM wParam
, LPARAM lParam
,
1211 struct treeview_faff tvfaff
;
1214 char filename
[sizeof(cfg
.keyfile
)];
1217 char fontstatic
[256];
1222 SetWindowLong(hwnd
, GWL_USERDATA
, 0);
1224 * Centre the window.
1226 { /* centre the window */
1229 hw
= GetDesktopWindow();
1230 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1231 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1232 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1233 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1237 * Create the tree view.
1244 r
.left
= 3; r
.right
= r
.left
+ 75;
1245 r
.top
= 3; r
.bottom
= r
.top
+ 10;
1246 MapDialogRect(hwnd
, &r
);
1247 tvstatic
= CreateWindowEx(0, "STATIC", "Cate&gory:",
1248 WS_CHILD
| WS_VISIBLE
,
1250 r
.right
-r
.left
, r
.bottom
-r
.top
,
1251 hwnd
, (HMENU
)IDCX_TVSTATIC
, hinst
, NULL
);
1252 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1253 SendMessage(tvstatic
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
1255 r
.left
= 3; r
.right
= r
.left
+ 75;
1256 r
.top
= 13; r
.bottom
= r
.top
+ 196;
1257 MapDialogRect(hwnd
, &r
);
1258 treeview
= CreateWindowEx(WS_EX_CLIENTEDGE
, WC_TREEVIEW
, "",
1259 WS_CHILD
| WS_VISIBLE
|
1260 WS_TABSTOP
| TVS_HASLINES
|
1261 TVS_DISABLEDRAGDROP
| TVS_HASBUTTONS
|
1262 TVS_LINESATROOT
| TVS_SHOWSELALWAYS
,
1264 r
.right
-r
.left
, r
.bottom
-r
.top
,
1265 hwnd
, (HMENU
)IDCX_TREEVIEW
, hinst
, NULL
);
1266 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1267 SendMessage(treeview
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
1268 tvfaff
.treeview
= treeview
;
1269 memset(tvfaff
.lastat
, 0, sizeof(tvfaff
.lastat
));
1273 * Create the various panelfuls of controls.
1276 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1279 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1280 bartitle(&cp
, "Basic options for your PuTTY session",
1283 beginbox(&cp
, "Specify your connection by host name",
1284 IDC_BOX_SESSION1
, IDC_BOXT_SESSION1
);
1286 "Host &Name", IDC_HOSTSTATIC
, IDC_HOST
, 75,
1287 "&Port", IDC_PORTSTATIC
, IDC_PORT
, 25, NULL
);
1288 if (backends
[2].backend
== NULL
) {
1289 /* this is PuTTYtel, so only two protocols available */
1290 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1291 "&Raw", IDC_PROTRAW
,
1292 "&Telnet", IDC_PROTTELNET
, NULL
);
1294 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1295 "&Raw", IDC_PROTRAW
,
1296 "&Telnet", IDC_PROTTELNET
,
1305 beginbox(&cp
, "Load, save or delete a stored session",
1306 IDC_BOX_SESSION2
, IDC_BOXT_SESSION2
);
1307 sesssaver(&cp
, "Stor&ed Sessions",
1308 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
1309 "&Load", IDC_SESSLOAD
,
1310 "&Save", IDC_SESSSAVE
,
1311 "&Delete", IDC_SESSDEL
, NULL
);
1314 beginbox(&cp
, NULL
, IDC_BOX_SESSION3
, 0);
1315 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
1318 hsession
= treeview_insert(&tvfaff
, 0, "Session");
1321 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1324 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1325 bartitle(&cp
, "Options controlling the terminal emulation",
1326 IDC_TITLE_TERMINAL
);
1327 beginbox(&cp
, "Set the size of the terminal window",
1328 IDC_BOX_TERMINAL1
, IDC_BOXT_TERMINAL1
);
1330 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 50,
1331 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 50,
1333 checkbox(&cp
, "Loc&k window size against resizing", IDC_LOCKSIZE
);
1335 beginbox(&cp
, "Set the font used in the terminal window",
1336 IDC_BOX_TERMINAL2
, IDC_BOXT_TERMINAL2
);
1337 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1339 beginbox(&cp
, "Set various terminal options",
1340 IDC_BOX_TERMINAL3
, IDC_BOXT_TERMINAL3
);
1341 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1342 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1343 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1344 checkbox(&cp
, "&Beep enabled", IDC_BEEP
);
1345 checkbox(&cp
, "Use background colour to &erase screen", IDC_BCE
);
1346 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1347 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1350 treeview_insert(&tvfaff
, 0, "Terminal");
1353 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1356 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1357 bartitle(&cp
, "Options controlling the effects of keys",
1358 IDC_TITLE_KEYBOARD
);
1359 beginbox(&cp
, "Change the sequences sent by:",
1360 IDC_BOX_KEYBOARD1
, IDC_BOXT_KEYBOARD1
);
1361 radioline(&cp
, "The Backspace key", IDC_DELSTATIC
, 2,
1362 "Control-&H", IDC_DEL008
,
1363 "Control-&? (127)", IDC_DEL127
, NULL
);
1364 radioline(&cp
, "The Home and End keys", IDC_HOMESTATIC
, 2,
1365 "&Standard", IDC_HOMETILDE
,
1366 "&rxvt", IDC_HOMERXVT
, NULL
);
1367 radioline(&cp
, "The Function keys and keypad", IDC_FUNCSTATIC
, 4,
1368 "&VT400", IDC_FUNCTILDE
,
1369 "&Linux", IDC_FUNCLINUX
,
1370 "&Xterm R6", IDC_FUNCXTERM
,
1371 "&VT400", IDC_FUNCVT400
, NULL
);
1373 beginbox(&cp
, "Change the initial state of:",
1374 IDC_BOX_KEYBOARD2
, IDC_BOXT_KEYBOARD2
);
1375 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1376 "&Normal", IDC_CURNORMAL
,
1377 "A&pplication", IDC_CURAPPLIC
, NULL
);
1378 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1379 "Nor&mal", IDC_KPNORMAL
,
1380 "Appl&ication", IDC_KPAPPLIC
,
1381 "N&etHack", IDC_KPNH
, NULL
);
1384 treeview_insert(&tvfaff
, 1, "Keyboard");
1387 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1390 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1391 bartitle(&cp
, "Options controlling PuTTY's window",
1393 beginbox(&cp
, "Adjust the use of the window title",
1394 IDC_BOX_WINDOW1
, IDC_BOXT_WINDOW1
);
1397 "Initial window &title:", IDC_WINTITLE
,
1398 IDC_WINEDIT
, 100, NULL
);
1399 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1401 beginbox(&cp
, "Adjust the use of the cursor",
1402 IDC_BOX_WINDOW2
, IDC_BOXT_WINDOW2
);
1403 checkbox(&cp
, "Cursor &blinks", IDC_BLINKCUR
);
1405 beginbox(&cp
, "Control the scrollback in the window",
1406 IDC_BOX_WINDOW3
, IDC_BOXT_WINDOW3
);
1407 staticedit(&cp
, "Lines of &scrollback",
1408 IDC_SAVESTATIC
, IDC_SAVEEDIT
, 50);
1409 checkbox(&cp
, "&Display scrollbar", IDC_SCROLLBAR
);
1410 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1412 beginbox(&cp
, NULL
, IDC_BOX_WINDOW4
, 0);
1413 checkbox(&cp
, "&Warn before closing window", IDC_CLOSEWARN
);
1414 checkbox(&cp
, "Window closes on ALT-F&4", IDC_ALTF4
);
1415 checkbox(&cp
, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE
);
1418 treeview_insert(&tvfaff
, 0, "Window");
1421 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1424 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1425 bartitle(&cp
, "Options controlling character set translation",
1426 IDC_TITLE_TRANSLATION
);
1427 beginbox(&cp
, "Adjust how PuTTY displays line drawing characters",
1428 IDC_BOX_TRANSLATION1
, IDC_BOXT_TRANSLATION1
);
1430 "Handling of line drawing characters:", IDC_VTSTATIC
,
1431 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
1432 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
1433 "Use font in O&EM mode only", IDC_VTOEMONLY
,
1434 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1435 IDC_VTPOORMAN
, NULL
);
1437 beginbox(&cp
, "Enable character set translation on received data",
1438 IDC_BOX_TRANSLATION2
, IDC_BOXT_TRANSLATION2
);
1440 "Character set translation:", IDC_XLATSTATIC
,
1441 "&None", IDC_NOXLAT
,
1442 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
1443 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
, NULL
);
1445 beginbox(&cp
, "Enable character set translation on input data",
1446 IDC_BOX_TRANSLATION3
, IDC_BOXT_TRANSLATION3
);
1447 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch",
1451 treeview_insert(&tvfaff
, 1, "Translation");
1454 /* The Selection panel. Accelerators used: [acgo] wxst */
1457 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1458 bartitle(&cp
, "Options controlling copy and paste",
1459 IDC_TITLE_SELECTION
);
1460 beginbox(&cp
, "Control which mouse button does which thing",
1461 IDC_BOX_SELECTION1
, IDC_BOXT_SELECTION1
);
1462 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1463 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1464 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1467 beginbox(&cp
, "Control the select-one-word-at-a-time mode",
1468 IDC_BOX_SELECTION2
, IDC_BOXT_SELECTION2
);
1469 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1470 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1471 "&to class", IDC_CCSTATIC2
);
1474 treeview_insert(&tvfaff
, 1, "Selection");
1477 /* The Colours panel. Accelerators used: [acgo] blum */
1480 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1481 bartitle(&cp
, "Options controlling use of colours",
1483 beginbox(&cp
, "General options for colour usage",
1484 IDC_BOX_COLOURS1
, IDC_BOXT_COLOURS1
);
1485 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
1486 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
1488 beginbox(&cp
, "Adjust the precise colours PuTTY displays",
1489 IDC_BOX_COLOURS2
, IDC_BOXT_COLOURS2
);
1490 colouredit(&cp
, "Select a colo&ur and then click to modify it:",
1491 IDC_STATIC
, IDC_LIST
,
1492 "&Modify...", IDC_CHANGE
,
1493 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
1494 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
1495 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
1498 treeview_insert(&tvfaff
, 1, "Colours");
1501 /* The Connection panel. Accelerators used: [acgo] tuk */
1504 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1505 bartitle(&cp
, "Options controlling the connection", IDC_TITLE_CONNECTION
);
1507 beginbox(&cp
, "Data to send to the server",
1508 IDC_BOX_CONNECTION1
, IDC_BOXT_CONNECTION1
);
1509 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
, 50);
1510 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
, 50);
1513 beginbox(&cp
, "Sending of null packets to keep session active",
1514 IDC_BOX_CONNECTION2
, IDC_BOXT_CONNECTION2
);
1515 staticedit(&cp
, "Minutes between &keepalives (0 to turn off)",
1516 IDC_PINGSTATIC
, IDC_PINGEDIT
, 25);
1519 treeview_insert(&tvfaff
, 0, "Connection");
1522 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1525 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1527 bartitle(&cp
, "Options controlling Telnet connections", IDC_TITLE_TELNET
);
1528 beginbox(&cp
, "Data to send to the server",
1529 IDC_BOX_TELNET1
, IDC_BOXT_TELNET1
);
1530 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
, 50);
1531 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1532 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1533 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1535 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1537 beginbox(&cp
, "Telnet protocol adjustments",
1538 IDC_BOX_TELNET2
, IDC_BOXT_TELNET2
);
1539 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1540 "&BSD (commonplace)", IDC_EMBSD
,
1541 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1544 treeview_insert(&tvfaff
, 1, "Telnet");
1548 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1551 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1553 bartitle(&cp
, "Options controlling SSH connections", IDC_TITLE_SSH
);
1554 beginbox(&cp
, "Data to send to the server",
1555 IDC_BOX_SSH1
, IDC_BOXT_SSH1
);
1557 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1560 beginbox(&cp
, "Authentication options",
1561 IDC_BOX_SSH2
, IDC_BOXT_SSH2
);
1562 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1564 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1565 editbutton(&cp
, "Private &key file for authentication:",
1566 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1568 beginbox(&cp
, "Protocol options",
1569 IDC_BOX_SSH3
, IDC_BOXT_SSH3
);
1570 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1571 radioline(&cp
, "Preferred SSH protocol version:",
1572 IDC_SSHPROTSTATIC
, 2,
1573 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1574 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1575 "&3DES", IDC_CIPHER3DES
,
1576 "&Blowfish", IDC_CIPHERBLOWF
,
1577 "&DES", IDC_CIPHERDES
, NULL
);
1580 treeview_insert(&tvfaff
, 1, "SSH");
1584 init_dlg_ctrls(hwnd
);
1587 * Hide all the controls to start with.
1589 hide(hwnd
, TRUE
, controlstartvalue
, controlendvalue
);
1592 * Put the treeview selection on to the Session panel. This
1593 * should also cause unhiding of the relevant controls.
1595 TreeView_SelectItem(treeview
, hsession
);
1598 * Set focus into the first available control.
1602 ctl
= GetDlgItem(hwnd
, IDC_HOST
);
1603 if (!ctl
) ctl
= GetDlgItem(hwnd
, IDC_CLOSEEXIT
);
1607 SetWindowLong(hwnd
, GWL_USERDATA
, 1);
1611 * Button release should trigger WM_OK if there was a
1612 * previous double click on the session list.
1616 SendMessage (hwnd
, WM_COMMAND
, IDOK
, 0);
1619 if (LOWORD(wParam
) == IDCX_TREEVIEW
&&
1620 ((LPNMHDR
)lParam
)->code
== TVN_SELCHANGED
) {
1621 HTREEITEM i
= TreeView_GetSelection(((LPNMHDR
)lParam
)->hwndFrom
);
1625 item
.pszText
= buffer
;
1626 item
.cchTextMax
= sizeof(buffer
);
1627 item
.mask
= TVIF_TEXT
;
1628 TreeView_GetItem(((LPNMHDR
)lParam
)->hwndFrom
, &item
);
1629 hide(hwnd
, TRUE
, controlstartvalue
, controlendvalue
);
1630 if (!strcmp(buffer
, "Session"))
1631 hide(hwnd
, FALSE
, sessionpanelstart
, sessionpanelend
);
1632 if (!strcmp(buffer
, "Keyboard"))
1633 hide(hwnd
, FALSE
, keyboardpanelstart
, keyboardpanelend
);
1634 if (!strcmp(buffer
, "Terminal"))
1635 hide(hwnd
, FALSE
, terminalpanelstart
, terminalpanelend
);
1636 if (!strcmp(buffer
, "Window"))
1637 hide(hwnd
, FALSE
, windowpanelstart
, windowpanelend
);
1638 if (!strcmp(buffer
, "Connection"))
1639 hide(hwnd
, FALSE
, connectionpanelstart
, connectionpanelend
);
1640 if (!strcmp(buffer
, "Telnet"))
1641 hide(hwnd
, FALSE
, telnetpanelstart
, telnetpanelend
);
1642 if (!strcmp(buffer
, "SSH"))
1643 hide(hwnd
, FALSE
, sshpanelstart
, sshpanelend
);
1644 if (!strcmp(buffer
, "Selection"))
1645 hide(hwnd
, FALSE
, selectionpanelstart
, selectionpanelend
);
1646 if (!strcmp(buffer
, "Colours"))
1647 hide(hwnd
, FALSE
, colourspanelstart
, colourspanelend
);
1648 if (!strcmp(buffer
, "Translation"))
1649 hide(hwnd
, FALSE
, translationpanelstart
, translationpanelend
);
1651 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1657 * Only process WM_COMMAND once the dialog is fully formed.
1659 if (GetWindowLong(hwnd
, GWL_USERDATA
) == 1) switch (LOWORD(wParam
)) {
1662 EndDialog (hwnd
, 1);
1667 EndDialog (hwnd
, 0);
1669 case IDC_PROTTELNET
:
1672 if (HIWORD(wParam
) == BN_CLICKED
||
1673 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1674 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
1675 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
1676 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
1677 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
1678 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
1679 cfg
.port
= i ?
22 : 23;
1680 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1685 if (HIWORD(wParam
) == EN_CHANGE
)
1686 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
1687 sizeof(cfg
.host
)-1);
1690 if (HIWORD(wParam
) == EN_CHANGE
)
1691 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
1694 if (HIWORD(wParam
) == EN_CHANGE
) {
1695 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1697 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
1698 savedsession
, sizeof(savedsession
)-1);
1699 savedsession
[sizeof(savedsession
)-1] = '\0';
1703 if (HIWORD(wParam
) == BN_CLICKED
||
1704 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1709 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
1711 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1712 LB_GETCURSEL
, 0, 0);
1717 strcpy (str
, sessions
[n
]);
1719 save_settings (str
, !!strcmp(str
, "Default Settings"), &cfg
);
1720 get_sesslist (FALSE
);
1721 get_sesslist (TRUE
);
1722 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1724 for (i
= 0; i
< nsessions
; i
++)
1725 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1726 0, (LPARAM
) (sessions
[i
]));
1727 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1733 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
1734 HIWORD(wParam
) != BN_CLICKED
&&
1735 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1737 if (LOWORD(wParam
) == IDC_SESSLIST
&&
1738 HIWORD(wParam
) != LBN_DBLCLK
)
1741 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1742 LB_GETCURSEL
, 0, 0);
1747 load_settings (sessions
[n
],
1748 !!strcmp(sessions
[n
], "Default Settings"),
1750 init_dlg_ctrls(hwnd
);
1752 if (LOWORD(wParam
) == IDC_SESSLIST
) {
1754 * A double-click on a saved session should
1755 * actually start the session, not just load it.
1756 * Unless it's Default Settings or some other
1757 * host-less set of saved settings.
1766 if (HIWORD(wParam
) == BN_CLICKED
||
1767 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1768 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1769 LB_GETCURSEL
, 0, 0);
1770 if (n
== LB_ERR
|| n
== 0) {
1774 del_settings(sessions
[n
]);
1775 get_sesslist (FALSE
);
1776 get_sesslist (TRUE
);
1777 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1779 for (i
= 0; i
< nsessions
; i
++)
1780 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1781 0, (LPARAM
) (sessions
[i
]));
1782 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1786 if (HIWORD(wParam
) == EN_CHANGE
)
1787 MyGetDlgItemInt (hwnd
, IDC_PINGEDIT
, &cfg
.ping_interval
);
1791 if (HIWORD(wParam
) == BN_CLICKED
||
1792 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1793 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1797 if (HIWORD(wParam
) == BN_CLICKED
||
1798 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1799 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1802 if (HIWORD(wParam
) == BN_CLICKED
||
1803 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1807 if (HIWORD(wParam
) == BN_CLICKED
||
1808 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1813 if (HIWORD(wParam
) == BN_CLICKED
||
1814 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1815 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1819 if (HIWORD(wParam
) == BN_CLICKED
||
1820 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1821 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1822 cfg
.nethack_keypad
= FALSE
;
1826 if (HIWORD(wParam
) == BN_CLICKED
||
1827 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1828 cfg
.app_keypad
= FALSE
;
1829 cfg
.nethack_keypad
= TRUE
;
1834 if (HIWORD(wParam
) == BN_CLICKED
||
1835 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1836 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1839 if (HIWORD(wParam
) == BN_CLICKED
||
1840 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1841 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1844 if (HIWORD(wParam
) == BN_CLICKED
||
1845 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1846 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1849 if (HIWORD(wParam
) == BN_CLICKED
||
1850 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1851 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1854 if (HIWORD(wParam
) == BN_CLICKED
||
1855 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1856 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1859 if (HIWORD(wParam
) == BN_CLICKED
||
1860 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1861 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1864 if (HIWORD(wParam
) == BN_CLICKED
||
1865 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1866 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1869 if (HIWORD(wParam
) == BN_CLICKED
||
1870 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1871 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1874 if (HIWORD(wParam
) == EN_CHANGE
)
1875 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1878 if (HIWORD(wParam
) == EN_CHANGE
)
1879 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1882 if (HIWORD(wParam
) == EN_CHANGE
)
1883 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1885 case IDC_CHOOSEFONT
:
1886 lf
.lfHeight
= cfg
.fontheight
;
1887 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1888 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1889 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1890 lf
.lfCharSet
= cfg
.fontcharset
;
1891 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1892 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1893 lf
.lfQuality
= DEFAULT_QUALITY
;
1894 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1895 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1896 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1898 cf
.lStructSize
= sizeof(cf
);
1899 cf
.hwndOwner
= hwnd
;
1901 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1902 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1904 if (ChooseFont (&cf
)) {
1905 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1906 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1907 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1908 cfg
.fontcharset
= lf
.lfCharSet
;
1909 cfg
.fontheight
= lf
.lfHeight
;
1910 fmtfont (fontstatic
);
1911 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1915 if (HIWORD(wParam
) == BN_CLICKED
||
1916 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1917 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1920 if (HIWORD(wParam
) == BN_CLICKED
||
1921 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1922 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1925 if (HIWORD(wParam
) == BN_CLICKED
||
1926 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1927 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1930 if (HIWORD(wParam
) == BN_CLICKED
||
1931 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1932 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1935 if (HIWORD(wParam
) == BN_CLICKED
||
1936 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1937 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1940 if (HIWORD(wParam
) == BN_CLICKED
||
1941 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1942 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1945 if (HIWORD(wParam
) == BN_CLICKED
||
1946 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1947 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1950 if (HIWORD(wParam
) == EN_CHANGE
)
1951 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1952 sizeof(cfg
.wintitle
)-1);
1955 if (HIWORD(wParam
) == BN_CLICKED
||
1956 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1957 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
1960 if (HIWORD(wParam
) == BN_CLICKED
||
1961 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1962 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
1965 if (HIWORD(wParam
) == EN_CHANGE
)
1966 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1967 sizeof(cfg
.termtype
)-1);
1970 if (HIWORD(wParam
) == EN_CHANGE
)
1971 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1972 sizeof(cfg
.termspeed
)-1);
1975 if (HIWORD(wParam
) == EN_CHANGE
)
1976 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1977 sizeof(cfg
.username
)-1);
1981 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1984 if (HIWORD(wParam
) == BN_CLICKED
||
1985 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1986 char str
[sizeof(cfg
.environmt
)];
1988 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
1993 p
= str
+ strlen(str
);
1995 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
2005 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
2007 p
[strlen(str
)+1] = '\0';
2008 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
2010 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
2011 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
2013 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
2014 MB_OK
| MB_ICONERROR
);
2019 if (HIWORD(wParam
) != BN_CLICKED
&&
2020 HIWORD(wParam
) != BN_DOUBLECLICKED
)
2022 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
2028 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
2053 if (HIWORD(wParam
) == BN_CLICKED
||
2054 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2055 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
2058 if (HIWORD(wParam
) == BN_CLICKED
||
2059 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2060 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
2062 case IDC_CIPHER3DES
:
2063 case IDC_CIPHERBLOWF
:
2065 if (HIWORD(wParam
) == BN_CLICKED
||
2066 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2067 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
2068 cfg
.cipher
= CIPHER_3DES
;
2069 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
2070 cfg
.cipher
= CIPHER_BLOWFISH
;
2071 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
2072 cfg
.cipher
= CIPHER_DES
;
2077 if (HIWORD(wParam
) == BN_CLICKED
||
2078 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2079 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
2081 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
2086 if (HIWORD(wParam
) == BN_CLICKED
||
2087 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2088 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
2091 if (HIWORD(wParam
) == EN_CHANGE
)
2092 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
2093 sizeof(cfg
.keyfile
)-1);
2096 if (HIWORD(wParam
) == EN_CHANGE
)
2097 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
2098 sizeof(cfg
.remote_cmd
)-1);
2101 memset(&of
, 0, sizeof(of
));
2102 #ifdef OPENFILENAME_SIZE_VERSION_400
2103 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
2105 of
.lStructSize
= sizeof(of
);
2107 of
.hwndOwner
= hwnd
;
2108 of
.lpstrFilter
= "All Files\0*\0\0\0";
2109 of
.lpstrCustomFilter
= NULL
;
2110 of
.nFilterIndex
= 1;
2111 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
2112 of
.nMaxFile
= sizeof(filename
);
2113 of
.lpstrFileTitle
= NULL
;
2114 of
.lpstrInitialDir
= NULL
;
2115 of
.lpstrTitle
= "Select Public Key File";
2117 if (GetOpenFileName(&of
)) {
2118 strcpy(cfg
.keyfile
, filename
);
2119 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
2124 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
2130 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
2135 for (i
=0; i
<256; i
++)
2136 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
2139 cfg
.wordness
[i
] = n
;
2140 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
2141 LB_DELETESTRING
, i
, 0);
2142 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
2143 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
2145 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
2152 case IDC_BOLDCOLOUR
:
2153 if (HIWORD(wParam
) == BN_CLICKED
||
2154 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2156 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
2157 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
2158 if (cfg
.bold_colour
&& n
!=22) {
2159 for (i
=0; i
<22; i
++)
2161 SendDlgItemMessage (hwnd
, IDC_LIST
,
2163 (LPARAM
) colours
[i
]);
2164 } else if (!cfg
.bold_colour
&& n
!=12) {
2167 SendDlgItemMessage (hwnd
, IDC_LIST
,
2168 LB_DELETESTRING
, i
, 0);
2173 if (HIWORD(wParam
) == BN_CLICKED
||
2174 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2175 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
2178 if (HIWORD(wParam
) == LBN_DBLCLK
||
2179 HIWORD(wParam
) == LBN_SELCHANGE
) {
2180 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2182 if (!cfg
.bold_colour
)
2183 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2184 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
2185 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
2186 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
2190 if (HIWORD(wParam
) == BN_CLICKED
||
2191 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2192 static CHOOSECOLOR cc
;
2193 static DWORD custom
[16] = {0}; /* zero initialisers */
2194 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2196 if (!cfg
.bold_colour
)
2197 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2198 cc
.lStructSize
= sizeof(cc
);
2199 cc
.hwndOwner
= hwnd
;
2200 cc
.hInstance
= (HWND
)hinst
;
2201 cc
.lpCustColors
= custom
;
2202 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
2204 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
2205 if (ChooseColor(&cc
)) {
2207 (unsigned char) (cc
.rgbResult
& 0xFF);
2209 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
2211 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
2212 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
2214 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
2216 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
2222 case IDC_KOI8WIN1251
:
2223 case IDC_88592WIN1250
:
2224 cfg
.xlat_enablekoiwin
=
2225 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
2226 cfg
.xlat_88592w1250
=
2227 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
2229 case IDC_CAPSLOCKCYR
:
2230 if (HIWORD(wParam
) == BN_CLICKED
||
2231 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2232 cfg
.xlat_capslockcyr
=
2233 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
2236 case IDC_VTXWINDOWS
:
2241 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
2242 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
2243 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
2249 EndDialog (hwnd
, 0);
2252 /* Grrr Explorer will maximize Dialogs! */
2254 if (wParam
== SIZE_MAXIMIZED
)
2261 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2262 WPARAM wParam
, LPARAM lParam
) {
2263 static HWND page
= NULL
;
2265 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2267 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDCX_ABOUT
) {
2268 EnableWindow(hwnd
, 0);
2269 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2270 GetParent(hwnd
), AboutProc
);
2271 EnableWindow(hwnd
, 1);
2272 SetActiveWindow(hwnd
);
2274 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
, 0);
2277 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2278 WPARAM wParam
, LPARAM lParam
) {
2280 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
, 1);
2283 int do_config (void) {
2287 savedsession
[0] = '\0';
2288 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2289 get_sesslist(FALSE
);
2294 int do_reconfig (HWND hwnd
) {
2298 backup_cfg
= cfg
; /* structure copy */
2299 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2301 cfg
= backup_cfg
; /* structure copy */
2308 void logevent (char *string
) {
2309 if (nevents
>= negsize
) {
2311 events
= srealloc (events
, negsize
* sizeof(*events
));
2313 events
[nevents
] = smalloc(1+strlen(string
));
2314 strcpy (events
[nevents
], string
);
2318 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2320 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2321 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2325 void showeventlog (HWND hwnd
) {
2327 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2329 ShowWindow (logbox
, SW_SHOWNORMAL
);
2333 void showabout (HWND hwnd
) {
2335 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2337 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2341 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2342 char *keystr
, char *fingerprint
) {
2345 static const char absentmsg
[] =
2346 "The server's host key is not cached in the registry. You\n"
2347 "have no guarantee that the server is the computer you\n"
2349 "The server's key fingerprint is:\n"
2351 "If you trust this host, hit Yes to add the key to\n"
2352 "PuTTY's cache and carry on connecting.\n"
2353 "If you do not trust this host, hit No to abandon the\n"
2356 static const char wrongmsg
[] =
2357 "WARNING - POTENTIAL SECURITY BREACH!\n"
2359 "The server's host key does not match the one PuTTY has\n"
2360 "cached in the registry. This means that either the\n"
2361 "server administrator has changed the host key, or you\n"
2362 "have actually connected to another computer pretending\n"
2363 "to be the server.\n"
2364 "The new key fingerprint is:\n"
2366 "If you were expecting this change and trust the new key,\n"
2367 "hit Yes to update PuTTY's cache and continue connecting.\n"
2368 "If you want to carry on connecting but without updating\n"
2369 "the cache, hit No.\n"
2370 "If you want to abandon the connection completely, hit\n"
2371 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2374 static const char mbtitle
[] = "PuTTY Security Alert";
2377 char message
[160+ /* sensible fingerprint max size */
2378 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2379 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2382 * Verify the key against the registry.
2384 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2386 if (ret
== 0) /* success - key matched OK */
2388 if (ret
== 2) { /* key was different */
2390 sprintf(message
, wrongmsg
, fingerprint
);
2391 mbret
= MessageBox(NULL
, message
, mbtitle
,
2392 MB_ICONWARNING
| MB_YESNOCANCEL
);
2394 store_host_key(host
, port
, keytype
, keystr
);
2395 if (mbret
== IDCANCEL
)
2398 if (ret
== 1) { /* key was absent */
2400 sprintf(message
, absentmsg
, fingerprint
);
2401 mbret
= MessageBox(NULL
, message
, mbtitle
,
2402 MB_ICONWARNING
| MB_YESNO
);
2405 store_host_key(host
, port
, keytype
, keystr
);