13 static char **events = NULL;
14 static int nevents = 0, negsize = 0;
16 static HWND logbox = NULL, abtbox = NULL;
20 static void force_normal(HWND hwnd)
22 static int recurse = 0;
29 wp.length = sizeof(wp);
30 if (GetWindowPlacement(hwnd, &wp))
32 wp.showCmd = SW_SHOWNORMAL;
33 SetWindowPlacement(hwnd, &wp);
38 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
41 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
46 static int CALLBACK LogProc (HWND hwnd, UINT msg,
47 WPARAM wParam, LPARAM lParam) {
52 for (i=0; i<nevents; i++)
53 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
54 0, (LPARAM)events[i]);
57 switch (LOWORD(wParam)) {
63 if (HIWORD(wParam) == BN_CLICKED ||
64 HIWORD(wParam) == BN_DOUBLECLICKED) {
67 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
68 LB_GETSELCOUNT, 0, 0);
69 selitems = smalloc(selcount * sizeof(int));
71 int count = SendDlgItemMessage(hwnd, IDN_LIST,
73 selcount, (LPARAM)selitems);
77 static unsigned char sel_nl[] = SEL_NL;
79 if (count == 0) { /* can't copy zero stuff */
85 for (i = 0; i < count; i++)
86 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
88 clipdata = smalloc(size);
91 for (i = 0; i < count; i++) {
92 char *q = events[selitems[i]];
96 memcpy(p, sel_nl, sizeof(sel_nl));
99 write_clip(clipdata, size, TRUE);
104 for (i = 0; i < nevents; i++)
105 SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
114 DestroyWindow (hwnd);
120 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
121 WPARAM wParam, LPARAM lParam) {
126 switch (LOWORD(wParam)) {
139 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
140 WPARAM wParam, LPARAM lParam) {
143 SetDlgItemText (hwnd, IDA_VERSION, ver);
146 switch (LOWORD(wParam)) {
149 DestroyWindow (hwnd);
152 EnableWindow(hwnd, 0);
153 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
155 EnableWindow(hwnd, 1);
156 SetActiveWindow(hwnd);
162 DestroyWindow (hwnd);
169 * Null dialog procedure.
171 static int CALLBACK NullDlgProc (HWND hwnd, UINT msg,
172 WPARAM wParam, LPARAM lParam) {
176 static char savedsession[2048];
178 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
182 IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
183 IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
204 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
205 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
206 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3,
232 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
244 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
245 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
264 appearancepanelstart,
265 IDC_TITLE_APPEARANCE,
266 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1,
267 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2,
268 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3,
277 connectionpanelstart,
278 IDC_TITLE_CONNECTION,
279 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
280 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
291 IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
292 IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
310 IDC_BOX_SSH1, IDC_BOXT_SSH1,
311 IDC_BOX_SSH2, IDC_BOXT_SSH2,
312 IDC_BOX_SSH3, IDC_BOXT_SSH3,
334 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
335 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
348 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
349 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
363 translationpanelstart,
364 IDC_TITLE_TRANSLATION,
365 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
366 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
367 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
384 static const char *const colours[] = {
385 "Default Foreground", "Default Bold Foreground",
386 "Default Background", "Default Bold Background",
387 "Cursor Text", "Cursor Colour",
388 "ANSI Black", "ANSI Black Bold",
389 "ANSI Red", "ANSI Red Bold",
390 "ANSI Green", "ANSI Green Bold",
391 "ANSI Yellow", "ANSI Yellow Bold",
392 "ANSI Blue", "ANSI Blue Bold",
393 "ANSI Magenta", "ANSI Magenta Bold",
394 "ANSI Cyan", "ANSI Cyan Bold",
395 "ANSI White", "ANSI White Bold"
397 static const int permcolour[] = {
398 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
399 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
400 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
403 static void fmtfont (char *buf) {
404 sprintf (buf, "Font: %s, ", cfg.font);
406 strcat(buf, "bold, ");
407 if (cfg.fontheight == 0)
408 strcat (buf, "default height");
410 sprintf (buf+strlen(buf), "%d-%s",
411 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
412 (cfg.fontheight < 0 ? "pixel" : "point"));
415 static void init_dlg_ctrls(HWND hwnd) {
417 char fontstatic[256];
419 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
420 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
421 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
422 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
423 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
424 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
425 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
427 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
428 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
429 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
430 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
431 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
432 cfg.funky_type == 0 ? IDC_FUNCTILDE :
433 cfg.funky_type == 1 ? IDC_FUNCLINUX :
434 cfg.funky_type == 2 ? IDC_FUNCXTERM :
435 cfg.funky_type == 3 ? IDC_FUNCVT400 :
437 CheckDlgButton (hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
438 CheckDlgButton (hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
439 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
440 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
441 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
442 cfg.nethack_keypad ? IDC_KPNH :
443 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
444 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
445 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
446 CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
447 CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
448 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
449 CheckDlgButton (hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
450 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
451 CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
453 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
454 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
455 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
456 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
457 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
458 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
459 fmtfont (fontstatic);
460 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
461 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
462 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
463 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
465 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
466 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
467 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
468 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
469 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
470 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
471 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
473 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
474 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
475 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
477 char *p = cfg.environmt;
479 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
484 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
485 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
487 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
488 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
489 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
490 CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
491 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
492 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
493 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
494 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
495 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
497 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
498 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
499 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
500 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
501 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
503 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
504 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
506 static int tabs[4] = {25, 61, 96, 128};
507 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
510 for (i=0; i<256; i++) {
512 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
513 (i>=0x21 && i != 0x7F) ? i : ' ',
515 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
519 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
520 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
523 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
525 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
526 LB_DELETESTRING, i, 0);
528 if (cfg.bold_colour || permcolour[i])
529 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
530 (LPARAM) colours[i]);
532 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
533 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
534 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
535 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
537 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
538 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
539 cfg.xlat_88592cp852 ? IDC_88592CP852 :
540 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
542 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
543 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
544 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
545 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
546 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
550 static void hide(HWND hwnd, int hide, int minid, int maxid) {
552 for (i = minid; i < maxid; i++) {
553 HWND ctl = GetDlgItem(hwnd, i);
555 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
560 struct treeview_faff {
565 static HTREEITEM treeview_insert(struct treeview_faff *faff,
566 int level, char *text) {
570 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
571 ins.hInsertAfter = faff->lastat[level];
572 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
573 #define INSITEM DUMMYUNIONNAME.item
577 ins.INSITEM.mask = TVIF_TEXT;
578 ins.INSITEM.pszText = text;
579 newitem = TreeView_InsertItem(faff->treeview, &ins);
581 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
582 faff->lastat[level] = newitem;
583 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
588 * This _huge_ function is the configuration box.
590 static int GenericMainDlgProc (HWND hwnd, UINT msg,
591 WPARAM wParam, LPARAM lParam,
594 struct treeview_faff tvfaff;
597 char filename[sizeof(cfg.keyfile)];
600 char fontstatic[256];
602 struct servent * service;
608 SetWindowLong(hwnd, GWL_USERDATA, 0);
612 { /* centre the window */
615 hw = GetDesktopWindow();
616 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
617 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
618 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
619 rd.right-rd.left, rd.bottom-rd.top, TRUE);
623 * Create the tree view.
630 r.left = 3; r.right = r.left + 75;
631 r.top = 3; r.bottom = r.top + 10;
632 MapDialogRect(hwnd, &r);
633 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
634 WS_CHILD | WS_VISIBLE,
636 r.right-r.left, r.bottom-r.top,
637 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
638 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
639 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
641 r.left = 3; r.right = r.left + 75;
642 r.top = 13; r.bottom = r.top + 206;
643 MapDialogRect(hwnd, &r);
644 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
645 WS_CHILD | WS_VISIBLE |
646 WS_TABSTOP | TVS_HASLINES |
647 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
648 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
650 r.right-r.left, r.bottom-r.top,
651 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
652 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
653 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
654 tvfaff.treeview = treeview;
655 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
659 * Create the various panelfuls of controls.
662 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
665 ctlposinit(&cp, hwnd, 80, 3, 13);
666 bartitle(&cp, "Basic options for your PuTTY session",
669 beginbox(&cp, "Specify your connection by host name",
670 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
672 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
673 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
674 if (backends[2].backend == NULL) {
675 /* this is PuTTYtel, so only two protocols available */
676 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
678 "&Telnet", IDC_PROTTELNET, NULL);
680 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
682 "&Telnet", IDC_PROTTELNET,
691 beginbox(&cp, "Load, save or delete a stored session",
692 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
693 sesssaver(&cp, "Sav&ed Sessions",
694 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
695 "&Load", IDC_SESSLOAD,
696 "&Save", IDC_SESSSAVE,
697 "&Delete", IDC_SESSDEL, NULL);
700 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
701 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
704 hsession = treeview_insert(&tvfaff, 0, "Session");
707 /* The Terminal panel. Accelerators used: [acgo] &dlbenu */
710 ctlposinit(&cp, hwnd, 80, 3, 13);
711 bartitle(&cp, "Options controlling the terminal emulation",
713 beginbox(&cp, "Set various terminal options",
714 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
715 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
716 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
717 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
718 checkbox(&cp, "&Beep enabled", IDC_BEEP);
719 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
720 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
721 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
724 treeview_insert(&tvfaff, 0, "Terminal");
727 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmietu */
730 ctlposinit(&cp, hwnd, 80, 3, 13);
731 bartitle(&cp, "Options controlling the effects of keys",
733 beginbox(&cp, "Change the sequences sent by:",
734 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
735 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
736 "Control-&H", IDC_DEL008,
737 "Control-&? (127)", IDC_DEL127, NULL);
738 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
739 "&Standard", IDC_HOMETILDE,
740 "&rxvt", IDC_HOMERXVT, NULL);
741 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
742 "ESC[n&~", IDC_FUNCTILDE,
743 "&Linux", IDC_FUNCLINUX,
744 "&Xterm R6", IDC_FUNCXTERM,
745 "&VT400", IDC_FUNCVT400, NULL);
747 beginbox(&cp, "Application keypad settings:",
748 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
750 "Application c&ursor keys totally disabled",
752 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
753 "&Normal", IDC_CURNORMAL,
754 "A&pplication", IDC_CURAPPLIC, NULL);
756 "Application ke&ypad keys totally disabled",
758 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
759 "Nor&mal", IDC_KPNORMAL,
760 "Appl&ication", IDC_KPAPPLIC,
761 "N&etHack", IDC_KPNH, NULL);
763 beginbox(&cp, "Enable extra keyboard features:",
764 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3);
765 checkbox(&cp, "Application and AltGr ac&t as Compose key",
769 treeview_insert(&tvfaff, 1, "Keyboard");
772 /* The Window panel. Accelerators used: [acgo] bsdkw4ylpt */
775 ctlposinit(&cp, hwnd, 80, 3, 13);
776 bartitle(&cp, "Options controlling PuTTY's window",
778 beginbox(&cp, "Set the size of the window",
779 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
781 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
782 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
784 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
786 beginbox(&cp, "Control the scrollback in the window",
787 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
788 staticedit(&cp, "Lines of &scrollback",
789 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
790 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
791 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
792 checkbox(&cp, "Reset scrollback on dis&play activity",
795 beginbox(&cp, NULL, IDC_BOX_WINDOW3, 0);
796 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
797 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
798 checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
799 checkbox(&cp, "System menu appears on A< alone", IDC_ALTONLY);
800 checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
803 treeview_insert(&tvfaff, 0, "Window");
806 /* The Appearance panel. Accelerators used: [acgo] rmkhti */
809 ctlposinit(&cp, hwnd, 80, 3, 13);
810 bartitle(&cp, "Options controlling PuTTY's appearance",
811 IDC_TITLE_APPEARANCE);
812 beginbox(&cp, "Adjust the use of the cursor",
813 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1);
814 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
816 beginbox(&cp, "Set the font used in the terminal window",
817 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2);
818 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
820 beginbox(&cp, "Adjust the use of the window title",
821 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3);
824 "Initial window &title:", IDC_WINTITLE,
825 IDC_WINEDIT, 100, NULL);
826 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
829 treeview_insert(&tvfaff, 1, "Appearance");
832 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
835 ctlposinit(&cp, hwnd, 80, 3, 13);
836 bartitle(&cp, "Options controlling character set translation",
837 IDC_TITLE_TRANSLATION);
838 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
839 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
841 "Handling of line drawing characters:", IDC_VTSTATIC,
842 "Font has &XWindows encoding", IDC_VTXWINDOWS,
843 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
844 "Use font in O&EM mode only", IDC_VTOEMONLY,
845 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
846 IDC_VTPOORMAN, NULL);
848 beginbox(&cp, "Enable character set translation on received data",
849 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
851 "Character set translation:", IDC_XLATSTATIC,
853 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
854 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
855 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
857 beginbox(&cp, "Enable character set translation on input data",
858 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
859 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
863 treeview_insert(&tvfaff, 1, "Translation");
866 /* The Selection panel. Accelerators used: [acgo] wxst */
869 ctlposinit(&cp, hwnd, 80, 3, 13);
870 bartitle(&cp, "Options controlling copy and paste",
871 IDC_TITLE_SELECTION);
872 beginbox(&cp, "Control which mouse button does which thing",
873 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
874 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
875 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
876 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
879 beginbox(&cp, "Control the select-one-word-at-a-time mode",
880 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
881 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
882 "&Set", IDC_CCSET, IDC_CCEDIT,
883 "&to class", IDC_CCSTATIC2);
886 treeview_insert(&tvfaff, 1, "Selection");
889 /* The Colours panel. Accelerators used: [acgo] blum */
892 ctlposinit(&cp, hwnd, 80, 3, 13);
893 bartitle(&cp, "Options controlling use of colours",
895 beginbox(&cp, "General options for colour usage",
896 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
897 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
898 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
900 beginbox(&cp, "Adjust the precise colours PuTTY displays",
901 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
902 colouredit(&cp, "Select a colo&ur and then click to modify it:",
903 IDC_COLOURSTATIC, IDC_COLOURLIST,
904 "&Modify...", IDC_CHANGE,
905 "Red:", IDC_RSTATIC, IDC_RVALUE,
906 "Green:", IDC_GSTATIC, IDC_GVALUE,
907 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
910 treeview_insert(&tvfaff, 1, "Colours");
913 /* The Connection panel. Accelerators used: [acgo] tuk */
916 ctlposinit(&cp, hwnd, 80, 3, 13);
917 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
919 beginbox(&cp, "Data to send to the server",
920 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
921 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
922 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
925 beginbox(&cp, "Sending of null packets to keep session active",
926 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
927 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
928 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
931 treeview_insert(&tvfaff, 0, "Connection");
934 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
937 ctlposinit(&cp, hwnd, 80, 3, 13);
939 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
940 beginbox(&cp, "Data to send to the server",
941 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
942 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
943 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
944 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
945 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
947 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
949 beginbox(&cp, "Telnet protocol adjustments",
950 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
951 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
952 "&BSD (commonplace)", IDC_EMBSD,
953 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
956 treeview_insert(&tvfaff, 1, "Telnet");
960 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
961 if (backends[2].backend != NULL) {
963 ctlposinit(&cp, hwnd, 80, 3, 13);
965 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
966 beginbox(&cp, "Data to send to the server",
967 IDC_BOX_SSH1, IDC_BOXT_SSH1);
969 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
972 beginbox(&cp, "Authentication options",
973 IDC_BOX_SSH2, IDC_BOXT_SSH2);
974 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
976 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
977 editbutton(&cp, "Private &key file for authentication:",
978 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
980 beginbox(&cp, "Protocol options",
981 IDC_BOX_SSH3, IDC_BOXT_SSH3);
982 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
983 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
984 radioline(&cp, "Preferred SSH protocol version:",
985 IDC_SSHPROTSTATIC, 2,
986 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
987 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
988 "&3DES", IDC_CIPHER3DES,
989 "&Blowfish", IDC_CIPHERBLOWF,
990 "&DES", IDC_CIPHERDES, NULL);
991 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
995 treeview_insert(&tvfaff, 1, "SSH");
999 init_dlg_ctrls(hwnd);
1000 for (i = 0; i < nsessions; i++)
1001 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1002 0, (LPARAM) (sessions[i]));
1005 * Hide all the controls to start with.
1007 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1010 * Put the treeview selection on to the Session panel. This
1011 * should also cause unhiding of the relevant controls.
1013 TreeView_SelectItem(treeview, hsession);
1016 * Set focus into the first available control.
1020 ctl = GetDlgItem(hwnd, IDC_HOST);
1021 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1025 SetWindowLong(hwnd, GWL_USERDATA, 1);
1029 * Button release should trigger WM_OK if there was a
1030 * previous double click on the session list.
1034 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1037 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1038 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1039 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1043 item.pszText = buffer;
1044 item.cchTextMax = sizeof(buffer);
1045 item.mask = TVIF_TEXT;
1046 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1047 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1048 if (!strcmp(buffer, "Session"))
1049 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1050 if (!strcmp(buffer, "Keyboard"))
1051 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1052 if (!strcmp(buffer, "Terminal"))
1053 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1054 if (!strcmp(buffer, "Window"))
1055 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1056 if (!strcmp(buffer, "Appearance"))
1057 hide(hwnd, FALSE, appearancepanelstart, appearancepanelend);
1058 if (!strcmp(buffer, "Connection"))
1059 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1060 if (!strcmp(buffer, "Telnet"))
1061 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1062 if (!strcmp(buffer, "SSH"))
1063 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1064 if (!strcmp(buffer, "Selection"))
1065 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1066 if (!strcmp(buffer, "Colours"))
1067 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1068 if (!strcmp(buffer, "Translation"))
1069 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1071 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1077 * Only process WM_COMMAND once the dialog is fully formed.
1079 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1082 EndDialog (hwnd, 1);
1087 EndDialog (hwnd, 0);
1089 case IDC_PROTTELNET:
1092 if (HIWORD(wParam) == BN_CLICKED ||
1093 HIWORD(wParam) == BN_DOUBLECLICKED) {
1094 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1095 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1096 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1097 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1098 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1099 cfg.port = i ? 22 : 23;
1100 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1105 if (HIWORD(wParam) == EN_CHANGE)
1106 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1107 sizeof(cfg.host)-1);
1110 if (HIWORD(wParam) == EN_CHANGE) {
1111 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1112 if (isdigit(portname[0]))
1113 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1115 service = getservbyname(portname, NULL);
1116 if (service) cfg.port = ntohs(service->s_port);
1122 if (HIWORD(wParam) == EN_CHANGE) {
1123 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1125 GetDlgItemText (hwnd, IDC_SESSEDIT,
1126 savedsession, sizeof(savedsession)-1);
1127 savedsession[sizeof(savedsession)-1] = '\0';
1131 if (HIWORD(wParam) == BN_CLICKED ||
1132 HIWORD(wParam) == BN_DOUBLECLICKED) {
1137 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1139 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1140 LB_GETCURSEL, 0, 0);
1145 strcpy (str, sessions[n]);
1147 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1148 get_sesslist (FALSE);
1149 get_sesslist (TRUE);
1150 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1152 for (i = 0; i < nsessions; i++)
1153 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1154 0, (LPARAM) (sessions[i]));
1155 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1161 if (LOWORD(wParam) == IDC_SESSLOAD &&
1162 HIWORD(wParam) != BN_CLICKED &&
1163 HIWORD(wParam) != BN_DOUBLECLICKED)
1165 if (LOWORD(wParam) == IDC_SESSLIST &&
1166 HIWORD(wParam) != LBN_DBLCLK)
1169 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1170 LB_GETCURSEL, 0, 0);
1176 isdef = !strcmp(sessions[n], "Default Settings");
1177 load_settings (sessions[n], !isdef, &cfg);
1178 init_dlg_ctrls(hwnd);
1180 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1182 SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1184 if (LOWORD(wParam) == IDC_SESSLIST) {
1186 * A double-click on a saved session should
1187 * actually start the session, not just load it.
1188 * Unless it's Default Settings or some other
1189 * host-less set of saved settings.
1198 if (HIWORD(wParam) == BN_CLICKED ||
1199 HIWORD(wParam) == BN_DOUBLECLICKED) {
1200 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1201 LB_GETCURSEL, 0, 0);
1202 if (n == LB_ERR || n == 0) {
1206 del_settings(sessions[n]);
1207 get_sesslist (FALSE);
1208 get_sesslist (TRUE);
1209 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1211 for (i = 0; i < nsessions; i++)
1212 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1213 0, (LPARAM) (sessions[i]));
1214 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1218 if (HIWORD(wParam) == EN_CHANGE)
1219 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1223 if (HIWORD(wParam) == BN_CLICKED ||
1224 HIWORD(wParam) == BN_DOUBLECLICKED)
1225 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1229 if (HIWORD(wParam) == BN_CLICKED ||
1230 HIWORD(wParam) == BN_DOUBLECLICKED)
1231 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1234 if (HIWORD(wParam) == BN_CLICKED ||
1235 HIWORD(wParam) == BN_DOUBLECLICKED)
1239 if (HIWORD(wParam) == BN_CLICKED ||
1240 HIWORD(wParam) == BN_DOUBLECLICKED)
1245 if (HIWORD(wParam) == BN_CLICKED ||
1246 HIWORD(wParam) == BN_DOUBLECLICKED)
1247 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1251 if (HIWORD(wParam) == BN_CLICKED ||
1252 HIWORD(wParam) == BN_DOUBLECLICKED) {
1253 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1254 cfg.nethack_keypad = FALSE;
1258 if (HIWORD(wParam) == BN_CLICKED ||
1259 HIWORD(wParam) == BN_DOUBLECLICKED) {
1260 cfg.app_keypad = FALSE;
1261 cfg.nethack_keypad = TRUE;
1266 if (HIWORD(wParam) == BN_CLICKED ||
1267 HIWORD(wParam) == BN_DOUBLECLICKED)
1268 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1271 if (HIWORD(wParam) == BN_CLICKED ||
1272 HIWORD(wParam) == BN_DOUBLECLICKED)
1273 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1276 if (HIWORD(wParam) == BN_CLICKED ||
1277 HIWORD(wParam) == BN_DOUBLECLICKED)
1278 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1281 if (HIWORD(wParam) == BN_CLICKED ||
1282 HIWORD(wParam) == BN_DOUBLECLICKED)
1283 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1286 if (HIWORD(wParam) == BN_CLICKED ||
1287 HIWORD(wParam) == BN_DOUBLECLICKED)
1288 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1291 if (HIWORD(wParam) == BN_CLICKED ||
1292 HIWORD(wParam) == BN_DOUBLECLICKED)
1293 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1296 if (HIWORD(wParam) == BN_CLICKED ||
1297 HIWORD(wParam) == BN_DOUBLECLICKED)
1298 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1300 case IDC_ALWAYSONTOP:
1301 if (HIWORD(wParam) == BN_CLICKED ||
1302 HIWORD(wParam) == BN_DOUBLECLICKED)
1303 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1306 if (HIWORD(wParam) == BN_CLICKED ||
1307 HIWORD(wParam) == BN_DOUBLECLICKED)
1308 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1310 case IDC_SCROLLDISP:
1311 if (HIWORD(wParam) == BN_CLICKED ||
1312 HIWORD(wParam) == BN_DOUBLECLICKED)
1313 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1315 case IDC_COMPOSEKEY:
1316 if (HIWORD(wParam) == BN_CLICKED ||
1317 HIWORD(wParam) == BN_DOUBLECLICKED)
1318 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1321 if (HIWORD(wParam) == BN_CLICKED ||
1322 HIWORD(wParam) == BN_DOUBLECLICKED)
1323 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1326 if (HIWORD(wParam) == BN_CLICKED ||
1327 HIWORD(wParam) == BN_DOUBLECLICKED)
1328 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1331 if (HIWORD(wParam) == BN_CLICKED ||
1332 HIWORD(wParam) == BN_DOUBLECLICKED)
1333 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1336 if (HIWORD(wParam) == EN_CHANGE)
1337 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1340 if (HIWORD(wParam) == EN_CHANGE)
1341 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1344 if (HIWORD(wParam) == EN_CHANGE)
1345 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1347 case IDC_CHOOSEFONT:
1348 lf.lfHeight = cfg.fontheight;
1349 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1350 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1351 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1352 lf.lfCharSet = cfg.fontcharset;
1353 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1354 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1355 lf.lfQuality = DEFAULT_QUALITY;
1356 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1357 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1358 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1360 cf.lStructSize = sizeof(cf);
1361 cf.hwndOwner = hwnd;
1363 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1364 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1366 if (ChooseFont (&cf)) {
1367 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1368 cfg.font[sizeof(cfg.font)-1] = '\0';
1369 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1370 cfg.fontcharset = lf.lfCharSet;
1371 cfg.fontheight = lf.lfHeight;
1372 fmtfont (fontstatic);
1373 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1377 if (HIWORD(wParam) == BN_CLICKED ||
1378 HIWORD(wParam) == BN_DOUBLECLICKED)
1379 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1382 if (HIWORD(wParam) == BN_CLICKED ||
1383 HIWORD(wParam) == BN_DOUBLECLICKED)
1384 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1387 if (HIWORD(wParam) == BN_CLICKED ||
1388 HIWORD(wParam) == BN_DOUBLECLICKED)
1389 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1392 if (HIWORD(wParam) == BN_CLICKED ||
1393 HIWORD(wParam) == BN_DOUBLECLICKED)
1394 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1397 if (HIWORD(wParam) == BN_CLICKED ||
1398 HIWORD(wParam) == BN_DOUBLECLICKED)
1399 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1402 if (HIWORD(wParam) == BN_CLICKED ||
1403 HIWORD(wParam) == BN_DOUBLECLICKED)
1404 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1407 if (HIWORD(wParam) == BN_CLICKED ||
1408 HIWORD(wParam) == BN_DOUBLECLICKED)
1409 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1412 if (HIWORD(wParam) == EN_CHANGE)
1413 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1414 sizeof(cfg.wintitle)-1);
1417 if (HIWORD(wParam) == BN_CLICKED ||
1418 HIWORD(wParam) == BN_DOUBLECLICKED)
1419 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1422 if (HIWORD(wParam) == BN_CLICKED ||
1423 HIWORD(wParam) == BN_DOUBLECLICKED)
1424 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1427 if (HIWORD(wParam) == EN_CHANGE)
1428 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1429 sizeof(cfg.termtype)-1);
1432 if (HIWORD(wParam) == EN_CHANGE)
1433 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1434 sizeof(cfg.termspeed)-1);
1437 if (HIWORD(wParam) == EN_CHANGE)
1438 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1439 sizeof(cfg.username)-1);
1443 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1446 if (HIWORD(wParam) == BN_CLICKED ||
1447 HIWORD(wParam) == BN_DOUBLECLICKED) {
1448 char str[sizeof(cfg.environmt)];
1450 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1455 p = str + strlen(str);
1457 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1467 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1469 p[strlen(str)+1] = '\0';
1470 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1472 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1473 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1475 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1476 MB_OK | MB_ICONERROR);
1481 if (HIWORD(wParam) != BN_CLICKED &&
1482 HIWORD(wParam) != BN_DOUBLECLICKED)
1484 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1490 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1515 if (HIWORD(wParam) == BN_CLICKED ||
1516 HIWORD(wParam) == BN_DOUBLECLICKED)
1517 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1520 if (HIWORD(wParam) == BN_CLICKED ||
1521 HIWORD(wParam) == BN_DOUBLECLICKED)
1522 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1525 if (HIWORD(wParam) == BN_CLICKED ||
1526 HIWORD(wParam) == BN_DOUBLECLICKED)
1527 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1530 if (HIWORD(wParam) == BN_CLICKED ||
1531 HIWORD(wParam) == BN_DOUBLECLICKED)
1532 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1534 case IDC_CIPHER3DES:
1535 case IDC_CIPHERBLOWF:
1537 if (HIWORD(wParam) == BN_CLICKED ||
1538 HIWORD(wParam) == BN_DOUBLECLICKED) {
1539 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1540 cfg.cipher = CIPHER_3DES;
1541 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1542 cfg.cipher = CIPHER_BLOWFISH;
1543 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1544 cfg.cipher = CIPHER_DES;
1549 if (HIWORD(wParam) == BN_CLICKED ||
1550 HIWORD(wParam) == BN_DOUBLECLICKED) {
1551 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1553 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1558 if (HIWORD(wParam) == BN_CLICKED ||
1559 HIWORD(wParam) == BN_DOUBLECLICKED)
1560 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1563 if (HIWORD(wParam) == EN_CHANGE)
1564 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1565 sizeof(cfg.keyfile)-1);
1568 if (HIWORD(wParam) == EN_CHANGE)
1569 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1570 sizeof(cfg.remote_cmd)-1);
1573 memset(&of, 0, sizeof(of));
1574 #ifdef OPENFILENAME_SIZE_VERSION_400
1575 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1577 of.lStructSize = sizeof(of);
1579 of.hwndOwner = hwnd;
1580 of.lpstrFilter = "All Files\0*\0\0\0";
1581 of.lpstrCustomFilter = NULL;
1582 of.nFilterIndex = 1;
1583 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1584 of.nMaxFile = sizeof(filename);
1585 of.lpstrFileTitle = NULL;
1586 of.lpstrInitialDir = NULL;
1587 of.lpstrTitle = "Select Public Key File";
1589 if (GetOpenFileName(&of)) {
1590 strcpy(cfg.keyfile, filename);
1591 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1596 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1602 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1607 for (i=0; i<256; i++)
1608 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1611 cfg.wordness[i] = n;
1612 SendDlgItemMessage (hwnd, IDC_CCLIST,
1613 LB_DELETESTRING, i, 0);
1614 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1615 (i>=0x21 && i != 0x7F) ? i : ' ',
1617 SendDlgItemMessage (hwnd, IDC_CCLIST,
1624 case IDC_BOLDCOLOUR:
1625 if (HIWORD(wParam) == BN_CLICKED ||
1626 HIWORD(wParam) == BN_DOUBLECLICKED) {
1628 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1629 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1630 if (n != 12+10*cfg.bold_colour) {
1632 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1633 LB_DELETESTRING, i, 0);
1634 for (i=0; i<22; i++)
1635 if (cfg.bold_colour || permcolour[i])
1636 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1638 (LPARAM) colours[i]);
1643 if (HIWORD(wParam) == BN_CLICKED ||
1644 HIWORD(wParam) == BN_DOUBLECLICKED)
1645 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1647 case IDC_COLOURLIST:
1648 if (HIWORD(wParam) == LBN_DBLCLK ||
1649 HIWORD(wParam) == LBN_SELCHANGE) {
1650 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1652 if (!cfg.bold_colour)
1653 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1654 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1655 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1656 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1660 if (HIWORD(wParam) == BN_CLICKED ||
1661 HIWORD(wParam) == BN_DOUBLECLICKED) {
1662 static CHOOSECOLOR cc;
1663 static DWORD custom[16] = {0}; /* zero initialisers */
1664 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1666 if (!cfg.bold_colour)
1667 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1668 cc.lStructSize = sizeof(cc);
1669 cc.hwndOwner = hwnd;
1670 cc.hInstance = (HWND)hinst;
1671 cc.lpCustColors = custom;
1672 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1674 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1675 if (ChooseColor(&cc)) {
1677 (unsigned char) (cc.rgbResult & 0xFF);
1679 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1681 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1682 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1684 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1686 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1692 case IDC_KOI8WIN1251:
1693 case IDC_88592WIN1250:
1694 case IDC_88592CP852:
1695 cfg.xlat_enablekoiwin =
1696 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1697 cfg.xlat_88592w1250 =
1698 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1699 cfg.xlat_88592cp852 =
1700 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1702 case IDC_CAPSLOCKCYR:
1703 if (HIWORD(wParam) == BN_CLICKED ||
1704 HIWORD(wParam) == BN_DOUBLECLICKED) {
1705 cfg.xlat_capslockcyr =
1706 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1709 case IDC_VTXWINDOWS:
1714 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1715 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1716 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1722 EndDialog (hwnd, 0);
1725 /* Grrr Explorer will maximize Dialogs! */
1727 if (wParam == SIZE_MAXIMIZED)
1734 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1735 WPARAM wParam, LPARAM lParam) {
1736 static HWND page = NULL;
1738 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1740 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1741 EnableWindow(hwnd, 0);
1742 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1743 GetParent(hwnd), AboutProc);
1744 EnableWindow(hwnd, 1);
1745 SetActiveWindow(hwnd);
1747 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1750 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1751 WPARAM wParam, LPARAM lParam) {
1753 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1756 void defuse_showwindow(void) {
1758 * Work around the fact that the app's first call to ShowWindow
1759 * will ignore the default in favour of the shell-provided
1764 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1766 ShowWindow(hwnd, SW_HIDE);
1767 DestroyWindow(hwnd);
1771 int do_config (void) {
1775 savedsession[0] = '\0';
1776 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1777 get_sesslist(FALSE);
1782 int do_reconfig (HWND hwnd) {
1786 backup_cfg = cfg; /* structure copy */
1787 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1789 cfg = backup_cfg; /* structure copy */
1796 void logevent (char *string) {
1797 if (nevents >= negsize) {
1799 events = srealloc (events, negsize * sizeof(*events));
1801 events[nevents] = smalloc(1+strlen(string));
1802 strcpy (events[nevents], string);
1806 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1808 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1809 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1813 void showeventlog (HWND hwnd) {
1815 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1817 ShowWindow (logbox, SW_SHOWNORMAL);
1821 void showabout (HWND hwnd) {
1823 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1825 ShowWindow (abtbox, SW_SHOWNORMAL);
1829 void verify_ssh_host_key(char *host, int port, char *keytype,
1830 char *keystr, char *fingerprint) {
1833 static const char absentmsg[] =
1834 "The server's host key is not cached in the registry. You\n"
1835 "have no guarantee that the server is the computer you\n"
1837 "The server's key fingerprint is:\n"
1839 "If you trust this host, hit Yes to add the key to\n"
1840 "PuTTY's cache and carry on connecting.\n"
1841 "If you do not trust this host, hit No to abandon the\n"
1844 static const char wrongmsg[] =
1845 "WARNING - POTENTIAL SECURITY BREACH!\n"
1847 "The server's host key does not match the one PuTTY has\n"
1848 "cached in the registry. This means that either the\n"
1849 "server administrator has changed the host key, or you\n"
1850 "have actually connected to another computer pretending\n"
1851 "to be the server.\n"
1852 "The new key fingerprint is:\n"
1854 "If you were expecting this change and trust the new key,\n"
1855 "hit Yes to update PuTTY's cache and continue connecting.\n"
1856 "If you want to carry on connecting but without updating\n"
1857 "the cache, hit No.\n"
1858 "If you want to abandon the connection completely, hit\n"
1859 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1862 static const char mbtitle[] = "PuTTY Security Alert";
1865 char message[160+ /* sensible fingerprint max size */
1866 (sizeof(absentmsg) > sizeof(wrongmsg) ?
1867 sizeof(absentmsg) : sizeof(wrongmsg))];
1870 * Verify the key against the registry.
1872 ret = verify_host_key(host, port, keytype, keystr);
1874 if (ret == 0) /* success - key matched OK */
1876 if (ret == 2) { /* key was different */
1878 sprintf(message, wrongmsg, fingerprint);
1879 mbret = MessageBox(NULL, message, mbtitle,
1880 MB_ICONWARNING | MB_YESNOCANCEL);
1882 store_host_key(host, port, keytype, keystr);
1883 if (mbret == IDCANCEL)
1886 if (ret == 1) { /* key was absent */
1888 sprintf(message, absentmsg, fingerprint);
1889 mbret = MessageBox(NULL, message, mbtitle,
1890 MB_ICONWARNING | MB_YESNO);
1893 store_host_key(host, port, keytype, keystr);