20 #define MAIN_NPANELS 8
21 #define RECONF_NPANELS 5
23 static const char *const puttystr
= PUTTY_REG_POS
"\\Sessions";
25 static char **events
= NULL
;
26 static int nevents
= 0, negsize
= 0;
28 static HWND logbox
= NULL
, abtbox
= NULL
;
30 static char hex
[16] = "0123456789ABCDEF";
32 static void mungestr(char *in
, char *out
) {
36 if (*in
== ' ' || *in
== '\\' || *in
== '*' || *in
== '?' ||
37 *in
== '%' || *in
< ' ' || *in
> '~' || (*in
== '.' && !candot
)) {
39 *out
++ = hex
[((unsigned char)*in
) >> 4];
40 *out
++ = hex
[((unsigned char)*in
) & 15];
50 static void unmungestr(char *in
, char *out
) {
52 if (*in
== '%' && in
[1] && in
[2]) {
55 i
= in
[1] - '0'; i
-= (i
> 9 ?
7 : 0);
56 j
= in
[2] - '0'; j
-= (j
> 9 ?
7 : 0);
67 static void wpps(HKEY key
, LPCTSTR name
, LPCTSTR value
) {
68 RegSetValueEx(key
, name
, 0, REG_SZ
, value
, 1+strlen(value
));
71 static void wppi(HKEY key
, LPCTSTR name
, int value
) {
72 RegSetValueEx(key
, name
, 0, REG_DWORD
,
73 (CONST BYTE
*)&value
, sizeof(value
));
76 static void gpps(HKEY key
, LPCTSTR name
, LPCTSTR def
,
77 LPTSTR val
, int len
) {
82 RegQueryValueEx(key
, name
, 0, &type
, val
, &size
) != ERROR_SUCCESS
||
84 strncpy(val
, def
, len
);
89 static void gppi(HKEY key
, LPCTSTR name
, int def
, int *i
) {
90 DWORD type
, val
, size
;
94 RegQueryValueEx(key
, name
, 0, &type
,
95 (BYTE
*)&val
, &size
) != ERROR_SUCCESS
||
96 size
!= sizeof(val
) || type
!= REG_DWORD
)
102 static HINSTANCE hinst
;
104 static int readytogo
;
106 static void save_settings (char *section
, int do_host
) {
108 HKEY subkey1
, sesskey
;
111 p
= malloc(3*strlen(section
)+1);
112 mungestr(section
, p
);
114 if (RegCreateKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
)!=ERROR_SUCCESS
||
115 RegCreateKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
120 RegCloseKey(subkey1
);
122 wppi (sesskey
, "Present", 1);
124 wpps (sesskey
, "HostName", cfg
.host
);
125 wppi (sesskey
, "PortNumber", cfg
.port
);
127 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
128 if (backends
[i
].protocol
== cfg
.protocol
) {
129 p
= backends
[i
].name
;
132 wpps (sesskey
, "Protocol", p
);
134 wppi (sesskey
, "CloseOnExit", !!cfg
.close_on_exit
);
135 wppi (sesskey
, "WarnOnClose", !!cfg
.warn_on_close
);
136 wpps (sesskey
, "TerminalType", cfg
.termtype
);
137 wpps (sesskey
, "TerminalSpeed", cfg
.termspeed
);
139 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
145 if (c
== '=' || c
== ',' || c
== '\\')
155 wpps (sesskey
, "Environment", buf
);
157 wpps (sesskey
, "UserName", cfg
.username
);
158 wppi (sesskey
, "NoPTY", cfg
.nopty
);
159 wppi (sesskey
, "AgentFwd", cfg
.agentfwd
);
160 wpps (sesskey
, "RemoteCmd", cfg
.remote_cmd
);
161 wpps (sesskey
, "Cipher", cfg
.cipher
== CIPHER_BLOWFISH ?
"blowfish" :
162 cfg
.cipher
== CIPHER_DES ?
"des" : "3des");
163 wppi (sesskey
, "AuthTIS", cfg
.try_tis_auth
);
164 wppi (sesskey
, "SshProt", cfg
.sshprot
);
165 wpps (sesskey
, "PublicKeyFile", cfg
.keyfile
);
166 wppi (sesskey
, "RFCEnviron", cfg
.rfc_environ
);
167 wppi (sesskey
, "BackspaceIsDelete", cfg
.bksp_is_delete
);
168 wppi (sesskey
, "RXVTHomeEnd", cfg
.rxvt_homeend
);
169 wppi (sesskey
, "LinuxFunctionKeys", cfg
.funky_type
);
170 wppi (sesskey
, "ApplicationCursorKeys", cfg
.app_cursor
);
171 wppi (sesskey
, "ApplicationKeypad", cfg
.app_keypad
);
172 wppi (sesskey
, "NetHackKeypad", cfg
.nethack_keypad
);
173 wppi (sesskey
, "AltF4", cfg
.alt_f4
);
174 wppi (sesskey
, "AltSpace", cfg
.alt_space
);
175 wppi (sesskey
, "LdiscTerm", cfg
.ldisc_term
);
176 wppi (sesskey
, "BlinkCur", cfg
.blink_cur
);
177 wppi (sesskey
, "Beep", cfg
.beep
);
178 wppi (sesskey
, "ScrollbackLines", cfg
.savelines
);
179 wppi (sesskey
, "DECOriginMode", cfg
.dec_om
);
180 wppi (sesskey
, "AutoWrapMode", cfg
.wrap_mode
);
181 wppi (sesskey
, "LFImpliesCR", cfg
.lfhascr
);
182 wppi (sesskey
, "WinNameAlways", cfg
.win_name_always
);
183 wppi (sesskey
, "TermWidth", cfg
.width
);
184 wppi (sesskey
, "TermHeight", cfg
.height
);
185 wpps (sesskey
, "Font", cfg
.font
);
186 wppi (sesskey
, "FontIsBold", cfg
.fontisbold
);
187 wppi (sesskey
, "FontCharSet", cfg
.fontcharset
);
188 wppi (sesskey
, "FontHeight", cfg
.fontheight
);
189 wppi (sesskey
, "FontVTMode", cfg
.vtmode
);
190 wppi (sesskey
, "TryPalette", cfg
.try_palette
);
191 wppi (sesskey
, "BoldAsColour", cfg
.bold_colour
);
192 for (i
=0; i
<22; i
++) {
193 char buf
[20], buf2
[30];
194 sprintf(buf
, "Colour%d", i
);
195 sprintf(buf2
, "%d,%d,%d", cfg
.colours
[i
][0],
196 cfg
.colours
[i
][1], cfg
.colours
[i
][2]);
197 wpps (sesskey
, buf
, buf2
);
199 wppi (sesskey
, "MouseIsXterm", cfg
.mouse_is_xterm
);
200 for (i
=0; i
<256; i
+=32) {
201 char buf
[20], buf2
[256];
203 sprintf(buf
, "Wordness%d", i
);
205 for (j
=i
; j
<i
+32; j
++) {
206 sprintf(buf2
+strlen(buf2
), "%s%d",
207 (*buf2 ?
"," : ""), cfg
.wordness
[j
]);
209 wpps (sesskey
, buf
, buf2
);
211 wppi (sesskey
, "KoiWinXlat", cfg
.xlat_enablekoiwin
);
212 wppi (sesskey
, "88592Xlat", cfg
.xlat_88592w1250
);
213 wppi (sesskey
, "CapsLockCyr", cfg
.xlat_capslockcyr
);
214 wppi (sesskey
, "ScrollBar", cfg
.scrollbar
);
215 wppi (sesskey
, "ScrollOnKey", cfg
.scroll_on_key
);
216 wppi (sesskey
, "LockSize", cfg
.locksize
);
217 wppi (sesskey
, "BCE", cfg
.bce
);
218 wppi (sesskey
, "BlinkText", cfg
.blinktext
);
220 RegCloseKey(sesskey
);
223 static void del_session (char *section
) {
227 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
)
230 p
= malloc(3*strlen(section
)+1);
231 mungestr(section
, p
);
232 RegDeleteKey(subkey1
, p
);
235 RegCloseKey(subkey1
);
238 static void load_settings (char *section
, int do_host
) {
240 HKEY subkey1
, sesskey
;
244 p
= malloc(3*strlen(section
)+1);
245 mungestr(section
, p
);
247 if (RegOpenKey(HKEY_CURRENT_USER
, puttystr
, &subkey1
) != ERROR_SUCCESS
) {
250 if (RegOpenKey(subkey1
, p
, &sesskey
) != ERROR_SUCCESS
) {
253 RegCloseKey(subkey1
);
258 gpps (sesskey
, "HostName", "", cfg
.host
, sizeof(cfg
.host
));
259 gppi (sesskey
, "PortNumber", default_port
, &cfg
.port
);
261 gpps (sesskey
, "Protocol", "default", prot
, 10);
262 cfg
.protocol
= default_protocol
;
263 for (i
= 0; backends
[i
].name
!= NULL
; i
++)
264 if (!strcmp(prot
, backends
[i
].name
)) {
265 cfg
.protocol
= backends
[i
].protocol
;
269 gppi (sesskey
, "CloseOnExit", 1, &cfg
.close_on_exit
);
270 gppi (sesskey
, "WarnOnClose", 1, &cfg
.warn_on_close
);
271 gpps (sesskey
, "TerminalType", "xterm", cfg
.termtype
,
272 sizeof(cfg
.termtype
));
273 gpps (sesskey
, "TerminalSpeed", "38400,38400", cfg
.termspeed
,
274 sizeof(cfg
.termspeed
));
276 char buf
[2*sizeof(cfg
.environmt
)], *p
, *q
;
277 gpps (sesskey
, "Environment", "", buf
, sizeof(buf
));
281 while (*p
&& *p
!= ',') {
294 gpps (sesskey
, "UserName", "", cfg
.username
, sizeof(cfg
.username
));
295 gppi (sesskey
, "NoPTY", 0, &cfg
.nopty
);
296 gppi (sesskey
, "AgentFwd", 0, &cfg
.agentfwd
);
297 gpps (sesskey
, "RemoteCmd", "", cfg
.remote_cmd
, sizeof(cfg
.remote_cmd
));
300 gpps (sesskey
, "Cipher", "3des", cipher
, 10);
301 if (!strcmp(cipher
, "blowfish"))
302 cfg
.cipher
= CIPHER_BLOWFISH
;
303 else if (!strcmp(cipher
, "des"))
304 cfg
.cipher
= CIPHER_DES
;
306 cfg
.cipher
= CIPHER_3DES
;
308 gppi (sesskey
, "SshProt", 1, &cfg
.sshprot
);
309 gppi (sesskey
, "AuthTIS", 0, &cfg
.try_tis_auth
);
310 gpps (sesskey
, "PublicKeyFile", "", cfg
.keyfile
, sizeof(cfg
.keyfile
));
311 gppi (sesskey
, "RFCEnviron", 0, &cfg
.rfc_environ
);
312 gppi (sesskey
, "BackspaceIsDelete", 1, &cfg
.bksp_is_delete
);
313 gppi (sesskey
, "RXVTHomeEnd", 0, &cfg
.rxvt_homeend
);
314 gppi (sesskey
, "LinuxFunctionKeys", 0, &cfg
.funky_type
);
315 gppi (sesskey
, "ApplicationCursorKeys", 0, &cfg
.app_cursor
);
316 gppi (sesskey
, "ApplicationKeypad", 0, &cfg
.app_keypad
);
317 gppi (sesskey
, "NetHackKeypad", 0, &cfg
.nethack_keypad
);
318 gppi (sesskey
, "AltF4", 1, &cfg
.alt_f4
);
319 gppi (sesskey
, "AltSpace", 0, &cfg
.alt_space
);
320 gppi (sesskey
, "LdiscTerm", 0, &cfg
.ldisc_term
);
321 gppi (sesskey
, "BlinkCur", 0, &cfg
.blink_cur
);
322 gppi (sesskey
, "Beep", 1, &cfg
.beep
);
323 gppi (sesskey
, "ScrollbackLines", 200, &cfg
.savelines
);
324 gppi (sesskey
, "DECOriginMode", 0, &cfg
.dec_om
);
325 gppi (sesskey
, "AutoWrapMode", 1, &cfg
.wrap_mode
);
326 gppi (sesskey
, "LFImpliesCR", 0, &cfg
.lfhascr
);
327 gppi (sesskey
, "WinNameAlways", 0, &cfg
.win_name_always
);
328 gppi (sesskey
, "TermWidth", 80, &cfg
.width
);
329 gppi (sesskey
, "TermHeight", 24, &cfg
.height
);
330 gpps (sesskey
, "Font", "Courier", cfg
.font
, sizeof(cfg
.font
));
331 gppi (sesskey
, "FontIsBold", 0, &cfg
.fontisbold
);
332 gppi (sesskey
, "FontCharSet", ANSI_CHARSET
, &cfg
.fontcharset
);
333 gppi (sesskey
, "FontHeight", 10, &cfg
.fontheight
);
334 gppi (sesskey
, "FontVTMode", VT_OEMANSI
, (int *)&cfg
.vtmode
);
335 gppi (sesskey
, "TryPalette", 0, &cfg
.try_palette
);
336 gppi (sesskey
, "BoldAsColour", 1, &cfg
.bold_colour
);
337 for (i
=0; i
<22; i
++) {
338 static char *defaults
[] = {
339 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
340 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
341 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
342 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
343 "85,255,255", "187,187,187", "255,255,255"
345 char buf
[20], buf2
[30];
347 sprintf(buf
, "Colour%d", i
);
348 gpps (sesskey
, buf
, defaults
[i
], buf2
, sizeof(buf2
));
349 if(sscanf(buf2
, "%d,%d,%d", &c0
, &c1
, &c2
) == 3) {
350 cfg
.colours
[i
][0] = c0
;
351 cfg
.colours
[i
][1] = c1
;
352 cfg
.colours
[i
][2] = c2
;
355 gppi (sesskey
, "MouseIsXterm", 0, &cfg
.mouse_is_xterm
);
356 for (i
=0; i
<256; i
+=32) {
357 static char *defaults
[] = {
358 "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",
359 "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",
360 "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",
361 "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",
362 "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",
363 "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",
364 "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",
365 "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"
367 char buf
[20], buf2
[256], *p
;
369 sprintf(buf
, "Wordness%d", i
);
370 gpps (sesskey
, buf
, defaults
[i
/32], buf2
, sizeof(buf2
));
372 for (j
=i
; j
<i
+32; j
++) {
374 while (*p
&& *p
!= ',') p
++;
375 if (*p
== ',') *p
++ = '\0';
376 cfg
.wordness
[j
] = atoi(q
);
379 gppi (sesskey
, "KoiWinXlat", 0, &cfg
.xlat_enablekoiwin
);
380 gppi (sesskey
, "88592Xlat", 0, &cfg
.xlat_88592w1250
);
381 gppi (sesskey
, "CapsLockCyr", 0, &cfg
.xlat_capslockcyr
);
382 gppi (sesskey
, "ScrollBar", 1, &cfg
.scrollbar
);
383 gppi (sesskey
, "ScrollOnKey", 0, &cfg
.scroll_on_key
);
384 gppi (sesskey
, "LockSize", 0, &cfg
.locksize
);
385 gppi (sesskey
, "BCE", 0, &cfg
.bce
);
386 gppi (sesskey
, "BlinkText", 0, &cfg
.blinktext
);
388 RegCloseKey(sesskey
);
391 static void force_normal(HWND hwnd
)
393 static int recurse
= 0;
400 wp
.length
= sizeof(wp
);
401 if (GetWindowPlacement(hwnd
, &wp
))
403 wp
.showCmd
= SW_SHOWNORMAL
;
404 SetWindowPlacement(hwnd
, &wp
);
409 static void MyGetDlgItemInt (HWND hwnd
, int id
, int *result
) {
412 n
= GetDlgItemInt (hwnd
, id
, &ok
, FALSE
);
417 static int CALLBACK
LogProc (HWND hwnd
, UINT msg
,
418 WPARAM wParam
, LPARAM lParam
) {
423 for (i
=0; i
<nevents
; i
++)
424 SendDlgItemMessage (hwnd
, IDN_LIST
, LB_ADDSTRING
,
425 0, (LPARAM
)events
[i
]);
427 /* case WM_CTLCOLORDLG: */
428 /* return (int) GetStockObject (LTGRAY_BRUSH); */
430 switch (LOWORD(wParam
)) {
433 DestroyWindow (hwnd
);
436 if (HIWORD(wParam
) == BN_CLICKED
||
437 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
440 selcount
= SendDlgItemMessage(hwnd
, IDN_LIST
,
441 LB_GETSELCOUNT
, 0, 0);
442 selitems
= malloc(selcount
* sizeof(int));
444 int count
= SendDlgItemMessage(hwnd
, IDN_LIST
,
446 selcount
, (LPARAM
)selitems
);
450 static unsigned char sel_nl
[] = SEL_NL
;
453 for (i
= 0; i
< count
; i
++)
454 size
+= strlen(events
[selitems
[i
]]) + sizeof(sel_nl
);
456 clipdata
= malloc(size
);
459 for (i
= 0; i
< count
; i
++) {
460 char *q
= events
[selitems
[i
]];
461 int qlen
= strlen(q
);
464 memcpy(p
, sel_nl
, sizeof(sel_nl
));
467 write_clip(clipdata
, size
);
479 DestroyWindow (hwnd
);
485 static int CALLBACK
LicenceProc (HWND hwnd
, UINT msg
,
486 WPARAM wParam
, LPARAM lParam
) {
491 switch (LOWORD(wParam
)) {
494 DestroyWindow (hwnd
);
500 DestroyWindow (hwnd
);
506 static int CALLBACK
AboutProc (HWND hwnd
, UINT msg
,
507 WPARAM wParam
, LPARAM lParam
) {
510 SetDlgItemText (hwnd
, IDA_VERSION
, ver
);
512 /* case WM_CTLCOLORDLG: */
513 /* return (int) GetStockObject (LTGRAY_BRUSH); */
514 /* case WM_CTLCOLORSTATIC: */
515 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
516 /* return (int) GetStockObject (LTGRAY_BRUSH); */
518 switch (LOWORD(wParam
)) {
521 DestroyWindow (hwnd
);
524 EnableWindow(hwnd
, 0);
525 DialogBox (hinst
, MAKEINTRESOURCE(IDD_LICENCEBOX
),
527 EnableWindow(hwnd
, 1);
528 SetActiveWindow(hwnd
);
534 DestroyWindow (hwnd
);
540 static int GeneralPanelProc (HWND hwnd
, UINT msg
,
541 WPARAM wParam
, LPARAM lParam
) {
544 SetWindowPos (hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
546 /* case WM_CTLCOLORDLG: */
547 /* return (int) GetStockObject (LTGRAY_BRUSH); */
548 /* case WM_CTLCOLORSTATIC: */
549 /* case WM_CTLCOLORBTN: */
550 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
551 /* return (int) GetStockObject (LTGRAY_BRUSH); */
553 DestroyWindow (hwnd
);
559 static char savedsession
[2048];
561 static int CALLBACK
ConnectionProc (HWND hwnd
, UINT msg
,
562 WPARAM wParam
, LPARAM lParam
) {
567 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
568 SetDlgItemText (hwnd
, IDC0_SESSEDIT
, savedsession
);
569 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
570 for (i
= 0; i
< nsessions
; i
++)
571 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
572 0, (LPARAM
) (sessions
[i
]));
573 CheckRadioButton (hwnd
, IDC0_PROTRAW
, IDC0_PROTSSH
,
574 cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
575 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
);
576 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
577 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
581 * Button release should trigger WM_OK if there was a
582 * previous double click on the session list.
586 SendMessage (GetParent(hwnd
), WM_COMMAND
, IDOK
, 0);
589 switch (LOWORD(wParam
)) {
590 case IDC0_PROTTELNET
:
593 if (HIWORD(wParam
) == BN_CLICKED
||
594 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
595 int i
= IsDlgButtonChecked (hwnd
, IDC0_PROTSSH
);
596 int j
= IsDlgButtonChecked (hwnd
, IDC0_PROTTELNET
);
597 cfg
.protocol
= i ? PROT_SSH
: j ? PROT_TELNET
: PROT_RAW
;
598 if ((cfg
.protocol
== PROT_SSH
&& cfg
.port
== 23) ||
599 (cfg
.protocol
== PROT_TELNET
&& cfg
.port
== 22)) {
600 cfg
.port
= i ?
22 : 23;
601 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
606 if (HIWORD(wParam
) == EN_CHANGE
)
607 GetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
,
611 if (HIWORD(wParam
) == EN_CHANGE
)
612 MyGetDlgItemInt (hwnd
, IDC0_PORT
, &cfg
.port
);
615 if (HIWORD(wParam
) == BN_CLICKED
||
616 HIWORD(wParam
) == BN_DOUBLECLICKED
)
617 cfg
.close_on_exit
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEEXIT
);
620 if (HIWORD(wParam
) == BN_CLICKED
||
621 HIWORD(wParam
) == BN_DOUBLECLICKED
)
622 cfg
.warn_on_close
= IsDlgButtonChecked (hwnd
, IDC0_CLOSEWARN
);
625 if (HIWORD(wParam
) == EN_CHANGE
) {
626 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
628 GetDlgItemText (hwnd
, IDC0_SESSEDIT
,
629 savedsession
, sizeof(savedsession
)-1);
630 savedsession
[sizeof(savedsession
)-1] = '\0';
634 if (HIWORD(wParam
) == BN_CLICKED
||
635 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
640 GetDlgItemText (hwnd
, IDC0_SESSEDIT
, str
, sizeof(str
)-1);
642 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
648 strcpy (str
, sessions
[n
]);
650 save_settings (str
, !!strcmp(str
, "Default Settings"));
651 get_sesslist (FALSE
);
653 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
655 for (i
= 0; i
< nsessions
; i
++)
656 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
657 0, (LPARAM
) (sessions
[i
]));
658 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
664 if (LOWORD(wParam
) == IDC0_SESSLOAD
&&
665 HIWORD(wParam
) != BN_CLICKED
&&
666 HIWORD(wParam
) != BN_DOUBLECLICKED
)
668 if (LOWORD(wParam
) == IDC0_SESSLIST
&&
669 HIWORD(wParam
) != LBN_DBLCLK
)
672 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
678 load_settings (sessions
[n
],
679 !!strcmp(sessions
[n
], "Default Settings"));
680 SetDlgItemText (hwnd
, IDC0_HOST
, cfg
.host
);
681 SetDlgItemInt (hwnd
, IDC0_PORT
, cfg
.port
, FALSE
);
682 CheckRadioButton (hwnd
, IDC0_PROTRAW
, IDC0_PROTSSH
,
683 (cfg
.protocol
==PROT_SSH ? IDC0_PROTSSH
:
684 cfg
.protocol
==PROT_TELNET ? IDC0_PROTTELNET
: IDC0_PROTRAW
));
685 CheckDlgButton (hwnd
, IDC0_CLOSEEXIT
, cfg
.close_on_exit
);
686 CheckDlgButton (hwnd
, IDC0_CLOSEWARN
, cfg
.warn_on_close
);
687 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
690 if (LOWORD(wParam
) == IDC0_SESSLIST
) {
692 * A double-click on a saved session should
693 * actually start the session, not just load it.
694 * Unless it's Default Settings or some other
695 * host-less set of saved settings.
704 if (HIWORD(wParam
) == BN_CLICKED
||
705 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
706 int n
= SendDlgItemMessage (hwnd
, IDC0_SESSLIST
,
708 if (n
== LB_ERR
|| n
== 0) {
712 del_session(sessions
[n
]);
713 get_sesslist (FALSE
);
715 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_RESETCONTENT
,
717 for (i
= 0; i
< nsessions
; i
++)
718 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_ADDSTRING
,
719 0, (LPARAM
) (sessions
[i
]));
720 SendDlgItemMessage (hwnd
, IDC0_SESSLIST
, LB_SETCURSEL
,
725 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
728 static int CALLBACK
KeyboardProc (HWND hwnd
, UINT msg
,
729 WPARAM wParam
, LPARAM lParam
) {
732 CheckRadioButton (hwnd
, IDC1_DEL008
, IDC1_DEL127
,
733 cfg
.bksp_is_delete ? IDC1_DEL127
: IDC1_DEL008
);
734 CheckRadioButton (hwnd
, IDC1_HOMETILDE
, IDC1_HOMERXVT
,
735 cfg
.rxvt_homeend ? IDC1_HOMERXVT
: IDC1_HOMETILDE
);
736 CheckRadioButton (hwnd
, IDC1_FUNCTILDE
, IDC1_FUNCXTERM
,
738 (cfg
.funky_type
==2 ? IDC1_FUNCXTERM
741 CheckRadioButton (hwnd
, IDC1_CURNORMAL
, IDC1_CURAPPLIC
,
742 cfg
.app_cursor ? IDC1_CURAPPLIC
: IDC1_CURNORMAL
);
743 CheckRadioButton (hwnd
, IDC1_KPNORMAL
, IDC1_KPNH
,
744 cfg
.nethack_keypad ? IDC1_KPNH
:
745 cfg
.app_keypad ? IDC1_KPAPPLIC
: IDC1_KPNORMAL
);
746 CheckDlgButton (hwnd
, IDC1_ALTF4
, cfg
.alt_f4
);
747 CheckDlgButton (hwnd
, IDC1_ALTSPACE
, cfg
.alt_space
);
748 CheckDlgButton (hwnd
, IDC1_LDISCTERM
, cfg
.ldisc_term
);
749 CheckDlgButton (hwnd
, IDC1_SCROLLKEY
, cfg
.scroll_on_key
);
752 if (HIWORD(wParam
) == BN_CLICKED
||
753 HIWORD(wParam
) == BN_DOUBLECLICKED
)
754 switch (LOWORD(wParam
)) {
757 cfg
.bksp_is_delete
= IsDlgButtonChecked (hwnd
, IDC1_DEL127
);
761 cfg
.rxvt_homeend
= IsDlgButtonChecked (hwnd
, IDC1_HOMERXVT
);
768 cfg
.funky_type
= IsDlgButtonChecked (hwnd
, IDC1_FUNCLINUX
);
772 cfg
.app_keypad
= IsDlgButtonChecked (hwnd
, IDC1_KPAPPLIC
);
773 cfg
.nethack_keypad
= FALSE
;
776 cfg
.app_keypad
= FALSE
;
777 cfg
.nethack_keypad
= TRUE
;
781 cfg
.app_cursor
= IsDlgButtonChecked (hwnd
, IDC1_CURAPPLIC
);
784 if (HIWORD(wParam
) == BN_CLICKED
||
785 HIWORD(wParam
) == BN_DOUBLECLICKED
)
786 cfg
.alt_f4
= IsDlgButtonChecked (hwnd
, IDC1_ALTF4
);
789 if (HIWORD(wParam
) == BN_CLICKED
||
790 HIWORD(wParam
) == BN_DOUBLECLICKED
)
791 cfg
.alt_space
= IsDlgButtonChecked (hwnd
, IDC1_ALTSPACE
);
794 if (HIWORD(wParam
) == BN_CLICKED
||
795 HIWORD(wParam
) == BN_DOUBLECLICKED
)
796 cfg
.ldisc_term
= IsDlgButtonChecked (hwnd
, IDC1_LDISCTERM
);
799 if (HIWORD(wParam
) == BN_CLICKED
||
800 HIWORD(wParam
) == BN_DOUBLECLICKED
)
801 cfg
.scroll_on_key
= IsDlgButtonChecked (hwnd
, IDC1_SCROLLKEY
);
805 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
808 static void fmtfont (char *buf
) {
809 sprintf (buf
, "Font: %s, ", cfg
.font
);
811 strcat(buf
, "bold, ");
812 if (cfg
.fontheight
== 0)
813 strcat (buf
, "default height");
815 sprintf (buf
+strlen(buf
), "%d-%s",
816 (cfg
.fontheight
< 0 ?
-cfg
.fontheight
: cfg
.fontheight
),
817 (cfg
.fontheight
< 0 ?
"pixel" : "point"));
820 static int CALLBACK
TerminalProc (HWND hwnd
, UINT msg
,
821 WPARAM wParam
, LPARAM lParam
) {
824 char fontstatic
[256];
828 CheckDlgButton (hwnd
, IDC2_WRAPMODE
, cfg
.wrap_mode
);
829 CheckDlgButton (hwnd
, IDC2_WINNAME
, cfg
.win_name_always
);
830 CheckDlgButton (hwnd
, IDC2_DECOM
, cfg
.dec_om
);
831 CheckDlgButton (hwnd
, IDC2_LFHASCR
, cfg
.lfhascr
);
832 SetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, cfg
.height
, FALSE
);
833 SetDlgItemInt (hwnd
, IDC2_COLSEDIT
, cfg
.width
, FALSE
);
834 SetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, cfg
.savelines
, FALSE
);
835 fmtfont (fontstatic
);
836 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
837 CheckDlgButton (hwnd
, IDC1_BLINKCUR
, cfg
.blink_cur
);
838 CheckDlgButton (hwnd
, IDC1_BEEP
, cfg
.beep
);
839 CheckDlgButton (hwnd
, IDC2_SCROLLBAR
, cfg
.scrollbar
);
840 CheckDlgButton (hwnd
, IDC2_LOCKSIZE
, cfg
.locksize
);
841 CheckDlgButton (hwnd
, IDC2_BCE
, cfg
.bce
);
842 CheckDlgButton (hwnd
, IDC2_BLINKTEXT
, cfg
.blinktext
);
845 switch (LOWORD(wParam
)) {
847 if (HIWORD(wParam
) == BN_CLICKED
||
848 HIWORD(wParam
) == BN_DOUBLECLICKED
)
849 cfg
.wrap_mode
= IsDlgButtonChecked (hwnd
, IDC2_WRAPMODE
);
852 if (HIWORD(wParam
) == BN_CLICKED
||
853 HIWORD(wParam
) == BN_DOUBLECLICKED
)
854 cfg
.win_name_always
= IsDlgButtonChecked (hwnd
, IDC2_WINNAME
);
857 if (HIWORD(wParam
) == BN_CLICKED
||
858 HIWORD(wParam
) == BN_DOUBLECLICKED
)
859 cfg
.dec_om
= IsDlgButtonChecked (hwnd
, IDC2_DECOM
);
862 if (HIWORD(wParam
) == BN_CLICKED
||
863 HIWORD(wParam
) == BN_DOUBLECLICKED
)
864 cfg
.lfhascr
= IsDlgButtonChecked (hwnd
, IDC2_LFHASCR
);
867 if (HIWORD(wParam
) == EN_CHANGE
)
868 MyGetDlgItemInt (hwnd
, IDC2_ROWSEDIT
, &cfg
.height
);
871 if (HIWORD(wParam
) == EN_CHANGE
)
872 MyGetDlgItemInt (hwnd
, IDC2_COLSEDIT
, &cfg
.width
);
875 if (HIWORD(wParam
) == EN_CHANGE
)
876 MyGetDlgItemInt (hwnd
, IDC2_SAVEEDIT
, &cfg
.savelines
);
878 case IDC2_CHOOSEFONT
:
879 lf
.lfHeight
= cfg
.fontheight
;
880 lf
.lfWidth
= lf
.lfEscapement
= lf
.lfOrientation
= 0;
881 lf
.lfItalic
= lf
.lfUnderline
= lf
.lfStrikeOut
= 0;
882 lf
.lfWeight
= (cfg
.fontisbold ? FW_BOLD
: 0);
883 lf
.lfCharSet
= cfg
.fontcharset
;
884 lf
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
885 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
886 lf
.lfQuality
= DEFAULT_QUALITY
;
887 lf
.lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
888 strncpy (lf
.lfFaceName
, cfg
.font
, sizeof(lf
.lfFaceName
)-1);
889 lf
.lfFaceName
[sizeof(lf
.lfFaceName
)-1] = '\0';
891 cf
.lStructSize
= sizeof(cf
);
894 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
|
895 CF_INITTOLOGFONTSTRUCT
| CF_SCREENFONTS
;
897 if (ChooseFont (&cf
)) {
898 strncpy (cfg
.font
, lf
.lfFaceName
, sizeof(cfg
.font
)-1);
899 cfg
.font
[sizeof(cfg
.font
)-1] = '\0';
900 cfg
.fontisbold
= (lf
.lfWeight
== FW_BOLD
);
901 cfg
.fontcharset
= lf
.lfCharSet
;
902 cfg
.fontheight
= lf
.lfHeight
;
903 fmtfont (fontstatic
);
904 SetDlgItemText (hwnd
, IDC2_FONTSTATIC
, fontstatic
);
908 if (HIWORD(wParam
) == BN_CLICKED
||
909 HIWORD(wParam
) == BN_DOUBLECLICKED
)
910 cfg
.blink_cur
= IsDlgButtonChecked (hwnd
, IDC1_BLINKCUR
);
913 if (HIWORD(wParam
) == BN_CLICKED
||
914 HIWORD(wParam
) == BN_DOUBLECLICKED
)
915 cfg
.beep
= IsDlgButtonChecked (hwnd
, IDC1_BEEP
);
918 if (HIWORD(wParam
) == BN_CLICKED
||
919 HIWORD(wParam
) == BN_DOUBLECLICKED
)
920 cfg
.scrollbar
= IsDlgButtonChecked (hwnd
, IDC2_SCROLLBAR
);
923 if (HIWORD(wParam
) == BN_CLICKED
||
924 HIWORD(wParam
) == BN_DOUBLECLICKED
)
925 cfg
.locksize
= IsDlgButtonChecked (hwnd
, IDC2_LOCKSIZE
);
928 if (HIWORD(wParam
) == BN_CLICKED
||
929 HIWORD(wParam
) == BN_DOUBLECLICKED
)
930 cfg
.blinktext
= IsDlgButtonChecked (hwnd
, IDC2_BLINKTEXT
);
933 if (HIWORD(wParam
) == BN_CLICKED
||
934 HIWORD(wParam
) == BN_DOUBLECLICKED
)
935 cfg
.bce
= IsDlgButtonChecked (hwnd
, IDC2_BCE
);
940 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
943 static int CALLBACK
TelnetProc (HWND hwnd
, UINT msg
,
944 WPARAM wParam
, LPARAM lParam
) {
949 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
950 SetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
);
951 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
953 char *p
= cfg
.environmt
;
955 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
, 0,
960 CheckRadioButton (hwnd
, IDC3_EMBSD
, IDC3_EMRFC
,
961 cfg
.rfc_environ ? IDC3_EMRFC
: IDC3_EMBSD
);
964 switch (LOWORD(wParam
)) {
966 if (HIWORD(wParam
) == EN_CHANGE
)
967 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
968 sizeof(cfg
.termtype
)-1);
971 if (HIWORD(wParam
) == EN_CHANGE
)
972 GetDlgItemText (hwnd
, IDC3_TSEDIT
, cfg
.termspeed
,
973 sizeof(cfg
.termspeed
)-1);
976 if (HIWORD(wParam
) == EN_CHANGE
)
977 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
978 sizeof(cfg
.username
)-1);
982 cfg
.rfc_environ
= IsDlgButtonChecked (hwnd
, IDC3_EMRFC
);
985 if (HIWORD(wParam
) == BN_CLICKED
||
986 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
987 char str
[sizeof(cfg
.environmt
)];
989 GetDlgItemText (hwnd
, IDC3_VAREDIT
, str
, sizeof(str
)-1);
994 p
= str
+ strlen(str
);
996 GetDlgItemText (hwnd
, IDC3_VALEDIT
, p
, sizeof(str
)-1-(p
-str
));
1006 if ((p
-cfg
.environmt
) + strlen(str
) + 2 < sizeof(cfg
.environmt
)) {
1008 p
[strlen(str
)+1] = '\0';
1009 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_ADDSTRING
,
1011 SetDlgItemText (hwnd
, IDC3_VAREDIT
, "");
1012 SetDlgItemText (hwnd
, IDC3_VALEDIT
, "");
1014 MessageBox(hwnd
, "Environment too big", "PuTTY Error",
1015 MB_OK
| MB_ICONERROR
);
1019 case IDC3_ENVREMOVE
:
1020 if (HIWORD(wParam
) != BN_CLICKED
&&
1021 HIWORD(wParam
) != BN_DOUBLECLICKED
)
1023 i
= SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_GETCURSEL
, 0, 0);
1029 SendDlgItemMessage (hwnd
, IDC3_ENVLIST
, LB_DELETESTRING
,
1056 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1059 static int CALLBACK
SshProc (HWND hwnd
, UINT msg
,
1060 WPARAM wParam
, LPARAM lParam
) {
1062 char filename
[sizeof(cfg
.keyfile
)];
1066 SetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
);
1067 SetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
);
1068 CheckDlgButton (hwnd
, IDC3_NOPTY
, cfg
.nopty
);
1069 CheckDlgButton (hwnd
, IDC3_AGENTFWD
, cfg
.agentfwd
);
1070 CheckRadioButton (hwnd
, IDC3_CIPHER3DES
, IDC3_CIPHERDES
,
1071 cfg
.cipher
== CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF
:
1072 cfg
.cipher
== CIPHER_DES ? IDC3_CIPHERDES
:
1074 CheckRadioButton (hwnd
, IDC3_SSHPROT1
, IDC3_SSHPROT2
,
1075 cfg
.sshprot
== 1 ? IDC3_SSHPROT1
: IDC3_SSHPROT2
);
1076 CheckDlgButton (hwnd
, IDC3_AUTHTIS
, cfg
.try_tis_auth
);
1077 SetDlgItemText (hwnd
, IDC3_PKEDIT
, cfg
.keyfile
);
1080 switch (LOWORD(wParam
)) {
1082 if (HIWORD(wParam
) == EN_CHANGE
)
1083 GetDlgItemText (hwnd
, IDC3_TTEDIT
, cfg
.termtype
,
1084 sizeof(cfg
.termtype
)-1);
1087 if (HIWORD(wParam
) == EN_CHANGE
)
1088 GetDlgItemText (hwnd
, IDC3_LOGEDIT
, cfg
.username
,
1089 sizeof(cfg
.username
)-1);
1092 if (HIWORD(wParam
) == BN_CLICKED
||
1093 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1094 cfg
.nopty
= IsDlgButtonChecked (hwnd
, IDC3_NOPTY
);
1097 if (HIWORD(wParam
) == BN_CLICKED
||
1098 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1099 cfg
.agentfwd
= IsDlgButtonChecked (hwnd
, IDC3_AGENTFWD
);
1101 case IDC3_CIPHER3DES
:
1102 case IDC3_CIPHERBLOWF
:
1103 case IDC3_CIPHERDES
:
1104 if (HIWORD(wParam
) == BN_CLICKED
||
1105 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1106 if (IsDlgButtonChecked (hwnd
, IDC3_CIPHER3DES
))
1107 cfg
.cipher
= CIPHER_3DES
;
1108 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERBLOWF
))
1109 cfg
.cipher
= CIPHER_BLOWFISH
;
1110 else if (IsDlgButtonChecked (hwnd
, IDC3_CIPHERDES
))
1111 cfg
.cipher
= CIPHER_DES
;
1116 if (HIWORD(wParam
) == BN_CLICKED
||
1117 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1118 if (IsDlgButtonChecked (hwnd
, IDC3_SSHPROT1
))
1120 else if (IsDlgButtonChecked (hwnd
, IDC3_SSHPROT2
))
1125 if (HIWORD(wParam
) == BN_CLICKED
||
1126 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1127 cfg
.try_tis_auth
= IsDlgButtonChecked (hwnd
, IDC3_AUTHTIS
);
1130 if (HIWORD(wParam
) == EN_CHANGE
)
1131 GetDlgItemText (hwnd
, IDC3_PKEDIT
, cfg
.keyfile
,
1132 sizeof(cfg
.keyfile
)-1);
1136 * FIXME: this crashes. Find out why.
1138 memset(&of
, 0, sizeof(of
));
1139 #ifdef OPENFILENAME_SIZE_VERSION_400
1140 of
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1142 of
.lStructSize
= sizeof(of
);
1144 of
.hwndOwner
= hwnd
;
1145 of
.lpstrFilter
= "All Files\0*\0\0\0";
1146 of
.lpstrCustomFilter
= NULL
;
1147 of
.nFilterIndex
= 1;
1148 of
.lpstrFile
= filename
; strcpy(filename
, cfg
.keyfile
);
1149 of
.nMaxFile
= sizeof(filename
);
1150 of
.lpstrFileTitle
= NULL
;
1151 of
.lpstrInitialDir
= NULL
;
1152 of
.lpstrTitle
= "Select Public Key File";
1154 if (GetOpenFileName(&of
)) {
1155 strcpy(cfg
.keyfile
, filename
);
1156 SetDlgItemText (hwnd
, IDC3_PKEDIT
, cfg
.keyfile
);
1162 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1165 static int CALLBACK
SelectionProc (HWND hwnd
, UINT msg
,
1166 WPARAM wParam
, LPARAM lParam
) {
1171 CheckRadioButton (hwnd
, IDC4_MBWINDOWS
, IDC4_MBXTERM
,
1172 cfg
.mouse_is_xterm ? IDC4_MBXTERM
: IDC4_MBWINDOWS
);
1174 static int tabs
[4] = {25, 61, 96, 128};
1175 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_SETTABSTOPS
, 4,
1178 for (i
=0; i
<256; i
++) {
1180 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1181 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1183 SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_ADDSTRING
, 0,
1188 switch (LOWORD(wParam
)) {
1189 case IDC4_MBWINDOWS
:
1191 cfg
.mouse_is_xterm
= IsDlgButtonChecked (hwnd
, IDC4_MBXTERM
);
1197 int n
= GetDlgItemInt (hwnd
, IDC4_CCEDIT
, &ok
, FALSE
);
1202 for (i
=0; i
<256; i
++)
1203 if (SendDlgItemMessage (hwnd
, IDC4_CCLIST
, LB_GETSEL
,
1206 cfg
.wordness
[i
] = n
;
1207 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
1208 LB_DELETESTRING
, i
, 0);
1209 sprintf(str
, "%d\t(0x%02X)\t%c\t%d", i
, i
,
1210 (i
>=0x21 && i
!= 0x7F) ? i
: ' ',
1212 SendDlgItemMessage (hwnd
, IDC4_CCLIST
,
1222 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1225 static int CALLBACK
ColourProc (HWND hwnd
, UINT msg
,
1226 WPARAM wParam
, LPARAM lParam
) {
1227 static const char *const colours
[] = {
1228 "Default Foreground", "Default Bold Foreground",
1229 "Default Background", "Default Bold Background",
1230 "Cursor Text", "Cursor Colour",
1231 "ANSI Black", "ANSI Black Bold",
1232 "ANSI Red", "ANSI Red Bold",
1233 "ANSI Green", "ANSI Green Bold",
1234 "ANSI Yellow", "ANSI Yellow Bold",
1235 "ANSI Blue", "ANSI Blue Bold",
1236 "ANSI Magenta", "ANSI Magenta Bold",
1237 "ANSI Cyan", "ANSI Cyan Bold",
1238 "ANSI White", "ANSI White Bold"
1240 static const int permanent
[] = {
1241 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, TRUE
,
1242 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
,
1243 TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
, TRUE
, FALSE
1247 CheckDlgButton (hwnd
, IDC5_BOLDCOLOUR
, cfg
.bold_colour
);
1248 CheckDlgButton (hwnd
, IDC5_PALETTE
, cfg
.try_palette
);
1251 for (i
=0; i
<22; i
++)
1252 if (cfg
.bold_colour
|| permanent
[i
])
1253 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_ADDSTRING
, 0,
1254 (LPARAM
) colours
[i
]);
1256 SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_SETCURSEL
, 0, 0);
1257 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[0][0], FALSE
);
1258 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[0][1], FALSE
);
1259 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[0][2], FALSE
);
1262 switch (LOWORD(wParam
)) {
1263 case IDC5_BOLDCOLOUR
:
1264 if (HIWORD(wParam
) == BN_CLICKED
||
1265 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1267 cfg
.bold_colour
= IsDlgButtonChecked (hwnd
, IDC5_BOLDCOLOUR
);
1268 n
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCOUNT
, 0, 0);
1269 if (cfg
.bold_colour
&& n
!=22) {
1270 for (i
=0; i
<22; i
++)
1272 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1274 (LPARAM
) colours
[i
]);
1275 } else if (!cfg
.bold_colour
&& n
!=12) {
1278 SendDlgItemMessage (hwnd
, IDC5_LIST
,
1279 LB_DELETESTRING
, i
, 0);
1284 if (HIWORD(wParam
) == BN_CLICKED
||
1285 HIWORD(wParam
) == BN_DOUBLECLICKED
)
1286 cfg
.try_palette
= IsDlgButtonChecked (hwnd
, IDC5_PALETTE
);
1289 if (HIWORD(wParam
) == LBN_DBLCLK
||
1290 HIWORD(wParam
) == LBN_SELCHANGE
) {
1291 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1293 if (!cfg
.bold_colour
)
1294 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1295 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0], FALSE
);
1296 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1], FALSE
);
1297 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2], FALSE
);
1301 if (HIWORD(wParam
) == BN_CLICKED
||
1302 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1303 static CHOOSECOLOR cc
;
1304 static DWORD custom
[16] = {0}; /* zero initialisers */
1305 int i
= SendDlgItemMessage (hwnd
, IDC5_LIST
, LB_GETCURSEL
,
1307 if (!cfg
.bold_colour
)
1308 i
= (i
< 3 ? i
*2 : i
== 3 ?
5 : i
*2-2);
1309 cc
.lStructSize
= sizeof(cc
);
1310 cc
.hwndOwner
= hwnd
;
1311 cc
.hInstance
= (HWND
)hinst
;
1312 cc
.lpCustColors
= custom
;
1313 cc
.rgbResult
= RGB (cfg
.colours
[i
][0], cfg
.colours
[i
][1],
1315 cc
.Flags
= CC_FULLOPEN
| CC_RGBINIT
;
1316 if (ChooseColor(&cc
)) {
1318 (unsigned char) (cc
.rgbResult
& 0xFF);
1320 (unsigned char) (cc
.rgbResult
>> 8) & 0xFF;
1322 (unsigned char) (cc
.rgbResult
>> 16) & 0xFF;
1323 SetDlgItemInt (hwnd
, IDC5_RVALUE
, cfg
.colours
[i
][0],
1325 SetDlgItemInt (hwnd
, IDC5_GVALUE
, cfg
.colours
[i
][1],
1327 SetDlgItemInt (hwnd
, IDC5_BVALUE
, cfg
.colours
[i
][2],
1335 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1338 static int CALLBACK
TranslationProc (HWND hwnd
, UINT msg
,
1339 WPARAM wParam
, LPARAM lParam
) {
1342 CheckRadioButton (hwnd
, IDC6_NOXLAT
, IDC6_88592WIN1250
,
1343 cfg
.xlat_88592w1250 ? IDC6_88592WIN1250
:
1344 cfg
.xlat_enablekoiwin ? IDC6_KOI8WIN1251
:
1346 CheckDlgButton (hwnd
, IDC6_CAPSLOCKCYR
, cfg
.xlat_capslockcyr
);
1347 CheckRadioButton (hwnd
, IDC2_VTXWINDOWS
, IDC2_VTPOORMAN
,
1348 cfg
.vtmode
== VT_XWINDOWS ? IDC2_VTXWINDOWS
:
1349 cfg
.vtmode
== VT_OEMANSI ? IDC2_VTOEMANSI
:
1350 cfg
.vtmode
== VT_OEMONLY ? IDC2_VTOEMONLY
:
1353 switch (LOWORD(wParam
)) {
1355 case IDC6_KOI8WIN1251
:
1356 case IDC6_88592WIN1250
:
1357 cfg
.xlat_enablekoiwin
=
1358 IsDlgButtonChecked (hwnd
, IDC6_KOI8WIN1251
);
1359 cfg
.xlat_88592w1250
=
1360 IsDlgButtonChecked (hwnd
, IDC6_88592WIN1250
);
1362 case IDC6_CAPSLOCKCYR
:
1363 if (HIWORD(wParam
) == BN_CLICKED
||
1364 HIWORD(wParam
) == BN_DOUBLECLICKED
) {
1365 cfg
.xlat_capslockcyr
=
1366 IsDlgButtonChecked (hwnd
, IDC6_CAPSLOCKCYR
);
1369 case IDC2_VTXWINDOWS
:
1370 case IDC2_VTOEMANSI
:
1371 case IDC2_VTOEMONLY
:
1372 case IDC2_VTPOORMAN
:
1374 (IsDlgButtonChecked (hwnd
, IDC2_VTXWINDOWS
) ? VT_XWINDOWS
:
1375 IsDlgButtonChecked (hwnd
, IDC2_VTOEMANSI
) ? VT_OEMANSI
:
1376 IsDlgButtonChecked (hwnd
, IDC2_VTOEMONLY
) ? VT_OEMONLY
:
1381 return GeneralPanelProc (hwnd
, msg
, wParam
, lParam
);
1384 static DLGPROC panelproc
[NPANELS
] = {
1385 ConnectionProc
, KeyboardProc
, TerminalProc
,
1386 TelnetProc
, SshProc
, SelectionProc
, ColourProc
, TranslationProc
1388 static char *panelids
[NPANELS
] = {
1389 MAKEINTRESOURCE(IDD_PANEL0
),
1390 MAKEINTRESOURCE(IDD_PANEL1
),
1391 MAKEINTRESOURCE(IDD_PANEL2
),
1392 MAKEINTRESOURCE(IDD_PANEL3
),
1393 MAKEINTRESOURCE(IDD_PANEL35
),
1394 MAKEINTRESOURCE(IDD_PANEL4
),
1395 MAKEINTRESOURCE(IDD_PANEL5
),
1396 MAKEINTRESOURCE(IDD_PANEL6
)
1399 static char *names
[NPANELS
] = {
1400 "Connection", "Keyboard", "Terminal", "Telnet",
1401 "SSH", "Selection", "Colours", "Translation"
1404 static int mainp
[MAIN_NPANELS
] = { 0, 1, 2, 3, 4, 5, 6, 7};
1405 static int reconfp
[RECONF_NPANELS
] = { 1, 2, 5, 6, 7};
1407 static int GenericMainDlgProc (HWND hwnd
, UINT msg
,
1408 WPARAM wParam
, LPARAM lParam
,
1409 int npanels
, int *panelnums
, HWND
*page
) {
1414 { /* centre the window */
1417 hw
= GetDesktopWindow();
1418 if (GetWindowRect (hw
, &rs
) && GetWindowRect (hwnd
, &rd
))
1419 MoveWindow (hwnd
, (rs
.right
+ rs
.left
+ rd
.left
- rd
.right
)/2,
1420 (rs
.bottom
+ rs
.top
+ rd
.top
- rd
.bottom
)/2,
1421 rd
.right
-rd
.left
, rd
.bottom
-rd
.top
, TRUE
);
1424 { /* initialise the tab control */
1428 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1429 for (i
=0; i
<npanels
; i
++) {
1430 tab
.mask
= TCIF_TEXT
;
1431 tab
.pszText
= names
[panelnums
[i
]];
1432 TabCtrl_InsertItem (hw
, i
, &tab
);
1434 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1435 hwnd, panelproc[panelnums[0]]);*/
1436 *page
= CreateDialog (hinst
, panelids
[panelnums
[0]],
1437 hwnd
, panelproc
[panelnums
[0]]);
1438 SetWindowLong (*page
, GWL_EXSTYLE
,
1439 GetWindowLong (*page
, GWL_EXSTYLE
) |
1440 WS_EX_CONTROLPARENT
);
1445 if (LOWORD(wParam
) == IDC_TAB
&&
1446 ((LPNMHDR
)lParam
)->code
== TCN_SELCHANGE
) {
1447 int i
= TabCtrl_GetCurSel(((LPNMHDR
)lParam
)->hwndFrom
);
1449 DestroyWindow (*page
);
1450 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1451 hwnd, panelproc[panelnums[i]]);*/
1452 *page
= CreateDialog (hinst
, panelids
[panelnums
[i
]],
1453 hwnd
, panelproc
[panelnums
[i
]]);
1454 SetWindowLong (*page
, GWL_EXSTYLE
,
1455 GetWindowLong (*page
, GWL_EXSTYLE
) |
1456 WS_EX_CONTROLPARENT
);
1457 SetFocus (((LPNMHDR
)lParam
)->hwndFrom
); /* ensure focus stays */
1461 /* case WM_CTLCOLORDLG: */
1462 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1464 switch (LOWORD(wParam
)) {
1467 EndDialog (hwnd
, 1);
1472 EndDialog (hwnd
, 0);
1477 EndDialog (hwnd
, 0);
1480 /* Grrr Explorer will maximize Dialogs! */
1482 if (wParam
== SIZE_MAXIMIZED
)
1489 static int CALLBACK
MainDlgProc (HWND hwnd
, UINT msg
,
1490 WPARAM wParam
, LPARAM lParam
) {
1495 static HWND page
= NULL
;
1497 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDOK
) {
1500 * If the Connection panel is active and the Session List
1501 * box is selected, we treat a press of Open to have an
1502 * implicit press of Load preceding it.
1504 hw
= GetDlgItem (hwnd
, IDC_TAB
);
1505 i
= TabCtrl_GetCurSel(hw
);
1506 if (panelproc
[mainp
[i
]] == ConnectionProc
&&
1507 page
&& implicit_load_ok
) {
1508 SendMessage (page
, WM_COMMAND
,
1509 MAKELONG(IDC0_SESSLOAD
, BN_CLICKED
), 0);
1513 if (msg
== WM_COMMAND
&& LOWORD(wParam
) == IDC_ABOUT
) {
1514 EnableWindow(hwnd
, 0);
1515 DialogBox(hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1516 GetParent(hwnd
), AboutProc
);
1517 EnableWindow(hwnd
, 1);
1518 SetActiveWindow(hwnd
);
1520 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1521 MAIN_NPANELS
, mainp
, &page
);
1524 static int CALLBACK
ReconfDlgProc (HWND hwnd
, UINT msg
,
1525 WPARAM wParam
, LPARAM lParam
) {
1527 return GenericMainDlgProc (hwnd
, msg
, wParam
, lParam
,
1528 RECONF_NPANELS
, reconfp
, &page
);
1531 void get_sesslist(int allocate
) {
1532 static char *buffer
;
1533 int buflen
, bufsize
, i
, ret
;
1534 char otherbuf
[2048];
1539 if (RegCreateKey(HKEY_CURRENT_USER
,
1540 puttystr
, &subkey1
) != ERROR_SUCCESS
)
1543 buflen
= bufsize
= 0;
1547 ret
= RegEnumKey(subkey1
, i
++, otherbuf
, sizeof(otherbuf
));
1548 if (ret
== ERROR_SUCCESS
) {
1549 bufsize
= buflen
+ 2048;
1550 buffer
= srealloc(buffer
, bufsize
);
1551 unmungestr(otherbuf
, buffer
+buflen
);
1552 buflen
+= strlen(buffer
+buflen
)+1;
1554 } while (ret
== ERROR_SUCCESS
);
1555 buffer
= srealloc(buffer
, buflen
+1);
1556 buffer
[buflen
] = '\0';
1559 nsessions
= 1; /* "Default Settings" counts as one */
1561 if (strcmp(p
, "Default Settings"))
1567 sessions
= smalloc(nsessions
* sizeof(char *));
1568 sessions
[0] = "Default Settings";
1572 if (strcmp(p
, "Default Settings"))
1583 int do_config (void) {
1587 savedsession
[0] = '\0';
1588 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_MAINBOX
), NULL
, MainDlgProc
);
1589 get_sesslist(FALSE
);
1594 int do_reconfig (HWND hwnd
) {
1598 backup_cfg
= cfg
; /* structure copy */
1599 ret
= DialogBox (hinst
, MAKEINTRESOURCE(IDD_RECONF
), hwnd
, ReconfDlgProc
);
1601 cfg
= backup_cfg
; /* structure copy */
1608 void do_defaults (char *session
) {
1610 load_settings (session
, TRUE
);
1612 load_settings ("Default Settings", FALSE
);
1615 void logevent (char *string
) {
1616 if (nevents
>= negsize
) {
1618 events
= srealloc (events
, negsize
* sizeof(*events
));
1620 events
[nevents
] = smalloc(1+strlen(string
));
1621 strcpy (events
[nevents
], string
);
1625 SendDlgItemMessage (logbox
, IDN_LIST
, LB_ADDSTRING
,
1627 count
= SendDlgItemMessage (logbox
, IDN_LIST
, LB_GETCOUNT
, 0, 0);
1628 SendDlgItemMessage (logbox
, IDN_LIST
, LB_SETTOPINDEX
, count
-1, 0);
1632 void showeventlog (HWND hwnd
) {
1634 logbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_LOGBOX
),
1636 ShowWindow (logbox
, SW_SHOWNORMAL
);
1640 void showabout (HWND hwnd
) {
1642 abtbox
= CreateDialog (hinst
, MAKEINTRESOURCE(IDD_ABOUTBOX
),
1644 ShowWindow (abtbox
, SW_SHOWNORMAL
);
1648 void verify_ssh_host_key(char *host
, char *keytype
,
1649 char *keystr
, char *fingerprint
) {
1652 static const char absentmsg
[] =
1653 "The server's host key is not cached in the registry. You\n"
1654 "have no guarantee that the server is the computer you\n"
1656 "The server's key fingerprint is:\n"
1658 "If you trust this host, hit Yes to add the key to\n"
1659 "PuTTY's cache and carry on connecting.\n"
1660 "If you do not trust this host, hit No to abandon the\n"
1663 static const char wrongmsg
[] =
1664 "WARNING - POTENTIAL SECURITY BREACH!\n"
1666 "The server's host key does not match the one PuTTY has\n"
1667 "cached in the registry. This means that either the\n"
1668 "server administrator has changed the host key, or you\n"
1669 "have actually connected to another computer pretending\n"
1670 "to be the server.\n"
1671 "The new key fingerprint is:\n"
1673 "If you were expecting this change and trust the new key,\n"
1674 "hit Yes to update PuTTY's cache and continue connecting.\n"
1675 "If you want to carry on connecting but without updating\n"
1676 "the cache, hit No.\n"
1677 "If you want to abandon the connection completely, hit\n"
1678 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1681 static const char mbtitle
[] = "PuTTY Security Alert";
1684 char message
[160+ /* sensible fingerprint max size */
1685 (sizeof(absentmsg
) > sizeof(wrongmsg
) ?
1686 sizeof(absentmsg
) : sizeof(wrongmsg
))];
1689 * Verify the key against the registry.
1691 ret
= verify_host_key(host
, keytype
, keystr
);
1693 if (ret
== 0) /* success - key matched OK */
1695 if (ret
== 2) { /* key was different */
1697 sprintf(message
, wrongmsg
, fingerprint
);
1698 mbret
= MessageBox(NULL
, message
, mbtitle
,
1699 MB_ICONWARNING
| MB_YESNOCANCEL
);
1701 store_host_key(host
, keytype
, keystr
);
1702 if (mbret
== IDCANCEL
)
1705 if (ret
== 1) { /* key was absent */
1707 sprintf(message
, absentmsg
, fingerprint
);
1708 mbret
= MessageBox(NULL
, message
, mbtitle
,
1709 MB_ICONWARNING
| MB_YESNO
);
1712 store_host_key(host
, keytype
, keystr
);