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 for (i = 0; i < nsessions; i++)
1051 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1052 0, (LPARAM) (sessions[i]));
1053 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1054 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1055 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1056 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
1058 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1059 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1060 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1061 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1062 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCXTERM,
1063 cfg.funky_type == 0 ? IDC_FUNCTILDE :
1064 cfg.funky_type == 1 ? IDC_FUNCLINUX :
1065 cfg.funky_type == 2 ? IDC_FUNCXTERM :
1066 cfg.funky_type == 3 ? IDC_FUNCVT400 :
1068 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1069 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1070 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1071 cfg.nethack_keypad ? IDC_KPNH :
1072 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1073 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1074 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1075 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1076 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
1078 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1079 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1080 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1081 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1082 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1083 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
1084 fmtfont (fontstatic);
1085 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1086 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1087 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1088 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
1090 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1091 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1092 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1093 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1094 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
1095 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1096 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1098 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1099 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1100 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1102 char *p = cfg.environmt;
1104 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
1109 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1110 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
1112 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1113 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1114 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
1115 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
1116 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
1117 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
1118 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
1120 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
1121 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
1122 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
1123 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1124 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
1126 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
1127 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
1129 static int tabs[4] = {25, 61, 96, 128};
1130 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
1133 for (i=0; i<256; i++) {
1135 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1136 (i>=0x21 && i != 0x7F) ? i : ' ',
1138 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
1142 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
1143 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
1146 for (i=0; i<22; i++)
1147 if (cfg.bold_colour || permcolour[i])
1148 SendDlgItemMessage (hwnd, IDC_LIST, LB_ADDSTRING, 0,
1149 (LPARAM) colours[i]);
1151 SendDlgItemMessage (hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
1152 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
1153 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
1154 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
1156 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
1157 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
1158 cfg.xlat_88592cp852 ? IDC_88592CP852 :
1159 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
1161 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1162 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
1163 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
1164 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
1165 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
1169 static void hide(HWND hwnd, int hide, int minid, int maxid) {
1171 for (i = minid; i < maxid; i++) {
1172 HWND ctl = GetDlgItem(hwnd, i);
1174 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1179 struct treeview_faff {
1181 HTREEITEM lastat[4];
1184 static HTREEITEM treeview_insert(struct treeview_faff *faff,
1185 int level, char *text) {
1189 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
1190 ins.hInsertAfter = faff->lastat[level];
1191 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
1192 #define INSITEM DUMMYUNIONNAME.item
1194 #define INSITEM item
1196 ins.INSITEM.mask = TVIF_TEXT;
1197 ins.INSITEM.pszText = text;
1198 newitem = TreeView_InsertItem(faff->treeview, &ins);
1200 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
1201 faff->lastat[level] = newitem;
1202 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
1207 * This _huge_ function is the configuration box.
1209 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1210 WPARAM wParam, LPARAM lParam,
1213 struct treeview_faff tvfaff;
1216 char filename[sizeof(cfg.keyfile)];
1219 char fontstatic[256];
1224 SetWindowLong(hwnd, GWL_USERDATA, 0);
1226 * Centre the window.
1228 { /* centre the window */
1231 hw = GetDesktopWindow();
1232 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1233 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1234 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1235 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1239 * Create the tree view.
1246 r.left = 3; r.right = r.left + 75;
1247 r.top = 3; r.bottom = r.top + 10;
1248 MapDialogRect(hwnd, &r);
1249 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1250 WS_CHILD | WS_VISIBLE,
1252 r.right-r.left, r.bottom-r.top,
1253 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1254 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1255 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1257 r.left = 3; r.right = r.left + 75;
1258 r.top = 13; r.bottom = r.top + 196;
1259 MapDialogRect(hwnd, &r);
1260 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1261 WS_CHILD | WS_VISIBLE |
1262 WS_TABSTOP | TVS_HASLINES |
1263 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1264 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1266 r.right-r.left, r.bottom-r.top,
1267 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1268 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1269 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1270 tvfaff.treeview = treeview;
1271 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1275 * Create the various panelfuls of controls.
1278 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1281 ctlposinit(&cp, hwnd, 80, 3, 13);
1282 bartitle(&cp, "Basic options for your PuTTY session",
1285 beginbox(&cp, "Specify your connection by host name",
1286 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
1288 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1289 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
1290 if (backends[2].backend == NULL) {
1291 /* this is PuTTYtel, so only two protocols available */
1292 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1293 "&Raw", IDC_PROTRAW,
1294 "&Telnet", IDC_PROTTELNET, NULL);
1296 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1297 "&Raw", IDC_PROTRAW,
1298 "&Telnet", IDC_PROTTELNET,
1307 beginbox(&cp, "Load, save or delete a stored session",
1308 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
1309 sesssaver(&cp, "Stor&ed Sessions",
1310 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1311 "&Load", IDC_SESSLOAD,
1312 "&Save", IDC_SESSSAVE,
1313 "&Delete", IDC_SESSDEL, NULL);
1316 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
1317 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1320 hsession = treeview_insert(&tvfaff, 0, "Session");
1323 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1326 ctlposinit(&cp, hwnd, 80, 3, 13);
1327 bartitle(&cp, "Options controlling the terminal emulation",
1328 IDC_TITLE_TERMINAL);
1329 beginbox(&cp, "Set the size of the terminal window",
1330 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
1332 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1333 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
1335 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
1337 beginbox(&cp, "Set the font used in the terminal window",
1338 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
1339 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1341 beginbox(&cp, "Set various terminal options",
1342 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3);
1343 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1344 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1345 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1346 checkbox(&cp, "&Beep enabled", IDC_BEEP);
1347 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
1348 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1349 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1352 treeview_insert(&tvfaff, 0, "Terminal");
1355 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1358 ctlposinit(&cp, hwnd, 80, 3, 13);
1359 bartitle(&cp, "Options controlling the effects of keys",
1360 IDC_TITLE_KEYBOARD);
1361 beginbox(&cp, "Change the sequences sent by:",
1362 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
1363 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
1364 "Control-&H", IDC_DEL008,
1365 "Control-&? (127)", IDC_DEL127, NULL);
1366 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
1367 "&Standard", IDC_HOMETILDE,
1368 "&rxvt", IDC_HOMERXVT, NULL);
1369 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
1370 "&VT400", IDC_FUNCTILDE,
1371 "&Linux", IDC_FUNCLINUX,
1372 "&Xterm R6", IDC_FUNCXTERM,
1373 "&VT400", IDC_FUNCVT400, NULL);
1375 beginbox(&cp, "Change the initial state of:",
1376 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
1377 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1378 "&Normal", IDC_CURNORMAL,
1379 "A&pplication", IDC_CURAPPLIC, NULL);
1380 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1381 "Nor&mal", IDC_KPNORMAL,
1382 "Appl&ication", IDC_KPAPPLIC,
1383 "N&etHack", IDC_KPNH, NULL);
1386 treeview_insert(&tvfaff, 1, "Keyboard");
1389 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1392 ctlposinit(&cp, hwnd, 80, 3, 13);
1393 bartitle(&cp, "Options controlling PuTTY's window",
1395 beginbox(&cp, "Adjust the use of the window title",
1396 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
1399 "Initial window &title:", IDC_WINTITLE,
1400 IDC_WINEDIT, 100, NULL);
1401 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1403 beginbox(&cp, "Adjust the use of the cursor",
1404 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
1405 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1407 beginbox(&cp, "Control the scrollback in the window",
1408 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3);
1409 staticedit(&cp, "Lines of &scrollback",
1410 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1411 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1412 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1414 beginbox(&cp, NULL, IDC_BOX_WINDOW4, 0);
1415 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1416 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1417 checkbox(&cp, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE);
1420 treeview_insert(&tvfaff, 0, "Window");
1423 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1426 ctlposinit(&cp, hwnd, 80, 3, 13);
1427 bartitle(&cp, "Options controlling character set translation",
1428 IDC_TITLE_TRANSLATION);
1429 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1430 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
1432 "Handling of line drawing characters:", IDC_VTSTATIC,
1433 "Font has &XWindows encoding", IDC_VTXWINDOWS,
1434 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1435 "Use font in O&EM mode only", IDC_VTOEMONLY,
1436 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1437 IDC_VTPOORMAN, NULL);
1439 beginbox(&cp, "Enable character set translation on received data",
1440 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
1442 "Character set translation:", IDC_XLATSTATIC,
1443 "&None", IDC_NOXLAT,
1444 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
1445 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
1446 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
1448 beginbox(&cp, "Enable character set translation on input data",
1449 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
1450 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
1454 treeview_insert(&tvfaff, 1, "Translation");
1457 /* The Selection panel. Accelerators used: [acgo] wxst */
1460 ctlposinit(&cp, hwnd, 80, 3, 13);
1461 bartitle(&cp, "Options controlling copy and paste",
1462 IDC_TITLE_SELECTION);
1463 beginbox(&cp, "Control which mouse button does which thing",
1464 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
1465 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1466 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1467 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1470 beginbox(&cp, "Control the select-one-word-at-a-time mode",
1471 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
1472 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1473 "&Set", IDC_CCSET, IDC_CCEDIT,
1474 "&to class", IDC_CCSTATIC2);
1477 treeview_insert(&tvfaff, 1, "Selection");
1480 /* The Colours panel. Accelerators used: [acgo] blum */
1483 ctlposinit(&cp, hwnd, 80, 3, 13);
1484 bartitle(&cp, "Options controlling use of colours",
1486 beginbox(&cp, "General options for colour usage",
1487 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
1488 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
1489 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1491 beginbox(&cp, "Adjust the precise colours PuTTY displays",
1492 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
1493 colouredit(&cp, "Select a colo&ur and then click to modify it:",
1494 IDC_STATIC, IDC_LIST,
1495 "&Modify...", IDC_CHANGE,
1496 "Red:", IDC_RSTATIC, IDC_RVALUE,
1497 "Green:", IDC_GSTATIC, IDC_GVALUE,
1498 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1501 treeview_insert(&tvfaff, 1, "Colours");
1504 /* The Connection panel. Accelerators used: [acgo] tuk */
1507 ctlposinit(&cp, hwnd, 80, 3, 13);
1508 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
1510 beginbox(&cp, "Data to send to the server",
1511 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
1512 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
1513 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
1516 beginbox(&cp, "Sending of null packets to keep session active",
1517 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
1518 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
1519 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
1522 treeview_insert(&tvfaff, 0, "Connection");
1525 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1528 ctlposinit(&cp, hwnd, 80, 3, 13);
1530 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
1531 beginbox(&cp, "Data to send to the server",
1532 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
1533 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
1534 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1535 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1536 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1538 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1540 beginbox(&cp, "Telnet protocol adjustments",
1541 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
1542 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1543 "&BSD (commonplace)", IDC_EMBSD,
1544 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1547 treeview_insert(&tvfaff, 1, "Telnet");
1551 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1554 ctlposinit(&cp, hwnd, 80, 3, 13);
1556 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1557 beginbox(&cp, "Data to send to the server",
1558 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1560 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1563 beginbox(&cp, "Authentication options",
1564 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1565 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1567 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1568 editbutton(&cp, "Private &key file for authentication:",
1569 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1571 beginbox(&cp, "Protocol options",
1572 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1573 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1574 radioline(&cp, "Preferred SSH protocol version:",
1575 IDC_SSHPROTSTATIC, 2,
1576 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1577 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1578 "&3DES", IDC_CIPHER3DES,
1579 "&Blowfish", IDC_CIPHERBLOWF,
1580 "&DES", IDC_CIPHERDES, NULL);
1583 treeview_insert(&tvfaff, 1, "SSH");
1587 init_dlg_ctrls(hwnd);
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);
1750 load_settings (sessions[n],
1751 !!strcmp(sessions[n], "Default Settings"),
1753 init_dlg_ctrls(hwnd);
1755 if (LOWORD(wParam) == IDC_SESSLIST) {
1757 * A double-click on a saved session should
1758 * actually start the session, not just load it.
1759 * Unless it's Default Settings or some other
1760 * host-less set of saved settings.
1769 if (HIWORD(wParam) == BN_CLICKED ||
1770 HIWORD(wParam) == BN_DOUBLECLICKED) {
1771 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1772 LB_GETCURSEL, 0, 0);
1773 if (n == LB_ERR || n == 0) {
1777 del_settings(sessions[n]);
1778 get_sesslist (FALSE);
1779 get_sesslist (TRUE);
1780 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1782 for (i = 0; i < nsessions; i++)
1783 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1784 0, (LPARAM) (sessions[i]));
1785 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1789 if (HIWORD(wParam) == EN_CHANGE)
1790 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1794 if (HIWORD(wParam) == BN_CLICKED ||
1795 HIWORD(wParam) == BN_DOUBLECLICKED)
1796 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1800 if (HIWORD(wParam) == BN_CLICKED ||
1801 HIWORD(wParam) == BN_DOUBLECLICKED)
1802 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1805 if (HIWORD(wParam) == BN_CLICKED ||
1806 HIWORD(wParam) == BN_DOUBLECLICKED)
1810 if (HIWORD(wParam) == BN_CLICKED ||
1811 HIWORD(wParam) == BN_DOUBLECLICKED)
1816 if (HIWORD(wParam) == BN_CLICKED ||
1817 HIWORD(wParam) == BN_DOUBLECLICKED)
1818 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1822 if (HIWORD(wParam) == BN_CLICKED ||
1823 HIWORD(wParam) == BN_DOUBLECLICKED) {
1824 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1825 cfg.nethack_keypad = FALSE;
1829 if (HIWORD(wParam) == BN_CLICKED ||
1830 HIWORD(wParam) == BN_DOUBLECLICKED) {
1831 cfg.app_keypad = FALSE;
1832 cfg.nethack_keypad = TRUE;
1837 if (HIWORD(wParam) == BN_CLICKED ||
1838 HIWORD(wParam) == BN_DOUBLECLICKED)
1839 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1842 if (HIWORD(wParam) == BN_CLICKED ||
1843 HIWORD(wParam) == BN_DOUBLECLICKED)
1844 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1847 if (HIWORD(wParam) == BN_CLICKED ||
1848 HIWORD(wParam) == BN_DOUBLECLICKED)
1849 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1852 if (HIWORD(wParam) == BN_CLICKED ||
1853 HIWORD(wParam) == BN_DOUBLECLICKED)
1854 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1857 if (HIWORD(wParam) == BN_CLICKED ||
1858 HIWORD(wParam) == BN_DOUBLECLICKED)
1859 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1862 if (HIWORD(wParam) == BN_CLICKED ||
1863 HIWORD(wParam) == BN_DOUBLECLICKED)
1864 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1867 if (HIWORD(wParam) == BN_CLICKED ||
1868 HIWORD(wParam) == BN_DOUBLECLICKED)
1869 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1872 if (HIWORD(wParam) == BN_CLICKED ||
1873 HIWORD(wParam) == BN_DOUBLECLICKED)
1874 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1877 if (HIWORD(wParam) == EN_CHANGE)
1878 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1881 if (HIWORD(wParam) == EN_CHANGE)
1882 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1885 if (HIWORD(wParam) == EN_CHANGE)
1886 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1888 case IDC_CHOOSEFONT:
1889 lf.lfHeight = cfg.fontheight;
1890 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1891 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1892 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1893 lf.lfCharSet = cfg.fontcharset;
1894 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1895 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1896 lf.lfQuality = DEFAULT_QUALITY;
1897 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1898 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1899 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1901 cf.lStructSize = sizeof(cf);
1902 cf.hwndOwner = hwnd;
1904 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1905 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1907 if (ChooseFont (&cf)) {
1908 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1909 cfg.font[sizeof(cfg.font)-1] = '\0';
1910 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1911 cfg.fontcharset = lf.lfCharSet;
1912 cfg.fontheight = lf.lfHeight;
1913 fmtfont (fontstatic);
1914 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1918 if (HIWORD(wParam) == BN_CLICKED ||
1919 HIWORD(wParam) == BN_DOUBLECLICKED)
1920 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1923 if (HIWORD(wParam) == BN_CLICKED ||
1924 HIWORD(wParam) == BN_DOUBLECLICKED)
1925 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1928 if (HIWORD(wParam) == BN_CLICKED ||
1929 HIWORD(wParam) == BN_DOUBLECLICKED)
1930 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1933 if (HIWORD(wParam) == BN_CLICKED ||
1934 HIWORD(wParam) == BN_DOUBLECLICKED)
1935 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1938 if (HIWORD(wParam) == BN_CLICKED ||
1939 HIWORD(wParam) == BN_DOUBLECLICKED)
1940 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1943 if (HIWORD(wParam) == BN_CLICKED ||
1944 HIWORD(wParam) == BN_DOUBLECLICKED)
1945 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1948 if (HIWORD(wParam) == BN_CLICKED ||
1949 HIWORD(wParam) == BN_DOUBLECLICKED)
1950 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1953 if (HIWORD(wParam) == EN_CHANGE)
1954 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1955 sizeof(cfg.wintitle)-1);
1958 if (HIWORD(wParam) == BN_CLICKED ||
1959 HIWORD(wParam) == BN_DOUBLECLICKED)
1960 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1963 if (HIWORD(wParam) == BN_CLICKED ||
1964 HIWORD(wParam) == BN_DOUBLECLICKED)
1965 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1968 if (HIWORD(wParam) == EN_CHANGE)
1969 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1970 sizeof(cfg.termtype)-1);
1973 if (HIWORD(wParam) == EN_CHANGE)
1974 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1975 sizeof(cfg.termspeed)-1);
1978 if (HIWORD(wParam) == EN_CHANGE)
1979 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1980 sizeof(cfg.username)-1);
1984 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
1987 if (HIWORD(wParam) == BN_CLICKED ||
1988 HIWORD(wParam) == BN_DOUBLECLICKED) {
1989 char str[sizeof(cfg.environmt)];
1991 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
1996 p = str + strlen(str);
1998 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
2008 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
2010 p[strlen(str)+1] = '\0';
2011 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
2013 SetDlgItemText (hwnd, IDC_VAREDIT, "");
2014 SetDlgItemText (hwnd, IDC_VALEDIT, "");
2016 MessageBox(hwnd, "Environment too big", "PuTTY Error",
2017 MB_OK | MB_ICONERROR);
2022 if (HIWORD(wParam) != BN_CLICKED &&
2023 HIWORD(wParam) != BN_DOUBLECLICKED)
2025 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
2031 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
2056 if (HIWORD(wParam) == BN_CLICKED ||
2057 HIWORD(wParam) == BN_DOUBLECLICKED)
2058 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
2061 if (HIWORD(wParam) == BN_CLICKED ||
2062 HIWORD(wParam) == BN_DOUBLECLICKED)
2063 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
2065 case IDC_CIPHER3DES:
2066 case IDC_CIPHERBLOWF:
2068 if (HIWORD(wParam) == BN_CLICKED ||
2069 HIWORD(wParam) == BN_DOUBLECLICKED) {
2070 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
2071 cfg.cipher = CIPHER_3DES;
2072 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
2073 cfg.cipher = CIPHER_BLOWFISH;
2074 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
2075 cfg.cipher = CIPHER_DES;
2080 if (HIWORD(wParam) == BN_CLICKED ||
2081 HIWORD(wParam) == BN_DOUBLECLICKED) {
2082 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
2084 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
2089 if (HIWORD(wParam) == BN_CLICKED ||
2090 HIWORD(wParam) == BN_DOUBLECLICKED)
2091 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
2094 if (HIWORD(wParam) == EN_CHANGE)
2095 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
2096 sizeof(cfg.keyfile)-1);
2099 if (HIWORD(wParam) == EN_CHANGE)
2100 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2101 sizeof(cfg.remote_cmd)-1);
2104 memset(&of, 0, sizeof(of));
2105 #ifdef OPENFILENAME_SIZE_VERSION_400
2106 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2108 of.lStructSize = sizeof(of);
2110 of.hwndOwner = hwnd;
2111 of.lpstrFilter = "All Files\0*\0\0\0";
2112 of.lpstrCustomFilter = NULL;
2113 of.nFilterIndex = 1;
2114 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
2115 of.nMaxFile = sizeof(filename);
2116 of.lpstrFileTitle = NULL;
2117 of.lpstrInitialDir = NULL;
2118 of.lpstrTitle = "Select Public Key File";
2120 if (GetOpenFileName(&of)) {
2121 strcpy(cfg.keyfile, filename);
2122 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
2127 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
2133 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
2138 for (i=0; i<256; i++)
2139 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
2142 cfg.wordness[i] = n;
2143 SendDlgItemMessage (hwnd, IDC_CCLIST,
2144 LB_DELETESTRING, i, 0);
2145 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2146 (i>=0x21 && i != 0x7F) ? i : ' ',
2148 SendDlgItemMessage (hwnd, IDC_CCLIST,
2155 case IDC_BOLDCOLOUR:
2156 if (HIWORD(wParam) == BN_CLICKED ||
2157 HIWORD(wParam) == BN_DOUBLECLICKED) {
2159 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2160 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
2161 if (cfg.bold_colour && n!=22) {
2162 for (i=0; i<22; i++)
2164 SendDlgItemMessage (hwnd, IDC_LIST,
2166 (LPARAM) colours[i]);
2167 } else if (!cfg.bold_colour && n!=12) {
2170 SendDlgItemMessage (hwnd, IDC_LIST,
2171 LB_DELETESTRING, i, 0);
2176 if (HIWORD(wParam) == BN_CLICKED ||
2177 HIWORD(wParam) == BN_DOUBLECLICKED)
2178 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
2181 if (HIWORD(wParam) == LBN_DBLCLK ||
2182 HIWORD(wParam) == LBN_SELCHANGE) {
2183 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2185 if (!cfg.bold_colour)
2186 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2187 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2188 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2189 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
2193 if (HIWORD(wParam) == BN_CLICKED ||
2194 HIWORD(wParam) == BN_DOUBLECLICKED) {
2195 static CHOOSECOLOR cc;
2196 static DWORD custom[16] = {0}; /* zero initialisers */
2197 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2199 if (!cfg.bold_colour)
2200 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2201 cc.lStructSize = sizeof(cc);
2202 cc.hwndOwner = hwnd;
2203 cc.hInstance = (HWND)hinst;
2204 cc.lpCustColors = custom;
2205 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2207 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2208 if (ChooseColor(&cc)) {
2210 (unsigned char) (cc.rgbResult & 0xFF);
2212 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2214 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2215 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
2217 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
2219 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
2225 case IDC_KOI8WIN1251:
2226 case IDC_88592WIN1250:
2227 case IDC_88592CP852:
2228 cfg.xlat_enablekoiwin =
2229 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
2230 cfg.xlat_88592w1250 =
2231 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
2232 cfg.xlat_88592cp852 =
2233 IsDlgButtonChecked (hwnd, IDC_88592CP852);
2235 case IDC_CAPSLOCKCYR:
2236 if (HIWORD(wParam) == BN_CLICKED ||
2237 HIWORD(wParam) == BN_DOUBLECLICKED) {
2238 cfg.xlat_capslockcyr =
2239 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
2242 case IDC_VTXWINDOWS:
2247 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2248 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2249 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
2255 EndDialog (hwnd, 0);
2258 /* Grrr Explorer will maximize Dialogs! */
2260 if (wParam == SIZE_MAXIMIZED)
2267 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2268 WPARAM wParam, LPARAM lParam) {
2269 static HWND page = NULL;
2271 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2273 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2274 EnableWindow(hwnd, 0);
2275 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2276 GetParent(hwnd), AboutProc);
2277 EnableWindow(hwnd, 1);
2278 SetActiveWindow(hwnd);
2280 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
2283 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2284 WPARAM wParam, LPARAM lParam) {
2286 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
2289 int do_config (void) {
2293 savedsession[0] = '\0';
2294 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2295 get_sesslist(FALSE);
2300 int do_reconfig (HWND hwnd) {
2304 backup_cfg = cfg; /* structure copy */
2305 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2307 cfg = backup_cfg; /* structure copy */
2314 void logevent (char *string) {
2315 if (nevents >= negsize) {
2317 events = srealloc (events, negsize * sizeof(*events));
2319 events[nevents] = smalloc(1+strlen(string));
2320 strcpy (events[nevents], string);
2324 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2326 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2327 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
2331 void showeventlog (HWND hwnd) {
2333 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2335 ShowWindow (logbox, SW_SHOWNORMAL);
2339 void showabout (HWND hwnd) {
2341 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2343 ShowWindow (abtbox, SW_SHOWNORMAL);
2347 void verify_ssh_host_key(char *host, int port, char *keytype,
2348 char *keystr, char *fingerprint) {
2351 static const char absentmsg[] =
2352 "The server's host key is not cached in the registry. You\n"
2353 "have no guarantee that the server is the computer you\n"
2355 "The server's key fingerprint is:\n"
2357 "If you trust this host, hit Yes to add the key to\n"
2358 "PuTTY's cache and carry on connecting.\n"
2359 "If you do not trust this host, hit No to abandon the\n"
2362 static const char wrongmsg[] =
2363 "WARNING - POTENTIAL SECURITY BREACH!\n"
2365 "The server's host key does not match the one PuTTY has\n"
2366 "cached in the registry. This means that either the\n"
2367 "server administrator has changed the host key, or you\n"
2368 "have actually connected to another computer pretending\n"
2369 "to be the server.\n"
2370 "The new key fingerprint is:\n"
2372 "If you were expecting this change and trust the new key,\n"
2373 "hit Yes to update PuTTY's cache and continue connecting.\n"
2374 "If you want to carry on connecting but without updating\n"
2375 "the cache, hit No.\n"
2376 "If you want to abandon the connection completely, hit\n"
2377 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2380 static const char mbtitle[] = "PuTTY Security Alert";
2383 char message[160+ /* sensible fingerprint max size */
2384 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2385 sizeof(absentmsg) : sizeof(wrongmsg))];
2388 * Verify the key against the registry.
2390 ret = verify_host_key(host, port, keytype, keystr);
2392 if (ret == 0) /* success - key matched OK */
2394 if (ret == 2) { /* key was different */
2396 sprintf(message, wrongmsg, fingerprint);
2397 mbret = MessageBox(NULL, message, mbtitle,
2398 MB_ICONWARNING | MB_YESNOCANCEL);
2400 store_host_key(host, port, keytype, keystr);
2401 if (mbret == IDCANCEL)
2404 if (ret == 1) { /* key was absent */
2406 sprintf(message, absentmsg, fingerprint);
2407 mbret = MessageBox(NULL, message, mbtitle,
2408 MB_ICONWARNING | MB_YESNO);
2411 store_host_key(host, port, keytype, keystr);