13 static char **events = NULL;
14 static int nevents = 0, negsize = 0;
16 static HWND logbox = NULL, abtbox = NULL;
20 static void force_normal(HWND hwnd)
22 static int recurse = 0;
29 wp.length = sizeof(wp);
30 if (GetWindowPlacement(hwnd, &wp))
32 wp.showCmd = SW_SHOWNORMAL;
33 SetWindowPlacement(hwnd, &wp);
38 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
41 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
46 static int CALLBACK LogProc (HWND hwnd, UINT msg,
47 WPARAM wParam, LPARAM lParam) {
52 for (i=0; i<nevents; i++)
53 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
54 0, (LPARAM)events[i]);
57 switch (LOWORD(wParam)) {
63 if (HIWORD(wParam) == BN_CLICKED ||
64 HIWORD(wParam) == BN_DOUBLECLICKED) {
67 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
68 LB_GETSELCOUNT, 0, 0);
69 selitems = malloc(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 = malloc(size);
91 for (i = 0; i < count; i++) {
92 char *q = events[selitems[i]];
96 memcpy(p, sel_nl, sizeof(sel_nl));
99 write_clip(clipdata, size, TRUE);
104 for (i = 0; i < nevents; i++)
105 SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
114 DestroyWindow (hwnd);
120 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
121 WPARAM wParam, LPARAM lParam) {
126 switch (LOWORD(wParam)) {
139 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
140 WPARAM wParam, LPARAM lParam) {
143 SetDlgItemText (hwnd, IDA_VERSION, ver);
146 switch (LOWORD(wParam)) {
149 DestroyWindow (hwnd);
152 EnableWindow(hwnd, 0);
153 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
155 EnableWindow(hwnd, 1);
156 SetActiveWindow(hwnd);
162 DestroyWindow (hwnd);
169 * Null dialog procedure.
171 static int CALLBACK NullDlgProc (HWND hwnd, UINT msg,
172 WPARAM wParam, LPARAM lParam) {
176 static char savedsession[2048];
178 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
182 IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
183 IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
204 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
205 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
206 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3,
231 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
243 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
244 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
262 appearancepanelstart,
263 IDC_TITLE_APPEARANCE,
264 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1,
265 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2,
266 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3,
275 connectionpanelstart,
276 IDC_TITLE_CONNECTION,
277 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
278 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
289 IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
290 IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
308 IDC_BOX_SSH1, IDC_BOXT_SSH1,
309 IDC_BOX_SSH2, IDC_BOXT_SSH2,
310 IDC_BOX_SSH3, IDC_BOXT_SSH3,
331 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
332 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
345 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
346 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
360 translationpanelstart,
361 IDC_TITLE_TRANSLATION,
362 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
363 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
364 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
381 static const char *const colours[] = {
382 "Default Foreground", "Default Bold Foreground",
383 "Default Background", "Default Bold Background",
384 "Cursor Text", "Cursor Colour",
385 "ANSI Black", "ANSI Black Bold",
386 "ANSI Red", "ANSI Red Bold",
387 "ANSI Green", "ANSI Green Bold",
388 "ANSI Yellow", "ANSI Yellow Bold",
389 "ANSI Blue", "ANSI Blue Bold",
390 "ANSI Magenta", "ANSI Magenta Bold",
391 "ANSI Cyan", "ANSI Cyan Bold",
392 "ANSI White", "ANSI White Bold"
394 static const int permcolour[] = {
395 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
396 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
397 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
400 static void fmtfont (char *buf) {
401 sprintf (buf, "Font: %s, ", cfg.font);
403 strcat(buf, "bold, ");
404 if (cfg.fontheight == 0)
405 strcat (buf, "default height");
407 sprintf (buf+strlen(buf), "%d-%s",
408 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
409 (cfg.fontheight < 0 ? "pixel" : "point"));
412 static void init_dlg_ctrls(HWND hwnd) {
414 char fontstatic[256];
416 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
417 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
418 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
419 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
420 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
421 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
422 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
424 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
425 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
426 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
427 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
428 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
429 cfg.funky_type == 0 ? IDC_FUNCTILDE :
430 cfg.funky_type == 1 ? IDC_FUNCLINUX :
431 cfg.funky_type == 2 ? IDC_FUNCXTERM :
432 cfg.funky_type == 3 ? IDC_FUNCVT400 :
434 CheckDlgButton (hwnd, IDC_NOAPPLIC, cfg.no_applic);
435 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
436 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
437 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
438 cfg.nethack_keypad ? IDC_KPNH :
439 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
440 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
441 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
442 CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
443 CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
444 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
445 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
446 CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
448 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
449 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
450 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
451 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
452 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
453 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
454 fmtfont (fontstatic);
455 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
456 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
457 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
458 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
460 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
461 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
462 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
463 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
464 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
465 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
466 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
468 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
469 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
470 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
472 char *p = cfg.environmt;
474 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
479 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
480 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
482 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
483 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
484 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
485 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
486 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
487 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
488 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
489 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
491 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
492 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
493 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
494 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
495 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
497 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
498 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
500 static int tabs[4] = {25, 61, 96, 128};
501 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
504 for (i=0; i<256; i++) {
506 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
507 (i>=0x21 && i != 0x7F) ? i : ' ',
509 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
513 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
514 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
518 if (cfg.bold_colour || permcolour[i])
519 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
520 (LPARAM) colours[i]);
522 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
523 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
524 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
525 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
527 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
528 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
529 cfg.xlat_88592cp852 ? IDC_88592CP852 :
530 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
532 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
533 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
534 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
535 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
536 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
540 static void hide(HWND hwnd, int hide, int minid, int maxid) {
542 for (i = minid; i < maxid; i++) {
543 HWND ctl = GetDlgItem(hwnd, i);
545 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
550 struct treeview_faff {
555 static HTREEITEM treeview_insert(struct treeview_faff *faff,
556 int level, char *text) {
560 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
561 ins.hInsertAfter = faff->lastat[level];
562 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
563 #define INSITEM DUMMYUNIONNAME.item
567 ins.INSITEM.mask = TVIF_TEXT;
568 ins.INSITEM.pszText = text;
569 newitem = TreeView_InsertItem(faff->treeview, &ins);
571 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
572 faff->lastat[level] = newitem;
573 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
578 * This _huge_ function is the configuration box.
580 static int GenericMainDlgProc (HWND hwnd, UINT msg,
581 WPARAM wParam, LPARAM lParam,
584 struct treeview_faff tvfaff;
587 char filename[sizeof(cfg.keyfile)];
590 char fontstatic[256];
596 SetWindowLong(hwnd, GWL_USERDATA, 0);
600 { /* centre the window */
603 hw = GetDesktopWindow();
604 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
605 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
606 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
607 rd.right-rd.left, rd.bottom-rd.top, TRUE);
611 * Create the tree view.
618 r.left = 3; r.right = r.left + 75;
619 r.top = 3; r.bottom = r.top + 10;
620 MapDialogRect(hwnd, &r);
621 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
622 WS_CHILD | WS_VISIBLE,
624 r.right-r.left, r.bottom-r.top,
625 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
626 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
627 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
629 r.left = 3; r.right = r.left + 75;
630 r.top = 13; r.bottom = r.top + 196;
631 MapDialogRect(hwnd, &r);
632 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
633 WS_CHILD | WS_VISIBLE |
634 WS_TABSTOP | TVS_HASLINES |
635 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
636 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
638 r.right-r.left, r.bottom-r.top,
639 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
640 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
641 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
642 tvfaff.treeview = treeview;
643 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
647 * Create the various panelfuls of controls.
650 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
653 ctlposinit(&cp, hwnd, 80, 3, 13);
654 bartitle(&cp, "Basic options for your PuTTY session",
657 beginbox(&cp, "Specify your connection by host name",
658 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
660 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
661 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
662 if (backends[2].backend == NULL) {
663 /* this is PuTTYtel, so only two protocols available */
664 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
666 "&Telnet", IDC_PROTTELNET, NULL);
668 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
670 "&Telnet", IDC_PROTTELNET,
679 beginbox(&cp, "Load, save or delete a stored session",
680 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
681 sesssaver(&cp, "Sav&ed Sessions",
682 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
683 "&Load", IDC_SESSLOAD,
684 "&Save", IDC_SESSSAVE,
685 "&Delete", IDC_SESSDEL, NULL);
688 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
689 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
692 hsession = treeview_insert(&tvfaff, 0, "Session");
695 /* The Terminal panel. Accelerators used: [acgo] &dlbenu */
698 ctlposinit(&cp, hwnd, 80, 3, 13);
699 bartitle(&cp, "Options controlling the terminal emulation",
701 beginbox(&cp, "Set various terminal options",
702 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
703 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
704 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
705 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
706 checkbox(&cp, "&Beep enabled", IDC_BEEP);
707 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
708 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
709 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
712 treeview_insert(&tvfaff, 0, "Terminal");
715 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmiet */
718 ctlposinit(&cp, hwnd, 80, 3, 13);
719 bartitle(&cp, "Options controlling the effects of keys",
721 beginbox(&cp, "Change the sequences sent by:",
722 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
723 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
724 "Control-&H", IDC_DEL008,
725 "Control-&? (127)", IDC_DEL127, NULL);
726 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
727 "&Standard", IDC_HOMETILDE,
728 "&rxvt", IDC_HOMERXVT, NULL);
729 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
730 "ESC[n&~", IDC_FUNCTILDE,
731 "&Linux", IDC_FUNCLINUX,
732 "&Xterm R6", IDC_FUNCXTERM,
733 "&VT400", IDC_FUNCVT400, NULL);
735 beginbox(&cp, "Application keypad settings:",
736 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
738 "Application ke&ypad and cursor keys totally disabled",
740 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
741 "&Normal", IDC_CURNORMAL,
742 "A&pplication", IDC_CURAPPLIC, NULL);
743 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
744 "Nor&mal", IDC_KPNORMAL,
745 "Appl&ication", IDC_KPAPPLIC,
746 "N&etHack", IDC_KPNH, NULL);
748 beginbox(&cp, "Enable extra keyboard features:",
749 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3);
750 checkbox(&cp, "Application and AltGr ac&t as Compose key",
754 treeview_insert(&tvfaff, 1, "Keyboard");
757 /* The Window panel. Accelerators used: [acgo] bsdkw4ylp */
760 ctlposinit(&cp, hwnd, 80, 3, 13);
761 bartitle(&cp, "Options controlling PuTTY's window",
763 beginbox(&cp, "Set the size of the window",
764 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
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",
772 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
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, 0);
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);
787 treeview_insert(&tvfaff, 0, "Window");
790 /* The Appearance panel. Accelerators used: [acgo] rmkhti */
793 ctlposinit(&cp, hwnd, 80, 3, 13);
794 bartitle(&cp, "Options controlling PuTTY's appearance",
796 beginbox(&cp, "Adjust the use of the cursor",
797 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1);
798 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
800 beginbox(&cp, "Set the font used in the terminal window",
801 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2);
802 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
804 beginbox(&cp, "Adjust the use of the window title",
805 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3);
808 "Initial window &title:", IDC_WINTITLE,
809 IDC_WINEDIT, 100, NULL);
810 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
813 treeview_insert(&tvfaff, 1, "Appearance");
816 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
819 ctlposinit(&cp, hwnd, 80, 3, 13);
820 bartitle(&cp, "Options controlling character set translation",
821 IDC_TITLE_TRANSLATION);
822 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
823 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
825 "Handling of line drawing characters:", IDC_VTSTATIC,
826 "Font has &XWindows encoding", IDC_VTXWINDOWS,
827 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
828 "Use font in O&EM mode only", IDC_VTOEMONLY,
829 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
830 IDC_VTPOORMAN, NULL);
832 beginbox(&cp, "Enable character set translation on received data",
833 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
835 "Character set translation:", IDC_XLATSTATIC,
837 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
838 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
839 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
841 beginbox(&cp, "Enable character set translation on input data",
842 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
843 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
847 treeview_insert(&tvfaff, 1, "Translation");
850 /* The Selection panel. Accelerators used: [acgo] wxst */
853 ctlposinit(&cp, hwnd, 80, 3, 13);
854 bartitle(&cp, "Options controlling copy and paste",
855 IDC_TITLE_SELECTION);
856 beginbox(&cp, "Control which mouse button does which thing",
857 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
858 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
859 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
860 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
863 beginbox(&cp, "Control the select-one-word-at-a-time mode",
864 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
865 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
866 "&Set", IDC_CCSET, IDC_CCEDIT,
867 "&to class", IDC_CCSTATIC2);
870 treeview_insert(&tvfaff, 1, "Selection");
873 /* The Colours panel. Accelerators used: [acgo] blum */
876 ctlposinit(&cp, hwnd, 80, 3, 13);
877 bartitle(&cp, "Options controlling use of colours",
879 beginbox(&cp, "General options for colour usage",
880 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
881 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
882 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
884 beginbox(&cp, "Adjust the precise colours PuTTY displays",
885 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
886 colouredit(&cp, "Select a colo&ur and then click to modify it:",
887 IDC_COLOURSTATIC, IDC_COLOURLIST,
888 "&Modify...", IDC_CHANGE,
889 "Red:", IDC_RSTATIC, IDC_RVALUE,
890 "Green:", IDC_GSTATIC, IDC_GVALUE,
891 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
894 treeview_insert(&tvfaff, 1, "Colours");
897 /* 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, IDC_BOXT_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, IDC_BOXT_CONNECTION2);
911 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
912 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
915 treeview_insert(&tvfaff, 0, "Connection");
918 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
921 ctlposinit(&cp, hwnd, 80, 3, 13);
923 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
924 beginbox(&cp, "Data to send to the server",
925 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
926 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
927 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
928 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
929 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
931 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
933 beginbox(&cp, "Telnet protocol adjustments",
934 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
935 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
936 "&BSD (commonplace)", IDC_EMBSD,
937 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
940 treeview_insert(&tvfaff, 1, "Telnet");
944 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
945 if (backends[2].backend != NULL) {
947 ctlposinit(&cp, hwnd, 80, 3, 13);
949 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
950 beginbox(&cp, "Data to send to the server",
951 IDC_BOX_SSH1, IDC_BOXT_SSH1);
953 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
956 beginbox(&cp, "Authentication options",
957 IDC_BOX_SSH2, IDC_BOXT_SSH2);
958 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
960 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
961 editbutton(&cp, "Private &key file for authentication:",
962 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
964 beginbox(&cp, "Protocol options",
965 IDC_BOX_SSH3, IDC_BOXT_SSH3);
966 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
967 radioline(&cp, "Preferred SSH protocol version:",
968 IDC_SSHPROTSTATIC, 2,
969 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
970 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
971 "&3DES", IDC_CIPHER3DES,
972 "&Blowfish", IDC_CIPHERBLOWF,
973 "&DES", IDC_CIPHERDES, NULL);
974 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
978 treeview_insert(&tvfaff, 1, "SSH");
982 init_dlg_ctrls(hwnd);
983 for (i = 0; i < nsessions; i++)
984 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
985 0, (LPARAM) (sessions[i]));
988 * Hide all the controls to start with.
990 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
993 * Put the treeview selection on to the Session panel. This
994 * should also cause unhiding of the relevant controls.
996 TreeView_SelectItem(treeview, hsession);
999 * Set focus into the first available control.
1003 ctl = GetDlgItem(hwnd, IDC_HOST);
1004 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1008 SetWindowLong(hwnd, GWL_USERDATA, 1);
1012 * Button release should trigger WM_OK if there was a
1013 * previous double click on the session list.
1017 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1020 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1021 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1022 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1026 item.pszText = buffer;
1027 item.cchTextMax = sizeof(buffer);
1028 item.mask = TVIF_TEXT;
1029 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1030 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1031 if (!strcmp(buffer, "Session"))
1032 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1033 if (!strcmp(buffer, "Keyboard"))
1034 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1035 if (!strcmp(buffer, "Terminal"))
1036 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1037 if (!strcmp(buffer, "Window"))
1038 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1039 if (!strcmp(buffer, "Appearance"))
1040 hide(hwnd, FALSE, appearancepanelstart, appearancepanelend);
1041 if (!strcmp(buffer, "Connection"))
1042 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1043 if (!strcmp(buffer, "Telnet"))
1044 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1045 if (!strcmp(buffer, "SSH"))
1046 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1047 if (!strcmp(buffer, "Selection"))
1048 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1049 if (!strcmp(buffer, "Colours"))
1050 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1051 if (!strcmp(buffer, "Translation"))
1052 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1054 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1060 * Only process WM_COMMAND once the dialog is fully formed.
1062 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1065 EndDialog (hwnd, 1);
1070 EndDialog (hwnd, 0);
1072 case IDC_PROTTELNET:
1075 if (HIWORD(wParam) == BN_CLICKED ||
1076 HIWORD(wParam) == BN_DOUBLECLICKED) {
1077 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1078 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1079 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1080 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1081 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1082 cfg.port = i ? 22 : 23;
1083 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1088 if (HIWORD(wParam) == EN_CHANGE)
1089 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1090 sizeof(cfg.host)-1);
1093 if (HIWORD(wParam) == EN_CHANGE)
1094 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1097 if (HIWORD(wParam) == EN_CHANGE) {
1098 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1100 GetDlgItemText (hwnd, IDC_SESSEDIT,
1101 savedsession, sizeof(savedsession)-1);
1102 savedsession[sizeof(savedsession)-1] = '\0';
1106 if (HIWORD(wParam) == BN_CLICKED ||
1107 HIWORD(wParam) == BN_DOUBLECLICKED) {
1112 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1114 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1115 LB_GETCURSEL, 0, 0);
1120 strcpy (str, sessions[n]);
1122 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1123 get_sesslist (FALSE);
1124 get_sesslist (TRUE);
1125 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1127 for (i = 0; i < nsessions; i++)
1128 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1129 0, (LPARAM) (sessions[i]));
1130 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1136 if (LOWORD(wParam) == IDC_SESSLOAD &&
1137 HIWORD(wParam) != BN_CLICKED &&
1138 HIWORD(wParam) != BN_DOUBLECLICKED)
1140 if (LOWORD(wParam) == IDC_SESSLIST &&
1141 HIWORD(wParam) != LBN_DBLCLK)
1144 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1145 LB_GETCURSEL, 0, 0);
1151 isdef = !strcmp(sessions[n], "Default Settings");
1152 load_settings (sessions[n], !isdef, &cfg);
1153 init_dlg_ctrls(hwnd);
1155 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1157 if (LOWORD(wParam) == IDC_SESSLIST) {
1159 * A double-click on a saved session should
1160 * actually start the session, not just load it.
1161 * Unless it's Default Settings or some other
1162 * host-less set of saved settings.
1171 if (HIWORD(wParam) == BN_CLICKED ||
1172 HIWORD(wParam) == BN_DOUBLECLICKED) {
1173 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1174 LB_GETCURSEL, 0, 0);
1175 if (n == LB_ERR || n == 0) {
1179 del_settings(sessions[n]);
1180 get_sesslist (FALSE);
1181 get_sesslist (TRUE);
1182 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1184 for (i = 0; i < nsessions; i++)
1185 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1186 0, (LPARAM) (sessions[i]));
1187 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1191 if (HIWORD(wParam) == EN_CHANGE)
1192 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1196 if (HIWORD(wParam) == BN_CLICKED ||
1197 HIWORD(wParam) == BN_DOUBLECLICKED)
1198 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1202 if (HIWORD(wParam) == BN_CLICKED ||
1203 HIWORD(wParam) == BN_DOUBLECLICKED)
1204 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1207 if (HIWORD(wParam) == BN_CLICKED ||
1208 HIWORD(wParam) == BN_DOUBLECLICKED)
1212 if (HIWORD(wParam) == BN_CLICKED ||
1213 HIWORD(wParam) == BN_DOUBLECLICKED)
1218 if (HIWORD(wParam) == BN_CLICKED ||
1219 HIWORD(wParam) == BN_DOUBLECLICKED)
1220 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1224 if (HIWORD(wParam) == BN_CLICKED ||
1225 HIWORD(wParam) == BN_DOUBLECLICKED) {
1226 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1227 cfg.nethack_keypad = FALSE;
1231 if (HIWORD(wParam) == BN_CLICKED ||
1232 HIWORD(wParam) == BN_DOUBLECLICKED) {
1233 cfg.app_keypad = FALSE;
1234 cfg.nethack_keypad = TRUE;
1239 if (HIWORD(wParam) == BN_CLICKED ||
1240 HIWORD(wParam) == BN_DOUBLECLICKED)
1241 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1244 if (HIWORD(wParam) == BN_CLICKED ||
1245 HIWORD(wParam) == BN_DOUBLECLICKED)
1246 cfg.no_applic = IsDlgButtonChecked (hwnd, IDC_NOAPPLIC);
1249 if (HIWORD(wParam) == BN_CLICKED ||
1250 HIWORD(wParam) == BN_DOUBLECLICKED)
1251 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1254 if (HIWORD(wParam) == BN_CLICKED ||
1255 HIWORD(wParam) == BN_DOUBLECLICKED)
1256 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1259 if (HIWORD(wParam) == BN_CLICKED ||
1260 HIWORD(wParam) == BN_DOUBLECLICKED)
1261 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1264 if (HIWORD(wParam) == BN_CLICKED ||
1265 HIWORD(wParam) == BN_DOUBLECLICKED)
1266 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1269 if (HIWORD(wParam) == BN_CLICKED ||
1270 HIWORD(wParam) == BN_DOUBLECLICKED)
1271 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1273 case IDC_SCROLLDISP:
1274 if (HIWORD(wParam) == BN_CLICKED ||
1275 HIWORD(wParam) == BN_DOUBLECLICKED)
1276 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1278 case IDC_COMPOSEKEY:
1279 if (HIWORD(wParam) == BN_CLICKED ||
1280 HIWORD(wParam) == BN_DOUBLECLICKED)
1281 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1284 if (HIWORD(wParam) == BN_CLICKED ||
1285 HIWORD(wParam) == BN_DOUBLECLICKED)
1286 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1289 if (HIWORD(wParam) == BN_CLICKED ||
1290 HIWORD(wParam) == BN_DOUBLECLICKED)
1291 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1294 if (HIWORD(wParam) == BN_CLICKED ||
1295 HIWORD(wParam) == BN_DOUBLECLICKED)
1296 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1299 if (HIWORD(wParam) == EN_CHANGE)
1300 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1303 if (HIWORD(wParam) == EN_CHANGE)
1304 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1307 if (HIWORD(wParam) == EN_CHANGE)
1308 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1310 case IDC_CHOOSEFONT:
1311 lf.lfHeight = cfg.fontheight;
1312 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1313 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1314 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1315 lf.lfCharSet = cfg.fontcharset;
1316 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1317 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1318 lf.lfQuality = DEFAULT_QUALITY;
1319 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1320 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1321 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1323 cf.lStructSize = sizeof(cf);
1324 cf.hwndOwner = hwnd;
1326 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1327 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1329 if (ChooseFont (&cf)) {
1330 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1331 cfg.font[sizeof(cfg.font)-1] = '\0';
1332 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1333 cfg.fontcharset = lf.lfCharSet;
1334 cfg.fontheight = lf.lfHeight;
1335 fmtfont (fontstatic);
1336 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1340 if (HIWORD(wParam) == BN_CLICKED ||
1341 HIWORD(wParam) == BN_DOUBLECLICKED)
1342 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1345 if (HIWORD(wParam) == BN_CLICKED ||
1346 HIWORD(wParam) == BN_DOUBLECLICKED)
1347 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1350 if (HIWORD(wParam) == BN_CLICKED ||
1351 HIWORD(wParam) == BN_DOUBLECLICKED)
1352 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1355 if (HIWORD(wParam) == BN_CLICKED ||
1356 HIWORD(wParam) == BN_DOUBLECLICKED)
1357 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1360 if (HIWORD(wParam) == BN_CLICKED ||
1361 HIWORD(wParam) == BN_DOUBLECLICKED)
1362 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1365 if (HIWORD(wParam) == BN_CLICKED ||
1366 HIWORD(wParam) == BN_DOUBLECLICKED)
1367 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1370 if (HIWORD(wParam) == BN_CLICKED ||
1371 HIWORD(wParam) == BN_DOUBLECLICKED)
1372 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1375 if (HIWORD(wParam) == EN_CHANGE)
1376 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1377 sizeof(cfg.wintitle)-1);
1380 if (HIWORD(wParam) == BN_CLICKED ||
1381 HIWORD(wParam) == BN_DOUBLECLICKED)
1382 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1385 if (HIWORD(wParam) == BN_CLICKED ||
1386 HIWORD(wParam) == BN_DOUBLECLICKED)
1387 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1390 if (HIWORD(wParam) == EN_CHANGE)
1391 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1392 sizeof(cfg.termtype)-1);
1395 if (HIWORD(wParam) == EN_CHANGE)
1396 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1397 sizeof(cfg.termspeed)-1);
1400 if (HIWORD(wParam) == EN_CHANGE)
1401 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1402 sizeof(cfg.username)-1);
1406 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1409 if (HIWORD(wParam) == BN_CLICKED ||
1410 HIWORD(wParam) == BN_DOUBLECLICKED) {
1411 char str[sizeof(cfg.environmt)];
1413 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1418 p = str + strlen(str);
1420 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1430 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1432 p[strlen(str)+1] = '\0';
1433 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1435 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1436 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1438 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1439 MB_OK | MB_ICONERROR);
1444 if (HIWORD(wParam) != BN_CLICKED &&
1445 HIWORD(wParam) != BN_DOUBLECLICKED)
1447 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1453 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1478 if (HIWORD(wParam) == BN_CLICKED ||
1479 HIWORD(wParam) == BN_DOUBLECLICKED)
1480 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1483 if (HIWORD(wParam) == BN_CLICKED ||
1484 HIWORD(wParam) == BN_DOUBLECLICKED)
1485 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1488 if (HIWORD(wParam) == BN_CLICKED ||
1489 HIWORD(wParam) == BN_DOUBLECLICKED)
1490 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1492 case IDC_CIPHER3DES:
1493 case IDC_CIPHERBLOWF:
1495 if (HIWORD(wParam) == BN_CLICKED ||
1496 HIWORD(wParam) == BN_DOUBLECLICKED) {
1497 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1498 cfg.cipher = CIPHER_3DES;
1499 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1500 cfg.cipher = CIPHER_BLOWFISH;
1501 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1502 cfg.cipher = CIPHER_DES;
1507 if (HIWORD(wParam) == BN_CLICKED ||
1508 HIWORD(wParam) == BN_DOUBLECLICKED) {
1509 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1511 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1516 if (HIWORD(wParam) == BN_CLICKED ||
1517 HIWORD(wParam) == BN_DOUBLECLICKED)
1518 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1521 if (HIWORD(wParam) == EN_CHANGE)
1522 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1523 sizeof(cfg.keyfile)-1);
1526 if (HIWORD(wParam) == EN_CHANGE)
1527 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1528 sizeof(cfg.remote_cmd)-1);
1531 memset(&of, 0, sizeof(of));
1532 #ifdef OPENFILENAME_SIZE_VERSION_400
1533 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1535 of.lStructSize = sizeof(of);
1537 of.hwndOwner = hwnd;
1538 of.lpstrFilter = "All Files\0*\0\0\0";
1539 of.lpstrCustomFilter = NULL;
1540 of.nFilterIndex = 1;
1541 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1542 of.nMaxFile = sizeof(filename);
1543 of.lpstrFileTitle = NULL;
1544 of.lpstrInitialDir = NULL;
1545 of.lpstrTitle = "Select Public Key File";
1547 if (GetOpenFileName(&of)) {
1548 strcpy(cfg.keyfile, filename);
1549 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1554 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1560 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1565 for (i=0; i<256; i++)
1566 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1569 cfg.wordness[i] = n;
1570 SendDlgItemMessage (hwnd, IDC_CCLIST,
1571 LB_DELETESTRING, i, 0);
1572 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1573 (i>=0x21 && i != 0x7F) ? i : ' ',
1575 SendDlgItemMessage (hwnd, IDC_CCLIST,
1582 case IDC_BOLDCOLOUR:
1583 if (HIWORD(wParam) == BN_CLICKED ||
1584 HIWORD(wParam) == BN_DOUBLECLICKED) {
1586 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1587 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1588 if (cfg.bold_colour && n!=22) {
1589 for (i=0; i<22; i++)
1591 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1593 (LPARAM) colours[i]);
1594 } else if (!cfg.bold_colour && n!=12) {
1597 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1598 LB_DELETESTRING, i, 0);
1603 if (HIWORD(wParam) == BN_CLICKED ||
1604 HIWORD(wParam) == BN_DOUBLECLICKED)
1605 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1607 case IDC_COLOURLIST:
1608 if (HIWORD(wParam) == LBN_DBLCLK ||
1609 HIWORD(wParam) == LBN_SELCHANGE) {
1610 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1612 if (!cfg.bold_colour)
1613 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1614 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1615 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1616 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1620 if (HIWORD(wParam) == BN_CLICKED ||
1621 HIWORD(wParam) == BN_DOUBLECLICKED) {
1622 static CHOOSECOLOR cc;
1623 static DWORD custom[16] = {0}; /* zero initialisers */
1624 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1626 if (!cfg.bold_colour)
1627 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1628 cc.lStructSize = sizeof(cc);
1629 cc.hwndOwner = hwnd;
1630 cc.hInstance = (HWND)hinst;
1631 cc.lpCustColors = custom;
1632 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1634 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1635 if (ChooseColor(&cc)) {
1637 (unsigned char) (cc.rgbResult & 0xFF);
1639 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1641 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1642 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1644 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1646 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1652 case IDC_KOI8WIN1251:
1653 case IDC_88592WIN1250:
1654 case IDC_88592CP852:
1655 cfg.xlat_enablekoiwin =
1656 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1657 cfg.xlat_88592w1250 =
1658 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1659 cfg.xlat_88592cp852 =
1660 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1662 case IDC_CAPSLOCKCYR:
1663 if (HIWORD(wParam) == BN_CLICKED ||
1664 HIWORD(wParam) == BN_DOUBLECLICKED) {
1665 cfg.xlat_capslockcyr =
1666 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1669 case IDC_VTXWINDOWS:
1674 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1675 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1676 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1682 EndDialog (hwnd, 0);
1685 /* Grrr Explorer will maximize Dialogs! */
1687 if (wParam == SIZE_MAXIMIZED)
1694 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1695 WPARAM wParam, LPARAM lParam) {
1696 static HWND page = NULL;
1698 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1700 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1701 EnableWindow(hwnd, 0);
1702 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1703 GetParent(hwnd), AboutProc);
1704 EnableWindow(hwnd, 1);
1705 SetActiveWindow(hwnd);
1707 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1710 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1711 WPARAM wParam, LPARAM lParam) {
1713 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1716 void defuse_showwindow(void) {
1718 * Work around the fact that the app's first call to ShowWindow
1719 * will ignore the default in favour of the shell-provided
1724 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1726 ShowWindow(hwnd, SW_HIDE);
1727 DestroyWindow(hwnd);
1731 int do_config (void) {
1735 savedsession[0] = '\0';
1736 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1737 get_sesslist(FALSE);
1742 int do_reconfig (HWND hwnd) {
1746 backup_cfg = cfg; /* structure copy */
1747 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1749 cfg = backup_cfg; /* structure copy */
1756 void logevent (char *string) {
1757 if (nevents >= negsize) {
1759 events = srealloc (events, negsize * sizeof(*events));
1761 events[nevents] = smalloc(1+strlen(string));
1762 strcpy (events[nevents], string);
1766 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1768 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1769 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1773 void showeventlog (HWND hwnd) {
1775 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1777 ShowWindow (logbox, SW_SHOWNORMAL);
1781 void showabout (HWND hwnd) {
1783 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1785 ShowWindow (abtbox, SW_SHOWNORMAL);
1789 void verify_ssh_host_key(char *host, int port, char *keytype,
1790 char *keystr, char *fingerprint) {
1793 static const char absentmsg[] =
1794 "The server's host key is not cached in the registry. You\n"
1795 "have no guarantee that the server is the computer you\n"
1797 "The server's key fingerprint is:\n"
1799 "If you trust this host, hit Yes to add the key to\n"
1800 "PuTTY's cache and carry on connecting.\n"
1801 "If you do not trust this host, hit No to abandon the\n"
1804 static const char wrongmsg[] =
1805 "WARNING - POTENTIAL SECURITY BREACH!\n"
1807 "The server's host key does not match the one PuTTY has\n"
1808 "cached in the registry. This means that either the\n"
1809 "server administrator has changed the host key, or you\n"
1810 "have actually connected to another computer pretending\n"
1811 "to be the server.\n"
1812 "The new key fingerprint is:\n"
1814 "If you were expecting this change and trust the new key,\n"
1815 "hit Yes to update PuTTY's cache and continue connecting.\n"
1816 "If you want to carry on connecting but without updating\n"
1817 "the cache, hit No.\n"
1818 "If you want to abandon the connection completely, hit\n"
1819 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1822 static const char mbtitle[] = "PuTTY Security Alert";
1825 char message[160+ /* sensible fingerprint max size */
1826 (sizeof(absentmsg) > sizeof(wrongmsg) ?
1827 sizeof(absentmsg) : sizeof(wrongmsg))];
1830 * Verify the key against the registry.
1832 ret = verify_host_key(host, port, keytype, keystr);
1834 if (ret == 0) /* success - key matched OK */
1836 if (ret == 2) { /* key was different */
1838 sprintf(message, wrongmsg, fingerprint);
1839 mbret = MessageBox(NULL, message, mbtitle,
1840 MB_ICONWARNING | MB_YESNOCANCEL);
1842 store_host_key(host, port, keytype, keystr);
1843 if (mbret == IDCANCEL)
1846 if (ret == 1) { /* key was absent */
1848 sprintf(message, absentmsg, fingerprint);
1849 mbret = MessageBox(NULL, message, mbtitle,
1850 MB_ICONWARNING | MB_YESNO);
1853 store_host_key(host, port, keytype, keystr);