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,
182 IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
183 IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
204 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
205 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
206 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3,
232 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
233 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
252 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
253 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
272 appearancepanelstart,
273 IDC_TITLE_APPEARANCE,
274 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1,
275 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2,
276 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3,
289 connectionpanelstart,
290 IDC_TITLE_CONNECTION,
291 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
292 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
303 IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
304 IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
322 IDC_BOX_SSH1, IDC_BOXT_SSH1,
323 IDC_BOX_SSH2, IDC_BOXT_SSH2,
324 IDC_BOX_SSH3, IDC_BOXT_SSH3,
346 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
347 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
360 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
361 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
375 translationpanelstart,
376 IDC_TITLE_TRANSLATION,
377 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
378 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
379 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
396 static const char *const colours[] = {
397 "Default Foreground", "Default Bold Foreground",
398 "Default Background", "Default Bold Background",
399 "Cursor Text", "Cursor Colour",
400 "ANSI Black", "ANSI Black Bold",
401 "ANSI Red", "ANSI Red Bold",
402 "ANSI Green", "ANSI Green Bold",
403 "ANSI Yellow", "ANSI Yellow Bold",
404 "ANSI Blue", "ANSI Blue Bold",
405 "ANSI Magenta", "ANSI Magenta Bold",
406 "ANSI Cyan", "ANSI Cyan Bold",
407 "ANSI White", "ANSI White Bold"
409 static const int permcolour[] = {
410 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
411 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
412 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
415 static void fmtfont (char *buf) {
416 sprintf (buf, "Font: %s, ", cfg.font);
418 strcat(buf, "bold, ");
419 if (cfg.fontheight == 0)
420 strcat (buf, "default height");
422 sprintf (buf+strlen(buf), "%d-%s",
423 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
424 (cfg.fontheight < 0 ? "pixel" : "point"));
427 static void init_dlg_ctrls(HWND hwnd) {
429 char fontstatic[256];
431 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
432 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
433 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
434 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
435 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
436 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
437 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
439 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
440 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
441 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
442 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
443 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
444 cfg.funky_type == 0 ? IDC_FUNCTILDE :
445 cfg.funky_type == 1 ? IDC_FUNCLINUX :
446 cfg.funky_type == 2 ? IDC_FUNCXTERM :
447 cfg.funky_type == 3 ? IDC_FUNCVT400 :
449 CheckDlgButton (hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
450 CheckDlgButton (hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
451 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
452 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
453 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
454 cfg.nethack_keypad ? IDC_KPNH :
455 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
456 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
457 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
458 CheckDlgButton (hwnd, IDC_ALTONLY, cfg.alt_only);
459 CheckDlgButton (hwnd, IDC_COMPOSEKEY, cfg.compose_key);
460 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
461 CheckDlgButton (hwnd, IDC_ALWAYSONTOP, cfg.alwaysontop);
462 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
463 CheckDlgButton (hwnd, IDC_SCROLLDISP, cfg.scroll_on_disp);
465 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
466 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
467 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
468 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
469 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
470 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
471 fmtfont (fontstatic);
472 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
473 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
474 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
475 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
477 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
478 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
479 CheckRadioButton (hwnd, IDC_CURBLOCK, IDC_CURVERT,
480 cfg.cursor_type==0 ? IDC_CURBLOCK :
481 cfg.cursor_type==1 ? IDC_CURUNDER : IDC_CURVERT);
482 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
483 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
484 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
485 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
486 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
488 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
489 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
490 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
491 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
492 CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
493 cfg.logtype == 0 ? IDC_LSTATOFF :
494 cfg.logtype == 1 ? IDC_LSTATASCII :
497 char *p = cfg.environmt;
499 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
504 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
505 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
507 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
508 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
509 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
510 CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
511 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
512 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
513 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
514 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
515 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
517 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
518 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
519 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
520 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
521 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
523 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
524 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
526 static int tabs[4] = {25, 61, 96, 128};
527 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
530 for (i=0; i<256; i++) {
532 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
533 (i>=0x21 && i != 0x7F) ? i : ' ',
535 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
539 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
540 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
543 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
545 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
546 LB_DELETESTRING, i, 0);
548 if (cfg.bold_colour || permcolour[i])
549 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_ADDSTRING, 0,
550 (LPARAM) colours[i]);
552 SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_SETCURSEL, 0, 0);
553 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
554 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
555 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
557 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
558 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
559 cfg.xlat_88592cp852 ? IDC_88592CP852 :
560 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
562 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
563 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
564 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
565 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
566 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
570 static void hide(HWND hwnd, int hide, int minid, int maxid) {
572 for (i = minid; i < maxid; i++) {
573 HWND ctl = GetDlgItem(hwnd, i);
575 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
580 struct treeview_faff {
585 static HTREEITEM treeview_insert(struct treeview_faff *faff,
586 int level, char *text) {
590 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
591 ins.hInsertAfter = faff->lastat[level];
592 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
593 #define INSITEM DUMMYUNIONNAME.item
597 ins.INSITEM.mask = TVIF_TEXT;
598 ins.INSITEM.pszText = text;
599 newitem = TreeView_InsertItem(faff->treeview, &ins);
601 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
602 faff->lastat[level] = newitem;
603 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
608 * This _huge_ function is the configuration box.
610 static int GenericMainDlgProc (HWND hwnd, UINT msg,
611 WPARAM wParam, LPARAM lParam,
614 struct treeview_faff tvfaff;
617 char filename[sizeof(cfg.keyfile)];
620 char fontstatic[256];
622 struct servent * service;
628 SetWindowLong(hwnd, GWL_USERDATA, 0);
632 { /* centre the window */
635 hw = GetDesktopWindow();
636 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
637 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
638 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
639 rd.right-rd.left, rd.bottom-rd.top, TRUE);
643 * Create the tree view.
650 r.left = 3; r.right = r.left + 75;
651 r.top = 3; r.bottom = r.top + 10;
652 MapDialogRect(hwnd, &r);
653 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
654 WS_CHILD | WS_VISIBLE,
656 r.right-r.left, r.bottom-r.top,
657 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
658 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
659 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
661 r.left = 3; r.right = r.left + 75;
662 r.top = 13; r.bottom = r.top + 206;
663 MapDialogRect(hwnd, &r);
664 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
665 WS_CHILD | WS_VISIBLE |
666 WS_TABSTOP | TVS_HASLINES |
667 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
668 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
670 r.right-r.left, r.bottom-r.top,
671 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
672 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
673 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
674 tvfaff.treeview = treeview;
675 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
679 * Create the various panelfuls of controls.
682 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
685 ctlposinit(&cp, hwnd, 80, 3, 13);
686 bartitle(&cp, "Basic options for your PuTTY session",
689 beginbox(&cp, "Specify your connection by host name",
690 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
692 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
693 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
694 if (backends[2].backend == NULL) {
695 /* this is PuTTYtel, so only two protocols available */
696 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
698 "&Telnet", IDC_PROTTELNET, NULL);
700 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
702 "&Telnet", IDC_PROTTELNET,
711 beginbox(&cp, "Load, save or delete a stored session",
712 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
713 sesssaver(&cp, "Sav&ed Sessions",
714 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
715 "&Load", IDC_SESSLOAD,
716 "&Save", IDC_SESSSAVE,
717 "&Delete", IDC_SESSDEL, NULL);
720 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
721 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
724 hsession = treeview_insert(&tvfaff, 0, "Session");
727 /* The Terminal panel. Accelerators used: [acgo] &dflbenuw */
730 ctlposinit(&cp, hwnd, 80, 3, 13);
731 bartitle(&cp, "Options controlling the terminal emulation",
733 beginbox(&cp, "Set various terminal options",
734 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
735 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
736 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
737 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
738 checkbox(&cp, "&Beep enabled", IDC_BEEP);
739 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
740 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
741 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
744 beginbox(&cp, "Control session logging",
745 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
747 "Session logging:", IDC_LSTATSTATIC,
748 "Logging turned &off completely", IDC_LSTATOFF,
749 "Log printable output only", IDC_LSTATASCII,
750 "Log all session output", IDC_LSTATRAW, NULL);
751 editbutton(&cp, "Log &file name:",
752 IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
756 treeview_insert(&tvfaff, 0, "Terminal");
759 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmietu */
762 ctlposinit(&cp, hwnd, 80, 3, 13);
763 bartitle(&cp, "Options controlling the effects of keys",
765 beginbox(&cp, "Change the sequences sent by:",
766 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
767 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
768 "Control-&H", IDC_DEL008,
769 "Control-&? (127)", IDC_DEL127, NULL);
770 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
771 "&Standard", IDC_HOMETILDE,
772 "&rxvt", IDC_HOMERXVT, NULL);
773 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
774 "ESC[n&~", IDC_FUNCTILDE,
775 "&Linux", IDC_FUNCLINUX,
776 "&Xterm R6", IDC_FUNCXTERM,
777 "&VT400", IDC_FUNCVT400, NULL);
779 beginbox(&cp, "Application keypad settings:",
780 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
782 "Application c&ursor keys totally disabled",
784 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
785 "&Normal", IDC_CURNORMAL,
786 "A&pplication", IDC_CURAPPLIC, NULL);
788 "Application ke&ypad keys totally disabled",
790 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
791 "Nor&mal", IDC_KPNORMAL,
792 "Appl&ication", IDC_KPAPPLIC,
793 "N&etHack", IDC_KPNH, NULL);
795 beginbox(&cp, "Enable extra keyboard features:",
796 IDC_BOX_KEYBOARD3, IDC_BOXT_KEYBOARD3);
797 checkbox(&cp, "Application and AltGr ac&t as Compose key",
801 treeview_insert(&tvfaff, 1, "Keyboard");
804 /* The Window panel. Accelerators used: [acgo] bsdkw4ylpt */
807 ctlposinit(&cp, hwnd, 80, 3, 13);
808 bartitle(&cp, "Options controlling PuTTY's window",
810 beginbox(&cp, "Set the size of the window",
811 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
813 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
814 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
816 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
818 beginbox(&cp, "Control the scrollback in the window",
819 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
820 staticedit(&cp, "Lines of &scrollback",
821 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
822 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
823 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
824 checkbox(&cp, "Reset scrollback on dis&play activity",
827 beginbox(&cp, NULL, IDC_BOX_WINDOW3, 0);
828 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
829 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
830 checkbox(&cp, "S&ystem menu appears on ALT-Space", IDC_ALTSPACE);
831 checkbox(&cp, "System menu appears on A< alone", IDC_ALTONLY);
832 checkbox(&cp, "Ensure window is always on &top", IDC_ALWAYSONTOP);
835 treeview_insert(&tvfaff, 0, "Window");
838 /* The Appearance panel. Accelerators used: [acgo] rmkhtibluv */
841 ctlposinit(&cp, hwnd, 80, 3, 13);
842 bartitle(&cp, "Options controlling PuTTY's appearance",
843 IDC_TITLE_APPEARANCE);
844 beginbox(&cp, "Adjust the use of the cursor",
845 IDC_BOX_APPEARANCE1, IDC_BOXT_APPEARANCE1);
846 radioline(&cp, "Cursor appearance:", IDC_CURSORSTATIC, 3,
847 "B&lock", IDC_CURBLOCK,
848 "&Underline", IDC_CURUNDER,
849 "&Vertical line", IDC_CURVERT,
851 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
853 beginbox(&cp, "Set the font used in the terminal window",
854 IDC_BOX_APPEARANCE2, IDC_BOXT_APPEARANCE2);
855 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
857 beginbox(&cp, "Adjust the use of the window title",
858 IDC_BOX_APPEARANCE3, IDC_BOXT_APPEARANCE3);
860 "Window &title:", IDC_WINTITLE,
861 IDC_WINEDIT, 100, NULL);
862 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
865 treeview_insert(&tvfaff, 1, "Appearance");
868 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
871 ctlposinit(&cp, hwnd, 80, 3, 13);
872 bartitle(&cp, "Options controlling character set translation",
873 IDC_TITLE_TRANSLATION);
874 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
875 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
877 "Handling of line drawing characters:", IDC_VTSTATIC,
878 "Font has &XWindows encoding", IDC_VTXWINDOWS,
879 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
880 "Use font in O&EM mode only", IDC_VTOEMONLY,
881 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
882 IDC_VTPOORMAN, NULL);
884 beginbox(&cp, "Enable character set translation on received data",
885 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
887 "Character set translation:", IDC_XLATSTATIC,
889 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
890 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
891 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
893 beginbox(&cp, "Enable character set translation on input data",
894 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
895 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
899 treeview_insert(&tvfaff, 1, "Translation");
902 /* The Selection panel. Accelerators used: [acgo] wxst */
905 ctlposinit(&cp, hwnd, 80, 3, 13);
906 bartitle(&cp, "Options controlling copy and paste",
907 IDC_TITLE_SELECTION);
908 beginbox(&cp, "Control which mouse button does which thing",
909 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
910 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
911 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
912 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
915 beginbox(&cp, "Control the select-one-word-at-a-time mode",
916 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
917 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
918 "&Set", IDC_CCSET, IDC_CCEDIT,
919 "&to class", IDC_CCSTATIC2);
922 treeview_insert(&tvfaff, 1, "Selection");
925 /* The Colours panel. Accelerators used: [acgo] blum */
928 ctlposinit(&cp, hwnd, 80, 3, 13);
929 bartitle(&cp, "Options controlling use of colours",
931 beginbox(&cp, "General options for colour usage",
932 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
933 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
934 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
936 beginbox(&cp, "Adjust the precise colours PuTTY displays",
937 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
938 colouredit(&cp, "Select a colo&ur and then click to modify it:",
939 IDC_COLOURSTATIC, IDC_COLOURLIST,
940 "&Modify...", IDC_CHANGE,
941 "Red:", IDC_RSTATIC, IDC_RVALUE,
942 "Green:", IDC_GSTATIC, IDC_GVALUE,
943 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
946 treeview_insert(&tvfaff, 1, "Colours");
949 /* The Connection panel. Accelerators used: [acgo] tuk */
952 ctlposinit(&cp, hwnd, 80, 3, 13);
953 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
955 beginbox(&cp, "Data to send to the server",
956 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
957 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
958 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
961 beginbox(&cp, "Sending of null packets to keep session active",
962 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
963 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
964 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
967 treeview_insert(&tvfaff, 0, "Connection");
970 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
973 ctlposinit(&cp, hwnd, 80, 3, 13);
975 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
976 beginbox(&cp, "Data to send to the server",
977 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
978 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
979 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
980 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
981 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
983 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
985 beginbox(&cp, "Telnet protocol adjustments",
986 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
987 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
988 "&BSD (commonplace)", IDC_EMBSD,
989 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
992 treeview_insert(&tvfaff, 1, "Telnet");
996 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
997 if (backends[2].backend != NULL) {
999 ctlposinit(&cp, hwnd, 80, 3, 13);
1001 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1002 beginbox(&cp, "Data to send to the server",
1003 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1005 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1008 beginbox(&cp, "Authentication options",
1009 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1010 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1012 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1013 editbutton(&cp, "Private &key file for authentication:",
1014 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1016 beginbox(&cp, "Protocol options",
1017 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1018 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1019 checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
1020 radioline(&cp, "Preferred SSH protocol version:",
1021 IDC_SSHPROTSTATIC, 2,
1022 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1023 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1024 "&3DES", IDC_CIPHER3DES,
1025 "&Blowfish", IDC_CIPHERBLOWF,
1026 "&DES", IDC_CIPHERDES, NULL);
1027 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1031 treeview_insert(&tvfaff, 1, "SSH");
1035 init_dlg_ctrls(hwnd);
1036 for (i = 0; i < nsessions; i++)
1037 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1038 0, (LPARAM) (sessions[i]));
1041 * Hide all the controls to start with.
1043 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1046 * Put the treeview selection on to the Session panel. This
1047 * should also cause unhiding of the relevant controls.
1049 TreeView_SelectItem(treeview, hsession);
1052 * Set focus into the first available control.
1056 ctl = GetDlgItem(hwnd, IDC_HOST);
1057 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1061 SetWindowLong(hwnd, GWL_USERDATA, 1);
1065 * Button release should trigger WM_OK if there was a
1066 * previous double click on the session list.
1070 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1073 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1074 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1075 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1079 item.pszText = buffer;
1080 item.cchTextMax = sizeof(buffer);
1081 item.mask = TVIF_TEXT;
1082 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1083 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1084 if (!strcmp(buffer, "Session"))
1085 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1086 if (!strcmp(buffer, "Keyboard"))
1087 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1088 if (!strcmp(buffer, "Terminal"))
1089 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1090 if (!strcmp(buffer, "Window"))
1091 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1092 if (!strcmp(buffer, "Appearance"))
1093 hide(hwnd, FALSE, appearancepanelstart, appearancepanelend);
1094 if (!strcmp(buffer, "Connection"))
1095 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1096 if (!strcmp(buffer, "Telnet"))
1097 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1098 if (!strcmp(buffer, "SSH"))
1099 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1100 if (!strcmp(buffer, "Selection"))
1101 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1102 if (!strcmp(buffer, "Colours"))
1103 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1104 if (!strcmp(buffer, "Translation"))
1105 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1107 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1113 * Only process WM_COMMAND once the dialog is fully formed.
1115 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1118 EndDialog (hwnd, 1);
1123 EndDialog (hwnd, 0);
1125 case IDC_PROTTELNET:
1128 if (HIWORD(wParam) == BN_CLICKED ||
1129 HIWORD(wParam) == BN_DOUBLECLICKED) {
1130 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1131 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1132 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1133 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1134 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1135 cfg.port = i ? 22 : 23;
1136 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1141 if (HIWORD(wParam) == EN_CHANGE)
1142 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1143 sizeof(cfg.host)-1);
1146 if (HIWORD(wParam) == EN_CHANGE) {
1147 GetDlgItemText (hwnd, IDC_PORT, portname, 31);
1148 if (isdigit(portname[0]))
1149 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1151 service = getservbyname(portname, NULL);
1152 if (service) cfg.port = ntohs(service->s_port);
1158 if (HIWORD(wParam) == EN_CHANGE) {
1159 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1161 GetDlgItemText (hwnd, IDC_SESSEDIT,
1162 savedsession, sizeof(savedsession)-1);
1163 savedsession[sizeof(savedsession)-1] = '\0';
1167 if (HIWORD(wParam) == BN_CLICKED ||
1168 HIWORD(wParam) == BN_DOUBLECLICKED) {
1173 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1175 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1176 LB_GETCURSEL, 0, 0);
1181 strcpy (str, sessions[n]);
1183 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1184 get_sesslist (FALSE);
1185 get_sesslist (TRUE);
1186 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1188 for (i = 0; i < nsessions; i++)
1189 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1190 0, (LPARAM) (sessions[i]));
1191 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1197 if (LOWORD(wParam) == IDC_SESSLOAD &&
1198 HIWORD(wParam) != BN_CLICKED &&
1199 HIWORD(wParam) != BN_DOUBLECLICKED)
1201 if (LOWORD(wParam) == IDC_SESSLIST &&
1202 HIWORD(wParam) != LBN_DBLCLK)
1205 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1206 LB_GETCURSEL, 0, 0);
1212 isdef = !strcmp(sessions[n], "Default Settings");
1213 load_settings (sessions[n], !isdef, &cfg);
1214 init_dlg_ctrls(hwnd);
1216 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1218 SetDlgItemText(hwnd, IDC_SESSEDIT, "");
1220 if (LOWORD(wParam) == IDC_SESSLIST) {
1222 * A double-click on a saved session should
1223 * actually start the session, not just load it.
1224 * Unless it's Default Settings or some other
1225 * host-less set of saved settings.
1234 if (HIWORD(wParam) == BN_CLICKED ||
1235 HIWORD(wParam) == BN_DOUBLECLICKED) {
1236 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1237 LB_GETCURSEL, 0, 0);
1238 if (n == LB_ERR || n == 0) {
1242 del_settings(sessions[n]);
1243 get_sesslist (FALSE);
1244 get_sesslist (TRUE);
1245 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1247 for (i = 0; i < nsessions; i++)
1248 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1249 0, (LPARAM) (sessions[i]));
1250 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1254 if (HIWORD(wParam) == EN_CHANGE)
1255 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1259 if (HIWORD(wParam) == BN_CLICKED ||
1260 HIWORD(wParam) == BN_DOUBLECLICKED)
1261 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1265 if (HIWORD(wParam) == BN_CLICKED ||
1266 HIWORD(wParam) == BN_DOUBLECLICKED)
1267 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1270 if (HIWORD(wParam) == BN_CLICKED ||
1271 HIWORD(wParam) == BN_DOUBLECLICKED)
1275 if (HIWORD(wParam) == BN_CLICKED ||
1276 HIWORD(wParam) == BN_DOUBLECLICKED)
1281 if (HIWORD(wParam) == BN_CLICKED ||
1282 HIWORD(wParam) == BN_DOUBLECLICKED)
1283 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1287 if (HIWORD(wParam) == BN_CLICKED ||
1288 HIWORD(wParam) == BN_DOUBLECLICKED) {
1289 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1290 cfg.nethack_keypad = FALSE;
1294 if (HIWORD(wParam) == BN_CLICKED ||
1295 HIWORD(wParam) == BN_DOUBLECLICKED) {
1296 cfg.app_keypad = FALSE;
1297 cfg.nethack_keypad = TRUE;
1302 if (HIWORD(wParam) == BN_CLICKED ||
1303 HIWORD(wParam) == BN_DOUBLECLICKED)
1304 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1307 if (HIWORD(wParam) == BN_CLICKED ||
1308 HIWORD(wParam) == BN_DOUBLECLICKED)
1309 cfg.no_applic_c = IsDlgButtonChecked (hwnd, IDC_NOAPPLICC);
1312 if (HIWORD(wParam) == BN_CLICKED ||
1313 HIWORD(wParam) == BN_DOUBLECLICKED)
1314 cfg.no_applic_k = IsDlgButtonChecked (hwnd, IDC_NOAPPLICK);
1317 if (HIWORD(wParam) == BN_CLICKED ||
1318 HIWORD(wParam) == BN_DOUBLECLICKED)
1319 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1322 if (HIWORD(wParam) == BN_CLICKED ||
1323 HIWORD(wParam) == BN_DOUBLECLICKED)
1324 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1327 if (HIWORD(wParam) == BN_CLICKED ||
1328 HIWORD(wParam) == BN_DOUBLECLICKED)
1329 cfg.alt_only = IsDlgButtonChecked (hwnd, IDC_ALTONLY);
1332 if (HIWORD(wParam) == BN_CLICKED ||
1333 HIWORD(wParam) == BN_DOUBLECLICKED)
1334 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1336 case IDC_ALWAYSONTOP:
1337 if (HIWORD(wParam) == BN_CLICKED ||
1338 HIWORD(wParam) == BN_DOUBLECLICKED)
1339 cfg.alwaysontop = IsDlgButtonChecked (hwnd, IDC_ALWAYSONTOP);
1342 if (HIWORD(wParam) == BN_CLICKED ||
1343 HIWORD(wParam) == BN_DOUBLECLICKED)
1344 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1346 case IDC_SCROLLDISP:
1347 if (HIWORD(wParam) == BN_CLICKED ||
1348 HIWORD(wParam) == BN_DOUBLECLICKED)
1349 cfg.scroll_on_disp = IsDlgButtonChecked (hwnd, IDC_SCROLLDISP);
1351 case IDC_COMPOSEKEY:
1352 if (HIWORD(wParam) == BN_CLICKED ||
1353 HIWORD(wParam) == BN_DOUBLECLICKED)
1354 cfg.compose_key = IsDlgButtonChecked (hwnd, IDC_COMPOSEKEY);
1357 if (HIWORD(wParam) == BN_CLICKED ||
1358 HIWORD(wParam) == BN_DOUBLECLICKED)
1359 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1362 if (HIWORD(wParam) == BN_CLICKED ||
1363 HIWORD(wParam) == BN_DOUBLECLICKED)
1364 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1367 if (HIWORD(wParam) == BN_CLICKED ||
1368 HIWORD(wParam) == BN_DOUBLECLICKED)
1369 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1372 if (HIWORD(wParam) == EN_CHANGE)
1373 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1376 if (HIWORD(wParam) == EN_CHANGE)
1377 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1380 if (HIWORD(wParam) == EN_CHANGE)
1381 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1383 case IDC_CHOOSEFONT:
1384 lf.lfHeight = cfg.fontheight;
1385 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1386 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1387 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1388 lf.lfCharSet = cfg.fontcharset;
1389 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1390 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1391 lf.lfQuality = DEFAULT_QUALITY;
1392 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1393 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1394 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1396 cf.lStructSize = sizeof(cf);
1397 cf.hwndOwner = hwnd;
1399 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1400 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1402 if (ChooseFont (&cf)) {
1403 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1404 cfg.font[sizeof(cfg.font)-1] = '\0';
1405 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1406 cfg.fontcharset = lf.lfCharSet;
1407 cfg.fontheight = lf.lfHeight;
1408 fmtfont (fontstatic);
1409 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1413 if (HIWORD(wParam) == BN_CLICKED ||
1414 HIWORD(wParam) == BN_DOUBLECLICKED)
1415 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1418 if (HIWORD(wParam) == BN_CLICKED ||
1419 HIWORD(wParam) == BN_DOUBLECLICKED)
1420 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1423 if (HIWORD(wParam) == BN_CLICKED ||
1424 HIWORD(wParam) == BN_DOUBLECLICKED)
1425 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1428 if (HIWORD(wParam) == BN_CLICKED ||
1429 HIWORD(wParam) == BN_DOUBLECLICKED)
1430 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1433 if (HIWORD(wParam) == BN_CLICKED ||
1434 HIWORD(wParam) == BN_DOUBLECLICKED)
1435 cfg.cursor_type = 0;
1438 if (HIWORD(wParam) == BN_CLICKED ||
1439 HIWORD(wParam) == BN_DOUBLECLICKED)
1440 cfg.cursor_type = 1;
1443 if (HIWORD(wParam) == BN_CLICKED ||
1444 HIWORD(wParam) == BN_DOUBLECLICKED)
1445 cfg.cursor_type = 2;
1448 if (HIWORD(wParam) == BN_CLICKED ||
1449 HIWORD(wParam) == BN_DOUBLECLICKED)
1450 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1453 if (HIWORD(wParam) == BN_CLICKED ||
1454 HIWORD(wParam) == BN_DOUBLECLICKED)
1455 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1458 if (HIWORD(wParam) == BN_CLICKED ||
1459 HIWORD(wParam) == BN_DOUBLECLICKED)
1460 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1463 if (HIWORD(wParam) == EN_CHANGE)
1464 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1465 sizeof(cfg.wintitle)-1);
1468 if (HIWORD(wParam) == BN_CLICKED ||
1469 HIWORD(wParam) == BN_DOUBLECLICKED)
1470 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1473 if (HIWORD(wParam) == BN_CLICKED ||
1474 HIWORD(wParam) == BN_DOUBLECLICKED)
1475 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1478 if (HIWORD(wParam) == EN_CHANGE)
1479 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1480 sizeof(cfg.termtype)-1);
1483 if (HIWORD(wParam) == EN_CHANGE)
1484 GetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename,
1485 sizeof(cfg.logfilename)-1);
1488 memset(&of, 0, sizeof(of));
1489 #ifdef OPENFILENAME_SIZE_VERSION_400
1490 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1492 of.lStructSize = sizeof(of);
1494 of.hwndOwner = hwnd;
1495 of.lpstrFilter = "All Files\0*\0\0\0";
1496 of.lpstrCustomFilter = NULL;
1497 of.nFilterIndex = 1;
1498 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1499 of.nMaxFile = sizeof(filename);
1500 of.lpstrFileTitle = NULL;
1501 of.lpstrInitialDir = NULL;
1502 of.lpstrTitle = "Select session log file";
1504 if (GetSaveFileName(&of)) {
1505 strcpy(cfg.keyfile, filename);
1506 SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.keyfile);
1510 case IDC_LSTATASCII:
1512 if (HIWORD(wParam) == BN_CLICKED ||
1513 HIWORD(wParam) == BN_DOUBLECLICKED) {
1514 if (IsDlgButtonChecked (hwnd, IDC_LSTATOFF)) cfg.logtype = 0;
1515 if (IsDlgButtonChecked (hwnd, IDC_LSTATASCII)) cfg.logtype = 1;
1516 if (IsDlgButtonChecked (hwnd, IDC_LSTATRAW)) cfg.logtype = 2;
1520 if (HIWORD(wParam) == EN_CHANGE)
1521 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1522 sizeof(cfg.termspeed)-1);
1525 if (HIWORD(wParam) == EN_CHANGE)
1526 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1527 sizeof(cfg.username)-1);
1531 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1534 if (HIWORD(wParam) == BN_CLICKED ||
1535 HIWORD(wParam) == BN_DOUBLECLICKED) {
1536 char str[sizeof(cfg.environmt)];
1538 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1543 p = str + strlen(str);
1545 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
1555 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
1557 p[strlen(str)+1] = '\0';
1558 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
1560 SetDlgItemText (hwnd, IDC_VAREDIT, "");
1561 SetDlgItemText (hwnd, IDC_VALEDIT, "");
1563 MessageBox(hwnd, "Environment too big", "PuTTY Error",
1564 MB_OK | MB_ICONERROR);
1569 if (HIWORD(wParam) != BN_CLICKED &&
1570 HIWORD(wParam) != BN_DOUBLECLICKED)
1572 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
1578 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
1603 if (HIWORD(wParam) == BN_CLICKED ||
1604 HIWORD(wParam) == BN_DOUBLECLICKED)
1605 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
1608 if (HIWORD(wParam) == BN_CLICKED ||
1609 HIWORD(wParam) == BN_DOUBLECLICKED)
1610 cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
1613 if (HIWORD(wParam) == BN_CLICKED ||
1614 HIWORD(wParam) == BN_DOUBLECLICKED)
1615 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
1618 if (HIWORD(wParam) == BN_CLICKED ||
1619 HIWORD(wParam) == BN_DOUBLECLICKED)
1620 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
1622 case IDC_CIPHER3DES:
1623 case IDC_CIPHERBLOWF:
1625 if (HIWORD(wParam) == BN_CLICKED ||
1626 HIWORD(wParam) == BN_DOUBLECLICKED) {
1627 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
1628 cfg.cipher = CIPHER_3DES;
1629 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
1630 cfg.cipher = CIPHER_BLOWFISH;
1631 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
1632 cfg.cipher = CIPHER_DES;
1637 if (HIWORD(wParam) == BN_CLICKED ||
1638 HIWORD(wParam) == BN_DOUBLECLICKED) {
1639 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
1641 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
1646 if (HIWORD(wParam) == BN_CLICKED ||
1647 HIWORD(wParam) == BN_DOUBLECLICKED)
1648 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
1651 if (HIWORD(wParam) == EN_CHANGE)
1652 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
1653 sizeof(cfg.keyfile)-1);
1656 if (HIWORD(wParam) == EN_CHANGE)
1657 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
1658 sizeof(cfg.remote_cmd)-1);
1661 memset(&of, 0, sizeof(of));
1662 #ifdef OPENFILENAME_SIZE_VERSION_400
1663 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1665 of.lStructSize = sizeof(of);
1667 of.hwndOwner = hwnd;
1668 of.lpstrFilter = "All Files\0*\0\0\0";
1669 of.lpstrCustomFilter = NULL;
1670 of.nFilterIndex = 1;
1671 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1672 of.nMaxFile = sizeof(filename);
1673 of.lpstrFileTitle = NULL;
1674 of.lpstrInitialDir = NULL;
1675 of.lpstrTitle = "Select Public Key File";
1677 if (GetOpenFileName(&of)) {
1678 strcpy(cfg.keyfile, filename);
1679 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1684 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
1690 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
1695 for (i=0; i<256; i++)
1696 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
1699 cfg.wordness[i] = n;
1700 SendDlgItemMessage (hwnd, IDC_CCLIST,
1701 LB_DELETESTRING, i, 0);
1702 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1703 (i>=0x21 && i != 0x7F) ? i : ' ',
1705 SendDlgItemMessage (hwnd, IDC_CCLIST,
1712 case IDC_BOLDCOLOUR:
1713 if (HIWORD(wParam) == BN_CLICKED ||
1714 HIWORD(wParam) == BN_DOUBLECLICKED) {
1716 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
1717 n = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCOUNT, 0, 0);
1718 if (n != 12+10*cfg.bold_colour) {
1720 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1721 LB_DELETESTRING, i, 0);
1722 for (i=0; i<22; i++)
1723 if (cfg.bold_colour || permcolour[i])
1724 SendDlgItemMessage (hwnd, IDC_COLOURLIST,
1726 (LPARAM) colours[i]);
1731 if (HIWORD(wParam) == BN_CLICKED ||
1732 HIWORD(wParam) == BN_DOUBLECLICKED)
1733 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
1735 case IDC_COLOURLIST:
1736 if (HIWORD(wParam) == LBN_DBLCLK ||
1737 HIWORD(wParam) == LBN_SELCHANGE) {
1738 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1740 if (!cfg.bold_colour)
1741 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1742 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
1743 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
1744 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
1748 if (HIWORD(wParam) == BN_CLICKED ||
1749 HIWORD(wParam) == BN_DOUBLECLICKED) {
1750 static CHOOSECOLOR cc;
1751 static DWORD custom[16] = {0}; /* zero initialisers */
1752 int i = SendDlgItemMessage (hwnd, IDC_COLOURLIST, LB_GETCURSEL,
1754 if (!cfg.bold_colour)
1755 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1756 cc.lStructSize = sizeof(cc);
1757 cc.hwndOwner = hwnd;
1758 cc.hInstance = (HWND)hinst;
1759 cc.lpCustColors = custom;
1760 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1762 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1763 if (ChooseColor(&cc)) {
1765 (unsigned char) (cc.rgbResult & 0xFF);
1767 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1769 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1770 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
1772 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
1774 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
1780 case IDC_KOI8WIN1251:
1781 case IDC_88592WIN1250:
1782 case IDC_88592CP852:
1783 cfg.xlat_enablekoiwin =
1784 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
1785 cfg.xlat_88592w1250 =
1786 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
1787 cfg.xlat_88592cp852 =
1788 IsDlgButtonChecked (hwnd, IDC_88592CP852);
1790 case IDC_CAPSLOCKCYR:
1791 if (HIWORD(wParam) == BN_CLICKED ||
1792 HIWORD(wParam) == BN_DOUBLECLICKED) {
1793 cfg.xlat_capslockcyr =
1794 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
1797 case IDC_VTXWINDOWS:
1802 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
1803 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
1804 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
1810 EndDialog (hwnd, 0);
1813 /* Grrr Explorer will maximize Dialogs! */
1815 if (wParam == SIZE_MAXIMIZED)
1822 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1823 WPARAM wParam, LPARAM lParam) {
1824 static HWND page = NULL;
1826 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1828 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
1829 EnableWindow(hwnd, 0);
1830 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1831 GetParent(hwnd), AboutProc);
1832 EnableWindow(hwnd, 1);
1833 SetActiveWindow(hwnd);
1835 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
1838 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1839 WPARAM wParam, LPARAM lParam) {
1841 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
1844 void defuse_showwindow(void) {
1846 * Work around the fact that the app's first call to ShowWindow
1847 * will ignore the default in favour of the shell-provided
1852 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1854 ShowWindow(hwnd, SW_HIDE);
1855 DestroyWindow(hwnd);
1859 int do_config (void) {
1863 savedsession[0] = '\0';
1864 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1865 get_sesslist(FALSE);
1870 int do_reconfig (HWND hwnd) {
1874 backup_cfg = cfg; /* structure copy */
1875 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1877 cfg = backup_cfg; /* structure copy */
1882 void logevent (char *string) {
1883 if (nevents >= negsize) {
1885 events = srealloc (events, negsize * sizeof(*events));
1887 events[nevents] = smalloc(1+strlen(string));
1888 strcpy (events[nevents], string);
1892 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1894 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
1895 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
1899 void showeventlog (HWND hwnd) {
1901 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1903 ShowWindow (logbox, SW_SHOWNORMAL);
1907 void showabout (HWND hwnd) {
1909 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1911 ShowWindow (abtbox, SW_SHOWNORMAL);
1915 void verify_ssh_host_key(char *host, int port, char *keytype,
1916 char *keystr, char *fingerprint) {
1919 static const char absentmsg[] =
1920 "The server's host key is not cached in the registry. You\n"
1921 "have no guarantee that the server is the computer you\n"
1923 "The server's key fingerprint is:\n"
1925 "If you trust this host, hit Yes to add the key to\n"
1926 "PuTTY's cache and carry on connecting.\n"
1927 "If you do not trust this host, hit No to abandon the\n"
1930 static const char wrongmsg[] =
1931 "WARNING - POTENTIAL SECURITY BREACH!\n"
1933 "The server's host key does not match the one PuTTY has\n"
1934 "cached in the registry. This means that either the\n"
1935 "server administrator has changed the host key, or you\n"
1936 "have actually connected to another computer pretending\n"
1937 "to be the server.\n"
1938 "The new key fingerprint is:\n"
1940 "If you were expecting this change and trust the new key,\n"
1941 "hit Yes to update PuTTY's cache and continue connecting.\n"
1942 "If you want to carry on connecting but without updating\n"
1943 "the cache, hit No.\n"
1944 "If you want to abandon the connection completely, hit\n"
1945 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
1948 static const char mbtitle[] = "PuTTY Security Alert";
1951 char message[160+ /* sensible fingerprint max size */
1952 (sizeof(absentmsg) > sizeof(wrongmsg) ?
1953 sizeof(absentmsg) : sizeof(wrongmsg))];
1956 * Verify the key against the registry.
1958 ret = verify_host_key(host, port, keytype, keystr);
1960 if (ret == 0) /* success - key matched OK */
1962 if (ret == 2) { /* key was different */
1964 sprintf(message, wrongmsg, fingerprint);
1965 mbret = MessageBox(NULL, message, mbtitle,
1966 MB_ICONWARNING | MB_YESNOCANCEL);
1968 store_host_key(host, port, keytype, keystr);
1969 if (mbret == IDCANCEL)
1972 if (ret == 1) { /* key was absent */
1974 sprintf(message, absentmsg, fingerprint);
1975 mbret = MessageBox(NULL, message, mbtitle,
1976 MB_ICONWARNING | MB_YESNO);
1979 store_host_key(host, port, keytype, keystr);
1984 * Ask whether to wipe a session log file before writing to it.
1985 * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
1987 int askappend(char *filename) {
1988 static const char mbtitle[] = "PuTTY Log to File";
1989 static const char msgtemplate[] =
1990 "The session log file \"%.*s\" already exists.\n"
1991 "You can overwrite it with a new session log,\n"
1992 "append your session log to the end of it,\n"
1993 "or disable session logging for this session.\n"
1994 "Hit Yes to wipe the file, No to append to it,\n"
1995 "or Cancel to disable logging.";
1996 char message[sizeof(msgtemplate) + FILENAME_MAX];
1998 sprintf(message, msgtemplate, FILENAME_MAX, filename);
2000 mbret = MessageBox(NULL, message, mbtitle,
2001 MB_ICONQUESTION | MB_YESNOCANCEL);
2004 else if (mbret == IDNO)