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
,
963 IDC_BOX_SELECTION1
, IDC_BOXT_SELECTION1
,
964 IDC_BOX_SELECTION2
, IDC_BOXT_SELECTION2
,
977 IDC_BOX_COLOURS1
, IDC_BOXT_COLOURS1
,
978 IDC_BOX_COLOURS2
, IDC_BOXT_COLOURS2
,
992 translationpanelstart
,
993 IDC_TITLE_TRANSLATION
,
994 IDC_BOX_TRANSLATION1
, IDC_BOXT_TRANSLATION1
,
995 IDC_BOX_TRANSLATION2
, IDC_BOXT_TRANSLATION2
,
996 IDC_BOX_TRANSLATION3
, IDC_BOXT_TRANSLATION3
,
1008 translationpanelend
,
1013 static const char *const colours
[] = {
1014 "Default Foreground", "Default Bold Foreground",
1015 "Default Background", "Default Bold Background",
1016 "Cursor Text", "Cursor Colour",
1017 "ANSI Black", "ANSI Black Bold",
1018 "ANSI Red", "ANSI Red Bold",
1019 "ANSI Green", "ANSI Green Bold",
1020 "ANSI Yellow", "ANSI Yellow Bold",
1021 "ANSI Blue", "ANSI Blue Bold",
1022 "ANSI Magenta", "ANSI Magenta Bold",
1023 "ANSI Cyan", "ANSI Cyan Bold",
1024 "ANSI White", "ANSI White Bold"
1026 static const int permcolour
[] = {
1027 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1028 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1029 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1032 static void fmtfont (char *buf
) {
1033 sprintf (buf
, "Font: %s, ", cfg
.font
);
1035 strcat(buf
, "bold, ");
1036 if (cfg
.fontheight
== 0)
1037 strcat (buf
, "default height");
1039 sprintf (buf
+strlen(buf
), "%d-%s",
1040 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1041 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1044 static void init_dlg_ctrls(HWND hwnd
) {
1046 char fontstatic
[256];
1048 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1049 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
1050 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1051 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1052 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1053 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
1054 SetDlgItemInt (hwnd
, IDC_PINGEDIT
, cfg
.ping_interval
, FALSE
);
1056 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1057 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1058 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1059 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1060 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCVT400
,
1061 cfg
.funky_type
== 0 ? IDC_FUNCTILDE
:
1062 cfg
.funky_type
== 1 ? IDC_FUNCLINUX
:
1063 cfg
.funky_type
== 2 ? IDC_FUNCXTERM
:
1064 cfg
.funky_type
== 3 ? IDC_FUNCVT400
:
1066 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1067 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1068 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1069 cfg
.nethack_keypad ? IDC_KPNH
:
1070 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1071 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1072 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1073 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1074 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1076 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1077 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1078 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1079 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1080 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1081 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1082 fmtfont (fontstatic
);
1083 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1084 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1085 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1086 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1088 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1089 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1090 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1091 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1092 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1093 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1094 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1096 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1097 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1098 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1100 char *p
= cfg
.environmt
;
1102 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1107 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1108 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1110 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1111 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1112 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1113 CheckDlgButton (hwnd
, IDC_BUGGYMAC
, cfg
.buggymac
);
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_88592CP852
,
1156 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
1157 cfg
.xlat_88592cp852 ? IDC_88592CP852
:
1158 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
1160 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1161 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
1162 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
1163 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
1164 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
1168 static void hide(HWND hwnd
, int hide
, int minid
, int maxid
) {
1170 for (i
= minid
; i
< maxid
; i
++) {
1171 HWND ctl
= GetDlgItem(hwnd
, i
);
1173 ShowWindow(ctl
, hide ? SW_HIDE
: SW_SHOW
);
1178 struct treeview_faff
{
1180 HTREEITEM lastat
[4];
1183 static HTREEITEM
treeview_insert(struct treeview_faff
*faff
,
1184 int level
, char *text
) {
1188 ins
.hParent
= (level
> 0 ? faff
->lastat
[level
-1] : TVI_ROOT
);
1189 ins
.hInsertAfter
= faff
->lastat
[level
];
1190 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
1191 #define INSITEM DUMMYUNIONNAME.item
1193 #define INSITEM item
1195 ins
.INSITEM
.mask
= TVIF_TEXT
;
1196 ins
.INSITEM
.pszText
= text
;
1197 newitem
= TreeView_InsertItem(faff
->treeview
, &ins
);
1199 TreeView_Expand(faff
->treeview
, faff
->lastat
[level
-1], TVE_EXPAND
);
1200 faff
->lastat
[level
] = newitem
;
1201 for (i
= level
+1; i
< 4; i
++) faff
->lastat
[i
] = NULL
;
1206 * This _huge_ function is the configuration box.
1208 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1209 WPARAM wParam
, LPARAM lParam
,
1212 struct treeview_faff tvfaff
;
1215 char filename
[sizeof(cfg
.keyfile
)];
1218 char fontstatic
[256];
1223 SetWindowLong(hwnd
, GWL_USERDATA
, 0);
1225 * Centre the window.
1227 { /* centre the window */
1230 hw
= GetDesktopWindow();
1231 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1232 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1233 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1234 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1238 * Create the tree view.
1245 r
.left
= 3; r
.right
= r
.left
+ 75;
1246 r
.top
= 3; r
.bottom
= r
.top
+ 10;
1247 MapDialogRect(hwnd
, &r
);
1248 tvstatic
= CreateWindowEx(0, "STATIC", "Cate&gory:",
1249 WS_CHILD
| WS_VISIBLE
,
1251 r
.right
-r
.left
, r
.bottom
-r
.top
,
1252 hwnd
, (HMENU
)IDCX_TVSTATIC
, hinst
, NULL
);
1253 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1254 SendMessage(tvstatic
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
1256 r
.left
= 3; r
.right
= r
.left
+ 75;
1257 r
.top
= 13; r
.bottom
= r
.top
+ 196;
1258 MapDialogRect(hwnd
, &r
);
1259 treeview
= CreateWindowEx(WS_EX_CLIENTEDGE
, WC_TREEVIEW
, "",
1260 WS_CHILD
| WS_VISIBLE
|
1261 WS_TABSTOP
| TVS_HASLINES
|
1262 TVS_DISABLEDRAGDROP
| TVS_HASBUTTONS
|
1263 TVS_LINESATROOT
| TVS_SHOWSELALWAYS
,
1265 r
.right
-r
.left
, r
.bottom
-r
.top
,
1266 hwnd
, (HMENU
)IDCX_TREEVIEW
, hinst
, NULL
);
1267 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1268 SendMessage(treeview
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
1269 tvfaff
.treeview
= treeview
;
1270 memset(tvfaff
.lastat
, 0, sizeof(tvfaff
.lastat
));
1274 * Create the various panelfuls of controls.
1277 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1280 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1281 bartitle(&cp
, "Basic options for your PuTTY session",
1284 beginbox(&cp
, "Specify your connection by host name",
1285 IDC_BOX_SESSION1
, IDC_BOXT_SESSION1
);
1287 "Host &Name", IDC_HOSTSTATIC
, IDC_HOST
, 75,
1288 "&Port", IDC_PORTSTATIC
, IDC_PORT
, 25, NULL
);
1289 if (backends
[2].backend
== NULL
) {
1290 /* this is PuTTYtel, so only two protocols available */
1291 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1292 "&Raw", IDC_PROTRAW
,
1293 "&Telnet", IDC_PROTTELNET
, NULL
);
1295 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1296 "&Raw", IDC_PROTRAW
,
1297 "&Telnet", IDC_PROTTELNET
,
1306 beginbox(&cp
, "Load, save or delete a stored session",
1307 IDC_BOX_SESSION2
, IDC_BOXT_SESSION2
);
1308 sesssaver(&cp
, "Stor&ed Sessions",
1309 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
1310 "&Load", IDC_SESSLOAD
,
1311 "&Save", IDC_SESSSAVE
,
1312 "&Delete", IDC_SESSDEL
, NULL
);
1315 beginbox(&cp
, NULL
, IDC_BOX_SESSION3
, 0);
1316 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
1319 hsession
= treeview_insert(&tvfaff
, 0, "Session");
1322 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1325 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1326 bartitle(&cp
, "Options controlling the terminal emulation",
1327 IDC_TITLE_TERMINAL
);
1328 beginbox(&cp
, "Set the size of the terminal window",
1329 IDC_BOX_TERMINAL1
, IDC_BOXT_TERMINAL1
);
1331 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 50,
1332 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 50,
1334 checkbox(&cp
, "Loc&k window size against resizing", IDC_LOCKSIZE
);
1336 beginbox(&cp
, "Set the font used in the terminal window",
1337 IDC_BOX_TERMINAL2
, IDC_BOXT_TERMINAL2
);
1338 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1340 beginbox(&cp
, "Set various terminal options",
1341 IDC_BOX_TERMINAL3
, IDC_BOXT_TERMINAL3
);
1342 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1343 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1344 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1345 checkbox(&cp
, "&Beep enabled", IDC_BEEP
);
1346 checkbox(&cp
, "Use background colour to &erase screen", IDC_BCE
);
1347 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1348 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1351 treeview_insert(&tvfaff
, 0, "Terminal");
1354 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1357 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1358 bartitle(&cp
, "Options controlling the effects of keys",
1359 IDC_TITLE_KEYBOARD
);
1360 beginbox(&cp
, "Change the sequences sent by:",
1361 IDC_BOX_KEYBOARD1
, IDC_BOXT_KEYBOARD1
);
1362 radioline(&cp
, "The Backspace key", IDC_DELSTATIC
, 2,
1363 "Control-&H", IDC_DEL008
,
1364 "Control-&? (127)", IDC_DEL127
, NULL
);
1365 radioline(&cp
, "The Home and End keys", IDC_HOMESTATIC
, 2,
1366 "&Standard", IDC_HOMETILDE
,
1367 "&rxvt", IDC_HOMERXVT
, NULL
);
1368 radioline(&cp
, "The Function keys and keypad", IDC_FUNCSTATIC
, 4,
1369 "ESC[n&~", IDC_FUNCTILDE
,
1370 "&Linux", IDC_FUNCLINUX
,
1371 "&Xterm R6", IDC_FUNCXTERM
,
1372 "&VT400", IDC_FUNCVT400
, NULL
);
1374 beginbox(&cp
, "Change the initial state of:",
1375 IDC_BOX_KEYBOARD2
, IDC_BOXT_KEYBOARD2
);
1376 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1377 "&Normal", IDC_CURNORMAL
,
1378 "A&pplication", IDC_CURAPPLIC
, NULL
);
1379 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1380 "Nor&mal", IDC_KPNORMAL
,
1381 "Appl&ication", IDC_KPAPPLIC
,
1382 "N&etHack", IDC_KPNH
, NULL
);
1385 treeview_insert(&tvfaff
, 1, "Keyboard");
1388 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1391 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1392 bartitle(&cp
, "Options controlling PuTTY's window",
1394 beginbox(&cp
, "Adjust the use of the window title",
1395 IDC_BOX_WINDOW1
, IDC_BOXT_WINDOW1
);
1398 "Initial window &title:", IDC_WINTITLE
,
1399 IDC_WINEDIT
, 100, NULL
);
1400 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1402 beginbox(&cp
, "Adjust the use of the cursor",
1403 IDC_BOX_WINDOW2
, IDC_BOXT_WINDOW2
);
1404 checkbox(&cp
, "Cursor &blinks", IDC_BLINKCUR
);
1406 beginbox(&cp
, "Control the scrollback in the window",
1407 IDC_BOX_WINDOW3
, IDC_BOXT_WINDOW3
);
1408 staticedit(&cp
, "Lines of &scrollback",
1409 IDC_SAVESTATIC
, IDC_SAVEEDIT
, 50);
1410 checkbox(&cp
, "&Display scrollbar", IDC_SCROLLBAR
);
1411 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1413 beginbox(&cp
, NULL
, IDC_BOX_WINDOW4
, 0);
1414 checkbox(&cp
, "&Warn before closing window", IDC_CLOSEWARN
);
1415 checkbox(&cp
, "Window closes on ALT-F&4", IDC_ALTF4
);
1416 checkbox(&cp
, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE
);
1419 treeview_insert(&tvfaff
, 0, "Window");
1422 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1425 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1426 bartitle(&cp
, "Options controlling character set translation",
1427 IDC_TITLE_TRANSLATION
);
1428 beginbox(&cp
, "Adjust how PuTTY displays line drawing characters",
1429 IDC_BOX_TRANSLATION1
, IDC_BOXT_TRANSLATION1
);
1431 "Handling of line drawing characters:", IDC_VTSTATIC
,
1432 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
1433 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
1434 "Use font in O&EM mode only", IDC_VTOEMONLY
,
1435 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1436 IDC_VTPOORMAN
, NULL
);
1438 beginbox(&cp
, "Enable character set translation on received data",
1439 IDC_BOX_TRANSLATION2
, IDC_BOXT_TRANSLATION2
);
1441 "Character set translation:", IDC_XLATSTATIC
,
1442 "&None", IDC_NOXLAT
,
1443 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
1444 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
,
1445 "&ISO-8859-2 / CP852", IDC_88592CP852
, NULL
);
1447 beginbox(&cp
, "Enable character set translation on input data",
1448 IDC_BOX_TRANSLATION3
, IDC_BOXT_TRANSLATION3
);
1449 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch",
1453 treeview_insert(&tvfaff
, 1, "Translation");
1456 /* The Selection panel. Accelerators used: [acgo] wxst */
1459 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1460 bartitle(&cp
, "Options controlling copy and paste",
1461 IDC_TITLE_SELECTION
);
1462 beginbox(&cp
, "Control which mouse button does which thing",
1463 IDC_BOX_SELECTION1
, IDC_BOXT_SELECTION1
);
1464 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1465 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1466 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1469 beginbox(&cp
, "Control the select-one-word-at-a-time mode",
1470 IDC_BOX_SELECTION2
, IDC_BOXT_SELECTION2
);
1471 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1472 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1473 "&to class", IDC_CCSTATIC2
);
1476 treeview_insert(&tvfaff
, 1, "Selection");
1479 /* The Colours panel. Accelerators used: [acgo] blum */
1482 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1483 bartitle(&cp
, "Options controlling use of colours",
1485 beginbox(&cp
, "General options for colour usage",
1486 IDC_BOX_COLOURS1
, IDC_BOXT_COLOURS1
);
1487 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
1488 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
1490 beginbox(&cp
, "Adjust the precise colours PuTTY displays",
1491 IDC_BOX_COLOURS2
, IDC_BOXT_COLOURS2
);
1492 colouredit(&cp
, "Select a colo&ur and then click to modify it:",
1493 IDC_STATIC
, IDC_LIST
,
1494 "&Modify...", IDC_CHANGE
,
1495 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
1496 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
1497 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
1500 treeview_insert(&tvfaff
, 1, "Colours");
1503 /* The Connection panel. Accelerators used: [acgo] tuk */
1506 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1507 bartitle(&cp
, "Options controlling the connection", IDC_TITLE_CONNECTION
);
1509 beginbox(&cp
, "Data to send to the server",
1510 IDC_BOX_CONNECTION1
, IDC_BOXT_CONNECTION1
);
1511 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
, 50);
1512 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
, 50);
1515 beginbox(&cp
, "Sending of null packets to keep session active",
1516 IDC_BOX_CONNECTION2
, IDC_BOXT_CONNECTION2
);
1517 staticedit(&cp
, "Minutes between &keepalives (0 to turn off)",
1518 IDC_PINGSTATIC
, IDC_PINGEDIT
, 25);
1521 treeview_insert(&tvfaff
, 0, "Connection");
1524 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1527 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1529 bartitle(&cp
, "Options controlling Telnet connections", IDC_TITLE_TELNET
);
1530 beginbox(&cp
, "Data to send to the server",
1531 IDC_BOX_TELNET1
, IDC_BOXT_TELNET1
);
1532 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
, 50);
1533 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1534 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1535 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1537 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1539 beginbox(&cp
, "Telnet protocol adjustments",
1540 IDC_BOX_TELNET2
, IDC_BOXT_TELNET2
);
1541 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1542 "&BSD (commonplace)", IDC_EMBSD
,
1543 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1546 treeview_insert(&tvfaff
, 1, "Telnet");
1550 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1551 if (backends
[2].backend
!= NULL
) {
1553 ctlposinit(&cp
, hwnd
, 80, 3, 13);
1555 bartitle(&cp
, "Options controlling SSH connections", IDC_TITLE_SSH
);
1556 beginbox(&cp
, "Data to send to the server",
1557 IDC_BOX_SSH1
, IDC_BOXT_SSH1
);
1559 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1562 beginbox(&cp
, "Authentication options",
1563 IDC_BOX_SSH2
, IDC_BOXT_SSH2
);
1564 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1566 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1567 editbutton(&cp
, "Private &key file for authentication:",
1568 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1570 beginbox(&cp
, "Protocol options",
1571 IDC_BOX_SSH3
, IDC_BOXT_SSH3
);
1572 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1573 radioline(&cp
, "Preferred SSH protocol version:",
1574 IDC_SSHPROTSTATIC
, 2,
1575 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1576 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1577 "&3DES", IDC_CIPHER3DES
,
1578 "&Blowfish", IDC_CIPHERBLOWF
,
1579 "&DES", IDC_CIPHERDES
, NULL
);
1580 checkbox(&cp
, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1584 treeview_insert(&tvfaff
, 1, "SSH");
1588 init_dlg_ctrls(hwnd
);
1589 for (i
= 0; i
< nsessions
; i
++)
1590 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1591 0, (LPARAM
) (sessions
[i
]));
1594 * Hide all the controls to start with.
1596 hide(hwnd
, TRUE
, controlstartvalue
, controlendvalue
);
1599 * Put the treeview selection on to the Session panel. This
1600 * should also cause unhiding of the relevant controls.
1602 TreeView_SelectItem(treeview
, hsession
);
1605 * Set focus into the first available control.
1609 ctl
= GetDlgItem(hwnd
, IDC_HOST
);
1610 if (!ctl
) ctl
= GetDlgItem(hwnd
, IDC_CLOSEEXIT
);
1614 SetWindowLong(hwnd
, GWL_USERDATA
, 1);
1618 * Button release should trigger WM_OK if there was a
1619 * previous double click on the session list.
1623 SendMessage (hwnd
, WM_COMMAND
, IDOK
, 0);
1626 if (LOWORD(wParam
) == IDCX_TREEVIEW
&&
1627 ((LPNMHDR
)lParam
)->code
== TVN_SELCHANGED
) {
1628 HTREEITEM i
= TreeView_GetSelection(((LPNMHDR
)lParam
)->hwndFrom
);
1632 item
.pszText
= buffer
;
1633 item
.cchTextMax
= sizeof(buffer
);
1634 item
.mask
= TVIF_TEXT
;
1635 TreeView_GetItem(((LPNMHDR
)lParam
)->hwndFrom
, &item
);
1636 hide(hwnd
, TRUE
, controlstartvalue
, controlendvalue
);
1637 if (!strcmp(buffer
, "Session"))
1638 hide(hwnd
, FALSE
, sessionpanelstart
, sessionpanelend
);
1639 if (!strcmp(buffer
, "Keyboard"))
1640 hide(hwnd
, FALSE
, keyboardpanelstart
, keyboardpanelend
);
1641 if (!strcmp(buffer
, "Terminal"))
1642 hide(hwnd
, FALSE
, terminalpanelstart
, terminalpanelend
);
1643 if (!strcmp(buffer
, "Window"))
1644 hide(hwnd
, FALSE
, windowpanelstart
, windowpanelend
);
1645 if (!strcmp(buffer
, "Connection"))
1646 hide(hwnd
, FALSE
, connectionpanelstart
, connectionpanelend
);
1647 if (!strcmp(buffer
, "Telnet"))
1648 hide(hwnd
, FALSE
, telnetpanelstart
, telnetpanelend
);
1649 if (!strcmp(buffer
, "SSH"))
1650 hide(hwnd
, FALSE
, sshpanelstart
, sshpanelend
);
1651 if (!strcmp(buffer
, "Selection"))
1652 hide(hwnd
, FALSE
, selectionpanelstart
, selectionpanelend
);
1653 if (!strcmp(buffer
, "Colours"))
1654 hide(hwnd
, FALSE
, colourspanelstart
, colourspanelend
);
1655 if (!strcmp(buffer
, "Translation"))
1656 hide(hwnd
, FALSE
, translationpanelstart
, translationpanelend
);
1658 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1664 * Only process WM_COMMAND once the dialog is fully formed.
1666 if (GetWindowLong(hwnd
, GWL_USERDATA
) == 1) switch (LOWORD(wParam
)) {
1669 EndDialog (hwnd
, 1);
1674 EndDialog (hwnd
, 0);
1676 case IDC_PROTTELNET
:
1679 if (HIWORD(wParam
) == BN_CLICKED
||
1680 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1681 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
1682 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
1683 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
1684 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
1685 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
1686 cfg
.port
= i ?
22 : 23;
1687 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1692 if (HIWORD(wParam
) == EN_CHANGE
)
1693 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
1694 sizeof(cfg
.host
)-1);
1697 if (HIWORD(wParam
) == EN_CHANGE
)
1698 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
1701 if (HIWORD(wParam
) == EN_CHANGE
) {
1702 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1704 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
1705 savedsession
, sizeof(savedsession
)-1);
1706 savedsession
[sizeof(savedsession
)-1] = '\0';
1710 if (HIWORD(wParam
) == BN_CLICKED
||
1711 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1716 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
1718 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1719 LB_GETCURSEL
, 0, 0);
1724 strcpy (str
, sessions
[n
]);
1726 save_settings (str
, !!strcmp(str
, "Default Settings"), &cfg
);
1727 get_sesslist (FALSE
);
1728 get_sesslist (TRUE
);
1729 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1731 for (i
= 0; i
< nsessions
; i
++)
1732 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1733 0, (LPARAM
) (sessions
[i
]));
1734 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1740 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
1741 HIWORD(wParam
) != BN_CLICKED
&&
1742 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1744 if (LOWORD(wParam
) == IDC_SESSLIST
&&
1745 HIWORD(wParam
) != LBN_DBLCLK
)
1748 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1749 LB_GETCURSEL
, 0, 0);
1755 isdef
= !strcmp(sessions
[n
], "Default Settings");
1756 load_settings (sessions
[n
], !isdef
, &cfg
);
1757 init_dlg_ctrls(hwnd
);
1759 SetDlgItemText(hwnd
, IDC_SESSEDIT
, sessions
[n
]);
1761 if (LOWORD(wParam
) == IDC_SESSLIST
) {
1763 * A double-click on a saved session should
1764 * actually start the session, not just load it.
1765 * Unless it's Default Settings or some other
1766 * host-less set of saved settings.
1775 if (HIWORD(wParam
) == BN_CLICKED
||
1776 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1777 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1778 LB_GETCURSEL
, 0, 0);
1779 if (n
== LB_ERR
|| n
== 0) {
1783 del_settings(sessions
[n
]);
1784 get_sesslist (FALSE
);
1785 get_sesslist (TRUE
);
1786 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1788 for (i
= 0; i
< nsessions
; i
++)
1789 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1790 0, (LPARAM
) (sessions
[i
]));
1791 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1795 if (HIWORD(wParam
) == EN_CHANGE
)
1796 MyGetDlgItemInt (hwnd
, IDC_PINGEDIT
, &cfg
.ping_interval
);
1800 if (HIWORD(wParam
) == BN_CLICKED
||
1801 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1802 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1806 if (HIWORD(wParam
) == BN_CLICKED
||
1807 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1808 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1811 if (HIWORD(wParam
) == BN_CLICKED
||
1812 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1816 if (HIWORD(wParam
) == BN_CLICKED
||
1817 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1822 if (HIWORD(wParam
) == BN_CLICKED
||
1823 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1824 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1828 if (HIWORD(wParam
) == BN_CLICKED
||
1829 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1830 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1831 cfg
.nethack_keypad
= FALSE
;
1835 if (HIWORD(wParam
) == BN_CLICKED
||
1836 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1837 cfg
.app_keypad
= FALSE
;
1838 cfg
.nethack_keypad
= TRUE
;
1843 if (HIWORD(wParam
) == BN_CLICKED
||
1844 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1845 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1848 if (HIWORD(wParam
) == BN_CLICKED
||
1849 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1850 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1853 if (HIWORD(wParam
) == BN_CLICKED
||
1854 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1855 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1858 if (HIWORD(wParam
) == BN_CLICKED
||
1859 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1860 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1863 if (HIWORD(wParam
) == BN_CLICKED
||
1864 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1865 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1868 if (HIWORD(wParam
) == BN_CLICKED
||
1869 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1870 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1873 if (HIWORD(wParam
) == BN_CLICKED
||
1874 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1875 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1878 if (HIWORD(wParam
) == BN_CLICKED
||
1879 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1880 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1883 if (HIWORD(wParam
) == EN_CHANGE
)
1884 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1887 if (HIWORD(wParam
) == EN_CHANGE
)
1888 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1891 if (HIWORD(wParam
) == EN_CHANGE
)
1892 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1894 case IDC_CHOOSEFONT
:
1895 lf
.lfHeight
= cfg
.fontheight
;
1896 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1897 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1898 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1899 lf
.lfCharSet
= cfg
.fontcharset
;
1900 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1901 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1902 lf
.lfQuality
= DEFAULT_QUALITY
;
1903 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1904 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1905 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1907 cf
.lStructSize
= sizeof(cf
);
1908 cf
.hwndOwner
= hwnd
;
1910 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1911 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1913 if (ChooseFont (&cf
)) {
1914 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1915 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1916 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1917 cfg
.fontcharset
= lf
.lfCharSet
;
1918 cfg
.fontheight
= lf
.lfHeight
;
1919 fmtfont (fontstatic
);
1920 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1924 if (HIWORD(wParam
) == BN_CLICKED
||
1925 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1926 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1929 if (HIWORD(wParam
) == BN_CLICKED
||
1930 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1931 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1934 if (HIWORD(wParam
) == BN_CLICKED
||
1935 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1936 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1939 if (HIWORD(wParam
) == BN_CLICKED
||
1940 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1941 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1944 if (HIWORD(wParam
) == BN_CLICKED
||
1945 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1946 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1949 if (HIWORD(wParam
) == BN_CLICKED
||
1950 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1951 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1954 if (HIWORD(wParam
) == BN_CLICKED
||
1955 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1956 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1959 if (HIWORD(wParam
) == EN_CHANGE
)
1960 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1961 sizeof(cfg
.wintitle
)-1);
1964 if (HIWORD(wParam
) == BN_CLICKED
||
1965 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1966 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
1969 if (HIWORD(wParam
) == BN_CLICKED
||
1970 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1971 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
1974 if (HIWORD(wParam
) == EN_CHANGE
)
1975 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1976 sizeof(cfg
.termtype
)-1);
1979 if (HIWORD(wParam
) == EN_CHANGE
)
1980 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1981 sizeof(cfg
.termspeed
)-1);
1984 if (HIWORD(wParam
) == EN_CHANGE
)
1985 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1986 sizeof(cfg
.username
)-1);
1990 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1993 if (HIWORD(wParam
) == BN_CLICKED
||
1994 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1995 char str
[sizeof(cfg
.environmt
)];
1997 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
2002 p
= str
+ strlen(str
);
2004 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
2014 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
2016 p
[strlen(str
)+1] = '\0';
2017 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
2019 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
2020 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
2022 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
2023 MB_OK
| MB_ICONERROR
);
2028 if (HIWORD(wParam
) != BN_CLICKED
&&
2029 HIWORD(wParam
) != BN_DOUBLECLICKED
)
2031 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
2037 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
2062 if (HIWORD(wParam
) == BN_CLICKED
||
2063 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2064 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
2067 if (HIWORD(wParam
) == BN_CLICKED
||
2068 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2069 cfg
.buggymac
= IsDlgButtonChecked (hwnd
, IDC_BUGGYMAC
);
2072 if (HIWORD(wParam
) == BN_CLICKED
||
2073 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2074 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
2076 case IDC_CIPHER3DES
:
2077 case IDC_CIPHERBLOWF
:
2079 if (HIWORD(wParam
) == BN_CLICKED
||
2080 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2081 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
2082 cfg
.cipher
= CIPHER_3DES
;
2083 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
2084 cfg
.cipher
= CIPHER_BLOWFISH
;
2085 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
2086 cfg
.cipher
= CIPHER_DES
;
2091 if (HIWORD(wParam
) == BN_CLICKED
||
2092 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2093 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
2095 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
2100 if (HIWORD(wParam
) == BN_CLICKED
||
2101 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2102 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
2105 if (HIWORD(wParam
) == EN_CHANGE
)
2106 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
2107 sizeof(cfg
.keyfile
)-1);
2110 if (HIWORD(wParam
) == EN_CHANGE
)
2111 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
2112 sizeof(cfg
.remote_cmd
)-1);
2115 memset(&of
, 0, sizeof(of
));
2116 #ifdef OPENFILENAME_SIZE_VERSION_400
2117 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
2119 of
.lStructSize
= sizeof(of
);
2121 of
.hwndOwner
= hwnd
;
2122 of
.lpstrFilter
= "All Files\0*\0\0\0";
2123 of
.lpstrCustomFilter
= NULL
;
2124 of
.nFilterIndex
= 1;
2125 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
2126 of
.nMaxFile
= sizeof(filename
);
2127 of
.lpstrFileTitle
= NULL
;
2128 of
.lpstrInitialDir
= NULL
;
2129 of
.lpstrTitle
= "Select Public Key File";
2131 if (GetOpenFileName(&of
)) {
2132 strcpy(cfg
.keyfile
, filename
);
2133 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
2138 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
2144 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
2149 for (i
=0; i
<256; i
++)
2150 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
2153 cfg
.wordness
[i
] = n
;
2154 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
2155 LB_DELETESTRING
, i
, 0);
2156 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
2157 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
2159 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
2166 case IDC_BOLDCOLOUR
:
2167 if (HIWORD(wParam
) == BN_CLICKED
||
2168 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2170 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
2171 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
2172 if (cfg
.bold_colour
&& n
!=22) {
2173 for (i
=0; i
<22; i
++)
2175 SendDlgItemMessage (hwnd
, IDC_LIST
,
2177 (LPARAM
) colours
[i
]);
2178 } else if (!cfg
.bold_colour
&& n
!=12) {
2181 SendDlgItemMessage (hwnd
, IDC_LIST
,
2182 LB_DELETESTRING
, i
, 0);
2187 if (HIWORD(wParam
) == BN_CLICKED
||
2188 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2189 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
2192 if (HIWORD(wParam
) == LBN_DBLCLK
||
2193 HIWORD(wParam
) == LBN_SELCHANGE
) {
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 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
2199 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
2200 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
2204 if (HIWORD(wParam
) == BN_CLICKED
||
2205 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2206 static CHOOSECOLOR cc
;
2207 static DWORD custom
[16] = {0}; /* zero initialisers */
2208 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2210 if (!cfg
.bold_colour
)
2211 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2212 cc
.lStructSize
= sizeof(cc
);
2213 cc
.hwndOwner
= hwnd
;
2214 cc
.hInstance
= (HWND
)hinst
;
2215 cc
.lpCustColors
= custom
;
2216 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
2218 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
2219 if (ChooseColor(&cc
)) {
2221 (unsigned char) (cc
.rgbResult
& 0xFF);
2223 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
2225 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
2226 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
2228 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
2230 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
2236 case IDC_KOI8WIN1251
:
2237 case IDC_88592WIN1250
:
2238 case IDC_88592CP852
:
2239 cfg
.xlat_enablekoiwin
=
2240 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
2241 cfg
.xlat_88592w1250
=
2242 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
2243 cfg
.xlat_88592cp852
=
2244 IsDlgButtonChecked (hwnd
, IDC_88592CP852
);
2246 case IDC_CAPSLOCKCYR
:
2247 if (HIWORD(wParam
) == BN_CLICKED
||
2248 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2249 cfg
.xlat_capslockcyr
=
2250 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
2253 case IDC_VTXWINDOWS
:
2258 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
2259 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
2260 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
2266 EndDialog (hwnd
, 0);
2269 /* Grrr Explorer will maximize Dialogs! */
2271 if (wParam
== SIZE_MAXIMIZED
)
2278 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2279 WPARAM wParam
, LPARAM lParam
) {
2280 static HWND page
= NULL
;
2282 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2284 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDCX_ABOUT
) {
2285 EnableWindow(hwnd
, 0);
2286 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2287 GetParent(hwnd
), AboutProc
);
2288 EnableWindow(hwnd
, 1);
2289 SetActiveWindow(hwnd
);
2291 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
, 0);
2294 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2295 WPARAM wParam
, LPARAM lParam
) {
2297 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
, 1);
2300 int do_config (void) {
2304 savedsession
[0] = '\0';
2305 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2306 get_sesslist(FALSE
);
2311 int do_reconfig (HWND hwnd
) {
2315 backup_cfg
= cfg
; /* structure copy */
2316 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2318 cfg
= backup_cfg
; /* structure copy */
2325 void logevent (char *string
) {
2326 if (nevents
>= negsize
) {
2328 events
= srealloc (events
, negsize
* sizeof(*events
));
2330 events
[nevents
] = smalloc(1+strlen(string
));
2331 strcpy (events
[nevents
], string
);
2335 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2337 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2338 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2342 void showeventlog (HWND hwnd
) {
2344 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2346 ShowWindow (logbox
, SW_SHOWNORMAL
);
2350 void showabout (HWND hwnd
) {
2352 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2354 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2358 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2359 char *keystr
, char *fingerprint
) {
2362 static const char absentmsg
[] =
2363 "The server's host key is not cached in the registry. You\n"
2364 "have no guarantee that the server is the computer you\n"
2366 "The server's key fingerprint is:\n"
2368 "If you trust this host, hit Yes to add the key to\n"
2369 "PuTTY's cache and carry on connecting.\n"
2370 "If you do not trust this host, hit No to abandon the\n"
2373 static const char wrongmsg
[] =
2374 "WARNING - POTENTIAL SECURITY BREACH!\n"
2376 "The server's host key does not match the one PuTTY has\n"
2377 "cached in the registry. This means that either the\n"
2378 "server administrator has changed the host key, or you\n"
2379 "have actually connected to another computer pretending\n"
2380 "to be the server.\n"
2381 "The new key fingerprint is:\n"
2383 "If you were expecting this change and trust the new key,\n"
2384 "hit Yes to update PuTTY's cache and continue connecting.\n"
2385 "If you want to carry on connecting but without updating\n"
2386 "the cache, hit No.\n"
2387 "If you want to abandon the connection completely, hit\n"
2388 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2391 static const char mbtitle
[] = "PuTTY Security Alert";
2394 char message
[160+ /* sensible fingerprint max size */
2395 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2396 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2399 * Verify the key against the registry.
2401 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2403 if (ret
== 0) /* success - key matched OK */
2405 if (ret
== 2) { /* key was different */
2407 sprintf(message
, wrongmsg
, fingerprint
);
2408 mbret
= MessageBox(NULL
, message
, mbtitle
,
2409 MB_ICONWARNING
| MB_YESNOCANCEL
);
2411 store_host_key(host
, port
, keytype
, keystr
);
2412 if (mbret
== IDCANCEL
)
2415 if (ret
== 1) { /* key was absent */
2417 sprintf(message
, absentmsg
, fingerprint
);
2418 mbret
= MessageBox(NULL
, message
, mbtitle
,
2419 MB_ICONWARNING
| MB_YESNO
);
2422 store_host_key(host
, port
, keytype
, keystr
);