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 if (backends
[2].backend
== NULL
) {
1095 /* this is PuTTYtel, so only two protocols available */
1096 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1097 "&Raw", IDC_PROTRAW
,
1098 "&Telnet", IDC_PROTTELNET
, NULL
);
1100 radioline(&cp
, "Protocol:", IDC_PROTSTATIC
, 3,
1101 "&Raw", IDC_PROTRAW
,
1102 "&Telnet", IDC_PROTTELNET
,
1110 sesssaver(&cp
, "Stor&ed Sessions",
1111 IDC_SESSSTATIC
, IDC_SESSEDIT
, IDC_SESSLIST
,
1112 "&Load", IDC_SESSLOAD
,
1113 "&Save", IDC_SESSSAVE
,
1114 "&Delete", IDC_SESSDEL
, NULL
);
1115 checkbox(&cp
, "Close Window on E&xit", IDC_CLOSEEXIT
);
1116 checkbox(&cp
, "&Warn on Close", IDC_CLOSEWARN
);
1118 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1119 SetDlgItemText (hwnd
, IDC_SESSEDIT
, savedsession
);
1120 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1121 for (i
= 0; i
< nsessions
; i
++)
1122 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1123 0, (LPARAM
) (sessions
[i
]));
1124 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1125 cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1126 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
);
1127 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1128 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1132 * Button release should trigger WM_OK if there was a
1133 * previous double click on the session list.
1137 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
1140 switch (LOWORD(wParam
)) {
1141 case IDC_PROTTELNET
:
1144 if (HIWORD(wParam
) == BN_CLICKED
||
1145 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1146 int i
= IsDlgButtonChecked (hwnd
, IDC_PROTSSH
);
1147 int j
= IsDlgButtonChecked (hwnd
, IDC_PROTTELNET
);
1148 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
1149 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
1150 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
1151 cfg
.port
= i ?
22 : 23;
1152 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1157 if (HIWORD(wParam
) == EN_CHANGE
)
1158 GetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
,
1159 sizeof(cfg
.host
)-1);
1162 if (HIWORD(wParam
) == EN_CHANGE
)
1163 MyGetDlgItemInt (hwnd
, IDC_PORT
, &cfg
.port
);
1166 if (HIWORD(wParam
) == BN_CLICKED
||
1167 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1168 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC_CLOSEEXIT
);
1171 if (HIWORD(wParam
) == BN_CLICKED
||
1172 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1173 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC_CLOSEWARN
);
1176 if (HIWORD(wParam
) == EN_CHANGE
) {
1177 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1179 GetDlgItemText (hwnd
, IDC_SESSEDIT
,
1180 savedsession
, sizeof(savedsession
)-1);
1181 savedsession
[sizeof(savedsession
)-1] = '\0';
1185 if (HIWORD(wParam
) == BN_CLICKED
||
1186 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1191 GetDlgItemText (hwnd
, IDC_SESSEDIT
, str
, sizeof(str
)-1);
1193 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1194 LB_GETCURSEL
, 0, 0);
1199 strcpy (str
, sessions
[n
]);
1201 save_settings (str
, !!strcmp(str
, "Default Settings"));
1202 get_sesslist (FALSE
);
1203 get_sesslist (TRUE
);
1204 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1206 for (i
= 0; i
< nsessions
; i
++)
1207 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1208 0, (LPARAM
) (sessions
[i
]));
1209 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1215 if (LOWORD(wParam
) == IDC_SESSLOAD
&&
1216 HIWORD(wParam
) != BN_CLICKED
&&
1217 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1219 if (LOWORD(wParam
) == IDC_SESSLIST
&&
1220 HIWORD(wParam
) != LBN_DBLCLK
)
1223 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1224 LB_GETCURSEL
, 0, 0);
1229 load_settings (sessions
[n
],
1230 !!strcmp(sessions
[n
], "Default Settings"));
1231 SetDlgItemText (hwnd
, IDC_HOST
, cfg
.host
);
1232 SetDlgItemInt (hwnd
, IDC_PORT
, cfg
.port
, FALSE
);
1233 CheckRadioButton (hwnd
, IDC_PROTRAW
, IDC_PROTSSH
,
1234 (cfg
.protocol
==PROT_SSH ? IDC_PROTSSH
:
1235 cfg
.protocol
==PROT_TELNET ? IDC_PROTTELNET
: IDC_PROTRAW
));
1236 CheckDlgButton (hwnd
, IDC_CLOSEEXIT
, cfg
.close_on_exit
);
1237 CheckDlgButton (hwnd
, IDC_CLOSEWARN
, cfg
.warn_on_close
);
1238 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1241 if (LOWORD(wParam
) == IDC_SESSLIST
) {
1243 * A double-click on a saved session should
1244 * actually start the session, not just load it.
1245 * Unless it's Default Settings or some other
1246 * host-less set of saved settings.
1255 if (HIWORD(wParam
) == BN_CLICKED
||
1256 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1257 int n
= SendDlgItemMessage (hwnd
, IDC_SESSLIST
,
1258 LB_GETCURSEL
, 0, 0);
1259 if (n
== LB_ERR
|| n
== 0) {
1263 del_settings(sessions
[n
]);
1264 get_sesslist (FALSE
);
1265 get_sesslist (TRUE
);
1266 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_RESETCONTENT
,
1268 for (i
= 0; i
< nsessions
; i
++)
1269 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_ADDSTRING
,
1270 0, (LPARAM
) (sessions
[i
]));
1271 SendDlgItemMessage (hwnd
, IDC_SESSLIST
, LB_SETCURSEL
,
1276 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1279 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
1280 WPARAM wParam
, LPARAM lParam
) {
1282 enum { controlstartvalue
= 1000,
1308 /* Accelerators used: [aco] 4?ehiklmnprsuvxy */
1309 ctlposinit(&cp
, hwnd
);
1310 radioline(&cp
, "Action of Backspace:", IDC_DELSTATIC
, 2,
1311 "Control-&H", IDC_DEL008
,
1312 "Control-&? (127)", IDC_DEL127
, NULL
);
1313 radioline(&cp
, "Action of Home and End:", IDC_HOMESTATIC
, 2,
1314 "&Standard", IDC_HOMETILDE
,
1315 "&rxvt", IDC_HOMERXVT
, NULL
);
1316 radioline(&cp
, "Function key and keypad layout:", IDC_FUNCSTATIC
, 3,
1317 "&VT400", IDC_FUNCTILDE
,
1318 "&Linux", IDC_FUNCLINUX
,
1319 "&Xterm R6", IDC_FUNCXTERM
, NULL
);
1320 radioline(&cp
, "Initial state of cursor keys:", IDC_CURSTATIC
, 2,
1321 "&Normal", IDC_CURNORMAL
,
1322 "A&pplication", IDC_CURAPPLIC
, NULL
);
1323 radioline(&cp
, "Initial state of numeric keypad:", IDC_KPSTATIC
, 3,
1324 "Nor&mal", IDC_KPNORMAL
,
1325 "Appl&ication", IDC_KPAPPLIC
,
1326 "N&etHack", IDC_KPNH
, NULL
);
1327 checkbox(&cp
, "ALT-F&4 is special (closes window)", IDC_ALTF4
);
1328 checkbox(&cp
, "ALT-Space is special (S&ystem menu)", IDC_ALTSPACE
);
1329 checkbox(&cp
, "&Use local terminal line discipline", IDC_LDISCTERM
);
1330 checkbox(&cp
, "Reset scrollback on &keypress", IDC_SCROLLKEY
);
1332 CheckRadioButton (hwnd
, IDC_DEL008
, IDC_DEL127
,
1333 cfg
.bksp_is_delete ? IDC_DEL127
: IDC_DEL008
);
1334 CheckRadioButton (hwnd
, IDC_HOMETILDE
, IDC_HOMERXVT
,
1335 cfg
.rxvt_homeend ? IDC_HOMERXVT
: IDC_HOMETILDE
);
1336 CheckRadioButton (hwnd
, IDC_FUNCTILDE
, IDC_FUNCXTERM
,
1338 (cfg
.funky_type
==2 ? IDC_FUNCXTERM
1341 CheckRadioButton (hwnd
, IDC_CURNORMAL
, IDC_CURAPPLIC
,
1342 cfg
.app_cursor ? IDC_CURAPPLIC
: IDC_CURNORMAL
);
1343 CheckRadioButton (hwnd
, IDC_KPNORMAL
, IDC_KPNH
,
1344 cfg
.nethack_keypad ? IDC_KPNH
:
1345 cfg
.app_keypad ? IDC_KPAPPLIC
: IDC_KPNORMAL
);
1346 CheckDlgButton (hwnd
, IDC_ALTF4
, cfg
.alt_f4
);
1347 CheckDlgButton (hwnd
, IDC_ALTSPACE
, cfg
.alt_space
);
1348 CheckDlgButton (hwnd
, IDC_LDISCTERM
, cfg
.ldisc_term
);
1349 CheckDlgButton (hwnd
, IDC_SCROLLKEY
, cfg
.scroll_on_key
);
1352 if (HIWORD(wParam
) == BN_CLICKED
||
1353 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1354 switch (LOWORD(wParam
)) {
1357 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC_DEL127
);
1361 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC_HOMERXVT
);
1368 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC_FUNCLINUX
);
1372 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC_KPAPPLIC
);
1373 cfg
.nethack_keypad
= FALSE
;
1376 cfg
.app_keypad
= FALSE
;
1377 cfg
.nethack_keypad
= TRUE
;
1381 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC_CURAPPLIC
);
1384 if (HIWORD(wParam
) == BN_CLICKED
||
1385 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1386 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC_ALTF4
);
1389 if (HIWORD(wParam
) == BN_CLICKED
||
1390 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1391 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC_ALTSPACE
);
1394 if (HIWORD(wParam
) == BN_CLICKED
||
1395 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1396 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC_LDISCTERM
);
1399 if (HIWORD(wParam
) == BN_CLICKED
||
1400 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1401 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC_SCROLLKEY
);
1405 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1408 static void fmtfont (char *buf
) {
1409 sprintf (buf
, "Font: %s, ", cfg
.font
);
1411 strcat(buf
, "bold, ");
1412 if (cfg
.fontheight
== 0)
1413 strcat (buf
, "default height");
1415 sprintf (buf
+strlen(buf
), "%d-%s",
1416 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
1417 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
1420 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
1421 WPARAM wParam
, LPARAM lParam
) {
1425 char fontstatic
[256];
1426 enum { controlstartvalue
= 1000,
1446 /* Accelerators used: [aco] dghlmnprsw */
1447 ctlposinit(&cp
, hwnd
);
1449 "&Rows", IDC_ROWSSTATIC
, IDC_ROWSEDIT
, 33,
1450 "Colu&mns", IDC_COLSSTATIC
, IDC_COLSEDIT
, 33,
1451 "&Scrollback", IDC_SAVESTATIC
, IDC_SAVEEDIT
, 33,
1453 staticbtn(&cp
, "", IDC_FONTSTATIC
, "C&hange...", IDC_CHOOSEFONT
);
1454 checkbox(&cp
, "Auto &wrap mode initially on", IDC_WRAPMODE
);
1455 checkbox(&cp
, "&DEC Origin Mode initially on", IDC_DECOM
);
1456 checkbox(&cp
, "Implicit CR in every &LF", IDC_LFHASCR
);
1457 checkbox(&cp
, "Bee&p enabled", IDC_BEEP
);
1458 checkbox(&cp
, "Use Back&ground colour erase", IDC_BCE
);
1459 checkbox(&cp
, "Enable bli&nking text", IDC_BLINKTEXT
);
1461 CheckDlgButton (hwnd
, IDC_WRAPMODE
, cfg
.wrap_mode
);
1462 CheckDlgButton (hwnd
, IDC_DECOM
, cfg
.dec_om
);
1463 CheckDlgButton (hwnd
, IDC_LFHASCR
, cfg
.lfhascr
);
1464 SetDlgItemInt (hwnd
, IDC_ROWSEDIT
, cfg
.height
, FALSE
);
1465 SetDlgItemInt (hwnd
, IDC_COLSEDIT
, cfg
.width
, FALSE
);
1466 SetDlgItemInt (hwnd
, IDC_SAVEEDIT
, cfg
.savelines
, FALSE
);
1467 fmtfont (fontstatic
);
1468 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1469 CheckDlgButton (hwnd
, IDC_BEEP
, cfg
.beep
);
1470 CheckDlgButton (hwnd
, IDC_BCE
, cfg
.bce
);
1471 CheckDlgButton (hwnd
, IDC_BLINKTEXT
, cfg
.blinktext
);
1474 switch (LOWORD(wParam
)) {
1476 if (HIWORD(wParam
) == BN_CLICKED
||
1477 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1478 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC_WRAPMODE
);
1481 if (HIWORD(wParam
) == BN_CLICKED
||
1482 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1483 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC_DECOM
);
1486 if (HIWORD(wParam
) == BN_CLICKED
||
1487 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1488 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC_LFHASCR
);
1491 if (HIWORD(wParam
) == EN_CHANGE
)
1492 MyGetDlgItemInt (hwnd
, IDC_ROWSEDIT
, &cfg
.height
);
1495 if (HIWORD(wParam
) == EN_CHANGE
)
1496 MyGetDlgItemInt (hwnd
, IDC_COLSEDIT
, &cfg
.width
);
1499 if (HIWORD(wParam
) == EN_CHANGE
)
1500 MyGetDlgItemInt (hwnd
, IDC_SAVEEDIT
, &cfg
.savelines
);
1502 case IDC_CHOOSEFONT
:
1503 lf
.lfHeight
= cfg
.fontheight
;
1504 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
1505 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
1506 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
1507 lf
.lfCharSet
= cfg
.fontcharset
;
1508 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1509 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1510 lf
.lfQuality
= DEFAULT_QUALITY
;
1511 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
1512 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
1513 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
1515 cf
.lStructSize
= sizeof(cf
);
1516 cf
.hwndOwner
= hwnd
;
1518 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
1519 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
1521 if (ChooseFont (&cf
)) {
1522 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
1523 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
1524 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
1525 cfg
.fontcharset
= lf
.lfCharSet
;
1526 cfg
.fontheight
= lf
.lfHeight
;
1527 fmtfont (fontstatic
);
1528 SetDlgItemText (hwnd
, IDC_FONTSTATIC
, fontstatic
);
1532 if (HIWORD(wParam
) == BN_CLICKED
||
1533 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1534 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC_BEEP
);
1537 if (HIWORD(wParam
) == BN_CLICKED
||
1538 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1539 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC_BLINKTEXT
);
1542 if (HIWORD(wParam
) == BN_CLICKED
||
1543 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1544 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC_BCE
);
1549 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1552 static int CALLBACK
WindowProc (HWND hwnd
, UINT msg
,
1553 WPARAM wParam
, LPARAM lParam
) {
1555 enum { controlstartvalue
= 1000,
1566 /* Accelerators used: [aco] bikty */
1567 ctlposinit(&cp
, hwnd
);
1569 "Initial window &title:", IDC_WINTITLE
, IDC_WINEDIT
, 100,
1571 checkbox(&cp
, "Avoid ever using &icon title", IDC_WINNAME
);
1572 checkbox(&cp
, "&Blinking cursor", IDC_BLINKCUR
);
1573 checkbox(&cp
, "Displa&y scrollbar", IDC_SCROLLBAR
);
1574 checkbox(&cp
, "Loc&k Window size", IDC_LOCKSIZE
);
1576 SetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
);
1577 CheckDlgButton (hwnd
, IDC_WINNAME
, cfg
.win_name_always
);
1578 CheckDlgButton (hwnd
, IDC_BLINKCUR
, cfg
.blink_cur
);
1579 CheckDlgButton (hwnd
, IDC_SCROLLBAR
, cfg
.scrollbar
);
1580 CheckDlgButton (hwnd
, IDC_LOCKSIZE
, cfg
.locksize
);
1583 switch (LOWORD(wParam
)) {
1585 if (HIWORD(wParam
) == BN_CLICKED
||
1586 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1587 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC_WINNAME
);
1590 if (HIWORD(wParam
) == BN_CLICKED
||
1591 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1592 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC_BLINKCUR
);
1595 if (HIWORD(wParam
) == BN_CLICKED
||
1596 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1597 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC_SCROLLBAR
);
1600 if (HIWORD(wParam
) == BN_CLICKED
||
1601 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1602 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC_LOCKSIZE
);
1605 if (HIWORD(wParam
) == EN_CHANGE
)
1606 GetDlgItemText (hwnd
, IDC_WINEDIT
, cfg
.wintitle
,
1607 sizeof(cfg
.wintitle
)-1);
1612 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1615 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
1616 WPARAM wParam
, LPARAM lParam
) {
1619 enum { controlstartvalue
= 1000,
1641 /* Accelerators used: [aco] bdflrstuv */
1642 ctlposinit(&cp
, hwnd
);
1643 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1644 staticedit(&cp
, "Terminal-&speed string", IDC_TSSTATIC
, IDC_TSEDIT
);
1645 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1646 envsetter(&cp
, "Environment variables:", IDC_ENVSTATIC
,
1647 "&Variable", IDC_VARSTATIC
, IDC_VAREDIT
,
1648 "Va&lue", IDC_VALSTATIC
, IDC_VALEDIT
,
1650 "A&dd", IDC_ENVADD
, "&Remove", IDC_ENVREMOVE
);
1651 radioline(&cp
, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC
, 2,
1652 "&BSD (commonplace)", IDC_EMBSD
,
1653 "R&FC 1408 (unusual)", IDC_EMRFC
, NULL
);
1655 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1656 SetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
);
1657 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1659 char *p
= cfg
.environmt
;
1661 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
, 0,
1666 CheckRadioButton (hwnd
, IDC_EMBSD
, IDC_EMRFC
,
1667 cfg
.rfc_environ ? IDC_EMRFC
: IDC_EMBSD
);
1670 switch (LOWORD(wParam
)) {
1672 if (HIWORD(wParam
) == EN_CHANGE
)
1673 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1674 sizeof(cfg
.termtype
)-1);
1677 if (HIWORD(wParam
) == EN_CHANGE
)
1678 GetDlgItemText (hwnd
, IDC_TSEDIT
, cfg
.termspeed
,
1679 sizeof(cfg
.termspeed
)-1);
1682 if (HIWORD(wParam
) == EN_CHANGE
)
1683 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1684 sizeof(cfg
.username
)-1);
1688 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC_EMRFC
);
1691 if (HIWORD(wParam
) == BN_CLICKED
||
1692 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1693 char str
[sizeof(cfg
.environmt
)];
1695 GetDlgItemText (hwnd
, IDC_VAREDIT
, str
, sizeof(str
)-1);
1700 p
= str
+ strlen(str
);
1702 GetDlgItemText (hwnd
, IDC_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
1712 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
1714 p
[strlen(str
)+1] = '\0';
1715 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_ADDSTRING
,
1717 SetDlgItemText (hwnd
, IDC_VAREDIT
, "");
1718 SetDlgItemText (hwnd
, IDC_VALEDIT
, "");
1720 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
1721 MB_OK
| MB_ICONERROR
);
1726 if (HIWORD(wParam
) != BN_CLICKED
&&
1727 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1729 i
= SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_GETCURSEL
, 0, 0);
1735 SendDlgItemMessage (hwnd
, IDC_ENVLIST
, LB_DELETESTRING
,
1762 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1765 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
1766 WPARAM wParam
, LPARAM lParam
) {
1769 char filename
[sizeof(cfg
.keyfile
)];
1770 enum { controlstartvalue
= 1000,
1794 /* Accelerators used: [aco] 123abdkmprtuw */
1795 ctlposinit(&cp
, hwnd
);
1796 staticedit(&cp
, "Terminal-&type string", IDC_TTSTATIC
, IDC_TTEDIT
);
1797 staticedit(&cp
, "Auto-login &username", IDC_LOGSTATIC
, IDC_LOGEDIT
);
1799 "&Remote command:", IDC_CMDSTATIC
, IDC_CMDEDIT
, 100,
1801 checkbox(&cp
, "Don't allocate a &pseudo-terminal", IDC_NOPTY
);
1802 checkbox(&cp
, "Atte&mpt TIS or CryptoCard authentication",
1804 checkbox(&cp
, "Allow &agent forwarding", IDC_AGENTFWD
);
1805 editbutton(&cp
, "Private &key file for authentication:",
1806 IDC_PKSTATIC
, IDC_PKEDIT
, "Bro&wse...", IDC_PKBUTTON
);
1807 radioline(&cp
, "Preferred SSH protocol version:",
1808 IDC_SSHPROTSTATIC
, 2,
1809 "&1", IDC_SSHPROT1
, "&2", IDC_SSHPROT2
, NULL
);
1810 radioline(&cp
, "Preferred encryption algorithm:", IDC_CIPHERSTATIC
, 3,
1811 "&3DES", IDC_CIPHER3DES
,
1812 "&Blowfish", IDC_CIPHERBLOWF
,
1813 "&DES", IDC_CIPHERDES
, NULL
);
1815 SetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
);
1816 SetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
);
1817 CheckDlgButton (hwnd
, IDC_NOPTY
, cfg
.nopty
);
1818 CheckDlgButton (hwnd
, IDC_AGENTFWD
, cfg
.agentfwd
);
1819 CheckRadioButton (hwnd
, IDC_CIPHER3DES
, IDC_CIPHERDES
,
1820 cfg
.cipher
== CIPHER_BLOWFISH ? IDC_CIPHERBLOWF
:
1821 cfg
.cipher
== CIPHER_DES ? IDC_CIPHERDES
:
1823 CheckRadioButton (hwnd
, IDC_SSHPROT1
, IDC_SSHPROT2
,
1824 cfg
.sshprot
== 1 ? IDC_SSHPROT1
: IDC_SSHPROT2
);
1825 CheckDlgButton (hwnd
, IDC_AUTHTIS
, cfg
.try_tis_auth
);
1826 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1827 SetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
);
1830 switch (LOWORD(wParam
)) {
1832 if (HIWORD(wParam
) == EN_CHANGE
)
1833 GetDlgItemText (hwnd
, IDC_TTEDIT
, cfg
.termtype
,
1834 sizeof(cfg
.termtype
)-1);
1837 if (HIWORD(wParam
) == EN_CHANGE
)
1838 GetDlgItemText (hwnd
, IDC_LOGEDIT
, cfg
.username
,
1839 sizeof(cfg
.username
)-1);
1842 if (HIWORD(wParam
) == BN_CLICKED
||
1843 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1844 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC_NOPTY
);
1847 if (HIWORD(wParam
) == BN_CLICKED
||
1848 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1849 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC_AGENTFWD
);
1851 case IDC_CIPHER3DES
:
1852 case IDC_CIPHERBLOWF
:
1854 if (HIWORD(wParam
) == BN_CLICKED
||
1855 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1856 if (IsDlgButtonChecked (hwnd
, IDC_CIPHER3DES
))
1857 cfg
.cipher
= CIPHER_3DES
;
1858 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERBLOWF
))
1859 cfg
.cipher
= CIPHER_BLOWFISH
;
1860 else if (IsDlgButtonChecked (hwnd
, IDC_CIPHERDES
))
1861 cfg
.cipher
= CIPHER_DES
;
1866 if (HIWORD(wParam
) == BN_CLICKED
||
1867 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1868 if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT1
))
1870 else if (IsDlgButtonChecked (hwnd
, IDC_SSHPROT2
))
1875 if (HIWORD(wParam
) == BN_CLICKED
||
1876 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1877 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC_AUTHTIS
);
1880 if (HIWORD(wParam
) == EN_CHANGE
)
1881 GetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
,
1882 sizeof(cfg
.keyfile
)-1);
1885 if (HIWORD(wParam
) == EN_CHANGE
)
1886 GetDlgItemText (hwnd
, IDC_CMDEDIT
, cfg
.remote_cmd
,
1887 sizeof(cfg
.remote_cmd
)-1);
1891 * FIXME: this crashes. Find out why.
1893 memset(&of
, 0, sizeof(of
));
1894 #ifdef OPENFILENAME_SIZE_VERSION_400
1895 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1897 of
.lStructSize
= sizeof(of
);
1899 of
.hwndOwner
= hwnd
;
1900 of
.lpstrFilter
= "All Files\0*\0\0\0";
1901 of
.lpstrCustomFilter
= NULL
;
1902 of
.nFilterIndex
= 1;
1903 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
1904 of
.nMaxFile
= sizeof(filename
);
1905 of
.lpstrFileTitle
= NULL
;
1906 of
.lpstrInitialDir
= NULL
;
1907 of
.lpstrTitle
= "Select Public Key File";
1909 if (GetOpenFileName(&of
)) {
1910 strcpy(cfg
.keyfile
, filename
);
1911 SetDlgItemText (hwnd
, IDC_PKEDIT
, cfg
.keyfile
);
1917 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1920 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1921 WPARAM wParam
, LPARAM lParam
) {
1924 enum { controlstartvalue
= 1000,
1937 /* Accelerators used: [aco] stwx */
1938 ctlposinit(&cp
, hwnd
);
1939 radiobig(&cp
, "Action of mouse buttons:", IDC_MBSTATIC
,
1940 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS
,
1941 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM
,
1943 charclass(&cp
, "Character classes:", IDC_CCSTATIC
, IDC_CCLIST
,
1944 "&Set", IDC_CCSET
, IDC_CCEDIT
,
1945 "&to class", IDC_CCSTATIC2
);
1947 CheckRadioButton (hwnd
, IDC_MBWINDOWS
, IDC_MBXTERM
,
1948 cfg
.mouse_is_xterm ? IDC_MBXTERM
: IDC_MBWINDOWS
);
1950 static int tabs
[4] = {25, 61, 96, 128};
1951 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_SETTABSTOPS
, 4,
1954 for (i
=0; i
<256; i
++) {
1956 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1957 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1959 SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_ADDSTRING
, 0,
1964 switch (LOWORD(wParam
)) {
1967 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC_MBXTERM
);
1973 int n
= GetDlgItemInt (hwnd
, IDC_CCEDIT
, &ok
, FALSE
);
1978 for (i
=0; i
<256; i
++)
1979 if (SendDlgItemMessage (hwnd
, IDC_CCLIST
, LB_GETSEL
,
1982 cfg
.wordness
[i
] = n
;
1983 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1984 LB_DELETESTRING
, i
, 0);
1985 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1986 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1988 SendDlgItemMessage (hwnd
, IDC_CCLIST
,
1998 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
2001 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
2002 WPARAM wParam
, LPARAM lParam
) {
2003 static const char *const colours
[] = {
2004 "Default Foreground", "Default Bold Foreground",
2005 "Default Background", "Default Bold Background",
2006 "Cursor Text", "Cursor Colour",
2007 "ANSI Black", "ANSI Black Bold",
2008 "ANSI Red", "ANSI Red Bold",
2009 "ANSI Green", "ANSI Green Bold",
2010 "ANSI Yellow", "ANSI Yellow Bold",
2011 "ANSI Blue", "ANSI Blue Bold",
2012 "ANSI Magenta", "ANSI Magenta Bold",
2013 "ANSI Cyan", "ANSI Cyan Bold",
2014 "ANSI White", "ANSI White Bold"
2016 static const int permanent
[] = {
2017 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
2018 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
2019 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
2022 enum { controlstartvalue
= 1000,
2038 /* Accelerators used: [aco] bmlu */
2039 ctlposinit(&cp
, hwnd
);
2040 checkbox(&cp
, "&Bolded text is a different colour", IDC_BOLDCOLOUR
);
2041 checkbox(&cp
, "Attempt to use &logical palettes", IDC_PALETTE
);
2042 colouredit(&cp
, "Select a colo&ur and click to modify it:",
2043 IDC_STATIC
, IDC_LIST
,
2044 "&Modify...", IDC_CHANGE
,
2045 "Red:", IDC_RSTATIC
, IDC_RVALUE
,
2046 "Green:", IDC_GSTATIC
, IDC_GVALUE
,
2047 "Blue:", IDC_BSTATIC
, IDC_BVALUE
, NULL
);
2049 CheckDlgButton (hwnd
, IDC_BOLDCOLOUR
, cfg
.bold_colour
);
2050 CheckDlgButton (hwnd
, IDC_PALETTE
, cfg
.try_palette
);
2053 for (i
=0; i
<22; i
++)
2054 if (cfg
.bold_colour
|| permanent
[i
])
2055 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_ADDSTRING
, 0,
2056 (LPARAM
) colours
[i
]);
2058 SendDlgItemMessage (hwnd
, IDC_LIST
, LB_SETCURSEL
, 0, 0);
2059 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[0][0], FALSE
);
2060 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[0][1], FALSE
);
2061 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[0][2], FALSE
);
2064 switch (LOWORD(wParam
)) {
2065 case IDC_BOLDCOLOUR
:
2066 if (HIWORD(wParam
) == BN_CLICKED
||
2067 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2069 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC_BOLDCOLOUR
);
2070 n
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCOUNT
, 0, 0);
2071 if (cfg
.bold_colour
&& n
!=22) {
2072 for (i
=0; i
<22; i
++)
2074 SendDlgItemMessage (hwnd
, IDC_LIST
,
2076 (LPARAM
) colours
[i
]);
2077 } else if (!cfg
.bold_colour
&& n
!=12) {
2080 SendDlgItemMessage (hwnd
, IDC_LIST
,
2081 LB_DELETESTRING
, i
, 0);
2086 if (HIWORD(wParam
) == BN_CLICKED
||
2087 HIWORD(wParam
) == BN_DOUBLECLICKED
)
2088 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC_PALETTE
);
2091 if (HIWORD(wParam
) == LBN_DBLCLK
||
2092 HIWORD(wParam
) == LBN_SELCHANGE
) {
2093 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2095 if (!cfg
.bold_colour
)
2096 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2097 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0], FALSE
);
2098 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1], FALSE
);
2099 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2], FALSE
);
2103 if (HIWORD(wParam
) == BN_CLICKED
||
2104 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2105 static CHOOSECOLOR cc
;
2106 static DWORD custom
[16] = {0}; /* zero initialisers */
2107 int i
= SendDlgItemMessage (hwnd
, IDC_LIST
, LB_GETCURSEL
,
2109 if (!cfg
.bold_colour
)
2110 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
2111 cc
.lStructSize
= sizeof(cc
);
2112 cc
.hwndOwner
= hwnd
;
2113 cc
.hInstance
= (HWND
)hinst
;
2114 cc
.lpCustColors
= custom
;
2115 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
2117 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
2118 if (ChooseColor(&cc
)) {
2120 (unsigned char) (cc
.rgbResult
& 0xFF);
2122 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
2124 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
2125 SetDlgItemInt (hwnd
, IDC_RVALUE
, cfg
.colours
[i
][0],
2127 SetDlgItemInt (hwnd
, IDC_GVALUE
, cfg
.colours
[i
][1],
2129 SetDlgItemInt (hwnd
, IDC_BVALUE
, cfg
.colours
[i
][2],
2137 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
2140 static int CALLBACK
TranslationProc (HWND hwnd
, UINT msg
,
2141 WPARAM wParam
, LPARAM lParam
) {
2143 enum { controlstartvalue
= 1000,
2158 /* Accelerators used: [aco] beiknpsx */
2159 ctlposinit(&cp
, hwnd
);
2161 "Handling of VT100 line drawing characters:", IDC_VTSTATIC
,
2162 "Font has &XWindows encoding", IDC_VTXWINDOWS
,
2163 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI
,
2164 "Use font in O&EM mode only", IDC_VTOEMONLY
,
2165 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
2166 IDC_VTPOORMAN
, NULL
);
2168 "Character set translation:", IDC_XLATSTATIC
,
2169 "&None", IDC_NOXLAT
,
2170 "&KOI8 / Win-1251", IDC_KOI8WIN1251
,
2171 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250
, NULL
);
2172 checkbox(&cp
, "CAP&S LOCK acts as cyrillic switch", IDC_CAPSLOCKCYR
);
2174 CheckRadioButton (hwnd
, IDC_NOXLAT
, IDC_88592WIN1250
,
2175 cfg
.xlat_88592w1250 ? IDC_88592WIN1250
:
2176 cfg
.xlat_enablekoiwin ? IDC_KOI8WIN1251
:
2178 CheckDlgButton (hwnd
, IDC_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
2179 CheckRadioButton (hwnd
, IDC_VTXWINDOWS
, IDC_VTPOORMAN
,
2180 cfg
.vtmode
== VT_XWINDOWS ? IDC_VTXWINDOWS
:
2181 cfg
.vtmode
== VT_OEMANSI ? IDC_VTOEMANSI
:
2182 cfg
.vtmode
== VT_OEMONLY ? IDC_VTOEMONLY
:
2185 switch (LOWORD(wParam
)) {
2187 case IDC_KOI8WIN1251
:
2188 case IDC_88592WIN1250
:
2189 cfg
.xlat_enablekoiwin
=
2190 IsDlgButtonChecked (hwnd
, IDC_KOI8WIN1251
);
2191 cfg
.xlat_88592w1250
=
2192 IsDlgButtonChecked (hwnd
, IDC_88592WIN1250
);
2194 case IDC_CAPSLOCKCYR
:
2195 if (HIWORD(wParam
) == BN_CLICKED
||
2196 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
2197 cfg
.xlat_capslockcyr
=
2198 IsDlgButtonChecked (hwnd
, IDC_CAPSLOCKCYR
);
2201 case IDC_VTXWINDOWS
:
2206 (IsDlgButtonChecked (hwnd
, IDC_VTXWINDOWS
) ? VT_XWINDOWS
:
2207 IsDlgButtonChecked (hwnd
, IDC_VTOEMANSI
) ? VT_OEMANSI
:
2208 IsDlgButtonChecked (hwnd
, IDC_VTOEMONLY
) ? VT_OEMONLY
:
2213 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
2216 static DLGPROC panelproc
[NPANELS
] = {
2217 ConnectionProc
, KeyboardProc
, TerminalProc
, WindowProc
,
2218 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, TranslationProc
2221 static char *names
[NPANELS
] = {
2222 "Connection", "Keyboard", "Terminal", "Window", "Telnet",
2223 "SSH", "Selection", "Colours", "Translation"
2226 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
2227 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 3, 6, 7, 8};
2229 static HWND
makesubdialog(HWND hwnd
, int x
, int y
, int w
, int h
, int n
) {
2233 r
.left
= x
; r
.top
= y
;
2234 r
.right
= r
.left
+ w
; r
.bottom
= r
.top
+ h
;
2235 MapDialogRect(hwnd
, &r
);
2236 ret
= CreateWindowEx(WS_EX_CONTROLPARENT
,
2237 WC_DIALOG
, "", /* no title */
2238 WS_CHILD
| WS_VISIBLE
| DS_SETFONT
,
2240 r
.right
-r
.left
, r
.bottom
-r
.top
,
2241 hwnd
, (HMENU
)IDC_SUBDLG
,
2243 SetWindowLong (ret
, DWL_DLGPROC
, (LONG
)panelproc
[n
]);
2244 font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2245 SendMessage (ret
, WM_SETFONT
, font
, MAKELPARAM(0, 0));
2246 SendMessage (ret
, WM_INITDIALOG
, 0, 0);
2250 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
2251 WPARAM wParam
, LPARAM lParam
,
2252 int npanels
, int *panelnums
, HWND
*page
) {
2257 { /* centre the window */
2260 hw
= GetDesktopWindow();
2261 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
2262 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
2263 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
2264 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
2268 r
.left
= 3; r
.right
= r
.left
+ 174;
2269 r
.top
= 3; r
.bottom
= r
.top
+ 193;
2270 MapDialogRect(hwnd
, &r
);
2271 tabctl
= CreateWindowEx(0, WC_TABCONTROL
, "",
2272 WS_CHILD
| WS_VISIBLE
|
2273 WS_TABSTOP
| TCS_MULTILINE
,
2275 r
.right
-r
.left
, r
.bottom
-r
.top
,
2276 hwnd
, (HMENU
)IDC_TAB
, hinst
, NULL
);
2280 ctlposinit2(&cp
, hwnd
);
2281 ersatztab(&cp
, "Category:", IDC_TABSTATIC1
, IDC_TABLIST
,
2284 WPARAM font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
2285 SendMessage(tabctl
, WM_SETFONT
, font
, MAKELPARAM(TRUE
, 0));
2289 if (tabctl
) { /* initialise the tab control */
2293 for (i
=0; i
<npanels
; i
++) {
2294 tab
.mask
= TCIF_TEXT
;
2295 tab
.pszText
= names
[panelnums
[i
]];
2296 TabCtrl_InsertItem (tabctl
, i
, &tab
);
2301 for (i
=0; i
<npanels
; i
++) {
2302 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_ADDSTRING
,
2303 0, (LPARAM
)names
[panelnums
[i
]]);
2305 SendDlgItemMessage(hwnd
, IDC_TABLIST
, CB_SETCURSEL
, 0, 0);
2307 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[0]);
2311 if (LOWORD(wParam
) == IDC_TAB
&&
2312 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
2313 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
2315 DestroyWindow (*page
);
2316 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2317 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
2322 switch (LOWORD(wParam
)) {
2324 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
2325 HWND tablist
= GetDlgItem (hwnd
, IDC_TABLIST
);
2326 int i
= SendMessage (tablist
, CB_GETCURSEL
, 0, 0);
2328 DestroyWindow (*page
);
2329 *page
= makesubdialog(hwnd
, 6, 30, 168, 163, panelnums
[i
]);
2330 SetFocus(tablist
); /* ensure focus stays */
2336 EndDialog (hwnd
, 1);
2341 EndDialog (hwnd
, 0);
2346 EndDialog (hwnd
, 0);
2349 /* Grrr Explorer will maximize Dialogs! */
2351 if (wParam
== SIZE_MAXIMIZED
)
2358 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
2359 WPARAM wParam
, LPARAM lParam
) {
2360 static HWND page
= NULL
;
2362 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
2364 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
2365 EnableWindow(hwnd
, 0);
2366 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2367 GetParent(hwnd
), AboutProc
);
2368 EnableWindow(hwnd
, 1);
2369 SetActiveWindow(hwnd
);
2371 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2372 MAIN_NPANELS
, mainp
, &page
);
2375 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
2376 WPARAM wParam
, LPARAM lParam
) {
2378 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
2379 RECONF_NPANELS
, reconfp
, &page
);
2382 void get_sesslist(int allocate
) {
2383 static char otherbuf
[2048];
2384 static char *buffer
;
2385 int buflen
, bufsize
, i
;
2391 if ((handle
= enum_settings_start()) == NULL
)
2394 buflen
= bufsize
= 0;
2397 ret
= enum_settings_next(handle
, otherbuf
, sizeof(otherbuf
));
2399 int len
= strlen(otherbuf
)+1;
2400 if (bufsize
< buflen
+len
) {
2401 bufsize
= buflen
+ len
+ 2048;
2402 buffer
= srealloc(buffer
, bufsize
);
2404 strcpy(buffer
+buflen
, otherbuf
);
2405 buflen
+= strlen(buffer
+buflen
)+1;
2408 enum_settings_finish(handle
);
2409 buffer
= srealloc(buffer
, buflen
+1);
2410 buffer
[buflen
] = '\0';
2413 nsessions
= 1; /* "Default Settings" counts as one */
2415 if (strcmp(p
, "Default Settings"))
2421 sessions
= smalloc(nsessions
* sizeof(char *));
2422 sessions
[0] = "Default Settings";
2426 if (strcmp(p
, "Default Settings"))
2437 int do_config (void) {
2441 savedsession
[0] = '\0';
2442 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
2443 get_sesslist(FALSE
);
2448 int do_reconfig (HWND hwnd
) {
2452 backup_cfg
= cfg
; /* structure copy */
2453 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
2455 cfg
= backup_cfg
; /* structure copy */
2462 void do_defaults (char *session
) {
2464 load_settings (session
, TRUE
);
2466 load_settings ("Default Settings", FALSE
);
2469 void logevent (char *string
) {
2470 if (nevents
>= negsize
) {
2472 events
= srealloc (events
, negsize
* sizeof(*events
));
2474 events
[nevents
] = smalloc(1+strlen(string
));
2475 strcpy (events
[nevents
], string
);
2479 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
2481 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
2482 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
2486 void showeventlog (HWND hwnd
) {
2488 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
2490 ShowWindow (logbox
, SW_SHOWNORMAL
);
2494 void showabout (HWND hwnd
) {
2496 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
2498 ShowWindow (abtbox
, SW_SHOWNORMAL
);
2502 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
2503 char *keystr
, char *fingerprint
) {
2506 static const char absentmsg
[] =
2507 "The server's host key is not cached in the registry. You\n"
2508 "have no guarantee that the server is the computer you\n"
2510 "The server's key fingerprint is:\n"
2512 "If you trust this host, hit Yes to add the key to\n"
2513 "PuTTY's cache and carry on connecting.\n"
2514 "If you do not trust this host, hit No to abandon the\n"
2517 static const char wrongmsg
[] =
2518 "WARNING - POTENTIAL SECURITY BREACH!\n"
2520 "The server's host key does not match the one PuTTY has\n"
2521 "cached in the registry. This means that either the\n"
2522 "server administrator has changed the host key, or you\n"
2523 "have actually connected to another computer pretending\n"
2524 "to be the server.\n"
2525 "The new key fingerprint is:\n"
2527 "If you were expecting this change and trust the new key,\n"
2528 "hit Yes to update PuTTY's cache and continue connecting.\n"
2529 "If you want to carry on connecting but without updating\n"
2530 "the cache, hit No.\n"
2531 "If you want to abandon the connection completely, hit\n"
2532 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2535 static const char mbtitle
[] = "PuTTY Security Alert";
2538 char message
[160+ /* sensible fingerprint max size */
2539 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
2540 sizeof(absentmsg
) : sizeof(wrongmsg
))];
2543 * Verify the key against the registry.
2545 ret
= verify_host_key(host
, port
, keytype
, keystr
);
2547 if (ret
== 0) /* success - key matched OK */
2549 if (ret
== 2) { /* key was different */
2551 sprintf(message
, wrongmsg
, fingerprint
);
2552 mbret
= MessageBox(NULL
, message
, mbtitle
,
2553 MB_ICONWARNING
| MB_YESNOCANCEL
);
2555 store_host_key(host
, port
, keytype
, keystr
);
2556 if (mbret
== IDCANCEL
)
2559 if (ret
== 1) { /* key was absent */
2561 sprintf(message
, absentmsg
, fingerprint
);
2562 mbret
= MessageBox(NULL
, message
, mbtitle
,
2563 MB_ICONWARNING
| MB_YESNO
);
2566 store_host_key(host
, port
, keytype
, keystr
);