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_addwithindex(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_addwithindex(ctrl, dlg, "Auto", AUTO);
183 dlg_listbox_addwithindex(ctrl, dlg, "Off", FORCE_OFF);
184 dlg_listbox_addwithindex(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 struct sessionsaver_data {
202 union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
203 union control *okbutton, *cancelbutton;
204 char savedsession[2048];
205 struct sesslist *sesslist;
209 * Helper function to load the session selected in the list box, if
210 * any, as this is done in more than one place below. Returns 0 for
213 static int load_selected_session(struct sessionsaver_data *ssd,
214 void *dlg, Config *cfg)
216 int i = dlg_listbox_index(ssd->listbox, dlg);
222 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
223 load_settings(ssd->sesslist->sessions[i], !isdef, cfg);
225 strncpy(ssd->savedsession, ssd->sesslist->sessions[i],
226 sizeof(ssd->savedsession));
227 ssd->savedsession[sizeof(ssd->savedsession)-1] = '\0';
229 ssd->savedsession[0] = '\0';
231 dlg_refresh(NULL, dlg);
232 /* Restore the selection, which might have been clobbered by
233 * changing the value of the edit box. */
234 dlg_listbox_select(ssd->listbox, dlg, i);
238 static void sessionsaver_handler(union control *ctrl, void *dlg,
239 void *data, int event)
241 Config *cfg = (Config *)data;
242 struct sessionsaver_data *ssd =
243 (struct sessionsaver_data *)ctrl->generic.context.p;
245 if (event == EVENT_REFRESH) {
246 if (ctrl == ssd->editbox) {
247 dlg_editbox_set(ctrl, dlg, ssd->savedsession);
248 } else if (ctrl == ssd->listbox) {
250 dlg_update_start(ctrl, dlg);
251 dlg_listbox_clear(ctrl, dlg);
252 for (i = 0; i < ssd->sesslist->nsessions; i++)
253 dlg_listbox_add(ctrl, dlg, ssd->sesslist->sessions[i]);
254 dlg_update_done(ctrl, dlg);
256 } else if (event == EVENT_VALCHANGE) {
257 if (ctrl == ssd->editbox) {
258 dlg_editbox_get(ctrl, dlg, ssd->savedsession,
259 sizeof(ssd->savedsession));
261 } else if (event == EVENT_ACTION) {
262 if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) {
264 * The user has double-clicked a session, or hit Load.
265 * We must load the selected session, and then
266 * terminate the configuration dialog _if_ there was a
267 * double-click on the list box _and_ that session
268 * contains a hostname.
270 if (load_selected_session(ssd, dlg, cfg) &&
271 (ctrl == ssd->listbox && cfg->host[0])) {
272 dlg_end(dlg, 1); /* it's all over, and succeeded */
274 } else if (ctrl == ssd->savebutton) {
275 int isdef = !strcmp(ssd->savedsession, "Default Settings");
276 if (!ssd->savedsession[0]) {
277 int i = dlg_listbox_index(ssd->listbox, dlg);
282 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
284 strncpy(ssd->savedsession, ssd->sesslist->sessions[i],
285 sizeof(ssd->savedsession));
286 ssd->savedsession[sizeof(ssd->savedsession)-1] = '\0';
288 ssd->savedsession[0] = '\0';
291 save_settings(ssd->savedsession, !isdef, cfg);
292 get_sesslist(ssd->sesslist, FALSE);
293 get_sesslist(ssd->sesslist, TRUE);
294 dlg_refresh(ssd->editbox, dlg);
295 dlg_refresh(ssd->listbox, dlg);
296 } else if (ctrl == ssd->delbutton) {
297 int i = dlg_listbox_index(ssd->listbox, dlg);
301 del_settings(ssd->sesslist->sessions[i]);
302 get_sesslist(ssd->sesslist, FALSE);
303 get_sesslist(ssd->sesslist, TRUE);
304 dlg_refresh(ssd->listbox, dlg);
306 } else if (ctrl == ssd->okbutton) {
308 * Annoying special case. If the `Open' button is
309 * pressed while no host name is currently set, _and_
310 * the session list previously had the focus, _and_
311 * there was a session selected in that which had a
312 * valid host name in it, then load it and go.
314 if (dlg_last_focused(dlg) == ssd->listbox && !*cfg->host) {
316 if (!load_selected_session(ssd, dlg, &cfg2)) {
320 /* If at this point we have a valid session, go! */
322 *cfg = cfg2; /* structure copy */
329 * Otherwise, do the normal thing: if we have a valid
330 * session, get going.
336 } else if (ctrl == ssd->cancelbutton) {
342 struct charclass_data {
343 union control *listbox, *editbox, *button;
346 static void charclass_handler(union control *ctrl, void *dlg,
347 void *data, int event)
349 Config *cfg = (Config *)data;
350 struct charclass_data *ccd =
351 (struct charclass_data *)ctrl->generic.context.p;
353 if (event == EVENT_REFRESH) {
354 if (ctrl == ccd->listbox) {
356 dlg_update_start(ctrl, dlg);
357 dlg_listbox_clear(ctrl, dlg);
358 for (i = 0; i < 128; i++) {
360 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
361 (i >= 0x21 && i != 0x7F) ? i : ' ', cfg->wordness[i]);
362 dlg_listbox_add(ctrl, dlg, str);
364 dlg_update_done(ctrl, dlg);
366 } else if (event == EVENT_ACTION) {
367 if (ctrl == ccd->button) {
370 dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str));
372 for (i = 0; i < 128; i++) {
373 if (dlg_listbox_issel(ccd->listbox, dlg, i))
374 cfg->wordness[i] = n;
376 dlg_refresh(ccd->listbox, dlg);
382 union control *listbox, *rgbtext, *button;
385 static const char *const colours[] = {
386 "Default Foreground", "Default Bold Foreground",
387 "Default Background", "Default Bold Background",
388 "Cursor Text", "Cursor Colour",
389 "ANSI Black", "ANSI Black Bold",
390 "ANSI Red", "ANSI Red Bold",
391 "ANSI Green", "ANSI Green Bold",
392 "ANSI Yellow", "ANSI Yellow Bold",
393 "ANSI Blue", "ANSI Blue Bold",
394 "ANSI Magenta", "ANSI Magenta Bold",
395 "ANSI Cyan", "ANSI Cyan Bold",
396 "ANSI White", "ANSI White Bold"
399 static void colour_handler(union control *ctrl, void *dlg,
400 void *data, int event)
402 Config *cfg = (Config *)data;
403 struct colour_data *cd =
404 (struct colour_data *)ctrl->generic.context.p;
405 int update = FALSE, r, g, b;
407 if (event == EVENT_REFRESH) {
408 if (ctrl == cd->listbox) {
410 dlg_update_start(ctrl, dlg);
411 dlg_listbox_clear(ctrl, dlg);
412 for (i = 0; i < lenof(colours); i++)
413 dlg_listbox_add(ctrl, dlg, colours[i]);
414 dlg_update_done(ctrl, dlg);
415 dlg_text_set(cd->rgbtext, dlg, "");
417 } else if (event == EVENT_SELCHANGE) {
418 if (ctrl == cd->listbox) {
419 /* The user has selected a colour. Update the RGB text. */
420 int i = dlg_listbox_index(ctrl, dlg);
425 r = cfg->colours[i][0];
426 g = cfg->colours[i][1];
427 b = cfg->colours[i][2];
430 } else if (event == EVENT_ACTION) {
431 if (ctrl == cd->button) {
432 int i = dlg_listbox_index(cd->listbox, dlg);
438 * Start a colour selector, which will send us an
439 * EVENT_CALLBACK when it's finished and allow us to
440 * pick up the results.
442 dlg_coloursel_start(ctrl, dlg,
447 } else if (event == EVENT_CALLBACK) {
448 if (ctrl == cd->button) {
449 int i = dlg_listbox_index(cd->listbox, dlg);
451 * Collect the results of the colour selector. Will
452 * return nonzero on success, or zero if the colour
453 * selector did nothing (user hit Cancel, for example).
455 if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
456 cfg->colours[i][0] = r;
457 cfg->colours[i][1] = g;
458 cfg->colours[i][2] = b;
466 sprintf(buf, "%02x/%02x/%02x", r, g, b);
467 dlg_text_set(cd->rgbtext, dlg, buf);
471 struct environ_data {
472 union control *varbox, *valbox, *addbutton, *rembutton, *listbox;
475 static void environ_handler(union control *ctrl, void *dlg,
476 void *data, int event)
478 Config *cfg = (Config *)data;
479 struct environ_data *ed =
480 (struct environ_data *)ctrl->generic.context.p;
482 if (event == EVENT_REFRESH) {
483 if (ctrl == ed->listbox) {
484 char *p = cfg->environmt;
485 dlg_update_start(ctrl, dlg);
486 dlg_listbox_clear(ctrl, dlg);
488 dlg_listbox_add(ctrl, dlg, p);
491 dlg_update_done(ctrl, dlg);
493 } else if (event == EVENT_ACTION) {
494 if (ctrl == ed->addbutton) {
495 char str[sizeof(cfg->environmt)];
497 dlg_editbox_get(ed->varbox, dlg, str, sizeof(str)-1);
502 p = str + strlen(str);
504 dlg_editbox_get(ed->valbox, dlg, p, sizeof(str)-1 - (p - str));
515 if ((p - cfg->environmt) + strlen(str) + 2 <
516 sizeof(cfg->environmt)) {
518 p[strlen(str) + 1] = '\0';
519 dlg_listbox_add(ed->listbox, dlg, str);
520 dlg_editbox_set(ed->varbox, dlg, "");
521 dlg_editbox_set(ed->valbox, dlg, "");
523 dlg_error_msg(dlg, "Environment too big");
525 } else if (ctrl == ed->rembutton) {
526 int i = dlg_listbox_index(ed->listbox, dlg);
532 dlg_listbox_del(ed->listbox, dlg, i);
560 struct portfwd_data {
561 union control *addbutton, *rembutton, *listbox;
562 union control *sourcebox, *destbox, *direction;
565 static void portfwd_handler(union control *ctrl, void *dlg,
566 void *data, int event)
568 Config *cfg = (Config *)data;
569 struct portfwd_data *pfd =
570 (struct portfwd_data *)ctrl->generic.context.p;
572 if (event == EVENT_REFRESH) {
573 if (ctrl == pfd->listbox) {
574 char *p = cfg->portfwd;
575 dlg_update_start(ctrl, dlg);
576 dlg_listbox_clear(ctrl, dlg);
578 dlg_listbox_add(ctrl, dlg, p);
581 dlg_update_done(ctrl, dlg);
583 } else if (event == EVENT_ACTION) {
584 if (ctrl == pfd->addbutton) {
585 char str[sizeof(cfg->portfwd)];
587 if (dlg_radiobutton_get(pfd->direction, dlg) == 0)
591 dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
593 dlg_error_msg(dlg, "You need to specify a source port number");
596 p = str + strlen(str);
598 dlg_editbox_get(pfd->destbox, dlg, p, sizeof(str)-1 - (p - str));
599 if (!*p || !strchr(p, ':')) {
601 "You need to specify a destination address\n"
602 "in the form \"host.name:port\"");
611 if ((p - cfg->portfwd) + strlen(str) + 2 <
612 sizeof(cfg->portfwd)) {
614 p[strlen(str) + 1] = '\0';
615 dlg_listbox_add(pfd->listbox, dlg, str);
616 dlg_editbox_set(pfd->sourcebox, dlg, "");
617 dlg_editbox_set(pfd->destbox, dlg, "");
619 dlg_error_msg(dlg, "Too many forwardings");
621 } else if (ctrl == pfd->rembutton) {
622 int i = dlg_listbox_index(pfd->listbox, dlg);
628 dlg_listbox_del(pfd->listbox, dlg, i);
656 void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
657 int midsession, int protocol)
659 struct controlset *s;
660 struct sessionsaver_data *ssd;
661 struct charclass_data *ccd;
662 struct colour_data *cd;
663 struct environ_data *ed;
664 struct portfwd_data *pfd;
667 ssd = (struct sessionsaver_data *)
668 ctrl_alloc(b, sizeof(struct sessionsaver_data));
669 ssd->sesslist = (midsession ? NULL : sesslist);
672 * The standard panel that appears at the bottom of all panels:
673 * Open, Cancel, Apply etc.
675 s = ctrl_getset(b, "", "", "");
676 ctrl_columns(s, 5, 20, 20, 20, 20, 20);
677 ssd->okbutton = ctrl_pushbutton(s,
678 (midsession ? "Apply" : "Open"),
679 (char)(midsession ? 'a' : 'o'),
681 sessionsaver_handler, P(ssd));
682 ssd->okbutton->button.isdefault = TRUE;
683 ssd->okbutton->generic.column = 3;
684 ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help),
685 sessionsaver_handler, P(ssd));
686 ssd->cancelbutton->generic.column = 4;
687 /* We carefully don't close the 5-column part, so that platform-
688 * specific add-ons can put extra buttons alongside Open and Cancel. */
693 ctrl_settitle(b, "Session", "Basic options for your PuTTY session");
696 s = ctrl_getset(b, "Session", "hostport",
697 "Specify your connection by host name or IP address");
698 ctrl_columns(s, 2, 75, 25);
699 c = ctrl_editbox(s, "Host Name (or IP address)", 'n', 100,
700 HELPCTX(session_hostname),
701 dlg_stdeditbox_handler, I(offsetof(Config,host)),
702 I(sizeof(((Config *)0)->host)));
703 c->generic.column = 0;
704 c = ctrl_editbox(s, "Port", 'p', 100, HELPCTX(session_hostname),
705 dlg_stdeditbox_handler,
706 I(offsetof(Config,port)), I(-1));
707 c->generic.column = 1;
708 ctrl_columns(s, 1, 100);
709 if (backends[3].backend == NULL) {
710 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 3,
711 HELPCTX(session_hostname),
712 protocolbuttons_handler, P(c),
713 "Raw", 'r', I(PROT_RAW),
714 "Telnet", 't', I(PROT_TELNET),
715 "Rlogin", 'i', I(PROT_RLOGIN),
718 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 4,
719 HELPCTX(session_hostname),
720 protocolbuttons_handler, P(c),
721 "Raw", 'r', I(PROT_RAW),
722 "Telnet", 't', I(PROT_TELNET),
723 "Rlogin", 'i', I(PROT_RLOGIN),
724 "SSH", 's', I(PROT_SSH),
728 s = ctrl_getset(b, "Session", "savedsessions",
729 "Load, save or delete a stored session");
730 ctrl_columns(s, 2, 75, 25);
731 ssd->savedsession[0] = '\0';
732 ssd->sesslist = sesslist;
733 ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
734 HELPCTX(session_saved),
735 sessionsaver_handler, P(ssd), P(NULL));
736 ssd->editbox->generic.column = 0;
737 /* Reset columns so that the buttons are alongside the list, rather
738 * than alongside that edit box. */
739 ctrl_columns(s, 1, 100);
740 ctrl_columns(s, 2, 75, 25);
741 ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l',
742 HELPCTX(session_saved),
743 sessionsaver_handler, P(ssd));
744 ssd->loadbutton->generic.column = 1;
745 ssd->savebutton = ctrl_pushbutton(s, "Save", 'v',
746 HELPCTX(session_saved),
747 sessionsaver_handler, P(ssd));
748 ssd->savebutton->generic.column = 1;
749 ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd',
750 HELPCTX(session_saved),
751 sessionsaver_handler, P(ssd));
752 ssd->delbutton->generic.column = 1;
753 ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
754 HELPCTX(session_saved),
755 sessionsaver_handler, P(ssd));
756 ssd->listbox->generic.column = 0;
757 ssd->listbox->listbox.height = 7;
758 ctrl_columns(s, 1, 100);
761 s = ctrl_getset(b, "Session", "otheropts", NULL);
762 c = ctrl_radiobuttons(s, "Close window on exit:", 'w', 4,
763 HELPCTX(session_coe),
764 dlg_stdradiobutton_handler,
765 I(offsetof(Config, close_on_exit)),
766 "Always", I(FORCE_ON),
767 "Never", I(FORCE_OFF),
768 "Only on clean exit", I(AUTO), NULL);
771 * The Session/Logging panel.
773 ctrl_settitle(b, "Session/Logging", "Options controlling session logging");
775 s = ctrl_getset(b, "Session/Logging", "main", NULL);
776 ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 1,
777 HELPCTX(logging_main),
778 dlg_stdradiobutton_handler, I(offsetof(Config, logtype)),
779 "Logging turned off completely", 't', I(LGTYP_NONE),
780 "Log printable output only", 'p', I(LGTYP_ASCII),
781 "Log all session output", 'l', I(LGTYP_DEBUG),
782 "Log SSH packet data", 's', I(LGTYP_PACKETS),
784 ctrl_filesel(s, "Log file name:", 'f',
785 NULL, TRUE, "Select session log file name",
786 HELPCTX(logging_filename),
787 dlg_stdfilesel_handler, I(offsetof(Config, logfilename)));
788 ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
789 " &T for time, and &H for host name)",
790 HELPCTX(logging_filename));
791 ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
792 HELPCTX(logging_exists),
793 dlg_stdradiobutton_handler, I(offsetof(Config,logxfovr)),
794 "Always overwrite it", I(LGXF_OVR),
795 "Always append to the end of it", I(LGXF_APN),
796 "Ask the user every time", I(LGXF_ASK), NULL);
799 * The Terminal panel.
801 ctrl_settitle(b, "Terminal", "Options controlling the terminal emulation");
803 s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
804 ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
805 HELPCTX(terminal_autowrap),
806 dlg_stdcheckbox_handler, I(offsetof(Config,wrap_mode)));
807 ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
808 HELPCTX(terminal_decom),
809 dlg_stdcheckbox_handler, I(offsetof(Config,dec_om)));
810 ctrl_checkbox(s, "Implicit CR in every LF", 'r',
811 HELPCTX(terminal_lfhascr),
812 dlg_stdcheckbox_handler, I(offsetof(Config,lfhascr)));
813 ctrl_checkbox(s, "Use background colour to erase screen", 'e',
814 HELPCTX(terminal_bce),
815 dlg_stdcheckbox_handler, I(offsetof(Config,bce)));
816 ctrl_checkbox(s, "Enable blinking text", 'n',
817 HELPCTX(terminal_blink),
818 dlg_stdcheckbox_handler, I(offsetof(Config,blinktext)));
819 ctrl_editbox(s, "Answerback to ^E:", 's', 100,
820 HELPCTX(terminal_answerback),
821 dlg_stdeditbox_handler, I(offsetof(Config,answerback)),
822 I(sizeof(((Config *)0)->answerback)));
824 s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
825 ctrl_radiobuttons(s, "Local echo:", 'l', 3,
826 HELPCTX(terminal_localecho),
827 dlg_stdradiobutton_handler,I(offsetof(Config,localecho)),
829 "Force on", I(FORCE_ON),
830 "Force off", I(FORCE_OFF), NULL);
831 ctrl_radiobuttons(s, "Local line editing:", 't', 3,
832 HELPCTX(terminal_localedit),
833 dlg_stdradiobutton_handler,I(offsetof(Config,localedit)),
835 "Force on", I(FORCE_ON),
836 "Force off", I(FORCE_OFF), NULL);
838 s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
839 ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100,
840 HELPCTX(terminal_printing),
841 printerbox_handler, P(NULL), P(NULL));
844 * The Terminal/Keyboard panel.
846 ctrl_settitle(b, "Terminal/Keyboard",
847 "Options controlling the effects of keys");
849 s = ctrl_getset(b, "Terminal/Keyboard", "mappings",
850 "Change the sequences sent by:");
851 ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
852 HELPCTX(keyboard_backspace),
853 dlg_stdradiobutton_handler,
854 I(offsetof(Config, bksp_is_delete)),
855 "Control-H", I(0), "Control-? (127)", I(1), NULL);
856 ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
857 HELPCTX(keyboard_homeend),
858 dlg_stdradiobutton_handler,
859 I(offsetof(Config, rxvt_homeend)),
860 "Standard", I(0), "rxvt", I(1), NULL);
861 ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3,
862 HELPCTX(keyboard_funkeys),
863 dlg_stdradiobutton_handler,
864 I(offsetof(Config, funky_type)),
865 "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2),
866 "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL);
868 s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad",
869 "Application keypad settings:");
870 ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
871 HELPCTX(keyboard_appcursor),
872 dlg_stdradiobutton_handler,
873 I(offsetof(Config, app_cursor)),
874 "Normal", I(0), "Application", I(1), NULL);
875 ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
876 HELPCTX(keyboard_appkeypad),
877 numeric_keypad_handler, P(NULL),
878 "Normal", I(0), "Application", I(1), "NetHack", I(2),
882 * The Terminal/Bell panel.
884 ctrl_settitle(b, "Terminal/Bell",
885 "Options controlling the terminal bell");
887 s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
888 ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
890 dlg_stdradiobutton_handler, I(offsetof(Config, beep)),
891 "None (bell disabled)", I(BELL_DISABLED),
892 "Make default system alert sound", I(BELL_DEFAULT),
893 "Visual bell (flash window)", I(BELL_VISUAL), NULL);
895 s = ctrl_getset(b, "Terminal/Bell", "overload",
896 "Control the bell overload behaviour");
897 ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
898 HELPCTX(bell_overload),
899 dlg_stdcheckbox_handler, I(offsetof(Config,bellovl)));
900 ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
901 HELPCTX(bell_overload),
902 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_n)), I(-1));
903 ctrl_editbox(s, "... in this many seconds", 't', 20,
904 HELPCTX(bell_overload),
905 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_t)),
907 ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
908 HELPCTX(bell_overload));
909 ctrl_editbox(s, "Seconds of silence required", 's', 20,
910 HELPCTX(bell_overload),
911 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_s)),
915 * The Terminal/Features panel.
917 ctrl_settitle(b, "Terminal/Features",
918 "Enabling and disabling advanced terminal features");
920 s = ctrl_getset(b, "Terminal/Features", "main", NULL);
921 ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
922 HELPCTX(features_application),
923 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_c)));
924 ctrl_checkbox(s, "Disable application keypad mode", 'k',
925 HELPCTX(features_application),
926 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_k)));
927 ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
928 HELPCTX(features_mouse),
929 dlg_stdcheckbox_handler, I(offsetof(Config,no_mouse_rep)));
930 ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
931 HELPCTX(features_resize),
932 dlg_stdcheckbox_handler,
933 I(offsetof(Config,no_remote_resize)));
934 ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
935 HELPCTX(features_altscreen),
936 dlg_stdcheckbox_handler, I(offsetof(Config,no_alt_screen)));
937 ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
938 HELPCTX(features_retitle),
939 dlg_stdcheckbox_handler,
940 I(offsetof(Config,no_remote_wintitle)));
941 ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
942 HELPCTX(features_dbackspace),
943 dlg_stdcheckbox_handler, I(offsetof(Config,no_dbackspace)));
944 ctrl_checkbox(s, "Disable remote-controlled character set configuration",
945 'r', HELPCTX(features_charset), dlg_stdcheckbox_handler,
946 I(offsetof(Config,no_remote_charset)));
951 ctrl_settitle(b, "Window", "Options controlling PuTTY's window");
953 s = ctrl_getset(b, "Window", "size", "Set the size of the window");
954 ctrl_columns(s, 2, 50, 50);
955 c = ctrl_editbox(s, "Rows", 'r', 100,
956 HELPCTX(window_size),
957 dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
958 c->generic.column = 0;
959 c = ctrl_editbox(s, "Columns", 'm', 100,
960 HELPCTX(window_size),
961 dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
962 c->generic.column = 1;
963 ctrl_columns(s, 1, 100);
965 s = ctrl_getset(b, "Window", "scrollback",
966 "Control the scrollback in the window");
967 ctrl_editbox(s, "Lines of scrollback", 's', 50,
968 HELPCTX(window_scrollback),
969 dlg_stdeditbox_handler, I(offsetof(Config,savelines)), I(-1));
970 ctrl_checkbox(s, "Display scrollbar", 'd',
971 HELPCTX(window_scrollback),
972 dlg_stdcheckbox_handler, I(offsetof(Config,scrollbar)));
973 ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
974 HELPCTX(window_scrollback),
975 dlg_stdcheckbox_handler,
976 I(offsetof(Config,scrollbar_in_fullscreen)));
977 ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
978 HELPCTX(window_scrollback),
979 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_key)));
980 ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
981 HELPCTX(window_scrollback),
982 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp)));
983 ctrl_checkbox(s, "Push erased text into scrollback", 'e',
984 HELPCTX(window_erased),
985 dlg_stdcheckbox_handler,
986 I(offsetof(Config,erase_to_scrollback)));
989 * The Window/Appearance panel.
991 ctrl_settitle(b, "Window/Appearance",
992 "Configure the appearance of PuTTY's window");
994 s = ctrl_getset(b, "Window/Appearance", "cursor",
995 "Adjust the use of the cursor");
996 ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
997 HELPCTX(appearance_cursor),
998 dlg_stdradiobutton_handler,
999 I(offsetof(Config, cursor_type)),
1001 "Underline", 'u', I(1),
1002 "Vertical line", 'v', I(2), NULL);
1003 ctrl_checkbox(s, "Cursor blinks", 'b',
1004 HELPCTX(appearance_cursor),
1005 dlg_stdcheckbox_handler, I(offsetof(Config,blink_cur)));
1007 s = ctrl_getset(b, "Window/Appearance", "font",
1009 ctrl_fontsel(s, "Font used in the terminal window", 'n',
1010 HELPCTX(appearance_font),
1011 dlg_stdfontsel_handler, I(offsetof(Config, font)));
1013 s = ctrl_getset(b, "Window/Appearance", "mouse",
1014 "Adjust the use of the mouse pointer");
1015 ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
1016 HELPCTX(appearance_hidemouse),
1017 dlg_stdcheckbox_handler, I(offsetof(Config,hide_mouseptr)));
1019 s = ctrl_getset(b, "Window/Appearance", "border",
1020 "Adjust the window border");
1021 ctrl_editbox(s, "Gap between text and window edge:", NO_SHORTCUT, 20,
1022 HELPCTX(appearance_border),
1023 dlg_stdeditbox_handler,
1024 I(offsetof(Config,window_border)), I(-1));
1027 * The Window/Behaviour panel.
1029 ctrl_settitle(b, "Window/Behaviour",
1030 "Configure the behaviour of PuTTY's window");
1032 s = ctrl_getset(b, "Window/Behaviour", "title",
1033 "Adjust the behaviour of the window title");
1034 ctrl_editbox(s, "Window title:", 't', 100,
1035 HELPCTX(appearance_title),
1036 dlg_stdeditbox_handler, I(offsetof(Config,wintitle)),
1037 I(sizeof(((Config *)0)->wintitle)));
1038 ctrl_checkbox(s, "Separate window and icon titles", 'i',
1039 HELPCTX(appearance_title),
1040 dlg_stdcheckbox_handler,
1041 I(CHECKBOX_INVERT | offsetof(Config,win_name_always)));
1043 s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
1044 ctrl_checkbox(s, "Warn before closing window", 'w',
1045 HELPCTX(behaviour_closewarn),
1046 dlg_stdcheckbox_handler, I(offsetof(Config,warn_on_close)));
1049 * The Window/Translation panel.
1051 ctrl_settitle(b, "Window/Translation",
1052 "Options controlling character set translation");
1054 s = ctrl_getset(b, "Window/Translation", "trans",
1055 "Character set translation on received data");
1056 ctrl_combobox(s, "Received data assumed to be in which character set:",
1057 'r', 100, HELPCTX(translation_codepage),
1058 codepage_handler, P(NULL), P(NULL));
1060 s = ctrl_getset(b, "Window/Translation", "linedraw",
1061 "Adjust how PuTTY displays line drawing characters");
1062 ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1,
1063 HELPCTX(translation_linedraw),
1064 dlg_stdradiobutton_handler,
1065 I(offsetof(Config, vtmode)),
1066 "Font has XWindows encoding", 'x', I(VT_XWINDOWS),
1067 "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN),
1068 "Unicode mode", 'u', I(VT_UNICODE), NULL);
1071 * The Window/Selection panel.
1073 ctrl_settitle(b, "Window/Selection", "Options controlling copy and paste");
1075 s = ctrl_getset(b, "Window/Selection", "trans",
1076 "Translation of pasted characters");
1077 ctrl_checkbox(s, "Don't translate line drawing chars into +, - and |",'d',
1078 HELPCTX(selection_linedraw),
1079 dlg_stdcheckbox_handler, I(offsetof(Config,rawcnp)));
1081 s = ctrl_getset(b, "Window/Selection", "mouse",
1082 "Control use of mouse");
1083 ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
1084 HELPCTX(selection_shiftdrag),
1085 dlg_stdcheckbox_handler, I(offsetof(Config,mouse_override)));
1086 ctrl_radiobuttons(s,
1087 "Default selection mode (Alt+drag does the other one):",
1089 HELPCTX(selection_rect),
1090 dlg_stdradiobutton_handler,
1091 I(offsetof(Config, rect_select)),
1092 "Normal", 'n', I(0),
1093 "Rectangular block", 'r', I(1), NULL);
1095 s = ctrl_getset(b, "Window/Selection", "charclass",
1096 "Control the select-one-word-at-a-time mode");
1097 ccd = (struct charclass_data *)
1098 ctrl_alloc(b, sizeof(struct charclass_data));
1099 ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
1100 HELPCTX(selection_charclasses),
1101 charclass_handler, P(ccd));
1102 ccd->listbox->listbox.multisel = 1;
1103 ccd->listbox->listbox.ncols = 4;
1104 ccd->listbox->listbox.percentages = smalloc(4*sizeof(int));
1105 ccd->listbox->listbox.percentages[0] = 15;
1106 ccd->listbox->listbox.percentages[1] = 25;
1107 ccd->listbox->listbox.percentages[2] = 20;
1108 ccd->listbox->listbox.percentages[3] = 40;
1109 ctrl_columns(s, 2, 67, 33);
1110 ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
1111 HELPCTX(selection_charclasses),
1112 charclass_handler, P(ccd), P(NULL));
1113 ccd->editbox->generic.column = 0;
1114 ccd->button = ctrl_pushbutton(s, "Set", 's',
1115 HELPCTX(selection_charclasses),
1116 charclass_handler, P(ccd));
1117 ccd->button->generic.column = 1;
1118 ctrl_columns(s, 1, 100);
1121 * The Window/Colours panel.
1123 ctrl_settitle(b, "Window/Colours", "Options controlling use of colours");
1125 s = ctrl_getset(b, "Window/Colours", "general",
1126 "General options for colour usage");
1127 ctrl_checkbox(s, "Bolded text is a different colour", 'b',
1128 HELPCTX(colours_bold),
1129 dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour)));
1131 s = ctrl_getset(b, "Window/Colours", "adjust",
1132 "Adjust the precise colours PuTTY displays");
1133 ctrl_text(s, "Select a colour from the list, and then click the"
1134 " Modify button to change its appearance.",
1135 HELPCTX(colours_config));
1136 ctrl_columns(s, 2, 67, 33);
1137 cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data));
1138 cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u',
1139 HELPCTX(colours_config), colour_handler, P(cd));
1140 cd->listbox->generic.column = 0;
1141 c = ctrl_text(s, "RGB value:", HELPCTX(colours_config));
1142 c->generic.column = 1;
1143 cd->rgbtext = ctrl_text(s, "00/00/00", HELPCTX(colours_config));
1144 cd->rgbtext->generic.column = 1;
1145 cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config),
1146 colour_handler, P(cd));
1147 cd->button->generic.column = 1;
1148 ctrl_columns(s, 1, 100);
1151 * The Connection panel.
1153 ctrl_settitle(b, "Connection", "Options controlling the connection");
1156 s = ctrl_getset(b, "Connection", "data", "Data to send to the server");
1157 ctrl_editbox(s, "Terminal-type string", 't', 50,
1158 HELPCTX(connection_termtype),
1159 dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
1160 I(sizeof(((Config *)0)->termtype)));
1161 ctrl_editbox(s, "Auto-login username", 'u', 50,
1162 HELPCTX(connection_username),
1163 dlg_stdeditbox_handler, I(offsetof(Config,username)),
1164 I(sizeof(((Config *)0)->username)));
1167 s = ctrl_getset(b, "Connection", "keepalive",
1168 "Sending of null packets to keep session active");
1169 ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
1170 HELPCTX(connection_keepalive),
1171 dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
1175 s = ctrl_getset(b, "Connection", "tcp",
1176 "Low-level TCP connection options");
1177 ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)", 'n',
1178 HELPCTX(connection_nodelay),
1179 dlg_stdcheckbox_handler,
1180 I(offsetof(Config,tcp_nodelay)));
1185 * The Connection/Proxy panel.
1187 ctrl_settitle(b, "Connection/Proxy",
1188 "Options controlling proxy usage");
1190 s = ctrl_getset(b, "Connection/Proxy", "basics", "Proxy basics");
1191 ctrl_radiobuttons(s, "Proxy type:", NO_SHORTCUT, 4,
1192 HELPCTX(proxy_type),
1193 dlg_stdradiobutton_handler,
1194 I(offsetof(Config, proxy_type)),
1195 "None", 'n', I(PROXY_NONE),
1196 "HTTP", 't', I(PROXY_HTTP),
1197 "SOCKS", 's', I(PROXY_SOCKS),
1198 "Telnet", 'l', I(PROXY_TELNET),
1200 ctrl_columns(s, 2, 80, 20);
1201 c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
1202 HELPCTX(proxy_main),
1203 dlg_stdeditbox_handler,
1204 I(offsetof(Config,proxy_host)),
1205 I(sizeof(((Config *)0)->proxy_host)));
1206 c->generic.column = 0;
1207 c = ctrl_editbox(s, "Port", 'p', 100,
1208 HELPCTX(proxy_main),
1209 dlg_stdeditbox_handler,
1210 I(offsetof(Config,proxy_port)),
1212 c->generic.column = 1;
1213 ctrl_columns(s, 1, 100);
1214 ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
1215 HELPCTX(proxy_exclude),
1216 dlg_stdeditbox_handler,
1217 I(offsetof(Config,proxy_exclude_list)),
1218 I(sizeof(((Config *)0)->proxy_exclude_list)));
1219 ctrl_checkbox(s, "Consider proxying local host connections", 'x',
1220 HELPCTX(proxy_exclude),
1221 dlg_stdcheckbox_handler,
1222 I(offsetof(Config,even_proxy_localhost)));
1223 ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
1225 dlg_stdradiobutton_handler,
1226 I(offsetof(Config, proxy_dns)),
1229 "Yes", I(FORCE_ON), NULL);
1230 ctrl_editbox(s, "Username", 'u', 60,
1231 HELPCTX(proxy_auth),
1232 dlg_stdeditbox_handler,
1233 I(offsetof(Config,proxy_username)),
1234 I(sizeof(((Config *)0)->proxy_username)));
1235 c = ctrl_editbox(s, "Password", 'w', 60,
1236 HELPCTX(proxy_auth),
1237 dlg_stdeditbox_handler,
1238 I(offsetof(Config,proxy_password)),
1239 I(sizeof(((Config *)0)->proxy_password)));
1240 c->editbox.password = 1;
1242 s = ctrl_getset(b, "Connection/Proxy", "misc",
1243 "Miscellaneous proxy settings");
1244 ctrl_editbox(s, "Telnet command", 'm', 100,
1245 HELPCTX(proxy_command),
1246 dlg_stdeditbox_handler,
1247 I(offsetof(Config,proxy_telnet_command)),
1248 I(sizeof(((Config *)0)->proxy_telnet_command)));
1249 ctrl_radiobuttons(s, "SOCKS Version", 'v', 2,
1250 HELPCTX(proxy_socksver),
1251 dlg_stdradiobutton_handler,
1252 I(offsetof(Config, proxy_socks_version)),
1253 "Version 5", I(5), "Version 4", I(4), NULL);
1257 * The Telnet panel exists in the base config box, and in a
1258 * mid-session reconfig box _if_ we're using Telnet.
1260 if (!midsession || protocol == PROT_TELNET) {
1262 * The Connection/Telnet panel.
1264 ctrl_settitle(b, "Connection/Telnet",
1265 "Options controlling Telnet connections");
1268 s = ctrl_getset(b, "Connection/Telnet", "data",
1269 "Data to send to the server");
1270 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1271 HELPCTX(telnet_termspeed),
1272 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1273 I(sizeof(((Config *)0)->termspeed)));
1274 ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
1275 ctrl_columns(s, 2, 80, 20);
1276 ed = (struct environ_data *)
1277 ctrl_alloc(b, sizeof(struct environ_data));
1278 ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
1279 HELPCTX(telnet_environ),
1280 environ_handler, P(ed), P(NULL));
1281 ed->varbox->generic.column = 0;
1282 ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
1283 HELPCTX(telnet_environ),
1284 environ_handler, P(ed), P(NULL));
1285 ed->valbox->generic.column = 0;
1286 ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
1287 HELPCTX(telnet_environ),
1288 environ_handler, P(ed));
1289 ed->addbutton->generic.column = 1;
1290 ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1291 HELPCTX(telnet_environ),
1292 environ_handler, P(ed));
1293 ed->rembutton->generic.column = 1;
1294 ctrl_columns(s, 1, 100);
1295 ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1296 HELPCTX(telnet_environ),
1297 environ_handler, P(ed));
1298 ed->listbox->listbox.height = 3;
1301 s = ctrl_getset(b, "Connection/Telnet", "protocol",
1302 "Telnet protocol adjustments");
1305 ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
1307 HELPCTX(telnet_oldenviron),
1308 dlg_stdradiobutton_handler,
1309 I(offsetof(Config, rfc_environ)),
1310 "BSD (commonplace)", 'b', I(0),
1311 "RFC 1408 (unusual)", 'f', I(1), NULL);
1312 ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
1313 HELPCTX(telnet_passive),
1314 dlg_stdradiobutton_handler,
1315 I(offsetof(Config, passive_telnet)),
1316 "Passive", I(1), "Active", I(0), NULL);
1318 ctrl_checkbox(s, "Keyboard sends telnet Backspace and Interrupt", 'k',
1319 HELPCTX(telnet_specialkeys),
1320 dlg_stdcheckbox_handler,
1321 I(offsetof(Config,telnet_keyboard)));
1322 ctrl_checkbox(s, "Return key sends telnet New Line instead of ^M",
1323 NO_SHORTCUT, HELPCTX(telnet_newline),
1324 dlg_stdcheckbox_handler,
1325 I(offsetof(Config,telnet_newline)));
1331 * The Connection/Rlogin panel.
1333 ctrl_settitle(b, "Connection/Rlogin",
1334 "Options controlling Rlogin connections");
1336 s = ctrl_getset(b, "Connection/Rlogin", "data",
1337 "Data to send to the server");
1338 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1339 HELPCTX(rlogin_termspeed),
1340 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1341 I(sizeof(((Config *)0)->termspeed)));
1342 ctrl_editbox(s, "Local username:", 'l', 50,
1343 HELPCTX(rlogin_localuser),
1344 dlg_stdeditbox_handler, I(offsetof(Config,localusername)),
1345 I(sizeof(((Config *)0)->localusername)));
1350 * All the SSH stuff is omitted in PuTTYtel.
1353 if (!midsession && backends[3].backend != NULL) {
1356 * The Connection/SSH panel.
1358 ctrl_settitle(b, "Connection/SSH",
1359 "Options controlling SSH connections");
1361 s = ctrl_getset(b, "Connection/SSH", "data",
1362 "Data to send to the server");
1363 ctrl_editbox(s, "Remote command:", 'r', 100,
1364 HELPCTX(ssh_command),
1365 dlg_stdeditbox_handler, I(offsetof(Config,remote_cmd)),
1366 I(sizeof(((Config *)0)->remote_cmd)));
1368 s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
1369 ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
1371 dlg_stdcheckbox_handler,
1372 I(offsetof(Config,nopty)));
1373 ctrl_checkbox(s, "Enable compression", 'e',
1374 HELPCTX(ssh_compress),
1375 dlg_stdcheckbox_handler,
1376 I(offsetof(Config,compression)));
1377 ctrl_radiobuttons(s, "Preferred SSH protocol version:", NO_SHORTCUT, 4,
1378 HELPCTX(ssh_protocol),
1379 dlg_stdradiobutton_handler,
1380 I(offsetof(Config, sshprot)),
1381 "1 only", 'l', I(0),
1384 "2 only", 'n', I(3), NULL);
1386 s = ctrl_getset(b, "Connection/SSH", "encryption", "Encryption options");
1387 c = ctrl_draglist(s, "Encryption cipher selection policy:", 's',
1388 HELPCTX(ssh_ciphers),
1389 cipherlist_handler, P(NULL));
1390 c->listbox.height = 6;
1392 ctrl_checkbox(s, "Enable non-standard use of single-DES in SSH 2", 'i',
1393 HELPCTX(ssh_ciphers),
1394 dlg_stdcheckbox_handler,
1395 I(offsetof(Config,ssh2_des_cbc)));
1398 * The Connection/SSH/Auth panel.
1400 ctrl_settitle(b, "Connection/SSH/Auth",
1401 "Options controlling SSH authentication");
1403 s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
1404 "Authentication methods");
1405 ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH1)", 'm',
1406 HELPCTX(ssh_auth_tis),
1407 dlg_stdcheckbox_handler,
1408 I(offsetof(Config,try_tis_auth)));
1409 ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH2)",
1410 'i', HELPCTX(ssh_auth_ki),
1411 dlg_stdcheckbox_handler,
1412 I(offsetof(Config,try_ki_auth)));
1414 s = ctrl_getset(b, "Connection/SSH/Auth", "params",
1415 "Authentication parameters");
1416 ctrl_checkbox(s, "Allow agent forwarding", 'f',
1417 HELPCTX(ssh_auth_agentfwd),
1418 dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
1419 ctrl_checkbox(s, "Allow attempted changes of username in SSH2", 'u',
1420 HELPCTX(ssh_auth_changeuser),
1421 dlg_stdcheckbox_handler,
1422 I(offsetof(Config,change_username)));
1423 ctrl_filesel(s, "Private key file for authentication:", 'k',
1424 FILTER_KEY_FILES, FALSE, "Select private key file",
1425 HELPCTX(ssh_auth_privkey),
1426 dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
1429 * The Connection/SSH/Tunnels panel.
1431 ctrl_settitle(b, "Connection/SSH/Tunnels",
1432 "Options controlling SSH tunnelling");
1434 s = ctrl_getset(b, "Connection/SSH/Tunnels", "x11", "X11 forwarding");
1435 ctrl_checkbox(s, "Enable X11 forwarding", 'e',
1436 HELPCTX(ssh_tunnels_x11),
1437 dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
1438 ctrl_editbox(s, "X display location", 'x', 50,
1439 HELPCTX(ssh_tunnels_x11),
1440 dlg_stdeditbox_handler, I(offsetof(Config,x11_display)),
1441 I(sizeof(((Config *)0)->x11_display)));
1442 ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
1443 HELPCTX(ssh_tunnels_x11auth),
1444 dlg_stdradiobutton_handler,
1445 I(offsetof(Config, x11_auth)),
1446 "MIT-Magic-Cookie-1", I(X11_MIT),
1447 "XDM-Authorization-1", I(X11_XDM), NULL);
1449 s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
1451 ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
1452 HELPCTX(ssh_tunnels_portfwd_localhost),
1453 dlg_stdcheckbox_handler,
1454 I(offsetof(Config,lport_acceptall)));
1455 ctrl_checkbox(s, "Remote ports do the same (SSH v2 only)", 'p',
1456 HELPCTX(ssh_tunnels_portfwd_localhost),
1457 dlg_stdcheckbox_handler,
1458 I(offsetof(Config,rport_acceptall)));
1460 ctrl_columns(s, 3, 55, 20, 25);
1461 c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
1462 c->generic.column = COLUMN_FIELD(0,2);
1463 /* You want to select from the list, _then_ hit Remove. So tab order
1464 * should be that way round. */
1465 pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data));
1466 pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1467 HELPCTX(ssh_tunnels_portfwd),
1468 portfwd_handler, P(pfd));
1469 pfd->rembutton->generic.column = 2;
1470 pfd->rembutton->generic.tabdelay = 1;
1471 pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1472 HELPCTX(ssh_tunnels_portfwd),
1473 portfwd_handler, P(pfd));
1474 pfd->listbox->listbox.height = 3;
1475 ctrl_tabdelay(s, pfd->rembutton);
1476 ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
1477 /* You want to enter source, destination and type, _then_ hit Add.
1478 * Again, we adjust the tab order to reflect this. */
1479 pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
1480 HELPCTX(ssh_tunnels_portfwd),
1481 portfwd_handler, P(pfd));
1482 pfd->addbutton->generic.column = 2;
1483 pfd->addbutton->generic.tabdelay = 1;
1484 pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40,
1485 HELPCTX(ssh_tunnels_portfwd),
1486 portfwd_handler, P(pfd), P(NULL));
1487 pfd->sourcebox->generic.column = 0;
1488 pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67,
1489 HELPCTX(ssh_tunnels_portfwd),
1490 portfwd_handler, P(pfd), P(NULL));
1491 pfd->direction = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 2,
1492 HELPCTX(ssh_tunnels_portfwd),
1493 portfwd_handler, P(pfd),
1494 "Local", 'l', P(NULL),
1495 "Remote", 'm', P(NULL), NULL);
1496 ctrl_tabdelay(s, pfd->addbutton);
1497 ctrl_columns(s, 1, 100);
1500 * The Connection/SSH/Bugs panel.
1502 ctrl_settitle(b, "Connection/SSH/Bugs",
1503 "Workarounds for SSH server bugs");
1505 s = ctrl_getset(b, "Connection/SSH/Bugs", "main",
1506 "Detection of known bugs in SSH servers");
1507 ctrl_droplist(s, "Chokes on SSH1 ignore messages", 'i', 20,
1508 HELPCTX(ssh_bugs_ignore1),
1509 sshbug_handler, I(offsetof(Config,sshbug_ignore1)));
1510 ctrl_droplist(s, "Refuses all SSH1 password camouflage", 's', 20,
1511 HELPCTX(ssh_bugs_plainpw1),
1512 sshbug_handler, I(offsetof(Config,sshbug_plainpw1)));
1513 ctrl_droplist(s, "Chokes on SSH1 RSA authentication", 'r', 20,
1514 HELPCTX(ssh_bugs_rsa1),
1515 sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
1516 ctrl_droplist(s, "Miscomputes SSH2 HMAC keys", 'm', 20,
1517 HELPCTX(ssh_bugs_hmac2),
1518 sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
1519 ctrl_droplist(s, "Miscomputes SSH2 encryption keys", 'e', 20,
1520 HELPCTX(ssh_bugs_derivekey2),
1521 sshbug_handler, I(offsetof(Config,sshbug_derivekey2)));
1522 ctrl_droplist(s, "Requires padding on SSH2 RSA signatures", 'p', 20,
1523 HELPCTX(ssh_bugs_rsapad2),
1524 sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
1525 ctrl_droplist(s, "Chokes on Diffie-Hellman group exchange", 'd', 20,
1526 HELPCTX(ssh_bugs_dhgex2),
1527 sshbug_handler, I(offsetof(Config,sshbug_dhgex2)));
1528 ctrl_droplist(s, "Misuses the session ID in PK auth", 'n', 20,
1529 HELPCTX(ssh_bugs_pksessid2),
1530 sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));