13 static char **events = NULL;
14 static int nevents = 0, negsize = 0;
16 static HWND logbox = NULL, abtbox = NULL;
20 void force_normal(HWND hwnd)
22 static int recurse = 0;
29 wp.length = sizeof(wp);
30 if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED)
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,
273 appearancepanelstart,
274 IDC_TITLE_APPEARANCE,
292 connectionpanelstart,
293 IDC_TITLE_CONNECTION,
388 translationpanelstart,
389 IDC_TITLE_TRANSLATION,
390 IDC_BOX_TRANSLATION1,
391 IDC_BOX_TRANSLATION2,
392 IDC_BOX_TRANSLATION3,
417 static const char *const colours[] = {
418 "Default Foreground", "Default Bold Foreground",
419 "Default Background", "Default Bold Background",
420 "Cursor Text", "Cursor Colour",
421 "ANSI Black", "ANSI Black Bold",
422 "ANSI Red", "ANSI Red Bold",
423 "ANSI Green", "ANSI Green Bold",
424 "ANSI Yellow", "ANSI Yellow Bold",
425 "ANSI Blue", "ANSI Blue Bold",
426 "ANSI Magenta", "ANSI Magenta Bold",
427 "ANSI Cyan", "ANSI Cyan Bold",
428 "ANSI White", "ANSI White Bold"
430 static const int permcolour[] = {
431 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
432 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
433 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
436 static void fmtfont (char *buf) {
437 sprintf (buf, "Font: %s, ", cfg.font);
439 strcat(buf, "bold, ");
440 if (cfg.fontheight == 0)
441 strcat (buf, "default height");
443 sprintf (buf+strlen(buf), "%d-%s",
444 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
445 (cfg.fontheight < 0 ? "pixel" : "point"));
448 static void init_dlg_ctrls(HWND hwnd) {
450 char fontstatic[256];
452 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
453 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
456 n = SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_GETCOUNT, 0, 0);
458 SendDlgItemMessage (hwnd, IDC_SESSLIST,
459 LB_DELETESTRING, i, 0);
460 for (i = 0; i < nsessions; i++)
461 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
462 0, (LPARAM) (sessions[i]));
464 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
465 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
466 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
467 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET :
468 cfg.protocol==PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW );
469 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
471 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
472 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
473 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
474 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
475 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
476 cfg.funky_type == 0 ? IDC_FUNCTILDE :
477 cfg.funky_type == 1 ? IDC_FUNCLINUX :
478 cfg.funky_type == 2 ? IDC_FUNCXTERM :
479 cfg.funky_type == 3 ? IDC_FUNCVT400 :
481 CheckDlgButton (hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
482 CheckDlgButton (hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
483 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
484 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
485 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
486 cfg.nethack_keypad ? IDC_KPNH :
487 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
488 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
489 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
490 CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
491 CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
492 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
493 CheckDlgButton (hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
494 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
495 CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
497 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
498 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
499 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
500 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
501 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
502 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
503 fmtfont (fontstatic);
504 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
505 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
506 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
507 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
509 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
510 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
511 CheckDlgButton (hwnd, IDC_HIDEMOUSE, cfg.hide_mouseptr);
512 CheckRadioButton (hwnd, IDC_CURBLOCK, IDC_CURVERT,
513 cfg.cursor_type==0 ? IDC_CURBLOCK :
514 cfg.cursor_type==1 ? IDC_CURUNDER : IDC_CURVERT);
515 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
516 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
517 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
518 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
519 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
521 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
522 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
523 SetDlgItemText (hwnd, IDC_R_TSEDIT, cfg.termspeed);
524 SetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername);
525 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
526 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
527 CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
528 cfg.logtype == 0 ? IDC_LSTATOFF :
529 cfg.logtype == 1 ? IDC_LSTATASCII :
532 char *p = cfg.environmt;
534 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
539 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
540 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
542 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
543 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
544 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
545 CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
546 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
547 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
548 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
549 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
550 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
552 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
553 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
554 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
555 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
556 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
558 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
559 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
561 static int tabs[4] = {25, 61, 96, 128};
562 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
565 for (i=0; i<256; i++) {
567 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
568 (i>=0x21 && i != 0x7F) ? i : ' ',
570 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
574 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
575 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
578 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
580 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
581 LB_DELETESTRING, i, 0);
583 if (cfg.bold_colour || permcolour[i])
584 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
585 (LPARAM) colours[i]);
587 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
588 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
589 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
590 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
592 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
593 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
594 cfg.xlat_88592cp852 ? IDC_88592CP852 :
595 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
597 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
598 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
599 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
600 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
601 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
604 CheckDlgButton (hwnd, IDC_X11_FORWARD, cfg.x11_forward);
605 SetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display);
608 struct treeview_faff {
613 static HTREEITEM treeview_insert(struct treeview_faff *faff,
614 int level, char *text) {
618 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
619 ins.hInsertAfter = faff->lastat[level];
620 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
621 #define INSITEM DUMMYUNIONNAME.item
625 ins.INSITEM.mask = TVIF_TEXT;
626 ins.INSITEM.pszText = text;
627 newitem = TreeView_InsertItem(faff->treeview, &ins);
629 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
630 faff->lastat[level] = newitem;
631 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
636 * Create the panelfuls of controls in the configuration box.
638 static void create_controls(HWND hwnd, int dlgtype, int panel) {
639 if (panel == sessionpanelstart) {
640 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
642 ctlposinit(&cp, hwnd, 80, 3, 13);
643 bartitle(&cp, "Basic options for your PuTTY session",
646 beginbox(&cp, "Specify your connection by host name",
649 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
650 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
651 if (backends[3].backend == NULL) {
652 /* this is PuTTYtel, so only three protocols available */
653 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
655 "&Telnet", IDC_PROTTELNET,
656 "R&login", IDC_PROTRLOGIN, NULL);
658 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
660 "&Telnet", IDC_PROTTELNET,
661 "R&login", IDC_PROTRLOGIN,
670 beginbox(&cp, "Load, save or delete a stored session",
672 sesssaver(&cp, "Sav&ed Sessions",
673 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
674 "&Load", IDC_SESSLOAD,
675 "&Save", IDC_SESSSAVE,
676 "&Delete", IDC_SESSDEL, NULL);
679 beginbox(&cp, NULL, IDC_BOX_SESSION3);
680 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
684 if (panel == terminalpanelstart) {
685 /* The Terminal panel. Accelerators used: [acgo] &dflbenuw */
687 ctlposinit(&cp, hwnd, 80, 3, 13);
688 bartitle(&cp, "Options controlling the terminal emulation",
690 beginbox(&cp, "Set various terminal options",
692 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
693 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
694 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
695 checkbox(&cp, "&Beep enabled", IDC_BEEP);
696 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
697 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
698 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
701 beginbox(&cp, "Control session logging",
704 "Session logging:", IDC_LSTATSTATIC,
705 "Logging turned &off completely", IDC_LSTATOFF,
706 "Log printable output only", IDC_LSTATASCII,
707 "Log all session output", IDC_LSTATRAW, NULL);
708 editbutton(&cp, "Log &file name:",
709 IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
714 if (panel == keyboardpanelstart) {
715 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmietu */
717 ctlposinit(&cp, hwnd, 80, 3, 13);
718 bartitle(&cp, "Options controlling the effects of keys",
720 beginbox(&cp, "Change the sequences sent by:",
722 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
723 "Control-&H", IDC_DEL008,
724 "Control-&? (127)", IDC_DEL127, NULL);
725 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
726 "&Standard", IDC_HOMETILDE,
727 "&rxvt", IDC_HOMERXVT, NULL);
728 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
729 "ESC[n&~", IDC_FUNCTILDE,
730 "&Linux", IDC_FUNCLINUX,
731 "&Xterm R6", IDC_FUNCXTERM,
732 "&VT400", IDC_FUNCVT400, NULL);
734 beginbox(&cp, "Application keypad settings:",
737 "Application c&ursor keys totally disabled",
739 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
740 "&Normal", IDC_CURNORMAL,
741 "A&pplication", IDC_CURAPPLIC, NULL);
743 "Application ke&ypad keys totally disabled",
745 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
746 "Nor&mal", IDC_KPNORMAL,
747 "Appl&ication", IDC_KPAPPLIC,
748 "N&etHack", IDC_KPNH, NULL);
750 beginbox(&cp, "Enable extra keyboard features:",
752 checkbox(&cp, "Application and AltGr ac&t as Compose key",
757 if (panel == windowpanelstart) {
758 /* The Window panel. Accelerators used: [acgo] bsdkw4ylpt */
760 ctlposinit(&cp, hwnd, 80, 3, 13);
761 bartitle(&cp, "Options controlling PuTTY's window",
763 beginbox(&cp, "Set the size of the window",
766 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
767 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
769 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
771 beginbox(&cp, "Control the scrollback in the window",
773 staticedit(&cp, "Lines of &scrollback",
774 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
775 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
776 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
777 checkbox(&cp, "Reset scrollback on dis&play activity",
780 beginbox(&cp, NULL, IDC_BOX_WINDOW3);
781 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
782 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
783 checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
784 checkbox(&cp, "System menu appears on A< alone", IDC_ALTONLY);
785 checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
789 if (panel == appearancepanelstart) {
790 /* The Appearance panel. Accelerators used: [acgo] rmkhtibluv */
792 ctlposinit(&cp, hwnd, 80, 3, 13);
793 bartitle(&cp, "Options controlling PuTTY's appearance",
794 IDC_TITLE_APPEARANCE);
795 beginbox(&cp, "Adjust the use of the cursor",
796 IDC_BOX_APPEARANCE1);
797 radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
798 "B&lock", IDC_CURBLOCK,
799 "&Underline", IDC_CURUNDER,
800 "&Vertical line", IDC_CURVERT,
802 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
804 beginbox(&cp, "Set the font used in the terminal window",
805 IDC_BOX_APPEARANCE2);
806 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
808 beginbox(&cp, "Adjust the use of the window title",
809 IDC_BOX_APPEARANCE3);
811 "Window &title:", IDC_WINTITLE,
812 IDC_WINEDIT, 100, NULL);
813 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
815 beginbox(&cp, "Adjust the use of the mouse pointer",
816 IDC_BOX_APPEARANCE4);
817 checkbox(&cp, "Hide mouse &pointer when typing in window",
822 if (panel == translationpanelstart) {
823 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
825 ctlposinit(&cp, hwnd, 80, 3, 13);
826 bartitle(&cp, "Options controlling character set translation",
827 IDC_TITLE_TRANSLATION);
828 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
829 IDC_BOX_TRANSLATION1);
831 "Handling of line drawing characters:", IDC_VTSTATIC,
832 "Font has &XWindows encoding", IDC_VTXWINDOWS,
833 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
834 "Use font in O&EM mode only", IDC_VTOEMONLY,
835 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
836 IDC_VTPOORMAN, NULL);
838 beginbox(&cp, "Enable character set translation on received data",
839 IDC_BOX_TRANSLATION2);
841 "Character set translation:", IDC_XLATSTATIC,
843 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
844 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
845 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
847 beginbox(&cp, "Enable character set translation on input data",
848 IDC_BOX_TRANSLATION3);
849 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
854 if (panel == selectionpanelstart) {
855 /* The Selection panel. Accelerators used: [acgo] wxst */
857 ctlposinit(&cp, hwnd, 80, 3, 13);
858 bartitle(&cp, "Options controlling copy and paste",
859 IDC_TITLE_SELECTION);
860 beginbox(&cp, "Control which mouse button does which thing",
862 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
863 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
864 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
867 beginbox(&cp, "Control the select-one-word-at-a-time mode",
869 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
870 "&Set", IDC_CCSET, IDC_CCEDIT,
871 "&to class", IDC_CCSTATIC2);
875 if (panel == colourspanelstart) {
876 /* The Colours panel. Accelerators used: [acgo] blum */
878 ctlposinit(&cp, hwnd, 80, 3, 13);
879 bartitle(&cp, "Options controlling use of colours",
881 beginbox(&cp, "General options for colour usage",
883 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
884 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
886 beginbox(&cp, "Adjust the precise colours PuTTY displays",
888 colouredit(&cp, "Select a colo&ur and then click to modify it:",
889 IDC_COLOURSTATIC, IDC_COLOURLIST,
890 "&Modify...", IDC_CHANGE,
891 "Red:", IDC_RSTATIC, IDC_RVALUE,
892 "Green:", IDC_GSTATIC, IDC_GVALUE,
893 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
897 if (panel == connectionpanelstart) {
898 /* The Connection panel. Accelerators used: [acgo] tuk */
900 ctlposinit(&cp, hwnd, 80, 3, 13);
901 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
903 beginbox(&cp, "Data to send to the server",
904 IDC_BOX_CONNECTION1);
905 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
906 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
909 beginbox(&cp, "Sending of null packets to keep session active",
910 IDC_BOX_CONNECTION2);
911 staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
912 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
916 if (panel == telnetpanelstart) {
917 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
919 ctlposinit(&cp, hwnd, 80, 3, 13);
921 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
922 beginbox(&cp, "Data to send to the server",
924 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
925 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
926 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
927 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
929 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
931 beginbox(&cp, "Telnet protocol adjustments",
933 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
934 "&BSD (commonplace)", IDC_EMBSD,
935 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
940 if (panel == rloginpanelstart) {
941 /* The Rlogin panel. Accelerators used: [acgo] sl */
943 ctlposinit(&cp, hwnd, 80, 3, 13);
945 bartitle(&cp, "Options controlling Rlogin connections", IDC_TITLE_RLOGIN);
946 beginbox(&cp, "Data to send to the server",
948 staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC, IDC_R_TSEDIT, 50);
949 staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC, IDC_RLLUSEREDIT, 50);
954 if (panel == sshpanelstart) {
955 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
957 ctlposinit(&cp, hwnd, 80, 3, 13);
959 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
960 beginbox(&cp, "Data to send to the server",
963 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
966 beginbox(&cp, "Authentication options",
968 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
970 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
971 editbutton(&cp, "Private &key file for authentication:",
972 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
974 beginbox(&cp, "Protocol options",
976 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
977 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
978 radioline(&cp, "Preferred SSH protocol version:",
979 IDC_SSHPROTSTATIC, 2,
980 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
981 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
982 "&3DES", IDC_CIPHER3DES,
983 "&Blowfish", IDC_CIPHERBLOWF,
984 "&DES", IDC_CIPHERDES, NULL);
985 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
991 if (panel == tunnelspanelstart) {
992 /* The Tunnels panel. Accelerators used: [acgo] ex */
994 ctlposinit(&cp, hwnd, 80, 3, 13);
996 bartitle(&cp, "Options controlling SSH tunnelling",
998 beginbox(&cp, "X11 forwarding options",
1000 checkbox(&cp, "&Enable X11 forwarding",
1002 multiedit(&cp, "&X display location", IDC_X11_DISPSTATIC,
1003 IDC_X11_DISPLAY, 50, NULL);
1010 * This function is the configuration box.
1012 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1013 WPARAM wParam, LPARAM lParam,
1016 struct treeview_faff tvfaff;
1019 char filename[sizeof(cfg.keyfile)];
1022 char fontstatic[256];
1024 struct servent * service;
1030 SetWindowLong(hwnd, GWL_USERDATA, 0);
1032 * Centre the window.
1034 { /* centre the window */
1037 hw = GetDesktopWindow();
1038 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1039 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1040 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1041 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1045 * Create the tree view.
1052 r.left = 3; r.right = r.left + 75;
1053 r.top = 3; r.bottom = r.top + 10;
1054 MapDialogRect(hwnd, &r);
1055 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1056 WS_CHILD | WS_VISIBLE,
1058 r.right-r.left, r.bottom-r.top,
1059 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1060 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1061 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1063 r.left = 3; r.right = r.left + 75;
1064 r.top = 13; r.bottom = r.top + 206;
1065 MapDialogRect(hwnd, &r);
1066 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1067 WS_CHILD | WS_VISIBLE |
1068 WS_TABSTOP | TVS_HASLINES |
1069 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1070 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1072 r.right-r.left, r.bottom-r.top,
1073 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1074 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1075 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1076 tvfaff.treeview = treeview;
1077 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1081 * Set up the tree view contents.
1083 hsession = treeview_insert(&tvfaff, 0, "Session");
1084 treeview_insert(&tvfaff, 0, "Terminal");
1085 treeview_insert(&tvfaff, 1, "Keyboard");
1086 treeview_insert(&tvfaff, 0, "Window");
1087 treeview_insert(&tvfaff, 1, "Appearance");
1088 treeview_insert(&tvfaff, 1, "Translation");
1089 treeview_insert(&tvfaff, 1, "Selection");
1090 treeview_insert(&tvfaff, 1, "Colours");
1091 treeview_insert(&tvfaff, 0, "Connection");
1093 treeview_insert(&tvfaff, 1, "Telnet");
1094 treeview_insert(&tvfaff, 1, "Rlogin");
1095 if (backends[3].backend != NULL) {
1096 treeview_insert(&tvfaff, 1, "SSH");
1097 treeview_insert(&tvfaff, 2, "Tunnels");
1102 * Put the treeview selection on to the Session panel. This
1103 * should also cause creation of the relevant controls.
1105 TreeView_SelectItem(treeview, hsession);
1108 * Set focus into the first available control.
1112 ctl = GetDlgItem(hwnd, IDC_HOST);
1113 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1117 SetWindowLong(hwnd, GWL_USERDATA, 1);
1121 * Button release should trigger WM_OK if there was a
1122 * previous double click on the session list.
1126 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1129 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1130 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1131 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1136 item.pszText = buffer;
1137 item.cchTextMax = sizeof(buffer);
1138 item.mask = TVIF_TEXT;
1139 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1140 for (j = controlstartvalue; j < controlendvalue; j++) {
1141 HWND item = GetDlgItem(hwnd, j);
1143 DestroyWindow(item);
1145 if (!strcmp(buffer, "Session"))
1146 create_controls(hwnd, dlgtype, sessionpanelstart);
1147 if (!strcmp(buffer, "Keyboard"))
1148 create_controls(hwnd, dlgtype, keyboardpanelstart);
1149 if (!strcmp(buffer, "Terminal"))
1150 create_controls(hwnd, dlgtype, terminalpanelstart);
1151 if (!strcmp(buffer, "Window"))
1152 create_controls(hwnd, dlgtype, windowpanelstart);
1153 if (!strcmp(buffer, "Appearance"))
1154 create_controls(hwnd, dlgtype, appearancepanelstart);
1155 if (!strcmp(buffer, "Tunnels"))
1156 create_controls(hwnd, dlgtype, tunnelspanelstart);
1157 if (!strcmp(buffer, "Connection"))
1158 create_controls(hwnd, dlgtype, connectionpanelstart);
1159 if (!strcmp(buffer, "Telnet"))
1160 create_controls(hwnd, dlgtype, telnetpanelstart);
1161 if (!strcmp(buffer, "Rlogin"))
1162 create_controls(hwnd, dlgtype, rloginpanelstart);
1163 if (!strcmp(buffer, "SSH"))
1164 create_controls(hwnd, dlgtype, sshpanelstart);
1165 if (!strcmp(buffer, "Selection"))
1166 create_controls(hwnd, dlgtype, selectionpanelstart);
1167 if (!strcmp(buffer, "Colours"))
1168 create_controls(hwnd, dlgtype, colourspanelstart);
1169 if (!strcmp(buffer, "Translation"))
1170 create_controls(hwnd, dlgtype, translationpanelstart);
1172 init_dlg_ctrls(hwnd);
1174 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1180 * Only process WM_COMMAND once the dialog is fully formed.
1182 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1185 EndDialog (hwnd, 1);
1190 EndDialog (hwnd, 0);
1192 case IDC_PROTTELNET:
1193 case IDC_PROTRLOGIN:
1196 if (HIWORD(wParam) == BN_CLICKED ||
1197 HIWORD(wParam) == BN_DOUBLECLICKED) {
1198 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1199 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1200 int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
1201 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN : PROT_RAW ;
1202 if ((cfg.protocol == PROT_SSH && cfg.port != 22) ||
1203 (cfg.protocol == PROT_TELNET && cfg.port != 23) ||
1204 (cfg.protocol == PROT_RLOGIN && cfg.port != 513)) {
1205 cfg.port = i ? 22 : j ? 23 : 513;
1206 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1211 if (HIWORD(wParam) == EN_CHANGE)
1212 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1213 sizeof(cfg.host)-1);
1216 if (HIWORD(wParam) == EN_CHANGE) {
1217 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1218 if (isdigit(portname[0]))
1219 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1221 service = getservbyname(portname, NULL);
1222 if (service) cfg.port = ntohs(service->s_port);
1228 if (HIWORD(wParam) == EN_CHANGE) {
1229 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1231 GetDlgItemText (hwnd, IDC_SESSEDIT,
1232 savedsession, sizeof(savedsession)-1);
1233 savedsession[sizeof(savedsession)-1] = '\0';
1237 if (HIWORD(wParam) == BN_CLICKED ||
1238 HIWORD(wParam) == BN_DOUBLECLICKED) {
1243 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1245 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1246 LB_GETCURSEL, 0, 0);
1251 strcpy (str, sessions[n]);
1253 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1254 get_sesslist (FALSE);
1255 get_sesslist (TRUE);
1256 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1258 for (i = 0; i < nsessions; i++)
1259 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1260 0, (LPARAM) (sessions[i]));
1261 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1267 if (LOWORD(wParam) == IDC_SESSLOAD &&
1268 HIWORD(wParam) != BN_CLICKED &&
1269 HIWORD(wParam) != BN_DOUBLECLICKED)
1271 if (LOWORD(wParam) == IDC_SESSLIST &&
1272 HIWORD(wParam) != LBN_DBLCLK)
1275 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1276 LB_GETCURSEL, 0, 0);
1282 isdef = !strcmp(sessions[n], "Default Settings");
1283 load_settings (sessions[n], !isdef, &cfg);
1284 init_dlg_ctrls(hwnd);
1286 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1288 SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1290 if (LOWORD(wParam) == IDC_SESSLIST) {
1292 * A double-click on a saved session should
1293 * actually start the session, not just load it.
1294 * Unless it's Default Settings or some other
1295 * host-less set of saved settings.
1304 if (HIWORD(wParam) == BN_CLICKED ||
1305 HIWORD(wParam) == BN_DOUBLECLICKED) {
1306 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1307 LB_GETCURSEL, 0, 0);
1308 if (n == LB_ERR || n == 0) {
1312 del_settings(sessions[n]);
1313 get_sesslist (FALSE);
1314 get_sesslist (TRUE);
1315 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1317 for (i = 0; i < nsessions; i++)
1318 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1319 0, (LPARAM) (sessions[i]));
1320 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1324 if (HIWORD(wParam) == EN_CHANGE)
1325 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1329 if (HIWORD(wParam) == BN_CLICKED ||
1330 HIWORD(wParam) == BN_DOUBLECLICKED)
1331 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1335 if (HIWORD(wParam) == BN_CLICKED ||
1336 HIWORD(wParam) == BN_DOUBLECLICKED)
1337 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1340 if (HIWORD(wParam) == BN_CLICKED ||
1341 HIWORD(wParam) == BN_DOUBLECLICKED)
1345 if (HIWORD(wParam) == BN_CLICKED ||
1346 HIWORD(wParam) == BN_DOUBLECLICKED)
1351 if (HIWORD(wParam) == BN_CLICKED ||
1352 HIWORD(wParam) == BN_DOUBLECLICKED)
1353 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1357 if (HIWORD(wParam) == BN_CLICKED ||
1358 HIWORD(wParam) == BN_DOUBLECLICKED) {
1359 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1360 cfg.nethack_keypad = FALSE;
1364 if (HIWORD(wParam) == BN_CLICKED ||
1365 HIWORD(wParam) == BN_DOUBLECLICKED) {
1366 cfg.app_keypad = FALSE;
1367 cfg.nethack_keypad = TRUE;
1372 if (HIWORD(wParam) == BN_CLICKED ||
1373 HIWORD(wParam) == BN_DOUBLECLICKED)
1374 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1377 if (HIWORD(wParam) == BN_CLICKED ||
1378 HIWORD(wParam) == BN_DOUBLECLICKED)
1379 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1382 if (HIWORD(wParam) == BN_CLICKED ||
1383 HIWORD(wParam) == BN_DOUBLECLICKED)
1384 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1387 if (HIWORD(wParam) == BN_CLICKED ||
1388 HIWORD(wParam) == BN_DOUBLECLICKED)
1389 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1392 if (HIWORD(wParam) == BN_CLICKED ||
1393 HIWORD(wParam) == BN_DOUBLECLICKED)
1394 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1397 if (HIWORD(wParam) == BN_CLICKED ||
1398 HIWORD(wParam) == BN_DOUBLECLICKED)
1399 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1402 if (HIWORD(wParam) == BN_CLICKED ||
1403 HIWORD(wParam) == BN_DOUBLECLICKED)
1404 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1406 case IDC_ALWAYSONTOP:
1407 if (HIWORD(wParam) == BN_CLICKED ||
1408 HIWORD(wParam) == BN_DOUBLECLICKED)
1409 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1412 if (HIWORD(wParam) == BN_CLICKED ||
1413 HIWORD(wParam) == BN_DOUBLECLICKED)
1414 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1416 case IDC_SCROLLDISP:
1417 if (HIWORD(wParam) == BN_CLICKED ||
1418 HIWORD(wParam) == BN_DOUBLECLICKED)
1419 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1421 case IDC_COMPOSEKEY:
1422 if (HIWORD(wParam) == BN_CLICKED ||
1423 HIWORD(wParam) == BN_DOUBLECLICKED)
1424 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1427 if (HIWORD(wParam) == BN_CLICKED ||
1428 HIWORD(wParam) == BN_DOUBLECLICKED)
1429 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1432 if (HIWORD(wParam) == BN_CLICKED ||
1433 HIWORD(wParam) == BN_DOUBLECLICKED)
1434 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1437 if (HIWORD(wParam) == BN_CLICKED ||
1438 HIWORD(wParam) == BN_DOUBLECLICKED)
1439 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1442 if (HIWORD(wParam) == EN_CHANGE)
1443 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1446 if (HIWORD(wParam) == EN_CHANGE)
1447 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1450 if (HIWORD(wParam) == EN_CHANGE)
1451 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1453 case IDC_CHOOSEFONT:
1454 lf.lfHeight = cfg.fontheight;
1455 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1456 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1457 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1458 lf.lfCharSet = cfg.fontcharset;
1459 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1460 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1461 lf.lfQuality = DEFAULT_QUALITY;
1462 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1463 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1464 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1466 cf.lStructSize = sizeof(cf);
1467 cf.hwndOwner = hwnd;
1469 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1470 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1472 if (ChooseFont (&cf)) {
1473 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1474 cfg.font[sizeof(cfg.font)-1] = '\0';
1475 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1476 cfg.fontcharset = lf.lfCharSet;
1477 cfg.fontheight = lf.lfHeight;
1478 fmtfont (fontstatic);
1479 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1483 if (HIWORD(wParam) == BN_CLICKED ||
1484 HIWORD(wParam) == BN_DOUBLECLICKED)
1485 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1488 if (HIWORD(wParam) == BN_CLICKED ||
1489 HIWORD(wParam) == BN_DOUBLECLICKED)
1490 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1493 if (HIWORD(wParam) == BN_CLICKED ||
1494 HIWORD(wParam) == BN_DOUBLECLICKED)
1495 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1498 if (HIWORD(wParam) == BN_CLICKED ||
1499 HIWORD(wParam) == BN_DOUBLECLICKED)
1500 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1503 if (HIWORD(wParam) == BN_CLICKED ||
1504 HIWORD(wParam) == BN_DOUBLECLICKED)
1505 cfg.hide_mouseptr = IsDlgButtonChecked (hwnd, IDC_HIDEMOUSE);
1508 if (HIWORD(wParam) == BN_CLICKED ||
1509 HIWORD(wParam) == BN_DOUBLECLICKED)
1510 cfg.cursor_type = 0;
1513 if (HIWORD(wParam) == BN_CLICKED ||
1514 HIWORD(wParam) == BN_DOUBLECLICKED)
1515 cfg.cursor_type = 1;
1518 if (HIWORD(wParam) == BN_CLICKED ||
1519 HIWORD(wParam) == BN_DOUBLECLICKED)
1520 cfg.cursor_type = 2;
1523 if (HIWORD(wParam) == BN_CLICKED ||
1524 HIWORD(wParam) == BN_DOUBLECLICKED)
1525 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1528 if (HIWORD(wParam) == BN_CLICKED ||
1529 HIWORD(wParam) == BN_DOUBLECLICKED)
1530 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1533 if (HIWORD(wParam) == BN_CLICKED ||
1534 HIWORD(wParam) == BN_DOUBLECLICKED)
1535 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1538 if (HIWORD(wParam) == EN_CHANGE)
1539 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1540 sizeof(cfg.wintitle)-1);
1543 if (HIWORD(wParam) == BN_CLICKED ||
1544 HIWORD(wParam) == BN_DOUBLECLICKED)
1545 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1548 if (HIWORD(wParam) == BN_CLICKED ||
1549 HIWORD(wParam) == BN_DOUBLECLICKED)
1550 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1553 if (HIWORD(wParam) == EN_CHANGE)
1554 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1555 sizeof(cfg.termtype)-1);
1558 if (HIWORD(wParam) == EN_CHANGE)
1559 GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1560 sizeof(cfg.logfilename)-1);
1563 memset(&of, 0, sizeof(of));
1564 #ifdef OPENFILENAME_SIZE_VERSION_400
1565 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1567 of.lStructSize = sizeof(of);
1569 of.hwndOwner = hwnd;
1570 of.lpstrFilter = "All Files\0*\0\0\0";
1571 of.lpstrCustomFilter = NULL;
1572 of.nFilterIndex = 1;
1573 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1574 of.nMaxFile = sizeof(filename);
1575 of.lpstrFileTitle = NULL;
1576 of.lpstrInitialDir = NULL;
1577 of.lpstrTitle = "Select session log file";
1579 if (GetSaveFileName(&of)) {
1580 strcpy(cfg.keyfile, filename);
1581 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1585 case IDC_LSTATASCII:
1587 if (HIWORD(wParam) == BN_CLICKED ||
1588 HIWORD(wParam) == BN_DOUBLECLICKED) {
1589 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1590 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1591 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1596 if (HIWORD(wParam) == EN_CHANGE)
1597 GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
1598 sizeof(cfg.termspeed)-1);
1601 if (HIWORD(wParam) == EN_CHANGE)
1602 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1603 sizeof(cfg.username)-1);
1605 case IDC_RLLUSEREDIT:
1606 if (HIWORD(wParam) == EN_CHANGE)
1607 GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
1608 sizeof(cfg.localusername)-1);
1612 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1615 if (HIWORD(wParam) == BN_CLICKED ||
1616 HIWORD(wParam) == BN_DOUBLECLICKED) {
1617 char str[sizeof(cfg.environmt)];
1619 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1624 p = str + strlen(str);
1626 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1636 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1638 p[strlen(str)+1] = '\0';
1639 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1641 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1642 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1644 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1645 MB_OK | MB_ICONERROR);
1650 if (HIWORD(wParam) != BN_CLICKED &&
1651 HIWORD(wParam) != BN_DOUBLECLICKED)
1653 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1659 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1684 if (HIWORD(wParam) == BN_CLICKED ||
1685 HIWORD(wParam) == BN_DOUBLECLICKED)
1686 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1689 if (HIWORD(wParam) == BN_CLICKED ||
1690 HIWORD(wParam) == BN_DOUBLECLICKED)
1691 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1694 if (HIWORD(wParam) == BN_CLICKED ||
1695 HIWORD(wParam) == BN_DOUBLECLICKED)
1696 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1699 if (HIWORD(wParam) == BN_CLICKED ||
1700 HIWORD(wParam) == BN_DOUBLECLICKED)
1701 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1703 case IDC_CIPHER3DES:
1704 case IDC_CIPHERBLOWF:
1706 if (HIWORD(wParam) == BN_CLICKED ||
1707 HIWORD(wParam) == BN_DOUBLECLICKED) {
1708 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1709 cfg.cipher = CIPHER_3DES;
1710 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1711 cfg.cipher = CIPHER_BLOWFISH;
1712 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1713 cfg.cipher = CIPHER_DES;
1718 if (HIWORD(wParam) == BN_CLICKED ||
1719 HIWORD(wParam) == BN_DOUBLECLICKED) {
1720 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1722 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1727 if (HIWORD(wParam) == BN_CLICKED ||
1728 HIWORD(wParam) == BN_DOUBLECLICKED)
1729 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1732 if (HIWORD(wParam) == EN_CHANGE)
1733 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1734 sizeof(cfg.keyfile)-1);
1737 if (HIWORD(wParam) == EN_CHANGE)
1738 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1739 sizeof(cfg.remote_cmd)-1);
1742 memset(&of, 0, sizeof(of));
1743 #ifdef OPENFILENAME_SIZE_VERSION_400
1744 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1746 of.lStructSize = sizeof(of);
1748 of.hwndOwner = hwnd;
1749 of.lpstrFilter = "All Files\0*\0\0\0";
1750 of.lpstrCustomFilter = NULL;
1751 of.nFilterIndex = 1;
1752 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1753 of.nMaxFile = sizeof(filename);
1754 of.lpstrFileTitle = NULL;
1755 of.lpstrInitialDir = NULL;
1756 of.lpstrTitle = "Select Public Key File";
1758 if (GetOpenFileName(&of)) {
1759 strcpy(cfg.keyfile, filename);
1760 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1765 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1771 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1776 for (i=0; i<256; i++)
1777 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1780 cfg.wordness[i] = n;
1781 SendDlgItemMessage (hwnd, IDC_CCLIST,
1782 LB_DELETESTRING, i, 0);
1783 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1784 (i>=0x21 && i != 0x7F) ? i : ' ',
1786 SendDlgItemMessage (hwnd, IDC_CCLIST,
1793 case IDC_BOLDCOLOUR:
1794 if (HIWORD(wParam) == BN_CLICKED ||
1795 HIWORD(wParam) == BN_DOUBLECLICKED) {
1797 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1798 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1799 if (n != 12+10*cfg.bold_colour) {
1801 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1802 LB_DELETESTRING, i, 0);
1803 for (i=0; i<22; i++)
1804 if (cfg.bold_colour || permcolour[i])
1805 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1807 (LPARAM) colours[i]);
1812 if (HIWORD(wParam) == BN_CLICKED ||
1813 HIWORD(wParam) == BN_DOUBLECLICKED)
1814 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1816 case IDC_COLOURLIST:
1817 if (HIWORD(wParam) == LBN_DBLCLK ||
1818 HIWORD(wParam) == LBN_SELCHANGE) {
1819 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1821 if (!cfg.bold_colour)
1822 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1823 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1824 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1825 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1829 if (HIWORD(wParam) == BN_CLICKED ||
1830 HIWORD(wParam) == BN_DOUBLECLICKED) {
1831 static CHOOSECOLOR cc;
1832 static DWORD custom[16] = {0}; /* zero initialisers */
1833 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1835 if (!cfg.bold_colour)
1836 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1837 cc.lStructSize = sizeof(cc);
1838 cc.hwndOwner = hwnd;
1839 cc.hInstance = (HWND)hinst;
1840 cc.lpCustColors = custom;
1841 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1843 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1844 if (ChooseColor(&cc)) {
1846 (unsigned char) (cc.rgbResult & 0xFF);
1848 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1850 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1851 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1853 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1855 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1861 case IDC_KOI8WIN1251:
1862 case IDC_88592WIN1250:
1863 case IDC_88592CP852:
1864 cfg.xlat_enablekoiwin =
1865 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1866 cfg.xlat_88592w1250 =
1867 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1868 cfg.xlat_88592cp852 =
1869 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1871 case IDC_CAPSLOCKCYR:
1872 if (HIWORD(wParam) == BN_CLICKED ||
1873 HIWORD(wParam) == BN_DOUBLECLICKED) {
1874 cfg.xlat_capslockcyr =
1875 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1878 case IDC_VTXWINDOWS:
1883 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1884 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1885 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1888 case IDC_X11_FORWARD:
1889 if (HIWORD(wParam) == BN_CLICKED ||
1890 HIWORD(wParam) == BN_DOUBLECLICKED)
1891 cfg.x11_forward = IsDlgButtonChecked (hwnd, IDC_X11_FORWARD);
1893 case IDC_X11_DISPLAY:
1894 if (HIWORD(wParam) == EN_CHANGE)
1895 GetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display,
1896 sizeof(cfg.x11_display)-1);
1901 EndDialog (hwnd, 0);
1904 /* Grrr Explorer will maximize Dialogs! */
1906 if (wParam == SIZE_MAXIMIZED)
1913 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1914 WPARAM wParam, LPARAM lParam) {
1915 static HWND page = NULL;
1917 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1919 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1920 EnableWindow(hwnd, 0);
1921 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1922 GetParent(hwnd), AboutProc);
1923 EnableWindow(hwnd, 1);
1924 SetActiveWindow(hwnd);
1926 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1929 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1930 WPARAM wParam, LPARAM lParam) {
1932 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1935 void defuse_showwindow(void) {
1937 * Work around the fact that the app's first call to ShowWindow
1938 * will ignore the default in favour of the shell-provided
1943 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1945 ShowWindow(hwnd, SW_HIDE);
1946 DestroyWindow(hwnd);
1950 int do_config (void) {
1954 savedsession[0] = '\0';
1955 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1956 get_sesslist(FALSE);
1961 int do_reconfig (HWND hwnd) {
1965 backup_cfg = cfg; /* structure copy */
1966 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1968 cfg = backup_cfg; /* structure copy */
1973 void logevent (char *string) {
1974 if (nevents >= negsize) {
1976 events = srealloc (events, negsize * sizeof(*events));
1978 events[nevents] = smalloc(1+strlen(string));
1979 strcpy (events[nevents], string);
1983 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1985 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1986 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1990 void showeventlog (HWND hwnd) {
1992 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1994 ShowWindow (logbox, SW_SHOWNORMAL);
1998 void showabout (HWND hwnd) {
2000 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2002 ShowWindow (abtbox, SW_SHOWNORMAL);
2006 void verify_ssh_host_key(char *host, int port, char *keytype,
2007 char *keystr, char *fingerprint) {
2010 static const char absentmsg[] =
2011 "The server's host key is not cached in the registry. You\n"
2012 "have no guarantee that the server is the computer you\n"
2014 "The server's key fingerprint is:\n"
2016 "If you trust this host, hit Yes to add the key to\n"
2017 "PuTTY's cache and carry on connecting.\n"
2018 "If you do not trust this host, hit No to abandon the\n"
2021 static const char wrongmsg[] =
2022 "WARNING - POTENTIAL SECURITY BREACH!\n"
2024 "The server's host key does not match the one PuTTY has\n"
2025 "cached in the registry. This means that either the\n"
2026 "server administrator has changed the host key, or you\n"
2027 "have actually connected to another computer pretending\n"
2028 "to be the server.\n"
2029 "The new key fingerprint is:\n"
2031 "If you were expecting this change and trust the new key,\n"
2032 "hit Yes to update PuTTY's cache and continue connecting.\n"
2033 "If you want to carry on connecting but without updating\n"
2034 "the cache, hit No.\n"
2035 "If you want to abandon the connection completely, hit\n"
2036 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2039 static const char mbtitle[] = "PuTTY Security Alert";
2042 char message[160+ /* sensible fingerprint max size */
2043 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2044 sizeof(absentmsg) : sizeof(wrongmsg))];
2047 * Verify the key against the registry.
2049 ret = verify_host_key(host, port, keytype, keystr);
2051 if (ret == 0) /* success - key matched OK */
2053 if (ret == 2) { /* key was different */
2055 sprintf(message, wrongmsg, fingerprint);
2056 mbret = MessageBox(NULL, message, mbtitle,
2057 MB_ICONWARNING | MB_YESNOCANCEL);
2059 store_host_key(host, port, keytype, keystr);
2060 if (mbret == IDCANCEL)
2063 if (ret == 1) { /* key was absent */
2065 sprintf(message, absentmsg, fingerprint);
2066 mbret = MessageBox(NULL, message, mbtitle,
2067 MB_ICONWARNING | MB_YESNO);
2070 store_host_key(host, port, keytype, keystr);
2075 * Ask whether to wipe a session log file before writing to it.
2076 * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2078 int askappend(char *filename) {
2079 static const char mbtitle[] = "PuTTY Log to File";
2080 static const char msgtemplate[] =
2081 "The session log file \"%.*s\" already exists.\n"
2082 "You can overwrite it with a new session log,\n"
2083 "append your session log to the end of it,\n"
2084 "or disable session logging for this session.\n"
2085 "Hit Yes to wipe the file, No to append to it,\n"
2086 "or Cancel to disable logging.";
2087 char message[sizeof(msgtemplate) + FILENAME_MAX];
2089 sprintf(message, msgtemplate, FILENAME_MAX, filename);
2091 mbret = MessageBox(NULL, message, mbtitle,
2092 MB_ICONQUESTION | MB_YESNOCANCEL);
2095 else if (mbret == IDNO)