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");
1101 * Put the treeview selection on to the Session panel. This
1102 * should also cause creation of the relevant controls.
1104 TreeView_SelectItem(treeview, hsession);
1107 * Set focus into the first available control.
1111 ctl = GetDlgItem(hwnd, IDC_HOST);
1112 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1116 SetWindowLong(hwnd, GWL_USERDATA, 1);
1120 * Button release should trigger WM_OK if there was a
1121 * previous double click on the session list.
1125 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1128 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1129 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1130 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1135 item.pszText = buffer;
1136 item.cchTextMax = sizeof(buffer);
1137 item.mask = TVIF_TEXT;
1138 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1139 for (j = controlstartvalue; j < controlendvalue; j++) {
1140 HWND item = GetDlgItem(hwnd, j);
1142 DestroyWindow(item);
1144 if (!strcmp(buffer, "Session"))
1145 create_controls(hwnd, dlgtype, sessionpanelstart);
1146 if (!strcmp(buffer, "Keyboard"))
1147 create_controls(hwnd, dlgtype, keyboardpanelstart);
1148 if (!strcmp(buffer, "Terminal"))
1149 create_controls(hwnd, dlgtype, terminalpanelstart);
1150 if (!strcmp(buffer, "Window"))
1151 create_controls(hwnd, dlgtype, windowpanelstart);
1152 if (!strcmp(buffer, "Appearance"))
1153 create_controls(hwnd, dlgtype, appearancepanelstart);
1154 if (!strcmp(buffer, "Tunnels"))
1155 create_controls(hwnd, dlgtype, tunnelspanelstart);
1156 if (!strcmp(buffer, "Connection"))
1157 create_controls(hwnd, dlgtype, connectionpanelstart);
1158 if (!strcmp(buffer, "Telnet"))
1159 create_controls(hwnd, dlgtype, telnetpanelstart);
1160 if (!strcmp(buffer, "Rlogin"))
1161 create_controls(hwnd, dlgtype, rloginpanelstart);
1162 if (!strcmp(buffer, "SSH"))
1163 create_controls(hwnd, dlgtype, sshpanelstart);
1164 if (!strcmp(buffer, "Selection"))
1165 create_controls(hwnd, dlgtype, selectionpanelstart);
1166 if (!strcmp(buffer, "Colours"))
1167 create_controls(hwnd, dlgtype, colourspanelstart);
1168 if (!strcmp(buffer, "Translation"))
1169 create_controls(hwnd, dlgtype, translationpanelstart);
1171 init_dlg_ctrls(hwnd);
1173 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1179 * Only process WM_COMMAND once the dialog is fully formed.
1181 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1184 EndDialog (hwnd, 1);
1189 EndDialog (hwnd, 0);
1191 case IDC_PROTTELNET:
1192 case IDC_PROTRLOGIN:
1195 if (HIWORD(wParam) == BN_CLICKED ||
1196 HIWORD(wParam) == BN_DOUBLECLICKED) {
1197 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1198 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1199 int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
1200 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN : PROT_RAW ;
1201 if ((cfg.protocol == PROT_SSH && cfg.port != 22) ||
1202 (cfg.protocol == PROT_TELNET && cfg.port != 23) ||
1203 (cfg.protocol == PROT_RLOGIN && cfg.port != 513)) {
1204 cfg.port = i ? 22 : j ? 23 : 513;
1205 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1210 if (HIWORD(wParam) == EN_CHANGE)
1211 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1212 sizeof(cfg.host)-1);
1215 if (HIWORD(wParam) == EN_CHANGE) {
1216 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1217 if (isdigit(portname[0]))
1218 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1220 service = getservbyname(portname, NULL);
1221 if (service) cfg.port = ntohs(service->s_port);
1227 if (HIWORD(wParam) == EN_CHANGE) {
1228 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1230 GetDlgItemText (hwnd, IDC_SESSEDIT,
1231 savedsession, sizeof(savedsession)-1);
1232 savedsession[sizeof(savedsession)-1] = '\0';
1236 if (HIWORD(wParam) == BN_CLICKED ||
1237 HIWORD(wParam) == BN_DOUBLECLICKED) {
1242 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1244 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1245 LB_GETCURSEL, 0, 0);
1250 strcpy (str, sessions[n]);
1252 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1253 get_sesslist (FALSE);
1254 get_sesslist (TRUE);
1255 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1257 for (i = 0; i < nsessions; i++)
1258 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1259 0, (LPARAM) (sessions[i]));
1260 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1266 if (LOWORD(wParam) == IDC_SESSLOAD &&
1267 HIWORD(wParam) != BN_CLICKED &&
1268 HIWORD(wParam) != BN_DOUBLECLICKED)
1270 if (LOWORD(wParam) == IDC_SESSLIST &&
1271 HIWORD(wParam) != LBN_DBLCLK)
1274 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1275 LB_GETCURSEL, 0, 0);
1281 isdef = !strcmp(sessions[n], "Default Settings");
1282 load_settings (sessions[n], !isdef, &cfg);
1283 init_dlg_ctrls(hwnd);
1285 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1287 SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1289 if (LOWORD(wParam) == IDC_SESSLIST) {
1291 * A double-click on a saved session should
1292 * actually start the session, not just load it.
1293 * Unless it's Default Settings or some other
1294 * host-less set of saved settings.
1303 if (HIWORD(wParam) == BN_CLICKED ||
1304 HIWORD(wParam) == BN_DOUBLECLICKED) {
1305 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1306 LB_GETCURSEL, 0, 0);
1307 if (n == LB_ERR || n == 0) {
1311 del_settings(sessions[n]);
1312 get_sesslist (FALSE);
1313 get_sesslist (TRUE);
1314 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1316 for (i = 0; i < nsessions; i++)
1317 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1318 0, (LPARAM) (sessions[i]));
1319 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1323 if (HIWORD(wParam) == EN_CHANGE)
1324 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1328 if (HIWORD(wParam) == BN_CLICKED ||
1329 HIWORD(wParam) == BN_DOUBLECLICKED)
1330 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1334 if (HIWORD(wParam) == BN_CLICKED ||
1335 HIWORD(wParam) == BN_DOUBLECLICKED)
1336 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1339 if (HIWORD(wParam) == BN_CLICKED ||
1340 HIWORD(wParam) == BN_DOUBLECLICKED)
1344 if (HIWORD(wParam) == BN_CLICKED ||
1345 HIWORD(wParam) == BN_DOUBLECLICKED)
1350 if (HIWORD(wParam) == BN_CLICKED ||
1351 HIWORD(wParam) == BN_DOUBLECLICKED)
1352 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1356 if (HIWORD(wParam) == BN_CLICKED ||
1357 HIWORD(wParam) == BN_DOUBLECLICKED) {
1358 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1359 cfg.nethack_keypad = FALSE;
1363 if (HIWORD(wParam) == BN_CLICKED ||
1364 HIWORD(wParam) == BN_DOUBLECLICKED) {
1365 cfg.app_keypad = FALSE;
1366 cfg.nethack_keypad = TRUE;
1371 if (HIWORD(wParam) == BN_CLICKED ||
1372 HIWORD(wParam) == BN_DOUBLECLICKED)
1373 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1376 if (HIWORD(wParam) == BN_CLICKED ||
1377 HIWORD(wParam) == BN_DOUBLECLICKED)
1378 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1381 if (HIWORD(wParam) == BN_CLICKED ||
1382 HIWORD(wParam) == BN_DOUBLECLICKED)
1383 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1386 if (HIWORD(wParam) == BN_CLICKED ||
1387 HIWORD(wParam) == BN_DOUBLECLICKED)
1388 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1391 if (HIWORD(wParam) == BN_CLICKED ||
1392 HIWORD(wParam) == BN_DOUBLECLICKED)
1393 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1396 if (HIWORD(wParam) == BN_CLICKED ||
1397 HIWORD(wParam) == BN_DOUBLECLICKED)
1398 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1401 if (HIWORD(wParam) == BN_CLICKED ||
1402 HIWORD(wParam) == BN_DOUBLECLICKED)
1403 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1405 case IDC_ALWAYSONTOP:
1406 if (HIWORD(wParam) == BN_CLICKED ||
1407 HIWORD(wParam) == BN_DOUBLECLICKED)
1408 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1411 if (HIWORD(wParam) == BN_CLICKED ||
1412 HIWORD(wParam) == BN_DOUBLECLICKED)
1413 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1415 case IDC_SCROLLDISP:
1416 if (HIWORD(wParam) == BN_CLICKED ||
1417 HIWORD(wParam) == BN_DOUBLECLICKED)
1418 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1420 case IDC_COMPOSEKEY:
1421 if (HIWORD(wParam) == BN_CLICKED ||
1422 HIWORD(wParam) == BN_DOUBLECLICKED)
1423 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1426 if (HIWORD(wParam) == BN_CLICKED ||
1427 HIWORD(wParam) == BN_DOUBLECLICKED)
1428 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1431 if (HIWORD(wParam) == BN_CLICKED ||
1432 HIWORD(wParam) == BN_DOUBLECLICKED)
1433 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1436 if (HIWORD(wParam) == BN_CLICKED ||
1437 HIWORD(wParam) == BN_DOUBLECLICKED)
1438 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1441 if (HIWORD(wParam) == EN_CHANGE)
1442 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1445 if (HIWORD(wParam) == EN_CHANGE)
1446 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1449 if (HIWORD(wParam) == EN_CHANGE)
1450 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1452 case IDC_CHOOSEFONT:
1453 lf.lfHeight = cfg.fontheight;
1454 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1455 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1456 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1457 lf.lfCharSet = cfg.fontcharset;
1458 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1459 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1460 lf.lfQuality = DEFAULT_QUALITY;
1461 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1462 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1463 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1465 cf.lStructSize = sizeof(cf);
1466 cf.hwndOwner = hwnd;
1468 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1469 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1471 if (ChooseFont (&cf)) {
1472 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1473 cfg.font[sizeof(cfg.font)-1] = '\0';
1474 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1475 cfg.fontcharset = lf.lfCharSet;
1476 cfg.fontheight = lf.lfHeight;
1477 fmtfont (fontstatic);
1478 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1482 if (HIWORD(wParam) == BN_CLICKED ||
1483 HIWORD(wParam) == BN_DOUBLECLICKED)
1484 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1487 if (HIWORD(wParam) == BN_CLICKED ||
1488 HIWORD(wParam) == BN_DOUBLECLICKED)
1489 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1492 if (HIWORD(wParam) == BN_CLICKED ||
1493 HIWORD(wParam) == BN_DOUBLECLICKED)
1494 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1497 if (HIWORD(wParam) == BN_CLICKED ||
1498 HIWORD(wParam) == BN_DOUBLECLICKED)
1499 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1502 if (HIWORD(wParam) == BN_CLICKED ||
1503 HIWORD(wParam) == BN_DOUBLECLICKED)
1504 cfg.hide_mouseptr = IsDlgButtonChecked (hwnd, IDC_HIDEMOUSE);
1507 if (HIWORD(wParam) == BN_CLICKED ||
1508 HIWORD(wParam) == BN_DOUBLECLICKED)
1509 cfg.cursor_type = 0;
1512 if (HIWORD(wParam) == BN_CLICKED ||
1513 HIWORD(wParam) == BN_DOUBLECLICKED)
1514 cfg.cursor_type = 1;
1517 if (HIWORD(wParam) == BN_CLICKED ||
1518 HIWORD(wParam) == BN_DOUBLECLICKED)
1519 cfg.cursor_type = 2;
1522 if (HIWORD(wParam) == BN_CLICKED ||
1523 HIWORD(wParam) == BN_DOUBLECLICKED)
1524 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1527 if (HIWORD(wParam) == BN_CLICKED ||
1528 HIWORD(wParam) == BN_DOUBLECLICKED)
1529 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1532 if (HIWORD(wParam) == BN_CLICKED ||
1533 HIWORD(wParam) == BN_DOUBLECLICKED)
1534 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1537 if (HIWORD(wParam) == EN_CHANGE)
1538 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1539 sizeof(cfg.wintitle)-1);
1542 if (HIWORD(wParam) == BN_CLICKED ||
1543 HIWORD(wParam) == BN_DOUBLECLICKED)
1544 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1547 if (HIWORD(wParam) == BN_CLICKED ||
1548 HIWORD(wParam) == BN_DOUBLECLICKED)
1549 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1552 if (HIWORD(wParam) == EN_CHANGE)
1553 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1554 sizeof(cfg.termtype)-1);
1557 if (HIWORD(wParam) == EN_CHANGE)
1558 GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1559 sizeof(cfg.logfilename)-1);
1562 memset(&of, 0, sizeof(of));
1563 #ifdef OPENFILENAME_SIZE_VERSION_400
1564 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1566 of.lStructSize = sizeof(of);
1568 of.hwndOwner = hwnd;
1569 of.lpstrFilter = "All Files\0*\0\0\0";
1570 of.lpstrCustomFilter = NULL;
1571 of.nFilterIndex = 1;
1572 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1573 of.nMaxFile = sizeof(filename);
1574 of.lpstrFileTitle = NULL;
1575 of.lpstrInitialDir = NULL;
1576 of.lpstrTitle = "Select session log file";
1578 if (GetSaveFileName(&of)) {
1579 strcpy(cfg.keyfile, filename);
1580 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1584 case IDC_LSTATASCII:
1586 if (HIWORD(wParam) == BN_CLICKED ||
1587 HIWORD(wParam) == BN_DOUBLECLICKED) {
1588 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1589 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1590 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1595 if (HIWORD(wParam) == EN_CHANGE)
1596 GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
1597 sizeof(cfg.termspeed)-1);
1600 if (HIWORD(wParam) == EN_CHANGE)
1601 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1602 sizeof(cfg.username)-1);
1604 case IDC_RLLUSEREDIT:
1605 if (HIWORD(wParam) == EN_CHANGE)
1606 GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
1607 sizeof(cfg.localusername)-1);
1611 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1614 if (HIWORD(wParam) == BN_CLICKED ||
1615 HIWORD(wParam) == BN_DOUBLECLICKED) {
1616 char str[sizeof(cfg.environmt)];
1618 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1623 p = str + strlen(str);
1625 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1635 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1637 p[strlen(str)+1] = '\0';
1638 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1640 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1641 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1643 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1644 MB_OK | MB_ICONERROR);
1649 if (HIWORD(wParam) != BN_CLICKED &&
1650 HIWORD(wParam) != BN_DOUBLECLICKED)
1652 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1658 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1683 if (HIWORD(wParam) == BN_CLICKED ||
1684 HIWORD(wParam) == BN_DOUBLECLICKED)
1685 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1688 if (HIWORD(wParam) == BN_CLICKED ||
1689 HIWORD(wParam) == BN_DOUBLECLICKED)
1690 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1693 if (HIWORD(wParam) == BN_CLICKED ||
1694 HIWORD(wParam) == BN_DOUBLECLICKED)
1695 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1698 if (HIWORD(wParam) == BN_CLICKED ||
1699 HIWORD(wParam) == BN_DOUBLECLICKED)
1700 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1702 case IDC_CIPHER3DES:
1703 case IDC_CIPHERBLOWF:
1705 if (HIWORD(wParam) == BN_CLICKED ||
1706 HIWORD(wParam) == BN_DOUBLECLICKED) {
1707 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1708 cfg.cipher = CIPHER_3DES;
1709 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1710 cfg.cipher = CIPHER_BLOWFISH;
1711 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1712 cfg.cipher = CIPHER_DES;
1717 if (HIWORD(wParam) == BN_CLICKED ||
1718 HIWORD(wParam) == BN_DOUBLECLICKED) {
1719 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1721 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1726 if (HIWORD(wParam) == BN_CLICKED ||
1727 HIWORD(wParam) == BN_DOUBLECLICKED)
1728 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1731 if (HIWORD(wParam) == EN_CHANGE)
1732 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1733 sizeof(cfg.keyfile)-1);
1736 if (HIWORD(wParam) == EN_CHANGE)
1737 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1738 sizeof(cfg.remote_cmd)-1);
1741 memset(&of, 0, sizeof(of));
1742 #ifdef OPENFILENAME_SIZE_VERSION_400
1743 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1745 of.lStructSize = sizeof(of);
1747 of.hwndOwner = hwnd;
1748 of.lpstrFilter = "All Files\0*\0\0\0";
1749 of.lpstrCustomFilter = NULL;
1750 of.nFilterIndex = 1;
1751 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1752 of.nMaxFile = sizeof(filename);
1753 of.lpstrFileTitle = NULL;
1754 of.lpstrInitialDir = NULL;
1755 of.lpstrTitle = "Select Public Key File";
1757 if (GetOpenFileName(&of)) {
1758 strcpy(cfg.keyfile, filename);
1759 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1764 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1770 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1775 for (i=0; i<256; i++)
1776 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1779 cfg.wordness[i] = n;
1780 SendDlgItemMessage (hwnd, IDC_CCLIST,
1781 LB_DELETESTRING, i, 0);
1782 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1783 (i>=0x21 && i != 0x7F) ? i : ' ',
1785 SendDlgItemMessage (hwnd, IDC_CCLIST,
1792 case IDC_BOLDCOLOUR:
1793 if (HIWORD(wParam) == BN_CLICKED ||
1794 HIWORD(wParam) == BN_DOUBLECLICKED) {
1796 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1797 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1798 if (n != 12+10*cfg.bold_colour) {
1800 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1801 LB_DELETESTRING, i, 0);
1802 for (i=0; i<22; i++)
1803 if (cfg.bold_colour || permcolour[i])
1804 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1806 (LPARAM) colours[i]);
1811 if (HIWORD(wParam) == BN_CLICKED ||
1812 HIWORD(wParam) == BN_DOUBLECLICKED)
1813 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1815 case IDC_COLOURLIST:
1816 if (HIWORD(wParam) == LBN_DBLCLK ||
1817 HIWORD(wParam) == LBN_SELCHANGE) {
1818 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1820 if (!cfg.bold_colour)
1821 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1822 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1823 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1824 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1828 if (HIWORD(wParam) == BN_CLICKED ||
1829 HIWORD(wParam) == BN_DOUBLECLICKED) {
1830 static CHOOSECOLOR cc;
1831 static DWORD custom[16] = {0}; /* zero initialisers */
1832 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1834 if (!cfg.bold_colour)
1835 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1836 cc.lStructSize = sizeof(cc);
1837 cc.hwndOwner = hwnd;
1838 cc.hInstance = (HWND)hinst;
1839 cc.lpCustColors = custom;
1840 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1842 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1843 if (ChooseColor(&cc)) {
1845 (unsigned char) (cc.rgbResult & 0xFF);
1847 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1849 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1850 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1852 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1854 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1860 case IDC_KOI8WIN1251:
1861 case IDC_88592WIN1250:
1862 case IDC_88592CP852:
1863 cfg.xlat_enablekoiwin =
1864 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1865 cfg.xlat_88592w1250 =
1866 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1867 cfg.xlat_88592cp852 =
1868 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1870 case IDC_CAPSLOCKCYR:
1871 if (HIWORD(wParam) == BN_CLICKED ||
1872 HIWORD(wParam) == BN_DOUBLECLICKED) {
1873 cfg.xlat_capslockcyr =
1874 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1877 case IDC_VTXWINDOWS:
1882 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1883 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1884 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1887 case IDC_X11_FORWARD:
1888 if (HIWORD(wParam) == BN_CLICKED ||
1889 HIWORD(wParam) == BN_DOUBLECLICKED)
1890 cfg.x11_forward = IsDlgButtonChecked (hwnd, IDC_X11_FORWARD);
1892 case IDC_X11_DISPLAY:
1893 if (HIWORD(wParam) == EN_CHANGE)
1894 GetDlgItemText (hwnd, IDC_X11_DISPLAY, cfg.x11_display,
1895 sizeof(cfg.x11_display)-1);
1900 EndDialog (hwnd, 0);
1903 /* Grrr Explorer will maximize Dialogs! */
1905 if (wParam == SIZE_MAXIMIZED)
1912 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1913 WPARAM wParam, LPARAM lParam) {
1914 static HWND page = NULL;
1916 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1918 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1919 EnableWindow(hwnd, 0);
1920 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1921 GetParent(hwnd), AboutProc);
1922 EnableWindow(hwnd, 1);
1923 SetActiveWindow(hwnd);
1925 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1928 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1929 WPARAM wParam, LPARAM lParam) {
1931 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1934 void defuse_showwindow(void) {
1936 * Work around the fact that the app's first call to ShowWindow
1937 * will ignore the default in favour of the shell-provided
1942 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1944 ShowWindow(hwnd, SW_HIDE);
1945 DestroyWindow(hwnd);
1949 int do_config (void) {
1953 savedsession[0] = '\0';
1954 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1955 get_sesslist(FALSE);
1960 int do_reconfig (HWND hwnd) {
1964 backup_cfg = cfg; /* structure copy */
1965 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1967 cfg = backup_cfg; /* structure copy */
1972 void logevent (char *string) {
1973 if (nevents >= negsize) {
1975 events = srealloc (events, negsize * sizeof(*events));
1977 events[nevents] = smalloc(1+strlen(string));
1978 strcpy (events[nevents], string);
1982 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1984 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1985 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1989 void showeventlog (HWND hwnd) {
1991 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1993 ShowWindow (logbox, SW_SHOWNORMAL);
1997 void showabout (HWND hwnd) {
1999 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2001 ShowWindow (abtbox, SW_SHOWNORMAL);
2005 void verify_ssh_host_key(char *host, int port, char *keytype,
2006 char *keystr, char *fingerprint) {
2009 static const char absentmsg[] =
2010 "The server's host key is not cached in the registry. You\n"
2011 "have no guarantee that the server is the computer you\n"
2013 "The server's key fingerprint is:\n"
2015 "If you trust this host, hit Yes to add the key to\n"
2016 "PuTTY's cache and carry on connecting.\n"
2017 "If you do not trust this host, hit No to abandon the\n"
2020 static const char wrongmsg[] =
2021 "WARNING - POTENTIAL SECURITY BREACH!\n"
2023 "The server's host key does not match the one PuTTY has\n"
2024 "cached in the registry. This means that either the\n"
2025 "server administrator has changed the host key, or you\n"
2026 "have actually connected to another computer pretending\n"
2027 "to be the server.\n"
2028 "The new key fingerprint is:\n"
2030 "If you were expecting this change and trust the new key,\n"
2031 "hit Yes to update PuTTY's cache and continue connecting.\n"
2032 "If you want to carry on connecting but without updating\n"
2033 "the cache, hit No.\n"
2034 "If you want to abandon the connection completely, hit\n"
2035 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2038 static const char mbtitle[] = "PuTTY Security Alert";
2041 char message[160+ /* sensible fingerprint max size */
2042 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2043 sizeof(absentmsg) : sizeof(wrongmsg))];
2046 * Verify the key against the registry.
2048 ret = verify_host_key(host, port, keytype, keystr);
2050 if (ret == 0) /* success - key matched OK */
2052 if (ret == 2) { /* key was different */
2054 sprintf(message, wrongmsg, fingerprint);
2055 mbret = MessageBox(NULL, message, mbtitle,
2056 MB_ICONWARNING | MB_YESNOCANCEL);
2058 store_host_key(host, port, keytype, keystr);
2059 if (mbret == IDCANCEL)
2062 if (ret == 1) { /* key was absent */
2064 sprintf(message, absentmsg, fingerprint);
2065 mbret = MessageBox(NULL, message, mbtitle,
2066 MB_ICONWARNING | MB_YESNO);
2069 store_host_key(host, port, keytype, keystr);
2074 * Ask whether to wipe a session log file before writing to it.
2075 * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
2077 int askappend(char *filename) {
2078 static const char mbtitle[] = "PuTTY Log to File";
2079 static const char msgtemplate[] =
2080 "The session log file \"%.*s\" already exists.\n"
2081 "You can overwrite it with a new session log,\n"
2082 "append your session log to the end of it,\n"
2083 "or disable session logging for this session.\n"
2084 "Hit Yes to wipe the file, No to append to it,\n"
2085 "or Cancel to disable logging.";
2086 char message[sizeof(msgtemplate) + FILENAME_MAX];
2088 sprintf(message, msgtemplate, FILENAME_MAX, filename);
2090 mbret = MessageBox(NULL, message, mbtitle,
2091 MB_ICONQUESTION | MB_YESNOCANCEL);
2094 else if (mbret == IDNO)