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);
177 * Null dialog procedure.
179 static int CALLBACK NullDlgProc (HWND hwnd, UINT msg,
180 WPARAM wParam, LPARAM lParam) {
184 /* ----------------------------------------------------------------------
185 * Routines to self-manage the controls in a dialog box.
193 #define STATICHEIGHT 8
194 #define CHECKBOXHEIGHT 8
195 #define RADIOHEIGHT 8
196 #define EDITHEIGHT 12
197 #define COMBOHEIGHT 12
198 #define PUSHBTNHEIGHT 14
206 int boxystart, boxid, boxtextid;
210 static void ctlposinit(struct ctlpos *cp, HWND hwnd,
211 int leftborder, int rightborder, int topborder) {
214 cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);
215 cp->ypos = topborder;
216 GetClientRect(hwnd, &r);
217 r2.left = r2.top = 0;
220 MapDialogRect(hwnd, &r2);
221 cp->dlu4inpix = r2.right;
222 cp->width = (r.right * 4) / (r2.right) - 2*GAPBETWEEN;
223 cp->xoff = leftborder;
224 cp->width -= leftborder + rightborder;
227 static void doctl(struct ctlpos *cp, RECT r,
228 char *wclass, int wstyle, int exstyle,
229 char *wtext, int wid) {
232 * Note nonstandard use of RECT. This is deliberate: by
233 * transforming the width and height directly we arrange to
234 * have all supposedly same-sized controls really same-sized.
238 MapDialogRect(cp->hwnd, &r);
240 ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,
241 r.left, r.top, r.right, r.bottom,
242 cp->hwnd, (HMENU)wid, hinst, NULL);
243 SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));
247 * A title bar across the top of a sub-dialog.
249 static void bartitle(struct ctlpos *cp, char *name, int id) {
252 r.left = GAPBETWEEN; r.right = cp->width;
253 r.top = cp->ypos; r.bottom = STATICHEIGHT;
254 cp->ypos += r.bottom + GAPBETWEEN;
255 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, name, id);
259 * Begin a grouping box, with or without a group title.
261 static void beginbox(struct ctlpos *cp, char *name, int idbox, int idtext) {
263 cp->ypos += STATICHEIGHT/2;
264 cp->boxystart = cp->ypos;
266 cp->ypos += STATICHEIGHT - (STATICHEIGHT/2);
268 cp->width -= 2*GAPXBOX;
271 cp->boxtextid = idtext;
276 * End a grouping box.
278 static void endbox(struct ctlpos *cp) {
281 cp->width += 2*GAPXBOX;
282 cp->ypos += GAPYBOX - GAPBETWEEN;
283 r.left = GAPBETWEEN; r.right = cp->width;
284 r.top = cp->boxystart; r.bottom = cp->ypos - cp->boxystart;
285 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,
290 HFONT oldfont, dlgfont;
291 hdc = GetDC(cp->hwnd);
292 dlgfont = (HFONT)cp->font;
293 oldfont = SelectObject(hdc, dlgfont);
294 GetTextExtentPoint32(hdc, cp->boxtext, strlen(cp->boxtext), &s);
295 SelectObject(hdc, oldfont);
297 r.left = GAPXBOX + GAPBETWEEN;
298 r.right = (s.cx * 4 + cp->dlu4inpix-1) / cp->dlu4inpix;
300 r.top = cp->boxystart - STATICHEIGHT/2; r.bottom = STATICHEIGHT;
301 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
302 cp->boxtext, cp->boxtextid);
308 * Some edit boxes. Each one has a static above it. The percentages
309 * of the horizontal space are provided.
311 static void multiedit(struct ctlpos *cp, ...) {
320 int staticid, editid, pcwidth;
321 text = va_arg(ap, char *);
324 staticid = va_arg(ap, int);
325 editid = va_arg(ap, int);
326 pcwidth = va_arg(ap, int);
328 r.left = xpos + GAPBETWEEN;
330 xpos = (cp->width + GAPBETWEEN) * percent / 100;
331 r.right = xpos - r.left;
333 r.top = cp->ypos; r.bottom = STATICHEIGHT;
334 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
336 r.top = cp->ypos + 8 + GAPWITHIN; r.bottom = EDITHEIGHT;
338 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
343 cp->ypos += 8+GAPWITHIN+12+GAPBETWEEN;
347 * A set of radio buttons on the same line, with a static above
348 * them. `nacross' dictates how many parts the line is divided into
349 * (you might want this not to equal the number of buttons if you
350 * needed to line up some 2s and some 3s to look good in the same
353 static void radioline(struct ctlpos *cp,
354 char *text, int id, int nacross, ...) {
360 r.left = GAPBETWEEN; r.top = cp->ypos;
361 r.right = cp->width; r.bottom = STATICHEIGHT;
362 cp->ypos += r.bottom + GAPWITHIN;
363 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
364 va_start(ap, nacross);
370 btext = va_arg(ap, char *);
373 bid = va_arg(ap, int);
374 r.left = GAPBETWEEN + i * (cp->width+GAPBETWEEN)/nacross;
375 r.right = (i+1) * (cp->width+GAPBETWEEN)/nacross - r.left;
376 r.top = cp->ypos; r.bottom = RADIOHEIGHT;
377 doctl(cp, r, "BUTTON",
378 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
385 cp->ypos += r.bottom + GAPBETWEEN;
389 * A set of radio buttons on multiple lines, with a static above
392 static void radiobig(struct ctlpos *cp, char *text, int id, ...) {
397 r.left = GAPBETWEEN; r.top = cp->ypos;
398 r.right = cp->width; r.bottom = STATICHEIGHT;
399 cp->ypos += r.bottom + GAPWITHIN;
400 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
406 btext = va_arg(ap, char *);
409 bid = va_arg(ap, int);
410 r.left = GAPBETWEEN; r.top = cp->ypos;
411 r.right = cp->width; r.bottom = STATICHEIGHT;
412 cp->ypos += r.bottom + GAPWITHIN;
413 doctl(cp, r, "BUTTON",
414 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group,
420 cp->ypos += GAPBETWEEN - GAPWITHIN;
424 * A single standalone checkbox.
426 static void checkbox(struct ctlpos *cp, char *text, int id) {
429 r.left = GAPBETWEEN; r.top = cp->ypos;
430 r.right = cp->width; r.bottom = CHECKBOXHEIGHT;
431 cp->ypos += r.bottom + GAPBETWEEN;
432 doctl(cp, r, "BUTTON",
433 BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,
438 * A button on the right hand side, with a static to its left.
440 static void staticbtn(struct ctlpos *cp, char *stext, int sid,
441 char *btext, int bid) {
442 const int height = (PUSHBTNHEIGHT > STATICHEIGHT ?
443 PUSHBTNHEIGHT : STATICHEIGHT);
445 int lwid, rwid, rpos;
447 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
448 lwid = rpos - 2*GAPBETWEEN;
449 rwid = cp->width + GAPBETWEEN - rpos;
451 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
452 r.right = lwid; r.bottom = STATICHEIGHT;
453 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
455 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
456 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
457 doctl(cp, r, "BUTTON",
458 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
462 cp->ypos += height + GAPBETWEEN;
466 * An edit control on the right hand side, with a static to its left.
468 static void staticedit(struct ctlpos *cp, char *stext,
469 int sid, int eid, int percentedit) {
470 const int height = (EDITHEIGHT > STATICHEIGHT ?
471 EDITHEIGHT : STATICHEIGHT);
473 int lwid, rwid, rpos;
475 rpos = GAPBETWEEN + (100-percentedit) * (cp->width + GAPBETWEEN) / 100;
476 lwid = rpos - 2*GAPBETWEEN;
477 rwid = cp->width + GAPBETWEEN - rpos;
479 r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2;
480 r.right = lwid; r.bottom = STATICHEIGHT;
481 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
483 r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2;
484 r.right = rwid; r.bottom = EDITHEIGHT;
486 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
490 cp->ypos += height + GAPBETWEEN;
494 * A tab-control substitute when a real tab control is unavailable.
496 static void ersatztab(struct ctlpos *cp, char *stext, int sid,
498 const int height = (COMBOHEIGHT > STATICHEIGHT ?
499 COMBOHEIGHT : STATICHEIGHT);
501 int bigwid, lwid, rwid, rpos;
502 static const int BIGGAP = 15;
503 static const int MEDGAP = 3;
505 bigwid = cp->width + 2*GAPBETWEEN - 2*BIGGAP;
507 rpos = BIGGAP + (bigwid + BIGGAP) / 2;
508 lwid = rpos - 2*BIGGAP;
509 rwid = bigwid + BIGGAP - rpos;
511 r.left = BIGGAP; r.top = cp->ypos + (height-STATICHEIGHT)/2;
512 r.right = lwid; r.bottom = STATICHEIGHT;
513 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
515 r.left = rpos; r.top = cp->ypos + (height-COMBOHEIGHT)/2;
516 r.right = rwid; r.bottom = COMBOHEIGHT*10;
517 doctl(cp, r, "COMBOBOX",
518 WS_CHILD | WS_VISIBLE | WS_TABSTOP |
519 CBS_DROPDOWNLIST | CBS_HASSTRINGS,
523 cp->ypos += height + MEDGAP + GAPBETWEEN;
525 r.left = GAPBETWEEN; r.top = cp->ypos;
526 r.right = cp->width; r.bottom = 2;
527 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
532 * A static line, followed by an edit control on the left hand side
533 * and a button on the right.
535 static void editbutton(struct ctlpos *cp, char *stext, int sid,
536 int eid, char *btext, int bid) {
537 const int height = (EDITHEIGHT > PUSHBTNHEIGHT ?
538 EDITHEIGHT : PUSHBTNHEIGHT);
540 int lwid, rwid, rpos;
542 r.left = GAPBETWEEN; r.top = cp->ypos;
543 r.right = cp->width; r.bottom = STATICHEIGHT;
544 cp->ypos += r.bottom + GAPWITHIN;
545 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
547 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
548 lwid = rpos - 2*GAPBETWEEN;
549 rwid = cp->width + GAPBETWEEN - rpos;
551 r.left = GAPBETWEEN; r.top = cp->ypos + (height-EDITHEIGHT)/2;
552 r.right = lwid; r.bottom = EDITHEIGHT;
554 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
558 r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2;
559 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
560 doctl(cp, r, "BUTTON",
561 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
565 cp->ypos += height + GAPBETWEEN;
569 * Special control which was hard to describe generically: the
570 * session-saver assembly. A static; below that an edit box; below
571 * that a list box. To the right of the list box, a column of
574 static void sesssaver(struct ctlpos *cp, char *text,
575 int staticid, int editid, int listid, ...) {
578 int lwid, rwid, rpos;
580 const int LISTDEFHEIGHT = 66;
582 rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
583 lwid = rpos - 2*GAPBETWEEN;
584 rwid = cp->width + GAPBETWEEN - rpos;
586 /* The static control. */
587 r.left = GAPBETWEEN; r.top = cp->ypos;
588 r.right = lwid; r.bottom = STATICHEIGHT;
589 cp->ypos += r.bottom + GAPWITHIN;
590 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
592 /* The edit control. */
593 r.left = GAPBETWEEN; r.top = cp->ypos;
594 r.right = lwid; r.bottom = EDITHEIGHT;
595 cp->ypos += r.bottom + GAPWITHIN;
597 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
602 * The buttons (we should hold off on the list box until we
603 * know how big the buttons are).
605 va_start(ap, listid);
608 char *btext = va_arg(ap, char *);
611 bid = va_arg(ap, int);
612 r.left = rpos; r.top = y;
613 r.right = rwid; r.bottom = PUSHBTNHEIGHT;
614 y += r.bottom + GAPWITHIN;
615 doctl(cp, r, "BUTTON",
616 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
621 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
624 if (y < LISTDEFHEIGHT) y = LISTDEFHEIGHT;
625 r.left = GAPBETWEEN; r.top = cp->ypos;
626 r.right = lwid; r.bottom = y;
627 cp->ypos += y + GAPBETWEEN;
628 doctl(cp, r, "LISTBOX",
629 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
630 LBS_NOTIFY | LBS_HASSTRINGS,
636 * Another special control: the environment-variable setter. A
637 * static line first; then a pair of edit boxes with associated
638 * statics, and two buttons; then a list box.
640 static void envsetter(struct ctlpos *cp, char *stext, int sid,
641 char *e1stext, int e1sid, int e1id,
642 char *e2stext, int e2sid, int e2id,
644 char *b1text, int b1id, char *b2text, int b2id) {
646 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
648 EDITHEIGHT > PUSHBTNHEIGHT ?
649 EDITHEIGHT : PUSHBTNHEIGHT);
650 const static int percents[] = { 20, 35, 10, 25 };
651 int i, j, xpos, percent;
652 const int LISTHEIGHT = 42;
654 /* The static control. */
655 r.left = GAPBETWEEN; r.top = cp->ypos;
656 r.right = cp->width; r.bottom = STATICHEIGHT;
657 cp->ypos += r.bottom + GAPWITHIN;
658 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
660 /* The statics+edits+buttons. */
661 for (j = 0; j < 2; j++) {
663 for (i = 0; i < 4; i++) {
664 xpos = (cp->width + GAPBETWEEN) * percent / 100;
665 r.left = xpos + GAPBETWEEN;
666 percent += percents[i];
667 xpos = (cp->width + GAPBETWEEN) * percent / 100;
668 r.right = xpos - r.left;
670 r.bottom = (i==0 ? STATICHEIGHT :
673 r.top += (height-r.bottom)/2;
675 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
676 j==0 ? e1stext : e2stext, j==0 ? e1sid : e2sid);
679 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
681 "", j==0 ? e1id : e2id);
683 doctl(cp, r, "BUTTON",
684 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
686 j==0 ? b1text : b2text, j==0 ? b1id : b2id);
689 cp->ypos += height + GAPWITHIN;
693 r.left = GAPBETWEEN; r.top = cp->ypos;
694 r.right = cp->width; r.bottom = LISTHEIGHT;
695 cp->ypos += r.bottom + GAPBETWEEN;
696 doctl(cp, r, "LISTBOX",
697 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
704 * Yet another special control: the character-class setter. A
705 * static, then a list, then a line containing a
706 * button-and-static-and-edit.
708 static void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
709 char *btext, int bid, int eid, char *s2text, int s2id) {
711 const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ?
713 EDITHEIGHT > PUSHBTNHEIGHT ?
714 EDITHEIGHT : PUSHBTNHEIGHT);
715 const static int percents[] = { 30, 40, 30 };
716 int i, xpos, percent;
717 const int LISTHEIGHT = 66;
719 /* The static control. */
720 r.left = GAPBETWEEN; r.top = cp->ypos;
721 r.right = cp->width; r.bottom = STATICHEIGHT;
722 cp->ypos += r.bottom + GAPWITHIN;
723 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
726 r.left = GAPBETWEEN; r.top = cp->ypos;
727 r.right = cp->width; r.bottom = LISTHEIGHT;
728 cp->ypos += r.bottom + GAPWITHIN;
729 doctl(cp, r, "LISTBOX",
730 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
735 /* The button+static+edit. */
737 for (i = 0; i < 3; i++) {
738 r.left = xpos + GAPBETWEEN;
739 percent += percents[i];
740 xpos = (cp->width + GAPBETWEEN) * percent / 100;
741 r.right = xpos - r.left;
743 r.bottom = (i==0 ? PUSHBTNHEIGHT :
744 i==1 ? STATICHEIGHT :
746 r.top += (height-r.bottom)/2;
748 doctl(cp, r, "BUTTON",
749 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
752 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER,
756 WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
757 WS_EX_CLIENTEDGE, "", eid);
760 cp->ypos += height + GAPBETWEEN;
764 * A special control (horrors!). The colour editor. A static line;
765 * then on the left, a list box, and on the right, a sequence of
766 * two-part statics followed by a button.
768 static void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
769 char *btext, int bid, ...) {
773 int lwid, rwid, rpos;
774 const int LISTHEIGHT = 66;
776 /* The static control. */
777 r.left = GAPBETWEEN; r.top = cp->ypos;
778 r.right = cp->width; r.bottom = STATICHEIGHT;
779 cp->ypos += r.bottom + GAPWITHIN;
780 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
782 rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3;
783 lwid = rpos - 2*GAPBETWEEN;
784 rwid = cp->width + GAPBETWEEN - rpos;
787 r.left = GAPBETWEEN; r.top = cp->ypos;
788 r.right = lwid; r.bottom = LISTHEIGHT;
789 doctl(cp, r, "LISTBOX",
790 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
801 ltext = va_arg(ap, char *);
803 lid = va_arg(ap, int);
804 rid = va_arg(ap, int);
805 r.top = y; r.bottom = STATICHEIGHT;
806 y += r.bottom + GAPWITHIN;
807 r.left = rpos; r.right = rwid/2;
808 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid);
809 r.left = rpos + r.right; r.right = rwid - r.right;
810 doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "", rid);
815 r.top = y + 2*GAPWITHIN; r.bottom = PUSHBTNHEIGHT;
816 r.left = rpos; r.right = rwid;
817 doctl(cp, r, "BUTTON",
818 WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
821 cp->ypos += LISTHEIGHT + GAPBETWEEN;
824 static char savedsession[2048];
826 enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
830 IDC_BOX_SESSION1, IDC_BOXT_SESSION1,
831 IDC_BOX_SESSION2, IDC_BOXT_SESSION2,
852 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1,
853 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2,
876 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1,
877 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2,
878 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3,
898 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1,
899 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2,
900 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3,
915 connectionpanelstart,
916 IDC_TITLE_CONNECTION,
917 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1,
918 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2,
929 IDC_BOX_TELNET1, IDC_BOXT_TELNET1,
930 IDC_BOX_TELNET2, IDC_BOXT_TELNET2,
948 IDC_BOX_SSH1, IDC_BOXT_SSH1,
949 IDC_BOX_SSH2, IDC_BOXT_SSH2,
950 IDC_BOX_SSH3, IDC_BOXT_SSH3,
971 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1,
972 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2,
985 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1,
986 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2,
1000 translationpanelstart,
1001 IDC_TITLE_TRANSLATION,
1002 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1,
1003 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2,
1004 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3,
1016 translationpanelend,
1021 static const char *const colours[] = {
1022 "Default Foreground", "Default Bold Foreground",
1023 "Default Background", "Default Bold Background",
1024 "Cursor Text", "Cursor Colour",
1025 "ANSI Black", "ANSI Black Bold",
1026 "ANSI Red", "ANSI Red Bold",
1027 "ANSI Green", "ANSI Green Bold",
1028 "ANSI Yellow", "ANSI Yellow Bold",
1029 "ANSI Blue", "ANSI Blue Bold",
1030 "ANSI Magenta", "ANSI Magenta Bold",
1031 "ANSI Cyan", "ANSI Cyan Bold",
1032 "ANSI White", "ANSI White Bold"
1034 static const int permcolour[] = {
1035 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1036 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1037 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1040 static void fmtfont (char *buf) {
1041 sprintf (buf, "Font: %s, ", cfg.font);
1043 strcat(buf, "bold, ");
1044 if (cfg.fontheight == 0)
1045 strcat (buf, "default height");
1047 sprintf (buf+strlen(buf), "%d-%s",
1048 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
1049 (cfg.fontheight < 0 ? "pixel" : "point"));
1052 static void init_dlg_ctrls(HWND hwnd) {
1054 char fontstatic[256];
1056 SetDlgItemText (hwnd, IDC_HOST, cfg.host);
1057 SetDlgItemText (hwnd, IDC_SESSEDIT, savedsession);
1058 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1059 CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
1060 cfg.protocol==PROT_SSH ? IDC_PROTSSH :
1061 cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
1062 SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
1064 CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
1065 cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
1066 CheckRadioButton (hwnd, IDC_HOMETILDE, IDC_HOMERXVT,
1067 cfg.rxvt_homeend ? IDC_HOMERXVT : IDC_HOMETILDE);
1068 CheckRadioButton (hwnd, IDC_FUNCTILDE, IDC_FUNCVT400,
1069 cfg.funky_type == 0 ? IDC_FUNCTILDE :
1070 cfg.funky_type == 1 ? IDC_FUNCLINUX :
1071 cfg.funky_type == 2 ? IDC_FUNCXTERM :
1072 cfg.funky_type == 3 ? IDC_FUNCVT400 :
1074 CheckRadioButton (hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
1075 cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
1076 CheckRadioButton (hwnd, IDC_KPNORMAL, IDC_KPNH,
1077 cfg.nethack_keypad ? IDC_KPNH :
1078 cfg.app_keypad ? IDC_KPAPPLIC : IDC_KPNORMAL);
1079 CheckDlgButton (hwnd, IDC_ALTF4, cfg.alt_f4);
1080 CheckDlgButton (hwnd, IDC_ALTSPACE, cfg.alt_space);
1081 CheckDlgButton (hwnd, IDC_LDISCTERM, cfg.ldisc_term);
1082 CheckDlgButton (hwnd, IDC_SCROLLKEY, cfg.scroll_on_key);
1084 CheckDlgButton (hwnd, IDC_WRAPMODE, cfg.wrap_mode);
1085 CheckDlgButton (hwnd, IDC_DECOM, cfg.dec_om);
1086 CheckDlgButton (hwnd, IDC_LFHASCR, cfg.lfhascr);
1087 SetDlgItemInt (hwnd, IDC_ROWSEDIT, cfg.height, FALSE);
1088 SetDlgItemInt (hwnd, IDC_COLSEDIT, cfg.width, FALSE);
1089 SetDlgItemInt (hwnd, IDC_SAVEEDIT, cfg.savelines, FALSE);
1090 fmtfont (fontstatic);
1091 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1092 CheckDlgButton (hwnd, IDC_BEEP, cfg.beep);
1093 CheckDlgButton (hwnd, IDC_BCE, cfg.bce);
1094 CheckDlgButton (hwnd, IDC_BLINKTEXT, cfg.blinktext);
1096 SetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle);
1097 CheckDlgButton (hwnd, IDC_WINNAME, cfg.win_name_always);
1098 CheckDlgButton (hwnd, IDC_BLINKCUR, cfg.blink_cur);
1099 CheckDlgButton (hwnd, IDC_SCROLLBAR, cfg.scrollbar);
1100 CheckDlgButton (hwnd, IDC_LOCKSIZE, cfg.locksize);
1101 CheckDlgButton (hwnd, IDC_CLOSEEXIT, cfg.close_on_exit);
1102 CheckDlgButton (hwnd, IDC_CLOSEWARN, cfg.warn_on_close);
1104 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1105 SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
1106 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1108 char *p = cfg.environmt;
1110 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING, 0,
1115 CheckRadioButton (hwnd, IDC_EMBSD, IDC_EMRFC,
1116 cfg.rfc_environ ? IDC_EMRFC : IDC_EMBSD);
1118 SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
1119 SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
1120 CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
1121 CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
1122 CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
1123 CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
1124 cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
1125 cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
1127 CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
1128 cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
1129 CheckDlgButton (hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
1130 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
1131 SetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd);
1133 CheckRadioButton (hwnd, IDC_MBWINDOWS, IDC_MBXTERM,
1134 cfg.mouse_is_xterm ? IDC_MBXTERM : IDC_MBWINDOWS);
1136 static int tabs[4] = {25, 61, 96, 128};
1137 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
1140 for (i=0; i<256; i++) {
1142 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1143 (i>=0x21 && i != 0x7F) ? i : ' ',
1145 SendDlgItemMessage (hwnd, IDC_CCLIST, LB_ADDSTRING, 0,
1149 CheckDlgButton (hwnd, IDC_BOLDCOLOUR, cfg.bold_colour);
1150 CheckDlgButton (hwnd, IDC_PALETTE, cfg.try_palette);
1153 for (i=0; i<22; i++)
1154 if (cfg.bold_colour || permcolour[i])
1155 SendDlgItemMessage (hwnd, IDC_LIST, LB_ADDSTRING, 0,
1156 (LPARAM) colours[i]);
1158 SendDlgItemMessage (hwnd, IDC_LIST, LB_SETCURSEL, 0, 0);
1159 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[0][0], FALSE);
1160 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[0][1], FALSE);
1161 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[0][2], FALSE);
1163 CheckRadioButton (hwnd, IDC_NOXLAT, IDC_88592CP852,
1164 cfg.xlat_88592w1250 ? IDC_88592WIN1250 :
1165 cfg.xlat_88592cp852 ? IDC_88592CP852 :
1166 cfg.xlat_enablekoiwin ? IDC_KOI8WIN1251 :
1168 CheckDlgButton (hwnd, IDC_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1169 CheckRadioButton (hwnd, IDC_VTXWINDOWS, IDC_VTPOORMAN,
1170 cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
1171 cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
1172 cfg.vtmode == VT_OEMONLY ? IDC_VTOEMONLY :
1176 static void hide(HWND hwnd, int hide, int minid, int maxid) {
1178 for (i = minid; i < maxid; i++) {
1179 HWND ctl = GetDlgItem(hwnd, i);
1181 ShowWindow(ctl, hide ? SW_HIDE : SW_SHOW);
1186 struct treeview_faff {
1188 HTREEITEM lastat[4];
1191 static HTREEITEM treeview_insert(struct treeview_faff *faff,
1192 int level, char *text) {
1196 ins.hParent = (level > 0 ? faff->lastat[level-1] : TVI_ROOT);
1197 ins.hInsertAfter = faff->lastat[level];
1198 #if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
1199 #define INSITEM DUMMYUNIONNAME.item
1201 #define INSITEM item
1203 ins.INSITEM.mask = TVIF_TEXT;
1204 ins.INSITEM.pszText = text;
1205 newitem = TreeView_InsertItem(faff->treeview, &ins);
1207 TreeView_Expand(faff->treeview, faff->lastat[level-1], TVE_EXPAND);
1208 faff->lastat[level] = newitem;
1209 for (i = level+1; i < 4; i++) faff->lastat[i] = NULL;
1214 * This _huge_ function is the configuration box.
1216 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1217 WPARAM wParam, LPARAM lParam,
1220 struct treeview_faff tvfaff;
1223 char filename[sizeof(cfg.keyfile)];
1226 char fontstatic[256];
1231 SetWindowLong(hwnd, GWL_USERDATA, 0);
1233 * Centre the window.
1235 { /* centre the window */
1238 hw = GetDesktopWindow();
1239 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1240 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1241 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1242 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1246 * Create the tree view.
1253 r.left = 3; r.right = r.left + 75;
1254 r.top = 3; r.bottom = r.top + 10;
1255 MapDialogRect(hwnd, &r);
1256 tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
1257 WS_CHILD | WS_VISIBLE,
1259 r.right-r.left, r.bottom-r.top,
1260 hwnd, (HMENU)IDCX_TVSTATIC, hinst, NULL);
1261 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1262 SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1264 r.left = 3; r.right = r.left + 75;
1265 r.top = 13; r.bottom = r.top + 196;
1266 MapDialogRect(hwnd, &r);
1267 treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
1268 WS_CHILD | WS_VISIBLE |
1269 WS_TABSTOP | TVS_HASLINES |
1270 TVS_DISABLEDRAGDROP | TVS_HASBUTTONS |
1271 TVS_LINESATROOT | TVS_SHOWSELALWAYS,
1273 r.right-r.left, r.bottom-r.top,
1274 hwnd, (HMENU)IDCX_TREEVIEW, hinst, NULL);
1275 font = SendMessage(hwnd, WM_GETFONT, 0, 0);
1276 SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
1277 tvfaff.treeview = treeview;
1278 memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
1282 * Create the various panelfuls of controls.
1285 /* The Session panel. Accelerators used: [acgo] nprthelsdx */
1288 ctlposinit(&cp, hwnd, 80, 3, 13);
1289 bartitle(&cp, "Basic options for your PuTTY session",
1292 beginbox(&cp, "Specify your connection by host name",
1293 IDC_BOX_SESSION1, IDC_BOXT_SESSION1);
1295 "Host &Name", IDC_HOSTSTATIC, IDC_HOST, 75,
1296 "&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
1297 if (backends[2].backend == NULL) {
1298 /* this is PuTTYtel, so only two protocols available */
1299 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1300 "&Raw", IDC_PROTRAW,
1301 "&Telnet", IDC_PROTTELNET, NULL);
1303 radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
1304 "&Raw", IDC_PROTRAW,
1305 "&Telnet", IDC_PROTTELNET,
1314 beginbox(&cp, "Load, save or delete a stored session",
1315 IDC_BOX_SESSION2, IDC_BOXT_SESSION2);
1316 sesssaver(&cp, "Stor&ed Sessions",
1317 IDC_SESSSTATIC, IDC_SESSEDIT, IDC_SESSLIST,
1318 "&Load", IDC_SESSLOAD,
1319 "&Save", IDC_SESSSAVE,
1320 "&Delete", IDC_SESSDEL, NULL);
1323 beginbox(&cp, NULL, IDC_BOX_SESSION3, 0);
1324 checkbox(&cp, "Close Window on E&xit", IDC_CLOSEEXIT);
1327 hsession = treeview_insert(&tvfaff, 0, "Session");
1330 /* The Terminal panel. Accelerators used: [acgo] rmkh&dlbenu */
1333 ctlposinit(&cp, hwnd, 80, 3, 13);
1334 bartitle(&cp, "Options controlling the terminal emulation",
1335 IDC_TITLE_TERMINAL);
1336 beginbox(&cp, "Set the size of the terminal window",
1337 IDC_BOX_TERMINAL1, IDC_BOXT_TERMINAL1);
1339 "&Rows", IDC_ROWSSTATIC, IDC_ROWSEDIT, 50,
1340 "Colu&mns", IDC_COLSSTATIC, IDC_COLSEDIT, 50,
1342 checkbox(&cp, "Loc&k window size against resizing", IDC_LOCKSIZE);
1344 beginbox(&cp, "Set the font used in the terminal window",
1345 IDC_BOX_TERMINAL2, IDC_BOXT_TERMINAL2);
1346 staticbtn(&cp, "", IDC_FONTSTATIC, "C&hange...", IDC_CHOOSEFONT);
1348 beginbox(&cp, "Set various terminal options",
1349 IDC_BOX_TERMINAL3, IDC_BOXT_TERMINAL3);
1350 checkbox(&cp, "Auto &wrap mode initially on", IDC_WRAPMODE);
1351 checkbox(&cp, "&DEC Origin Mode initially on", IDC_DECOM);
1352 checkbox(&cp, "Implicit CR in every &LF", IDC_LFHASCR);
1353 checkbox(&cp, "&Beep enabled", IDC_BEEP);
1354 checkbox(&cp, "Use background colour to &erase screen", IDC_BCE);
1355 checkbox(&cp, "Enable bli&nking text", IDC_BLINKTEXT);
1356 checkbox(&cp, "&Use local terminal line discipline", IDC_LDISCTERM);
1359 treeview_insert(&tvfaff, 0, "Terminal");
1362 /* The Keyboard panel. Accelerators used: [acgo] h?srvlxvnpmie */
1365 ctlposinit(&cp, hwnd, 80, 3, 13);
1366 bartitle(&cp, "Options controlling the effects of keys",
1367 IDC_TITLE_KEYBOARD);
1368 beginbox(&cp, "Change the sequences sent by:",
1369 IDC_BOX_KEYBOARD1, IDC_BOXT_KEYBOARD1);
1370 radioline(&cp, "The Backspace key", IDC_DELSTATIC, 2,
1371 "Control-&H", IDC_DEL008,
1372 "Control-&? (127)", IDC_DEL127, NULL);
1373 radioline(&cp, "The Home and End keys", IDC_HOMESTATIC, 2,
1374 "&Standard", IDC_HOMETILDE,
1375 "&rxvt", IDC_HOMERXVT, NULL);
1376 radioline(&cp, "The Function keys and keypad", IDC_FUNCSTATIC, 4,
1377 "ESC[n&~", IDC_FUNCTILDE,
1378 "&Linux", IDC_FUNCLINUX,
1379 "&Xterm R6", IDC_FUNCXTERM,
1380 "&VT400", IDC_FUNCVT400, NULL);
1382 beginbox(&cp, "Change the initial state of:",
1383 IDC_BOX_KEYBOARD2, IDC_BOXT_KEYBOARD2);
1384 radioline(&cp, "Initial state of cursor keys:", IDC_CURSTATIC, 2,
1385 "&Normal", IDC_CURNORMAL,
1386 "A&pplication", IDC_CURAPPLIC, NULL);
1387 radioline(&cp, "Initial state of numeric keypad:", IDC_KPSTATIC, 3,
1388 "Nor&mal", IDC_KPNORMAL,
1389 "Appl&ication", IDC_KPAPPLIC,
1390 "N&etHack", IDC_KPNH, NULL);
1393 treeview_insert(&tvfaff, 1, "Keyboard");
1396 /* The Window panel. Accelerators used: [acgo] tibsdkw4y */
1399 ctlposinit(&cp, hwnd, 80, 3, 13);
1400 bartitle(&cp, "Options controlling PuTTY's window",
1402 beginbox(&cp, "Adjust the use of the window title",
1403 IDC_BOX_WINDOW1, IDC_BOXT_WINDOW1);
1406 "Initial window &title:", IDC_WINTITLE,
1407 IDC_WINEDIT, 100, NULL);
1408 checkbox(&cp, "Avoid ever using &icon title", IDC_WINNAME);
1410 beginbox(&cp, "Adjust the use of the cursor",
1411 IDC_BOX_WINDOW2, IDC_BOXT_WINDOW2);
1412 checkbox(&cp, "Cursor &blinks", IDC_BLINKCUR);
1414 beginbox(&cp, "Control the scrollback in the window",
1415 IDC_BOX_WINDOW3, IDC_BOXT_WINDOW3);
1416 staticedit(&cp, "Lines of &scrollback",
1417 IDC_SAVESTATIC, IDC_SAVEEDIT, 50);
1418 checkbox(&cp, "&Display scrollbar", IDC_SCROLLBAR);
1419 checkbox(&cp, "Reset scrollback on &keypress", IDC_SCROLLKEY);
1421 beginbox(&cp, NULL, IDC_BOX_WINDOW4, 0);
1422 checkbox(&cp, "&Warn before closing window", IDC_CLOSEWARN);
1423 checkbox(&cp, "Window closes on ALT-F&4", IDC_ALTF4);
1424 checkbox(&cp, "S&ystem menu appears on ALT-Space)", IDC_ALTSPACE);
1427 treeview_insert(&tvfaff, 0, "Window");
1430 /* The Translation panel. Accelerators used: [acgo] xbepnkis */
1433 ctlposinit(&cp, hwnd, 80, 3, 13);
1434 bartitle(&cp, "Options controlling character set translation",
1435 IDC_TITLE_TRANSLATION);
1436 beginbox(&cp, "Adjust how PuTTY displays line drawing characters",
1437 IDC_BOX_TRANSLATION1, IDC_BOXT_TRANSLATION1);
1439 "Handling of line drawing characters:", IDC_VTSTATIC,
1440 "Font has &XWindows encoding", IDC_VTXWINDOWS,
1441 "Use font in &both ANSI and OEM modes", IDC_VTOEMANSI,
1442 "Use font in O&EM mode only", IDC_VTOEMONLY,
1443 "&Poor man's line drawing (""+"", ""-"" and ""|"")",
1444 IDC_VTPOORMAN, NULL);
1446 beginbox(&cp, "Enable character set translation on received data",
1447 IDC_BOX_TRANSLATION2, IDC_BOXT_TRANSLATION2);
1449 "Character set translation:", IDC_XLATSTATIC,
1450 "&None", IDC_NOXLAT,
1451 "&KOI8 / Win-1251", IDC_KOI8WIN1251,
1452 "&ISO-8859-2 / Win-1250", IDC_88592WIN1250,
1453 "&ISO-8859-2 / CP852", IDC_88592CP852, NULL);
1455 beginbox(&cp, "Enable character set translation on input data",
1456 IDC_BOX_TRANSLATION3, IDC_BOXT_TRANSLATION3);
1457 checkbox(&cp, "CAP&S LOCK acts as cyrillic switch",
1461 treeview_insert(&tvfaff, 1, "Translation");
1464 /* The Selection panel. Accelerators used: [acgo] wxst */
1467 ctlposinit(&cp, hwnd, 80, 3, 13);
1468 bartitle(&cp, "Options controlling copy and paste",
1469 IDC_TITLE_SELECTION);
1470 beginbox(&cp, "Control which mouse button does which thing",
1471 IDC_BOX_SELECTION1, IDC_BOXT_SELECTION1);
1472 radiobig(&cp, "Action of mouse buttons:", IDC_MBSTATIC,
1473 "&Windows (Right pastes, Middle extends)", IDC_MBWINDOWS,
1474 "&xterm (Right extends, Middle pastes)", IDC_MBXTERM,
1477 beginbox(&cp, "Control the select-one-word-at-a-time mode",
1478 IDC_BOX_SELECTION2, IDC_BOXT_SELECTION2);
1479 charclass(&cp, "Character classes:", IDC_CCSTATIC, IDC_CCLIST,
1480 "&Set", IDC_CCSET, IDC_CCEDIT,
1481 "&to class", IDC_CCSTATIC2);
1484 treeview_insert(&tvfaff, 1, "Selection");
1487 /* The Colours panel. Accelerators used: [acgo] blum */
1490 ctlposinit(&cp, hwnd, 80, 3, 13);
1491 bartitle(&cp, "Options controlling use of colours",
1493 beginbox(&cp, "General options for colour usage",
1494 IDC_BOX_COLOURS1, IDC_BOXT_COLOURS1);
1495 checkbox(&cp, "&Bolded text is a different colour", IDC_BOLDCOLOUR);
1496 checkbox(&cp, "Attempt to use &logical palettes", IDC_PALETTE);
1498 beginbox(&cp, "Adjust the precise colours PuTTY displays",
1499 IDC_BOX_COLOURS2, IDC_BOXT_COLOURS2);
1500 colouredit(&cp, "Select a colo&ur and then click to modify it:",
1501 IDC_STATIC, IDC_LIST,
1502 "&Modify...", IDC_CHANGE,
1503 "Red:", IDC_RSTATIC, IDC_RVALUE,
1504 "Green:", IDC_GSTATIC, IDC_GVALUE,
1505 "Blue:", IDC_BSTATIC, IDC_BVALUE, NULL);
1508 treeview_insert(&tvfaff, 1, "Colours");
1511 /* The Connection panel. Accelerators used: [acgo] tuk */
1514 ctlposinit(&cp, hwnd, 80, 3, 13);
1515 bartitle(&cp, "Options controlling the connection", IDC_TITLE_CONNECTION);
1517 beginbox(&cp, "Data to send to the server",
1518 IDC_BOX_CONNECTION1, IDC_BOXT_CONNECTION1);
1519 staticedit(&cp, "Terminal-&type string", IDC_TTSTATIC, IDC_TTEDIT, 50);
1520 staticedit(&cp, "Auto-login &username", IDC_LOGSTATIC, IDC_LOGEDIT, 50);
1523 beginbox(&cp, "Sending of null packets to keep session active",
1524 IDC_BOX_CONNECTION2, IDC_BOXT_CONNECTION2);
1525 staticedit(&cp, "Minutes between &keepalives (0 to turn off)",
1526 IDC_PINGSTATIC, IDC_PINGEDIT, 25);
1529 treeview_insert(&tvfaff, 0, "Connection");
1532 /* The Telnet panel. Accelerators used: [acgo] svldrbf */
1535 ctlposinit(&cp, hwnd, 80, 3, 13);
1537 bartitle(&cp, "Options controlling Telnet connections", IDC_TITLE_TELNET);
1538 beginbox(&cp, "Data to send to the server",
1539 IDC_BOX_TELNET1, IDC_BOXT_TELNET1);
1540 staticedit(&cp, "Terminal-&speed string", IDC_TSSTATIC, IDC_TSEDIT, 50);
1541 envsetter(&cp, "Environment variables:", IDC_ENVSTATIC,
1542 "&Variable", IDC_VARSTATIC, IDC_VAREDIT,
1543 "Va&lue", IDC_VALSTATIC, IDC_VALEDIT,
1545 "A&dd", IDC_ENVADD, "&Remove", IDC_ENVREMOVE);
1547 beginbox(&cp, "Telnet protocol adjustments",
1548 IDC_BOX_TELNET2, IDC_BOXT_TELNET2);
1549 radioline(&cp, "Handling of OLD_ENVIRON ambiguity:", IDC_EMSTATIC, 2,
1550 "&BSD (commonplace)", IDC_EMBSD,
1551 "R&FC 1408 (unusual)", IDC_EMRFC, NULL);
1554 treeview_insert(&tvfaff, 1, "Telnet");
1558 /* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
1559 if (backends[2].backend != NULL) {
1561 ctlposinit(&cp, hwnd, 80, 3, 13);
1563 bartitle(&cp, "Options controlling SSH connections", IDC_TITLE_SSH);
1564 beginbox(&cp, "Data to send to the server",
1565 IDC_BOX_SSH1, IDC_BOXT_SSH1);
1567 "&Remote command:", IDC_CMDSTATIC, IDC_CMDEDIT, 100,
1570 beginbox(&cp, "Authentication options",
1571 IDC_BOX_SSH2, IDC_BOXT_SSH2);
1572 checkbox(&cp, "Atte&mpt TIS or CryptoCard authentication",
1574 checkbox(&cp, "Allow &agent forwarding", IDC_AGENTFWD);
1575 editbutton(&cp, "Private &key file for authentication:",
1576 IDC_PKSTATIC, IDC_PKEDIT, "Bro&wse...", IDC_PKBUTTON);
1578 beginbox(&cp, "Protocol options",
1579 IDC_BOX_SSH3, IDC_BOXT_SSH3);
1580 checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
1581 radioline(&cp, "Preferred SSH protocol version:",
1582 IDC_SSHPROTSTATIC, 2,
1583 "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
1584 radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
1585 "&3DES", IDC_CIPHER3DES,
1586 "&Blowfish", IDC_CIPHERBLOWF,
1587 "&DES", IDC_CIPHERDES, NULL);
1588 checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x",
1592 treeview_insert(&tvfaff, 1, "SSH");
1596 init_dlg_ctrls(hwnd);
1597 for (i = 0; i < nsessions; i++)
1598 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1599 0, (LPARAM) (sessions[i]));
1602 * Hide all the controls to start with.
1604 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1607 * Put the treeview selection on to the Session panel. This
1608 * should also cause unhiding of the relevant controls.
1610 TreeView_SelectItem(treeview, hsession);
1613 * Set focus into the first available control.
1617 ctl = GetDlgItem(hwnd, IDC_HOST);
1618 if (!ctl) ctl = GetDlgItem(hwnd, IDC_CLOSEEXIT);
1622 SetWindowLong(hwnd, GWL_USERDATA, 1);
1626 * Button release should trigger WM_OK if there was a
1627 * previous double click on the session list.
1631 SendMessage (hwnd, WM_COMMAND, IDOK, 0);
1634 if (LOWORD(wParam) == IDCX_TREEVIEW &&
1635 ((LPNMHDR)lParam)->code == TVN_SELCHANGED) {
1636 HTREEITEM i = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
1640 item.pszText = buffer;
1641 item.cchTextMax = sizeof(buffer);
1642 item.mask = TVIF_TEXT;
1643 TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &item);
1644 hide(hwnd, TRUE, controlstartvalue, controlendvalue);
1645 if (!strcmp(buffer, "Session"))
1646 hide(hwnd, FALSE, sessionpanelstart, sessionpanelend);
1647 if (!strcmp(buffer, "Keyboard"))
1648 hide(hwnd, FALSE, keyboardpanelstart, keyboardpanelend);
1649 if (!strcmp(buffer, "Terminal"))
1650 hide(hwnd, FALSE, terminalpanelstart, terminalpanelend);
1651 if (!strcmp(buffer, "Window"))
1652 hide(hwnd, FALSE, windowpanelstart, windowpanelend);
1653 if (!strcmp(buffer, "Connection"))
1654 hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
1655 if (!strcmp(buffer, "Telnet"))
1656 hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
1657 if (!strcmp(buffer, "SSH"))
1658 hide(hwnd, FALSE, sshpanelstart, sshpanelend);
1659 if (!strcmp(buffer, "Selection"))
1660 hide(hwnd, FALSE, selectionpanelstart, selectionpanelend);
1661 if (!strcmp(buffer, "Colours"))
1662 hide(hwnd, FALSE, colourspanelstart, colourspanelend);
1663 if (!strcmp(buffer, "Translation"))
1664 hide(hwnd, FALSE, translationpanelstart, translationpanelend);
1666 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1672 * Only process WM_COMMAND once the dialog is fully formed.
1674 if (GetWindowLong(hwnd, GWL_USERDATA) == 1) switch (LOWORD(wParam)) {
1677 EndDialog (hwnd, 1);
1682 EndDialog (hwnd, 0);
1684 case IDC_PROTTELNET:
1687 if (HIWORD(wParam) == BN_CLICKED ||
1688 HIWORD(wParam) == BN_DOUBLECLICKED) {
1689 int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
1690 int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
1691 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
1692 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
1693 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
1694 cfg.port = i ? 22 : 23;
1695 SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
1700 if (HIWORD(wParam) == EN_CHANGE)
1701 GetDlgItemText (hwnd, IDC_HOST, cfg.host,
1702 sizeof(cfg.host)-1);
1705 if (HIWORD(wParam) == EN_CHANGE)
1706 MyGetDlgItemInt (hwnd, IDC_PORT, &cfg.port);
1709 if (HIWORD(wParam) == EN_CHANGE) {
1710 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1712 GetDlgItemText (hwnd, IDC_SESSEDIT,
1713 savedsession, sizeof(savedsession)-1);
1714 savedsession[sizeof(savedsession)-1] = '\0';
1718 if (HIWORD(wParam) == BN_CLICKED ||
1719 HIWORD(wParam) == BN_DOUBLECLICKED) {
1724 GetDlgItemText (hwnd, IDC_SESSEDIT, str, sizeof(str)-1);
1726 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1727 LB_GETCURSEL, 0, 0);
1732 strcpy (str, sessions[n]);
1734 save_settings (str, !!strcmp(str, "Default Settings"), &cfg);
1735 get_sesslist (FALSE);
1736 get_sesslist (TRUE);
1737 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1739 for (i = 0; i < nsessions; i++)
1740 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1741 0, (LPARAM) (sessions[i]));
1742 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1748 if (LOWORD(wParam) == IDC_SESSLOAD &&
1749 HIWORD(wParam) != BN_CLICKED &&
1750 HIWORD(wParam) != BN_DOUBLECLICKED)
1752 if (LOWORD(wParam) == IDC_SESSLIST &&
1753 HIWORD(wParam) != LBN_DBLCLK)
1756 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1757 LB_GETCURSEL, 0, 0);
1763 isdef = !strcmp(sessions[n], "Default Settings");
1764 load_settings (sessions[n], !isdef, &cfg);
1765 init_dlg_ctrls(hwnd);
1767 SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
1769 if (LOWORD(wParam) == IDC_SESSLIST) {
1771 * A double-click on a saved session should
1772 * actually start the session, not just load it.
1773 * Unless it's Default Settings or some other
1774 * host-less set of saved settings.
1783 if (HIWORD(wParam) == BN_CLICKED ||
1784 HIWORD(wParam) == BN_DOUBLECLICKED) {
1785 int n = SendDlgItemMessage (hwnd, IDC_SESSLIST,
1786 LB_GETCURSEL, 0, 0);
1787 if (n == LB_ERR || n == 0) {
1791 del_settings(sessions[n]);
1792 get_sesslist (FALSE);
1793 get_sesslist (TRUE);
1794 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_RESETCONTENT,
1796 for (i = 0; i < nsessions; i++)
1797 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_ADDSTRING,
1798 0, (LPARAM) (sessions[i]));
1799 SendDlgItemMessage (hwnd, IDC_SESSLIST, LB_SETCURSEL,
1803 if (HIWORD(wParam) == EN_CHANGE)
1804 MyGetDlgItemInt (hwnd, IDC_PINGEDIT, &cfg.ping_interval);
1808 if (HIWORD(wParam) == BN_CLICKED ||
1809 HIWORD(wParam) == BN_DOUBLECLICKED)
1810 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC_DEL127);
1814 if (HIWORD(wParam) == BN_CLICKED ||
1815 HIWORD(wParam) == BN_DOUBLECLICKED)
1816 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC_HOMERXVT);
1819 if (HIWORD(wParam) == BN_CLICKED ||
1820 HIWORD(wParam) == BN_DOUBLECLICKED)
1824 if (HIWORD(wParam) == BN_CLICKED ||
1825 HIWORD(wParam) == BN_DOUBLECLICKED)
1830 if (HIWORD(wParam) == BN_CLICKED ||
1831 HIWORD(wParam) == BN_DOUBLECLICKED)
1832 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC_FUNCLINUX);
1836 if (HIWORD(wParam) == BN_CLICKED ||
1837 HIWORD(wParam) == BN_DOUBLECLICKED) {
1838 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC_KPAPPLIC);
1839 cfg.nethack_keypad = FALSE;
1843 if (HIWORD(wParam) == BN_CLICKED ||
1844 HIWORD(wParam) == BN_DOUBLECLICKED) {
1845 cfg.app_keypad = FALSE;
1846 cfg.nethack_keypad = TRUE;
1851 if (HIWORD(wParam) == BN_CLICKED ||
1852 HIWORD(wParam) == BN_DOUBLECLICKED)
1853 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC_CURAPPLIC);
1856 if (HIWORD(wParam) == BN_CLICKED ||
1857 HIWORD(wParam) == BN_DOUBLECLICKED)
1858 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC_ALTF4);
1861 if (HIWORD(wParam) == BN_CLICKED ||
1862 HIWORD(wParam) == BN_DOUBLECLICKED)
1863 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC_ALTSPACE);
1866 if (HIWORD(wParam) == BN_CLICKED ||
1867 HIWORD(wParam) == BN_DOUBLECLICKED)
1868 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC_LDISCTERM);
1871 if (HIWORD(wParam) == BN_CLICKED ||
1872 HIWORD(wParam) == BN_DOUBLECLICKED)
1873 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC_SCROLLKEY);
1876 if (HIWORD(wParam) == BN_CLICKED ||
1877 HIWORD(wParam) == BN_DOUBLECLICKED)
1878 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC_WRAPMODE);
1881 if (HIWORD(wParam) == BN_CLICKED ||
1882 HIWORD(wParam) == BN_DOUBLECLICKED)
1883 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC_DECOM);
1886 if (HIWORD(wParam) == BN_CLICKED ||
1887 HIWORD(wParam) == BN_DOUBLECLICKED)
1888 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC_LFHASCR);
1891 if (HIWORD(wParam) == EN_CHANGE)
1892 MyGetDlgItemInt (hwnd, IDC_ROWSEDIT, &cfg.height);
1895 if (HIWORD(wParam) == EN_CHANGE)
1896 MyGetDlgItemInt (hwnd, IDC_COLSEDIT, &cfg.width);
1899 if (HIWORD(wParam) == EN_CHANGE)
1900 MyGetDlgItemInt (hwnd, IDC_SAVEEDIT, &cfg.savelines);
1902 case IDC_CHOOSEFONT:
1903 lf.lfHeight = cfg.fontheight;
1904 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
1905 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
1906 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
1907 lf.lfCharSet = cfg.fontcharset;
1908 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1909 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1910 lf.lfQuality = DEFAULT_QUALITY;
1911 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
1912 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
1913 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
1915 cf.lStructSize = sizeof(cf);
1916 cf.hwndOwner = hwnd;
1918 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
1919 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
1921 if (ChooseFont (&cf)) {
1922 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
1923 cfg.font[sizeof(cfg.font)-1] = '\0';
1924 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
1925 cfg.fontcharset = lf.lfCharSet;
1926 cfg.fontheight = lf.lfHeight;
1927 fmtfont (fontstatic);
1928 SetDlgItemText (hwnd, IDC_FONTSTATIC, fontstatic);
1932 if (HIWORD(wParam) == BN_CLICKED ||
1933 HIWORD(wParam) == BN_DOUBLECLICKED)
1934 cfg.beep = IsDlgButtonChecked (hwnd, IDC_BEEP);
1937 if (HIWORD(wParam) == BN_CLICKED ||
1938 HIWORD(wParam) == BN_DOUBLECLICKED)
1939 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC_BLINKTEXT);
1942 if (HIWORD(wParam) == BN_CLICKED ||
1943 HIWORD(wParam) == BN_DOUBLECLICKED)
1944 cfg.bce = IsDlgButtonChecked (hwnd, IDC_BCE);
1947 if (HIWORD(wParam) == BN_CLICKED ||
1948 HIWORD(wParam) == BN_DOUBLECLICKED)
1949 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC_WINNAME);
1952 if (HIWORD(wParam) == BN_CLICKED ||
1953 HIWORD(wParam) == BN_DOUBLECLICKED)
1954 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC_BLINKCUR);
1957 if (HIWORD(wParam) == BN_CLICKED ||
1958 HIWORD(wParam) == BN_DOUBLECLICKED)
1959 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC_SCROLLBAR);
1962 if (HIWORD(wParam) == BN_CLICKED ||
1963 HIWORD(wParam) == BN_DOUBLECLICKED)
1964 cfg.locksize = IsDlgButtonChecked (hwnd, IDC_LOCKSIZE);
1967 if (HIWORD(wParam) == EN_CHANGE)
1968 GetDlgItemText (hwnd, IDC_WINEDIT, cfg.wintitle,
1969 sizeof(cfg.wintitle)-1);
1972 if (HIWORD(wParam) == BN_CLICKED ||
1973 HIWORD(wParam) == BN_DOUBLECLICKED)
1974 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC_CLOSEEXIT);
1977 if (HIWORD(wParam) == BN_CLICKED ||
1978 HIWORD(wParam) == BN_DOUBLECLICKED)
1979 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC_CLOSEWARN);
1982 if (HIWORD(wParam) == EN_CHANGE)
1983 GetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype,
1984 sizeof(cfg.termtype)-1);
1987 if (HIWORD(wParam) == EN_CHANGE)
1988 GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
1989 sizeof(cfg.termspeed)-1);
1992 if (HIWORD(wParam) == EN_CHANGE)
1993 GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
1994 sizeof(cfg.username)-1);
1998 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
2001 if (HIWORD(wParam) == BN_CLICKED ||
2002 HIWORD(wParam) == BN_DOUBLECLICKED) {
2003 char str[sizeof(cfg.environmt)];
2005 GetDlgItemText (hwnd, IDC_VAREDIT, str, sizeof(str)-1);
2010 p = str + strlen(str);
2012 GetDlgItemText (hwnd, IDC_VALEDIT, p, sizeof(str)-1-(p-str));
2022 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
2024 p[strlen(str)+1] = '\0';
2025 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_ADDSTRING,
2027 SetDlgItemText (hwnd, IDC_VAREDIT, "");
2028 SetDlgItemText (hwnd, IDC_VALEDIT, "");
2030 MessageBox(hwnd, "Environment too big", "PuTTY Error",
2031 MB_OK | MB_ICONERROR);
2036 if (HIWORD(wParam) != BN_CLICKED &&
2037 HIWORD(wParam) != BN_DOUBLECLICKED)
2039 i = SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_GETCURSEL, 0, 0);
2045 SendDlgItemMessage (hwnd, IDC_ENVLIST, LB_DELETESTRING,
2070 if (HIWORD(wParam) == BN_CLICKED ||
2071 HIWORD(wParam) == BN_DOUBLECLICKED)
2072 cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
2075 if (HIWORD(wParam) == BN_CLICKED ||
2076 HIWORD(wParam) == BN_DOUBLECLICKED)
2077 cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC);
2080 if (HIWORD(wParam) == BN_CLICKED ||
2081 HIWORD(wParam) == BN_DOUBLECLICKED)
2082 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC_AGENTFWD);
2084 case IDC_CIPHER3DES:
2085 case IDC_CIPHERBLOWF:
2087 if (HIWORD(wParam) == BN_CLICKED ||
2088 HIWORD(wParam) == BN_DOUBLECLICKED) {
2089 if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
2090 cfg.cipher = CIPHER_3DES;
2091 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERBLOWF))
2092 cfg.cipher = CIPHER_BLOWFISH;
2093 else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
2094 cfg.cipher = CIPHER_DES;
2099 if (HIWORD(wParam) == BN_CLICKED ||
2100 HIWORD(wParam) == BN_DOUBLECLICKED) {
2101 if (IsDlgButtonChecked (hwnd, IDC_SSHPROT1))
2103 else if (IsDlgButtonChecked (hwnd, IDC_SSHPROT2))
2108 if (HIWORD(wParam) == BN_CLICKED ||
2109 HIWORD(wParam) == BN_DOUBLECLICKED)
2110 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC_AUTHTIS);
2113 if (HIWORD(wParam) == EN_CHANGE)
2114 GetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile,
2115 sizeof(cfg.keyfile)-1);
2118 if (HIWORD(wParam) == EN_CHANGE)
2119 GetDlgItemText (hwnd, IDC_CMDEDIT, cfg.remote_cmd,
2120 sizeof(cfg.remote_cmd)-1);
2123 memset(&of, 0, sizeof(of));
2124 #ifdef OPENFILENAME_SIZE_VERSION_400
2125 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
2127 of.lStructSize = sizeof(of);
2129 of.hwndOwner = hwnd;
2130 of.lpstrFilter = "All Files\0*\0\0\0";
2131 of.lpstrCustomFilter = NULL;
2132 of.nFilterIndex = 1;
2133 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
2134 of.nMaxFile = sizeof(filename);
2135 of.lpstrFileTitle = NULL;
2136 of.lpstrInitialDir = NULL;
2137 of.lpstrTitle = "Select Public Key File";
2139 if (GetOpenFileName(&of)) {
2140 strcpy(cfg.keyfile, filename);
2141 SetDlgItemText (hwnd, IDC_PKEDIT, cfg.keyfile);
2146 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC_MBXTERM);
2152 int n = GetDlgItemInt (hwnd, IDC_CCEDIT, &ok, FALSE);
2157 for (i=0; i<256; i++)
2158 if (SendDlgItemMessage (hwnd, IDC_CCLIST, LB_GETSEL,
2161 cfg.wordness[i] = n;
2162 SendDlgItemMessage (hwnd, IDC_CCLIST,
2163 LB_DELETESTRING, i, 0);
2164 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
2165 (i>=0x21 && i != 0x7F) ? i : ' ',
2167 SendDlgItemMessage (hwnd, IDC_CCLIST,
2174 case IDC_BOLDCOLOUR:
2175 if (HIWORD(wParam) == BN_CLICKED ||
2176 HIWORD(wParam) == BN_DOUBLECLICKED) {
2178 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC_BOLDCOLOUR);
2179 n = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCOUNT, 0, 0);
2180 if (cfg.bold_colour && n!=22) {
2181 for (i=0; i<22; i++)
2183 SendDlgItemMessage (hwnd, IDC_LIST,
2185 (LPARAM) colours[i]);
2186 } else if (!cfg.bold_colour && n!=12) {
2189 SendDlgItemMessage (hwnd, IDC_LIST,
2190 LB_DELETESTRING, i, 0);
2195 if (HIWORD(wParam) == BN_CLICKED ||
2196 HIWORD(wParam) == BN_DOUBLECLICKED)
2197 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC_PALETTE);
2200 if (HIWORD(wParam) == LBN_DBLCLK ||
2201 HIWORD(wParam) == LBN_SELCHANGE) {
2202 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2204 if (!cfg.bold_colour)
2205 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2206 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0], FALSE);
2207 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1], FALSE);
2208 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2], FALSE);
2212 if (HIWORD(wParam) == BN_CLICKED ||
2213 HIWORD(wParam) == BN_DOUBLECLICKED) {
2214 static CHOOSECOLOR cc;
2215 static DWORD custom[16] = {0}; /* zero initialisers */
2216 int i = SendDlgItemMessage (hwnd, IDC_LIST, LB_GETCURSEL,
2218 if (!cfg.bold_colour)
2219 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
2220 cc.lStructSize = sizeof(cc);
2221 cc.hwndOwner = hwnd;
2222 cc.hInstance = (HWND)hinst;
2223 cc.lpCustColors = custom;
2224 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
2226 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
2227 if (ChooseColor(&cc)) {
2229 (unsigned char) (cc.rgbResult & 0xFF);
2231 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
2233 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
2234 SetDlgItemInt (hwnd, IDC_RVALUE, cfg.colours[i][0],
2236 SetDlgItemInt (hwnd, IDC_GVALUE, cfg.colours[i][1],
2238 SetDlgItemInt (hwnd, IDC_BVALUE, cfg.colours[i][2],
2244 case IDC_KOI8WIN1251:
2245 case IDC_88592WIN1250:
2246 case IDC_88592CP852:
2247 cfg.xlat_enablekoiwin =
2248 IsDlgButtonChecked (hwnd, IDC_KOI8WIN1251);
2249 cfg.xlat_88592w1250 =
2250 IsDlgButtonChecked (hwnd, IDC_88592WIN1250);
2251 cfg.xlat_88592cp852 =
2252 IsDlgButtonChecked (hwnd, IDC_88592CP852);
2254 case IDC_CAPSLOCKCYR:
2255 if (HIWORD(wParam) == BN_CLICKED ||
2256 HIWORD(wParam) == BN_DOUBLECLICKED) {
2257 cfg.xlat_capslockcyr =
2258 IsDlgButtonChecked (hwnd, IDC_CAPSLOCKCYR);
2261 case IDC_VTXWINDOWS:
2266 (IsDlgButtonChecked (hwnd, IDC_VTXWINDOWS) ? VT_XWINDOWS :
2267 IsDlgButtonChecked (hwnd, IDC_VTOEMANSI) ? VT_OEMANSI :
2268 IsDlgButtonChecked (hwnd, IDC_VTOEMONLY) ? VT_OEMONLY :
2274 EndDialog (hwnd, 0);
2277 /* Grrr Explorer will maximize Dialogs! */
2279 if (wParam == SIZE_MAXIMIZED)
2286 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
2287 WPARAM wParam, LPARAM lParam) {
2288 static HWND page = NULL;
2290 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
2292 if (msg == WM_COMMAND && LOWORD(wParam) == IDCX_ABOUT) {
2293 EnableWindow(hwnd, 0);
2294 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2295 GetParent(hwnd), AboutProc);
2296 EnableWindow(hwnd, 1);
2297 SetActiveWindow(hwnd);
2299 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 0);
2302 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
2303 WPARAM wParam, LPARAM lParam) {
2305 return GenericMainDlgProc (hwnd, msg, wParam, lParam, 1);
2308 int defuse_showwindow(void) {
2310 * Work around the fact that the app's first call to ShowWindow
2311 * will ignore the default in favour of the shell-provided
2316 hwnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2318 ShowWindow(hwnd, SW_HIDE);
2319 DestroyWindow(hwnd);
2323 int do_config (void) {
2327 savedsession[0] = '\0';
2328 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
2329 get_sesslist(FALSE);
2334 int do_reconfig (HWND hwnd) {
2338 backup_cfg = cfg; /* structure copy */
2339 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
2341 cfg = backup_cfg; /* structure copy */
2348 void logevent (char *string) {
2349 if (nevents >= negsize) {
2351 events = srealloc (events, negsize * sizeof(*events));
2353 events[nevents] = smalloc(1+strlen(string));
2354 strcpy (events[nevents], string);
2358 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
2360 count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
2361 SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0);
2365 void showeventlog (HWND hwnd) {
2367 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
2369 ShowWindow (logbox, SW_SHOWNORMAL);
2373 void showabout (HWND hwnd) {
2375 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
2377 ShowWindow (abtbox, SW_SHOWNORMAL);
2381 void verify_ssh_host_key(char *host, int port, char *keytype,
2382 char *keystr, char *fingerprint) {
2385 static const char absentmsg[] =
2386 "The server's host key is not cached in the registry. You\n"
2387 "have no guarantee that the server is the computer you\n"
2389 "The server's key fingerprint is:\n"
2391 "If you trust this host, hit Yes to add the key to\n"
2392 "PuTTY's cache and carry on connecting.\n"
2393 "If you do not trust this host, hit No to abandon the\n"
2396 static const char wrongmsg[] =
2397 "WARNING - POTENTIAL SECURITY BREACH!\n"
2399 "The server's host key does not match the one PuTTY has\n"
2400 "cached in the registry. This means that either the\n"
2401 "server administrator has changed the host key, or you\n"
2402 "have actually connected to another computer pretending\n"
2403 "to be the server.\n"
2404 "The new key fingerprint is:\n"
2406 "If you were expecting this change and trust the new key,\n"
2407 "hit Yes to update PuTTY's cache and continue connecting.\n"
2408 "If you want to carry on connecting but without updating\n"
2409 "the cache, hit No.\n"
2410 "If you want to abandon the connection completely, hit\n"
2411 "Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
2414 static const char mbtitle[] = "PuTTY Security Alert";
2417 char message[160+ /* sensible fingerprint max size */
2418 (sizeof(absentmsg) > sizeof(wrongmsg) ?
2419 sizeof(absentmsg) : sizeof(wrongmsg))];
2422 * Verify the key against the registry.
2424 ret = verify_host_key(host, port, keytype, keystr);
2426 if (ret == 0) /* success - key matched OK */
2428 if (ret == 2) { /* key was different */
2430 sprintf(message, wrongmsg, fingerprint);
2431 mbret = MessageBox(NULL, message, mbtitle,
2432 MB_ICONWARNING | MB_YESNOCANCEL);
2434 store_host_key(host, port, keytype, keystr);
2435 if (mbret == IDCANCEL)
2438 if (ret == 1) { /* key was absent */
2440 sprintf(message, absentmsg, fingerprint);
2441 mbret = MessageBox(NULL, message, mbtitle,
2442 MB_ICONWARNING | MB_YESNO);
2445 store_host_key(host, port, keytype, keystr);