20 #define MAIN_NPANELS 9
21 #define RECONF_NPANELS 7
23 static char **events
= NULL
;
24 static int nevents
= 0, negsize
= 0;
26 static HWND logbox
= NULL
, abtbox
= NULL
;
28 static HINSTANCE hinst
;
32 static void force_normal(HWND hwnd
)
34 static int recurse
= 0;
41 wp
.length
= sizeof(wp
);
42 if (GetWindowPlacement(hwnd
, &wp
))
44 wp
.showCmd
= SW_SHOWNORMAL
;
45 SetWindowPlacement(hwnd
, &wp
);
50 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
53 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
58 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
59 WPARAM wParam
, LPARAM lParam
) {
64 for (i
=0; i
<nevents
; i
++)
65 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
66 0, (LPARAM
)events
[i
]);
69 switch (LOWORD(wParam
)) {
75 if (HIWORD(wParam
) == BN_CLICKED
||
76 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
79 selcount
= SendDlgItemMessage(hwnd
, IDN_LIST
,
80 LB_GETSELCOUNT
, 0, 0);
81 selitems
= malloc(selcount
* sizeof(int));
83 int count
= SendDlgItemMessage(hwnd
, IDN_LIST
,
85 selcount
, (LPARAM
)selitems
);
89 static unsigned char sel_nl
[] = SEL_NL
;
91 if (count
== 0) { /* can't copy zero stuff */
97 for (i
= 0; i
< count
; i
++)
98 size
+= strlen(events
[selitems
[i
]]) + sizeof(sel_nl
);
100 clipdata
= malloc(size
);
103 for (i
= 0; i
< count
; i
++) {
104 char *q
= events
[selitems
[i
]];
105 int qlen
= strlen(q
);
108 memcpy(p
, sel_nl
, sizeof(sel_nl
));
111 write_clip(clipdata
, size
, TRUE
);
116 for (i
= 0; i
< nevents
; i
++)
117 SendDlgItemMessage(hwnd
, IDN_LIST
, LB_SETSEL
,
126 DestroyWindow (hwnd
);
132 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
133 WPARAM wParam
, LPARAM lParam
) {
138 switch (LOWORD(wParam
)) {
151 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
152 WPARAM wParam
, LPARAM lParam
) {
155 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
158 switch (LOWORD(wParam
)) {
161 DestroyWindow (hwnd
);
164 EnableWindow(hwnd
, 0);
165 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
167 EnableWindow(hwnd
, 1);
168 SetActiveWindow(hwnd
);
174 DestroyWindow (hwnd
);
180 /* ----------------------------------------------------------------------
181 * Routines to self-manage the controls in a dialog box.
187 #define STATICHEIGHT 8
188 #define CHECKBOXHEIGHT 8
189 #define RADIOHEIGHT 8
190 #define EDITHEIGHT 12
191 #define COMBOHEIGHT 12
192 #define PUSHBTNHEIGHT 14
201 /* Used on self-constructed dialogs. */
202 static void ctlposinit(struct ctlpos
*cp
, HWND hwnd
) {
205 cp
->units
= GetWindowLong(hwnd
, GWL_USERDATA
);
206 cp
->font
= GetWindowLong(hwnd
, DWL_USER
);
207 cp
->ypos
= GAPBETWEEN
;
208 GetClientRect(hwnd
, &r
);
209 cp
->width
= (r
.right
* 4) / (cp
->units
& 0xFFFF) - 2*GAPBETWEEN
;
212 /* Used on kosher dialogs. */
213 static void ctlposinit2(struct ctlpos
*cp
, HWND hwnd
) {
219 MapDialogRect(hwnd
, &r
);
220 cp
->units
= (r
.bottom
<< 16) | r
.right
;
221 cp
->font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
222 cp
->ypos
= GAPBETWEEN
;
223 GetClientRect(hwnd
, &r
);
224 cp
->width
= (r
.right
* 4) / (cp
->units
& 0xFFFF) - 2*GAPBETWEEN
;
227 static void doctl(struct ctlpos
*cp
, RECT r
,
228 char *wclass
, int wstyle
, int exstyle
,
229 char *wtext
, int wid
) {
232 * Note nonstandard use of RECT. This is deliberate: by
233 * transforming the width and height directly we arrange to
234 * have all supposedly same-sized controls really same-sized.
237 /* MapDialogRect, or its near equivalent. */
238 r
.left
= (r
.left
* (cp
->units
& 0xFFFF)) / 4;
239 r
.right
= (r
.right
* (cp
->units
& 0xFFFF)) / 4;
240 r
.top
= (r
.top
* ((cp
->units
>>16) & 0xFFFF)) / 8;
241 r
.bottom
= (r
.bottom
* ((cp
->units
>>16) & 0xFFFF)) / 8;
243 ctl
= CreateWindowEx(exstyle
, wclass
, wtext
, wstyle
,
244 r
.left
, r
.top
, r
.right
, r
.bottom
,
245 cp
->hwnd
, (HMENU
)wid
, hinst
, NULL
);
246 SendMessage(ctl
, WM_SETFONT
, cp
->font
, MAKELPARAM(TRUE
, 0));
250 * Some edit boxes. Each one has a static above it. The percentages
251 * of the horizontal space are provided.
253 static void multiedit(struct ctlpos
*cp
, ...) {
262 int staticid
, editid
, pcwidth
;
263 text
= va_arg(ap
, char *);
266 staticid
= va_arg(ap
, int);
267 editid
= va_arg(ap
, int);
268 pcwidth
= va_arg(ap
, int);
270 r
.left
= xpos
+ GAPBETWEEN
;
272 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
273 r
.right
= xpos
- r
.left
;
275 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
276 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
278 r
.top
= cp
->ypos
+ 8 + GAPWITHIN
; r
.bottom
= EDITHEIGHT
;
280 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
285 cp
->ypos
+= 8+GAPWITHIN
+12+GAPBETWEEN
;
289 * A set of radio buttons on the same line, with a static above
290 * them. `nacross' dictates how many parts the line is divided into
291 * (you might want this not to equal the number of buttons if you
292 * needed to line up some 2s and some 3s to look good in the same
295 static void radioline(struct ctlpos
*cp
,
296 char *text
, int id
, int nacross
, ...) {
302 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
303 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
304 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
305 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
306 va_start(ap
, nacross
);
312 btext
= va_arg(ap
, char *);
315 bid
= va_arg(ap
, int);
316 r
.left
= GAPBETWEEN
+ i
* (cp
->width
+GAPBETWEEN
)/nacross
;
317 r
.right
= (i
+1) * (cp
->width
+GAPBETWEEN
)/nacross
- r
.left
;
318 r
.top
= cp
->ypos
; r
.bottom
= RADIOHEIGHT
;
319 doctl(cp
, r
, "BUTTON",
320 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
327 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
331 * A set of radio buttons on multiple lines, with a static above
334 static void radiobig(struct ctlpos
*cp
, char *text
, int id
, ...) {
339 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
340 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
341 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
342 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
348 btext
= va_arg(ap
, char *);
351 bid
= va_arg(ap
, int);
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
, "BUTTON",
356 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
362 cp
->ypos
+= GAPBETWEEN
- GAPWITHIN
;
366 * A single standalone checkbox.
368 static void checkbox(struct ctlpos
*cp
, char *text
, int id
) {
371 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
372 r
.right
= cp
->width
; r
.bottom
= CHECKBOXHEIGHT
;
373 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
374 doctl(cp
, r
, "BUTTON",
375 BS_AUTOCHECKBOX
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
, 0,
380 * A button on the right hand side, with a static to its left.
382 static void staticbtn(struct ctlpos
*cp
, char *stext
, int sid
,
383 char *btext
, int bid
) {
384 const int height
= (PUSHBTNHEIGHT
> STATICHEIGHT ?
385 PUSHBTNHEIGHT
: STATICHEIGHT
);
387 int lwid
, rwid
, rpos
;
389 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
390 lwid
= rpos
- 2*GAPBETWEEN
;
391 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
393 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
394 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
395 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
397 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
398 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
399 doctl(cp
, r
, "BUTTON",
400 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
404 cp
->ypos
+= height
+ GAPBETWEEN
;
408 * An edit control on the right hand side, with a static to its left.
410 static void staticedit(struct ctlpos
*cp
, char *stext
, int sid
, int eid
) {
411 const int height
= (EDITHEIGHT
> STATICHEIGHT ?
412 EDITHEIGHT
: STATICHEIGHT
);
414 int lwid
, rwid
, rpos
;
416 rpos
= GAPBETWEEN
+ (cp
->width
+ GAPBETWEEN
) / 2;
417 lwid
= rpos
- 2*GAPBETWEEN
;
418 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
420 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
421 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
422 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
424 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
425 r
.right
= rwid
; r
.bottom
= EDITHEIGHT
;
427 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
431 cp
->ypos
+= height
+ GAPBETWEEN
;
435 * A tab-control substitute when a real tab control is unavailable.
437 static void ersatztab(struct ctlpos
*cp
, char *stext
, int sid
,
439 const int height
= (COMBOHEIGHT
> STATICHEIGHT ?
440 COMBOHEIGHT
: STATICHEIGHT
);
442 int bigwid
, lwid
, rwid
, rpos
;
443 static const int BIGGAP
= 15;
444 static const int MEDGAP
= 3;
446 bigwid
= cp
->width
+ 2*GAPBETWEEN
- 2*BIGGAP
;
448 rpos
= BIGGAP
+ (bigwid
+ BIGGAP
) / 2;
449 lwid
= rpos
- 2*BIGGAP
;
450 rwid
= bigwid
+ BIGGAP
- rpos
;
452 r
.left
= BIGGAP
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
453 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
454 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
456 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-COMBOHEIGHT
)/2;
457 r
.right
= rwid
; r
.bottom
= COMBOHEIGHT
*10;
458 doctl(cp
, r
, "COMBOBOX",
459 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
460 CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
464 cp
->ypos
+= height
+ MEDGAP
+ GAPBETWEEN
;
466 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
467 r
.right
= cp
->width
; r
.bottom
= 2;
468 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDHORZ
,
473 * A static line, followed by an edit control on the left hand side
474 * and a button on the right.
476 static void editbutton(struct ctlpos
*cp
, char *stext
, int sid
,
477 int eid
, char *btext
, int bid
) {
478 const int height
= (EDITHEIGHT
> PUSHBTNHEIGHT ?
479 EDITHEIGHT
: PUSHBTNHEIGHT
);
481 int lwid
, rwid
, rpos
;
483 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
484 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
485 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
486 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
488 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
489 lwid
= rpos
- 2*GAPBETWEEN
;
490 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
492 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
493 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
495 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
499 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
500 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
501 doctl(cp
, r
, "BUTTON",
502 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
506 cp
->ypos
+= height
+ GAPBETWEEN
;
510 * Special control which was hard to describe generically: the
511 * session-saver assembly. A static; below that an edit box; below
512 * that a list box. To the right of the list box, a column of
515 static void sesssaver(struct ctlpos
*cp
, char *text
,
516 int staticid
, int editid
, int listid
, ...) {
519 int lwid
, rwid
, rpos
;
521 const int LISTDEFHEIGHT
= 66;
523 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
524 lwid
= rpos
- 2*GAPBETWEEN
;
525 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
527 /* The static control. */
528 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
529 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
530 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
531 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
533 /* The edit control. */
534 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
535 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
536 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
538 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
543 * The buttons (we should hold off on the list box until we
544 * know how big the buttons are).
546 va_start(ap
, listid
);
549 char *btext
= va_arg(ap
, char *);
552 bid
= va_arg(ap
, int);
553 r
.left
= rpos
; r
.top
= y
;
554 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
555 y
+= r
.bottom
+ GAPWITHIN
;
556 doctl(cp
, r
, "BUTTON",
557 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
562 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
565 if (y
< LISTDEFHEIGHT
) y
= LISTDEFHEIGHT
;
566 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
567 r
.right
= lwid
; r
.bottom
= y
;
568 cp
->ypos
+= y
+ GAPBETWEEN
;
569 doctl(cp
, r
, "LISTBOX",
570 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
|
571 LBS_STANDARD
| LBS_HASSTRINGS
,
577 * Another special control: the environment-variable setter. A
578 * static line first; then a pair of edit boxes with associated
579 * statics, and two buttons; then a list box.
581 static void envsetter(struct ctlpos
*cp
, char *stext
, int sid
,
582 char *e1stext
, int e1sid
, int e1id
,
583 char *e2stext
, int e2sid
, int e2id
,
585 char *b1text
, int b1id
, char *b2text
, int b2id
) {
587 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
589 EDITHEIGHT
> PUSHBTNHEIGHT ?
590 EDITHEIGHT
: PUSHBTNHEIGHT
);
591 const static int percents
[] = { 20, 35, 10, 25 };
592 int i
, j
, xpos
, percent
;
593 const int LISTHEIGHT
= 42;
595 /* The static control. */
596 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
597 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
598 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
599 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
601 /* The statics+edits+buttons. */
602 for (j
= 0; j
< 2; j
++) {
604 for (i
= 0; i
< 4; i
++) {
605 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
606 r
.left
= xpos
+ GAPBETWEEN
;
607 percent
+= percents
[i
];
608 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
609 r
.right
= xpos
- r
.left
;
611 r
.bottom
= (i
==0 ? STATICHEIGHT
:
614 r
.top
+= (height
-r
.bottom
)/2;
616 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
617 j
==0 ? e1stext
: e2stext
, j
==0 ? e1sid
: e2sid
);
620 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
622 "", j
==0 ? e1id
: e2id
);
624 doctl(cp
, r
, "BUTTON",
625 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
627 j
==0 ? b1text
: b2text
, j
==0 ? b1id
: b2id
);
630 cp
->ypos
+= height
+ GAPWITHIN
;
634 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
635 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
636 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
637 doctl(cp
, r
, "LISTBOX",
638 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
645 * Yet another special control: the character-class setter. A
646 * static, then a list, then a line containing a
647 * button-and-static-and-edit.
649 static void charclass(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
650 char *btext
, int bid
, int eid
, char *s2text
, int s2id
) {
652 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
654 EDITHEIGHT
> PUSHBTNHEIGHT ?
655 EDITHEIGHT
: PUSHBTNHEIGHT
);
656 const static int percents
[] = { 30, 40, 30 };
657 int i
, xpos
, percent
;
658 const int LISTHEIGHT
= 66;
660 /* The static control. */
661 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
662 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
663 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
664 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
667 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
668 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
669 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
670 doctl(cp
, r
, "LISTBOX",
671 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
676 /* The button+static+edit. */
678 for (i
= 0; i
< 3; i
++) {
679 r
.left
= xpos
+ GAPBETWEEN
;
680 percent
+= percents
[i
];
681 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
682 r
.right
= xpos
- r
.left
;
684 r
.bottom
= (i
==0 ? PUSHBTNHEIGHT
:
685 i
==1 ? STATICHEIGHT
:
687 r
.top
+= (height
-r
.bottom
)/2;
689 doctl(cp
, r
, "BUTTON",
690 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
693 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
697 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
698 WS_EX_CLIENTEDGE
, "", eid
);
701 cp
->ypos
+= height
+ GAPBETWEEN
;
705 * A special control (horrors!). The colour editor. A static line;
706 * then on the left, a list box, and on the right, a sequence of
707 * two-part statics followed by a button.
709 static void colouredit(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
710 char *btext
, int bid
, ...) {
714 int lwid
, rwid
, rpos
;
715 const int LISTHEIGHT
= 66;
717 /* The static control. */
718 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
719 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
720 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
721 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
723 rpos
= GAPBETWEEN
+ 2 * (cp
->width
+ GAPBETWEEN
) / 3;
724 lwid
= rpos
- 2*GAPBETWEEN
;
725 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
728 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
729 r
.right
= lwid
; r
.bottom
= LISTHEIGHT
;
730 doctl(cp
, r
, "LISTBOX",
731 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
742 ltext
= va_arg(ap
, char *);
744 lid
= va_arg(ap
, int);
745 rid
= va_arg(ap
, int);
746 r
.top
= y
; r
.bottom
= STATICHEIGHT
;
747 y
+= r
.bottom
+ GAPWITHIN
;
748 r
.left
= rpos
; r
.right
= rwid
/2;
749 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, ltext
, lid
);
750 r
.left
= rpos
+ r
.right
; r
.right
= rwid
- r
.right
;
751 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_RIGHT
, 0, "", rid
);
756 r
.top
= y
+ 2*GAPWITHIN
; r
.bottom
= PUSHBTNHEIGHT
;
757 r
.left
= rpos
; r
.right
= rwid
;
758 doctl(cp
, r
, "BUTTON",
759 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
762 cp
->ypos
+= LISTHEIGHT
+ GAPBETWEEN
;
765 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
766 WPARAM wParam
, LPARAM lParam
) {
770 HFONT hfont
= (HFONT
)wParam
;
777 oldfont
= SelectObject(hdc
, hfont
);
778 GetTextMetrics(hdc
, &tm
);
779 units
= (tm
.tmHeight
<< 16) | tm
.tmAveCharWidth
;
780 SelectObject(hdc
, oldfont
);
782 SetWindowLong(hwnd
, GWL_USERDATA
, units
);
783 SetWindowLong(hwnd
, DWL_USER
, wParam
);
787 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
790 DestroyWindow (hwnd
);
796 static char savedsession
[2048];
798 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
799 WPARAM wParam
, LPARAM lParam
) {
802 enum { controlstartvalue
= 1000,
823 /* Accelerators used: [aco] dehlnprstwx */
824 ctlposinit(&cp
, hwnd
);
827 "Host &Name", IDC_HOSTSTATIC
, IDC_HOST
, 75,
828 "&Port", IDC_PORTSTATIC
, IDC_PORT
, 25, NULL
);
829 if (backends
[2].backend
== NULL
) {
830 /* this is PuTTYtel, so only two protocols available */
831 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
833 "&Telnet", IDC_PROTTELNET
, NULL
);
835 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
837 "&Telnet", IDC_PROTTELNET
,
845 sesssaver(&cp
, "Stor&ed Sessions",
846 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
847 "&Load", IDC_SESSLOAD
,
848 "&Save", IDC_SESSSAVE
,
849 "&Delete", IDC_SESSDEL
, NULL
);
851 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
852 checkbox(&cp
, "&Warn on Close", IDC_CLOSEWARN
);
854 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
855 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
856 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
857 for (i
= 0; i
< nsessions
; i
++)
858 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
859 0, (LPARAM
) (sessions
[i
]));
860 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
861 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
862 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
863 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
864 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
868 * Button release should trigger WM_OK if there was a
869 * previous double click on the session list.
873 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
876 switch (LOWORD(wParam
)) {
880 if (HIWORD(wParam
) == BN_CLICKED
||
881 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
882 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
883 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
884 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
885 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
886 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
887 cfg
.port
= i ?
22 : 23;
888 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
893 if (HIWORD(wParam
) == EN_CHANGE
)
894 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
898 if (HIWORD(wParam
) == EN_CHANGE
)
899 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
902 if (HIWORD(wParam
) == BN_CLICKED
||
903 HIWORD(wParam
) == BN_DOUBLECLICKED
)
904 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
907 if (HIWORD(wParam
) == BN_CLICKED
||
908 HIWORD(wParam
) == BN_DOUBLECLICKED
)
909 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
912 if (HIWORD(wParam
) == EN_CHANGE
) {
913 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
915 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
916 savedsession
, sizeof(savedsession
)-1);
917 savedsession
[sizeof(savedsession
)-1] = '\0';
921 if (HIWORD(wParam
) == BN_CLICKED
||
922 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
927 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
929 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
935 strcpy (str
, sessions
[n
]);
937 save_settings (str
, !!strcmp(str
, "Default Settings"), &cfg
);
938 get_sesslist (FALSE
);
940 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
942 for (i
= 0; i
< nsessions
; i
++)
943 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
944 0, (LPARAM
) (sessions
[i
]));
945 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
951 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
952 HIWORD(wParam
) != BN_CLICKED
&&
953 HIWORD(wParam
) != BN_DOUBLECLICKED
)
955 if (LOWORD(wParam
) == IDC_SESSLIST
&&
956 HIWORD(wParam
) != LBN_DBLCLK
)
959 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
965 load_settings (sessions
[n
],
966 !!strcmp(sessions
[n
], "Default Settings"),
968 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
969 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
970 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
971 (cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
972 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
));
973 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
974 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
975 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
978 if (LOWORD(wParam
) == IDC_SESSLIST
) {
980 * A double-click on a saved session should
981 * actually start the session, not just load it.
982 * Unless it's Default Settings or some other
983 * host-less set of saved settings.
992 if (HIWORD(wParam
) == BN_CLICKED
||
993 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
994 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
996 if (n
== LB_ERR
|| n
== 0) {
1000 del_settings(sessions
[n
]);
1001 get_sesslist (FALSE
);
1002 get_sesslist (TRUE
);
1003 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1005 for (i
= 0; i
< nsessions
; i
++)
1006 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1007 0, (LPARAM
) (sessions
[i
]));
1008 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1013 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1016 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
1017 WPARAM wParam
, LPARAM lParam
) {
1019 enum { controlstartvalue
= 1000,
1045 /* Accelerators used: [aco] 4?ehiklmnprsuvxy */
1046 ctlposinit(&cp
, hwnd
);
1047 radioline(&cp
, "Action of Backspace:", IDC_DELSTATIC
, 2,
1048 "Control-&H", IDC_DEL008
,
1049 "Control-&? (127)", IDC_DEL127
, NULL
);
1050 radioline(&cp
, "Action of Home and End:", IDC_HOMESTATIC
, 2,
1051 "&Standard", IDC_HOMETILDE
,
1052 "&rxvt", IDC_HOMERXVT
, NULL
);
1053 radioline(&cp
, "Function key and keypad layout:", IDC_FUNCSTATIC
, 3,
1054 "&VT400", IDC_FUNCTILDE
,
1055 "&Linux", IDC_FUNCLINUX
,
1056 "&Xterm R6", IDC_FUNCXTERM
, NULL
);
1057 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1058 "&Normal", IDC_CURNORMAL
,
1059 "A&pplication", IDC_CURAPPLIC
, NULL
);
1060 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1061 "Nor&mal", IDC_KPNORMAL
,
1062 "Appl&ication", IDC_KPAPPLIC
,
1063 "N&etHack", IDC_KPNH
, NULL
);
1064 checkbox(&cp
, "ALT-F&4 is special (closes window)", IDC_ALTF4
);
1065 checkbox(&cp
, "ALT-Space is special (S&ystem menu)", IDC_ALTSPACE
);
1066 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1067 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1069 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1070 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1071 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1072 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1073 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCXTERM
,
1075 (cfg
.funky_type
==2 ? IDC_FUNCXTERM
1078 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1079 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1080 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1081 cfg
.nethack_keypad ? IDC_KPNH
:
1082 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1083 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1084 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1085 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1086 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1089 if (HIWORD(wParam
) == BN_CLICKED
||
1090 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1091 switch (LOWORD(wParam
)) {
1094 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1098 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1105 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1109 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1110 cfg
.nethack_keypad
= FALSE
;
1113 cfg
.app_keypad
= FALSE
;
1114 cfg
.nethack_keypad
= TRUE
;
1118 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1121 if (HIWORD(wParam
) == BN_CLICKED
||
1122 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1123 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1126 if (HIWORD(wParam
) == BN_CLICKED
||
1127 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1128 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1131 if (HIWORD(wParam
) == BN_CLICKED
||
1132 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1133 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1136 if (HIWORD(wParam
) == BN_CLICKED
||
1137 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1138 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1142 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1145 static void fmtfont (char *buf
) {
1146 sprintf (buf
, "Font: %s, ", cfg
.font
);
1148 strcat(buf
, "bold, ");
1149 if (cfg
.fontheight
== 0)
1150 strcat (buf
, "default height");
1152 sprintf (buf
+strlen(buf
), "%d-%s",
1153 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1154 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1157 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
1158 WPARAM wParam
, LPARAM lParam
) {
1162 char fontstatic
[256];
1163 enum { controlstartvalue
= 1000,
1183 /* Accelerators used: [aco] dghlmnprsw */
1184 ctlposinit(&cp
, hwnd
);
1186 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 33,
1187 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 33,
1188 "&Scrollback", IDC_SAVESTATIC
, IDC_SAVEEDIT
, 33,
1190 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1191 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1192 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1193 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1194 checkbox(&cp
, "Bee&p enabled", IDC_BEEP
);
1195 checkbox(&cp
, "Use Back&ground colour erase", IDC_BCE
);
1196 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1198 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1199 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1200 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1201 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1202 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1203 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1204 fmtfont (fontstatic
);
1205 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1206 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1207 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1208 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1211 switch (LOWORD(wParam
)) {
1213 if (HIWORD(wParam
) == BN_CLICKED
||
1214 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1215 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1218 if (HIWORD(wParam
) == BN_CLICKED
||
1219 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1220 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1223 if (HIWORD(wParam
) == BN_CLICKED
||
1224 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1225 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1228 if (HIWORD(wParam
) == EN_CHANGE
)
1229 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1232 if (HIWORD(wParam
) == EN_CHANGE
)
1233 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1236 if (HIWORD(wParam
) == EN_CHANGE
)
1237 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1239 case IDC_CHOOSEFONT
:
1240 lf
.lfHeight
= cfg
.fontheight
;
1241 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1242 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1243 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1244 lf
.lfCharSet
= cfg
.fontcharset
;
1245 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1246 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1247 lf
.lfQuality
= DEFAULT_QUALITY
;
1248 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1249 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1250 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1252 cf
.lStructSize
= sizeof(cf
);
1253 cf
.hwndOwner
= hwnd
;
1255 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1256 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1258 if (ChooseFont (&cf
)) {
1259 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1260 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1261 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1262 cfg
.fontcharset
= lf
.lfCharSet
;
1263 cfg
.fontheight
= lf
.lfHeight
;
1264 fmtfont (fontstatic
);
1265 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1269 if (HIWORD(wParam
) == BN_CLICKED
||
1270 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1271 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1274 if (HIWORD(wParam
) == BN_CLICKED
||
1275 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1276 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1279 if (HIWORD(wParam
) == BN_CLICKED
||
1280 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1281 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1286 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1289 static int CALLBACK
WindowProc (HWND hwnd
, UINT msg
,
1290 WPARAM wParam
, LPARAM lParam
) {
1292 enum { controlstartvalue
= 1000,
1303 /* Accelerators used: [aco] bikty */
1304 ctlposinit(&cp
, hwnd
);
1307 "Initial window &title:", IDC_WINTITLE
, IDC_WINEDIT
, 100,
1309 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1310 checkbox(&cp
, "&Blinking cursor", IDC_BLINKCUR
);
1311 checkbox(&cp
, "Displa&y scrollbar", IDC_SCROLLBAR
);
1312 checkbox(&cp
, "Loc&k Window size", IDC_LOCKSIZE
);
1314 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1315 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1316 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1317 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1318 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1321 switch (LOWORD(wParam
)) {
1323 if (HIWORD(wParam
) == BN_CLICKED
||
1324 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1325 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1328 if (HIWORD(wParam
) == BN_CLICKED
||
1329 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1330 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1333 if (HIWORD(wParam
) == BN_CLICKED
||
1334 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1335 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1338 if (HIWORD(wParam
) == BN_CLICKED
||
1339 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1340 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1343 if (HIWORD(wParam
) == EN_CHANGE
)
1344 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1345 sizeof(cfg
.wintitle
)-1);
1350 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1353 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
1354 WPARAM wParam
, LPARAM lParam
) {
1357 enum { controlstartvalue
= 1000,
1379 /* Accelerators used: [aco] bdflrstuv */
1380 ctlposinit(&cp
, hwnd
);
1382 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1383 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
);
1384 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1385 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1386 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1387 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1389 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1390 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1391 "&BSD (commonplace)", IDC_EMBSD
,
1392 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1395 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1396 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1397 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1399 char *p
= cfg
.environmt
;
1401 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1406 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1407 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1410 switch (LOWORD(wParam
)) {
1412 if (HIWORD(wParam
) == EN_CHANGE
)
1413 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1414 sizeof(cfg
.termtype
)-1);
1417 if (HIWORD(wParam
) == EN_CHANGE
)
1418 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1419 sizeof(cfg
.termspeed
)-1);
1422 if (HIWORD(wParam
) == EN_CHANGE
)
1423 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1424 sizeof(cfg
.username
)-1);
1428 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1431 if (HIWORD(wParam
) == BN_CLICKED
||
1432 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1433 char str
[sizeof(cfg
.environmt
)];
1435 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
1440 p
= str
+ strlen(str
);
1442 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
1452 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
1454 p
[strlen(str
)+1] = '\0';
1455 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
1457 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
1458 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
1460 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
1461 MB_OK
| MB_ICONERROR
);
1466 if (HIWORD(wParam
) != BN_CLICKED
&&
1467 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1469 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
1475 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
1502 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1505 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
1506 WPARAM wParam
, LPARAM lParam
) {
1509 char filename
[sizeof(cfg
.keyfile
)];
1510 enum { controlstartvalue
= 1000,
1534 /* Accelerators used: [aco] 123abdkmprtuw */
1535 ctlposinit(&cp
, hwnd
);
1537 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1538 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1540 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1542 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1543 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1545 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1546 editbutton(&cp
, "Private &key file for authentication:",
1547 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1548 radioline(&cp
, "Preferred SSH protocol version:",
1549 IDC_SSHPROTSTATIC
, 2,
1550 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1551 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1552 "&3DES", IDC_CIPHER3DES
,
1553 "&Blowfish", IDC_CIPHERBLOWF
,
1554 "&DES", IDC_CIPHERDES
, NULL
);
1557 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1558 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1559 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1560 CheckDlgButton (hwnd
, IDC_AGENTFWD
, cfg
.agentfwd
);
1561 CheckRadioButton (hwnd
, IDC_CIPHER3DES
, IDC_CIPHERDES
,
1562 cfg
.cipher
== CIPHER_BLOWFISH ? IDC_CIPHERBLOWF
:
1563 cfg
.cipher
== CIPHER_DES ? IDC_CIPHERDES
:
1565 CheckRadioButton (hwnd
, IDC_SSHPROT1
, IDC_SSHPROT2
,
1566 cfg
.sshprot
== 1 ? IDC_SSHPROT1
: IDC_SSHPROT2
);
1567 CheckDlgButton (hwnd
, IDC_AUTHTIS
, cfg
.try_tis_auth
);
1568 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1569 SetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
);
1572 switch (LOWORD(wParam
)) {
1574 if (HIWORD(wParam
) == EN_CHANGE
)
1575 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1576 sizeof(cfg
.termtype
)-1);
1579 if (HIWORD(wParam
) == EN_CHANGE
)
1580 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1581 sizeof(cfg
.username
)-1);
1584 if (HIWORD(wParam
) == BN_CLICKED
||
1585 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1586 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
1589 if (HIWORD(wParam
) == BN_CLICKED
||
1590 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1591 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
1593 case IDC_CIPHER3DES
:
1594 case IDC_CIPHERBLOWF
:
1596 if (HIWORD(wParam
) == BN_CLICKED
||
1597 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1598 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
1599 cfg
.cipher
= CIPHER_3DES
;
1600 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
1601 cfg
.cipher
= CIPHER_BLOWFISH
;
1602 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
1603 cfg
.cipher
= CIPHER_DES
;
1608 if (HIWORD(wParam
) == BN_CLICKED
||
1609 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1610 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
1612 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
1617 if (HIWORD(wParam
) == BN_CLICKED
||
1618 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1619 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
1622 if (HIWORD(wParam
) == EN_CHANGE
)
1623 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
1624 sizeof(cfg
.keyfile
)-1);
1627 if (HIWORD(wParam
) == EN_CHANGE
)
1628 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
1629 sizeof(cfg
.remote_cmd
)-1);
1633 * FIXME: this crashes. Find out why.
1635 memset(&of
, 0, sizeof(of
));
1636 #ifdef OPENFILENAME_SIZE_VERSION_400
1637 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1639 of
.lStructSize
= sizeof(of
);
1641 of
.hwndOwner
= hwnd
;
1642 of
.lpstrFilter
= "All Files\0*\0\0\0";
1643 of
.lpstrCustomFilter
= NULL
;
1644 of
.nFilterIndex
= 1;
1645 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
1646 of
.nMaxFile
= sizeof(filename
);
1647 of
.lpstrFileTitle
= NULL
;
1648 of
.lpstrInitialDir
= NULL
;
1649 of
.lpstrTitle
= "Select Public Key File";
1651 if (GetOpenFileName(&of
)) {
1652 strcpy(cfg
.keyfile
, filename
);
1653 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1659 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1662 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1663 WPARAM wParam
, LPARAM lParam
) {
1666 enum { controlstartvalue
= 1000,
1679 /* Accelerators used: [aco] stwx */
1680 ctlposinit(&cp
, hwnd
);
1681 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1682 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1683 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1685 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1686 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1687 "&to class", IDC_CCSTATIC2
);
1689 CheckRadioButton (hwnd
, IDC_MBWINDOWS
, IDC_MBXTERM
,
1690 cfg
.mouse_is_xterm ? IDC_MBXTERM
: IDC_MBWINDOWS
);
1692 static int tabs
[4] = {25, 61, 96, 128};
1693 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_SETTABSTOPS
, 4,
1696 for (i
=0; i
<256; i
++) {
1698 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1699 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1701 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_ADDSTRING
, 0,
1706 switch (LOWORD(wParam
)) {
1709 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
1715 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
1720 for (i
=0; i
<256; i
++)
1721 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
1724 cfg
.wordness
[i
] = n
;
1725 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1726 LB_DELETESTRING
, i
, 0);
1727 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1728 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1730 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1740 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1743 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
1744 WPARAM wParam
, LPARAM lParam
) {
1745 static const char *const colours
[] = {
1746 "Default Foreground", "Default Bold Foreground",
1747 "Default Background", "Default Bold Background",
1748 "Cursor Text", "Cursor Colour",
1749 "ANSI Black", "ANSI Black Bold",
1750 "ANSI Red", "ANSI Red Bold",
1751 "ANSI Green", "ANSI Green Bold",
1752 "ANSI Yellow", "ANSI Yellow Bold",
1753 "ANSI Blue", "ANSI Blue Bold",
1754 "ANSI Magenta", "ANSI Magenta Bold",
1755 "ANSI Cyan", "ANSI Cyan Bold",
1756 "ANSI White", "ANSI White Bold"
1758 static const int permanent
[] = {
1759 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1760 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1761 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1764 enum { controlstartvalue
= 1000,
1780 /* Accelerators used: [aco] bmlu */
1781 ctlposinit(&cp
, hwnd
);
1782 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
1783 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
1784 colouredit(&cp
, "Select a colo&ur and click to modify it:",
1785 IDC_STATIC
, IDC_LIST
,
1786 "&Modify...", IDC_CHANGE
,
1787 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
1788 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
1789 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
1791 CheckDlgButton (hwnd
, IDC_BOLDCOLOUR
, cfg
.bold_colour
);
1792 CheckDlgButton (hwnd
, IDC_PALETTE
, cfg
.try_palette
);
1795 for (i
=0; i
<22; i
++)
1796 if (cfg
.bold_colour
|| permanent
[i
])
1797 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_ADDSTRING
, 0,
1798 (LPARAM
) colours
[i
]);
1800 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_SETCURSEL
, 0, 0);
1801 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[0][0], FALSE
);
1802 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[0][1], FALSE
);
1803 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[0][2], FALSE
);
1806 switch (LOWORD(wParam
)) {
1807 case IDC_BOLDCOLOUR
:
1808 if (HIWORD(wParam
) == BN_CLICKED
||
1809 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1811 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
1812 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
1813 if (cfg
.bold_colour
&& n
!=22) {
1814 for (i
=0; i
<22; i
++)
1816 SendDlgItemMessage (hwnd
, IDC_LIST
,
1818 (LPARAM
) colours
[i
]);
1819 } else if (!cfg
.bold_colour
&& n
!=12) {
1822 SendDlgItemMessage (hwnd
, IDC_LIST
,
1823 LB_DELETESTRING
, i
, 0);
1828 if (HIWORD(wParam
) == BN_CLICKED
||
1829 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1830 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
1833 if (HIWORD(wParam
) == LBN_DBLCLK
||
1834 HIWORD(wParam
) == LBN_SELCHANGE
) {
1835 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
1837 if (!cfg
.bold_colour
)
1838 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1839 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1840 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1841 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1845 if (HIWORD(wParam
) == BN_CLICKED
||
1846 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1847 static CHOOSECOLOR cc
;
1848 static DWORD custom
[16] = {0}; /* zero initialisers */
1849 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
1851 if (!cfg
.bold_colour
)
1852 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1853 cc
.lStructSize
= sizeof(cc
);
1854 cc
.hwndOwner
= hwnd
;
1855 cc
.hInstance
= (HWND
)hinst
;
1856 cc
.lpCustColors
= custom
;
1857 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1859 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1860 if (ChooseColor(&cc
)) {
1862 (unsigned char) (cc
.rgbResult
& 0xFF);
1864 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1866 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1867 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
1869 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
1871 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
1879 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1882 static int CALLBACK
TranslationProc (HWND hwnd
, UINT msg
,
1883 WPARAM wParam
, LPARAM lParam
) {
1885 enum { controlstartvalue
= 1000,
1900 /* Accelerators used: [aco] beiknpsx */
1901 ctlposinit(&cp
, hwnd
);
1903 "Handling of VT100 line drawing characters:", IDC_VTSTATIC
,
1904 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
1905 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
1906 "Use font in O&EM mode only", IDC_VTOEMONLY
,
1907 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1908 IDC_VTPOORMAN
, NULL
);
1910 "Character set translation:", IDC_XLATSTATIC
,
1911 "&None", IDC_NOXLAT
,
1912 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
1913 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
, NULL
);
1914 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch", IDC_CAPSLOCKCYR
);
1916 CheckRadioButton (hwnd
, IDC_NOXLAT
, IDC_88592WIN1250
,
1917 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
1918 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
1920 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1921 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
1922 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
1923 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
1924 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
1927 switch (LOWORD(wParam
)) {
1929 case IDC_KOI8WIN1251
:
1930 case IDC_88592WIN1250
:
1931 cfg
.xlat_enablekoiwin
=
1932 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
1933 cfg
.xlat_88592w1250
=
1934 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
1936 case IDC_CAPSLOCKCYR
:
1937 if (HIWORD(wParam
) == BN_CLICKED
||
1938 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1939 cfg
.xlat_capslockcyr
=
1940 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
1943 case IDC_VTXWINDOWS
:
1948 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
1949 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
1950 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
1955 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1958 static DLGPROC panelproc
[NPANELS
] = {
1959 ConnectionProc
, KeyboardProc
, TerminalProc
, WindowProc
,
1960 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, TranslationProc
1963 static char *names
[NPANELS
] = {
1964 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
1965 "SSH", "Selection", "Colours", "Translation"
1968 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
1969 static int reconfp
[RECONF_NPANELS
] = { 0, 1, 2, 3, 6, 7, 8};
1971 static HWND
makesubdialog(HWND hwnd
, int x
, int y
, int w
, int h
,
1972 int n
, int dlgtype
) {
1976 r
.left
= x
; r
.top
= y
;
1977 r
.right
= r
.left
+ w
; r
.bottom
= r
.top
+ h
;
1978 MapDialogRect(hwnd
, &r
);
1979 ret
= CreateWindowEx(WS_EX_CONTROLPARENT
,
1980 WC_DIALOG
, "", /* no title */
1981 WS_CHILD
| WS_VISIBLE
| DS_SETFONT
,
1983 r
.right
-r
.left
, r
.bottom
-r
.top
,
1984 hwnd
, (HMENU
)IDC_SUBDLG
,
1986 SetWindowLong (ret
, DWL_DLGPROC
, (LONG
)panelproc
[n
]);
1987 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1988 SendMessage (ret
, WM_SETFONT
, font
, MAKELPARAM(0, 0));
1989 SendMessage (ret
, WM_INITDIALOG
, dlgtype
, 0);
1993 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1994 WPARAM wParam
, LPARAM lParam
,
1995 int npanels
, int dlgtype
,
1996 int *panelnums
, HWND
*page
) {
2001 { /* centre the window */
2004 hw
= GetDesktopWindow();
2005 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
2006 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
2007 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
2008 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
2012 r
.left
= 3; r
.right
= r
.left
+ 174;
2013 r
.top
= 3; r
.bottom
= r
.top
+ 193;
2014 MapDialogRect(hwnd
, &r
);
2015 tabctl
= CreateWindowEx(0, WC_TABCONTROL
, "",
2016 WS_CHILD
| WS_VISIBLE
|
2017 WS_TABSTOP
| TCS_MULTILINE
,
2019 r
.right
-r
.left
, r
.bottom
-r
.top
,
2020 hwnd
, (HMENU
)IDC_TAB
, hinst
, NULL
);
2024 ctlposinit2(&cp
, hwnd
);
2025 ersatztab(&cp
, "Category:", IDC_TABSTATIC1
, IDC_TABLIST
,
2028 WPARAM font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2029 SendMessage(tabctl
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
2033 if (tabctl
) { /* initialise the tab control */
2037 for (i
=0; i
<npanels
; i
++) {
2038 tab
.mask
= TCIF_TEXT
;
2039 tab
.pszText
= names
[panelnums
[i
]];
2040 TabCtrl_InsertItem (tabctl
, i
, &tab
);
2045 for (i
=0; i
<npanels
; i
++) {
2046 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_ADDSTRING
,
2047 0, (LPARAM
)names
[panelnums
[i
]]);
2049 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_SETCURSEL
, 0, 0);
2051 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[0], dlgtype
);
2055 if (LOWORD(wParam
) == IDC_TAB
&&
2056 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
2057 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
2059 DestroyWindow (*page
);
2060 *page
= makesubdialog(hwnd
, 6, 30, 168, 163,
2061 panelnums
[i
], dlgtype
);
2062 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
2067 switch (LOWORD(wParam
)) {
2069 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
2070 HWND tablist
= GetDlgItem (hwnd
, IDC_TABLIST
);
2071 int i
= SendMessage (tablist
, CB_GETCURSEL
, 0, 0);
2073 DestroyWindow (*page
);
2074 *page
= makesubdialog(hwnd
, 6, 30, 168, 163,
2075 panelnums
[i
], dlgtype
);
2076 SetFocus(tablist
); /* ensure focus stays */
2082 EndDialog (hwnd
, 1);
2087 EndDialog (hwnd
, 0);
2092 EndDialog (hwnd
, 0);
2095 /* Grrr Explorer will maximize Dialogs! */
2097 if (wParam
== SIZE_MAXIMIZED
)
2104 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2105 WPARAM wParam
, LPARAM lParam
) {
2106 static HWND page
= NULL
;
2108 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2110 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
2111 EnableWindow(hwnd
, 0);
2112 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2113 GetParent(hwnd
), AboutProc
);
2114 EnableWindow(hwnd
, 1);
2115 SetActiveWindow(hwnd
);
2117 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2118 MAIN_NPANELS
, 0, mainp
, &page
);
2121 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2122 WPARAM wParam
, LPARAM lParam
) {
2124 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2125 RECONF_NPANELS
, 1, reconfp
, &page
);
2128 int do_config (void) {
2132 savedsession
[0] = '\0';
2133 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2134 get_sesslist(FALSE
);
2139 int do_reconfig (HWND hwnd
) {
2143 backup_cfg
= cfg
; /* structure copy */
2144 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2146 cfg
= backup_cfg
; /* structure copy */
2153 void logevent (char *string
) {
2154 if (nevents
>= negsize
) {
2156 events
= srealloc (events
, negsize
* sizeof(*events
));
2158 events
[nevents
] = smalloc(1+strlen(string
));
2159 strcpy (events
[nevents
], string
);
2163 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2165 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2166 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2170 void showeventlog (HWND hwnd
) {
2172 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2174 ShowWindow (logbox
, SW_SHOWNORMAL
);
2178 void showabout (HWND hwnd
) {
2180 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2182 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2186 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2187 char *keystr
, char *fingerprint
) {
2190 static const char absentmsg
[] =
2191 "The server's host key is not cached in the registry. You\n"
2192 "have no guarantee that the server is the computer you\n"
2194 "The server's key fingerprint is:\n"
2196 "If you trust this host, hit Yes to add the key to\n"
2197 "PuTTY's cache and carry on connecting.\n"
2198 "If you do not trust this host, hit No to abandon the\n"
2201 static const char wrongmsg
[] =
2202 "WARNING - POTENTIAL SECURITY BREACH!\n"
2204 "The server's host key does not match the one PuTTY has\n"
2205 "cached in the registry. This means that either the\n"
2206 "server administrator has changed the host key, or you\n"
2207 "have actually connected to another computer pretending\n"
2208 "to be the server.\n"
2209 "The new key fingerprint is:\n"
2211 "If you were expecting this change and trust the new key,\n"
2212 "hit Yes to update PuTTY's cache and continue connecting.\n"
2213 "If you want to carry on connecting but without updating\n"
2214 "the cache, hit No.\n"
2215 "If you want to abandon the connection completely, hit\n"
2216 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2219 static const char mbtitle
[] = "PuTTY Security Alert";
2222 char message
[160+ /* sensible fingerprint max size */
2223 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2224 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2227 * Verify the key against the registry.
2229 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2231 if (ret
== 0) /* success - key matched OK */
2233 if (ret
== 2) { /* key was different */
2235 sprintf(message
, wrongmsg
, fingerprint
);
2236 mbret
= MessageBox(NULL
, message
, mbtitle
,
2237 MB_ICONWARNING
| MB_YESNOCANCEL
);
2239 store_host_key(host
, port
, keytype
, keystr
);
2240 if (mbret
== IDCANCEL
)
2243 if (ret
== 1) { /* key was absent */
2245 sprintf(message
, absentmsg
, fingerprint
);
2246 mbret
= MessageBox(NULL
, message
, mbtitle
,
2247 MB_ICONWARNING
| MB_YESNO
);
2250 store_host_key(host
, port
, keytype
, keystr
);