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,
1007 translationpanelend,
1012 static const char *const colours[] = {
1013 "Default Foreground", "Default Bold Foreground",
1014 "Default Background", "Default Bold Background",
1015 "Cursor Text", "Cursor Colour",
1016 "ANSI Black", "ANSI Black Bold",
1017 "ANSI Red", "ANSI Red Bold",
1018 "ANSI Green", "ANSI Green Bold",
1019 "ANSI Yellow", "ANSI Yellow Bold",
1020 "ANSI Blue", "ANSI Blue Bold",
1021 "ANSI Magenta", "ANSI Magenta Bold",
1022 "ANSI Cyan", "ANSI Cyan Bold",
1023 "ANSI White", "ANSI White Bold"
1025 static const int permcolour[] = {
1026 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1027 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1028 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1031 static void fmtfont (char *buf) {
1032 sprintf (buf, "Font: %s, ", cfg.font);
1034 strcat(buf, "bold, ");
1035 if (cfg.fontheight == 0)
1036 strcat (buf, "default height");
1038 sprintf (buf+strlen(buf), "%d-%s",
1039 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
1040 (cfg.fontheight < 0 ? "pixel" : "point"));
1043 static void init_dlg_ctrls(HWND hwnd) {
1045 char fontstatic[256];
1047 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1048 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
1049 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1050 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1051 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1052 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1053 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
1055 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1056 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1057 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1058 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1059 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
1060 cfg.funky_type == 0 ? IDC_FUNCTILDE :
1061 cfg.funky_type == 1 ? IDC_FUNCLINUX :
1062 cfg.funky_type == 2 ? IDC_FUNCXTERM :
1063 cfg.funky_type == 3 ? IDC_FUNCVT400 :
1065 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1066 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1067 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1068 cfg.nethack_keypad ? IDC_KPNH :
1069 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1070 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1071 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1072 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1073 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
1075 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1076 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1077 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1078 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1079 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1080 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
1081 fmtfont (fontstatic);
1082 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1083 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1084 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1085 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
1087 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1088 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1089 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1090 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1091 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
1092 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1093 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1095 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1096 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1097 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1099 char *p = cfg.environmt;
1101 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
1106 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1107 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
1109 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1110 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1111 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
1112 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
1113 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
1114 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
1115 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
1117 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
1118 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
1119 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
1120 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1121 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
1123 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
1124 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
1126 static int tabs[4] = {25, 61, 96, 128};
1127 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
1130 for (i=0; i<256; i++) {
1132 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1133 (i>=0x21 && i != 0x7F) ? i : ' ',
1135 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
1139 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
1140 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
1143 for (i=0; i<22; i++)
1144 if (cfg.bold_colour || permcolour[i])
1145 SendDlgItemMessage (hwnd, IDC_LIST, LB_ADDSTRING, 0,
1146 (LPARAM) colours[i]);
1148 SendDlgItemMessage (hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
1149 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
1150 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
1151 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
1153 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
1154 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
1155 cfg.xlat_88592cp852 ? IDC_88592CP852 :
1156 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
1158 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1159 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
1160 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
1161 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
1162 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
1166 static void hide(HWND hwnd, int hide, int minid, int maxid) {
1168 for (i = minid; i < maxid; i++) {
1169 HWND ctl = GetDlgItem(hwnd, i);
1171 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1176 struct treeview_faff {
1178 HTREEITEM lastat[4];
1181 static HTREEITEM treeview_insert(struct treeview_faff *faff,
1182 int level, char *text) {
1186 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
1187 ins.hInsertAfter = faff->lastat[level];
1188 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
1189 #define INSITEM DUMMYUNIONNAME.item
1191 #define INSITEM item
1193 ins.INSITEM.mask = TVIF_TEXT;
1194 ins.INSITEM.pszText = text;
1195 newitem = TreeView_InsertItem(faff->treeview, &ins);
1197 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
1198 faff->lastat[level] = newitem;
1199 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
1204 * This _huge_ function is the configuration box.
1206 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1207 WPARAM wParam, LPARAM lParam,
1210 struct treeview_faff tvfaff;
1213 char filename[sizeof(cfg.keyfile)];
1216 char fontstatic[256];
1221 SetWindowLong(hwnd, GWL_USERDATA, 0);
1223 * Centre the window.
1225 { /* centre the window */
1228 hw = GetDesktopWindow();
1229 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1230 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1231 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1232 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1236 * Create the tree view.
1243 r.left = 3; r.right = r.left + 75;
1244 r.top = 3; r.bottom = r.top + 10;
1245 MapDialogRect(hwnd, &r);
1246 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1247 WS_CHILD | WS_VISIBLE,
1249 r.right-r.left, r.bottom-r.top,
1250 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1251 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1252 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1254 r.left = 3; r.right = r.left + 75;
1255 r.top = 13; r.bottom = r.top + 196;
1256 MapDialogRect(hwnd, &r);
1257 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1258 WS_CHILD | WS_VISIBLE |
1259 WS_TABSTOP | TVS_HASLINES |
1260 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1261 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1263 r.right-r.left, r.bottom-r.top,
1264 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1265 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1266 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1267 tvfaff.treeview = treeview;
1268 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1272 * Create the various panelfuls of controls.
1275 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1278 ctlposinit(&cp, hwnd, 80, 3, 13);
1279 bartitle(&cp, "Basic options for your PuTTY session",
1282 beginbox(&cp, "Specify your connection by host name",
1283 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
1285 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1286 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
1287 if (backends[2].backend == NULL) {
1288 /* this is PuTTYtel, so only two protocols available */
1289 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1290 "&Raw", IDC_PROTRAW,
1291 "&Telnet", IDC_PROTTELNET, NULL);
1293 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1294 "&Raw", IDC_PROTRAW,
1295 "&Telnet", IDC_PROTTELNET,
1304 beginbox(&cp, "Load, save or delete a stored session",
1305 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
1306 sesssaver(&cp, "Stor&ed Sessions",
1307 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1308 "&Load", IDC_SESSLOAD,
1309 "&Save", IDC_SESSSAVE,
1310 "&Delete", IDC_SESSDEL, NULL);
1313 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
1314 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1317 hsession = treeview_insert(&tvfaff, 0, "Session");
1320 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1323 ctlposinit(&cp, hwnd, 80, 3, 13);
1324 bartitle(&cp, "Options controlling the terminal emulation",
1325 IDC_TITLE_TERMINAL);
1326 beginbox(&cp, "Set the size of the terminal window",
1327 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
1329 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1330 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
1332 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
1334 beginbox(&cp, "Set the font used in the terminal window",
1335 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
1336 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1338 beginbox(&cp, "Set various terminal options",
1339 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3);
1340 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1341 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1342 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1343 checkbox(&cp, "&Beep enabled", IDC_BEEP);
1344 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
1345 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1346 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1349 treeview_insert(&tvfaff, 0, "Terminal");
1352 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1355 ctlposinit(&cp, hwnd, 80, 3, 13);
1356 bartitle(&cp, "Options controlling the effects of keys",
1357 IDC_TITLE_KEYBOARD);
1358 beginbox(&cp, "Change the sequences sent by:",
1359 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
1360 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
1361 "Control-&H", IDC_DEL008,
1362 "Control-&? (127)", IDC_DEL127, NULL);
1363 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
1364 "&Standard", IDC_HOMETILDE,
1365 "&rxvt", IDC_HOMERXVT, NULL);
1366 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
1367 "ESC[n&~", IDC_FUNCTILDE,
1368 "&Linux", IDC_FUNCLINUX,
1369 "&Xterm R6", IDC_FUNCXTERM,
1370 "&VT400", IDC_FUNCVT400, NULL);
1372 beginbox(&cp, "Change the initial state of:",
1373 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
1374 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1375 "&Normal", IDC_CURNORMAL,
1376 "A&pplication", IDC_CURAPPLIC, NULL);
1377 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1378 "Nor&mal", IDC_KPNORMAL,
1379 "Appl&ication", IDC_KPAPPLIC,
1380 "N&etHack", IDC_KPNH, NULL);
1383 treeview_insert(&tvfaff, 1, "Keyboard");
1386 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1389 ctlposinit(&cp, hwnd, 80, 3, 13);
1390 bartitle(&cp, "Options controlling PuTTY's window",
1392 beginbox(&cp, "Adjust the use of the window title",
1393 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
1396 "Initial window &title:", IDC_WINTITLE,
1397 IDC_WINEDIT, 100, NULL);
1398 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1400 beginbox(&cp, "Adjust the use of the cursor",
1401 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
1402 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1404 beginbox(&cp, "Control the scrollback in the window",
1405 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3);
1406 staticedit(&cp, "Lines of &scrollback",
1407 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1408 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1409 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1411 beginbox(&cp, NULL, IDC_BOX_WINDOW4, 0);
1412 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1413 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1414 checkbox(&cp, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE);
1417 treeview_insert(&tvfaff, 0, "Window");
1420 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1423 ctlposinit(&cp, hwnd, 80, 3, 13);
1424 bartitle(&cp, "Options controlling character set translation",
1425 IDC_TITLE_TRANSLATION);
1426 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1427 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
1429 "Handling of line drawing characters:", IDC_VTSTATIC,
1430 "Font has &XWindows encoding", IDC_VTXWINDOWS,
1431 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1432 "Use font in O&EM mode only", IDC_VTOEMONLY,
1433 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1434 IDC_VTPOORMAN, NULL);
1436 beginbox(&cp, "Enable character set translation on received data",
1437 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
1439 "Character set translation:", IDC_XLATSTATIC,
1440 "&None", IDC_NOXLAT,
1441 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
1442 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
1443 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
1445 beginbox(&cp, "Enable character set translation on input data",
1446 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
1447 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
1451 treeview_insert(&tvfaff, 1, "Translation");
1454 /* The Selection panel. Accelerators used: [acgo] wxst */
1457 ctlposinit(&cp, hwnd, 80, 3, 13);
1458 bartitle(&cp, "Options controlling copy and paste",
1459 IDC_TITLE_SELECTION);
1460 beginbox(&cp, "Control which mouse button does which thing",
1461 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
1462 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1463 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1464 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1467 beginbox(&cp, "Control the select-one-word-at-a-time mode",
1468 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
1469 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1470 "&Set", IDC_CCSET, IDC_CCEDIT,
1471 "&to class", IDC_CCSTATIC2);
1474 treeview_insert(&tvfaff, 1, "Selection");
1477 /* The Colours panel. Accelerators used: [acgo] blum */
1480 ctlposinit(&cp, hwnd, 80, 3, 13);
1481 bartitle(&cp, "Options controlling use of colours",
1483 beginbox(&cp, "General options for colour usage",
1484 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
1485 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
1486 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1488 beginbox(&cp, "Adjust the precise colours PuTTY displays",
1489 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
1490 colouredit(&cp, "Select a colo&ur and then click to modify it:",
1491 IDC_STATIC, IDC_LIST,
1492 "&Modify...", IDC_CHANGE,
1493 "Red:", IDC_RSTATIC, IDC_RVALUE,
1494 "Green:", IDC_GSTATIC, IDC_GVALUE,
1495 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1498 treeview_insert(&tvfaff, 1, "Colours");
1501 /* The Connection panel. Accelerators used: [acgo] tuk */
1504 ctlposinit(&cp, hwnd, 80, 3, 13);
1505 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
1507 beginbox(&cp, "Data to send to the server",
1508 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
1509 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
1510 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
1513 beginbox(&cp, "Sending of null packets to keep session active",
1514 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
1515 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
1516 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
1519 treeview_insert(&tvfaff, 0, "Connection");
1522 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1525 ctlposinit(&cp, hwnd, 80, 3, 13);
1527 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
1528 beginbox(&cp, "Data to send to the server",
1529 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
1530 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
1531 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1532 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1533 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1535 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1537 beginbox(&cp, "Telnet protocol adjustments",
1538 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
1539 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1540 "&BSD (commonplace)", IDC_EMBSD,
1541 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1544 treeview_insert(&tvfaff, 1, "Telnet");
1548 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1549 if (backends[2].backend != NULL) {
1551 ctlposinit(&cp, hwnd, 80, 3, 13);
1553 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1554 beginbox(&cp, "Data to send to the server",
1555 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1557 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1560 beginbox(&cp, "Authentication options",
1561 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1562 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1564 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1565 editbutton(&cp, "Private &key file for authentication:",
1566 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1568 beginbox(&cp, "Protocol options",
1569 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1570 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1571 radioline(&cp, "Preferred SSH protocol version:",
1572 IDC_SSHPROTSTATIC, 2,
1573 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1574 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1575 "&3DES", IDC_CIPHER3DES,
1576 "&Blowfish", IDC_CIPHERBLOWF,
1577 "&DES", IDC_CIPHERDES, NULL);
1580 treeview_insert(&tvfaff, 1, "SSH");
1584 init_dlg_ctrls(hwnd);
1585 for (i = 0; i < nsessions; i++)
1586 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1587 0, (LPARAM) (sessions[i]));
1590 * Hide all the controls to start with.
1592 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1595 * Put the treeview selection on to the Session panel. This
1596 * should also cause unhiding of the relevant controls.
1598 TreeView_SelectItem(treeview, hsession);
1601 * Set focus into the first available control.
1605 ctl = GetDlgItem(hwnd, IDC_HOST);
1606 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1610 SetWindowLong(hwnd, GWL_USERDATA, 1);
1614 * Button release should trigger WM_OK if there was a
1615 * previous double click on the session list.
1619 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1622 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1623 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1624 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1628 item.pszText = buffer;
1629 item.cchTextMax = sizeof(buffer);
1630 item.mask = TVIF_TEXT;
1631 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1632 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1633 if (!strcmp(buffer, "Session"))
1634 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1635 if (!strcmp(buffer, "Keyboard"))
1636 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1637 if (!strcmp(buffer, "Terminal"))
1638 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1639 if (!strcmp(buffer, "Window"))
1640 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1641 if (!strcmp(buffer, "Connection"))
1642 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1643 if (!strcmp(buffer, "Telnet"))
1644 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1645 if (!strcmp(buffer, "SSH"))
1646 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1647 if (!strcmp(buffer, "Selection"))
1648 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1649 if (!strcmp(buffer, "Colours"))
1650 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1651 if (!strcmp(buffer, "Translation"))
1652 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1654 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1660 * Only process WM_COMMAND once the dialog is fully formed.
1662 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1665 EndDialog (hwnd, 1);
1670 EndDialog (hwnd, 0);
1672 case IDC_PROTTELNET:
1675 if (HIWORD(wParam) == BN_CLICKED ||
1676 HIWORD(wParam) == BN_DOUBLECLICKED) {
1677 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1678 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1679 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1680 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1681 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1682 cfg.port = i ? 22 : 23;
1683 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1688 if (HIWORD(wParam) == EN_CHANGE)
1689 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1690 sizeof(cfg.host)-1);
1693 if (HIWORD(wParam) == EN_CHANGE)
1694 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1697 if (HIWORD(wParam) == EN_CHANGE) {
1698 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1700 GetDlgItemText (hwnd, IDC_SESSEDIT,
1701 savedsession, sizeof(savedsession)-1);
1702 savedsession[sizeof(savedsession)-1] = '\0';
1706 if (HIWORD(wParam) == BN_CLICKED ||
1707 HIWORD(wParam) == BN_DOUBLECLICKED) {
1712 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1714 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1715 LB_GETCURSEL, 0, 0);
1720 strcpy (str, sessions[n]);
1722 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1723 get_sesslist (FALSE);
1724 get_sesslist (TRUE);
1725 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1727 for (i = 0; i < nsessions; i++)
1728 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1729 0, (LPARAM) (sessions[i]));
1730 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1736 if (LOWORD(wParam) == IDC_SESSLOAD &&
1737 HIWORD(wParam) != BN_CLICKED &&
1738 HIWORD(wParam) != BN_DOUBLECLICKED)
1740 if (LOWORD(wParam) == IDC_SESSLIST &&
1741 HIWORD(wParam) != LBN_DBLCLK)
1744 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1745 LB_GETCURSEL, 0, 0);
1751 isdef = !strcmp(sessions[n], "Default Settings");
1752 load_settings (sessions[n], !isdef, &cfg);
1753 init_dlg_ctrls(hwnd);
1755 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1757 if (LOWORD(wParam) == IDC_SESSLIST) {
1759 * A double-click on a saved session should
1760 * actually start the session, not just load it.
1761 * Unless it's Default Settings or some other
1762 * host-less set of saved settings.
1771 if (HIWORD(wParam) == BN_CLICKED ||
1772 HIWORD(wParam) == BN_DOUBLECLICKED) {
1773 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1774 LB_GETCURSEL, 0, 0);
1775 if (n == LB_ERR || n == 0) {
1779 del_settings(sessions[n]);
1780 get_sesslist (FALSE);
1781 get_sesslist (TRUE);
1782 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1784 for (i = 0; i < nsessions; i++)
1785 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1786 0, (LPARAM) (sessions[i]));
1787 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1791 if (HIWORD(wParam) == EN_CHANGE)
1792 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1796 if (HIWORD(wParam) == BN_CLICKED ||
1797 HIWORD(wParam) == BN_DOUBLECLICKED)
1798 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1802 if (HIWORD(wParam) == BN_CLICKED ||
1803 HIWORD(wParam) == BN_DOUBLECLICKED)
1804 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1807 if (HIWORD(wParam) == BN_CLICKED ||
1808 HIWORD(wParam) == BN_DOUBLECLICKED)
1812 if (HIWORD(wParam) == BN_CLICKED ||
1813 HIWORD(wParam) == BN_DOUBLECLICKED)
1818 if (HIWORD(wParam) == BN_CLICKED ||
1819 HIWORD(wParam) == BN_DOUBLECLICKED)
1820 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1824 if (HIWORD(wParam) == BN_CLICKED ||
1825 HIWORD(wParam) == BN_DOUBLECLICKED) {
1826 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1827 cfg.nethack_keypad = FALSE;
1831 if (HIWORD(wParam) == BN_CLICKED ||
1832 HIWORD(wParam) == BN_DOUBLECLICKED) {
1833 cfg.app_keypad = FALSE;
1834 cfg.nethack_keypad = TRUE;
1839 if (HIWORD(wParam) == BN_CLICKED ||
1840 HIWORD(wParam) == BN_DOUBLECLICKED)
1841 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1844 if (HIWORD(wParam) == BN_CLICKED ||
1845 HIWORD(wParam) == BN_DOUBLECLICKED)
1846 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1849 if (HIWORD(wParam) == BN_CLICKED ||
1850 HIWORD(wParam) == BN_DOUBLECLICKED)
1851 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1854 if (HIWORD(wParam) == BN_CLICKED ||
1855 HIWORD(wParam) == BN_DOUBLECLICKED)
1856 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1859 if (HIWORD(wParam) == BN_CLICKED ||
1860 HIWORD(wParam) == BN_DOUBLECLICKED)
1861 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1864 if (HIWORD(wParam) == BN_CLICKED ||
1865 HIWORD(wParam) == BN_DOUBLECLICKED)
1866 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1869 if (HIWORD(wParam) == BN_CLICKED ||
1870 HIWORD(wParam) == BN_DOUBLECLICKED)
1871 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1874 if (HIWORD(wParam) == BN_CLICKED ||
1875 HIWORD(wParam) == BN_DOUBLECLICKED)
1876 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1879 if (HIWORD(wParam) == EN_CHANGE)
1880 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1883 if (HIWORD(wParam) == EN_CHANGE)
1884 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1887 if (HIWORD(wParam) == EN_CHANGE)
1888 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1890 case IDC_CHOOSEFONT:
1891 lf.lfHeight = cfg.fontheight;
1892 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1893 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1894 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1895 lf.lfCharSet = cfg.fontcharset;
1896 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1897 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1898 lf.lfQuality = DEFAULT_QUALITY;
1899 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1900 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1901 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1903 cf.lStructSize = sizeof(cf);
1904 cf.hwndOwner = hwnd;
1906 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1907 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1909 if (ChooseFont (&cf)) {
1910 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1911 cfg.font[sizeof(cfg.font)-1] = '\0';
1912 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1913 cfg.fontcharset = lf.lfCharSet;
1914 cfg.fontheight = lf.lfHeight;
1915 fmtfont (fontstatic);
1916 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1920 if (HIWORD(wParam) == BN_CLICKED ||
1921 HIWORD(wParam) == BN_DOUBLECLICKED)
1922 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1925 if (HIWORD(wParam) == BN_CLICKED ||
1926 HIWORD(wParam) == BN_DOUBLECLICKED)
1927 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1930 if (HIWORD(wParam) == BN_CLICKED ||
1931 HIWORD(wParam) == BN_DOUBLECLICKED)
1932 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1935 if (HIWORD(wParam) == BN_CLICKED ||
1936 HIWORD(wParam) == BN_DOUBLECLICKED)
1937 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1940 if (HIWORD(wParam) == BN_CLICKED ||
1941 HIWORD(wParam) == BN_DOUBLECLICKED)
1942 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1945 if (HIWORD(wParam) == BN_CLICKED ||
1946 HIWORD(wParam) == BN_DOUBLECLICKED)
1947 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1950 if (HIWORD(wParam) == BN_CLICKED ||
1951 HIWORD(wParam) == BN_DOUBLECLICKED)
1952 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1955 if (HIWORD(wParam) == EN_CHANGE)
1956 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1957 sizeof(cfg.wintitle)-1);
1960 if (HIWORD(wParam) == BN_CLICKED ||
1961 HIWORD(wParam) == BN_DOUBLECLICKED)
1962 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1965 if (HIWORD(wParam) == BN_CLICKED ||
1966 HIWORD(wParam) == BN_DOUBLECLICKED)
1967 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1970 if (HIWORD(wParam) == EN_CHANGE)
1971 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1972 sizeof(cfg.termtype)-1);
1975 if (HIWORD(wParam) == EN_CHANGE)
1976 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1977 sizeof(cfg.termspeed)-1);
1980 if (HIWORD(wParam) == EN_CHANGE)
1981 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1982 sizeof(cfg.username)-1);
1986 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1989 if (HIWORD(wParam) == BN_CLICKED ||
1990 HIWORD(wParam) == BN_DOUBLECLICKED) {
1991 char str[sizeof(cfg.environmt)];
1993 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1998 p = str + strlen(str);
2000 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
2010 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
2012 p[strlen(str)+1] = '\0';
2013 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
2015 SetDlgItemText (hwnd, IDC_VAREDIT, "");
2016 SetDlgItemText (hwnd, IDC_VALEDIT, "");
2018 MessageBox(hwnd, "Environment too big", "PuTTY Error",
2019 MB_OK | MB_ICONERROR);
2024 if (HIWORD(wParam) != BN_CLICKED &&
2025 HIWORD(wParam) != BN_DOUBLECLICKED)
2027 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
2033 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
2058 if (HIWORD(wParam) == BN_CLICKED ||
2059 HIWORD(wParam) == BN_DOUBLECLICKED)
2060 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
2063 if (HIWORD(wParam) == BN_CLICKED ||
2064 HIWORD(wParam) == BN_DOUBLECLICKED)
2065 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
2067 case IDC_CIPHER3DES:
2068 case IDC_CIPHERBLOWF:
2070 if (HIWORD(wParam) == BN_CLICKED ||
2071 HIWORD(wParam) == BN_DOUBLECLICKED) {
2072 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
2073 cfg.cipher = CIPHER_3DES;
2074 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
2075 cfg.cipher = CIPHER_BLOWFISH;
2076 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
2077 cfg.cipher = CIPHER_DES;
2082 if (HIWORD(wParam) == BN_CLICKED ||
2083 HIWORD(wParam) == BN_DOUBLECLICKED) {
2084 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
2086 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
2091 if (HIWORD(wParam) == BN_CLICKED ||
2092 HIWORD(wParam) == BN_DOUBLECLICKED)
2093 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
2096 if (HIWORD(wParam) == EN_CHANGE)
2097 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
2098 sizeof(cfg.keyfile)-1);
2101 if (HIWORD(wParam) == EN_CHANGE)
2102 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2103 sizeof(cfg.remote_cmd)-1);
2106 memset(&of, 0, sizeof(of));
2107 #ifdef OPENFILENAME_SIZE_VERSION_400
2108 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2110 of.lStructSize = sizeof(of);
2112 of.hwndOwner = hwnd;
2113 of.lpstrFilter = "All Files\0*\0\0\0";
2114 of.lpstrCustomFilter = NULL;
2115 of.nFilterIndex = 1;
2116 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
2117 of.nMaxFile = sizeof(filename);
2118 of.lpstrFileTitle = NULL;
2119 of.lpstrInitialDir = NULL;
2120 of.lpstrTitle = "Select Public Key File";
2122 if (GetOpenFileName(&of)) {
2123 strcpy(cfg.keyfile, filename);
2124 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
2129 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
2135 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
2140 for (i=0; i<256; i++)
2141 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
2144 cfg.wordness[i] = n;
2145 SendDlgItemMessage (hwnd, IDC_CCLIST,
2146 LB_DELETESTRING, i, 0);
2147 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2148 (i>=0x21 && i != 0x7F) ? i : ' ',
2150 SendDlgItemMessage (hwnd, IDC_CCLIST,
2157 case IDC_BOLDCOLOUR:
2158 if (HIWORD(wParam) == BN_CLICKED ||
2159 HIWORD(wParam) == BN_DOUBLECLICKED) {
2161 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2162 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
2163 if (cfg.bold_colour && n!=22) {
2164 for (i=0; i<22; i++)
2166 SendDlgItemMessage (hwnd, IDC_LIST,
2168 (LPARAM) colours[i]);
2169 } else if (!cfg.bold_colour && n!=12) {
2172 SendDlgItemMessage (hwnd, IDC_LIST,
2173 LB_DELETESTRING, i, 0);
2178 if (HIWORD(wParam) == BN_CLICKED ||
2179 HIWORD(wParam) == BN_DOUBLECLICKED)
2180 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
2183 if (HIWORD(wParam) == LBN_DBLCLK ||
2184 HIWORD(wParam) == LBN_SELCHANGE) {
2185 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2187 if (!cfg.bold_colour)
2188 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2189 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2190 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2191 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
2195 if (HIWORD(wParam) == BN_CLICKED ||
2196 HIWORD(wParam) == BN_DOUBLECLICKED) {
2197 static CHOOSECOLOR cc;
2198 static DWORD custom[16] = {0}; /* zero initialisers */
2199 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2201 if (!cfg.bold_colour)
2202 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2203 cc.lStructSize = sizeof(cc);
2204 cc.hwndOwner = hwnd;
2205 cc.hInstance = (HWND)hinst;
2206 cc.lpCustColors = custom;
2207 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2209 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2210 if (ChooseColor(&cc)) {
2212 (unsigned char) (cc.rgbResult & 0xFF);
2214 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2216 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2217 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
2219 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
2221 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
2227 case IDC_KOI8WIN1251:
2228 case IDC_88592WIN1250:
2229 case IDC_88592CP852:
2230 cfg.xlat_enablekoiwin =
2231 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
2232 cfg.xlat_88592w1250 =
2233 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
2234 cfg.xlat_88592cp852 =
2235 IsDlgButtonChecked (hwnd, IDC_88592CP852);
2237 case IDC_CAPSLOCKCYR:
2238 if (HIWORD(wParam) == BN_CLICKED ||
2239 HIWORD(wParam) == BN_DOUBLECLICKED) {
2240 cfg.xlat_capslockcyr =
2241 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
2244 case IDC_VTXWINDOWS:
2249 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2250 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2251 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
2257 EndDialog (hwnd, 0);
2260 /* Grrr Explorer will maximize Dialogs! */
2262 if (wParam == SIZE_MAXIMIZED)
2269 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2270 WPARAM wParam, LPARAM lParam) {
2271 static HWND page = NULL;
2273 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2275 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2276 EnableWindow(hwnd, 0);
2277 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2278 GetParent(hwnd), AboutProc);
2279 EnableWindow(hwnd, 1);
2280 SetActiveWindow(hwnd);
2282 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
2285 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2286 WPARAM wParam, LPARAM lParam) {
2288 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
2291 int do_config (void) {
2295 savedsession[0] = '\0';
2296 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2297 get_sesslist(FALSE);
2302 int do_reconfig (HWND hwnd) {
2306 backup_cfg = cfg; /* structure copy */
2307 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2309 cfg = backup_cfg; /* structure copy */
2316 void logevent (char *string) {
2317 if (nevents >= negsize) {
2319 events = srealloc (events, negsize * sizeof(*events));
2321 events[nevents] = smalloc(1+strlen(string));
2322 strcpy (events[nevents], string);
2326 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2328 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2329 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
2333 void showeventlog (HWND hwnd) {
2335 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2337 ShowWindow (logbox, SW_SHOWNORMAL);
2341 void showabout (HWND hwnd) {
2343 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2345 ShowWindow (abtbox, SW_SHOWNORMAL);
2349 void verify_ssh_host_key(char *host, int port, char *keytype,
2350 char *keystr, char *fingerprint) {
2353 static const char absentmsg[] =
2354 "The server's host key is not cached in the registry. You\n"
2355 "have no guarantee that the server is the computer you\n"
2357 "The server's key fingerprint is:\n"
2359 "If you trust this host, hit Yes to add the key to\n"
2360 "PuTTY's cache and carry on connecting.\n"
2361 "If you do not trust this host, hit No to abandon the\n"
2364 static const char wrongmsg[] =
2365 "WARNING - POTENTIAL SECURITY BREACH!\n"
2367 "The server's host key does not match the one PuTTY has\n"
2368 "cached in the registry. This means that either the\n"
2369 "server administrator has changed the host key, or you\n"
2370 "have actually connected to another computer pretending\n"
2371 "to be the server.\n"
2372 "The new key fingerprint is:\n"
2374 "If you were expecting this change and trust the new key,\n"
2375 "hit Yes to update PuTTY's cache and continue connecting.\n"
2376 "If you want to carry on connecting but without updating\n"
2377 "the cache, hit No.\n"
2378 "If you want to abandon the connection completely, hit\n"
2379 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2382 static const char mbtitle[] = "PuTTY Security Alert";
2385 char message[160+ /* sensible fingerprint max size */
2386 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2387 sizeof(absentmsg) : sizeof(wrongmsg))];
2390 * Verify the key against the registry.
2392 ret = verify_host_key(host, port, keytype, keystr);
2394 if (ret == 0) /* success - key matched OK */
2396 if (ret == 2) { /* key was different */
2398 sprintf(message, wrongmsg, fingerprint);
2399 mbret = MessageBox(NULL, message, mbtitle,
2400 MB_ICONWARNING | MB_YESNOCANCEL);
2402 store_host_key(host, port, keytype, keystr);
2403 if (mbret == IDCANCEL)
2406 if (ret == 1) { /* key was absent */
2408 sprintf(message, absentmsg, fingerprint);
2409 mbret = MessageBox(NULL, message, mbtitle,
2410 MB_ICONWARNING | MB_YESNO);
2413 store_host_key(host, port, keytype, keystr);