2 * config.c - the platform-independent parts of the PuTTY
13 #define PRINTER_DISABLED_STRING "None (printing disabled)"
15 static void protocolbuttons_handler(union control *ctrl, void *dlg,
16 void *data, int event)
19 Config *cfg = (Config *)data;
21 * This function works just like the standard radio-button
22 * handler, except that it also has to change the setting of
23 * the port box. We expect the context parameter to point at
24 * the `union control' structure for the port box.
26 if (event == EVENT_REFRESH) {
27 for (button = 0; button < ctrl->radio.nbuttons; button++)
28 if (cfg->protocol == ctrl->radio.buttondata[button].i)
30 /* We expected that `break' to happen, in all circumstances. */
31 assert(button < ctrl->radio.nbuttons);
32 dlg_radiobutton_set(ctrl, dlg, button);
33 } else if (event == EVENT_VALCHANGE) {
34 int oldproto = cfg->protocol;
35 button = dlg_radiobutton_get(ctrl, dlg);
36 assert(button >= 0 && button < ctrl->radio.nbuttons);
37 cfg->protocol = ctrl->radio.buttondata[button].i;
38 if (oldproto != cfg->protocol) {
40 switch (cfg->protocol) {
41 case PROT_SSH: defport = 22; break;
42 case PROT_TELNET: defport = 23; break;
43 case PROT_RLOGIN: defport = 513; break;
45 if (defport > 0 && cfg->port != defport) {
47 dlg_refresh((union control *)ctrl->radio.context.p, dlg);
53 static void numeric_keypad_handler(union control *ctrl, void *dlg,
54 void *data, int event)
57 Config *cfg = (Config *)data;
59 * This function works much like the standard radio button
60 * handler, but it has to handle two fields in Config.
62 if (event == EVENT_REFRESH) {
63 if (cfg->nethack_keypad)
65 else if (cfg->app_keypad)
69 assert(button < ctrl->radio.nbuttons);
70 dlg_radiobutton_set(ctrl, dlg, button);
71 } else if (event == EVENT_VALCHANGE) {
72 button = dlg_radiobutton_get(ctrl, dlg);
73 assert(button >= 0 && button < ctrl->radio.nbuttons);
75 cfg->app_keypad = FALSE;
76 cfg->nethack_keypad = TRUE;
78 cfg->app_keypad = (button != 0);
79 cfg->nethack_keypad = FALSE;
84 static void cipherlist_handler(union control *ctrl, void *dlg,
85 void *data, int event)
87 Config *cfg = (Config *)data;
88 if (event == EVENT_REFRESH) {
91 static const struct { char *s; int c; } ciphers[] = {
92 { "3DES", CIPHER_3DES },
93 { "Blowfish", CIPHER_BLOWFISH },
94 { "DES", CIPHER_DES },
95 { "AES (SSH 2 only)", CIPHER_AES },
96 { "-- warn below here --", CIPHER_WARN }
99 /* Set up the "selected ciphers" box. */
100 /* (cipherlist assumed to contain all ciphers) */
101 dlg_update_start(ctrl, dlg);
102 dlg_listbox_clear(ctrl, dlg);
103 for (i = 0; i < CIPHER_MAX; i++) {
104 int c = cfg->ssh_cipherlist[i];
107 for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
108 if (ciphers[j].c == c) {
113 dlg_listbox_addwithid(ctrl, dlg, cstr, c);
115 dlg_update_done(ctrl, dlg);
117 } else if (event == EVENT_VALCHANGE) {
120 /* Update array to match the list box. */
121 for (i=0; i < CIPHER_MAX; i++)
122 cfg->ssh_cipherlist[i] = dlg_listbox_getid(ctrl, dlg, i);
127 static void printerbox_handler(union control *ctrl, void *dlg,
128 void *data, int event)
130 Config *cfg = (Config *)data;
131 if (event == EVENT_REFRESH) {
135 dlg_update_start(ctrl, dlg);
137 * Some backends may wish to disable the drop-down list on
138 * this edit box. Be prepared for this.
140 if (ctrl->editbox.has_list) {
141 dlg_listbox_clear(ctrl, dlg);
142 dlg_listbox_add(ctrl, dlg, PRINTER_DISABLED_STRING);
143 pe = printer_start_enum(&nprinters);
144 for (i = 0; i < nprinters; i++)
145 dlg_listbox_add(ctrl, dlg, printer_get_name(pe, i));
146 printer_finish_enum(pe);
148 dlg_editbox_set(ctrl, dlg,
149 (*cfg->printer ? cfg->printer :
150 PRINTER_DISABLED_STRING));
151 dlg_update_done(ctrl, dlg);
152 } else if (event == EVENT_VALCHANGE) {
153 dlg_editbox_get(ctrl, dlg, cfg->printer, sizeof(cfg->printer));
154 if (!strcmp(cfg->printer, PRINTER_DISABLED_STRING))
155 *cfg->printer = '\0';
159 static void codepage_handler(union control *ctrl, void *dlg,
160 void *data, int event)
162 Config *cfg = (Config *)data;
163 if (event == EVENT_REFRESH) {
166 dlg_update_start(ctrl, dlg);
167 strcpy(cfg->line_codepage,
168 cp_name(decode_codepage(cfg->line_codepage)));
169 dlg_listbox_clear(ctrl, dlg);
170 for (i = 0; (cp = cp_enumerate(i)) != NULL; i++)
171 dlg_listbox_add(ctrl, dlg, cp);
172 dlg_editbox_set(ctrl, dlg, cfg->line_codepage);
173 dlg_update_done(ctrl, dlg);
174 } else if (event == EVENT_VALCHANGE) {
175 dlg_editbox_get(ctrl, dlg, cfg->line_codepage,
176 sizeof(cfg->line_codepage));
177 strcpy(cfg->line_codepage,
178 cp_name(decode_codepage(cfg->line_codepage)));
182 static void sshbug_handler(union control *ctrl, void *dlg,
183 void *data, int event)
185 if (event == EVENT_REFRESH) {
186 dlg_update_start(ctrl, dlg);
187 dlg_listbox_clear(ctrl, dlg);
188 dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO);
189 dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF);
190 dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON);
191 switch (*(int *)ATOFFSET(data, ctrl->listbox.context.i)) {
192 case AUTO: dlg_listbox_select(ctrl, dlg, 0); break;
193 case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 1); break;
194 case FORCE_ON: dlg_listbox_select(ctrl, dlg, 2); break;
196 dlg_update_done(ctrl, dlg);
197 } else if (event == EVENT_SELCHANGE) {
198 int i = dlg_listbox_index(ctrl, dlg);
202 i = dlg_listbox_getid(ctrl, dlg, i);
203 *(int *)ATOFFSET(data, ctrl->listbox.context.i) = i;
207 #define SAVEDSESSION_LEN 2048
209 struct sessionsaver_data {
210 union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
211 union control *okbutton, *cancelbutton;
212 struct sesslist *sesslist;
216 * Helper function to load the session selected in the list box, if
217 * any, as this is done in more than one place below. Returns 0 for
220 static int load_selected_session(struct sessionsaver_data *ssd,
222 void *dlg, Config *cfg)
224 int i = dlg_listbox_index(ssd->listbox, dlg);
230 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
231 load_settings(ssd->sesslist->sessions[i], !isdef, cfg);
233 strncpy(savedsession, ssd->sesslist->sessions[i],
235 savedsession[SAVEDSESSION_LEN-1] = '\0';
237 savedsession[0] = '\0';
239 dlg_refresh(NULL, dlg);
240 /* Restore the selection, which might have been clobbered by
241 * changing the value of the edit box. */
242 dlg_listbox_select(ssd->listbox, dlg, i);
246 static void sessionsaver_handler(union control *ctrl, void *dlg,
247 void *data, int event)
249 Config *cfg = (Config *)data;
250 struct sessionsaver_data *ssd =
251 (struct sessionsaver_data *)ctrl->generic.context.p;
255 * The first time we're called in a new dialog, we must
256 * allocate space to store the current contents of the saved
257 * session edit box (since it must persist even when we switch
258 * panels, but is not part of the Config).
260 if (!dlg_get_privdata(ssd->editbox, dlg)) {
261 savedsession = (char *)
262 dlg_alloc_privdata(ssd->editbox, dlg, SAVEDSESSION_LEN);
263 savedsession[0] = '\0';
265 savedsession = dlg_get_privdata(ssd->editbox, dlg);
268 if (event == EVENT_REFRESH) {
269 if (ctrl == ssd->editbox) {
270 dlg_editbox_set(ctrl, dlg, savedsession);
271 } else if (ctrl == ssd->listbox) {
273 dlg_update_start(ctrl, dlg);
274 dlg_listbox_clear(ctrl, dlg);
275 for (i = 0; i < ssd->sesslist->nsessions; i++)
276 dlg_listbox_add(ctrl, dlg, ssd->sesslist->sessions[i]);
277 dlg_update_done(ctrl, dlg);
279 } else if (event == EVENT_VALCHANGE) {
280 if (ctrl == ssd->editbox) {
281 dlg_editbox_get(ctrl, dlg, savedsession,
284 } else if (event == EVENT_ACTION) {
285 if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) {
287 * The user has double-clicked a session, or hit Load.
288 * We must load the selected session, and then
289 * terminate the configuration dialog _if_ there was a
290 * double-click on the list box _and_ that session
291 * contains a hostname.
293 if (load_selected_session(ssd, savedsession, dlg, cfg) &&
294 (ctrl == ssd->listbox && cfg->host[0])) {
295 dlg_end(dlg, 1); /* it's all over, and succeeded */
297 } else if (ctrl == ssd->savebutton) {
298 int isdef = !strcmp(savedsession, "Default Settings");
299 if (!savedsession[0]) {
300 int i = dlg_listbox_index(ssd->listbox, dlg);
305 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
307 strncpy(savedsession, ssd->sesslist->sessions[i],
309 savedsession[SAVEDSESSION_LEN-1] = '\0';
311 savedsession[0] = '\0';
315 char *errmsg = save_settings(savedsession, !isdef, cfg);
317 dlg_error_msg(dlg, errmsg);
321 get_sesslist(ssd->sesslist, FALSE);
322 get_sesslist(ssd->sesslist, TRUE);
323 dlg_refresh(ssd->editbox, dlg);
324 dlg_refresh(ssd->listbox, dlg);
325 } else if (ctrl == ssd->delbutton) {
326 int i = dlg_listbox_index(ssd->listbox, dlg);
330 del_settings(ssd->sesslist->sessions[i]);
331 get_sesslist(ssd->sesslist, FALSE);
332 get_sesslist(ssd->sesslist, TRUE);
333 dlg_refresh(ssd->listbox, dlg);
335 } else if (ctrl == ssd->okbutton) {
337 * Annoying special case. If the `Open' button is
338 * pressed while no host name is currently set, _and_
339 * the session list previously had the focus, _and_
340 * there was a session selected in that which had a
341 * valid host name in it, then load it and go.
343 if (dlg_last_focused(ctrl, dlg) == ssd->listbox && !*cfg->host) {
345 if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) {
349 /* If at this point we have a valid session, go! */
351 *cfg = cfg2; /* structure copy */
358 * Otherwise, do the normal thing: if we have a valid
359 * session, get going.
365 } else if (ctrl == ssd->cancelbutton) {
371 struct charclass_data {
372 union control *listbox, *editbox, *button;
375 static void charclass_handler(union control *ctrl, void *dlg,
376 void *data, int event)
378 Config *cfg = (Config *)data;
379 struct charclass_data *ccd =
380 (struct charclass_data *)ctrl->generic.context.p;
382 if (event == EVENT_REFRESH) {
383 if (ctrl == ccd->listbox) {
385 dlg_update_start(ctrl, dlg);
386 dlg_listbox_clear(ctrl, dlg);
387 for (i = 0; i < 128; i++) {
389 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
390 (i >= 0x21 && i != 0x7F) ? i : ' ', cfg->wordness[i]);
391 dlg_listbox_add(ctrl, dlg, str);
393 dlg_update_done(ctrl, dlg);
395 } else if (event == EVENT_ACTION) {
396 if (ctrl == ccd->button) {
399 dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str));
401 for (i = 0; i < 128; i++) {
402 if (dlg_listbox_issel(ccd->listbox, dlg, i))
403 cfg->wordness[i] = n;
405 dlg_refresh(ccd->listbox, dlg);
411 union control *listbox, *redit, *gedit, *bedit, *button;
414 static const char *const colours[] = {
415 "Default Foreground", "Default Bold Foreground",
416 "Default Background", "Default Bold Background",
417 "Cursor Text", "Cursor Colour",
418 "ANSI Black", "ANSI Black Bold",
419 "ANSI Red", "ANSI Red Bold",
420 "ANSI Green", "ANSI Green Bold",
421 "ANSI Yellow", "ANSI Yellow Bold",
422 "ANSI Blue", "ANSI Blue Bold",
423 "ANSI Magenta", "ANSI Magenta Bold",
424 "ANSI Cyan", "ANSI Cyan Bold",
425 "ANSI White", "ANSI White Bold"
428 static void colour_handler(union control *ctrl, void *dlg,
429 void *data, int event)
431 Config *cfg = (Config *)data;
432 struct colour_data *cd =
433 (struct colour_data *)ctrl->generic.context.p;
434 int update = FALSE, r, g, b;
436 if (event == EVENT_REFRESH) {
437 if (ctrl == cd->listbox) {
439 dlg_update_start(ctrl, dlg);
440 dlg_listbox_clear(ctrl, dlg);
441 for (i = 0; i < lenof(colours); i++)
442 dlg_listbox_add(ctrl, dlg, colours[i]);
443 dlg_update_done(ctrl, dlg);
444 dlg_editbox_set(cd->redit, dlg, "");
445 dlg_editbox_set(cd->gedit, dlg, "");
446 dlg_editbox_set(cd->bedit, dlg, "");
448 } else if (event == EVENT_SELCHANGE) {
449 if (ctrl == cd->listbox) {
450 /* The user has selected a colour. Update the RGB text. */
451 int i = dlg_listbox_index(ctrl, dlg);
456 r = cfg->colours[i][0];
457 g = cfg->colours[i][1];
458 b = cfg->colours[i][2];
461 } else if (event == EVENT_VALCHANGE) {
462 if (ctrl == cd->redit || ctrl == cd->gedit || ctrl == cd->bedit) {
463 /* The user has changed the colour using the edit boxes. */
467 dlg_editbox_get(ctrl, dlg, buf, lenof(buf));
468 cval = atoi(buf) & 255;
470 i = dlg_listbox_index(cd->listbox, dlg);
472 if (ctrl == cd->redit)
473 cfg->colours[i][0] = cval;
474 else if (ctrl == cd->gedit)
475 cfg->colours[i][1] = cval;
476 else if (ctrl == cd->bedit)
477 cfg->colours[i][2] = cval;
480 } else if (event == EVENT_ACTION) {
481 if (ctrl == cd->button) {
482 int i = dlg_listbox_index(cd->listbox, dlg);
488 * Start a colour selector, which will send us an
489 * EVENT_CALLBACK when it's finished and allow us to
490 * pick up the results.
492 dlg_coloursel_start(ctrl, dlg,
497 } else if (event == EVENT_CALLBACK) {
498 if (ctrl == cd->button) {
499 int i = dlg_listbox_index(cd->listbox, dlg);
501 * Collect the results of the colour selector. Will
502 * return nonzero on success, or zero if the colour
503 * selector did nothing (user hit Cancel, for example).
505 if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
506 cfg->colours[i][0] = r;
507 cfg->colours[i][1] = g;
508 cfg->colours[i][2] = b;
516 sprintf(buf, "%d", r); dlg_editbox_set(cd->redit, dlg, buf);
517 sprintf(buf, "%d", g); dlg_editbox_set(cd->gedit, dlg, buf);
518 sprintf(buf, "%d", b); dlg_editbox_set(cd->bedit, dlg, buf);
522 struct environ_data {
523 union control *varbox, *valbox, *addbutton, *rembutton, *listbox;
526 static void environ_handler(union control *ctrl, void *dlg,
527 void *data, int event)
529 Config *cfg = (Config *)data;
530 struct environ_data *ed =
531 (struct environ_data *)ctrl->generic.context.p;
533 if (event == EVENT_REFRESH) {
534 if (ctrl == ed->listbox) {
535 char *p = cfg->environmt;
536 dlg_update_start(ctrl, dlg);
537 dlg_listbox_clear(ctrl, dlg);
539 dlg_listbox_add(ctrl, dlg, p);
542 dlg_update_done(ctrl, dlg);
544 } else if (event == EVENT_ACTION) {
545 if (ctrl == ed->addbutton) {
546 char str[sizeof(cfg->environmt)];
548 dlg_editbox_get(ed->varbox, dlg, str, sizeof(str)-1);
553 p = str + strlen(str);
555 dlg_editbox_get(ed->valbox, dlg, p, sizeof(str)-1 - (p - str));
566 if ((p - cfg->environmt) + strlen(str) + 2 <
567 sizeof(cfg->environmt)) {
569 p[strlen(str) + 1] = '\0';
570 dlg_listbox_add(ed->listbox, dlg, str);
571 dlg_editbox_set(ed->varbox, dlg, "");
572 dlg_editbox_set(ed->valbox, dlg, "");
574 dlg_error_msg(dlg, "Environment too big");
576 } else if (ctrl == ed->rembutton) {
577 int i = dlg_listbox_index(ed->listbox, dlg);
583 dlg_listbox_del(ed->listbox, dlg, i);
611 struct portfwd_data {
612 union control *addbutton, *rembutton, *listbox;
613 union control *sourcebox, *destbox, *direction;
616 static void portfwd_handler(union control *ctrl, void *dlg,
617 void *data, int event)
619 Config *cfg = (Config *)data;
620 struct portfwd_data *pfd =
621 (struct portfwd_data *)ctrl->generic.context.p;
623 if (event == EVENT_REFRESH) {
624 if (ctrl == pfd->listbox) {
625 char *p = cfg->portfwd;
626 dlg_update_start(ctrl, dlg);
627 dlg_listbox_clear(ctrl, dlg);
629 dlg_listbox_add(ctrl, dlg, p);
632 dlg_update_done(ctrl, dlg);
633 } else if (ctrl == pfd->direction) {
637 dlg_radiobutton_set(ctrl, dlg, 0);
639 } else if (event == EVENT_ACTION) {
640 if (ctrl == pfd->addbutton) {
641 char str[sizeof(cfg->portfwd)];
643 int whichbutton = dlg_radiobutton_get(pfd->direction, dlg);
644 if (whichbutton == 0)
646 else if (whichbutton == 1)
650 dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
652 dlg_error_msg(dlg, "You need to specify a source port number");
655 p = str + strlen(str);
658 dlg_editbox_get(pfd->destbox, dlg, p,
659 sizeof(str)-1 - (p - str));
660 if (!*p || !strchr(p, ':')) {
662 "You need to specify a destination address\n"
663 "in the form \"host.name:port\"");
674 if ((p - cfg->portfwd) + strlen(str) + 2 <
675 sizeof(cfg->portfwd)) {
677 p[strlen(str) + 1] = '\0';
678 dlg_listbox_add(pfd->listbox, dlg, str);
679 dlg_editbox_set(pfd->sourcebox, dlg, "");
680 dlg_editbox_set(pfd->destbox, dlg, "");
682 dlg_error_msg(dlg, "Too many forwardings");
684 } else if (ctrl == pfd->rembutton) {
685 int i = dlg_listbox_index(pfd->listbox, dlg);
691 dlg_listbox_del(pfd->listbox, dlg, i);
719 void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
720 int midsession, int protocol)
722 struct controlset *s;
723 struct sessionsaver_data *ssd;
724 struct charclass_data *ccd;
725 struct colour_data *cd;
726 struct environ_data *ed;
727 struct portfwd_data *pfd;
730 ssd = (struct sessionsaver_data *)
731 ctrl_alloc(b, sizeof(struct sessionsaver_data));
732 ssd->sesslist = (midsession ? NULL : sesslist);
735 * The standard panel that appears at the bottom of all panels:
736 * Open, Cancel, Apply etc.
738 s = ctrl_getset(b, "", "", "");
739 ctrl_columns(s, 5, 20, 20, 20, 20, 20);
740 ssd->okbutton = ctrl_pushbutton(s,
741 (midsession ? "Apply" : "Open"),
742 (char)(midsession ? 'a' : 'o'),
744 sessionsaver_handler, P(ssd));
745 ssd->okbutton->button.isdefault = TRUE;
746 ssd->okbutton->generic.column = 3;
747 ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help),
748 sessionsaver_handler, P(ssd));
749 ssd->cancelbutton->button.iscancel = TRUE;
750 ssd->cancelbutton->generic.column = 4;
751 /* We carefully don't close the 5-column part, so that platform-
752 * specific add-ons can put extra buttons alongside Open and Cancel. */
757 ctrl_settitle(b, "Session", "Basic options for your PuTTY session");
760 s = ctrl_getset(b, "Session", "hostport",
761 "Specify your connection by host name or IP address");
762 ctrl_columns(s, 2, 75, 25);
763 c = ctrl_editbox(s, "Host Name (or IP address)", 'n', 100,
764 HELPCTX(session_hostname),
765 dlg_stdeditbox_handler, I(offsetof(Config,host)),
766 I(sizeof(((Config *)0)->host)));
767 c->generic.column = 0;
768 c = ctrl_editbox(s, "Port", 'p', 100, HELPCTX(session_hostname),
769 dlg_stdeditbox_handler,
770 I(offsetof(Config,port)), I(-1));
771 c->generic.column = 1;
772 ctrl_columns(s, 1, 100);
773 if (backends[3].name == NULL) {
774 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 3,
775 HELPCTX(session_hostname),
776 protocolbuttons_handler, P(c),
777 "Raw", 'r', I(PROT_RAW),
778 "Telnet", 't', I(PROT_TELNET),
779 "Rlogin", 'i', I(PROT_RLOGIN),
782 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 4,
783 HELPCTX(session_hostname),
784 protocolbuttons_handler, P(c),
785 "Raw", 'r', I(PROT_RAW),
786 "Telnet", 't', I(PROT_TELNET),
787 "Rlogin", 'i', I(PROT_RLOGIN),
788 "SSH", 's', I(PROT_SSH),
792 s = ctrl_getset(b, "Session", "savedsessions",
793 "Load, save or delete a stored session");
794 ctrl_columns(s, 2, 75, 25);
795 ssd->sesslist = sesslist;
796 ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
797 HELPCTX(session_saved),
798 sessionsaver_handler, P(ssd), P(NULL));
799 ssd->editbox->generic.column = 0;
800 /* Reset columns so that the buttons are alongside the list, rather
801 * than alongside that edit box. */
802 ctrl_columns(s, 1, 100);
803 ctrl_columns(s, 2, 75, 25);
804 ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
805 HELPCTX(session_saved),
806 sessionsaver_handler, P(ssd));
807 ssd->listbox->generic.column = 0;
808 ssd->listbox->listbox.height = 7;
809 ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l',
810 HELPCTX(session_saved),
811 sessionsaver_handler, P(ssd));
812 ssd->loadbutton->generic.column = 1;
813 ssd->savebutton = ctrl_pushbutton(s, "Save", 'v',
814 HELPCTX(session_saved),
815 sessionsaver_handler, P(ssd));
816 ssd->savebutton->generic.column = 1;
817 ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd',
818 HELPCTX(session_saved),
819 sessionsaver_handler, P(ssd));
820 ssd->delbutton->generic.column = 1;
821 ctrl_columns(s, 1, 100);
824 s = ctrl_getset(b, "Session", "otheropts", NULL);
825 c = ctrl_radiobuttons(s, "Close window on exit:", 'w', 4,
826 HELPCTX(session_coe),
827 dlg_stdradiobutton_handler,
828 I(offsetof(Config, close_on_exit)),
829 "Always", I(FORCE_ON),
830 "Never", I(FORCE_OFF),
831 "Only on clean exit", I(AUTO), NULL);
834 * The Session/Logging panel.
836 ctrl_settitle(b, "Session/Logging", "Options controlling session logging");
838 s = ctrl_getset(b, "Session/Logging", "main", NULL);
839 ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 1,
840 HELPCTX(logging_main),
841 dlg_stdradiobutton_handler, I(offsetof(Config, logtype)),
842 "Logging turned off completely", 't', I(LGTYP_NONE),
843 "Log printable output only", 'p', I(LGTYP_ASCII),
844 "Log all session output", 'l', I(LGTYP_DEBUG),
845 "Log SSH packet data", 's', I(LGTYP_PACKETS),
847 ctrl_filesel(s, "Log file name:", 'f',
848 NULL, TRUE, "Select session log file name",
849 HELPCTX(logging_filename),
850 dlg_stdfilesel_handler, I(offsetof(Config, logfilename)));
851 ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
852 " &T for time, and &H for host name)",
853 HELPCTX(logging_filename));
854 ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
855 HELPCTX(logging_exists),
856 dlg_stdradiobutton_handler, I(offsetof(Config,logxfovr)),
857 "Always overwrite it", I(LGXF_OVR),
858 "Always append to the end of it", I(LGXF_APN),
859 "Ask the user every time", I(LGXF_ASK), NULL);
862 * The Terminal panel.
864 ctrl_settitle(b, "Terminal", "Options controlling the terminal emulation");
866 s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
867 ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
868 HELPCTX(terminal_autowrap),
869 dlg_stdcheckbox_handler, I(offsetof(Config,wrap_mode)));
870 ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
871 HELPCTX(terminal_decom),
872 dlg_stdcheckbox_handler, I(offsetof(Config,dec_om)));
873 ctrl_checkbox(s, "Implicit CR in every LF", 'r',
874 HELPCTX(terminal_lfhascr),
875 dlg_stdcheckbox_handler, I(offsetof(Config,lfhascr)));
876 ctrl_checkbox(s, "Use background colour to erase screen", 'e',
877 HELPCTX(terminal_bce),
878 dlg_stdcheckbox_handler, I(offsetof(Config,bce)));
879 ctrl_checkbox(s, "Enable blinking text", 'n',
880 HELPCTX(terminal_blink),
881 dlg_stdcheckbox_handler, I(offsetof(Config,blinktext)));
882 ctrl_editbox(s, "Answerback to ^E:", 's', 100,
883 HELPCTX(terminal_answerback),
884 dlg_stdeditbox_handler, I(offsetof(Config,answerback)),
885 I(sizeof(((Config *)0)->answerback)));
887 s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
888 ctrl_radiobuttons(s, "Local echo:", 'l', 3,
889 HELPCTX(terminal_localecho),
890 dlg_stdradiobutton_handler,I(offsetof(Config,localecho)),
892 "Force on", I(FORCE_ON),
893 "Force off", I(FORCE_OFF), NULL);
894 ctrl_radiobuttons(s, "Local line editing:", 't', 3,
895 HELPCTX(terminal_localedit),
896 dlg_stdradiobutton_handler,I(offsetof(Config,localedit)),
898 "Force on", I(FORCE_ON),
899 "Force off", I(FORCE_OFF), NULL);
901 s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
902 ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100,
903 HELPCTX(terminal_printing),
904 printerbox_handler, P(NULL), P(NULL));
907 * The Terminal/Keyboard panel.
909 ctrl_settitle(b, "Terminal/Keyboard",
910 "Options controlling the effects of keys");
912 s = ctrl_getset(b, "Terminal/Keyboard", "mappings",
913 "Change the sequences sent by:");
914 ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
915 HELPCTX(keyboard_backspace),
916 dlg_stdradiobutton_handler,
917 I(offsetof(Config, bksp_is_delete)),
918 "Control-H", I(0), "Control-? (127)", I(1), NULL);
919 ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
920 HELPCTX(keyboard_homeend),
921 dlg_stdradiobutton_handler,
922 I(offsetof(Config, rxvt_homeend)),
923 "Standard", I(0), "rxvt", I(1), NULL);
924 ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3,
925 HELPCTX(keyboard_funkeys),
926 dlg_stdradiobutton_handler,
927 I(offsetof(Config, funky_type)),
928 "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2),
929 "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL);
931 s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad",
932 "Application keypad settings:");
933 ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
934 HELPCTX(keyboard_appcursor),
935 dlg_stdradiobutton_handler,
936 I(offsetof(Config, app_cursor)),
937 "Normal", I(0), "Application", I(1), NULL);
938 ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
939 HELPCTX(keyboard_appkeypad),
940 numeric_keypad_handler, P(NULL),
941 "Normal", I(0), "Application", I(1), "NetHack", I(2),
945 * The Terminal/Bell panel.
947 ctrl_settitle(b, "Terminal/Bell",
948 "Options controlling the terminal bell");
950 s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
951 ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
953 dlg_stdradiobutton_handler, I(offsetof(Config, beep)),
954 "None (bell disabled)", I(BELL_DISABLED),
955 "Make default system alert sound", I(BELL_DEFAULT),
956 "Visual bell (flash window)", I(BELL_VISUAL), NULL);
958 s = ctrl_getset(b, "Terminal/Bell", "overload",
959 "Control the bell overload behaviour");
960 ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
961 HELPCTX(bell_overload),
962 dlg_stdcheckbox_handler, I(offsetof(Config,bellovl)));
963 ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
964 HELPCTX(bell_overload),
965 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_n)), I(-1));
966 ctrl_editbox(s, "... in this many seconds", 't', 20,
967 HELPCTX(bell_overload),
968 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_t)),
970 ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
971 HELPCTX(bell_overload));
972 ctrl_editbox(s, "Seconds of silence required", 's', 20,
973 HELPCTX(bell_overload),
974 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_s)),
978 * The Terminal/Features panel.
980 ctrl_settitle(b, "Terminal/Features",
981 "Enabling and disabling advanced terminal features");
983 s = ctrl_getset(b, "Terminal/Features", "main", NULL);
984 ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
985 HELPCTX(features_application),
986 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_c)));
987 ctrl_checkbox(s, "Disable application keypad mode", 'k',
988 HELPCTX(features_application),
989 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_k)));
990 ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
991 HELPCTX(features_mouse),
992 dlg_stdcheckbox_handler, I(offsetof(Config,no_mouse_rep)));
993 ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
994 HELPCTX(features_resize),
995 dlg_stdcheckbox_handler,
996 I(offsetof(Config,no_remote_resize)));
997 ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
998 HELPCTX(features_altscreen),
999 dlg_stdcheckbox_handler, I(offsetof(Config,no_alt_screen)));
1000 ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
1001 HELPCTX(features_retitle),
1002 dlg_stdcheckbox_handler,
1003 I(offsetof(Config,no_remote_wintitle)));
1004 ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
1005 HELPCTX(features_dbackspace),
1006 dlg_stdcheckbox_handler, I(offsetof(Config,no_dbackspace)));
1007 ctrl_checkbox(s, "Disable remote-controlled character set configuration",
1008 'r', HELPCTX(features_charset), dlg_stdcheckbox_handler,
1009 I(offsetof(Config,no_remote_charset)));
1014 ctrl_settitle(b, "Window", "Options controlling PuTTY's window");
1016 s = ctrl_getset(b, "Window", "size", "Set the size of the window");
1017 ctrl_columns(s, 2, 50, 50);
1018 c = ctrl_editbox(s, "Rows", 'r', 100,
1019 HELPCTX(window_size),
1020 dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
1021 c->generic.column = 0;
1022 c = ctrl_editbox(s, "Columns", 'm', 100,
1023 HELPCTX(window_size),
1024 dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
1025 c->generic.column = 1;
1026 ctrl_columns(s, 1, 100);
1028 s = ctrl_getset(b, "Window", "scrollback",
1029 "Control the scrollback in the window");
1030 ctrl_editbox(s, "Lines of scrollback", 's', 50,
1031 HELPCTX(window_scrollback),
1032 dlg_stdeditbox_handler, I(offsetof(Config,savelines)), I(-1));
1033 ctrl_checkbox(s, "Display scrollbar", 'd',
1034 HELPCTX(window_scrollback),
1035 dlg_stdcheckbox_handler, I(offsetof(Config,scrollbar)));
1036 ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
1037 HELPCTX(window_scrollback),
1038 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_key)));
1039 ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
1040 HELPCTX(window_scrollback),
1041 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp)));
1042 ctrl_checkbox(s, "Push erased text into scrollback", 'e',
1043 HELPCTX(window_erased),
1044 dlg_stdcheckbox_handler,
1045 I(offsetof(Config,erase_to_scrollback)));
1048 * The Window/Appearance panel.
1050 ctrl_settitle(b, "Window/Appearance",
1051 "Configure the appearance of PuTTY's window");
1053 s = ctrl_getset(b, "Window/Appearance", "cursor",
1054 "Adjust the use of the cursor");
1055 ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
1056 HELPCTX(appearance_cursor),
1057 dlg_stdradiobutton_handler,
1058 I(offsetof(Config, cursor_type)),
1060 "Underline", 'u', I(1),
1061 "Vertical line", 'v', I(2), NULL);
1062 ctrl_checkbox(s, "Cursor blinks", 'b',
1063 HELPCTX(appearance_cursor),
1064 dlg_stdcheckbox_handler, I(offsetof(Config,blink_cur)));
1066 s = ctrl_getset(b, "Window/Appearance", "font",
1068 ctrl_fontsel(s, "Font used in the terminal window", 'n',
1069 HELPCTX(appearance_font),
1070 dlg_stdfontsel_handler, I(offsetof(Config, font)));
1072 s = ctrl_getset(b, "Window/Appearance", "mouse",
1073 "Adjust the use of the mouse pointer");
1074 ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
1075 HELPCTX(appearance_hidemouse),
1076 dlg_stdcheckbox_handler, I(offsetof(Config,hide_mouseptr)));
1078 s = ctrl_getset(b, "Window/Appearance", "border",
1079 "Adjust the window border");
1080 ctrl_editbox(s, "Gap between text and window edge:", NO_SHORTCUT, 20,
1081 HELPCTX(appearance_border),
1082 dlg_stdeditbox_handler,
1083 I(offsetof(Config,window_border)), I(-1));
1086 * The Window/Behaviour panel.
1088 ctrl_settitle(b, "Window/Behaviour",
1089 "Configure the behaviour of PuTTY's window");
1091 s = ctrl_getset(b, "Window/Behaviour", "title",
1092 "Adjust the behaviour of the window title");
1093 ctrl_editbox(s, "Window title:", 't', 100,
1094 HELPCTX(appearance_title),
1095 dlg_stdeditbox_handler, I(offsetof(Config,wintitle)),
1096 I(sizeof(((Config *)0)->wintitle)));
1097 ctrl_checkbox(s, "Separate window and icon titles", 'i',
1098 HELPCTX(appearance_title),
1099 dlg_stdcheckbox_handler,
1100 I(CHECKBOX_INVERT | offsetof(Config,win_name_always)));
1102 s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
1103 ctrl_checkbox(s, "Warn before closing window", 'w',
1104 HELPCTX(behaviour_closewarn),
1105 dlg_stdcheckbox_handler, I(offsetof(Config,warn_on_close)));
1108 * The Window/Translation panel.
1110 ctrl_settitle(b, "Window/Translation",
1111 "Options controlling character set translation");
1113 s = ctrl_getset(b, "Window/Translation", "trans",
1114 "Character set translation on received data");
1115 ctrl_combobox(s, "Received data assumed to be in which character set:",
1116 'r', 100, HELPCTX(translation_codepage),
1117 codepage_handler, P(NULL), P(NULL));
1119 s = ctrl_getset(b, "Window/Translation", "linedraw",
1120 "Adjust how PuTTY displays line drawing characters");
1121 ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1,
1122 HELPCTX(translation_linedraw),
1123 dlg_stdradiobutton_handler,
1124 I(offsetof(Config, vtmode)),
1125 "Font has XWindows encoding", 'x', I(VT_XWINDOWS),
1126 "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN),
1127 "Unicode mode", 'u', I(VT_UNICODE), NULL);
1130 * The Window/Selection panel.
1132 ctrl_settitle(b, "Window/Selection", "Options controlling copy and paste");
1134 s = ctrl_getset(b, "Window/Selection", "trans",
1135 "Translation of pasted characters");
1136 ctrl_checkbox(s, "Don't translate line drawing chars into +, - and |",'d',
1137 HELPCTX(selection_linedraw),
1138 dlg_stdcheckbox_handler, I(offsetof(Config,rawcnp)));
1140 s = ctrl_getset(b, "Window/Selection", "mouse",
1141 "Control use of mouse");
1142 ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
1143 HELPCTX(selection_shiftdrag),
1144 dlg_stdcheckbox_handler, I(offsetof(Config,mouse_override)));
1145 ctrl_radiobuttons(s,
1146 "Default selection mode (Alt+drag does the other one):",
1148 HELPCTX(selection_rect),
1149 dlg_stdradiobutton_handler,
1150 I(offsetof(Config, rect_select)),
1151 "Normal", 'n', I(0),
1152 "Rectangular block", 'r', I(1), NULL);
1154 s = ctrl_getset(b, "Window/Selection", "charclass",
1155 "Control the select-one-word-at-a-time mode");
1156 ccd = (struct charclass_data *)
1157 ctrl_alloc(b, sizeof(struct charclass_data));
1158 ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
1159 HELPCTX(selection_charclasses),
1160 charclass_handler, P(ccd));
1161 ccd->listbox->listbox.multisel = 1;
1162 ccd->listbox->listbox.ncols = 4;
1163 ccd->listbox->listbox.percentages = snewn(4, int);
1164 ccd->listbox->listbox.percentages[0] = 15;
1165 ccd->listbox->listbox.percentages[1] = 25;
1166 ccd->listbox->listbox.percentages[2] = 20;
1167 ccd->listbox->listbox.percentages[3] = 40;
1168 ctrl_columns(s, 2, 67, 33);
1169 ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
1170 HELPCTX(selection_charclasses),
1171 charclass_handler, P(ccd), P(NULL));
1172 ccd->editbox->generic.column = 0;
1173 ccd->button = ctrl_pushbutton(s, "Set", 's',
1174 HELPCTX(selection_charclasses),
1175 charclass_handler, P(ccd));
1176 ccd->button->generic.column = 1;
1177 ctrl_columns(s, 1, 100);
1180 * The Window/Colours panel.
1182 ctrl_settitle(b, "Window/Colours", "Options controlling use of colours");
1184 s = ctrl_getset(b, "Window/Colours", "general",
1185 "General options for colour usage");
1186 ctrl_checkbox(s, "Bolded text is a different colour", 'b',
1187 HELPCTX(colours_bold),
1188 dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour)));
1190 s = ctrl_getset(b, "Window/Colours", "adjust",
1191 "Adjust the precise colours PuTTY displays");
1192 ctrl_text(s, "Select a colour from the list, and then click the"
1193 " Modify button to change its appearance.",
1194 HELPCTX(colours_config));
1195 ctrl_columns(s, 2, 67, 33);
1196 cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data));
1197 cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u',
1198 HELPCTX(colours_config), colour_handler, P(cd));
1199 cd->listbox->generic.column = 0;
1200 cd->listbox->listbox.height = 7;
1201 c = ctrl_text(s, "RGB value:", HELPCTX(colours_config));
1202 c->generic.column = 1;
1203 cd->redit = ctrl_editbox(s, "Red", 'r', 50, HELPCTX(colours_config),
1204 colour_handler, P(cd), P(NULL));
1205 cd->redit->generic.column = 1;
1206 cd->gedit = ctrl_editbox(s, "Green", 'n', 50, HELPCTX(colours_config),
1207 colour_handler, P(cd), P(NULL));
1208 cd->gedit->generic.column = 1;
1209 cd->bedit = ctrl_editbox(s, "Blue", 'e', 50, HELPCTX(colours_config),
1210 colour_handler, P(cd), P(NULL));
1211 cd->bedit->generic.column = 1;
1212 cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config),
1213 colour_handler, P(cd));
1214 cd->button->generic.column = 1;
1215 ctrl_columns(s, 1, 100);
1218 * The Connection panel.
1220 ctrl_settitle(b, "Connection", "Options controlling the connection");
1223 s = ctrl_getset(b, "Connection", "data", "Data to send to the server");
1224 ctrl_editbox(s, "Terminal-type string", 't', 50,
1225 HELPCTX(connection_termtype),
1226 dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
1227 I(sizeof(((Config *)0)->termtype)));
1228 ctrl_editbox(s, "Auto-login username", 'u', 50,
1229 HELPCTX(connection_username),
1230 dlg_stdeditbox_handler, I(offsetof(Config,username)),
1231 I(sizeof(((Config *)0)->username)));
1234 s = ctrl_getset(b, "Connection", "keepalive",
1235 "Sending of null packets to keep session active");
1236 ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
1237 HELPCTX(connection_keepalive),
1238 dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
1242 s = ctrl_getset(b, "Connection", "tcp",
1243 "Low-level TCP connection options");
1244 ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)", 'n',
1245 HELPCTX(connection_nodelay),
1246 dlg_stdcheckbox_handler,
1247 I(offsetof(Config,tcp_nodelay)));
1252 * The Connection/Proxy panel.
1254 ctrl_settitle(b, "Connection/Proxy",
1255 "Options controlling proxy usage");
1257 s = ctrl_getset(b, "Connection/Proxy", "basics", "Proxy basics");
1258 ctrl_radiobuttons(s, "Proxy type:", NO_SHORTCUT, 4,
1259 HELPCTX(proxy_type),
1260 dlg_stdradiobutton_handler,
1261 I(offsetof(Config, proxy_type)),
1262 "None", 'n', I(PROXY_NONE),
1263 "HTTP", 't', I(PROXY_HTTP),
1264 "SOCKS", 's', I(PROXY_SOCKS),
1265 "Telnet", 'l', I(PROXY_TELNET),
1267 ctrl_columns(s, 2, 80, 20);
1268 c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
1269 HELPCTX(proxy_main),
1270 dlg_stdeditbox_handler,
1271 I(offsetof(Config,proxy_host)),
1272 I(sizeof(((Config *)0)->proxy_host)));
1273 c->generic.column = 0;
1274 c = ctrl_editbox(s, "Port", 'p', 100,
1275 HELPCTX(proxy_main),
1276 dlg_stdeditbox_handler,
1277 I(offsetof(Config,proxy_port)),
1279 c->generic.column = 1;
1280 ctrl_columns(s, 1, 100);
1281 ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
1282 HELPCTX(proxy_exclude),
1283 dlg_stdeditbox_handler,
1284 I(offsetof(Config,proxy_exclude_list)),
1285 I(sizeof(((Config *)0)->proxy_exclude_list)));
1286 ctrl_checkbox(s, "Consider proxying local host connections", 'x',
1287 HELPCTX(proxy_exclude),
1288 dlg_stdcheckbox_handler,
1289 I(offsetof(Config,even_proxy_localhost)));
1290 ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
1292 dlg_stdradiobutton_handler,
1293 I(offsetof(Config, proxy_dns)),
1296 "Yes", I(FORCE_ON), NULL);
1297 ctrl_editbox(s, "Username", 'u', 60,
1298 HELPCTX(proxy_auth),
1299 dlg_stdeditbox_handler,
1300 I(offsetof(Config,proxy_username)),
1301 I(sizeof(((Config *)0)->proxy_username)));
1302 c = ctrl_editbox(s, "Password", 'w', 60,
1303 HELPCTX(proxy_auth),
1304 dlg_stdeditbox_handler,
1305 I(offsetof(Config,proxy_password)),
1306 I(sizeof(((Config *)0)->proxy_password)));
1307 c->editbox.password = 1;
1309 s = ctrl_getset(b, "Connection/Proxy", "misc",
1310 "Miscellaneous proxy settings");
1311 ctrl_editbox(s, "Telnet command", 'm', 100,
1312 HELPCTX(proxy_command),
1313 dlg_stdeditbox_handler,
1314 I(offsetof(Config,proxy_telnet_command)),
1315 I(sizeof(((Config *)0)->proxy_telnet_command)));
1316 ctrl_radiobuttons(s, "SOCKS Version", 'v', 2,
1317 HELPCTX(proxy_socksver),
1318 dlg_stdradiobutton_handler,
1319 I(offsetof(Config, proxy_socks_version)),
1320 "Version 5", I(5), "Version 4", I(4), NULL);
1324 * The Telnet panel exists in the base config box, and in a
1325 * mid-session reconfig box _if_ we're using Telnet.
1327 if (!midsession || protocol == PROT_TELNET) {
1329 * The Connection/Telnet panel.
1331 ctrl_settitle(b, "Connection/Telnet",
1332 "Options controlling Telnet connections");
1335 s = ctrl_getset(b, "Connection/Telnet", "data",
1336 "Data to send to the server");
1337 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1338 HELPCTX(telnet_termspeed),
1339 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1340 I(sizeof(((Config *)0)->termspeed)));
1341 ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
1342 ctrl_columns(s, 2, 80, 20);
1343 ed = (struct environ_data *)
1344 ctrl_alloc(b, sizeof(struct environ_data));
1345 ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
1346 HELPCTX(telnet_environ),
1347 environ_handler, P(ed), P(NULL));
1348 ed->varbox->generic.column = 0;
1349 ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
1350 HELPCTX(telnet_environ),
1351 environ_handler, P(ed), P(NULL));
1352 ed->valbox->generic.column = 0;
1353 ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
1354 HELPCTX(telnet_environ),
1355 environ_handler, P(ed));
1356 ed->addbutton->generic.column = 1;
1357 ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1358 HELPCTX(telnet_environ),
1359 environ_handler, P(ed));
1360 ed->rembutton->generic.column = 1;
1361 ctrl_columns(s, 1, 100);
1362 ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1363 HELPCTX(telnet_environ),
1364 environ_handler, P(ed));
1365 ed->listbox->listbox.height = 3;
1366 ed->listbox->listbox.ncols = 2;
1367 ed->listbox->listbox.percentages = snewn(2, int);
1368 ed->listbox->listbox.percentages[0] = 30;
1369 ed->listbox->listbox.percentages[1] = 70;
1372 s = ctrl_getset(b, "Connection/Telnet", "protocol",
1373 "Telnet protocol adjustments");
1376 ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
1378 HELPCTX(telnet_oldenviron),
1379 dlg_stdradiobutton_handler,
1380 I(offsetof(Config, rfc_environ)),
1381 "BSD (commonplace)", 'b', I(0),
1382 "RFC 1408 (unusual)", 'f', I(1), NULL);
1383 ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
1384 HELPCTX(telnet_passive),
1385 dlg_stdradiobutton_handler,
1386 I(offsetof(Config, passive_telnet)),
1387 "Passive", I(1), "Active", I(0), NULL);
1389 ctrl_checkbox(s, "Keyboard sends telnet Backspace and Interrupt", 'k',
1390 HELPCTX(telnet_specialkeys),
1391 dlg_stdcheckbox_handler,
1392 I(offsetof(Config,telnet_keyboard)));
1393 ctrl_checkbox(s, "Return key sends telnet New Line instead of ^M",
1394 NO_SHORTCUT, HELPCTX(telnet_newline),
1395 dlg_stdcheckbox_handler,
1396 I(offsetof(Config,telnet_newline)));
1402 * The Connection/Rlogin panel.
1404 ctrl_settitle(b, "Connection/Rlogin",
1405 "Options controlling Rlogin connections");
1407 s = ctrl_getset(b, "Connection/Rlogin", "data",
1408 "Data to send to the server");
1409 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1410 HELPCTX(rlogin_termspeed),
1411 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1412 I(sizeof(((Config *)0)->termspeed)));
1413 ctrl_editbox(s, "Local username:", 'l', 50,
1414 HELPCTX(rlogin_localuser),
1415 dlg_stdeditbox_handler, I(offsetof(Config,localusername)),
1416 I(sizeof(((Config *)0)->localusername)));
1421 * All the SSH stuff is omitted in PuTTYtel.
1424 if (!midsession && backends[3].name != NULL) {
1427 * The Connection/SSH panel.
1429 ctrl_settitle(b, "Connection/SSH",
1430 "Options controlling SSH connections");
1432 s = ctrl_getset(b, "Connection/SSH", "data",
1433 "Data to send to the server");
1434 ctrl_editbox(s, "Remote command:", 'r', 100,
1435 HELPCTX(ssh_command),
1436 dlg_stdeditbox_handler, I(offsetof(Config,remote_cmd)),
1437 I(sizeof(((Config *)0)->remote_cmd)));
1439 s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
1440 ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
1442 dlg_stdcheckbox_handler,
1443 I(offsetof(Config,nopty)));
1444 ctrl_checkbox(s, "Enable compression", 'e',
1445 HELPCTX(ssh_compress),
1446 dlg_stdcheckbox_handler,
1447 I(offsetof(Config,compression)));
1448 ctrl_radiobuttons(s, "Preferred SSH protocol version:", NO_SHORTCUT, 4,
1449 HELPCTX(ssh_protocol),
1450 dlg_stdradiobutton_handler,
1451 I(offsetof(Config, sshprot)),
1452 "1 only", 'l', I(0),
1455 "2 only", 'n', I(3), NULL);
1457 s = ctrl_getset(b, "Connection/SSH", "encryption", "Encryption options");
1458 c = ctrl_draglist(s, "Encryption cipher selection policy:", 's',
1459 HELPCTX(ssh_ciphers),
1460 cipherlist_handler, P(NULL));
1461 c->listbox.height = 6;
1463 ctrl_checkbox(s, "Enable non-standard use of single-DES in SSH 2", 'i',
1464 HELPCTX(ssh_ciphers),
1465 dlg_stdcheckbox_handler,
1466 I(offsetof(Config,ssh2_des_cbc)));
1469 * The Connection/SSH/Auth panel.
1471 ctrl_settitle(b, "Connection/SSH/Auth",
1472 "Options controlling SSH authentication");
1474 s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
1475 "Authentication methods");
1476 ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH1)", 'm',
1477 HELPCTX(ssh_auth_tis),
1478 dlg_stdcheckbox_handler,
1479 I(offsetof(Config,try_tis_auth)));
1480 ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH2)",
1481 'i', HELPCTX(ssh_auth_ki),
1482 dlg_stdcheckbox_handler,
1483 I(offsetof(Config,try_ki_auth)));
1485 s = ctrl_getset(b, "Connection/SSH/Auth", "params",
1486 "Authentication parameters");
1487 ctrl_checkbox(s, "Allow agent forwarding", 'f',
1488 HELPCTX(ssh_auth_agentfwd),
1489 dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
1490 ctrl_checkbox(s, "Allow attempted changes of username in SSH2", 'u',
1491 HELPCTX(ssh_auth_changeuser),
1492 dlg_stdcheckbox_handler,
1493 I(offsetof(Config,change_username)));
1494 ctrl_filesel(s, "Private key file for authentication:", 'k',
1495 FILTER_KEY_FILES, FALSE, "Select private key file",
1496 HELPCTX(ssh_auth_privkey),
1497 dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
1500 * The Connection/SSH/Tunnels panel.
1502 ctrl_settitle(b, "Connection/SSH/Tunnels",
1503 "Options controlling SSH tunnelling");
1505 s = ctrl_getset(b, "Connection/SSH/Tunnels", "x11", "X11 forwarding");
1506 ctrl_checkbox(s, "Enable X11 forwarding", 'e',
1507 HELPCTX(ssh_tunnels_x11),
1508 dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
1509 ctrl_editbox(s, "X display location", 'x', 50,
1510 HELPCTX(ssh_tunnels_x11),
1511 dlg_stdeditbox_handler, I(offsetof(Config,x11_display)),
1512 I(sizeof(((Config *)0)->x11_display)));
1513 ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
1514 HELPCTX(ssh_tunnels_x11auth),
1515 dlg_stdradiobutton_handler,
1516 I(offsetof(Config, x11_auth)),
1517 "MIT-Magic-Cookie-1", I(X11_MIT),
1518 "XDM-Authorization-1", I(X11_XDM), NULL);
1520 s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
1522 ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
1523 HELPCTX(ssh_tunnels_portfwd_localhost),
1524 dlg_stdcheckbox_handler,
1525 I(offsetof(Config,lport_acceptall)));
1526 ctrl_checkbox(s, "Remote ports do the same (SSH v2 only)", 'p',
1527 HELPCTX(ssh_tunnels_portfwd_localhost),
1528 dlg_stdcheckbox_handler,
1529 I(offsetof(Config,rport_acceptall)));
1531 ctrl_columns(s, 3, 55, 20, 25);
1532 c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
1533 c->generic.column = COLUMN_FIELD(0,2);
1534 /* You want to select from the list, _then_ hit Remove. So tab order
1535 * should be that way round. */
1536 pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data));
1537 pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1538 HELPCTX(ssh_tunnels_portfwd),
1539 portfwd_handler, P(pfd));
1540 pfd->rembutton->generic.column = 2;
1541 pfd->rembutton->generic.tabdelay = 1;
1542 pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1543 HELPCTX(ssh_tunnels_portfwd),
1544 portfwd_handler, P(pfd));
1545 pfd->listbox->listbox.height = 3;
1546 pfd->listbox->listbox.ncols = 2;
1547 pfd->listbox->listbox.percentages = snewn(2, int);
1548 pfd->listbox->listbox.percentages[0] = 20;
1549 pfd->listbox->listbox.percentages[1] = 80;
1550 ctrl_tabdelay(s, pfd->rembutton);
1551 ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
1552 /* You want to enter source, destination and type, _then_ hit Add.
1553 * Again, we adjust the tab order to reflect this. */
1554 pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
1555 HELPCTX(ssh_tunnels_portfwd),
1556 portfwd_handler, P(pfd));
1557 pfd->addbutton->generic.column = 2;
1558 pfd->addbutton->generic.tabdelay = 1;
1559 pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40,
1560 HELPCTX(ssh_tunnels_portfwd),
1561 portfwd_handler, P(pfd), P(NULL));
1562 pfd->sourcebox->generic.column = 0;
1563 pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67,
1564 HELPCTX(ssh_tunnels_portfwd),
1565 portfwd_handler, P(pfd), P(NULL));
1566 pfd->direction = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
1567 HELPCTX(ssh_tunnels_portfwd),
1568 portfwd_handler, P(pfd),
1569 "Local", 'l', P(NULL),
1570 "Remote", 'm', P(NULL),
1571 "Dynamic", 'y', P(NULL),
1573 ctrl_tabdelay(s, pfd->addbutton);
1574 ctrl_columns(s, 1, 100);
1577 * The Connection/SSH/Bugs panel.
1579 ctrl_settitle(b, "Connection/SSH/Bugs",
1580 "Workarounds for SSH server bugs");
1582 s = ctrl_getset(b, "Connection/SSH/Bugs", "main",
1583 "Detection of known bugs in SSH servers");
1584 ctrl_droplist(s, "Chokes on SSH1 ignore messages", 'i', 20,
1585 HELPCTX(ssh_bugs_ignore1),
1586 sshbug_handler, I(offsetof(Config,sshbug_ignore1)));
1587 ctrl_droplist(s, "Refuses all SSH1 password camouflage", 's', 20,
1588 HELPCTX(ssh_bugs_plainpw1),
1589 sshbug_handler, I(offsetof(Config,sshbug_plainpw1)));
1590 ctrl_droplist(s, "Chokes on SSH1 RSA authentication", 'r', 20,
1591 HELPCTX(ssh_bugs_rsa1),
1592 sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
1593 ctrl_droplist(s, "Miscomputes SSH2 HMAC keys", 'm', 20,
1594 HELPCTX(ssh_bugs_hmac2),
1595 sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
1596 ctrl_droplist(s, "Miscomputes SSH2 encryption keys", 'e', 20,
1597 HELPCTX(ssh_bugs_derivekey2),
1598 sshbug_handler, I(offsetof(Config,sshbug_derivekey2)));
1599 ctrl_droplist(s, "Requires padding on SSH2 RSA signatures", 'p', 20,
1600 HELPCTX(ssh_bugs_rsapad2),
1601 sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
1602 ctrl_droplist(s, "Chokes on Diffie-Hellman group exchange", 'd', 20,
1603 HELPCTX(ssh_bugs_dhgex2),
1604 sshbug_handler, I(offsetof(Config,sshbug_dhgex2)));
1605 ctrl_droplist(s, "Misuses the session ID in PK auth", 'n', 20,
1606 HELPCTX(ssh_bugs_pksessid2),
1607 sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));