20 #define MAIN_NPANELS 9
21 #define RECONF_NPANELS 6
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
);
826 "Host &Name", IDC_HOSTSTATIC
, IDC_HOST
, 75,
827 "&Port", IDC_PORTSTATIC
, IDC_PORT
, 25, NULL
);
828 if (backends
[2].backend
== NULL
) {
829 /* this is PuTTYtel, so only two protocols available */
830 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
832 "&Telnet", IDC_PROTTELNET
, NULL
);
834 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
836 "&Telnet", IDC_PROTTELNET
,
844 sesssaver(&cp
, "Stor&ed Sessions",
845 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
846 "&Load", IDC_SESSLOAD
,
847 "&Save", IDC_SESSSAVE
,
848 "&Delete", IDC_SESSDEL
, NULL
);
849 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
850 checkbox(&cp
, "&Warn on Close", IDC_CLOSEWARN
);
852 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
853 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
854 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
855 for (i
= 0; i
< nsessions
; i
++)
856 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
857 0, (LPARAM
) (sessions
[i
]));
858 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
859 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
860 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
861 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
862 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
866 * Button release should trigger WM_OK if there was a
867 * previous double click on the session list.
871 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
874 switch (LOWORD(wParam
)) {
878 if (HIWORD(wParam
) == BN_CLICKED
||
879 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
880 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
881 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
882 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
883 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
884 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
885 cfg
.port
= i ?
22 : 23;
886 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
891 if (HIWORD(wParam
) == EN_CHANGE
)
892 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
896 if (HIWORD(wParam
) == EN_CHANGE
)
897 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
900 if (HIWORD(wParam
) == BN_CLICKED
||
901 HIWORD(wParam
) == BN_DOUBLECLICKED
)
902 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
905 if (HIWORD(wParam
) == BN_CLICKED
||
906 HIWORD(wParam
) == BN_DOUBLECLICKED
)
907 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
910 if (HIWORD(wParam
) == EN_CHANGE
) {
911 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
913 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
914 savedsession
, sizeof(savedsession
)-1);
915 savedsession
[sizeof(savedsession
)-1] = '\0';
919 if (HIWORD(wParam
) == BN_CLICKED
||
920 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
925 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
927 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
933 strcpy (str
, sessions
[n
]);
935 save_settings (str
, !!strcmp(str
, "Default Settings"), &cfg
);
936 get_sesslist (FALSE
);
938 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
940 for (i
= 0; i
< nsessions
; i
++)
941 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
942 0, (LPARAM
) (sessions
[i
]));
943 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
949 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
950 HIWORD(wParam
) != BN_CLICKED
&&
951 HIWORD(wParam
) != BN_DOUBLECLICKED
)
953 if (LOWORD(wParam
) == IDC_SESSLIST
&&
954 HIWORD(wParam
) != LBN_DBLCLK
)
957 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
963 load_settings (sessions
[n
],
964 !!strcmp(sessions
[n
], "Default Settings"),
966 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
967 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
968 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
969 (cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
970 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
));
971 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
972 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
973 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
976 if (LOWORD(wParam
) == IDC_SESSLIST
) {
978 * A double-click on a saved session should
979 * actually start the session, not just load it.
980 * Unless it's Default Settings or some other
981 * host-less set of saved settings.
990 if (HIWORD(wParam
) == BN_CLICKED
||
991 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
992 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
994 if (n
== LB_ERR
|| n
== 0) {
998 del_settings(sessions
[n
]);
999 get_sesslist (FALSE
);
1000 get_sesslist (TRUE
);
1001 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1003 for (i
= 0; i
< nsessions
; i
++)
1004 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1005 0, (LPARAM
) (sessions
[i
]));
1006 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1011 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1014 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
1015 WPARAM wParam
, LPARAM lParam
) {
1017 enum { controlstartvalue
= 1000,
1043 /* Accelerators used: [aco] 4?ehiklmnprsuvxy */
1044 ctlposinit(&cp
, hwnd
);
1045 radioline(&cp
, "Action of Backspace:", IDC_DELSTATIC
, 2,
1046 "Control-&H", IDC_DEL008
,
1047 "Control-&? (127)", IDC_DEL127
, NULL
);
1048 radioline(&cp
, "Action of Home and End:", IDC_HOMESTATIC
, 2,
1049 "&Standard", IDC_HOMETILDE
,
1050 "&rxvt", IDC_HOMERXVT
, NULL
);
1051 radioline(&cp
, "Function key and keypad layout:", IDC_FUNCSTATIC
, 3,
1052 "&VT400", IDC_FUNCTILDE
,
1053 "&Linux", IDC_FUNCLINUX
,
1054 "&Xterm R6", IDC_FUNCXTERM
, NULL
);
1055 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1056 "&Normal", IDC_CURNORMAL
,
1057 "A&pplication", IDC_CURAPPLIC
, NULL
);
1058 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1059 "Nor&mal", IDC_KPNORMAL
,
1060 "Appl&ication", IDC_KPAPPLIC
,
1061 "N&etHack", IDC_KPNH
, NULL
);
1062 checkbox(&cp
, "ALT-F&4 is special (closes window)", IDC_ALTF4
);
1063 checkbox(&cp
, "ALT-Space is special (S&ystem menu)", IDC_ALTSPACE
);
1064 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1065 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1067 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1068 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1069 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1070 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1071 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCXTERM
,
1073 (cfg
.funky_type
==2 ? IDC_FUNCXTERM
1076 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1077 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1078 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1079 cfg
.nethack_keypad ? IDC_KPNH
:
1080 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1081 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1082 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1083 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1084 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1087 if (HIWORD(wParam
) == BN_CLICKED
||
1088 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1089 switch (LOWORD(wParam
)) {
1092 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1096 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1103 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1107 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1108 cfg
.nethack_keypad
= FALSE
;
1111 cfg
.app_keypad
= FALSE
;
1112 cfg
.nethack_keypad
= TRUE
;
1116 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1119 if (HIWORD(wParam
) == BN_CLICKED
||
1120 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1121 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1124 if (HIWORD(wParam
) == BN_CLICKED
||
1125 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1126 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1129 if (HIWORD(wParam
) == BN_CLICKED
||
1130 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1131 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1134 if (HIWORD(wParam
) == BN_CLICKED
||
1135 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1136 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1140 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1143 static void fmtfont (char *buf
) {
1144 sprintf (buf
, "Font: %s, ", cfg
.font
);
1146 strcat(buf
, "bold, ");
1147 if (cfg
.fontheight
== 0)
1148 strcat (buf
, "default height");
1150 sprintf (buf
+strlen(buf
), "%d-%s",
1151 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1152 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1155 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
1156 WPARAM wParam
, LPARAM lParam
) {
1160 char fontstatic
[256];
1161 enum { controlstartvalue
= 1000,
1181 /* Accelerators used: [aco] dghlmnprsw */
1182 ctlposinit(&cp
, hwnd
);
1184 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 33,
1185 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 33,
1186 "&Scrollback", IDC_SAVESTATIC
, IDC_SAVEEDIT
, 33,
1188 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1189 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1190 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1191 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1192 checkbox(&cp
, "Bee&p enabled", IDC_BEEP
);
1193 checkbox(&cp
, "Use Back&ground colour erase", IDC_BCE
);
1194 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1196 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1197 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1198 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1199 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1200 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1201 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1202 fmtfont (fontstatic
);
1203 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1204 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1205 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1206 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1209 switch (LOWORD(wParam
)) {
1211 if (HIWORD(wParam
) == BN_CLICKED
||
1212 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1213 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1216 if (HIWORD(wParam
) == BN_CLICKED
||
1217 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1218 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1221 if (HIWORD(wParam
) == BN_CLICKED
||
1222 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1223 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1226 if (HIWORD(wParam
) == EN_CHANGE
)
1227 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1230 if (HIWORD(wParam
) == EN_CHANGE
)
1231 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1234 if (HIWORD(wParam
) == EN_CHANGE
)
1235 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1237 case IDC_CHOOSEFONT
:
1238 lf
.lfHeight
= cfg
.fontheight
;
1239 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1240 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1241 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1242 lf
.lfCharSet
= cfg
.fontcharset
;
1243 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1244 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1245 lf
.lfQuality
= DEFAULT_QUALITY
;
1246 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1247 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1248 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1250 cf
.lStructSize
= sizeof(cf
);
1251 cf
.hwndOwner
= hwnd
;
1253 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1254 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1256 if (ChooseFont (&cf
)) {
1257 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1258 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1259 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1260 cfg
.fontcharset
= lf
.lfCharSet
;
1261 cfg
.fontheight
= lf
.lfHeight
;
1262 fmtfont (fontstatic
);
1263 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1267 if (HIWORD(wParam
) == BN_CLICKED
||
1268 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1269 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1272 if (HIWORD(wParam
) == BN_CLICKED
||
1273 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1274 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1277 if (HIWORD(wParam
) == BN_CLICKED
||
1278 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1279 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1284 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1287 static int CALLBACK
WindowProc (HWND hwnd
, UINT msg
,
1288 WPARAM wParam
, LPARAM lParam
) {
1290 enum { controlstartvalue
= 1000,
1301 /* Accelerators used: [aco] bikty */
1302 ctlposinit(&cp
, hwnd
);
1304 "Initial window &title:", IDC_WINTITLE
, IDC_WINEDIT
, 100,
1306 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1307 checkbox(&cp
, "&Blinking cursor", IDC_BLINKCUR
);
1308 checkbox(&cp
, "Displa&y scrollbar", IDC_SCROLLBAR
);
1309 checkbox(&cp
, "Loc&k Window size", IDC_LOCKSIZE
);
1311 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1312 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1313 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1314 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1315 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1318 switch (LOWORD(wParam
)) {
1320 if (HIWORD(wParam
) == BN_CLICKED
||
1321 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1322 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1325 if (HIWORD(wParam
) == BN_CLICKED
||
1326 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1327 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1330 if (HIWORD(wParam
) == BN_CLICKED
||
1331 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1332 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1335 if (HIWORD(wParam
) == BN_CLICKED
||
1336 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1337 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1340 if (HIWORD(wParam
) == EN_CHANGE
)
1341 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1342 sizeof(cfg
.wintitle
)-1);
1347 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1350 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
1351 WPARAM wParam
, LPARAM lParam
) {
1354 enum { controlstartvalue
= 1000,
1376 /* Accelerators used: [aco] bdflrstuv */
1377 ctlposinit(&cp
, hwnd
);
1378 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1379 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
);
1380 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1381 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1382 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1383 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1385 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1386 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1387 "&BSD (commonplace)", IDC_EMBSD
,
1388 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1390 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1391 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1392 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1394 char *p
= cfg
.environmt
;
1396 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1401 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1402 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1405 switch (LOWORD(wParam
)) {
1407 if (HIWORD(wParam
) == EN_CHANGE
)
1408 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1409 sizeof(cfg
.termtype
)-1);
1412 if (HIWORD(wParam
) == EN_CHANGE
)
1413 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1414 sizeof(cfg
.termspeed
)-1);
1417 if (HIWORD(wParam
) == EN_CHANGE
)
1418 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1419 sizeof(cfg
.username
)-1);
1423 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1426 if (HIWORD(wParam
) == BN_CLICKED
||
1427 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1428 char str
[sizeof(cfg
.environmt
)];
1430 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
1435 p
= str
+ strlen(str
);
1437 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
1447 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
1449 p
[strlen(str
)+1] = '\0';
1450 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
1452 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
1453 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
1455 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
1456 MB_OK
| MB_ICONERROR
);
1461 if (HIWORD(wParam
) != BN_CLICKED
&&
1462 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1464 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
1470 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
1497 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1500 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
1501 WPARAM wParam
, LPARAM lParam
) {
1504 char filename
[sizeof(cfg
.keyfile
)];
1505 enum { controlstartvalue
= 1000,
1529 /* Accelerators used: [aco] 123abdkmprtuw */
1530 ctlposinit(&cp
, hwnd
);
1531 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1532 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1534 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1536 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1537 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1539 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1540 editbutton(&cp
, "Private &key file for authentication:",
1541 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1542 radioline(&cp
, "Preferred SSH protocol version:",
1543 IDC_SSHPROTSTATIC
, 2,
1544 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1545 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1546 "&3DES", IDC_CIPHER3DES
,
1547 "&Blowfish", IDC_CIPHERBLOWF
,
1548 "&DES", IDC_CIPHERDES
, NULL
);
1550 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1551 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1552 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1553 CheckDlgButton (hwnd
, IDC_AGENTFWD
, cfg
.agentfwd
);
1554 CheckRadioButton (hwnd
, IDC_CIPHER3DES
, IDC_CIPHERDES
,
1555 cfg
.cipher
== CIPHER_BLOWFISH ? IDC_CIPHERBLOWF
:
1556 cfg
.cipher
== CIPHER_DES ? IDC_CIPHERDES
:
1558 CheckRadioButton (hwnd
, IDC_SSHPROT1
, IDC_SSHPROT2
,
1559 cfg
.sshprot
== 1 ? IDC_SSHPROT1
: IDC_SSHPROT2
);
1560 CheckDlgButton (hwnd
, IDC_AUTHTIS
, cfg
.try_tis_auth
);
1561 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1562 SetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
);
1565 switch (LOWORD(wParam
)) {
1567 if (HIWORD(wParam
) == EN_CHANGE
)
1568 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1569 sizeof(cfg
.termtype
)-1);
1572 if (HIWORD(wParam
) == EN_CHANGE
)
1573 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1574 sizeof(cfg
.username
)-1);
1577 if (HIWORD(wParam
) == BN_CLICKED
||
1578 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1579 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
1582 if (HIWORD(wParam
) == BN_CLICKED
||
1583 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1584 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
1586 case IDC_CIPHER3DES
:
1587 case IDC_CIPHERBLOWF
:
1589 if (HIWORD(wParam
) == BN_CLICKED
||
1590 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1591 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
1592 cfg
.cipher
= CIPHER_3DES
;
1593 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
1594 cfg
.cipher
= CIPHER_BLOWFISH
;
1595 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
1596 cfg
.cipher
= CIPHER_DES
;
1601 if (HIWORD(wParam
) == BN_CLICKED
||
1602 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1603 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
1605 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
1610 if (HIWORD(wParam
) == BN_CLICKED
||
1611 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1612 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
1615 if (HIWORD(wParam
) == EN_CHANGE
)
1616 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
1617 sizeof(cfg
.keyfile
)-1);
1620 if (HIWORD(wParam
) == EN_CHANGE
)
1621 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
1622 sizeof(cfg
.remote_cmd
)-1);
1626 * FIXME: this crashes. Find out why.
1628 memset(&of
, 0, sizeof(of
));
1629 #ifdef OPENFILENAME_SIZE_VERSION_400
1630 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1632 of
.lStructSize
= sizeof(of
);
1634 of
.hwndOwner
= hwnd
;
1635 of
.lpstrFilter
= "All Files\0*\0\0\0";
1636 of
.lpstrCustomFilter
= NULL
;
1637 of
.nFilterIndex
= 1;
1638 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
1639 of
.nMaxFile
= sizeof(filename
);
1640 of
.lpstrFileTitle
= NULL
;
1641 of
.lpstrInitialDir
= NULL
;
1642 of
.lpstrTitle
= "Select Public Key File";
1644 if (GetOpenFileName(&of
)) {
1645 strcpy(cfg
.keyfile
, filename
);
1646 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1652 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1655 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1656 WPARAM wParam
, LPARAM lParam
) {
1659 enum { controlstartvalue
= 1000,
1672 /* Accelerators used: [aco] stwx */
1673 ctlposinit(&cp
, hwnd
);
1674 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1675 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1676 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1678 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1679 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1680 "&to class", IDC_CCSTATIC2
);
1682 CheckRadioButton (hwnd
, IDC_MBWINDOWS
, IDC_MBXTERM
,
1683 cfg
.mouse_is_xterm ? IDC_MBXTERM
: IDC_MBWINDOWS
);
1685 static int tabs
[4] = {25, 61, 96, 128};
1686 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_SETTABSTOPS
, 4,
1689 for (i
=0; i
<256; i
++) {
1691 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1692 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1694 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_ADDSTRING
, 0,
1699 switch (LOWORD(wParam
)) {
1702 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
1708 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
1713 for (i
=0; i
<256; i
++)
1714 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
1717 cfg
.wordness
[i
] = n
;
1718 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1719 LB_DELETESTRING
, i
, 0);
1720 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1721 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1723 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1733 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1736 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
1737 WPARAM wParam
, LPARAM lParam
) {
1738 static const char *const colours
[] = {
1739 "Default Foreground", "Default Bold Foreground",
1740 "Default Background", "Default Bold Background",
1741 "Cursor Text", "Cursor Colour",
1742 "ANSI Black", "ANSI Black Bold",
1743 "ANSI Red", "ANSI Red Bold",
1744 "ANSI Green", "ANSI Green Bold",
1745 "ANSI Yellow", "ANSI Yellow Bold",
1746 "ANSI Blue", "ANSI Blue Bold",
1747 "ANSI Magenta", "ANSI Magenta Bold",
1748 "ANSI Cyan", "ANSI Cyan Bold",
1749 "ANSI White", "ANSI White Bold"
1751 static const int permanent
[] = {
1752 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1753 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1754 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1757 enum { controlstartvalue
= 1000,
1773 /* Accelerators used: [aco] bmlu */
1774 ctlposinit(&cp
, hwnd
);
1775 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
1776 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
1777 colouredit(&cp
, "Select a colo&ur and click to modify it:",
1778 IDC_STATIC
, IDC_LIST
,
1779 "&Modify...", IDC_CHANGE
,
1780 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
1781 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
1782 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
1784 CheckDlgButton (hwnd
, IDC_BOLDCOLOUR
, cfg
.bold_colour
);
1785 CheckDlgButton (hwnd
, IDC_PALETTE
, cfg
.try_palette
);
1788 for (i
=0; i
<22; i
++)
1789 if (cfg
.bold_colour
|| permanent
[i
])
1790 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_ADDSTRING
, 0,
1791 (LPARAM
) colours
[i
]);
1793 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_SETCURSEL
, 0, 0);
1794 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[0][0], FALSE
);
1795 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[0][1], FALSE
);
1796 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[0][2], FALSE
);
1799 switch (LOWORD(wParam
)) {
1800 case IDC_BOLDCOLOUR
:
1801 if (HIWORD(wParam
) == BN_CLICKED
||
1802 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1804 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
1805 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
1806 if (cfg
.bold_colour
&& n
!=22) {
1807 for (i
=0; i
<22; i
++)
1809 SendDlgItemMessage (hwnd
, IDC_LIST
,
1811 (LPARAM
) colours
[i
]);
1812 } else if (!cfg
.bold_colour
&& n
!=12) {
1815 SendDlgItemMessage (hwnd
, IDC_LIST
,
1816 LB_DELETESTRING
, i
, 0);
1821 if (HIWORD(wParam
) == BN_CLICKED
||
1822 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1823 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
1826 if (HIWORD(wParam
) == LBN_DBLCLK
||
1827 HIWORD(wParam
) == LBN_SELCHANGE
) {
1828 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
1830 if (!cfg
.bold_colour
)
1831 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1832 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1833 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1834 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1838 if (HIWORD(wParam
) == BN_CLICKED
||
1839 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1840 static CHOOSECOLOR cc
;
1841 static DWORD custom
[16] = {0}; /* zero initialisers */
1842 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
1844 if (!cfg
.bold_colour
)
1845 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1846 cc
.lStructSize
= sizeof(cc
);
1847 cc
.hwndOwner
= hwnd
;
1848 cc
.hInstance
= (HWND
)hinst
;
1849 cc
.lpCustColors
= custom
;
1850 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1852 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1853 if (ChooseColor(&cc
)) {
1855 (unsigned char) (cc
.rgbResult
& 0xFF);
1857 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1859 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1860 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
1862 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
1864 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
1872 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1875 static int CALLBACK
TranslationProc (HWND hwnd
, UINT msg
,
1876 WPARAM wParam
, LPARAM lParam
) {
1878 enum { controlstartvalue
= 1000,
1893 /* Accelerators used: [aco] beiknpsx */
1894 ctlposinit(&cp
, hwnd
);
1896 "Handling of VT100 line drawing characters:", IDC_VTSTATIC
,
1897 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
1898 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
1899 "Use font in O&EM mode only", IDC_VTOEMONLY
,
1900 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1901 IDC_VTPOORMAN
, NULL
);
1903 "Character set translation:", IDC_XLATSTATIC
,
1904 "&None", IDC_NOXLAT
,
1905 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
1906 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
, NULL
);
1907 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch", IDC_CAPSLOCKCYR
);
1909 CheckRadioButton (hwnd
, IDC_NOXLAT
, IDC_88592WIN1250
,
1910 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
1911 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
1913 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1914 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
1915 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
1916 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
1917 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
1920 switch (LOWORD(wParam
)) {
1922 case IDC_KOI8WIN1251
:
1923 case IDC_88592WIN1250
:
1924 cfg
.xlat_enablekoiwin
=
1925 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
1926 cfg
.xlat_88592w1250
=
1927 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
1929 case IDC_CAPSLOCKCYR
:
1930 if (HIWORD(wParam
) == BN_CLICKED
||
1931 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1932 cfg
.xlat_capslockcyr
=
1933 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
1936 case IDC_VTXWINDOWS
:
1941 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
1942 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
1943 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
1948 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1951 static DLGPROC panelproc
[NPANELS
] = {
1952 ConnectionProc
, KeyboardProc
, TerminalProc
, WindowProc
,
1953 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, TranslationProc
1956 static char *names
[NPANELS
] = {
1957 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
1958 "SSH", "Selection", "Colours", "Translation"
1961 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
1962 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 3, 6, 7, 8};
1964 static HWND
makesubdialog(HWND hwnd
, int x
, int y
, int w
, int h
, int n
) {
1968 r
.left
= x
; r
.top
= y
;
1969 r
.right
= r
.left
+ w
; r
.bottom
= r
.top
+ h
;
1970 MapDialogRect(hwnd
, &r
);
1971 ret
= CreateWindowEx(WS_EX_CONTROLPARENT
,
1972 WC_DIALOG
, "", /* no title */
1973 WS_CHILD
| WS_VISIBLE
| DS_SETFONT
,
1975 r
.right
-r
.left
, r
.bottom
-r
.top
,
1976 hwnd
, (HMENU
)IDC_SUBDLG
,
1978 SetWindowLong (ret
, DWL_DLGPROC
, (LONG
)panelproc
[n
]);
1979 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
1980 SendMessage (ret
, WM_SETFONT
, font
, MAKELPARAM(0, 0));
1981 SendMessage (ret
, WM_INITDIALOG
, 0, 0);
1985 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1986 WPARAM wParam
, LPARAM lParam
,
1987 int npanels
, int *panelnums
, HWND
*page
) {
1992 { /* centre the window */
1995 hw
= GetDesktopWindow();
1996 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1997 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1998 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1999 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
2003 r
.left
= 3; r
.right
= r
.left
+ 174;
2004 r
.top
= 3; r
.bottom
= r
.top
+ 193;
2005 MapDialogRect(hwnd
, &r
);
2006 tabctl
= CreateWindowEx(0, WC_TABCONTROL
, "",
2007 WS_CHILD
| WS_VISIBLE
|
2008 WS_TABSTOP
| TCS_MULTILINE
,
2010 r
.right
-r
.left
, r
.bottom
-r
.top
,
2011 hwnd
, (HMENU
)IDC_TAB
, hinst
, NULL
);
2015 ctlposinit2(&cp
, hwnd
);
2016 ersatztab(&cp
, "Category:", IDC_TABSTATIC1
, IDC_TABLIST
,
2019 WPARAM font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2020 SendMessage(tabctl
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
2024 if (tabctl
) { /* initialise the tab control */
2028 for (i
=0; i
<npanels
; i
++) {
2029 tab
.mask
= TCIF_TEXT
;
2030 tab
.pszText
= names
[panelnums
[i
]];
2031 TabCtrl_InsertItem (tabctl
, i
, &tab
);
2036 for (i
=0; i
<npanels
; i
++) {
2037 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_ADDSTRING
,
2038 0, (LPARAM
)names
[panelnums
[i
]]);
2040 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_SETCURSEL
, 0, 0);
2042 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[0]);
2046 if (LOWORD(wParam
) == IDC_TAB
&&
2047 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
2048 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
2050 DestroyWindow (*page
);
2051 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2052 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
2057 switch (LOWORD(wParam
)) {
2059 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
2060 HWND tablist
= GetDlgItem (hwnd
, IDC_TABLIST
);
2061 int i
= SendMessage (tablist
, CB_GETCURSEL
, 0, 0);
2063 DestroyWindow (*page
);
2064 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2065 SetFocus(tablist
); /* ensure focus stays */
2071 EndDialog (hwnd
, 1);
2076 EndDialog (hwnd
, 0);
2081 EndDialog (hwnd
, 0);
2084 /* Grrr Explorer will maximize Dialogs! */
2086 if (wParam
== SIZE_MAXIMIZED
)
2093 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2094 WPARAM wParam
, LPARAM lParam
) {
2095 static HWND page
= NULL
;
2097 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2099 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
2100 EnableWindow(hwnd
, 0);
2101 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2102 GetParent(hwnd
), AboutProc
);
2103 EnableWindow(hwnd
, 1);
2104 SetActiveWindow(hwnd
);
2106 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2107 MAIN_NPANELS
, mainp
, &page
);
2110 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2111 WPARAM wParam
, LPARAM lParam
) {
2113 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2114 RECONF_NPANELS
, reconfp
, &page
);
2117 int do_config (void) {
2121 savedsession
[0] = '\0';
2122 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2123 get_sesslist(FALSE
);
2128 int do_reconfig (HWND hwnd
) {
2132 backup_cfg
= cfg
; /* structure copy */
2133 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2135 cfg
= backup_cfg
; /* structure copy */
2142 void logevent (char *string
) {
2143 if (nevents
>= negsize
) {
2145 events
= srealloc (events
, negsize
* sizeof(*events
));
2147 events
[nevents
] = smalloc(1+strlen(string
));
2148 strcpy (events
[nevents
], string
);
2152 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2154 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2155 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2159 void showeventlog (HWND hwnd
) {
2161 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2163 ShowWindow (logbox
, SW_SHOWNORMAL
);
2167 void showabout (HWND hwnd
) {
2169 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2171 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2175 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2176 char *keystr
, char *fingerprint
) {
2179 static const char absentmsg
[] =
2180 "The server's host key is not cached in the registry. You\n"
2181 "have no guarantee that the server is the computer you\n"
2183 "The server's key fingerprint is:\n"
2185 "If you trust this host, hit Yes to add the key to\n"
2186 "PuTTY's cache and carry on connecting.\n"
2187 "If you do not trust this host, hit No to abandon the\n"
2190 static const char wrongmsg
[] =
2191 "WARNING - POTENTIAL SECURITY BREACH!\n"
2193 "The server's host key does not match the one PuTTY has\n"
2194 "cached in the registry. This means that either the\n"
2195 "server administrator has changed the host key, or you\n"
2196 "have actually connected to another computer pretending\n"
2197 "to be the server.\n"
2198 "The new key fingerprint is:\n"
2200 "If you were expecting this change and trust the new key,\n"
2201 "hit Yes to update PuTTY's cache and continue connecting.\n"
2202 "If you want to carry on connecting but without updating\n"
2203 "the cache, hit No.\n"
2204 "If you want to abandon the connection completely, hit\n"
2205 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2208 static const char mbtitle
[] = "PuTTY Security Alert";
2211 char message
[160+ /* sensible fingerprint max size */
2212 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2213 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2216 * Verify the key against the registry.
2218 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2220 if (ret
== 0) /* success - key matched OK */
2222 if (ret
== 2) { /* key was different */
2224 sprintf(message
, wrongmsg
, fingerprint
);
2225 mbret
= MessageBox(NULL
, message
, mbtitle
,
2226 MB_ICONWARNING
| MB_YESNOCANCEL
);
2228 store_host_key(host
, port
, keytype
, keystr
);
2229 if (mbret
== IDCANCEL
)
2232 if (ret
== 1) { /* key was absent */
2234 sprintf(message
, absentmsg
, fingerprint
);
2235 mbret
= MessageBox(NULL
, message
, mbtitle
,
2236 MB_ICONWARNING
| MB_YESNO
);
2239 store_host_key(host
, port
, keytype
, keystr
);