13 #define MAIN_NPANELS 8
14 #define RECONF_NPANELS 5
16 static const char *const puttystr
= PUTTY_REG_POS
"\\Sessions";
18 static char **events
= NULL
;
19 static int nevents
= 0, negsize
= 0;
21 static HWND logbox
= NULL
, abtbox
= NULL
;
23 static char hex
[16] = "0123456789ABCDEF";
25 static void mungestr(char *in
, char *out
) {
29 if (*in
== ' ' || *in
== '\\' || *in
== '*' || *in
== '?' ||
30 *in
== '%' || *in
< ' ' || *in
> '~' || (*in
== '.' && !candot
)) {
32 *out
++ = hex
[((unsigned char)*in
) >> 4];
33 *out
++ = hex
[((unsigned char)*in
) & 15];
43 static void unmungestr(char *in
, char *out
) {
45 if (*in
== '%' && in
[1] && in
[2]) {
48 i
= in
[1] - '0'; i
-= (i
> 9 ?
7 : 0);
49 j
= in
[2] - '0'; j
-= (j
> 9 ?
7 : 0);
60 static void wpps(HKEY key
, LPCTSTR name
, LPCTSTR value
) {
61 RegSetValueEx(key
, name
, 0, REG_SZ
, value
, 1+strlen(value
));
64 static void wppi(HKEY key
, LPCTSTR name
, int value
) {
65 RegSetValueEx(key
, name
, 0, REG_DWORD
,
66 (CONST BYTE
*)&value
, sizeof(value
));
69 static void gpps(HKEY key
, LPCTSTR name
, LPCTSTR def
,
70 LPTSTR val
, int len
) {
75 RegQueryValueEx(key
, name
, 0, &type
, val
, &size
) != ERROR_SUCCESS
||
77 strncpy(val
, def
, len
);
82 static void gppi(HKEY key
, LPCTSTR name
, int def
, int *i
) {
83 DWORD type
, val
, size
;
87 RegQueryValueEx(key
, name
, 0, &type
,
88 (BYTE
*)&val
, &size
) != ERROR_SUCCESS
||
89 size
!= sizeof(val
) || type
!= REG_DWORD
)
95 static HINSTANCE hinst
;
99 static void save_settings (char *section
, int do_host
) {
101 HKEY subkey1
, sesskey
;
104 p
= malloc(3*strlen(section
)+1);
105 mungestr(section
, p
);
107 if (RegCreateKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
)!=ERROR_SUCCESS
||
108 RegCreateKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
113 RegCloseKey(subkey1
);
115 wppi (sesskey
, "Present", 1);
117 wpps (sesskey
, "HostName", cfg
.host
);
118 wppi (sesskey
, "PortNumber", cfg
.port
);
120 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
121 if (backends
[i
].protocol
== cfg
.protocol
) {
122 p
= backends
[i
].name
;
125 wpps (sesskey
, "Protocol", p
);
127 wppi (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
128 wppi (sesskey
, "WarnOnClose", !!cfg
.warn_on_close
);
129 wpps (sesskey
, "TerminalType", cfg
.termtype
);
130 wpps (sesskey
, "TerminalSpeed", cfg
.termspeed
);
132 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
138 if (c
== '=' || c
== ',' || c
== '\\')
148 wpps (sesskey
, "Environment", buf
);
150 wpps (sesskey
, "UserName", cfg
.username
);
151 wppi (sesskey
, "NoPTY", cfg
.nopty
);
152 wpps (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
153 cfg
.cipher
== CIPHER_DES ?
"des" : "3des");
154 wppi (sesskey
, "AuthTIS", cfg
.try_tis_auth
);
155 wppi (sesskey
, "RFCEnviron", cfg
.rfc_environ
);
156 wppi (sesskey
, "BackspaceIsDelete", cfg
.bksp_is_delete
);
157 wppi (sesskey
, "RXVTHomeEnd", cfg
.rxvt_homeend
);
158 wppi (sesskey
, "LinuxFunctionKeys", cfg
.linux_funkeys
);
159 wppi (sesskey
, "ApplicationCursorKeys", cfg
.app_cursor
);
160 wppi (sesskey
, "ApplicationKeypad", cfg
.app_keypad
);
161 wppi (sesskey
, "NetHackKeypad", cfg
.nethack_keypad
);
162 wppi (sesskey
, "AltF4", cfg
.alt_f4
);
163 wppi (sesskey
, "AltSpace", cfg
.alt_space
);
164 wppi (sesskey
, "LdiscTerm", cfg
.ldisc_term
);
165 wppi (sesskey
, "BlinkCur", cfg
.blink_cur
);
166 wppi (sesskey
, "Beep", cfg
.beep
);
167 wppi (sesskey
, "ScrollbackLines", cfg
.savelines
);
168 wppi (sesskey
, "DECOriginMode", cfg
.dec_om
);
169 wppi (sesskey
, "AutoWrapMode", cfg
.wrap_mode
);
170 wppi (sesskey
, "LFImpliesCR", cfg
.lfhascr
);
171 wppi (sesskey
, "WinNameAlways", cfg
.win_name_always
);
172 wppi (sesskey
, "TermWidth", cfg
.width
);
173 wppi (sesskey
, "TermHeight", cfg
.height
);
174 wpps (sesskey
, "Font", cfg
.font
);
175 wppi (sesskey
, "FontIsBold", cfg
.fontisbold
);
176 wppi (sesskey
, "FontCharSet", cfg
.fontcharset
);
177 wppi (sesskey
, "FontHeight", cfg
.fontheight
);
178 wppi (sesskey
, "FontVTMode", cfg
.vtmode
);
179 wppi (sesskey
, "TryPalette", cfg
.try_palette
);
180 wppi (sesskey
, "BoldAsColour", cfg
.bold_colour
);
181 for (i
=0; i
<22; i
++) {
182 char buf
[20], buf2
[30];
183 sprintf(buf
, "Colour%d", i
);
184 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
185 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
186 wpps (sesskey
, buf
, buf2
);
188 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
189 for (i
=0; i
<256; i
+=32) {
190 char buf
[20], buf2
[256];
192 sprintf(buf
, "Wordness%d", i
);
194 for (j
=i
; j
<i
+32; j
++) {
195 sprintf(buf2
+strlen(buf2
), "%s%d",
196 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
198 wpps (sesskey
, buf
, buf2
);
200 wppi (sesskey
, "KoiWinXlat", cfg
.xlat_enablekoiwin
);
201 wppi (sesskey
, "88592Xlat", cfg
.xlat_88592w1250
);
202 wppi (sesskey
, "CapsLockCyr", cfg
.xlat_capslockcyr
);
204 RegCloseKey(sesskey
);
207 static void del_session (char *section
) {
211 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
)
214 p
= malloc(3*strlen(section
)+1);
215 mungestr(section
, p
);
216 RegDeleteKey(subkey1
, p
);
219 RegCloseKey(subkey1
);
222 static void load_settings (char *section
, int do_host
) {
224 HKEY subkey1
, sesskey
;
228 p
= malloc(3*strlen(section
)+1);
229 mungestr(section
, p
);
231 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
234 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
237 RegCloseKey(subkey1
);
242 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
243 gppi (sesskey
, "PortNumber", default_port
, &cfg
.port
);
245 gpps (sesskey
, "Protocol", "default", prot
, 10);
246 cfg
.protocol
= default_protocol
;
247 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
248 if (!strcmp(prot
, backends
[i
].name
)) {
249 cfg
.protocol
= backends
[i
].protocol
;
253 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
254 gppi (sesskey
, "WarnOnClose", 1, &cfg
.warn_on_close
);
255 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
256 sizeof(cfg
.termtype
));
257 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
258 sizeof(cfg
.termspeed
));
260 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
261 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
265 while (*p
&& *p
!= ',') {
278 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
279 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
282 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
283 if (!strcmp(cipher
, "blowfish"))
284 cfg
.cipher
= CIPHER_BLOWFISH
;
285 else if (!strcmp(cipher
, "des"))
286 cfg
.cipher
= CIPHER_DES
;
288 cfg
.cipher
= CIPHER_3DES
;
290 gppi (sesskey
, "AuthTIS", 0, &cfg
.try_tis_auth
);
291 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
292 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
293 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
294 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.linux_funkeys
);
295 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
296 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
297 gppi (sesskey
, "NetHackKeypad", 0, &cfg
.nethack_keypad
);
298 gppi (sesskey
, "AltF4", 1, &cfg
.alt_f4
);
299 gppi (sesskey
, "AltSpace", 0, &cfg
.alt_space
);
300 gppi (sesskey
, "LdiscTerm", 0, &cfg
.ldisc_term
);
301 gppi (sesskey
, "BlinkCur", 0, &cfg
.blink_cur
);
302 gppi (sesskey
, "Beep", 1, &cfg
.beep
);
303 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
304 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
305 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
306 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
307 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
308 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
309 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
310 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
311 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
312 gppi (sesskey
, "FontCharSet", ANSI_CHARSET
, &cfg
.fontcharset
);
313 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
314 gppi (sesskey
, "FontVTMode", VT_OEMANSI
, (int *)&cfg
.vtmode
);
315 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
316 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
317 for (i
=0; i
<22; i
++) {
318 static char *defaults
[] = {
319 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
320 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
321 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
322 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
323 "85,255,255", "187,187,187", "255,255,255"
325 char buf
[20], buf2
[30];
327 sprintf(buf
, "Colour%d", i
);
328 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
329 if(sscanf(buf2
, "%d,%d,%d", &c0
, &c1
, &c2
) == 3) {
330 cfg
.colours
[i
][0] = c0
;
331 cfg
.colours
[i
][1] = c1
;
332 cfg
.colours
[i
][2] = c2
;
335 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
336 for (i
=0; i
<256; i
+=32) {
337 static char *defaults
[] = {
338 "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",
339 "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",
340 "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",
341 "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",
342 "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",
343 "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",
344 "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",
345 "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"
347 char buf
[20], buf2
[256], *p
;
349 sprintf(buf
, "Wordness%d", i
);
350 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
352 for (j
=i
; j
<i
+32; j
++) {
354 while (*p
&& *p
!= ',') p
++;
355 if (*p
== ',') *p
++ = '\0';
356 cfg
.wordness
[j
] = atoi(q
);
359 gppi (sesskey
, "KoiWinXlat", 0, &cfg
.xlat_enablekoiwin
);
360 gppi (sesskey
, "88592Xlat", 0, &cfg
.xlat_88592w1250
);
361 gppi (sesskey
, "CapsLockCyr", 0, &cfg
.xlat_capslockcyr
);
363 RegCloseKey(sesskey
);
366 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
369 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
374 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
375 WPARAM wParam
, LPARAM lParam
) {
380 for (i
=0; i
<nevents
; i
++)
381 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
382 0, (LPARAM
)events
[i
]);
384 /* case WM_CTLCOLORDLG: */
385 /* return (int) GetStockObject (LTGRAY_BRUSH); */
387 switch (LOWORD(wParam
)) {
390 DestroyWindow (hwnd
);
396 DestroyWindow (hwnd
);
402 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
403 WPARAM wParam
, LPARAM lParam
) {
408 switch (LOWORD(wParam
)) {
411 DestroyWindow (hwnd
);
417 DestroyWindow (hwnd
);
423 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
424 WPARAM wParam
, LPARAM lParam
) {
427 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
429 /* case WM_CTLCOLORDLG: */
430 /* return (int) GetStockObject (LTGRAY_BRUSH); */
431 /* case WM_CTLCOLORSTATIC: */
432 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
433 /* return (int) GetStockObject (LTGRAY_BRUSH); */
435 switch (LOWORD(wParam
)) {
438 DestroyWindow (hwnd
);
441 EnableWindow(hwnd
, 0);
442 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
444 EnableWindow(hwnd
, 1);
450 DestroyWindow (hwnd
);
456 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
457 WPARAM wParam
, LPARAM lParam
) {
460 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
462 /* case WM_CTLCOLORDLG: */
463 /* return (int) GetStockObject (LTGRAY_BRUSH); */
464 /* case WM_CTLCOLORSTATIC: */
465 /* case WM_CTLCOLORBTN: */
466 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
467 /* return (int) GetStockObject (LTGRAY_BRUSH); */
469 DestroyWindow (hwnd
);
475 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
476 WPARAM wParam
, LPARAM lParam
) {
481 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
482 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
483 for (i
= 0; i
< nsessions
; i
++)
484 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
485 0, (LPARAM
) (sessions
[i
]));
486 CheckRadioButton (hwnd
, IDC0_PROTRAW
, IDC0_PROTSSH
,
487 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
488 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
);
489 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
490 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
494 * Button release should trigger WM_OK if there was a
495 * previous double click on the session list.
499 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
502 switch (LOWORD(wParam
)) {
503 case IDC0_PROTTELNET
:
506 if (HIWORD(wParam
) == BN_CLICKED
||
507 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
508 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
509 int j
= IsDlgButtonChecked (hwnd
, IDC0_PROTTELNET
);
510 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
511 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
512 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
513 cfg
.port
= i ?
22 : 23;
514 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
519 if (HIWORD(wParam
) == EN_CHANGE
)
520 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
524 if (HIWORD(wParam
) == EN_CHANGE
)
525 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
528 if (HIWORD(wParam
) == BN_CLICKED
||
529 HIWORD(wParam
) == BN_DOUBLECLICKED
)
530 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
533 if (HIWORD(wParam
) == BN_CLICKED
||
534 HIWORD(wParam
) == BN_DOUBLECLICKED
)
535 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEWARN
);
538 if (HIWORD(wParam
) == EN_CHANGE
)
539 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
543 if (HIWORD(wParam
) == BN_CLICKED
||
544 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
549 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
551 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
557 strcpy (str
, sessions
[n
]);
559 save_settings (str
, !!strcmp(str
, "Default Settings"));
560 get_sesslist (FALSE
);
562 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
564 for (i
= 0; i
< nsessions
; i
++)
565 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
566 0, (LPARAM
) (sessions
[i
]));
567 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
573 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
574 HIWORD(wParam
) != BN_CLICKED
&&
575 HIWORD(wParam
) != BN_DOUBLECLICKED
)
577 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
578 HIWORD(wParam
) != LBN_DBLCLK
)
581 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
587 load_settings (sessions
[n
],
588 !!strcmp(sessions
[n
], "Default Settings"));
589 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
590 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
591 CheckRadioButton (hwnd
, IDC0_PROTRAW
, IDC0_PROTSSH
,
592 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
593 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
));
594 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
595 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
596 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
599 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
601 * A double-click on a saved session should
602 * actually start the session, not just load it.
603 * Unless it's Default Settings or some other
604 * host-less set of saved settings.
613 if (HIWORD(wParam
) == BN_CLICKED
||
614 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
615 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
617 if (n
== LB_ERR
|| n
== 0) {
621 del_session(sessions
[n
]);
622 get_sesslist (FALSE
);
624 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
626 for (i
= 0; i
< nsessions
; i
++)
627 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
628 0, (LPARAM
) (sessions
[i
]));
629 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
634 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
637 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
638 WPARAM wParam
, LPARAM lParam
) {
641 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
642 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
643 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
644 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
645 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCLINUX
,
646 cfg
.linux_funkeys ? IDC1_FUNCLINUX
: IDC1_FUNCTILDE
);
647 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
648 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
649 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPNH
,
650 cfg
.nethack_keypad ? IDC1_KPNH
:
651 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
652 CheckDlgButton (hwnd
, IDC1_ALTF4
, cfg
.alt_f4
);
653 CheckDlgButton (hwnd
, IDC1_ALTSPACE
, cfg
.alt_space
);
654 CheckDlgButton (hwnd
, IDC1_LDISCTERM
, cfg
.ldisc_term
);
655 CheckDlgButton (hwnd
, IDC1_BLINKCUR
, cfg
.blink_cur
);
656 CheckDlgButton (hwnd
, IDC1_BEEP
, cfg
.beep
);
659 if (HIWORD(wParam
) == BN_CLICKED
||
660 HIWORD(wParam
) == BN_DOUBLECLICKED
)
661 switch (LOWORD(wParam
)) {
664 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
668 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
672 cfg
.linux_funkeys
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
676 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
677 cfg
.nethack_keypad
= FALSE
;
680 cfg
.app_keypad
= FALSE
;
681 cfg
.nethack_keypad
= TRUE
;
685 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
688 if (HIWORD(wParam
) == BN_CLICKED
||
689 HIWORD(wParam
) == BN_DOUBLECLICKED
)
690 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC1_ALTF4
);
693 if (HIWORD(wParam
) == BN_CLICKED
||
694 HIWORD(wParam
) == BN_DOUBLECLICKED
)
695 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC1_ALTSPACE
);
698 if (HIWORD(wParam
) == BN_CLICKED
||
699 HIWORD(wParam
) == BN_DOUBLECLICKED
)
700 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC1_LDISCTERM
);
703 if (HIWORD(wParam
) == BN_CLICKED
||
704 HIWORD(wParam
) == BN_DOUBLECLICKED
)
705 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC1_BLINKCUR
);
707 if (HIWORD(wParam
) == BN_CLICKED
||
708 HIWORD(wParam
) == BN_DOUBLECLICKED
)
709 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC1_BEEP
);
713 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
716 static void fmtfont (char *buf
) {
717 sprintf (buf
, "Font: %s, ", cfg
.font
);
719 strcat(buf
, "bold, ");
720 if (cfg
.fontheight
== 0)
721 strcat (buf
, "default height");
723 sprintf (buf
+strlen(buf
), "%d-%s",
724 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
725 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
728 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
729 WPARAM wParam
, LPARAM lParam
) {
732 char fontstatic
[256];
736 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
737 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
738 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
739 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
740 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
741 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
742 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
743 fmtfont (fontstatic
);
744 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
745 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
746 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
747 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
748 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
752 switch (LOWORD(wParam
)) {
754 if (HIWORD(wParam
) == BN_CLICKED
||
755 HIWORD(wParam
) == BN_DOUBLECLICKED
)
756 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
759 if (HIWORD(wParam
) == BN_CLICKED
||
760 HIWORD(wParam
) == BN_DOUBLECLICKED
)
761 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
764 if (HIWORD(wParam
) == BN_CLICKED
||
765 HIWORD(wParam
) == BN_DOUBLECLICKED
)
766 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
769 if (HIWORD(wParam
) == BN_CLICKED
||
770 HIWORD(wParam
) == BN_DOUBLECLICKED
)
771 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
774 if (HIWORD(wParam
) == EN_CHANGE
)
775 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
778 if (HIWORD(wParam
) == EN_CHANGE
)
779 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
782 if (HIWORD(wParam
) == EN_CHANGE
)
783 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
785 case IDC2_CHOOSEFONT
:
786 lf
.lfHeight
= cfg
.fontheight
;
787 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
788 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
789 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
790 lf
.lfCharSet
= cfg
.fontcharset
;
791 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
792 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
793 lf
.lfQuality
= DEFAULT_QUALITY
;
794 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
795 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
796 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
798 cf
.lStructSize
= sizeof(cf
);
801 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
802 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
804 if (ChooseFont (&cf
)) {
805 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
806 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
807 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
808 cfg
.fontcharset
= lf
.lfCharSet
;
809 cfg
.fontheight
= lf
.lfHeight
;
810 fmtfont (fontstatic
);
811 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
814 case IDC2_VTXWINDOWS
:
819 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
820 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
821 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
827 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
830 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
831 WPARAM wParam
, LPARAM lParam
) {
836 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
837 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
838 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
840 char *p
= cfg
.environmt
;
842 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
847 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
848 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
851 switch (LOWORD(wParam
)) {
853 if (HIWORD(wParam
) == EN_CHANGE
)
854 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
855 sizeof(cfg
.termtype
)-1);
858 if (HIWORD(wParam
) == EN_CHANGE
)
859 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
860 sizeof(cfg
.termspeed
)-1);
863 if (HIWORD(wParam
) == EN_CHANGE
)
864 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
865 sizeof(cfg
.username
)-1);
869 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
872 if (HIWORD(wParam
) == BN_CLICKED
||
873 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
874 char str
[sizeof(cfg
.environmt
)];
876 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
881 p
= str
+ strlen(str
);
883 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
893 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
895 p
[strlen(str
)+1] = '\0';
896 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
898 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
899 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
901 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
902 MB_OK
| MB_ICONERROR
);
907 if (HIWORD(wParam
) != BN_CLICKED
&&
908 HIWORD(wParam
) != BN_DOUBLECLICKED
)
910 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
916 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
943 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
946 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
947 WPARAM wParam
, LPARAM lParam
) {
950 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
951 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
952 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
953 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERDES
,
954 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
955 cfg
.cipher
== CIPHER_DES ? IDC3_CIPHERDES
:
958 CheckDlgButton (hwnd
, IDC3_AUTHTIS
, cfg
.try_tis_auth
);
961 switch (LOWORD(wParam
)) {
963 if (HIWORD(wParam
) == EN_CHANGE
)
964 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
965 sizeof(cfg
.termtype
)-1);
968 if (HIWORD(wParam
) == EN_CHANGE
)
969 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
970 sizeof(cfg
.username
)-1);
973 if (HIWORD(wParam
) == BN_CLICKED
||
974 HIWORD(wParam
) == BN_DOUBLECLICKED
)
975 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
977 case IDC3_CIPHER3DES
:
978 case IDC3_CIPHERBLOWF
:
980 if (HIWORD(wParam
) == BN_CLICKED
||
981 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
982 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
983 cfg
.cipher
= CIPHER_3DES
;
984 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
985 cfg
.cipher
= CIPHER_BLOWFISH
;
986 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERDES
))
987 cfg
.cipher
= CIPHER_DES
;
991 if (HIWORD(wParam
) == BN_CLICKED
||
992 HIWORD(wParam
) == BN_DOUBLECLICKED
)
993 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC3_AUTHTIS
);
998 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1001 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1002 WPARAM wParam
, LPARAM lParam
) {
1007 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
1008 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
1010 static int tabs
[4] = {25, 61, 96, 128};
1011 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
1014 for (i
=0; i
<256; i
++) {
1016 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1017 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1019 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
1024 switch (LOWORD(wParam
)) {
1025 case IDC4_MBWINDOWS
:
1027 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
1033 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
1038 for (i
=0; i
<256; i
++)
1039 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
1042 cfg
.wordness
[i
] = n
;
1043 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
1044 LB_DELETESTRING
, i
, 0);
1045 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1046 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1048 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
1058 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1061 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
1062 WPARAM wParam
, LPARAM lParam
) {
1063 static const char *const colours
[] = {
1064 "Default Foreground", "Default Bold Foreground",
1065 "Default Background", "Default Bold Background",
1066 "Cursor Text", "Cursor Colour",
1067 "ANSI Black", "ANSI Black Bold",
1068 "ANSI Red", "ANSI Red Bold",
1069 "ANSI Green", "ANSI Green Bold",
1070 "ANSI Yellow", "ANSI Yellow Bold",
1071 "ANSI Blue", "ANSI Blue Bold",
1072 "ANSI Magenta", "ANSI Magenta Bold",
1073 "ANSI Cyan", "ANSI Cyan Bold",
1074 "ANSI White", "ANSI White Bold"
1076 static const int permanent
[] = {
1077 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1078 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1079 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1083 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
1084 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1087 for (i
=0; i
<22; i
++)
1088 if (cfg
.bold_colour
|| permanent
[i
])
1089 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1090 (LPARAM
) colours
[i
]);
1092 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1093 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1094 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1095 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1098 switch (LOWORD(wParam
)) {
1099 case IDC5_BOLDCOLOUR
:
1100 if (HIWORD(wParam
) == BN_CLICKED
||
1101 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1103 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1104 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1105 if (cfg
.bold_colour
&& n
!=22) {
1106 for (i
=0; i
<22; i
++)
1108 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1110 (LPARAM
) colours
[i
]);
1111 } else if (!cfg
.bold_colour
&& n
!=12) {
1114 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1115 LB_DELETESTRING
, i
, 0);
1120 if (HIWORD(wParam
) == BN_CLICKED
||
1121 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1122 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1125 if (HIWORD(wParam
) == LBN_DBLCLK
||
1126 HIWORD(wParam
) == LBN_SELCHANGE
) {
1127 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1129 if (!cfg
.bold_colour
)
1130 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1131 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1132 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1133 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1137 if (HIWORD(wParam
) == BN_CLICKED
||
1138 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1139 static CHOOSECOLOR cc
;
1140 static DWORD custom
[16] = {0}; /* zero initialisers */
1141 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1143 if (!cfg
.bold_colour
)
1144 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1145 cc
.lStructSize
= sizeof(cc
);
1146 cc
.hwndOwner
= hwnd
;
1147 cc
.hInstance
= (HWND
)hinst
;
1148 cc
.lpCustColors
= custom
;
1149 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1151 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1152 if (ChooseColor(&cc
)) {
1154 (unsigned char) (cc
.rgbResult
& 0xFF);
1156 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1158 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1159 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1161 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1163 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1171 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1174 static int CALLBACK
LanguageProc (HWND hwnd
, UINT msg
,
1175 WPARAM wParam
, LPARAM lParam
) {
1178 CheckRadioButton (hwnd
, IDC6_NOXLAT
, IDC6_88592WIN1250
,
1179 cfg
.xlat_88592w1250 ? IDC6_88592WIN1250
:
1180 cfg
.xlat_enablekoiwin ? IDC6_KOI8WIN1251
:
1182 CheckDlgButton (hwnd
, IDC6_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1184 switch (LOWORD(wParam
)) {
1186 case IDC6_KOI8WIN1251
:
1187 case IDC6_88592WIN1250
:
1188 cfg
.xlat_enablekoiwin
=
1189 IsDlgButtonChecked (hwnd
, IDC6_KOI8WIN1251
);
1190 cfg
.xlat_88592w1250
=
1191 IsDlgButtonChecked (hwnd
, IDC6_88592WIN1250
);
1193 case IDC6_CAPSLOCKCYR
:
1194 if (HIWORD(wParam
) == BN_CLICKED
||
1195 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1196 cfg
.xlat_capslockcyr
=
1197 IsDlgButtonChecked (hwnd
, IDC6_CAPSLOCKCYR
);
1202 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1205 static DLGPROC panelproc
[NPANELS
] = {
1206 ConnectionProc
, KeyboardProc
, TerminalProc
,
1207 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, LanguageProc
1209 static char *panelids
[NPANELS
] = {
1210 MAKEINTRESOURCE(IDD_PANEL0
),
1211 MAKEINTRESOURCE(IDD_PANEL1
),
1212 MAKEINTRESOURCE(IDD_PANEL2
),
1213 MAKEINTRESOURCE(IDD_PANEL3
),
1214 MAKEINTRESOURCE(IDD_PANEL35
),
1215 MAKEINTRESOURCE(IDD_PANEL4
),
1216 MAKEINTRESOURCE(IDD_PANEL5
),
1217 MAKEINTRESOURCE(IDD_PANEL6
)
1220 static char *names
[NPANELS
] = {
1221 "Connection", "Keyboard", "Terminal", "Telnet",
1222 "SSH", "Selection", "Colours", "Language"
1225 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7};
1226 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6, 7};
1228 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1229 WPARAM wParam
, LPARAM lParam
,
1230 int npanels
, int *panelnums
, HWND
*page
) {
1235 { /* centre the window */
1238 hw
= GetDesktopWindow();
1239 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1240 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1241 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1242 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1245 { /* initialise the tab control */
1249 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1250 for (i
=0; i
<npanels
; i
++) {
1251 tab
.mask
= TCIF_TEXT
;
1252 tab
.pszText
= names
[panelnums
[i
]];
1253 TabCtrl_InsertItem (hw
, i
, &tab
);
1255 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1256 hwnd, panelproc[panelnums[0]]);*/
1257 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1258 hwnd
, panelproc
[panelnums
[0]]);
1259 SetWindowLong (*page
, GWL_EXSTYLE
,
1260 GetWindowLong (*page
, GWL_EXSTYLE
) |
1261 WS_EX_CONTROLPARENT
);
1266 if (LOWORD(wParam
) == IDC_TAB
&&
1267 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1268 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1270 DestroyWindow (*page
);
1271 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1272 hwnd, panelproc[panelnums[i]]);*/
1273 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1274 hwnd
, panelproc
[panelnums
[i
]]);
1275 SetWindowLong (*page
, GWL_EXSTYLE
,
1276 GetWindowLong (*page
, GWL_EXSTYLE
) |
1277 WS_EX_CONTROLPARENT
);
1278 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1282 /* case WM_CTLCOLORDLG: */
1283 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1285 switch (LOWORD(wParam
)) {
1288 EndDialog (hwnd
, 1);
1293 EndDialog (hwnd
, 0);
1298 EndDialog (hwnd
, 0);
1304 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1305 WPARAM wParam
, LPARAM lParam
) {
1310 static HWND page
= NULL
;
1312 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1315 * If the Connection panel is active and the Session List
1316 * box is selected, we treat a press of Open to have an
1317 * implicit press of Load preceding it.
1319 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1320 i
= TabCtrl_GetCurSel(hw
);
1321 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1322 page
&& implicit_load_ok
) {
1323 SendMessage (page
, WM_COMMAND
,
1324 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1328 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1329 EnableWindow(hwnd
, 0);
1330 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1331 GetParent(hwnd
), AboutProc
);
1332 EnableWindow(hwnd
, 1);
1334 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1335 MAIN_NPANELS
, mainp
, &page
);
1338 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1339 WPARAM wParam
, LPARAM lParam
) {
1341 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1342 RECONF_NPANELS
, reconfp
, &page
);
1345 void get_sesslist(int allocate
) {
1346 static char *buffer
;
1347 int buflen
, bufsize
, i
, ret
;
1348 char otherbuf
[2048];
1353 if (RegCreateKey(HKEY_CURRENT_USER
,
1354 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1357 buflen
= bufsize
= 0;
1361 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1362 if (ret
== ERROR_SUCCESS
) {
1363 bufsize
= buflen
+ 2048;
1364 buffer
= srealloc(buffer
, bufsize
);
1365 unmungestr(otherbuf
, buffer
+buflen
);
1366 buflen
+= strlen(buffer
+buflen
)+1;
1368 } while (ret
== ERROR_SUCCESS
);
1369 buffer
= srealloc(buffer
, buflen
+1);
1370 buffer
[buflen
] = '\0';
1373 nsessions
= 1; /* "Default Settings" counts as one */
1375 if (strcmp(p
, "Default Settings"))
1381 sessions
= smalloc(nsessions
* sizeof(char *));
1382 sessions
[0] = "Default Settings";
1386 if (strcmp(p
, "Default Settings"))
1397 int do_config (void) {
1401 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1402 get_sesslist(FALSE
);
1407 int do_reconfig (HWND hwnd
) {
1411 backup_cfg
= cfg
; /* structure copy */
1412 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1414 cfg
= backup_cfg
; /* structure copy */
1418 void do_defaults (char *session
) {
1420 load_settings (session
, TRUE
);
1422 load_settings ("Default Settings", FALSE
);
1425 void logevent (char *string
) {
1426 if (nevents
>= negsize
) {
1428 events
= srealloc (events
, negsize
* sizeof(*events
));
1430 events
[nevents
] = smalloc(1+strlen(string
));
1431 strcpy (events
[nevents
], string
);
1434 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1438 void showeventlog (HWND hwnd
) {
1440 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1442 ShowWindow (logbox
, SW_SHOWNORMAL
);
1446 void showabout (HWND hwnd
) {
1448 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1450 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1454 void verify_ssh_host_key(char *host
, char *keystr
) {
1455 char *otherstr
, *mungedhost
;
1459 len
= 1 + strlen(keystr
);
1462 * Now read a saved key in from the registry and see what it
1465 otherstr
= malloc(len
);
1466 mungedhost
= malloc(3*strlen(host
)+1);
1467 if (!otherstr
|| !mungedhost
)
1468 fatalbox("Out of memory");
1470 mungestr(host
, mungedhost
);
1472 if (RegCreateKey(HKEY_CURRENT_USER
, PUTTY_REG_POS
"\\SshHostKeys",
1473 &rkey
) != ERROR_SUCCESS
) {
1474 if (MessageBox(NULL
, "PuTTY was unable to open the host key cache\n"
1475 "in the registry. There is thus no way to tell\n"
1476 "if the remote host is what you think it is.\n"
1477 "Connect anyway?", "PuTTY Problem",
1478 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1481 DWORD readlen
= len
;
1485 ret
= RegQueryValueEx(rkey
, mungedhost
, NULL
,
1486 &type
, otherstr
, &readlen
);
1488 if (ret
== ERROR_MORE_DATA
||
1489 (ret
== ERROR_SUCCESS
&& type
== REG_SZ
&&
1490 strcmp(otherstr
, keystr
))) {
1491 if (MessageBox(NULL
,
1492 "This host's host key is different from the\n"
1493 "one cached in the registry! Someone may be\n"
1494 "impersonating this host for malicious reasons;\n"
1495 "alternatively, the host key may have changed\n"
1496 "due to sloppy system administration.\n"
1497 "Replace key in registry and connect?",
1498 "PuTTY: Security Warning",
1499 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1501 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,
1503 } else if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) {
1504 if (MessageBox(NULL
,
1505 "This host's host key is not cached in the\n"
1506 "registry. Do you want to add it to the cache\n"
1507 "and carry on connecting?",
1509 MB_ICONWARNING
| MB_YESNO
) == IDNO
)
1511 RegSetValueEx(rkey
, mungedhost
, 0, REG_SZ
, keystr
,