19 static char **events = NULL;
20 static int nevents = 0, negsize = 0;
22 static HWND logbox = NULL, abtbox = NULL;
24 static HINSTANCE hinst;
28 static void force_normal(HWND hwnd)
30 static int recurse = 0;
37 wp.length = sizeof(wp);
38 if (GetWindowPlacement(hwnd, &wp))
40 wp.showCmd = SW_SHOWNORMAL;
41 SetWindowPlacement(hwnd, &wp);
46 static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
49 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
54 static int CALLBACK LogProc (HWND hwnd, UINT msg,
55 WPARAM wParam, LPARAM lParam) {
60 for (i=0; i<nevents; i++)
61 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
62 0, (LPARAM)events[i]);
65 switch (LOWORD(wParam)) {
71 if (HIWORD(wParam) == BN_CLICKED ||
72 HIWORD(wParam) == BN_DOUBLECLICKED) {
75 selcount = SendDlgItemMessage(hwnd, IDN_LIST,
76 LB_GETSELCOUNT, 0, 0);
77 selitems = malloc(selcount * sizeof(int));
79 int count = SendDlgItemMessage(hwnd, IDN_LIST,
81 selcount, (LPARAM)selitems);
85 static unsigned char sel_nl[] = SEL_NL;
87 if (count == 0) { /* can't copy zero stuff */
93 for (i = 0; i < count; i++)
94 size += strlen(events[selitems[i]]) + sizeof(sel_nl);
96 clipdata = malloc(size);
99 for (i = 0; i < count; i++) {
100 char *q = events[selitems[i]];
101 int qlen = strlen(q);
104 memcpy(p, sel_nl, sizeof(sel_nl));
107 write_clip(clipdata, size, TRUE);
112 for (i = 0; i < nevents; i++)
113 SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
122 DestroyWindow (hwnd);
128 static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
129 WPARAM wParam, LPARAM lParam) {
134 switch (LOWORD(wParam)) {
147 static int CALLBACK AboutProc (HWND hwnd, UINT msg,
148 WPARAM wParam, LPARAM lParam) {
151 SetDlgItemText (hwnd, IDA_VERSION, ver);
154 switch (LOWORD(wParam)) {
157 DestroyWindow (hwnd);
160 EnableWindow(hwnd, 0);
161 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
163 EnableWindow(hwnd, 1);
164 SetActiveWindow(hwnd);
170 DestroyWindow (hwnd);
176 /* ----------------------------------------------------------------------
177 * Routines to self-manage the controls in a dialog box.
185 #define STATICHEIGHT 8
186 #define CHECKBOXHEIGHT 8
187 #define RADIOHEIGHT 8
188 #define EDITHEIGHT 12
189 #define COMBOHEIGHT 12
190 #define PUSHBTNHEIGHT 14
198 int boxystart, boxid, boxtextid;
202 static void ctlposinit(struct ctlpos *cp, HWND hwnd,
203 int leftborder, int rightborder, int topborder) {
206 cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);
207 cp->ypos = topborder;
208 GetClientRect(hwnd, &r);
209 r2.left = r2.top = 0;
212 MapDialogRect(hwnd, &r2);
213 cp->dlu4inpix = r2.right;
214 cp->width = (r.right * 4) / (r2.right) - 2*GAPBETWEEN;
215 cp->xoff = leftborder;
216 cp->width -= leftborder + rightborder;
219 static void doctl(struct ctlpos *cp, RECT r,
220 char *wclass, int wstyle, int exstyle,
221 char *wtext, int wid) {
224 * Note nonstandard use of RECT. This is deliberate: by
225 * transforming the width and height directly we arrange to
226 * have all supposedly same-sized controls really same-sized.
230 MapDialogRect(cp->hwnd, &r);
232 ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,
233 r.left, r.top, r.right, r.bottom,
234 cp->hwnd, (HMENU)wid, hinst, NULL);
235 SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));
239 * A title bar across the top of a sub-dialog.
241 static void bartitle(struct ctlpos *cp, char *name, int id) {
244 r.left = GAPBETWEEN; r.right = cp->width;
245 r.top = cp->ypos; r.bottom = STATICHEIGHT;
246 cp->ypos += r.bottom + GAPBETWEEN;
247 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, name, id);
251 * Begin a grouping box, with or without a group title.
253 static void beginbox(struct ctlpos *cp, char *name, int idbox, int idtext) {
255 cp->ypos += STATICHEIGHT/2;
256 cp->boxystart = cp->ypos;
258 cp->ypos += STATICHEIGHT - (STATICHEIGHT/2);
260 cp->width -= 2*GAPXBOX;
263 cp->boxtextid = idtext;
268 * End a grouping box.
270 static void endbox(struct ctlpos *cp) {
273 cp->width += 2*GAPXBOX;
274 cp->ypos += GAPYBOX - GAPBETWEEN;
275 r.left = GAPBETWEEN; r.right = cp->width;
276 r.top = cp->boxystart; r.bottom = cp->ypos - cp->boxystart;
277 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,
282 HFONT oldfont, dlgfont;
283 hdc = GetDC(cp->hwnd);
284 dlgfont = (HFONT)cp->font;
285 oldfont = SelectObject(hdc, dlgfont);
286 GetTextExtentPoint32(hdc, cp->boxtext, strlen(cp->boxtext), &s);
287 SelectObject(hdc, oldfont);
289 r.left = GAPXBOX + GAPBETWEEN;
290 r.right = (s.cx * 4 + cp->dlu4inpix-1) / cp->dlu4inpix;
292 r.top = cp->boxystart - STATICHEIGHT/2; r.bottom = STATICHEIGHT;
293 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
294 cp->boxtext, cp->boxtextid);
300 * Some edit boxes. Each one has a static above it. The percentages
301 * of the horizontal space are provided.
303 static void multiedit(struct ctlpos *cp, ...) {
312 int staticid, editid, pcwidth;
313 text = va_arg(ap, char *);
316 staticid = va_arg(ap, int);
317 editid = va_arg(ap, int);
318 pcwidth = va_arg(ap, int);
320 r.left = xpos + GAPBETWEEN;
322 xpos = (cp->width + GAPBETWEEN) * percent / 100;
323 r.right = xpos - r.left;
325 r.top = cp->ypos; r.bottom = STATICHEIGHT;
326 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
328 r.top = cp->ypos + 8 + GAPWITHIN; r.bottom = EDITHEIGHT;
330 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
335 cp->ypos += 8+GAPWITHIN+12+GAPBETWEEN;
339 * A set of radio buttons on the same line, with a static above
340 * them. `nacross' dictates how many parts the line is divided into
341 * (you might want this not to equal the number of buttons if you
342 * needed to line up some 2s and some 3s to look good in the same
345 static void radioline(struct ctlpos *cp,
346 char *text, int id, int nacross, ...) {
352 r.left = GAPBETWEEN; r.top = cp->ypos;
353 r.right = cp->width; r.bottom = STATICHEIGHT;
354 cp->ypos += r.bottom + GAPWITHIN;
355 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
356 va_start(ap, nacross);
362 btext = va_arg(ap, char *);
365 bid = va_arg(ap, int);
366 r.left = GAPBETWEEN + i * (cp->width+GAPBETWEEN)/nacross;
367 r.right = (i+1) * (cp->width+GAPBETWEEN)/nacross - r.left;
368 r.top = cp->ypos; r.bottom = RADIOHEIGHT;
369 doctl(cp, r, "BUTTON",
370 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
377 cp->ypos += r.bottom + GAPBETWEEN;
381 * A set of radio buttons on multiple lines, with a static above
384 static void radiobig(struct ctlpos *cp, char *text, int id, ...) {
389 r.left = GAPBETWEEN; r.top = cp->ypos;
390 r.right = cp->width; r.bottom = STATICHEIGHT;
391 cp->ypos += r.bottom + GAPWITHIN;
392 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
398 btext = va_arg(ap, char *);
401 bid = va_arg(ap, int);
402 r.left = GAPBETWEEN; r.top = cp->ypos;
403 r.right = cp->width; r.bottom = STATICHEIGHT;
404 cp->ypos += r.bottom + GAPWITHIN;
405 doctl(cp, r, "BUTTON",
406 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
412 cp->ypos += GAPBETWEEN - GAPWITHIN;
416 * A single standalone checkbox.
418 static void checkbox(struct ctlpos *cp, char *text, int id) {
421 r.left = GAPBETWEEN; r.top = cp->ypos;
422 r.right = cp->width; r.bottom = CHECKBOXHEIGHT;
423 cp->ypos += r.bottom + GAPBETWEEN;
424 doctl(cp, r, "BUTTON",
425 BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,
430 * A button on the right hand side, with a static to its left.
432 static void staticbtn(struct ctlpos *cp, char *stext, int sid,
433 char *btext, int bid) {
434 const int height = (PUSHBTNHEIGHT > STATICHEIGHT ?
435 PUSHBTNHEIGHT : STATICHEIGHT);
437 int lwid, rwid, rpos;
439 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
440 lwid = rpos - 2*GAPBETWEEN;
441 rwid = cp->width + GAPBETWEEN - rpos;
443 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
444 r.right = lwid; r.bottom = STATICHEIGHT;
445 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
447 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
448 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
449 doctl(cp, r, "BUTTON",
450 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
454 cp->ypos += height + GAPBETWEEN;
458 * An edit control on the right hand side, with a static to its left.
460 static void staticedit(struct ctlpos *cp, char *stext,
461 int sid, int eid, int percentedit) {
462 const int height = (EDITHEIGHT > STATICHEIGHT ?
463 EDITHEIGHT : STATICHEIGHT);
465 int lwid, rwid, rpos;
467 rpos = GAPBETWEEN + (100-percentedit) * (cp->width + GAPBETWEEN) / 100;
468 lwid = rpos - 2*GAPBETWEEN;
469 rwid = cp->width + GAPBETWEEN - rpos;
471 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
472 r.right = lwid; r.bottom = STATICHEIGHT;
473 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
475 r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2;
476 r.right = rwid; r.bottom = EDITHEIGHT;
478 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
482 cp->ypos += height + GAPBETWEEN;
486 * A tab-control substitute when a real tab control is unavailable.
488 static void ersatztab(struct ctlpos *cp, char *stext, int sid,
490 const int height = (COMBOHEIGHT > STATICHEIGHT ?
491 COMBOHEIGHT : STATICHEIGHT);
493 int bigwid, lwid, rwid, rpos;
494 static const int BIGGAP = 15;
495 static const int MEDGAP = 3;
497 bigwid = cp->width + 2*GAPBETWEEN - 2*BIGGAP;
499 rpos = BIGGAP + (bigwid + BIGGAP) / 2;
500 lwid = rpos - 2*BIGGAP;
501 rwid = bigwid + BIGGAP - rpos;
503 r.left = BIGGAP; r.top = cp->ypos + (height-STATICHEIGHT)/2;
504 r.right = lwid; r.bottom = STATICHEIGHT;
505 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
507 r.left = rpos; r.top = cp->ypos + (height-COMBOHEIGHT)/2;
508 r.right = rwid; r.bottom = COMBOHEIGHT*10;
509 doctl(cp, r, "COMBOBOX",
510 WS_CHILD | WS_VISIBLE | WS_TABSTOP |
511 CBS_DROPDOWNLIST | CBS_HASSTRINGS,
515 cp->ypos += height + MEDGAP + GAPBETWEEN;
517 r.left = GAPBETWEEN; r.top = cp->ypos;
518 r.right = cp->width; r.bottom = 2;
519 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
524 * A static line, followed by an edit control on the left hand side
525 * and a button on the right.
527 static void editbutton(struct ctlpos *cp, char *stext, int sid,
528 int eid, char *btext, int bid) {
529 const int height = (EDITHEIGHT > PUSHBTNHEIGHT ?
530 EDITHEIGHT : PUSHBTNHEIGHT);
532 int lwid, rwid, rpos;
534 r.left = GAPBETWEEN; r.top = cp->ypos;
535 r.right = cp->width; r.bottom = STATICHEIGHT;
536 cp->ypos += r.bottom + GAPWITHIN;
537 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
539 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
540 lwid = rpos - 2*GAPBETWEEN;
541 rwid = cp->width + GAPBETWEEN - rpos;
543 r.left = GAPBETWEEN; r.top = cp->ypos + (height-EDITHEIGHT)/2;
544 r.right = lwid; r.bottom = EDITHEIGHT;
546 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
550 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
551 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
552 doctl(cp, r, "BUTTON",
553 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
557 cp->ypos += height + GAPBETWEEN;
561 * Special control which was hard to describe generically: the
562 * session-saver assembly. A static; below that an edit box; below
563 * that a list box. To the right of the list box, a column of
566 static void sesssaver(struct ctlpos *cp, char *text,
567 int staticid, int editid, int listid, ...) {
570 int lwid, rwid, rpos;
572 const int LISTDEFHEIGHT = 66;
574 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
575 lwid = rpos - 2*GAPBETWEEN;
576 rwid = cp->width + GAPBETWEEN - rpos;
578 /* The static control. */
579 r.left = GAPBETWEEN; r.top = cp->ypos;
580 r.right = lwid; r.bottom = STATICHEIGHT;
581 cp->ypos += r.bottom + GAPWITHIN;
582 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
584 /* The edit control. */
585 r.left = GAPBETWEEN; r.top = cp->ypos;
586 r.right = lwid; r.bottom = EDITHEIGHT;
587 cp->ypos += r.bottom + GAPWITHIN;
589 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
594 * The buttons (we should hold off on the list box until we
595 * know how big the buttons are).
597 va_start(ap, listid);
600 char *btext = va_arg(ap, char *);
603 bid = va_arg(ap, int);
604 r.left = rpos; r.top = y;
605 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
606 y += r.bottom + GAPWITHIN;
607 doctl(cp, r, "BUTTON",
608 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
613 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
616 if (y < LISTDEFHEIGHT) y = LISTDEFHEIGHT;
617 r.left = GAPBETWEEN; r.top = cp->ypos;
618 r.right = lwid; r.bottom = y;
619 cp->ypos += y + GAPBETWEEN;
620 doctl(cp, r, "LISTBOX",
621 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
622 LBS_NOTIFY | LBS_HASSTRINGS,
628 * Another special control: the environment-variable setter. A
629 * static line first; then a pair of edit boxes with associated
630 * statics, and two buttons; then a list box.
632 static void envsetter(struct ctlpos *cp, char *stext, int sid,
633 char *e1stext, int e1sid, int e1id,
634 char *e2stext, int e2sid, int e2id,
636 char *b1text, int b1id, char *b2text, int b2id) {
638 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
640 EDITHEIGHT > PUSHBTNHEIGHT ?
641 EDITHEIGHT : PUSHBTNHEIGHT);
642 const static int percents[] = { 20, 35, 10, 25 };
643 int i, j, xpos, percent;
644 const int LISTHEIGHT = 42;
646 /* The static control. */
647 r.left = GAPBETWEEN; r.top = cp->ypos;
648 r.right = cp->width; r.bottom = STATICHEIGHT;
649 cp->ypos += r.bottom + GAPWITHIN;
650 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
652 /* The statics+edits+buttons. */
653 for (j = 0; j < 2; j++) {
655 for (i = 0; i < 4; i++) {
656 xpos = (cp->width + GAPBETWEEN) * percent / 100;
657 r.left = xpos + GAPBETWEEN;
658 percent += percents[i];
659 xpos = (cp->width + GAPBETWEEN) * percent / 100;
660 r.right = xpos - r.left;
662 r.bottom = (i==0 ? STATICHEIGHT :
665 r.top += (height-r.bottom)/2;
667 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
668 j==0 ? e1stext : e2stext, j==0 ? e1sid : e2sid);
671 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
673 "", j==0 ? e1id : e2id);
675 doctl(cp, r, "BUTTON",
676 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
678 j==0 ? b1text : b2text, j==0 ? b1id : b2id);
681 cp->ypos += height + GAPWITHIN;
685 r.left = GAPBETWEEN; r.top = cp->ypos;
686 r.right = cp->width; r.bottom = LISTHEIGHT;
687 cp->ypos += r.bottom + GAPBETWEEN;
688 doctl(cp, r, "LISTBOX",
689 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
696 * Yet another special control: the character-class setter. A
697 * static, then a list, then a line containing a
698 * button-and-static-and-edit.
700 static void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
701 char *btext, int bid, int eid, char *s2text, int s2id) {
703 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
705 EDITHEIGHT > PUSHBTNHEIGHT ?
706 EDITHEIGHT : PUSHBTNHEIGHT);
707 const static int percents[] = { 30, 40, 30 };
708 int i, xpos, percent;
709 const int LISTHEIGHT = 66;
711 /* The static control. */
712 r.left = GAPBETWEEN; r.top = cp->ypos;
713 r.right = cp->width; r.bottom = STATICHEIGHT;
714 cp->ypos += r.bottom + GAPWITHIN;
715 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
718 r.left = GAPBETWEEN; r.top = cp->ypos;
719 r.right = cp->width; r.bottom = LISTHEIGHT;
720 cp->ypos += r.bottom + GAPWITHIN;
721 doctl(cp, r, "LISTBOX",
722 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
727 /* The button+static+edit. */
729 for (i = 0; i < 3; i++) {
730 r.left = xpos + GAPBETWEEN;
731 percent += percents[i];
732 xpos = (cp->width + GAPBETWEEN) * percent / 100;
733 r.right = xpos - r.left;
735 r.bottom = (i==0 ? PUSHBTNHEIGHT :
736 i==1 ? STATICHEIGHT :
738 r.top += (height-r.bottom)/2;
740 doctl(cp, r, "BUTTON",
741 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
744 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER,
748 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
749 WS_EX_CLIENTEDGE, "", eid);
752 cp->ypos += height + GAPBETWEEN;
756 * A special control (horrors!). The colour editor. A static line;
757 * then on the left, a list box, and on the right, a sequence of
758 * two-part statics followed by a button.
760 static void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
761 char *btext, int bid, ...) {
765 int lwid, rwid, rpos;
766 const int LISTHEIGHT = 66;
768 /* The static control. */
769 r.left = GAPBETWEEN; r.top = cp->ypos;
770 r.right = cp->width; r.bottom = STATICHEIGHT;
771 cp->ypos += r.bottom + GAPWITHIN;
772 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
774 rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3;
775 lwid = rpos - 2*GAPBETWEEN;
776 rwid = cp->width + GAPBETWEEN - rpos;
779 r.left = GAPBETWEEN; r.top = cp->ypos;
780 r.right = lwid; r.bottom = LISTHEIGHT;
781 doctl(cp, r, "LISTBOX",
782 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
793 ltext = va_arg(ap, char *);
795 lid = va_arg(ap, int);
796 rid = va_arg(ap, int);
797 r.top = y; r.bottom = STATICHEIGHT;
798 y += r.bottom + GAPWITHIN;
799 r.left = rpos; r.right = rwid/2;
800 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid);
801 r.left = rpos + r.right; r.right = rwid - r.right;
802 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "", rid);
807 r.top = y + 2*GAPWITHIN; r.bottom = PUSHBTNHEIGHT;
808 r.left = rpos; r.right = rwid;
809 doctl(cp, r, "BUTTON",
810 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
813 cp->ypos += LISTHEIGHT + GAPBETWEEN;
816 static char savedsession[2048];
818 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
822 IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
823 IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
844 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
845 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
868 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
869 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
870 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3,
890 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
891 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
892 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3,
907 connectionpanelstart,
908 IDC_TITLE_CONNECTION,
909 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
910 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
921 IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
922 IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
940 IDC_BOX_SSH1, IDC_BOXT_SSH1,
941 IDC_BOX_SSH2, IDC_BOXT_SSH2,
942 IDC_BOX_SSH3, IDC_BOXT_SSH3,
962 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
963 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
976 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
977 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
991 translationpanelstart,
992 IDC_TITLE_TRANSLATION,
993 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
994 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
995 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
1006 translationpanelend,
1011 static const char *const colours[] = {
1012 "Default Foreground", "Default Bold Foreground",
1013 "Default Background", "Default Bold Background",
1014 "Cursor Text", "Cursor Colour",
1015 "ANSI Black", "ANSI Black Bold",
1016 "ANSI Red", "ANSI Red Bold",
1017 "ANSI Green", "ANSI Green Bold",
1018 "ANSI Yellow", "ANSI Yellow Bold",
1019 "ANSI Blue", "ANSI Blue Bold",
1020 "ANSI Magenta", "ANSI Magenta Bold",
1021 "ANSI Cyan", "ANSI Cyan Bold",
1022 "ANSI White", "ANSI White Bold"
1024 static const int permcolour[] = {
1025 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1026 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1027 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1030 static void fmtfont (char *buf) {
1031 sprintf (buf, "Font: %s, ", cfg.font);
1033 strcat(buf, "bold, ");
1034 if (cfg.fontheight == 0)
1035 strcat (buf, "default height");
1037 sprintf (buf+strlen(buf), "%d-%s",
1038 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
1039 (cfg.fontheight < 0 ? "pixel" : "point"));
1042 static void init_dlg_ctrls(HWND hwnd) {
1044 char fontstatic[256];
1046 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1047 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
1048 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1049 for (i = 0; i < nsessions; i++)
1050 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1051 0, (LPARAM) (sessions[i]));
1052 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1053 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1054 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1055 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
1057 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1058 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1059 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1060 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1061 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCXTERM,
1062 cfg.funky_type == 0 ? IDC_FUNCTILDE :
1063 cfg.funky_type == 1 ? IDC_FUNCLINUX :
1064 cfg.funky_type == 2 ? IDC_FUNCXTERM :
1065 cfg.funky_type == 3 ? IDC_FUNCVT400 :
1067 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1068 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1069 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1070 cfg.nethack_keypad ? IDC_KPNH :
1071 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1072 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1073 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1074 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1075 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
1077 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1078 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1079 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1080 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1081 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1082 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
1083 fmtfont (fontstatic);
1084 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1085 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1086 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1087 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
1089 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1090 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1091 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1092 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1093 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
1094 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1095 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1097 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1098 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1099 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1101 char *p = cfg.environmt;
1103 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
1108 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1109 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
1111 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1112 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1113 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
1114 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
1115 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
1116 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
1117 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
1119 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
1120 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
1121 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
1122 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1123 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
1125 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
1126 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
1128 static int tabs[4] = {25, 61, 96, 128};
1129 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
1132 for (i=0; i<256; i++) {
1134 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1135 (i>=0x21 && i != 0x7F) ? i : ' ',
1137 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
1141 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
1142 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
1145 for (i=0; i<22; i++)
1146 if (cfg.bold_colour || permcolour[i])
1147 SendDlgItemMessage (hwnd, IDC_LIST, LB_ADDSTRING, 0,
1148 (LPARAM) colours[i]);
1150 SendDlgItemMessage (hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
1151 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
1152 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
1153 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
1155 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592WIN1250,
1156 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
1157 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
1159 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1160 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
1161 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
1162 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
1163 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
1167 static void hide(HWND hwnd, int hide, int minid, int maxid) {
1169 for (i = minid; i < maxid; i++) {
1170 HWND ctl = GetDlgItem(hwnd, i);
1172 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1177 struct treeview_faff {
1179 HTREEITEM lastat[4];
1182 static HTREEITEM treeview_insert(struct treeview_faff *faff,
1183 int level, char *text) {
1187 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
1188 ins.hInsertAfter = faff->lastat[level];
1189 ins.DUMMYUNIONNAME.item.mask = TVIF_TEXT;
1190 ins.DUMMYUNIONNAME.item.pszText = text;
1191 newitem = TreeView_InsertItem(faff->treeview, &ins);
1193 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
1194 faff->lastat[level] = newitem;
1195 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
1200 * This _huge_ function is the configuration box.
1202 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1203 WPARAM wParam, LPARAM lParam,
1206 struct treeview_faff tvfaff;
1209 char filename[sizeof(cfg.keyfile)];
1212 char fontstatic[256];
1217 SetWindowLong(hwnd, GWL_USERDATA, 0);
1219 * Centre the window.
1221 { /* centre the window */
1224 hw = GetDesktopWindow();
1225 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1226 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1227 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1228 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1232 * Create the tree view.
1239 r.left = 3; r.right = r.left + 75;
1240 r.top = 3; r.bottom = r.top + 10;
1241 MapDialogRect(hwnd, &r);
1242 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1243 WS_CHILD | WS_VISIBLE,
1245 r.right-r.left, r.bottom-r.top,
1246 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1247 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1248 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1250 r.left = 3; r.right = r.left + 75;
1251 r.top = 13; r.bottom = r.top + 196;
1252 MapDialogRect(hwnd, &r);
1253 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1254 WS_CHILD | WS_VISIBLE |
1255 WS_TABSTOP | TVS_HASLINES |
1256 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1257 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1259 r.right-r.left, r.bottom-r.top,
1260 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1261 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1262 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1263 tvfaff.treeview = treeview;
1264 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1268 * Create the various panelfuls of controls.
1271 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1274 ctlposinit(&cp, hwnd, 80, 3, 13);
1275 bartitle(&cp, "Basic options for your PuTTY session",
1278 beginbox(&cp, "Specify your connection by host name",
1279 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
1281 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1282 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
1283 if (backends[2].backend == NULL) {
1284 /* this is PuTTYtel, so only two protocols available */
1285 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1286 "&Raw", IDC_PROTRAW,
1287 "&Telnet", IDC_PROTTELNET, NULL);
1289 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1290 "&Raw", IDC_PROTRAW,
1291 "&Telnet", IDC_PROTTELNET,
1300 beginbox(&cp, "Load, save or delete a stored session",
1301 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
1302 sesssaver(&cp, "Stor&ed Sessions",
1303 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1304 "&Load", IDC_SESSLOAD,
1305 "&Save", IDC_SESSSAVE,
1306 "&Delete", IDC_SESSDEL, NULL);
1309 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
1310 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1313 hsession = treeview_insert(&tvfaff, 0, "Session");
1316 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1319 ctlposinit(&cp, hwnd, 80, 3, 13);
1320 bartitle(&cp, "Options controlling the terminal emulation",
1321 IDC_TITLE_TERMINAL);
1322 beginbox(&cp, "Set the size of the terminal window",
1323 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
1325 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1326 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
1328 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
1330 beginbox(&cp, "Set the font used in the terminal window",
1331 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
1332 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1334 beginbox(&cp, "Set various terminal options",
1335 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3);
1336 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1337 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1338 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1339 checkbox(&cp, "&Beep enabled", IDC_BEEP);
1340 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
1341 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1342 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1345 treeview_insert(&tvfaff, 0, "Terminal");
1348 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1351 ctlposinit(&cp, hwnd, 80, 3, 13);
1352 bartitle(&cp, "Options controlling the effects of keys",
1353 IDC_TITLE_KEYBOARD);
1354 beginbox(&cp, "Change the sequences sent by:",
1355 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
1356 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
1357 "Control-&H", IDC_DEL008,
1358 "Control-&? (127)", IDC_DEL127, NULL);
1359 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
1360 "&Standard", IDC_HOMETILDE,
1361 "&rxvt", IDC_HOMERXVT, NULL);
1362 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
1363 "&VT400", IDC_FUNCTILDE,
1364 "&Linux", IDC_FUNCLINUX,
1365 "&Xterm R6", IDC_FUNCXTERM,
1366 "&VT400", IDC_FUNCVT400, NULL);
1368 beginbox(&cp, "Change the initial state of:",
1369 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
1370 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1371 "&Normal", IDC_CURNORMAL,
1372 "A&pplication", IDC_CURAPPLIC, NULL);
1373 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1374 "Nor&mal", IDC_KPNORMAL,
1375 "Appl&ication", IDC_KPAPPLIC,
1376 "N&etHack", IDC_KPNH, NULL);
1379 treeview_insert(&tvfaff, 1, "Keyboard");
1382 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1385 ctlposinit(&cp, hwnd, 80, 3, 13);
1386 bartitle(&cp, "Options controlling PuTTY's window",
1388 beginbox(&cp, "Adjust the use of the window title",
1389 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
1392 "Initial window &title:", IDC_WINTITLE,
1393 IDC_WINEDIT, 100, NULL);
1394 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1396 beginbox(&cp, "Adjust the use of the cursor",
1397 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
1398 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1400 beginbox(&cp, "Control the scrollback in the window",
1401 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3);
1402 staticedit(&cp, "Lines of &scrollback",
1403 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1404 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1405 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1407 beginbox(&cp, NULL, IDC_BOX_WINDOW4, 0);
1408 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1409 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1410 checkbox(&cp, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE);
1413 treeview_insert(&tvfaff, 0, "Window");
1416 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1419 ctlposinit(&cp, hwnd, 80, 3, 13);
1420 bartitle(&cp, "Options controlling character set translation",
1421 IDC_TITLE_TRANSLATION);
1422 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1423 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
1425 "Handling of line drawing characters:", IDC_VTSTATIC,
1426 "Font has &XWindows encoding", IDC_VTXWINDOWS,
1427 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1428 "Use font in O&EM mode only", IDC_VTOEMONLY,
1429 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1430 IDC_VTPOORMAN, NULL);
1432 beginbox(&cp, "Enable character set translation on received data",
1433 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
1435 "Character set translation:", IDC_XLATSTATIC,
1436 "&None", IDC_NOXLAT,
1437 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
1438 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250, NULL);
1440 beginbox(&cp, "Enable character set translation on input data",
1441 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
1442 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
1446 treeview_insert(&tvfaff, 1, "Translation");
1449 /* The Selection panel. Accelerators used: [acgo] wxst */
1452 ctlposinit(&cp, hwnd, 80, 3, 13);
1453 bartitle(&cp, "Options controlling copy and paste",
1454 IDC_TITLE_SELECTION);
1455 beginbox(&cp, "Control which mouse button does which thing",
1456 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
1457 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1458 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1459 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1462 beginbox(&cp, "Control the select-one-word-at-a-time mode",
1463 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
1464 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1465 "&Set", IDC_CCSET, IDC_CCEDIT,
1466 "&to class", IDC_CCSTATIC2);
1469 treeview_insert(&tvfaff, 1, "Selection");
1472 /* The Colours panel. Accelerators used: [acgo] blum */
1475 ctlposinit(&cp, hwnd, 80, 3, 13);
1476 bartitle(&cp, "Options controlling use of colours",
1478 beginbox(&cp, "General options for colour usage",
1479 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
1480 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
1481 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1483 beginbox(&cp, "Adjust the precise colours PuTTY displays",
1484 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
1485 colouredit(&cp, "Select a colo&ur and then click to modify it:",
1486 IDC_STATIC, IDC_LIST,
1487 "&Modify...", IDC_CHANGE,
1488 "Red:", IDC_RSTATIC, IDC_RVALUE,
1489 "Green:", IDC_GSTATIC, IDC_GVALUE,
1490 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1493 treeview_insert(&tvfaff, 1, "Colours");
1496 /* The Connection panel. Accelerators used: [acgo] tuk */
1499 ctlposinit(&cp, hwnd, 80, 3, 13);
1500 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
1502 beginbox(&cp, "Data to send to the server",
1503 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
1504 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
1505 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
1508 beginbox(&cp, "Sending of null packets to keep session active",
1509 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
1510 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
1511 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
1514 treeview_insert(&tvfaff, 0, "Connection");
1517 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1520 ctlposinit(&cp, hwnd, 80, 3, 13);
1522 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
1523 beginbox(&cp, "Data to send to the server",
1524 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
1525 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
1526 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1527 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1528 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1530 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1532 beginbox(&cp, "Telnet protocol adjustments",
1533 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
1534 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1535 "&BSD (commonplace)", IDC_EMBSD,
1536 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1539 treeview_insert(&tvfaff, 1, "Telnet");
1543 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1546 ctlposinit(&cp, hwnd, 80, 3, 13);
1548 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1549 beginbox(&cp, "Data to send to the server",
1550 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1552 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1555 beginbox(&cp, "Authentication options",
1556 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1557 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1559 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1560 editbutton(&cp, "Private &key file for authentication:",
1561 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1563 beginbox(&cp, "Protocol options",
1564 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1565 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1566 radioline(&cp, "Preferred SSH protocol version:",
1567 IDC_SSHPROTSTATIC, 2,
1568 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1569 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1570 "&3DES", IDC_CIPHER3DES,
1571 "&Blowfish", IDC_CIPHERBLOWF,
1572 "&DES", IDC_CIPHERDES, NULL);
1575 treeview_insert(&tvfaff, 1, "SSH");
1579 init_dlg_ctrls(hwnd);
1582 * Hide all the controls to start with.
1584 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1587 * Put the treeview selection on to the Session panel. This
1588 * should also cause unhiding of the relevant controls.
1590 TreeView_SelectItem(treeview, hsession);
1593 * Set focus into the first available control.
1597 ctl = GetDlgItem(hwnd, IDC_HOST);
1598 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1602 SetWindowLong(hwnd, GWL_USERDATA, 1);
1606 * Button release should trigger WM_OK if there was a
1607 * previous double click on the session list.
1611 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1614 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1615 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1616 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1620 item.pszText = buffer;
1621 item.cchTextMax = sizeof(buffer);
1622 item.mask = TVIF_TEXT;
1623 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1624 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1625 if (!strcmp(buffer, "Session"))
1626 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1627 if (!strcmp(buffer, "Keyboard"))
1628 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1629 if (!strcmp(buffer, "Terminal"))
1630 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1631 if (!strcmp(buffer, "Window"))
1632 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1633 if (!strcmp(buffer, "Connection"))
1634 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1635 if (!strcmp(buffer, "Telnet"))
1636 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1637 if (!strcmp(buffer, "SSH"))
1638 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1639 if (!strcmp(buffer, "Selection"))
1640 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1641 if (!strcmp(buffer, "Colours"))
1642 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1643 if (!strcmp(buffer, "Translation"))
1644 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1646 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1652 * Only process WM_COMMAND once the dialog is fully formed.
1654 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1657 EndDialog (hwnd, 1);
1662 EndDialog (hwnd, 0);
1664 case IDC_PROTTELNET:
1667 if (HIWORD(wParam) == BN_CLICKED ||
1668 HIWORD(wParam) == BN_DOUBLECLICKED) {
1669 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1670 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1671 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1672 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1673 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1674 cfg.port = i ? 22 : 23;
1675 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1680 if (HIWORD(wParam) == EN_CHANGE)
1681 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1682 sizeof(cfg.host)-1);
1685 if (HIWORD(wParam) == EN_CHANGE)
1686 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1689 if (HIWORD(wParam) == EN_CHANGE) {
1690 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1692 GetDlgItemText (hwnd, IDC_SESSEDIT,
1693 savedsession, sizeof(savedsession)-1);
1694 savedsession[sizeof(savedsession)-1] = '\0';
1698 if (HIWORD(wParam) == BN_CLICKED ||
1699 HIWORD(wParam) == BN_DOUBLECLICKED) {
1704 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1706 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1707 LB_GETCURSEL, 0, 0);
1712 strcpy (str, sessions[n]);
1714 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1715 get_sesslist (FALSE);
1716 get_sesslist (TRUE);
1717 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1719 for (i = 0; i < nsessions; i++)
1720 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1721 0, (LPARAM) (sessions[i]));
1722 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1728 if (LOWORD(wParam) == IDC_SESSLOAD &&
1729 HIWORD(wParam) != BN_CLICKED &&
1730 HIWORD(wParam) != BN_DOUBLECLICKED)
1732 if (LOWORD(wParam) == IDC_SESSLIST &&
1733 HIWORD(wParam) != LBN_DBLCLK)
1736 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1737 LB_GETCURSEL, 0, 0);
1742 load_settings (sessions[n],
1743 !!strcmp(sessions[n], "Default Settings"),
1745 init_dlg_ctrls(hwnd);
1747 if (LOWORD(wParam) == IDC_SESSLIST) {
1749 * A double-click on a saved session should
1750 * actually start the session, not just load it.
1751 * Unless it's Default Settings or some other
1752 * host-less set of saved settings.
1761 if (HIWORD(wParam) == BN_CLICKED ||
1762 HIWORD(wParam) == BN_DOUBLECLICKED) {
1763 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1764 LB_GETCURSEL, 0, 0);
1765 if (n == LB_ERR || n == 0) {
1769 del_settings(sessions[n]);
1770 get_sesslist (FALSE);
1771 get_sesslist (TRUE);
1772 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1774 for (i = 0; i < nsessions; i++)
1775 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1776 0, (LPARAM) (sessions[i]));
1777 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1781 if (HIWORD(wParam) == EN_CHANGE)
1782 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1786 if (HIWORD(wParam) == BN_CLICKED ||
1787 HIWORD(wParam) == BN_DOUBLECLICKED)
1788 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1792 if (HIWORD(wParam) == BN_CLICKED ||
1793 HIWORD(wParam) == BN_DOUBLECLICKED)
1794 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1797 if (HIWORD(wParam) == BN_CLICKED ||
1798 HIWORD(wParam) == BN_DOUBLECLICKED)
1802 if (HIWORD(wParam) == BN_CLICKED ||
1803 HIWORD(wParam) == BN_DOUBLECLICKED)
1808 if (HIWORD(wParam) == BN_CLICKED ||
1809 HIWORD(wParam) == BN_DOUBLECLICKED)
1810 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1814 if (HIWORD(wParam) == BN_CLICKED ||
1815 HIWORD(wParam) == BN_DOUBLECLICKED) {
1816 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1817 cfg.nethack_keypad = FALSE;
1821 if (HIWORD(wParam) == BN_CLICKED ||
1822 HIWORD(wParam) == BN_DOUBLECLICKED) {
1823 cfg.app_keypad = FALSE;
1824 cfg.nethack_keypad = TRUE;
1829 if (HIWORD(wParam) == BN_CLICKED ||
1830 HIWORD(wParam) == BN_DOUBLECLICKED)
1831 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1834 if (HIWORD(wParam) == BN_CLICKED ||
1835 HIWORD(wParam) == BN_DOUBLECLICKED)
1836 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1839 if (HIWORD(wParam) == BN_CLICKED ||
1840 HIWORD(wParam) == BN_DOUBLECLICKED)
1841 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1844 if (HIWORD(wParam) == BN_CLICKED ||
1845 HIWORD(wParam) == BN_DOUBLECLICKED)
1846 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1849 if (HIWORD(wParam) == BN_CLICKED ||
1850 HIWORD(wParam) == BN_DOUBLECLICKED)
1851 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1854 if (HIWORD(wParam) == BN_CLICKED ||
1855 HIWORD(wParam) == BN_DOUBLECLICKED)
1856 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1859 if (HIWORD(wParam) == BN_CLICKED ||
1860 HIWORD(wParam) == BN_DOUBLECLICKED)
1861 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1864 if (HIWORD(wParam) == BN_CLICKED ||
1865 HIWORD(wParam) == BN_DOUBLECLICKED)
1866 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1869 if (HIWORD(wParam) == EN_CHANGE)
1870 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1873 if (HIWORD(wParam) == EN_CHANGE)
1874 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1877 if (HIWORD(wParam) == EN_CHANGE)
1878 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1880 case IDC_CHOOSEFONT:
1881 lf.lfHeight = cfg.fontheight;
1882 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1883 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1884 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1885 lf.lfCharSet = cfg.fontcharset;
1886 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1887 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1888 lf.lfQuality = DEFAULT_QUALITY;
1889 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1890 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1891 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1893 cf.lStructSize = sizeof(cf);
1894 cf.hwndOwner = hwnd;
1896 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1897 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1899 if (ChooseFont (&cf)) {
1900 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1901 cfg.font[sizeof(cfg.font)-1] = '\0';
1902 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1903 cfg.fontcharset = lf.lfCharSet;
1904 cfg.fontheight = lf.lfHeight;
1905 fmtfont (fontstatic);
1906 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1910 if (HIWORD(wParam) == BN_CLICKED ||
1911 HIWORD(wParam) == BN_DOUBLECLICKED)
1912 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1915 if (HIWORD(wParam) == BN_CLICKED ||
1916 HIWORD(wParam) == BN_DOUBLECLICKED)
1917 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1920 if (HIWORD(wParam) == BN_CLICKED ||
1921 HIWORD(wParam) == BN_DOUBLECLICKED)
1922 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1925 if (HIWORD(wParam) == BN_CLICKED ||
1926 HIWORD(wParam) == BN_DOUBLECLICKED)
1927 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1930 if (HIWORD(wParam) == BN_CLICKED ||
1931 HIWORD(wParam) == BN_DOUBLECLICKED)
1932 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1935 if (HIWORD(wParam) == BN_CLICKED ||
1936 HIWORD(wParam) == BN_DOUBLECLICKED)
1937 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1940 if (HIWORD(wParam) == BN_CLICKED ||
1941 HIWORD(wParam) == BN_DOUBLECLICKED)
1942 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1945 if (HIWORD(wParam) == EN_CHANGE)
1946 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1947 sizeof(cfg.wintitle)-1);
1950 if (HIWORD(wParam) == BN_CLICKED ||
1951 HIWORD(wParam) == BN_DOUBLECLICKED)
1952 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1955 if (HIWORD(wParam) == BN_CLICKED ||
1956 HIWORD(wParam) == BN_DOUBLECLICKED)
1957 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1960 if (HIWORD(wParam) == EN_CHANGE)
1961 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1962 sizeof(cfg.termtype)-1);
1965 if (HIWORD(wParam) == EN_CHANGE)
1966 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1967 sizeof(cfg.termspeed)-1);
1970 if (HIWORD(wParam) == EN_CHANGE)
1971 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1972 sizeof(cfg.username)-1);
1976 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1979 if (HIWORD(wParam) == BN_CLICKED ||
1980 HIWORD(wParam) == BN_DOUBLECLICKED) {
1981 char str[sizeof(cfg.environmt)];
1983 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1988 p = str + strlen(str);
1990 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
2000 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
2002 p[strlen(str)+1] = '\0';
2003 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
2005 SetDlgItemText (hwnd, IDC_VAREDIT, "");
2006 SetDlgItemText (hwnd, IDC_VALEDIT, "");
2008 MessageBox(hwnd, "Environment too big", "PuTTY Error",
2009 MB_OK | MB_ICONERROR);
2014 if (HIWORD(wParam) != BN_CLICKED &&
2015 HIWORD(wParam) != BN_DOUBLECLICKED)
2017 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
2023 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
2048 if (HIWORD(wParam) == BN_CLICKED ||
2049 HIWORD(wParam) == BN_DOUBLECLICKED)
2050 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
2053 if (HIWORD(wParam) == BN_CLICKED ||
2054 HIWORD(wParam) == BN_DOUBLECLICKED)
2055 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
2057 case IDC_CIPHER3DES:
2058 case IDC_CIPHERBLOWF:
2060 if (HIWORD(wParam) == BN_CLICKED ||
2061 HIWORD(wParam) == BN_DOUBLECLICKED) {
2062 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
2063 cfg.cipher = CIPHER_3DES;
2064 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
2065 cfg.cipher = CIPHER_BLOWFISH;
2066 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
2067 cfg.cipher = CIPHER_DES;
2072 if (HIWORD(wParam) == BN_CLICKED ||
2073 HIWORD(wParam) == BN_DOUBLECLICKED) {
2074 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
2076 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
2081 if (HIWORD(wParam) == BN_CLICKED ||
2082 HIWORD(wParam) == BN_DOUBLECLICKED)
2083 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
2086 if (HIWORD(wParam) == EN_CHANGE)
2087 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
2088 sizeof(cfg.keyfile)-1);
2091 if (HIWORD(wParam) == EN_CHANGE)
2092 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2093 sizeof(cfg.remote_cmd)-1);
2096 memset(&of, 0, sizeof(of));
2097 #ifdef OPENFILENAME_SIZE_VERSION_400
2098 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2100 of.lStructSize = sizeof(of);
2102 of.hwndOwner = hwnd;
2103 of.lpstrFilter = "All Files\0*\0\0\0";
2104 of.lpstrCustomFilter = NULL;
2105 of.nFilterIndex = 1;
2106 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
2107 of.nMaxFile = sizeof(filename);
2108 of.lpstrFileTitle = NULL;
2109 of.lpstrInitialDir = NULL;
2110 of.lpstrTitle = "Select Public Key File";
2112 if (GetOpenFileName(&of)) {
2113 strcpy(cfg.keyfile, filename);
2114 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
2119 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
2125 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
2130 for (i=0; i<256; i++)
2131 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
2134 cfg.wordness[i] = n;
2135 SendDlgItemMessage (hwnd, IDC_CCLIST,
2136 LB_DELETESTRING, i, 0);
2137 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2138 (i>=0x21 && i != 0x7F) ? i : ' ',
2140 SendDlgItemMessage (hwnd, IDC_CCLIST,
2147 case IDC_BOLDCOLOUR:
2148 if (HIWORD(wParam) == BN_CLICKED ||
2149 HIWORD(wParam) == BN_DOUBLECLICKED) {
2151 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2152 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
2153 if (cfg.bold_colour && n!=22) {
2154 for (i=0; i<22; i++)
2156 SendDlgItemMessage (hwnd, IDC_LIST,
2158 (LPARAM) colours[i]);
2159 } else if (!cfg.bold_colour && n!=12) {
2162 SendDlgItemMessage (hwnd, IDC_LIST,
2163 LB_DELETESTRING, i, 0);
2168 if (HIWORD(wParam) == BN_CLICKED ||
2169 HIWORD(wParam) == BN_DOUBLECLICKED)
2170 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
2173 if (HIWORD(wParam) == LBN_DBLCLK ||
2174 HIWORD(wParam) == LBN_SELCHANGE) {
2175 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2177 if (!cfg.bold_colour)
2178 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2179 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2180 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2181 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
2185 if (HIWORD(wParam) == BN_CLICKED ||
2186 HIWORD(wParam) == BN_DOUBLECLICKED) {
2187 static CHOOSECOLOR cc;
2188 static DWORD custom[16] = {0}; /* zero initialisers */
2189 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2191 if (!cfg.bold_colour)
2192 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2193 cc.lStructSize = sizeof(cc);
2194 cc.hwndOwner = hwnd;
2195 cc.hInstance = (HWND)hinst;
2196 cc.lpCustColors = custom;
2197 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2199 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2200 if (ChooseColor(&cc)) {
2202 (unsigned char) (cc.rgbResult & 0xFF);
2204 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2206 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2207 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
2209 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
2211 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
2217 case IDC_KOI8WIN1251:
2218 case IDC_88592WIN1250:
2219 cfg.xlat_enablekoiwin =
2220 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
2221 cfg.xlat_88592w1250 =
2222 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
2224 case IDC_CAPSLOCKCYR:
2225 if (HIWORD(wParam) == BN_CLICKED ||
2226 HIWORD(wParam) == BN_DOUBLECLICKED) {
2227 cfg.xlat_capslockcyr =
2228 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
2231 case IDC_VTXWINDOWS:
2236 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2237 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2238 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
2244 EndDialog (hwnd, 0);
2247 /* Grrr Explorer will maximize Dialogs! */
2249 if (wParam == SIZE_MAXIMIZED)
2256 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2257 WPARAM wParam, LPARAM lParam) {
2258 static HWND page = NULL;
2260 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2262 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2263 EnableWindow(hwnd, 0);
2264 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2265 GetParent(hwnd), AboutProc);
2266 EnableWindow(hwnd, 1);
2267 SetActiveWindow(hwnd);
2269 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
2272 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2273 WPARAM wParam, LPARAM lParam) {
2275 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
2278 int do_config (void) {
2282 savedsession[0] = '\0';
2283 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2284 get_sesslist(FALSE);
2289 int do_reconfig (HWND hwnd) {
2293 backup_cfg = cfg; /* structure copy */
2294 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2296 cfg = backup_cfg; /* structure copy */
2303 void logevent (char *string) {
2304 if (nevents >= negsize) {
2306 events = srealloc (events, negsize * sizeof(*events));
2308 events[nevents] = smalloc(1+strlen(string));
2309 strcpy (events[nevents], string);
2313 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2315 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2316 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
2320 void showeventlog (HWND hwnd) {
2322 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2324 ShowWindow (logbox, SW_SHOWNORMAL);
2328 void showabout (HWND hwnd) {
2330 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2332 ShowWindow (abtbox, SW_SHOWNORMAL);
2336 void verify_ssh_host_key(char *host, int port, char *keytype,
2337 char *keystr, char *fingerprint) {
2340 static const char absentmsg[] =
2341 "The server's host key is not cached in the registry. You\n"
2342 "have no guarantee that the server is the computer you\n"
2344 "The server's key fingerprint is:\n"
2346 "If you trust this host, hit Yes to add the key to\n"
2347 "PuTTY's cache and carry on connecting.\n"
2348 "If you do not trust this host, hit No to abandon the\n"
2351 static const char wrongmsg[] =
2352 "WARNING - POTENTIAL SECURITY BREACH!\n"
2354 "The server's host key does not match the one PuTTY has\n"
2355 "cached in the registry. This means that either the\n"
2356 "server administrator has changed the host key, or you\n"
2357 "have actually connected to another computer pretending\n"
2358 "to be the server.\n"
2359 "The new key fingerprint is:\n"
2361 "If you were expecting this change and trust the new key,\n"
2362 "hit Yes to update PuTTY's cache and continue connecting.\n"
2363 "If you want to carry on connecting but without updating\n"
2364 "the cache, hit No.\n"
2365 "If you want to abandon the connection completely, hit\n"
2366 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2369 static const char mbtitle[] = "PuTTY Security Alert";
2372 char message[160+ /* sensible fingerprint max size */
2373 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2374 sizeof(absentmsg) : sizeof(wrongmsg))];
2377 * Verify the key against the registry.
2379 ret = verify_host_key(host, port, keytype, keystr);
2381 if (ret == 0) /* success - key matched OK */
2383 if (ret == 2) { /* key was different */
2385 sprintf(message, wrongmsg, fingerprint);
2386 mbret = MessageBox(NULL, message, mbtitle,
2387 MB_ICONWARNING | MB_YESNOCANCEL);
2389 store_host_key(host, port, keytype, keystr);
2390 if (mbret == IDCANCEL)
2393 if (ret == 1) { /* key was absent */
2395 sprintf(message, absentmsg, fingerprint);
2396 mbret = MessageBox(NULL, message, mbtitle,
2397 MB_ICONWARNING | MB_YESNO);
2400 store_host_key(host, port, keytype, keystr);