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);
136 dlg_listbox_clear(ctrl, dlg);
137 dlg_listbox_add(ctrl, dlg, PRINTER_DISABLED_STRING);
138 pe = printer_start_enum(&nprinters);
139 for (i = 0; i < nprinters; i++)
140 dlg_listbox_add(ctrl, dlg, printer_get_name(pe, i));
141 printer_finish_enum(pe);
142 dlg_editbox_set(ctrl, dlg,
143 (*cfg->printer ? cfg->printer :
144 PRINTER_DISABLED_STRING));
145 dlg_update_done(ctrl, dlg);
146 } else if (event == EVENT_VALCHANGE) {
147 dlg_editbox_get(ctrl, dlg, cfg->printer, sizeof(cfg->printer));
148 if (!strcmp(cfg->printer, PRINTER_DISABLED_STRING))
149 *cfg->printer = '\0';
153 static void codepage_handler(union control *ctrl, void *dlg,
154 void *data, int event)
156 Config *cfg = (Config *)data;
157 if (event == EVENT_REFRESH) {
160 dlg_update_start(ctrl, dlg);
161 strcpy(cfg->line_codepage,
162 cp_name(decode_codepage(cfg->line_codepage)));
163 dlg_listbox_clear(ctrl, dlg);
164 for (i = 0; (cp = cp_enumerate(i)) != NULL; i++)
165 dlg_listbox_add(ctrl, dlg, cp);
166 dlg_editbox_set(ctrl, dlg, cfg->line_codepage);
167 dlg_update_done(ctrl, dlg);
168 } else if (event == EVENT_VALCHANGE) {
169 dlg_editbox_get(ctrl, dlg, cfg->line_codepage,
170 sizeof(cfg->line_codepage));
171 strcpy(cfg->line_codepage,
172 cp_name(decode_codepage(cfg->line_codepage)));
176 static void sshbug_handler(union control *ctrl, void *dlg,
177 void *data, int event)
179 if (event == EVENT_REFRESH) {
180 dlg_update_start(ctrl, dlg);
181 dlg_listbox_clear(ctrl, dlg);
182 dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO);
183 dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF);
184 dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON);
185 switch (*(int *)ATOFFSET(data, ctrl->listbox.context.i)) {
186 case AUTO: dlg_listbox_select(ctrl, dlg, 0); break;
187 case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 1); break;
188 case FORCE_ON: dlg_listbox_select(ctrl, dlg, 2); break;
190 dlg_update_done(ctrl, dlg);
191 } else if (event == EVENT_SELCHANGE) {
192 int i = dlg_listbox_index(ctrl, dlg);
196 i = dlg_listbox_getid(ctrl, dlg, i);
197 *(int *)ATOFFSET(data, ctrl->listbox.context.i) = i;
201 #define SAVEDSESSION_LEN 2048
203 struct sessionsaver_data {
204 union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
205 union control *okbutton, *cancelbutton;
206 struct sesslist *sesslist;
210 * Helper function to load the session selected in the list box, if
211 * any, as this is done in more than one place below. Returns 0 for
214 static int load_selected_session(struct sessionsaver_data *ssd,
216 void *dlg, Config *cfg)
218 int i = dlg_listbox_index(ssd->listbox, dlg);
224 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
225 load_settings(ssd->sesslist->sessions[i], !isdef, cfg);
227 strncpy(savedsession, ssd->sesslist->sessions[i],
229 savedsession[SAVEDSESSION_LEN-1] = '\0';
231 savedsession[0] = '\0';
233 dlg_refresh(NULL, dlg);
234 /* Restore the selection, which might have been clobbered by
235 * changing the value of the edit box. */
236 dlg_listbox_select(ssd->listbox, dlg, i);
240 static void sessionsaver_handler(union control *ctrl, void *dlg,
241 void *data, int event)
243 Config *cfg = (Config *)data;
244 struct sessionsaver_data *ssd =
245 (struct sessionsaver_data *)ctrl->generic.context.p;
249 * The first time we're called in a new dialog, we must
250 * allocate space to store the current contents of the saved
251 * session edit box (since it must persist even when we switch
252 * panels, but is not part of the Config).
254 if (!dlg_get_privdata(ssd->editbox, dlg)) {
255 savedsession = (char *)
256 dlg_alloc_privdata(ssd->editbox, dlg, SAVEDSESSION_LEN);
257 savedsession[0] = '\0';
259 savedsession = dlg_get_privdata(ssd->editbox, dlg);
262 if (event == EVENT_REFRESH) {
263 if (ctrl == ssd->editbox) {
264 dlg_editbox_set(ctrl, dlg, savedsession);
265 } else if (ctrl == ssd->listbox) {
267 dlg_update_start(ctrl, dlg);
268 dlg_listbox_clear(ctrl, dlg);
269 for (i = 0; i < ssd->sesslist->nsessions; i++)
270 dlg_listbox_add(ctrl, dlg, ssd->sesslist->sessions[i]);
271 dlg_update_done(ctrl, dlg);
273 } else if (event == EVENT_VALCHANGE) {
274 if (ctrl == ssd->editbox) {
275 dlg_editbox_get(ctrl, dlg, savedsession,
278 } else if (event == EVENT_ACTION) {
279 if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) {
281 * The user has double-clicked a session, or hit Load.
282 * We must load the selected session, and then
283 * terminate the configuration dialog _if_ there was a
284 * double-click on the list box _and_ that session
285 * contains a hostname.
287 if (load_selected_session(ssd, savedsession, dlg, cfg) &&
288 (ctrl == ssd->listbox && cfg->host[0])) {
289 dlg_end(dlg, 1); /* it's all over, and succeeded */
291 } else if (ctrl == ssd->savebutton) {
292 int isdef = !strcmp(savedsession, "Default Settings");
293 if (!savedsession[0]) {
294 int i = dlg_listbox_index(ssd->listbox, dlg);
299 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
301 strncpy(savedsession, ssd->sesslist->sessions[i],
303 savedsession[SAVEDSESSION_LEN-1] = '\0';
305 savedsession[0] = '\0';
308 save_settings(savedsession, !isdef, cfg);
309 get_sesslist(ssd->sesslist, FALSE);
310 get_sesslist(ssd->sesslist, TRUE);
311 dlg_refresh(ssd->editbox, dlg);
312 dlg_refresh(ssd->listbox, dlg);
313 } else if (ctrl == ssd->delbutton) {
314 int i = dlg_listbox_index(ssd->listbox, dlg);
318 del_settings(ssd->sesslist->sessions[i]);
319 get_sesslist(ssd->sesslist, FALSE);
320 get_sesslist(ssd->sesslist, TRUE);
321 dlg_refresh(ssd->listbox, dlg);
323 } else if (ctrl == ssd->okbutton) {
325 * Annoying special case. If the `Open' button is
326 * pressed while no host name is currently set, _and_
327 * the session list previously had the focus, _and_
328 * there was a session selected in that which had a
329 * valid host name in it, then load it and go.
331 if (dlg_last_focused(ctrl, dlg) == ssd->listbox && !*cfg->host) {
333 if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) {
337 /* If at this point we have a valid session, go! */
339 *cfg = cfg2; /* structure copy */
346 * Otherwise, do the normal thing: if we have a valid
347 * session, get going.
353 } else if (ctrl == ssd->cancelbutton) {
359 struct charclass_data {
360 union control *listbox, *editbox, *button;
363 static void charclass_handler(union control *ctrl, void *dlg,
364 void *data, int event)
366 Config *cfg = (Config *)data;
367 struct charclass_data *ccd =
368 (struct charclass_data *)ctrl->generic.context.p;
370 if (event == EVENT_REFRESH) {
371 if (ctrl == ccd->listbox) {
373 dlg_update_start(ctrl, dlg);
374 dlg_listbox_clear(ctrl, dlg);
375 for (i = 0; i < 128; i++) {
377 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
378 (i >= 0x21 && i != 0x7F) ? i : ' ', cfg->wordness[i]);
379 dlg_listbox_add(ctrl, dlg, str);
381 dlg_update_done(ctrl, dlg);
383 } else if (event == EVENT_ACTION) {
384 if (ctrl == ccd->button) {
387 dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str));
389 for (i = 0; i < 128; i++) {
390 if (dlg_listbox_issel(ccd->listbox, dlg, i))
391 cfg->wordness[i] = n;
393 dlg_refresh(ccd->listbox, dlg);
399 union control *listbox, *redit, *gedit, *bedit, *button;
402 static const char *const colours[] = {
403 "Default Foreground", "Default Bold Foreground",
404 "Default Background", "Default Bold Background",
405 "Cursor Text", "Cursor Colour",
406 "ANSI Black", "ANSI Black Bold",
407 "ANSI Red", "ANSI Red Bold",
408 "ANSI Green", "ANSI Green Bold",
409 "ANSI Yellow", "ANSI Yellow Bold",
410 "ANSI Blue", "ANSI Blue Bold",
411 "ANSI Magenta", "ANSI Magenta Bold",
412 "ANSI Cyan", "ANSI Cyan Bold",
413 "ANSI White", "ANSI White Bold"
416 static void colour_handler(union control *ctrl, void *dlg,
417 void *data, int event)
419 Config *cfg = (Config *)data;
420 struct colour_data *cd =
421 (struct colour_data *)ctrl->generic.context.p;
422 int update = FALSE, r, g, b;
424 if (event == EVENT_REFRESH) {
425 if (ctrl == cd->listbox) {
427 dlg_update_start(ctrl, dlg);
428 dlg_listbox_clear(ctrl, dlg);
429 for (i = 0; i < lenof(colours); i++)
430 dlg_listbox_add(ctrl, dlg, colours[i]);
431 dlg_update_done(ctrl, dlg);
432 dlg_editbox_set(cd->redit, dlg, "");
433 dlg_editbox_set(cd->gedit, dlg, "");
434 dlg_editbox_set(cd->bedit, dlg, "");
436 } else if (event == EVENT_SELCHANGE) {
437 if (ctrl == cd->listbox) {
438 /* The user has selected a colour. Update the RGB text. */
439 int i = dlg_listbox_index(ctrl, dlg);
444 r = cfg->colours[i][0];
445 g = cfg->colours[i][1];
446 b = cfg->colours[i][2];
449 } else if (event == EVENT_VALCHANGE) {
450 if (ctrl == cd->redit || ctrl == cd->gedit || ctrl == cd->bedit) {
451 /* The user has changed the colour using the edit boxes. */
455 dlg_editbox_get(ctrl, dlg, buf, lenof(buf));
456 cval = atoi(buf) & 255;
458 i = dlg_listbox_index(cd->listbox, dlg);
460 if (ctrl == cd->redit)
461 cfg->colours[i][0] = cval;
462 else if (ctrl == cd->gedit)
463 cfg->colours[i][1] = cval;
464 else if (ctrl == cd->bedit)
465 cfg->colours[i][2] = cval;
468 } else if (event == EVENT_ACTION) {
469 if (ctrl == cd->button) {
470 int i = dlg_listbox_index(cd->listbox, dlg);
476 * Start a colour selector, which will send us an
477 * EVENT_CALLBACK when it's finished and allow us to
478 * pick up the results.
480 dlg_coloursel_start(ctrl, dlg,
485 } else if (event == EVENT_CALLBACK) {
486 if (ctrl == cd->button) {
487 int i = dlg_listbox_index(cd->listbox, dlg);
489 * Collect the results of the colour selector. Will
490 * return nonzero on success, or zero if the colour
491 * selector did nothing (user hit Cancel, for example).
493 if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
494 cfg->colours[i][0] = r;
495 cfg->colours[i][1] = g;
496 cfg->colours[i][2] = b;
504 sprintf(buf, "%d", r); dlg_editbox_set(cd->redit, dlg, buf);
505 sprintf(buf, "%d", g); dlg_editbox_set(cd->gedit, dlg, buf);
506 sprintf(buf, "%d", b); dlg_editbox_set(cd->bedit, dlg, buf);
510 struct environ_data {
511 union control *varbox, *valbox, *addbutton, *rembutton, *listbox;
514 static void environ_handler(union control *ctrl, void *dlg,
515 void *data, int event)
517 Config *cfg = (Config *)data;
518 struct environ_data *ed =
519 (struct environ_data *)ctrl->generic.context.p;
521 if (event == EVENT_REFRESH) {
522 if (ctrl == ed->listbox) {
523 char *p = cfg->environmt;
524 dlg_update_start(ctrl, dlg);
525 dlg_listbox_clear(ctrl, dlg);
527 dlg_listbox_add(ctrl, dlg, p);
530 dlg_update_done(ctrl, dlg);
532 } else if (event == EVENT_ACTION) {
533 if (ctrl == ed->addbutton) {
534 char str[sizeof(cfg->environmt)];
536 dlg_editbox_get(ed->varbox, dlg, str, sizeof(str)-1);
541 p = str + strlen(str);
543 dlg_editbox_get(ed->valbox, dlg, p, sizeof(str)-1 - (p - str));
554 if ((p - cfg->environmt) + strlen(str) + 2 <
555 sizeof(cfg->environmt)) {
557 p[strlen(str) + 1] = '\0';
558 dlg_listbox_add(ed->listbox, dlg, str);
559 dlg_editbox_set(ed->varbox, dlg, "");
560 dlg_editbox_set(ed->valbox, dlg, "");
562 dlg_error_msg(dlg, "Environment too big");
564 } else if (ctrl == ed->rembutton) {
565 int i = dlg_listbox_index(ed->listbox, dlg);
571 dlg_listbox_del(ed->listbox, dlg, i);
599 struct portfwd_data {
600 union control *addbutton, *rembutton, *listbox;
601 union control *sourcebox, *destbox, *direction;
604 static void portfwd_handler(union control *ctrl, void *dlg,
605 void *data, int event)
607 Config *cfg = (Config *)data;
608 struct portfwd_data *pfd =
609 (struct portfwd_data *)ctrl->generic.context.p;
611 if (event == EVENT_REFRESH) {
612 if (ctrl == pfd->listbox) {
613 char *p = cfg->portfwd;
614 dlg_update_start(ctrl, dlg);
615 dlg_listbox_clear(ctrl, dlg);
617 dlg_listbox_add(ctrl, dlg, p);
620 dlg_update_done(ctrl, dlg);
621 } else if (ctrl == pfd->direction) {
625 dlg_radiobutton_set(ctrl, dlg, 0);
627 } else if (event == EVENT_ACTION) {
628 if (ctrl == pfd->addbutton) {
629 char str[sizeof(cfg->portfwd)];
631 if (dlg_radiobutton_get(pfd->direction, dlg) == 0)
635 dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
637 dlg_error_msg(dlg, "You need to specify a source port number");
640 p = str + strlen(str);
642 dlg_editbox_get(pfd->destbox, dlg, p, sizeof(str)-1 - (p - str));
643 if (!*p || !strchr(p, ':')) {
645 "You need to specify a destination address\n"
646 "in the form \"host.name:port\"");
655 if ((p - cfg->portfwd) + strlen(str) + 2 <
656 sizeof(cfg->portfwd)) {
658 p[strlen(str) + 1] = '\0';
659 dlg_listbox_add(pfd->listbox, dlg, str);
660 dlg_editbox_set(pfd->sourcebox, dlg, "");
661 dlg_editbox_set(pfd->destbox, dlg, "");
663 dlg_error_msg(dlg, "Too many forwardings");
665 } else if (ctrl == pfd->rembutton) {
666 int i = dlg_listbox_index(pfd->listbox, dlg);
672 dlg_listbox_del(pfd->listbox, dlg, i);
700 void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
701 int midsession, int protocol)
703 struct controlset *s;
704 struct sessionsaver_data *ssd;
705 struct charclass_data *ccd;
706 struct colour_data *cd;
707 struct environ_data *ed;
708 struct portfwd_data *pfd;
711 ssd = (struct sessionsaver_data *)
712 ctrl_alloc(b, sizeof(struct sessionsaver_data));
713 ssd->sesslist = (midsession ? NULL : sesslist);
716 * The standard panel that appears at the bottom of all panels:
717 * Open, Cancel, Apply etc.
719 s = ctrl_getset(b, "", "", "");
720 ctrl_columns(s, 5, 20, 20, 20, 20, 20);
721 ssd->okbutton = ctrl_pushbutton(s,
722 (midsession ? "Apply" : "Open"),
723 (char)(midsession ? 'a' : 'o'),
725 sessionsaver_handler, P(ssd));
726 ssd->okbutton->button.isdefault = TRUE;
727 ssd->okbutton->generic.column = 3;
728 ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help),
729 sessionsaver_handler, P(ssd));
730 ssd->cancelbutton->button.iscancel = TRUE;
731 ssd->cancelbutton->generic.column = 4;
732 /* We carefully don't close the 5-column part, so that platform-
733 * specific add-ons can put extra buttons alongside Open and Cancel. */
738 ctrl_settitle(b, "Session", "Basic options for your PuTTY session");
741 s = ctrl_getset(b, "Session", "hostport",
742 "Specify your connection by host name or IP address");
743 ctrl_columns(s, 2, 75, 25);
744 c = ctrl_editbox(s, "Host Name (or IP address)", 'n', 100,
745 HELPCTX(session_hostname),
746 dlg_stdeditbox_handler, I(offsetof(Config,host)),
747 I(sizeof(((Config *)0)->host)));
748 c->generic.column = 0;
749 c = ctrl_editbox(s, "Port", 'p', 100, HELPCTX(session_hostname),
750 dlg_stdeditbox_handler,
751 I(offsetof(Config,port)), I(-1));
752 c->generic.column = 1;
753 ctrl_columns(s, 1, 100);
754 if (backends[3].name == NULL) {
755 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 3,
756 HELPCTX(session_hostname),
757 protocolbuttons_handler, P(c),
758 "Raw", 'r', I(PROT_RAW),
759 "Telnet", 't', I(PROT_TELNET),
760 "Rlogin", 'i', I(PROT_RLOGIN),
763 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 4,
764 HELPCTX(session_hostname),
765 protocolbuttons_handler, P(c),
766 "Raw", 'r', I(PROT_RAW),
767 "Telnet", 't', I(PROT_TELNET),
768 "Rlogin", 'i', I(PROT_RLOGIN),
769 "SSH", 's', I(PROT_SSH),
773 s = ctrl_getset(b, "Session", "savedsessions",
774 "Load, save or delete a stored session");
775 ctrl_columns(s, 2, 75, 25);
776 ssd->sesslist = sesslist;
777 ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
778 HELPCTX(session_saved),
779 sessionsaver_handler, P(ssd), P(NULL));
780 ssd->editbox->generic.column = 0;
781 /* Reset columns so that the buttons are alongside the list, rather
782 * than alongside that edit box. */
783 ctrl_columns(s, 1, 100);
784 ctrl_columns(s, 2, 75, 25);
785 ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
786 HELPCTX(session_saved),
787 sessionsaver_handler, P(ssd));
788 ssd->listbox->generic.column = 0;
789 ssd->listbox->listbox.height = 7;
790 ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l',
791 HELPCTX(session_saved),
792 sessionsaver_handler, P(ssd));
793 ssd->loadbutton->generic.column = 1;
794 ssd->savebutton = ctrl_pushbutton(s, "Save", 'v',
795 HELPCTX(session_saved),
796 sessionsaver_handler, P(ssd));
797 ssd->savebutton->generic.column = 1;
798 ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd',
799 HELPCTX(session_saved),
800 sessionsaver_handler, P(ssd));
801 ssd->delbutton->generic.column = 1;
802 ctrl_columns(s, 1, 100);
805 s = ctrl_getset(b, "Session", "otheropts", NULL);
806 c = ctrl_radiobuttons(s, "Close window on exit:", 'w', 4,
807 HELPCTX(session_coe),
808 dlg_stdradiobutton_handler,
809 I(offsetof(Config, close_on_exit)),
810 "Always", I(FORCE_ON),
811 "Never", I(FORCE_OFF),
812 "Only on clean exit", I(AUTO), NULL);
815 * The Session/Logging panel.
817 ctrl_settitle(b, "Session/Logging", "Options controlling session logging");
819 s = ctrl_getset(b, "Session/Logging", "main", NULL);
820 ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 1,
821 HELPCTX(logging_main),
822 dlg_stdradiobutton_handler, I(offsetof(Config, logtype)),
823 "Logging turned off completely", 't', I(LGTYP_NONE),
824 "Log printable output only", 'p', I(LGTYP_ASCII),
825 "Log all session output", 'l', I(LGTYP_DEBUG),
826 "Log SSH packet data", 's', I(LGTYP_PACKETS),
828 ctrl_filesel(s, "Log file name:", 'f',
829 NULL, TRUE, "Select session log file name",
830 HELPCTX(logging_filename),
831 dlg_stdfilesel_handler, I(offsetof(Config, logfilename)));
832 ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
833 " &T for time, and &H for host name)",
834 HELPCTX(logging_filename));
835 ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
836 HELPCTX(logging_exists),
837 dlg_stdradiobutton_handler, I(offsetof(Config,logxfovr)),
838 "Always overwrite it", I(LGXF_OVR),
839 "Always append to the end of it", I(LGXF_APN),
840 "Ask the user every time", I(LGXF_ASK), NULL);
843 * The Terminal panel.
845 ctrl_settitle(b, "Terminal", "Options controlling the terminal emulation");
847 s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
848 ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
849 HELPCTX(terminal_autowrap),
850 dlg_stdcheckbox_handler, I(offsetof(Config,wrap_mode)));
851 ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
852 HELPCTX(terminal_decom),
853 dlg_stdcheckbox_handler, I(offsetof(Config,dec_om)));
854 ctrl_checkbox(s, "Implicit CR in every LF", 'r',
855 HELPCTX(terminal_lfhascr),
856 dlg_stdcheckbox_handler, I(offsetof(Config,lfhascr)));
857 ctrl_checkbox(s, "Use background colour to erase screen", 'e',
858 HELPCTX(terminal_bce),
859 dlg_stdcheckbox_handler, I(offsetof(Config,bce)));
860 ctrl_checkbox(s, "Enable blinking text", 'n',
861 HELPCTX(terminal_blink),
862 dlg_stdcheckbox_handler, I(offsetof(Config,blinktext)));
863 ctrl_editbox(s, "Answerback to ^E:", 's', 100,
864 HELPCTX(terminal_answerback),
865 dlg_stdeditbox_handler, I(offsetof(Config,answerback)),
866 I(sizeof(((Config *)0)->answerback)));
868 s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
869 ctrl_radiobuttons(s, "Local echo:", 'l', 3,
870 HELPCTX(terminal_localecho),
871 dlg_stdradiobutton_handler,I(offsetof(Config,localecho)),
873 "Force on", I(FORCE_ON),
874 "Force off", I(FORCE_OFF), NULL);
875 ctrl_radiobuttons(s, "Local line editing:", 't', 3,
876 HELPCTX(terminal_localedit),
877 dlg_stdradiobutton_handler,I(offsetof(Config,localedit)),
879 "Force on", I(FORCE_ON),
880 "Force off", I(FORCE_OFF), NULL);
882 s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
883 ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100,
884 HELPCTX(terminal_printing),
885 printerbox_handler, P(NULL), P(NULL));
888 * The Terminal/Keyboard panel.
890 ctrl_settitle(b, "Terminal/Keyboard",
891 "Options controlling the effects of keys");
893 s = ctrl_getset(b, "Terminal/Keyboard", "mappings",
894 "Change the sequences sent by:");
895 ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
896 HELPCTX(keyboard_backspace),
897 dlg_stdradiobutton_handler,
898 I(offsetof(Config, bksp_is_delete)),
899 "Control-H", I(0), "Control-? (127)", I(1), NULL);
900 ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
901 HELPCTX(keyboard_homeend),
902 dlg_stdradiobutton_handler,
903 I(offsetof(Config, rxvt_homeend)),
904 "Standard", I(0), "rxvt", I(1), NULL);
905 ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3,
906 HELPCTX(keyboard_funkeys),
907 dlg_stdradiobutton_handler,
908 I(offsetof(Config, funky_type)),
909 "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2),
910 "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL);
912 s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad",
913 "Application keypad settings:");
914 ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
915 HELPCTX(keyboard_appcursor),
916 dlg_stdradiobutton_handler,
917 I(offsetof(Config, app_cursor)),
918 "Normal", I(0), "Application", I(1), NULL);
919 ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
920 HELPCTX(keyboard_appkeypad),
921 numeric_keypad_handler, P(NULL),
922 "Normal", I(0), "Application", I(1), "NetHack", I(2),
926 * The Terminal/Bell panel.
928 ctrl_settitle(b, "Terminal/Bell",
929 "Options controlling the terminal bell");
931 s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
932 ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
934 dlg_stdradiobutton_handler, I(offsetof(Config, beep)),
935 "None (bell disabled)", I(BELL_DISABLED),
936 "Make default system alert sound", I(BELL_DEFAULT),
937 "Visual bell (flash window)", I(BELL_VISUAL), NULL);
939 s = ctrl_getset(b, "Terminal/Bell", "overload",
940 "Control the bell overload behaviour");
941 ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
942 HELPCTX(bell_overload),
943 dlg_stdcheckbox_handler, I(offsetof(Config,bellovl)));
944 ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
945 HELPCTX(bell_overload),
946 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_n)), I(-1));
947 ctrl_editbox(s, "... in this many seconds", 't', 20,
948 HELPCTX(bell_overload),
949 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_t)),
951 ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
952 HELPCTX(bell_overload));
953 ctrl_editbox(s, "Seconds of silence required", 's', 20,
954 HELPCTX(bell_overload),
955 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_s)),
959 * The Terminal/Features panel.
961 ctrl_settitle(b, "Terminal/Features",
962 "Enabling and disabling advanced terminal features");
964 s = ctrl_getset(b, "Terminal/Features", "main", NULL);
965 ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
966 HELPCTX(features_application),
967 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_c)));
968 ctrl_checkbox(s, "Disable application keypad mode", 'k',
969 HELPCTX(features_application),
970 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_k)));
971 ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
972 HELPCTX(features_mouse),
973 dlg_stdcheckbox_handler, I(offsetof(Config,no_mouse_rep)));
974 ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
975 HELPCTX(features_resize),
976 dlg_stdcheckbox_handler,
977 I(offsetof(Config,no_remote_resize)));
978 ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
979 HELPCTX(features_altscreen),
980 dlg_stdcheckbox_handler, I(offsetof(Config,no_alt_screen)));
981 ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
982 HELPCTX(features_retitle),
983 dlg_stdcheckbox_handler,
984 I(offsetof(Config,no_remote_wintitle)));
985 ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
986 HELPCTX(features_dbackspace),
987 dlg_stdcheckbox_handler, I(offsetof(Config,no_dbackspace)));
988 ctrl_checkbox(s, "Disable remote-controlled character set configuration",
989 'r', HELPCTX(features_charset), dlg_stdcheckbox_handler,
990 I(offsetof(Config,no_remote_charset)));
995 ctrl_settitle(b, "Window", "Options controlling PuTTY's window");
997 s = ctrl_getset(b, "Window", "size", "Set the size of the window");
998 ctrl_columns(s, 2, 50, 50);
999 c = ctrl_editbox(s, "Rows", 'r', 100,
1000 HELPCTX(window_size),
1001 dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
1002 c->generic.column = 0;
1003 c = ctrl_editbox(s, "Columns", 'm', 100,
1004 HELPCTX(window_size),
1005 dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
1006 c->generic.column = 1;
1007 ctrl_columns(s, 1, 100);
1009 s = ctrl_getset(b, "Window", "scrollback",
1010 "Control the scrollback in the window");
1011 ctrl_editbox(s, "Lines of scrollback", 's', 50,
1012 HELPCTX(window_scrollback),
1013 dlg_stdeditbox_handler, I(offsetof(Config,savelines)), I(-1));
1014 ctrl_checkbox(s, "Display scrollbar", 'd',
1015 HELPCTX(window_scrollback),
1016 dlg_stdcheckbox_handler, I(offsetof(Config,scrollbar)));
1017 ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
1018 HELPCTX(window_scrollback),
1019 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_key)));
1020 ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
1021 HELPCTX(window_scrollback),
1022 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp)));
1023 ctrl_checkbox(s, "Push erased text into scrollback", 'e',
1024 HELPCTX(window_erased),
1025 dlg_stdcheckbox_handler,
1026 I(offsetof(Config,erase_to_scrollback)));
1029 * The Window/Appearance panel.
1031 ctrl_settitle(b, "Window/Appearance",
1032 "Configure the appearance of PuTTY's window");
1034 s = ctrl_getset(b, "Window/Appearance", "cursor",
1035 "Adjust the use of the cursor");
1036 ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
1037 HELPCTX(appearance_cursor),
1038 dlg_stdradiobutton_handler,
1039 I(offsetof(Config, cursor_type)),
1041 "Underline", 'u', I(1),
1042 "Vertical line", 'v', I(2), NULL);
1043 ctrl_checkbox(s, "Cursor blinks", 'b',
1044 HELPCTX(appearance_cursor),
1045 dlg_stdcheckbox_handler, I(offsetof(Config,blink_cur)));
1047 s = ctrl_getset(b, "Window/Appearance", "font",
1049 ctrl_fontsel(s, "Font used in the terminal window", 'n',
1050 HELPCTX(appearance_font),
1051 dlg_stdfontsel_handler, I(offsetof(Config, font)));
1053 s = ctrl_getset(b, "Window/Appearance", "mouse",
1054 "Adjust the use of the mouse pointer");
1055 ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
1056 HELPCTX(appearance_hidemouse),
1057 dlg_stdcheckbox_handler, I(offsetof(Config,hide_mouseptr)));
1059 s = ctrl_getset(b, "Window/Appearance", "border",
1060 "Adjust the window border");
1061 ctrl_editbox(s, "Gap between text and window edge:", NO_SHORTCUT, 20,
1062 HELPCTX(appearance_border),
1063 dlg_stdeditbox_handler,
1064 I(offsetof(Config,window_border)), I(-1));
1067 * The Window/Behaviour panel.
1069 ctrl_settitle(b, "Window/Behaviour",
1070 "Configure the behaviour of PuTTY's window");
1072 s = ctrl_getset(b, "Window/Behaviour", "title",
1073 "Adjust the behaviour of the window title");
1074 ctrl_editbox(s, "Window title:", 't', 100,
1075 HELPCTX(appearance_title),
1076 dlg_stdeditbox_handler, I(offsetof(Config,wintitle)),
1077 I(sizeof(((Config *)0)->wintitle)));
1078 ctrl_checkbox(s, "Separate window and icon titles", 'i',
1079 HELPCTX(appearance_title),
1080 dlg_stdcheckbox_handler,
1081 I(CHECKBOX_INVERT | offsetof(Config,win_name_always)));
1083 s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
1084 ctrl_checkbox(s, "Warn before closing window", 'w',
1085 HELPCTX(behaviour_closewarn),
1086 dlg_stdcheckbox_handler, I(offsetof(Config,warn_on_close)));
1089 * The Window/Translation panel.
1091 ctrl_settitle(b, "Window/Translation",
1092 "Options controlling character set translation");
1094 s = ctrl_getset(b, "Window/Translation", "trans",
1095 "Character set translation on received data");
1096 ctrl_combobox(s, "Received data assumed to be in which character set:",
1097 'r', 100, HELPCTX(translation_codepage),
1098 codepage_handler, P(NULL), P(NULL));
1100 s = ctrl_getset(b, "Window/Translation", "linedraw",
1101 "Adjust how PuTTY displays line drawing characters");
1102 ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1,
1103 HELPCTX(translation_linedraw),
1104 dlg_stdradiobutton_handler,
1105 I(offsetof(Config, vtmode)),
1106 "Font has XWindows encoding", 'x', I(VT_XWINDOWS),
1107 "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN),
1108 "Unicode mode", 'u', I(VT_UNICODE), NULL);
1111 * The Window/Selection panel.
1113 ctrl_settitle(b, "Window/Selection", "Options controlling copy and paste");
1115 s = ctrl_getset(b, "Window/Selection", "trans",
1116 "Translation of pasted characters");
1117 ctrl_checkbox(s, "Don't translate line drawing chars into +, - and |",'d',
1118 HELPCTX(selection_linedraw),
1119 dlg_stdcheckbox_handler, I(offsetof(Config,rawcnp)));
1121 s = ctrl_getset(b, "Window/Selection", "mouse",
1122 "Control use of mouse");
1123 ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
1124 HELPCTX(selection_shiftdrag),
1125 dlg_stdcheckbox_handler, I(offsetof(Config,mouse_override)));
1126 ctrl_radiobuttons(s,
1127 "Default selection mode (Alt+drag does the other one):",
1129 HELPCTX(selection_rect),
1130 dlg_stdradiobutton_handler,
1131 I(offsetof(Config, rect_select)),
1132 "Normal", 'n', I(0),
1133 "Rectangular block", 'r', I(1), NULL);
1135 s = ctrl_getset(b, "Window/Selection", "charclass",
1136 "Control the select-one-word-at-a-time mode");
1137 ccd = (struct charclass_data *)
1138 ctrl_alloc(b, sizeof(struct charclass_data));
1139 ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
1140 HELPCTX(selection_charclasses),
1141 charclass_handler, P(ccd));
1142 ccd->listbox->listbox.multisel = 1;
1143 ccd->listbox->listbox.ncols = 4;
1144 ccd->listbox->listbox.percentages = snewn(4, int);
1145 ccd->listbox->listbox.percentages[0] = 15;
1146 ccd->listbox->listbox.percentages[1] = 25;
1147 ccd->listbox->listbox.percentages[2] = 20;
1148 ccd->listbox->listbox.percentages[3] = 40;
1149 ctrl_columns(s, 2, 67, 33);
1150 ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
1151 HELPCTX(selection_charclasses),
1152 charclass_handler, P(ccd), P(NULL));
1153 ccd->editbox->generic.column = 0;
1154 ccd->button = ctrl_pushbutton(s, "Set", 's',
1155 HELPCTX(selection_charclasses),
1156 charclass_handler, P(ccd));
1157 ccd->button->generic.column = 1;
1158 ctrl_columns(s, 1, 100);
1161 * The Window/Colours panel.
1163 ctrl_settitle(b, "Window/Colours", "Options controlling use of colours");
1165 s = ctrl_getset(b, "Window/Colours", "general",
1166 "General options for colour usage");
1167 ctrl_checkbox(s, "Bolded text is a different colour", 'b',
1168 HELPCTX(colours_bold),
1169 dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour)));
1171 s = ctrl_getset(b, "Window/Colours", "adjust",
1172 "Adjust the precise colours PuTTY displays");
1173 ctrl_text(s, "Select a colour from the list, and then click the"
1174 " Modify button to change its appearance.",
1175 HELPCTX(colours_config));
1176 ctrl_columns(s, 2, 67, 33);
1177 cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data));
1178 cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u',
1179 HELPCTX(colours_config), colour_handler, P(cd));
1180 cd->listbox->generic.column = 0;
1181 cd->listbox->listbox.height = 7;
1182 c = ctrl_text(s, "RGB value:", HELPCTX(colours_config));
1183 c->generic.column = 1;
1184 cd->redit = ctrl_editbox(s, "Red", 'r', 50, HELPCTX(colours_config),
1185 colour_handler, P(cd), P(NULL));
1186 cd->redit->generic.column = 1;
1187 cd->gedit = ctrl_editbox(s, "Green", 'n', 50, HELPCTX(colours_config),
1188 colour_handler, P(cd), P(NULL));
1189 cd->gedit->generic.column = 1;
1190 cd->bedit = ctrl_editbox(s, "Blue", 'e', 50, HELPCTX(colours_config),
1191 colour_handler, P(cd), P(NULL));
1192 cd->bedit->generic.column = 1;
1193 cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config),
1194 colour_handler, P(cd));
1195 cd->button->generic.column = 1;
1196 ctrl_columns(s, 1, 100);
1199 * The Connection panel.
1201 ctrl_settitle(b, "Connection", "Options controlling the connection");
1204 s = ctrl_getset(b, "Connection", "data", "Data to send to the server");
1205 ctrl_editbox(s, "Terminal-type string", 't', 50,
1206 HELPCTX(connection_termtype),
1207 dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
1208 I(sizeof(((Config *)0)->termtype)));
1209 ctrl_editbox(s, "Auto-login username", 'u', 50,
1210 HELPCTX(connection_username),
1211 dlg_stdeditbox_handler, I(offsetof(Config,username)),
1212 I(sizeof(((Config *)0)->username)));
1215 s = ctrl_getset(b, "Connection", "keepalive",
1216 "Sending of null packets to keep session active");
1217 ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
1218 HELPCTX(connection_keepalive),
1219 dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
1223 s = ctrl_getset(b, "Connection", "tcp",
1224 "Low-level TCP connection options");
1225 ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)", 'n',
1226 HELPCTX(connection_nodelay),
1227 dlg_stdcheckbox_handler,
1228 I(offsetof(Config,tcp_nodelay)));
1233 * The Connection/Proxy panel.
1235 ctrl_settitle(b, "Connection/Proxy",
1236 "Options controlling proxy usage");
1238 s = ctrl_getset(b, "Connection/Proxy", "basics", "Proxy basics");
1239 ctrl_radiobuttons(s, "Proxy type:", NO_SHORTCUT, 4,
1240 HELPCTX(proxy_type),
1241 dlg_stdradiobutton_handler,
1242 I(offsetof(Config, proxy_type)),
1243 "None", 'n', I(PROXY_NONE),
1244 "HTTP", 't', I(PROXY_HTTP),
1245 "SOCKS", 's', I(PROXY_SOCKS),
1246 "Telnet", 'l', I(PROXY_TELNET),
1248 ctrl_columns(s, 2, 80, 20);
1249 c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
1250 HELPCTX(proxy_main),
1251 dlg_stdeditbox_handler,
1252 I(offsetof(Config,proxy_host)),
1253 I(sizeof(((Config *)0)->proxy_host)));
1254 c->generic.column = 0;
1255 c = ctrl_editbox(s, "Port", 'p', 100,
1256 HELPCTX(proxy_main),
1257 dlg_stdeditbox_handler,
1258 I(offsetof(Config,proxy_port)),
1260 c->generic.column = 1;
1261 ctrl_columns(s, 1, 100);
1262 ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
1263 HELPCTX(proxy_exclude),
1264 dlg_stdeditbox_handler,
1265 I(offsetof(Config,proxy_exclude_list)),
1266 I(sizeof(((Config *)0)->proxy_exclude_list)));
1267 ctrl_checkbox(s, "Consider proxying local host connections", 'x',
1268 HELPCTX(proxy_exclude),
1269 dlg_stdcheckbox_handler,
1270 I(offsetof(Config,even_proxy_localhost)));
1271 ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
1273 dlg_stdradiobutton_handler,
1274 I(offsetof(Config, proxy_dns)),
1277 "Yes", I(FORCE_ON), NULL);
1278 ctrl_editbox(s, "Username", 'u', 60,
1279 HELPCTX(proxy_auth),
1280 dlg_stdeditbox_handler,
1281 I(offsetof(Config,proxy_username)),
1282 I(sizeof(((Config *)0)->proxy_username)));
1283 c = ctrl_editbox(s, "Password", 'w', 60,
1284 HELPCTX(proxy_auth),
1285 dlg_stdeditbox_handler,
1286 I(offsetof(Config,proxy_password)),
1287 I(sizeof(((Config *)0)->proxy_password)));
1288 c->editbox.password = 1;
1290 s = ctrl_getset(b, "Connection/Proxy", "misc",
1291 "Miscellaneous proxy settings");
1292 ctrl_editbox(s, "Telnet command", 'm', 100,
1293 HELPCTX(proxy_command),
1294 dlg_stdeditbox_handler,
1295 I(offsetof(Config,proxy_telnet_command)),
1296 I(sizeof(((Config *)0)->proxy_telnet_command)));
1297 ctrl_radiobuttons(s, "SOCKS Version", 'v', 2,
1298 HELPCTX(proxy_socksver),
1299 dlg_stdradiobutton_handler,
1300 I(offsetof(Config, proxy_socks_version)),
1301 "Version 5", I(5), "Version 4", I(4), NULL);
1305 * The Telnet panel exists in the base config box, and in a
1306 * mid-session reconfig box _if_ we're using Telnet.
1308 if (!midsession || protocol == PROT_TELNET) {
1310 * The Connection/Telnet panel.
1312 ctrl_settitle(b, "Connection/Telnet",
1313 "Options controlling Telnet connections");
1316 s = ctrl_getset(b, "Connection/Telnet", "data",
1317 "Data to send to the server");
1318 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1319 HELPCTX(telnet_termspeed),
1320 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1321 I(sizeof(((Config *)0)->termspeed)));
1322 ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
1323 ctrl_columns(s, 2, 80, 20);
1324 ed = (struct environ_data *)
1325 ctrl_alloc(b, sizeof(struct environ_data));
1326 ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
1327 HELPCTX(telnet_environ),
1328 environ_handler, P(ed), P(NULL));
1329 ed->varbox->generic.column = 0;
1330 ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
1331 HELPCTX(telnet_environ),
1332 environ_handler, P(ed), P(NULL));
1333 ed->valbox->generic.column = 0;
1334 ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
1335 HELPCTX(telnet_environ),
1336 environ_handler, P(ed));
1337 ed->addbutton->generic.column = 1;
1338 ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1339 HELPCTX(telnet_environ),
1340 environ_handler, P(ed));
1341 ed->rembutton->generic.column = 1;
1342 ctrl_columns(s, 1, 100);
1343 ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1344 HELPCTX(telnet_environ),
1345 environ_handler, P(ed));
1346 ed->listbox->listbox.height = 3;
1347 ed->listbox->listbox.ncols = 2;
1348 ed->listbox->listbox.percentages = snewn(2, int);
1349 ed->listbox->listbox.percentages[0] = 30;
1350 ed->listbox->listbox.percentages[1] = 70;
1353 s = ctrl_getset(b, "Connection/Telnet", "protocol",
1354 "Telnet protocol adjustments");
1357 ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
1359 HELPCTX(telnet_oldenviron),
1360 dlg_stdradiobutton_handler,
1361 I(offsetof(Config, rfc_environ)),
1362 "BSD (commonplace)", 'b', I(0),
1363 "RFC 1408 (unusual)", 'f', I(1), NULL);
1364 ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
1365 HELPCTX(telnet_passive),
1366 dlg_stdradiobutton_handler,
1367 I(offsetof(Config, passive_telnet)),
1368 "Passive", I(1), "Active", I(0), NULL);
1370 ctrl_checkbox(s, "Keyboard sends telnet Backspace and Interrupt", 'k',
1371 HELPCTX(telnet_specialkeys),
1372 dlg_stdcheckbox_handler,
1373 I(offsetof(Config,telnet_keyboard)));
1374 ctrl_checkbox(s, "Return key sends telnet New Line instead of ^M",
1375 NO_SHORTCUT, HELPCTX(telnet_newline),
1376 dlg_stdcheckbox_handler,
1377 I(offsetof(Config,telnet_newline)));
1383 * The Connection/Rlogin panel.
1385 ctrl_settitle(b, "Connection/Rlogin",
1386 "Options controlling Rlogin connections");
1388 s = ctrl_getset(b, "Connection/Rlogin", "data",
1389 "Data to send to the server");
1390 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1391 HELPCTX(rlogin_termspeed),
1392 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1393 I(sizeof(((Config *)0)->termspeed)));
1394 ctrl_editbox(s, "Local username:", 'l', 50,
1395 HELPCTX(rlogin_localuser),
1396 dlg_stdeditbox_handler, I(offsetof(Config,localusername)),
1397 I(sizeof(((Config *)0)->localusername)));
1402 * All the SSH stuff is omitted in PuTTYtel.
1405 if (!midsession && backends[3].name != NULL) {
1408 * The Connection/SSH panel.
1410 ctrl_settitle(b, "Connection/SSH",
1411 "Options controlling SSH connections");
1413 s = ctrl_getset(b, "Connection/SSH", "data",
1414 "Data to send to the server");
1415 ctrl_editbox(s, "Remote command:", 'r', 100,
1416 HELPCTX(ssh_command),
1417 dlg_stdeditbox_handler, I(offsetof(Config,remote_cmd)),
1418 I(sizeof(((Config *)0)->remote_cmd)));
1420 s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
1421 ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
1423 dlg_stdcheckbox_handler,
1424 I(offsetof(Config,nopty)));
1425 ctrl_checkbox(s, "Enable compression", 'e',
1426 HELPCTX(ssh_compress),
1427 dlg_stdcheckbox_handler,
1428 I(offsetof(Config,compression)));
1429 ctrl_radiobuttons(s, "Preferred SSH protocol version:", NO_SHORTCUT, 4,
1430 HELPCTX(ssh_protocol),
1431 dlg_stdradiobutton_handler,
1432 I(offsetof(Config, sshprot)),
1433 "1 only", 'l', I(0),
1436 "2 only", 'n', I(3), NULL);
1438 s = ctrl_getset(b, "Connection/SSH", "encryption", "Encryption options");
1439 c = ctrl_draglist(s, "Encryption cipher selection policy:", 's',
1440 HELPCTX(ssh_ciphers),
1441 cipherlist_handler, P(NULL));
1442 c->listbox.height = 6;
1444 ctrl_checkbox(s, "Enable non-standard use of single-DES in SSH 2", 'i',
1445 HELPCTX(ssh_ciphers),
1446 dlg_stdcheckbox_handler,
1447 I(offsetof(Config,ssh2_des_cbc)));
1450 * The Connection/SSH/Auth panel.
1452 ctrl_settitle(b, "Connection/SSH/Auth",
1453 "Options controlling SSH authentication");
1455 s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
1456 "Authentication methods");
1457 ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH1)", 'm',
1458 HELPCTX(ssh_auth_tis),
1459 dlg_stdcheckbox_handler,
1460 I(offsetof(Config,try_tis_auth)));
1461 ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH2)",
1462 'i', HELPCTX(ssh_auth_ki),
1463 dlg_stdcheckbox_handler,
1464 I(offsetof(Config,try_ki_auth)));
1466 s = ctrl_getset(b, "Connection/SSH/Auth", "params",
1467 "Authentication parameters");
1468 ctrl_checkbox(s, "Allow agent forwarding", 'f',
1469 HELPCTX(ssh_auth_agentfwd),
1470 dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
1471 ctrl_checkbox(s, "Allow attempted changes of username in SSH2", 'u',
1472 HELPCTX(ssh_auth_changeuser),
1473 dlg_stdcheckbox_handler,
1474 I(offsetof(Config,change_username)));
1475 ctrl_filesel(s, "Private key file for authentication:", 'k',
1476 FILTER_KEY_FILES, FALSE, "Select private key file",
1477 HELPCTX(ssh_auth_privkey),
1478 dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
1481 * The Connection/SSH/Tunnels panel.
1483 ctrl_settitle(b, "Connection/SSH/Tunnels",
1484 "Options controlling SSH tunnelling");
1486 s = ctrl_getset(b, "Connection/SSH/Tunnels", "x11", "X11 forwarding");
1487 ctrl_checkbox(s, "Enable X11 forwarding", 'e',
1488 HELPCTX(ssh_tunnels_x11),
1489 dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
1490 ctrl_editbox(s, "X display location", 'x', 50,
1491 HELPCTX(ssh_tunnels_x11),
1492 dlg_stdeditbox_handler, I(offsetof(Config,x11_display)),
1493 I(sizeof(((Config *)0)->x11_display)));
1494 ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
1495 HELPCTX(ssh_tunnels_x11auth),
1496 dlg_stdradiobutton_handler,
1497 I(offsetof(Config, x11_auth)),
1498 "MIT-Magic-Cookie-1", I(X11_MIT),
1499 "XDM-Authorization-1", I(X11_XDM), NULL);
1501 s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
1503 ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
1504 HELPCTX(ssh_tunnels_portfwd_localhost),
1505 dlg_stdcheckbox_handler,
1506 I(offsetof(Config,lport_acceptall)));
1507 ctrl_checkbox(s, "Remote ports do the same (SSH v2 only)", 'p',
1508 HELPCTX(ssh_tunnels_portfwd_localhost),
1509 dlg_stdcheckbox_handler,
1510 I(offsetof(Config,rport_acceptall)));
1512 ctrl_columns(s, 3, 55, 20, 25);
1513 c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
1514 c->generic.column = COLUMN_FIELD(0,2);
1515 /* You want to select from the list, _then_ hit Remove. So tab order
1516 * should be that way round. */
1517 pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data));
1518 pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1519 HELPCTX(ssh_tunnels_portfwd),
1520 portfwd_handler, P(pfd));
1521 pfd->rembutton->generic.column = 2;
1522 pfd->rembutton->generic.tabdelay = 1;
1523 pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1524 HELPCTX(ssh_tunnels_portfwd),
1525 portfwd_handler, P(pfd));
1526 pfd->listbox->listbox.height = 3;
1527 pfd->listbox->listbox.ncols = 2;
1528 pfd->listbox->listbox.percentages = snewn(2, int);
1529 pfd->listbox->listbox.percentages[0] = 20;
1530 pfd->listbox->listbox.percentages[1] = 80;
1531 ctrl_tabdelay(s, pfd->rembutton);
1532 ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
1533 /* You want to enter source, destination and type, _then_ hit Add.
1534 * Again, we adjust the tab order to reflect this. */
1535 pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
1536 HELPCTX(ssh_tunnels_portfwd),
1537 portfwd_handler, P(pfd));
1538 pfd->addbutton->generic.column = 2;
1539 pfd->addbutton->generic.tabdelay = 1;
1540 pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40,
1541 HELPCTX(ssh_tunnels_portfwd),
1542 portfwd_handler, P(pfd), P(NULL));
1543 pfd->sourcebox->generic.column = 0;
1544 pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67,
1545 HELPCTX(ssh_tunnels_portfwd),
1546 portfwd_handler, P(pfd), P(NULL));
1547 pfd->direction = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 2,
1548 HELPCTX(ssh_tunnels_portfwd),
1549 portfwd_handler, P(pfd),
1550 "Local", 'l', P(NULL),
1551 "Remote", 'm', P(NULL), NULL);
1552 ctrl_tabdelay(s, pfd->addbutton);
1553 ctrl_columns(s, 1, 100);
1556 * The Connection/SSH/Bugs panel.
1558 ctrl_settitle(b, "Connection/SSH/Bugs",
1559 "Workarounds for SSH server bugs");
1561 s = ctrl_getset(b, "Connection/SSH/Bugs", "main",
1562 "Detection of known bugs in SSH servers");
1563 ctrl_droplist(s, "Chokes on SSH1 ignore messages", 'i', 20,
1564 HELPCTX(ssh_bugs_ignore1),
1565 sshbug_handler, I(offsetof(Config,sshbug_ignore1)));
1566 ctrl_droplist(s, "Refuses all SSH1 password camouflage", 's', 20,
1567 HELPCTX(ssh_bugs_plainpw1),
1568 sshbug_handler, I(offsetof(Config,sshbug_plainpw1)));
1569 ctrl_droplist(s, "Chokes on SSH1 RSA authentication", 'r', 20,
1570 HELPCTX(ssh_bugs_rsa1),
1571 sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
1572 ctrl_droplist(s, "Miscomputes SSH2 HMAC keys", 'm', 20,
1573 HELPCTX(ssh_bugs_hmac2),
1574 sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
1575 ctrl_droplist(s, "Miscomputes SSH2 encryption keys", 'e', 20,
1576 HELPCTX(ssh_bugs_derivekey2),
1577 sshbug_handler, I(offsetof(Config,sshbug_derivekey2)));
1578 ctrl_droplist(s, "Requires padding on SSH2 RSA signatures", 'p', 20,
1579 HELPCTX(ssh_bugs_rsapad2),
1580 sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
1581 ctrl_droplist(s, "Chokes on Diffie-Hellman group exchange", 'd', 20,
1582 HELPCTX(ssh_bugs_dhgex2),
1583 sshbug_handler, I(offsetof(Config,sshbug_dhgex2)));
1584 ctrl_droplist(s, "Misuses the session ID in PK auth", 'n', 20,
1585 HELPCTX(ssh_bugs_pksessid2),
1586 sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));