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 void gpps(void *handle
, char *name
, char *def
, char *val
, int len
) {
29 if (!read_setting_s(handle
, name
, val
, len
)) {
30 strncpy(val
, def
, len
);
35 static void gppi(void *handle
, char *name
, int def
, int *i
) {
36 *i
= read_setting_i(handle
, name
, def
);
39 static HINSTANCE hinst
;
43 static void save_settings (char *section
, int do_host
) {
48 sesskey
= open_settings_w(section
);
52 write_setting_i (sesskey
, "Present", 1);
54 write_setting_s (sesskey
, "HostName", cfg
.host
);
55 write_setting_i (sesskey
, "PortNumber", cfg
.port
);
57 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
58 if (backends
[i
].protocol
== cfg
.protocol
) {
62 write_setting_s (sesskey
, "Protocol", p
);
64 write_setting_i (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
65 write_setting_i (sesskey
, "WarnOnClose", !!cfg
.warn_on_close
);
66 write_setting_s (sesskey
, "TerminalType", cfg
.termtype
);
67 write_setting_s (sesskey
, "TerminalSpeed", cfg
.termspeed
);
69 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
75 if (c
== '=' || c
== ',' || c
== '\\')
85 write_setting_s (sesskey
, "Environment", buf
);
87 write_setting_s (sesskey
, "UserName", cfg
.username
);
88 write_setting_i (sesskey
, "NoPTY", cfg
.nopty
);
89 write_setting_i (sesskey
, "AgentFwd", cfg
.agentfwd
);
90 write_setting_s (sesskey
, "RemoteCmd", cfg
.remote_cmd
);
91 write_setting_s (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
92 cfg
.cipher
== CIPHER_DES ?
"des" : "3des");
93 write_setting_i (sesskey
, "AuthTIS", cfg
.try_tis_auth
);
94 write_setting_i (sesskey
, "SshProt", cfg
.sshprot
);
95 write_setting_s (sesskey
, "PublicKeyFile", cfg
.keyfile
);
96 write_setting_s (sesskey
, "RemoteCommand", cfg
.remote_cmd
);
97 write_setting_i (sesskey
, "RFCEnviron", cfg
.rfc_environ
);
98 write_setting_i (sesskey
, "BackspaceIsDelete", cfg
.bksp_is_delete
);
99 write_setting_i (sesskey
, "RXVTHomeEnd", cfg
.rxvt_homeend
);
100 write_setting_i (sesskey
, "LinuxFunctionKeys", cfg
.funky_type
);
101 write_setting_i (sesskey
, "ApplicationCursorKeys", cfg
.app_cursor
);
102 write_setting_i (sesskey
, "ApplicationKeypad", cfg
.app_keypad
);
103 write_setting_i (sesskey
, "NetHackKeypad", cfg
.nethack_keypad
);
104 write_setting_i (sesskey
, "AltF4", cfg
.alt_f4
);
105 write_setting_i (sesskey
, "AltSpace", cfg
.alt_space
);
106 write_setting_i (sesskey
, "LdiscTerm", cfg
.ldisc_term
);
107 write_setting_i (sesskey
, "BlinkCur", cfg
.blink_cur
);
108 write_setting_i (sesskey
, "Beep", cfg
.beep
);
109 write_setting_i (sesskey
, "ScrollbackLines", cfg
.savelines
);
110 write_setting_i (sesskey
, "DECOriginMode", cfg
.dec_om
);
111 write_setting_i (sesskey
, "AutoWrapMode", cfg
.wrap_mode
);
112 write_setting_i (sesskey
, "LFImpliesCR", cfg
.lfhascr
);
113 write_setting_i (sesskey
, "WinNameAlways", cfg
.win_name_always
);
114 write_setting_s (sesskey
, "WinTitle", cfg
.wintitle
);
115 write_setting_i (sesskey
, "TermWidth", cfg
.width
);
116 write_setting_i (sesskey
, "TermHeight", cfg
.height
);
117 write_setting_s (sesskey
, "Font", cfg
.font
);
118 write_setting_i (sesskey
, "FontIsBold", cfg
.fontisbold
);
119 write_setting_i (sesskey
, "FontCharSet", cfg
.fontcharset
);
120 write_setting_i (sesskey
, "FontHeight", cfg
.fontheight
);
121 write_setting_i (sesskey
, "FontVTMode", cfg
.vtmode
);
122 write_setting_i (sesskey
, "TryPalette", cfg
.try_palette
);
123 write_setting_i (sesskey
, "BoldAsColour", cfg
.bold_colour
);
124 for (i
=0; i
<22; i
++) {
125 char buf
[20], buf2
[30];
126 sprintf(buf
, "Colour%d", i
);
127 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
128 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
129 write_setting_s (sesskey
, buf
, buf2
);
131 write_setting_i (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
132 for (i
=0; i
<256; i
+=32) {
133 char buf
[20], buf2
[256];
135 sprintf(buf
, "Wordness%d", i
);
137 for (j
=i
; j
<i
+32; j
++) {
138 sprintf(buf2
+strlen(buf2
), "%s%d",
139 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
141 write_setting_s (sesskey
, buf
, buf2
);
143 write_setting_i (sesskey
, "KoiWinXlat", cfg
.xlat_enablekoiwin
);
144 write_setting_i (sesskey
, "88592Xlat", cfg
.xlat_88592w1250
);
145 write_setting_i (sesskey
, "CapsLockCyr", cfg
.xlat_capslockcyr
);
146 write_setting_i (sesskey
, "ScrollBar", cfg
.scrollbar
);
147 write_setting_i (sesskey
, "ScrollOnKey", cfg
.scroll_on_key
);
148 write_setting_i (sesskey
, "LockSize", cfg
.locksize
);
149 write_setting_i (sesskey
, "BCE", cfg
.bce
);
150 write_setting_i (sesskey
, "BlinkText", cfg
.blinktext
);
152 close_settings_w(sesskey
);
155 static void load_settings (char *section
, int do_host
) {
160 sesskey
= open_settings_r(section
);
162 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
163 gppi (sesskey
, "PortNumber", default_port
, &cfg
.port
);
165 gpps (sesskey
, "Protocol", "default", prot
, 10);
166 cfg
.protocol
= default_protocol
;
167 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
168 if (!strcmp(prot
, backends
[i
].name
)) {
169 cfg
.protocol
= backends
[i
].protocol
;
173 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
174 gppi (sesskey
, "WarnOnClose", 1, &cfg
.warn_on_close
);
175 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
176 sizeof(cfg
.termtype
));
177 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
178 sizeof(cfg
.termspeed
));
180 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
181 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
185 while (*p
&& *p
!= ',') {
198 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
199 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
200 gppi (sesskey
, "AgentFwd", 0, &cfg
.agentfwd
);
201 gpps (sesskey
, "RemoteCmd", "", cfg
.remote_cmd
, sizeof(cfg
.remote_cmd
));
204 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
205 if (!strcmp(cipher
, "blowfish"))
206 cfg
.cipher
= CIPHER_BLOWFISH
;
207 else if (!strcmp(cipher
, "des"))
208 cfg
.cipher
= CIPHER_DES
;
210 cfg
.cipher
= CIPHER_3DES
;
212 gppi (sesskey
, "SshProt", 1, &cfg
.sshprot
);
213 gppi (sesskey
, "AuthTIS", 0, &cfg
.try_tis_auth
);
214 gpps (sesskey
, "PublicKeyFile", "", cfg
.keyfile
, sizeof(cfg
.keyfile
));
215 gpps (sesskey
, "RemoteCommand", "", cfg
.remote_cmd
,
216 sizeof(cfg
.remote_cmd
));
217 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
218 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
219 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
220 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.funky_type
);
221 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
222 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
223 gppi (sesskey
, "NetHackKeypad", 0, &cfg
.nethack_keypad
);
224 gppi (sesskey
, "AltF4", 1, &cfg
.alt_f4
);
225 gppi (sesskey
, "AltSpace", 0, &cfg
.alt_space
);
226 gppi (sesskey
, "LdiscTerm", 0, &cfg
.ldisc_term
);
227 gppi (sesskey
, "BlinkCur", 0, &cfg
.blink_cur
);
228 gppi (sesskey
, "Beep", 1, &cfg
.beep
);
229 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
230 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
231 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
232 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
233 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
234 gpps (sesskey
, "WinTitle", "", cfg
.wintitle
, sizeof(cfg
.wintitle
));
235 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
236 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
237 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
238 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
239 gppi (sesskey
, "FontCharSet", ANSI_CHARSET
, &cfg
.fontcharset
);
240 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
241 gppi (sesskey
, "FontVTMode", VT_OEMANSI
, (int *)&cfg
.vtmode
);
242 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
243 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
244 for (i
=0; i
<22; i
++) {
245 static char *defaults
[] = {
246 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
247 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
248 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
249 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
250 "85,255,255", "187,187,187", "255,255,255"
252 char buf
[20], buf2
[30];
254 sprintf(buf
, "Colour%d", i
);
255 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
256 if(sscanf(buf2
, "%d,%d,%d", &c0
, &c1
, &c2
) == 3) {
257 cfg
.colours
[i
][0] = c0
;
258 cfg
.colours
[i
][1] = c1
;
259 cfg
.colours
[i
][2] = c2
;
262 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
263 for (i
=0; i
<256; i
+=32) {
264 static char *defaults
[] = {
265 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
266 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
267 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
268 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
269 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
270 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
271 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
272 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
274 char buf
[20], buf2
[256], *p
;
276 sprintf(buf
, "Wordness%d", i
);
277 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
279 for (j
=i
; j
<i
+32; j
++) {
281 while (*p
&& *p
!= ',') p
++;
282 if (*p
== ',') *p
++ = '\0';
283 cfg
.wordness
[j
] = atoi(q
);
286 gppi (sesskey
, "KoiWinXlat", 0, &cfg
.xlat_enablekoiwin
);
287 gppi (sesskey
, "88592Xlat", 0, &cfg
.xlat_88592w1250
);
288 gppi (sesskey
, "CapsLockCyr", 0, &cfg
.xlat_capslockcyr
);
289 gppi (sesskey
, "ScrollBar", 1, &cfg
.scrollbar
);
290 gppi (sesskey
, "ScrollOnKey", 0, &cfg
.scroll_on_key
);
291 gppi (sesskey
, "LockSize", 0, &cfg
.locksize
);
292 gppi (sesskey
, "BCE", 0, &cfg
.bce
);
293 gppi (sesskey
, "BlinkText", 0, &cfg
.blinktext
);
295 close_settings_r(sesskey
);
298 static void force_normal(HWND hwnd
)
300 static int recurse
= 0;
307 wp
.length
= sizeof(wp
);
308 if (GetWindowPlacement(hwnd
, &wp
))
310 wp
.showCmd
= SW_SHOWNORMAL
;
311 SetWindowPlacement(hwnd
, &wp
);
316 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
319 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
324 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
325 WPARAM wParam
, LPARAM lParam
) {
330 for (i
=0; i
<nevents
; i
++)
331 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
332 0, (LPARAM
)events
[i
]);
335 switch (LOWORD(wParam
)) {
338 DestroyWindow (hwnd
);
341 if (HIWORD(wParam
) == BN_CLICKED
||
342 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
345 selcount
= SendDlgItemMessage(hwnd
, IDN_LIST
,
346 LB_GETSELCOUNT
, 0, 0);
347 selitems
= malloc(selcount
* sizeof(int));
349 int count
= SendDlgItemMessage(hwnd
, IDN_LIST
,
351 selcount
, (LPARAM
)selitems
);
355 static unsigned char sel_nl
[] = SEL_NL
;
357 if (count
== 0) { /* can't copy zero stuff */
363 for (i
= 0; i
< count
; i
++)
364 size
+= strlen(events
[selitems
[i
]]) + sizeof(sel_nl
);
366 clipdata
= malloc(size
);
369 for (i
= 0; i
< count
; i
++) {
370 char *q
= events
[selitems
[i
]];
371 int qlen
= strlen(q
);
374 memcpy(p
, sel_nl
, sizeof(sel_nl
));
377 write_clip(clipdata
, size
, TRUE
);
382 for (i
= 0; i
< nevents
; i
++)
383 SendDlgItemMessage(hwnd
, IDN_LIST
, LB_SETSEL
,
392 DestroyWindow (hwnd
);
398 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
399 WPARAM wParam
, LPARAM lParam
) {
404 switch (LOWORD(wParam
)) {
417 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
418 WPARAM wParam
, LPARAM lParam
) {
421 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
424 switch (LOWORD(wParam
)) {
427 DestroyWindow (hwnd
);
430 EnableWindow(hwnd
, 0);
431 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
433 EnableWindow(hwnd
, 1);
434 SetActiveWindow(hwnd
);
440 DestroyWindow (hwnd
);
446 /* ----------------------------------------------------------------------
447 * Routines to self-manage the controls in a dialog box.
453 #define STATICHEIGHT 8
454 #define CHECKBOXHEIGHT 8
455 #define RADIOHEIGHT 8
456 #define EDITHEIGHT 12
457 #define COMBOHEIGHT 12
458 #define PUSHBTNHEIGHT 14
467 /* Used on self-constructed dialogs. */
468 static void ctlposinit(struct ctlpos
*cp
, HWND hwnd
) {
471 cp
->units
= GetWindowLong(hwnd
, GWL_USERDATA
);
472 cp
->font
= GetWindowLong(hwnd
, DWL_USER
);
473 cp
->ypos
= GAPBETWEEN
;
474 GetClientRect(hwnd
, &r
);
475 cp
->width
= (r
.right
* 4) / (cp
->units
& 0xFFFF) - 2*GAPBETWEEN
;
478 /* Used on kosher dialogs. */
479 static void ctlposinit2(struct ctlpos
*cp
, HWND hwnd
) {
485 MapDialogRect(hwnd
, &r
);
486 cp
->units
= (r
.bottom
<< 16) | r
.right
;
487 cp
->font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
488 cp
->ypos
= GAPBETWEEN
;
489 GetClientRect(hwnd
, &r
);
490 cp
->width
= (r
.right
* 4) / (cp
->units
& 0xFFFF) - 2*GAPBETWEEN
;
493 static void doctl(struct ctlpos
*cp
, RECT r
,
494 char *wclass
, int wstyle
, int exstyle
,
495 char *wtext
, int wid
) {
498 * Note nonstandard use of RECT. This is deliberate: by
499 * transforming the width and height directly we arrange to
500 * have all supposedly same-sized controls really same-sized.
503 /* MapDialogRect, or its near equivalent. */
504 r
.left
= (r
.left
* (cp
->units
& 0xFFFF)) / 4;
505 r
.right
= (r
.right
* (cp
->units
& 0xFFFF)) / 4;
506 r
.top
= (r
.top
* ((cp
->units
>>16) & 0xFFFF)) / 8;
507 r
.bottom
= (r
.bottom
* ((cp
->units
>>16) & 0xFFFF)) / 8;
509 ctl
= CreateWindowEx(exstyle
, wclass
, wtext
, wstyle
,
510 r
.left
, r
.top
, r
.right
, r
.bottom
,
511 cp
->hwnd
, (HMENU
)wid
, hinst
, NULL
);
512 SendMessage(ctl
, WM_SETFONT
, cp
->font
, MAKELPARAM(TRUE
, 0));
516 * Some edit boxes. Each one has a static above it. The percentages
517 * of the horizontal space are provided.
519 static void multiedit(struct ctlpos
*cp
, ...) {
528 int staticid
, editid
, pcwidth
;
529 text
= va_arg(ap
, char *);
532 staticid
= va_arg(ap
, int);
533 editid
= va_arg(ap
, int);
534 pcwidth
= va_arg(ap
, int);
536 r
.left
= xpos
+ GAPBETWEEN
;
538 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
539 r
.right
= xpos
- r
.left
;
541 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
542 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
544 r
.top
= cp
->ypos
+ 8 + GAPWITHIN
; r
.bottom
= EDITHEIGHT
;
546 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
551 cp
->ypos
+= 8+GAPWITHIN
+12+GAPBETWEEN
;
555 * A set of radio buttons on the same line, with a static above
556 * them. `nacross' dictates how many parts the line is divided into
557 * (you might want this not to equal the number of buttons if you
558 * needed to line up some 2s and some 3s to look good in the same
561 static void radioline(struct ctlpos
*cp
,
562 char *text
, int id
, int nacross
, ...) {
568 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
569 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
570 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
571 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
572 va_start(ap
, nacross
);
578 btext
= va_arg(ap
, char *);
581 bid
= va_arg(ap
, int);
582 r
.left
= GAPBETWEEN
+ i
* (cp
->width
+GAPBETWEEN
)/nacross
;
583 r
.right
= (i
+1) * (cp
->width
+GAPBETWEEN
)/nacross
- r
.left
;
584 r
.top
= cp
->ypos
; r
.bottom
= RADIOHEIGHT
;
585 doctl(cp
, r
, "BUTTON",
586 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
593 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
597 * A set of radio buttons on multiple lines, with a static above
600 static void radiobig(struct ctlpos
*cp
, char *text
, int id
, ...) {
605 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
606 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
607 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
608 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
614 btext
= va_arg(ap
, char *);
617 bid
= va_arg(ap
, int);
618 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
619 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
620 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
621 doctl(cp
, r
, "BUTTON",
622 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
628 cp
->ypos
+= GAPBETWEEN
- GAPWITHIN
;
632 * A single standalone checkbox.
634 static void checkbox(struct ctlpos
*cp
, char *text
, int id
) {
637 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
638 r
.right
= cp
->width
; r
.bottom
= CHECKBOXHEIGHT
;
639 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
640 doctl(cp
, r
, "BUTTON",
641 BS_AUTOCHECKBOX
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
, 0,
646 * A button on the right hand side, with a static to its left.
648 static void staticbtn(struct ctlpos
*cp
, char *stext
, int sid
,
649 char *btext
, int bid
) {
650 const int height
= (PUSHBTNHEIGHT
> STATICHEIGHT ?
651 PUSHBTNHEIGHT
: STATICHEIGHT
);
653 int lwid
, rwid
, rpos
;
655 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
656 lwid
= rpos
- 2*GAPBETWEEN
;
657 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
659 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
660 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
661 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
663 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
664 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
665 doctl(cp
, r
, "BUTTON",
666 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
670 cp
->ypos
+= height
+ GAPBETWEEN
;
674 * An edit control on the right hand side, with a static to its left.
676 static void staticedit(struct ctlpos
*cp
, char *stext
, int sid
, int eid
) {
677 const int height
= (EDITHEIGHT
> STATICHEIGHT ?
678 EDITHEIGHT
: STATICHEIGHT
);
680 int lwid
, rwid
, rpos
;
682 rpos
= GAPBETWEEN
+ (cp
->width
+ GAPBETWEEN
) / 2;
683 lwid
= rpos
- 2*GAPBETWEEN
;
684 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
686 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
687 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
688 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
690 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
691 r
.right
= rwid
; r
.bottom
= EDITHEIGHT
;
693 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
697 cp
->ypos
+= height
+ GAPBETWEEN
;
701 * A tab-control substitute when a real tab control is unavailable.
703 static void ersatztab(struct ctlpos
*cp
, char *stext
, int sid
,
705 const int height
= (COMBOHEIGHT
> STATICHEIGHT ?
706 COMBOHEIGHT
: STATICHEIGHT
);
708 int bigwid
, lwid
, rwid
, rpos
;
709 static const int BIGGAP
= 15;
710 static const int MEDGAP
= 3;
712 bigwid
= cp
->width
+ 2*GAPBETWEEN
- 2*BIGGAP
;
714 rpos
= BIGGAP
+ (bigwid
+ BIGGAP
) / 2;
715 lwid
= rpos
- 2*BIGGAP
;
716 rwid
= bigwid
+ BIGGAP
- rpos
;
718 r
.left
= BIGGAP
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
719 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
720 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
722 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-COMBOHEIGHT
)/2;
723 r
.right
= rwid
; r
.bottom
= COMBOHEIGHT
*10;
724 doctl(cp
, r
, "COMBOBOX",
725 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
726 CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
730 cp
->ypos
+= height
+ MEDGAP
+ GAPBETWEEN
;
732 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
733 r
.right
= cp
->width
; r
.bottom
= 2;
734 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDHORZ
,
739 * A static line, followed by an edit control on the left hand side
740 * and a button on the right.
742 static void editbutton(struct ctlpos
*cp
, char *stext
, int sid
,
743 int eid
, char *btext
, int bid
) {
744 const int height
= (EDITHEIGHT
> PUSHBTNHEIGHT ?
745 EDITHEIGHT
: PUSHBTNHEIGHT
);
747 int lwid
, rwid
, rpos
;
749 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
750 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
751 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
752 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
754 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
755 lwid
= rpos
- 2*GAPBETWEEN
;
756 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
758 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
759 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
761 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
765 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
766 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
767 doctl(cp
, r
, "BUTTON",
768 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
772 cp
->ypos
+= height
+ GAPBETWEEN
;
776 * Special control which was hard to describe generically: the
777 * session-saver assembly. A static; below that an edit box; below
778 * that a list box. To the right of the list box, a column of
781 static void sesssaver(struct ctlpos
*cp
, char *text
,
782 int staticid
, int editid
, int listid
, ...) {
785 int lwid
, rwid
, rpos
;
787 const int LISTDEFHEIGHT
= 66;
789 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
790 lwid
= rpos
- 2*GAPBETWEEN
;
791 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
793 /* The static control. */
794 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
795 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
796 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
797 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
799 /* The edit control. */
800 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
801 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
802 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
804 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
809 * The buttons (we should hold off on the list box until we
810 * know how big the buttons are).
812 va_start(ap
, listid
);
815 char *btext
= va_arg(ap
, char *);
818 bid
= va_arg(ap
, int);
819 r
.left
= rpos
; r
.top
= y
;
820 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
821 y
+= r
.bottom
+ GAPWITHIN
;
822 doctl(cp
, r
, "BUTTON",
823 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
828 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
831 if (y
< LISTDEFHEIGHT
) y
= LISTDEFHEIGHT
;
832 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
833 r
.right
= lwid
; r
.bottom
= y
;
834 cp
->ypos
+= y
+ GAPBETWEEN
;
835 doctl(cp
, r
, "LISTBOX",
836 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
|
837 LBS_STANDARD
| LBS_HASSTRINGS
,
843 * Another special control: the environment-variable setter. A
844 * static line first; then a pair of edit boxes with associated
845 * statics, and two buttons; then a list box.
847 static void envsetter(struct ctlpos
*cp
, char *stext
, int sid
,
848 char *e1stext
, int e1sid
, int e1id
,
849 char *e2stext
, int e2sid
, int e2id
,
851 char *b1text
, int b1id
, char *b2text
, int b2id
) {
853 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
855 EDITHEIGHT
> PUSHBTNHEIGHT ?
856 EDITHEIGHT
: PUSHBTNHEIGHT
);
857 const static int percents
[] = { 20, 35, 10, 25 };
858 int i
, j
, xpos
, percent
;
859 const int LISTHEIGHT
= 42;
861 /* The static control. */
862 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
863 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
864 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
865 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
867 /* The statics+edits+buttons. */
868 for (j
= 0; j
< 2; j
++) {
870 for (i
= 0; i
< 4; i
++) {
871 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
872 r
.left
= xpos
+ GAPBETWEEN
;
873 percent
+= percents
[i
];
874 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
875 r
.right
= xpos
- r
.left
;
877 r
.bottom
= (i
==0 ? STATICHEIGHT
:
880 r
.top
+= (height
-r
.bottom
)/2;
882 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
883 j
==0 ? e1stext
: e2stext
, j
==0 ? e1sid
: e2sid
);
886 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
888 "", j
==0 ? e1id
: e2id
);
890 doctl(cp
, r
, "BUTTON",
891 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
893 j
==0 ? b1text
: b2text
, j
==0 ? b1id
: b2id
);
896 cp
->ypos
+= height
+ GAPWITHIN
;
900 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
901 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
902 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
903 doctl(cp
, r
, "LISTBOX",
904 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
911 * Yet another special control: the character-class setter. A
912 * static, then a list, then a line containing a
913 * button-and-static-and-edit.
915 static void charclass(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
916 char *btext
, int bid
, int eid
, char *s2text
, int s2id
) {
918 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
920 EDITHEIGHT
> PUSHBTNHEIGHT ?
921 EDITHEIGHT
: PUSHBTNHEIGHT
);
922 const static int percents
[] = { 30, 40, 30 };
923 int i
, xpos
, percent
;
924 const int LISTHEIGHT
= 66;
926 /* The static control. */
927 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
928 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
929 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
930 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
933 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
934 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
935 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
936 doctl(cp
, r
, "LISTBOX",
937 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
942 /* The button+static+edit. */
944 for (i
= 0; i
< 3; i
++) {
945 r
.left
= xpos
+ GAPBETWEEN
;
946 percent
+= percents
[i
];
947 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
948 r
.right
= xpos
- r
.left
;
950 r
.bottom
= (i
==0 ? PUSHBTNHEIGHT
:
951 i
==1 ? STATICHEIGHT
:
953 r
.top
+= (height
-r
.bottom
)/2;
955 doctl(cp
, r
, "BUTTON",
956 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
959 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
963 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
964 WS_EX_CLIENTEDGE
, "", eid
);
967 cp
->ypos
+= height
+ GAPBETWEEN
;
971 * A special control (horrors!). The colour editor. A static line;
972 * then on the left, a list box, and on the right, a sequence of
973 * two-part statics followed by a button.
975 static void colouredit(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
976 char *btext
, int bid
, ...) {
980 int lwid
, rwid
, rpos
;
981 const int LISTHEIGHT
= 66;
983 /* The static control. */
984 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
985 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
986 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
987 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
989 rpos
= GAPBETWEEN
+ 2 * (cp
->width
+ GAPBETWEEN
) / 3;
990 lwid
= rpos
- 2*GAPBETWEEN
;
991 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
994 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
995 r
.right
= lwid
; r
.bottom
= LISTHEIGHT
;
996 doctl(cp
, r
, "LISTBOX",
997 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
1008 ltext
= va_arg(ap
, char *);
1010 lid
= va_arg(ap
, int);
1011 rid
= va_arg(ap
, int);
1012 r
.top
= y
; r
.bottom
= STATICHEIGHT
;
1013 y
+= r
.bottom
+ GAPWITHIN
;
1014 r
.left
= rpos
; r
.right
= rwid
/2;
1015 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, ltext
, lid
);
1016 r
.left
= rpos
+ r
.right
; r
.right
= rwid
- r
.right
;
1017 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_RIGHT
, 0, "", rid
);
1022 r
.top
= y
+ 2*GAPWITHIN
; r
.bottom
= PUSHBTNHEIGHT
;
1023 r
.left
= rpos
; r
.right
= rwid
;
1024 doctl(cp
, r
, "BUTTON",
1025 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
1028 cp
->ypos
+= LISTHEIGHT
+ GAPBETWEEN
;
1031 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
1032 WPARAM wParam
, LPARAM lParam
) {
1036 HFONT hfont
= (HFONT
)wParam
;
1043 oldfont
= SelectObject(hdc
, hfont
);
1044 GetTextMetrics(hdc
, &tm
);
1045 units
= (tm
.tmHeight
<< 16) | tm
.tmAveCharWidth
;
1046 SelectObject(hdc
, oldfont
);
1048 SetWindowLong(hwnd
, GWL_USERDATA
, units
);
1049 SetWindowLong(hwnd
, DWL_USER
, wParam
);
1053 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1056 DestroyWindow (hwnd
);
1062 static char savedsession
[2048];
1064 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
1065 WPARAM wParam
, LPARAM lParam
) {
1068 enum { controlstartvalue
= 1000,
1089 /* Accelerators used: [aco] dehlnprstwx */
1090 ctlposinit(&cp
, hwnd
);
1092 "Host &Name", IDC_HOSTSTATIC
, IDC_HOST
, 75,
1093 "&Port", IDC_PORTSTATIC
, IDC_PORT
, 25, NULL
);
1094 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1095 "&Raw", IDC_PROTRAW
,
1096 "&Telnet", IDC_PROTTELNET
,
1103 sesssaver(&cp
, "Stor&ed Sessions",
1104 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
1105 "&Load", IDC_SESSLOAD
,
1106 "&Save", IDC_SESSSAVE
,
1107 "&Delete", IDC_SESSDEL
, NULL
);
1108 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
1109 checkbox(&cp
, "&Warn on Close", IDC_CLOSEWARN
);
1111 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1112 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
1113 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1114 for (i
= 0; i
< nsessions
; i
++)
1115 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1116 0, (LPARAM
) (sessions
[i
]));
1117 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1118 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1119 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
1120 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1121 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1125 * Button release should trigger WM_OK if there was a
1126 * previous double click on the session list.
1130 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
1133 switch (LOWORD(wParam
)) {
1134 case IDC_PROTTELNET
:
1137 if (HIWORD(wParam
) == BN_CLICKED
||
1138 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1139 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
1140 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
1141 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
1142 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
1143 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
1144 cfg
.port
= i ?
22 : 23;
1145 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1150 if (HIWORD(wParam
) == EN_CHANGE
)
1151 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
1152 sizeof(cfg
.host
)-1);
1155 if (HIWORD(wParam
) == EN_CHANGE
)
1156 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
1159 if (HIWORD(wParam
) == BN_CLICKED
||
1160 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1161 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
1164 if (HIWORD(wParam
) == BN_CLICKED
||
1165 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1166 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
1169 if (HIWORD(wParam
) == EN_CHANGE
) {
1170 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1172 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
1173 savedsession
, sizeof(savedsession
)-1);
1174 savedsession
[sizeof(savedsession
)-1] = '\0';
1178 if (HIWORD(wParam
) == BN_CLICKED
||
1179 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1184 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
1186 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1187 LB_GETCURSEL
, 0, 0);
1192 strcpy (str
, sessions
[n
]);
1194 save_settings (str
, !!strcmp(str
, "Default Settings"));
1195 get_sesslist (FALSE
);
1196 get_sesslist (TRUE
);
1197 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1199 for (i
= 0; i
< nsessions
; i
++)
1200 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1201 0, (LPARAM
) (sessions
[i
]));
1202 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1208 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
1209 HIWORD(wParam
) != BN_CLICKED
&&
1210 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1212 if (LOWORD(wParam
) == IDC_SESSLIST
&&
1213 HIWORD(wParam
) != LBN_DBLCLK
)
1216 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1217 LB_GETCURSEL
, 0, 0);
1222 load_settings (sessions
[n
],
1223 !!strcmp(sessions
[n
], "Default Settings"));
1224 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1225 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1226 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1227 (cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1228 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
));
1229 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1230 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1231 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1234 if (LOWORD(wParam
) == IDC_SESSLIST
) {
1236 * A double-click on a saved session should
1237 * actually start the session, not just load it.
1238 * Unless it's Default Settings or some other
1239 * host-less set of saved settings.
1248 if (HIWORD(wParam
) == BN_CLICKED
||
1249 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1250 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1251 LB_GETCURSEL
, 0, 0);
1252 if (n
== LB_ERR
|| n
== 0) {
1256 del_settings(sessions
[n
]);
1257 get_sesslist (FALSE
);
1258 get_sesslist (TRUE
);
1259 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1261 for (i
= 0; i
< nsessions
; i
++)
1262 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1263 0, (LPARAM
) (sessions
[i
]));
1264 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1269 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1272 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
1273 WPARAM wParam
, LPARAM lParam
) {
1275 enum { controlstartvalue
= 1000,
1301 /* Accelerators used: [aco] 4?ehiklmnprsuvxy */
1302 ctlposinit(&cp
, hwnd
);
1303 radioline(&cp
, "Action of Backspace:", IDC_DELSTATIC
, 2,
1304 "Control-&H", IDC_DEL008
,
1305 "Control-&? (127)", IDC_DEL127
, NULL
);
1306 radioline(&cp
, "Action of Home and End:", IDC_HOMESTATIC
, 2,
1307 "&Standard", IDC_HOMETILDE
,
1308 "&rxvt", IDC_HOMERXVT
, NULL
);
1309 radioline(&cp
, "Function key and keypad layout:", IDC_FUNCSTATIC
, 3,
1310 "&VT400", IDC_FUNCTILDE
,
1311 "&Linux", IDC_FUNCLINUX
,
1312 "&Xterm R6", IDC_FUNCXTERM
, NULL
);
1313 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1314 "&Normal", IDC_CURNORMAL
,
1315 "A&pplication", IDC_CURAPPLIC
, NULL
);
1316 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1317 "Nor&mal", IDC_KPNORMAL
,
1318 "Appl&ication", IDC_KPAPPLIC
,
1319 "N&etHack", IDC_KPNH
, NULL
);
1320 checkbox(&cp
, "ALT-F&4 is special (closes window)", IDC_ALTF4
);
1321 checkbox(&cp
, "ALT-Space is special (S&ystem menu)", IDC_ALTSPACE
);
1322 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1323 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1325 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1326 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1327 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1328 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1329 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCXTERM
,
1331 (cfg
.funky_type
==2 ? IDC_FUNCXTERM
1334 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1335 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1336 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1337 cfg
.nethack_keypad ? IDC_KPNH
:
1338 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1339 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1340 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1341 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1342 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1345 if (HIWORD(wParam
) == BN_CLICKED
||
1346 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1347 switch (LOWORD(wParam
)) {
1350 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1354 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1361 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1365 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1366 cfg
.nethack_keypad
= FALSE
;
1369 cfg
.app_keypad
= FALSE
;
1370 cfg
.nethack_keypad
= TRUE
;
1374 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1377 if (HIWORD(wParam
) == BN_CLICKED
||
1378 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1379 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1382 if (HIWORD(wParam
) == BN_CLICKED
||
1383 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1384 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1387 if (HIWORD(wParam
) == BN_CLICKED
||
1388 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1389 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1392 if (HIWORD(wParam
) == BN_CLICKED
||
1393 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1394 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1398 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1401 static void fmtfont (char *buf
) {
1402 sprintf (buf
, "Font: %s, ", cfg
.font
);
1404 strcat(buf
, "bold, ");
1405 if (cfg
.fontheight
== 0)
1406 strcat (buf
, "default height");
1408 sprintf (buf
+strlen(buf
), "%d-%s",
1409 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1410 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1413 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
1414 WPARAM wParam
, LPARAM lParam
) {
1418 char fontstatic
[256];
1419 enum { controlstartvalue
= 1000,
1439 /* Accelerators used: [aco] dghlmnprsw */
1440 ctlposinit(&cp
, hwnd
);
1442 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 33,
1443 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 33,
1444 "&Scrollback", IDC_SAVESTATIC
, IDC_SAVEEDIT
, 33,
1446 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1447 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1448 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1449 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1450 checkbox(&cp
, "Bee&p enabled", IDC_BEEP
);
1451 checkbox(&cp
, "Use Back&ground colour erase", IDC_BCE
);
1452 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1454 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1455 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1456 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1457 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1458 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1459 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1460 fmtfont (fontstatic
);
1461 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1462 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1463 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1464 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1467 switch (LOWORD(wParam
)) {
1469 if (HIWORD(wParam
) == BN_CLICKED
||
1470 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1471 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1474 if (HIWORD(wParam
) == BN_CLICKED
||
1475 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1476 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1479 if (HIWORD(wParam
) == BN_CLICKED
||
1480 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1481 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1484 if (HIWORD(wParam
) == EN_CHANGE
)
1485 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1488 if (HIWORD(wParam
) == EN_CHANGE
)
1489 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1492 if (HIWORD(wParam
) == EN_CHANGE
)
1493 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1495 case IDC_CHOOSEFONT
:
1496 lf
.lfHeight
= cfg
.fontheight
;
1497 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1498 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1499 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1500 lf
.lfCharSet
= cfg
.fontcharset
;
1501 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1502 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1503 lf
.lfQuality
= DEFAULT_QUALITY
;
1504 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1505 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1506 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1508 cf
.lStructSize
= sizeof(cf
);
1509 cf
.hwndOwner
= hwnd
;
1511 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1512 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1514 if (ChooseFont (&cf
)) {
1515 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1516 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1517 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1518 cfg
.fontcharset
= lf
.lfCharSet
;
1519 cfg
.fontheight
= lf
.lfHeight
;
1520 fmtfont (fontstatic
);
1521 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1525 if (HIWORD(wParam
) == BN_CLICKED
||
1526 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1527 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1530 if (HIWORD(wParam
) == BN_CLICKED
||
1531 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1532 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1535 if (HIWORD(wParam
) == BN_CLICKED
||
1536 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1537 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1542 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1545 static int CALLBACK
WindowProc (HWND hwnd
, UINT msg
,
1546 WPARAM wParam
, LPARAM lParam
) {
1548 enum { controlstartvalue
= 1000,
1559 /* Accelerators used: [aco] bikty */
1560 ctlposinit(&cp
, hwnd
);
1562 "Initial window &title:", IDC_WINTITLE
, IDC_WINEDIT
, 100,
1564 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1565 checkbox(&cp
, "&Blinking cursor", IDC_BLINKCUR
);
1566 checkbox(&cp
, "Displa&y scrollbar", IDC_SCROLLBAR
);
1567 checkbox(&cp
, "Loc&k Window size", IDC_LOCKSIZE
);
1569 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1570 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1571 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1572 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1573 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1576 switch (LOWORD(wParam
)) {
1578 if (HIWORD(wParam
) == BN_CLICKED
||
1579 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1580 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1583 if (HIWORD(wParam
) == BN_CLICKED
||
1584 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1585 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1588 if (HIWORD(wParam
) == BN_CLICKED
||
1589 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1590 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1593 if (HIWORD(wParam
) == BN_CLICKED
||
1594 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1595 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1598 if (HIWORD(wParam
) == EN_CHANGE
)
1599 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1600 sizeof(cfg
.wintitle
)-1);
1605 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1608 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
1609 WPARAM wParam
, LPARAM lParam
) {
1612 enum { controlstartvalue
= 1000,
1634 /* Accelerators used: [aco] bdflrstuv */
1635 ctlposinit(&cp
, hwnd
);
1636 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1637 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
);
1638 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1639 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1640 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1641 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1643 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1644 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1645 "&BSD (commonplace)", IDC_EMBSD
,
1646 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1648 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1649 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1650 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1652 char *p
= cfg
.environmt
;
1654 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1659 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1660 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1663 switch (LOWORD(wParam
)) {
1665 if (HIWORD(wParam
) == EN_CHANGE
)
1666 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1667 sizeof(cfg
.termtype
)-1);
1670 if (HIWORD(wParam
) == EN_CHANGE
)
1671 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1672 sizeof(cfg
.termspeed
)-1);
1675 if (HIWORD(wParam
) == EN_CHANGE
)
1676 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1677 sizeof(cfg
.username
)-1);
1681 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1684 if (HIWORD(wParam
) == BN_CLICKED
||
1685 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1686 char str
[sizeof(cfg
.environmt
)];
1688 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
1693 p
= str
+ strlen(str
);
1695 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
1705 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
1707 p
[strlen(str
)+1] = '\0';
1708 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
1710 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
1711 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
1713 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
1714 MB_OK
| MB_ICONERROR
);
1719 if (HIWORD(wParam
) != BN_CLICKED
&&
1720 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1722 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
1728 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
1755 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1758 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
1759 WPARAM wParam
, LPARAM lParam
) {
1762 char filename
[sizeof(cfg
.keyfile
)];
1763 enum { controlstartvalue
= 1000,
1787 /* Accelerators used: [aco] 123abdkmprtuw */
1788 ctlposinit(&cp
, hwnd
);
1789 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1790 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1792 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1794 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1795 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1797 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1798 editbutton(&cp
, "Private &key file for authentication:",
1799 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1800 radioline(&cp
, "Preferred SSH protocol version:",
1801 IDC_SSHPROTSTATIC
, 2,
1802 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1803 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1804 "&3DES", IDC_CIPHER3DES
,
1805 "&Blowfish", IDC_CIPHERBLOWF
,
1806 "&DES", IDC_CIPHERDES
, NULL
);
1808 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1809 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1810 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1811 CheckDlgButton (hwnd
, IDC_AGENTFWD
, cfg
.agentfwd
);
1812 CheckRadioButton (hwnd
, IDC_CIPHER3DES
, IDC_CIPHERDES
,
1813 cfg
.cipher
== CIPHER_BLOWFISH ? IDC_CIPHERBLOWF
:
1814 cfg
.cipher
== CIPHER_DES ? IDC_CIPHERDES
:
1816 CheckRadioButton (hwnd
, IDC_SSHPROT1
, IDC_SSHPROT2
,
1817 cfg
.sshprot
== 1 ? IDC_SSHPROT1
: IDC_SSHPROT2
);
1818 CheckDlgButton (hwnd
, IDC_AUTHTIS
, cfg
.try_tis_auth
);
1819 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1820 SetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
);
1823 switch (LOWORD(wParam
)) {
1825 if (HIWORD(wParam
) == EN_CHANGE
)
1826 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1827 sizeof(cfg
.termtype
)-1);
1830 if (HIWORD(wParam
) == EN_CHANGE
)
1831 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1832 sizeof(cfg
.username
)-1);
1835 if (HIWORD(wParam
) == BN_CLICKED
||
1836 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1837 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
1840 if (HIWORD(wParam
) == BN_CLICKED
||
1841 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1842 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
1844 case IDC_CIPHER3DES
:
1845 case IDC_CIPHERBLOWF
:
1847 if (HIWORD(wParam
) == BN_CLICKED
||
1848 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1849 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
1850 cfg
.cipher
= CIPHER_3DES
;
1851 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
1852 cfg
.cipher
= CIPHER_BLOWFISH
;
1853 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
1854 cfg
.cipher
= CIPHER_DES
;
1859 if (HIWORD(wParam
) == BN_CLICKED
||
1860 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1861 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
1863 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
1868 if (HIWORD(wParam
) == BN_CLICKED
||
1869 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1870 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
1873 if (HIWORD(wParam
) == EN_CHANGE
)
1874 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
1875 sizeof(cfg
.keyfile
)-1);
1878 if (HIWORD(wParam
) == EN_CHANGE
)
1879 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
1880 sizeof(cfg
.remote_cmd
)-1);
1884 * FIXME: this crashes. Find out why.
1886 memset(&of
, 0, sizeof(of
));
1887 #ifdef OPENFILENAME_SIZE_VERSION_400
1888 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1890 of
.lStructSize
= sizeof(of
);
1892 of
.hwndOwner
= hwnd
;
1893 of
.lpstrFilter
= "All Files\0*\0\0\0";
1894 of
.lpstrCustomFilter
= NULL
;
1895 of
.nFilterIndex
= 1;
1896 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
1897 of
.nMaxFile
= sizeof(filename
);
1898 of
.lpstrFileTitle
= NULL
;
1899 of
.lpstrInitialDir
= NULL
;
1900 of
.lpstrTitle
= "Select Public Key File";
1902 if (GetOpenFileName(&of
)) {
1903 strcpy(cfg
.keyfile
, filename
);
1904 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1910 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1913 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1914 WPARAM wParam
, LPARAM lParam
) {
1917 enum { controlstartvalue
= 1000,
1930 /* Accelerators used: [aco] stwx */
1931 ctlposinit(&cp
, hwnd
);
1932 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1933 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1934 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1936 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1937 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1938 "&to class", IDC_CCSTATIC2
);
1940 CheckRadioButton (hwnd
, IDC_MBWINDOWS
, IDC_MBXTERM
,
1941 cfg
.mouse_is_xterm ? IDC_MBXTERM
: IDC_MBWINDOWS
);
1943 static int tabs
[4] = {25, 61, 96, 128};
1944 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_SETTABSTOPS
, 4,
1947 for (i
=0; i
<256; i
++) {
1949 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1950 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1952 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_ADDSTRING
, 0,
1957 switch (LOWORD(wParam
)) {
1960 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
1966 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
1971 for (i
=0; i
<256; i
++)
1972 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
1975 cfg
.wordness
[i
] = n
;
1976 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1977 LB_DELETESTRING
, i
, 0);
1978 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1979 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1981 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1991 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1994 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
1995 WPARAM wParam
, LPARAM lParam
) {
1996 static const char *const colours
[] = {
1997 "Default Foreground", "Default Bold Foreground",
1998 "Default Background", "Default Bold Background",
1999 "Cursor Text", "Cursor Colour",
2000 "ANSI Black", "ANSI Black Bold",
2001 "ANSI Red", "ANSI Red Bold",
2002 "ANSI Green", "ANSI Green Bold",
2003 "ANSI Yellow", "ANSI Yellow Bold",
2004 "ANSI Blue", "ANSI Blue Bold",
2005 "ANSI Magenta", "ANSI Magenta Bold",
2006 "ANSI Cyan", "ANSI Cyan Bold",
2007 "ANSI White", "ANSI White Bold"
2009 static const int permanent
[] = {
2010 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
2011 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
2012 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
2015 enum { controlstartvalue
= 1000,
2031 /* Accelerators used: [aco] bmlu */
2032 ctlposinit(&cp
, hwnd
);
2033 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
2034 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
2035 colouredit(&cp
, "Select a colo&ur and click to modify it:",
2036 IDC_STATIC
, IDC_LIST
,
2037 "&Modify...", IDC_CHANGE
,
2038 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
2039 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
2040 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
2042 CheckDlgButton (hwnd
, IDC_BOLDCOLOUR
, cfg
.bold_colour
);
2043 CheckDlgButton (hwnd
, IDC_PALETTE
, cfg
.try_palette
);
2046 for (i
=0; i
<22; i
++)
2047 if (cfg
.bold_colour
|| permanent
[i
])
2048 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_ADDSTRING
, 0,
2049 (LPARAM
) colours
[i
]);
2051 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_SETCURSEL
, 0, 0);
2052 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[0][0], FALSE
);
2053 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[0][1], FALSE
);
2054 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[0][2], FALSE
);
2057 switch (LOWORD(wParam
)) {
2058 case IDC_BOLDCOLOUR
:
2059 if (HIWORD(wParam
) == BN_CLICKED
||
2060 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2062 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
2063 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
2064 if (cfg
.bold_colour
&& n
!=22) {
2065 for (i
=0; i
<22; i
++)
2067 SendDlgItemMessage (hwnd
, IDC_LIST
,
2069 (LPARAM
) colours
[i
]);
2070 } else if (!cfg
.bold_colour
&& n
!=12) {
2073 SendDlgItemMessage (hwnd
, IDC_LIST
,
2074 LB_DELETESTRING
, i
, 0);
2079 if (HIWORD(wParam
) == BN_CLICKED
||
2080 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2081 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
2084 if (HIWORD(wParam
) == LBN_DBLCLK
||
2085 HIWORD(wParam
) == LBN_SELCHANGE
) {
2086 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2088 if (!cfg
.bold_colour
)
2089 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2090 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
2091 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
2092 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
2096 if (HIWORD(wParam
) == BN_CLICKED
||
2097 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2098 static CHOOSECOLOR cc
;
2099 static DWORD custom
[16] = {0}; /* zero initialisers */
2100 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2102 if (!cfg
.bold_colour
)
2103 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2104 cc
.lStructSize
= sizeof(cc
);
2105 cc
.hwndOwner
= hwnd
;
2106 cc
.hInstance
= (HWND
)hinst
;
2107 cc
.lpCustColors
= custom
;
2108 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
2110 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
2111 if (ChooseColor(&cc
)) {
2113 (unsigned char) (cc
.rgbResult
& 0xFF);
2115 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
2117 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
2118 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
2120 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
2122 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
2130 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
2133 static int CALLBACK
TranslationProc (HWND hwnd
, UINT msg
,
2134 WPARAM wParam
, LPARAM lParam
) {
2136 enum { controlstartvalue
= 1000,
2151 /* Accelerators used: [aco] beiknpsx */
2152 ctlposinit(&cp
, hwnd
);
2154 "Handling of VT100 line drawing characters:", IDC_VTSTATIC
,
2155 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
2156 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
2157 "Use font in O&EM mode only", IDC_VTOEMONLY
,
2158 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
2159 IDC_VTPOORMAN
, NULL
);
2161 "Character set translation:", IDC_XLATSTATIC
,
2162 "&None", IDC_NOXLAT
,
2163 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
2164 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
, NULL
);
2165 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch", IDC_CAPSLOCKCYR
);
2167 CheckRadioButton (hwnd
, IDC_NOXLAT
, IDC_88592WIN1250
,
2168 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
2169 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
2171 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
2172 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
2173 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
2174 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
2175 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
2178 switch (LOWORD(wParam
)) {
2180 case IDC_KOI8WIN1251
:
2181 case IDC_88592WIN1250
:
2182 cfg
.xlat_enablekoiwin
=
2183 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
2184 cfg
.xlat_88592w1250
=
2185 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
2187 case IDC_CAPSLOCKCYR
:
2188 if (HIWORD(wParam
) == BN_CLICKED
||
2189 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2190 cfg
.xlat_capslockcyr
=
2191 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
2194 case IDC_VTXWINDOWS
:
2199 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
2200 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
2201 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
2206 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
2209 static DLGPROC panelproc
[NPANELS
] = {
2210 ConnectionProc
, KeyboardProc
, TerminalProc
, WindowProc
,
2211 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, TranslationProc
2214 static char *names
[NPANELS
] = {
2215 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
2216 "SSH", "Selection", "Colours", "Translation"
2219 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
2220 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 3, 6, 7, 8};
2222 static HWND
makesubdialog(HWND hwnd
, int x
, int y
, int w
, int h
, int n
) {
2226 r
.left
= x
; r
.top
= y
;
2227 r
.right
= r
.left
+ w
; r
.bottom
= r
.top
+ h
;
2228 MapDialogRect(hwnd
, &r
);
2229 ret
= CreateWindowEx(WS_EX_CONTROLPARENT
,
2230 WC_DIALOG
, "", /* no title */
2231 WS_CHILD
| WS_VISIBLE
| DS_SETFONT
,
2233 r
.right
-r
.left
, r
.bottom
-r
.top
,
2234 hwnd
, (HMENU
)IDC_SUBDLG
,
2236 SetWindowLong (ret
, DWL_DLGPROC
, (LONG
)panelproc
[n
]);
2237 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2238 SendMessage (ret
, WM_SETFONT
, font
, MAKELPARAM(0, 0));
2239 SendMessage (ret
, WM_INITDIALOG
, 0, 0);
2243 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
2244 WPARAM wParam
, LPARAM lParam
,
2245 int npanels
, int *panelnums
, HWND
*page
) {
2250 { /* centre the window */
2253 hw
= GetDesktopWindow();
2254 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
2255 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
2256 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
2257 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
2261 r
.left
= 3; r
.right
= r
.left
+ 174;
2262 r
.top
= 3; r
.bottom
= r
.top
+ 193;
2263 MapDialogRect(hwnd
, &r
);
2264 tabctl
= CreateWindowEx(0, WC_TABCONTROL
, "",
2265 WS_CHILD
| WS_VISIBLE
|
2266 WS_TABSTOP
| TCS_MULTILINE
,
2268 r
.right
-r
.left
, r
.bottom
-r
.top
,
2269 hwnd
, (HMENU
)IDC_TAB
, hinst
, NULL
);
2273 ctlposinit2(&cp
, hwnd
);
2274 ersatztab(&cp
, "Category:", IDC_TABSTATIC1
, IDC_TABLIST
,
2277 WPARAM font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2278 SendMessage(tabctl
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
2282 if (tabctl
) { /* initialise the tab control */
2286 for (i
=0; i
<npanels
; i
++) {
2287 tab
.mask
= TCIF_TEXT
;
2288 tab
.pszText
= names
[panelnums
[i
]];
2289 TabCtrl_InsertItem (tabctl
, i
, &tab
);
2294 for (i
=0; i
<npanels
; i
++) {
2295 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_ADDSTRING
,
2296 0, (LPARAM
)names
[panelnums
[i
]]);
2298 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_SETCURSEL
, 0, 0);
2300 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[0]);
2304 if (LOWORD(wParam
) == IDC_TAB
&&
2305 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
2306 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
2308 DestroyWindow (*page
);
2309 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2310 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
2315 switch (LOWORD(wParam
)) {
2317 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
2318 HWND tablist
= GetDlgItem (hwnd
, IDC_TABLIST
);
2319 int i
= SendMessage (tablist
, CB_GETCURSEL
, 0, 0);
2321 DestroyWindow (*page
);
2322 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2323 SetFocus(tablist
); /* ensure focus stays */
2329 EndDialog (hwnd
, 1);
2334 EndDialog (hwnd
, 0);
2339 EndDialog (hwnd
, 0);
2342 /* Grrr Explorer will maximize Dialogs! */
2344 if (wParam
== SIZE_MAXIMIZED
)
2351 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2352 WPARAM wParam
, LPARAM lParam
) {
2353 static HWND page
= NULL
;
2355 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2357 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
2358 EnableWindow(hwnd
, 0);
2359 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2360 GetParent(hwnd
), AboutProc
);
2361 EnableWindow(hwnd
, 1);
2362 SetActiveWindow(hwnd
);
2364 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2365 MAIN_NPANELS
, mainp
, &page
);
2368 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2369 WPARAM wParam
, LPARAM lParam
) {
2371 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2372 RECONF_NPANELS
, reconfp
, &page
);
2375 void get_sesslist(int allocate
) {
2376 static char otherbuf
[2048];
2377 static char *buffer
;
2378 int buflen
, bufsize
, i
;
2384 if ((handle
= enum_settings_start()) == NULL
)
2387 buflen
= bufsize
= 0;
2390 ret
= enum_settings_next(handle
, otherbuf
, sizeof(otherbuf
));
2392 int len
= strlen(otherbuf
)+1;
2393 if (bufsize
< buflen
+len
) {
2394 bufsize
= buflen
+ len
+ 2048;
2395 buffer
= srealloc(buffer
, bufsize
);
2397 strcpy(buffer
+buflen
, otherbuf
);
2398 buflen
+= strlen(buffer
+buflen
)+1;
2401 enum_settings_finish(handle
);
2402 buffer
= srealloc(buffer
, buflen
+1);
2403 buffer
[buflen
] = '\0';
2406 nsessions
= 1; /* "Default Settings" counts as one */
2408 if (strcmp(p
, "Default Settings"))
2414 sessions
= smalloc(nsessions
* sizeof(char *));
2415 sessions
[0] = "Default Settings";
2419 if (strcmp(p
, "Default Settings"))
2430 int do_config (void) {
2434 savedsession
[0] = '\0';
2435 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2436 get_sesslist(FALSE
);
2441 int do_reconfig (HWND hwnd
) {
2445 backup_cfg
= cfg
; /* structure copy */
2446 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2448 cfg
= backup_cfg
; /* structure copy */
2455 void do_defaults (char *session
) {
2457 load_settings (session
, TRUE
);
2459 load_settings ("Default Settings", FALSE
);
2462 void logevent (char *string
) {
2463 if (nevents
>= negsize
) {
2465 events
= srealloc (events
, negsize
* sizeof(*events
));
2467 events
[nevents
] = smalloc(1+strlen(string
));
2468 strcpy (events
[nevents
], string
);
2472 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2474 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2475 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2479 void showeventlog (HWND hwnd
) {
2481 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2483 ShowWindow (logbox
, SW_SHOWNORMAL
);
2487 void showabout (HWND hwnd
) {
2489 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2491 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2495 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2496 char *keystr
, char *fingerprint
) {
2499 static const char absentmsg
[] =
2500 "The server's host key is not cached in the registry. You\n"
2501 "have no guarantee that the server is the computer you\n"
2503 "The server's key fingerprint is:\n"
2505 "If you trust this host, hit Yes to add the key to\n"
2506 "PuTTY's cache and carry on connecting.\n"
2507 "If you do not trust this host, hit No to abandon the\n"
2510 static const char wrongmsg
[] =
2511 "WARNING - POTENTIAL SECURITY BREACH!\n"
2513 "The server's host key does not match the one PuTTY has\n"
2514 "cached in the registry. This means that either the\n"
2515 "server administrator has changed the host key, or you\n"
2516 "have actually connected to another computer pretending\n"
2517 "to be the server.\n"
2518 "The new key fingerprint is:\n"
2520 "If you were expecting this change and trust the new key,\n"
2521 "hit Yes to update PuTTY's cache and continue connecting.\n"
2522 "If you want to carry on connecting but without updating\n"
2523 "the cache, hit No.\n"
2524 "If you want to abandon the connection completely, hit\n"
2525 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2528 static const char mbtitle
[] = "PuTTY Security Alert";
2531 char message
[160+ /* sensible fingerprint max size */
2532 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2533 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2536 * Verify the key against the registry.
2538 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2540 if (ret
== 0) /* success - key matched OK */
2542 if (ret
== 2) { /* key was different */
2544 sprintf(message
, wrongmsg
, fingerprint
);
2545 mbret
= MessageBox(NULL
, message
, mbtitle
,
2546 MB_ICONWARNING
| MB_YESNOCANCEL
);
2548 store_host_key(host
, port
, keytype
, keystr
);
2549 if (mbret
== IDCANCEL
)
2552 if (ret
== 1) { /* key was absent */
2554 sprintf(message
, absentmsg
, fingerprint
);
2555 mbret
= MessageBox(NULL
, message
, mbtitle
,
2556 MB_ICONWARNING
| MB_YESNO
);
2559 store_host_key(host
, port
, keytype
, keystr
);