Increase PuTTY's default partition size to 2 MB. 1 MB just isn't enough.
[u/mdw/putty] / config.c
CommitLineData
fe8abbf4 1/*
2 * config.c - the platform-independent parts of the PuTTY
3 * configuration box.
4 */
5
6#include <assert.h>
7#include <stdlib.h>
8
9#include "putty.h"
10#include "dialog.h"
11#include "storage.h"
12
13#define PRINTER_DISABLED_STRING "None (printing disabled)"
14
15static void protocolbuttons_handler(union control *ctrl, void *dlg,
16 void *data, int event)
17{
18 int button, defport;
19 Config *cfg = (Config *)data;
20 /*
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.
25 */
26 if (event == EVENT_REFRESH) {
27 for (button = 0; button < ctrl->radio.nbuttons; button++)
28 if (cfg->protocol == ctrl->radio.buttondata[button].i)
29 break;
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) {
39 defport = -1;
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;
44 }
45 if (defport > 0 && cfg->port != defport) {
46 cfg->port = defport;
47 dlg_refresh((union control *)ctrl->radio.context.p, dlg);
48 }
49 }
50 }
51}
52
53static void numeric_keypad_handler(union control *ctrl, void *dlg,
54 void *data, int event)
55{
56 int button;
57 Config *cfg = (Config *)data;
58 /*
59 * This function works much like the standard radio button
60 * handler, but it has to handle two fields in Config.
61 */
62 if (event == EVENT_REFRESH) {
63 if (cfg->nethack_keypad)
64 button = 2;
65 else if (cfg->app_keypad)
66 button = 1;
67 else
68 button = 0;
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);
74 if (button == 2) {
75 cfg->app_keypad = FALSE;
76 cfg->nethack_keypad = TRUE;
77 } else {
78 cfg->app_keypad = (button != 0);
79 cfg->nethack_keypad = FALSE;
80 }
81 }
82}
83
84static void cipherlist_handler(union control *ctrl, void *dlg,
85 void *data, int event)
86{
87 Config *cfg = (Config *)data;
88 if (event == EVENT_REFRESH) {
89 int i;
90
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 }
97 };
98
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];
105 int j;
106 char *cstr = NULL;
107 for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
108 if (ciphers[j].c == c) {
109 cstr = ciphers[j].s;
110 break;
111 }
112 }
113 dlg_listbox_addwithindex(ctrl, dlg, cstr, c);
114 }
115 dlg_update_done(ctrl, dlg);
116
117 } else if (event == EVENT_VALCHANGE) {
118 int i;
119
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);
123
124 }
125}
126
127static void printerbox_handler(union control *ctrl, void *dlg,
128 void *data, int event)
129{
130 Config *cfg = (Config *)data;
131 if (event == EVENT_REFRESH) {
132 int nprinters, i;
133 printer_enum *pe;
134
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';
150 }
151}
152
153static void codepage_handler(union control *ctrl, void *dlg,
154 void *data, int event)
155{
156 Config *cfg = (Config *)data;
157 if (event == EVENT_REFRESH) {
158 int i;
159 char *cp;
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)));
173 }
174}
175
176static void sshbug_handler(union control *ctrl, void *dlg,
177 void *data, int event)
178{
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;
189 }
190 dlg_update_done(ctrl, dlg);
191 } else if (event == EVENT_SELCHANGE) {
192 int i = dlg_listbox_index(ctrl, dlg);
193 if (i < 0)
194 i = AUTO;
195 else
196 i = dlg_listbox_getid(ctrl, dlg, i);
197 *(int *)ATOFFSET(data, ctrl->listbox.context.i) = i;
198 }
199}
200
4e6d4091 201#define SAVEDSESSION_LEN 2048
202
fe8abbf4 203struct sessionsaver_data {
204 union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
205 union control *okbutton, *cancelbutton;
fe8abbf4 206 struct sesslist *sesslist;
207};
208
209/*
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
212 * failure.
213 */
214static int load_selected_session(struct sessionsaver_data *ssd,
4e6d4091 215 char *savedsession,
fe8abbf4 216 void *dlg, Config *cfg)
217{
218 int i = dlg_listbox_index(ssd->listbox, dlg);
219 int isdef;
220 if (i < 0) {
221 dlg_beep(dlg);
222 return 0;
223 }
224 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
225 load_settings(ssd->sesslist->sessions[i], !isdef, cfg);
226 if (!isdef) {
4e6d4091 227 strncpy(savedsession, ssd->sesslist->sessions[i],
228 SAVEDSESSION_LEN);
229 savedsession[SAVEDSESSION_LEN-1] = '\0';
fe8abbf4 230 } else {
4e6d4091 231 savedsession[0] = '\0';
fe8abbf4 232 }
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);
237 return 1;
238}
239
240static void sessionsaver_handler(union control *ctrl, void *dlg,
241 void *data, int event)
242{
243 Config *cfg = (Config *)data;
244 struct sessionsaver_data *ssd =
245 (struct sessionsaver_data *)ctrl->generic.context.p;
4e6d4091 246 char *savedsession;
247
248 /*
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).
253 */
254 if (!dlg_get_privdata(ssd->editbox, dlg)) {
255 savedsession = (char *)
256 dlg_alloc_privdata(ssd->editbox, dlg, SAVEDSESSION_LEN);
257 savedsession[0] = '\0';
258 } else {
259 savedsession = dlg_get_privdata(ssd->editbox, dlg);
260 }
fe8abbf4 261
262 if (event == EVENT_REFRESH) {
263 if (ctrl == ssd->editbox) {
4e6d4091 264 dlg_editbox_set(ctrl, dlg, savedsession);
fe8abbf4 265 } else if (ctrl == ssd->listbox) {
266 int i;
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);
272 }
273 } else if (event == EVENT_VALCHANGE) {
274 if (ctrl == ssd->editbox) {
4e6d4091 275 dlg_editbox_get(ctrl, dlg, savedsession,
276 SAVEDSESSION_LEN);
fe8abbf4 277 }
278 } else if (event == EVENT_ACTION) {
279 if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) {
280 /*
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.
286 */
4e6d4091 287 if (load_selected_session(ssd, savedsession, dlg, cfg) &&
fe8abbf4 288 (ctrl == ssd->listbox && cfg->host[0])) {
289 dlg_end(dlg, 1); /* it's all over, and succeeded */
290 }
291 } else if (ctrl == ssd->savebutton) {
4e6d4091 292 int isdef = !strcmp(savedsession, "Default Settings");
293 if (!savedsession[0]) {
8b0cb5aa 294 int i = dlg_listbox_index(ssd->listbox, dlg);
fe8abbf4 295 if (i < 0) {
296 dlg_beep(dlg);
297 return;
298 }
299 isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings");
300 if (!isdef) {
4e6d4091 301 strncpy(savedsession, ssd->sesslist->sessions[i],
302 SAVEDSESSION_LEN);
303 savedsession[SAVEDSESSION_LEN-1] = '\0';
fe8abbf4 304 } else {
4e6d4091 305 savedsession[0] = '\0';
fe8abbf4 306 }
307 }
4e6d4091 308 save_settings(savedsession, !isdef, cfg);
fe8abbf4 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) {
6f87d111 314 int i = dlg_listbox_index(ssd->listbox, dlg);
fe8abbf4 315 if (i <= 0) {
316 dlg_beep(dlg);
317 } else {
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);
322 }
323 } else if (ctrl == ssd->okbutton) {
324 /*
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.
330 */
331 if (dlg_last_focused(dlg) == ssd->listbox && !*cfg->host) {
332 Config cfg2;
4e6d4091 333 if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) {
fe8abbf4 334 dlg_beep(dlg);
335 return;
336 }
337 /* If at this point we have a valid session, go! */
338 if (*cfg2.host) {
339 *cfg = cfg2; /* structure copy */
340 dlg_end(dlg, 1);
341 } else
342 dlg_beep(dlg);
343 }
344
345 /*
346 * Otherwise, do the normal thing: if we have a valid
347 * session, get going.
348 */
349 if (*cfg->host) {
350 dlg_end(dlg, 1);
351 } else
352 dlg_beep(dlg);
353 } else if (ctrl == ssd->cancelbutton) {
354 dlg_end(dlg, 0);
355 }
356 }
357}
358
359struct charclass_data {
360 union control *listbox, *editbox, *button;
361};
362
363static void charclass_handler(union control *ctrl, void *dlg,
364 void *data, int event)
365{
366 Config *cfg = (Config *)data;
367 struct charclass_data *ccd =
368 (struct charclass_data *)ctrl->generic.context.p;
369
370 if (event == EVENT_REFRESH) {
371 if (ctrl == ccd->listbox) {
372 int i;
373 dlg_update_start(ctrl, dlg);
374 dlg_listbox_clear(ctrl, dlg);
375 for (i = 0; i < 128; i++) {
376 char str[100];
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);
380 }
381 dlg_update_done(ctrl, dlg);
382 }
383 } else if (event == EVENT_ACTION) {
384 if (ctrl == ccd->button) {
385 char str[100];
386 int i, n;
387 dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str));
388 n = atoi(str);
389 for (i = 0; i < 128; i++) {
390 if (dlg_listbox_issel(ccd->listbox, dlg, i))
391 cfg->wordness[i] = n;
392 }
393 dlg_refresh(ccd->listbox, dlg);
394 }
395 }
396}
397
398struct colour_data {
399 union control *listbox, *rgbtext, *button;
400};
401
402static 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"
414};
415
416static void colour_handler(union control *ctrl, void *dlg,
417 void *data, int event)
418{
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;
423
424 if (event == EVENT_REFRESH) {
425 if (ctrl == cd->listbox) {
426 int i;
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_text_set(cd->rgbtext, dlg, "");
433 }
434 } else if (event == EVENT_SELCHANGE) {
435 if (ctrl == cd->listbox) {
436 /* The user has selected a colour. Update the RGB text. */
437 int i = dlg_listbox_index(ctrl, dlg);
438 if (i < 0) {
439 dlg_beep(dlg);
440 return;
441 }
442 r = cfg->colours[i][0];
443 g = cfg->colours[i][1];
444 b = cfg->colours[i][2];
445 update = TRUE;
446 }
447 } else if (event == EVENT_ACTION) {
448 if (ctrl == cd->button) {
449 int i = dlg_listbox_index(cd->listbox, dlg);
450 if (i < 0) {
451 dlg_beep(dlg);
452 return;
453 }
454 /*
455 * Start a colour selector, which will send us an
456 * EVENT_CALLBACK when it's finished and allow us to
457 * pick up the results.
458 */
459 dlg_coloursel_start(ctrl, dlg,
460 cfg->colours[i][0],
461 cfg->colours[i][1],
462 cfg->colours[i][2]);
463 }
464 } else if (event == EVENT_CALLBACK) {
465 if (ctrl == cd->button) {
466 int i = dlg_listbox_index(cd->listbox, dlg);
467 /*
468 * Collect the results of the colour selector. Will
469 * return nonzero on success, or zero if the colour
470 * selector did nothing (user hit Cancel, for example).
471 */
472 if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
473 cfg->colours[i][0] = r;
474 cfg->colours[i][1] = g;
475 cfg->colours[i][2] = b;
476 update = TRUE;
477 }
478 }
479 }
480
481 if (update) {
482 char buf[40];
483 sprintf(buf, "%02x/%02x/%02x", r, g, b);
484 dlg_text_set(cd->rgbtext, dlg, buf);
485 }
486}
487
488struct environ_data {
489 union control *varbox, *valbox, *addbutton, *rembutton, *listbox;
490};
491
492static void environ_handler(union control *ctrl, void *dlg,
493 void *data, int event)
494{
495 Config *cfg = (Config *)data;
496 struct environ_data *ed =
497 (struct environ_data *)ctrl->generic.context.p;
498
499 if (event == EVENT_REFRESH) {
500 if (ctrl == ed->listbox) {
501 char *p = cfg->environmt;
502 dlg_update_start(ctrl, dlg);
503 dlg_listbox_clear(ctrl, dlg);
504 while (*p) {
505 dlg_listbox_add(ctrl, dlg, p);
506 p += strlen(p) + 1;
507 }
508 dlg_update_done(ctrl, dlg);
509 }
510 } else if (event == EVENT_ACTION) {
511 if (ctrl == ed->addbutton) {
512 char str[sizeof(cfg->environmt)];
513 char *p;
514 dlg_editbox_get(ed->varbox, dlg, str, sizeof(str)-1);
515 if (!*str) {
516 dlg_beep(dlg);
517 return;
518 }
519 p = str + strlen(str);
520 *p++ = '\t';
521 dlg_editbox_get(ed->valbox, dlg, p, sizeof(str)-1 - (p - str));
522 if (!*p) {
523 dlg_beep(dlg);
524 return;
525 }
526 p = cfg->environmt;
527 while (*p) {
528 while (*p)
529 p++;
530 p++;
531 }
532 if ((p - cfg->environmt) + strlen(str) + 2 <
533 sizeof(cfg->environmt)) {
534 strcpy(p, str);
535 p[strlen(str) + 1] = '\0';
536 dlg_listbox_add(ed->listbox, dlg, str);
537 dlg_editbox_set(ed->varbox, dlg, "");
538 dlg_editbox_set(ed->valbox, dlg, "");
539 } else {
540 dlg_error_msg(dlg, "Environment too big");
541 }
542 } else if (ctrl == ed->rembutton) {
543 int i = dlg_listbox_index(ed->listbox, dlg);
544 if (i < 0) {
545 dlg_beep(dlg);
546 } else {
547 char *p, *q;
548
549 dlg_listbox_del(ed->listbox, dlg, i);
550 p = cfg->environmt;
551 while (i > 0) {
552 if (!*p)
553 goto disaster;
554 while (*p)
555 p++;
556 p++;
557 i--;
558 }
559 q = p;
560 if (!*p)
561 goto disaster;
562 while (*p)
563 p++;
564 p++;
565 while (*p) {
566 while (*p)
567 *q++ = *p++;
568 *q++ = *p++;
569 }
570 *q = '\0';
571 disaster:;
572 }
573 }
574 }
575}
576
577struct portfwd_data {
578 union control *addbutton, *rembutton, *listbox;
579 union control *sourcebox, *destbox, *direction;
580};
581
582static void portfwd_handler(union control *ctrl, void *dlg,
583 void *data, int event)
584{
585 Config *cfg = (Config *)data;
586 struct portfwd_data *pfd =
587 (struct portfwd_data *)ctrl->generic.context.p;
588
589 if (event == EVENT_REFRESH) {
590 if (ctrl == pfd->listbox) {
591 char *p = cfg->portfwd;
592 dlg_update_start(ctrl, dlg);
593 dlg_listbox_clear(ctrl, dlg);
594 while (*p) {
595 dlg_listbox_add(ctrl, dlg, p);
596 p += strlen(p) + 1;
597 }
598 dlg_update_done(ctrl, dlg);
599 }
600 } else if (event == EVENT_ACTION) {
601 if (ctrl == pfd->addbutton) {
602 char str[sizeof(cfg->portfwd)];
603 char *p;
604 if (dlg_radiobutton_get(pfd->direction, dlg) == 0)
605 str[0] = 'L';
606 else
607 str[0] = 'R';
608 dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
609 if (!str[1]) {
610 dlg_error_msg(dlg, "You need to specify a source port number");
611 return;
612 }
613 p = str + strlen(str);
614 *p++ = '\t';
615 dlg_editbox_get(pfd->destbox, dlg, p, sizeof(str)-1 - (p - str));
616 if (!*p || !strchr(p, ':')) {
617 dlg_error_msg(dlg,
618 "You need to specify a destination address\n"
619 "in the form \"host.name:port\"");
620 return;
621 }
622 p = cfg->portfwd;
623 while (*p) {
624 while (*p)
625 p++;
626 p++;
627 }
628 if ((p - cfg->portfwd) + strlen(str) + 2 <
629 sizeof(cfg->portfwd)) {
630 strcpy(p, str);
631 p[strlen(str) + 1] = '\0';
632 dlg_listbox_add(pfd->listbox, dlg, str);
633 dlg_editbox_set(pfd->sourcebox, dlg, "");
634 dlg_editbox_set(pfd->destbox, dlg, "");
635 } else {
636 dlg_error_msg(dlg, "Too many forwardings");
637 }
638 } else if (ctrl == pfd->rembutton) {
639 int i = dlg_listbox_index(pfd->listbox, dlg);
640 if (i < 0)
641 dlg_beep(dlg);
642 else {
643 char *p, *q;
644
645 dlg_listbox_del(pfd->listbox, dlg, i);
646 p = cfg->portfwd;
647 while (i > 0) {
648 if (!*p)
649 goto disaster2;
650 while (*p)
651 p++;
652 p++;
653 i--;
654 }
655 q = p;
656 if (!*p)
657 goto disaster2;
658 while (*p)
659 p++;
660 p++;
661 while (*p) {
662 while (*p)
663 *q++ = *p++;
664 *q++ = *p++;
665 }
666 *q = '\0';
667 disaster2:;
668 }
669 }
670 }
671}
672
673void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
674 int midsession, int protocol)
675{
676 struct controlset *s;
677 struct sessionsaver_data *ssd;
678 struct charclass_data *ccd;
679 struct colour_data *cd;
680 struct environ_data *ed;
681 struct portfwd_data *pfd;
682 union control *c;
683
684 ssd = (struct sessionsaver_data *)
685 ctrl_alloc(b, sizeof(struct sessionsaver_data));
686 ssd->sesslist = (midsession ? NULL : sesslist);
687
688 /*
689 * The standard panel that appears at the bottom of all panels:
690 * Open, Cancel, Apply etc.
691 */
692 s = ctrl_getset(b, "", "", "");
693 ctrl_columns(s, 5, 20, 20, 20, 20, 20);
694 ssd->okbutton = ctrl_pushbutton(s,
695 (midsession ? "Apply" : "Open"),
696 (char)(midsession ? 'a' : 'o'),
697 HELPCTX(no_help),
698 sessionsaver_handler, P(ssd));
699 ssd->okbutton->button.isdefault = TRUE;
700 ssd->okbutton->generic.column = 3;
701 ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help),
702 sessionsaver_handler, P(ssd));
703 ssd->cancelbutton->generic.column = 4;
704 /* We carefully don't close the 5-column part, so that platform-
705 * specific add-ons can put extra buttons alongside Open and Cancel. */
706
707 /*
708 * The Session panel.
709 */
710 ctrl_settitle(b, "Session", "Basic options for your PuTTY session");
711
712 if (!midsession) {
713 s = ctrl_getset(b, "Session", "hostport",
714 "Specify your connection by host name or IP address");
715 ctrl_columns(s, 2, 75, 25);
716 c = ctrl_editbox(s, "Host Name (or IP address)", 'n', 100,
717 HELPCTX(session_hostname),
718 dlg_stdeditbox_handler, I(offsetof(Config,host)),
719 I(sizeof(((Config *)0)->host)));
720 c->generic.column = 0;
721 c = ctrl_editbox(s, "Port", 'p', 100, HELPCTX(session_hostname),
722 dlg_stdeditbox_handler,
723 I(offsetof(Config,port)), I(-1));
724 c->generic.column = 1;
725 ctrl_columns(s, 1, 100);
726 if (backends[3].backend == NULL) {
727 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 3,
728 HELPCTX(session_hostname),
729 protocolbuttons_handler, P(c),
730 "Raw", 'r', I(PROT_RAW),
731 "Telnet", 't', I(PROT_TELNET),
732 "Rlogin", 'i', I(PROT_RLOGIN),
733 NULL);
734 } else {
735 ctrl_radiobuttons(s, "Protocol:", NO_SHORTCUT, 4,
736 HELPCTX(session_hostname),
737 protocolbuttons_handler, P(c),
738 "Raw", 'r', I(PROT_RAW),
739 "Telnet", 't', I(PROT_TELNET),
740 "Rlogin", 'i', I(PROT_RLOGIN),
741 "SSH", 's', I(PROT_SSH),
742 NULL);
743 }
744
745 s = ctrl_getset(b, "Session", "savedsessions",
746 "Load, save or delete a stored session");
747 ctrl_columns(s, 2, 75, 25);
fe8abbf4 748 ssd->sesslist = sesslist;
749 ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
750 HELPCTX(session_saved),
751 sessionsaver_handler, P(ssd), P(NULL));
752 ssd->editbox->generic.column = 0;
753 /* Reset columns so that the buttons are alongside the list, rather
754 * than alongside that edit box. */
755 ctrl_columns(s, 1, 100);
756 ctrl_columns(s, 2, 75, 25);
757 ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l',
758 HELPCTX(session_saved),
759 sessionsaver_handler, P(ssd));
760 ssd->loadbutton->generic.column = 1;
761 ssd->savebutton = ctrl_pushbutton(s, "Save", 'v',
762 HELPCTX(session_saved),
763 sessionsaver_handler, P(ssd));
764 ssd->savebutton->generic.column = 1;
765 ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd',
766 HELPCTX(session_saved),
767 sessionsaver_handler, P(ssd));
768 ssd->delbutton->generic.column = 1;
769 ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
770 HELPCTX(session_saved),
771 sessionsaver_handler, P(ssd));
772 ssd->listbox->generic.column = 0;
773 ssd->listbox->listbox.height = 7;
774 ctrl_columns(s, 1, 100);
775 }
776
777 s = ctrl_getset(b, "Session", "otheropts", NULL);
778 c = ctrl_radiobuttons(s, "Close window on exit:", 'w', 4,
779 HELPCTX(session_coe),
780 dlg_stdradiobutton_handler,
781 I(offsetof(Config, close_on_exit)),
782 "Always", I(FORCE_ON),
783 "Never", I(FORCE_OFF),
784 "Only on clean exit", I(AUTO), NULL);
785
786 /*
787 * The Session/Logging panel.
788 */
789 ctrl_settitle(b, "Session/Logging", "Options controlling session logging");
790
791 s = ctrl_getset(b, "Session/Logging", "main", NULL);
792 ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 1,
793 HELPCTX(logging_main),
794 dlg_stdradiobutton_handler, I(offsetof(Config, logtype)),
795 "Logging turned off completely", 't', I(LGTYP_NONE),
796 "Log printable output only", 'p', I(LGTYP_ASCII),
797 "Log all session output", 'l', I(LGTYP_DEBUG),
798 "Log SSH packet data", 's', I(LGTYP_PACKETS),
799 NULL);
800 ctrl_filesel(s, "Log file name:", 'f',
801 NULL, TRUE, "Select session log file name",
802 HELPCTX(logging_filename),
803 dlg_stdfilesel_handler, I(offsetof(Config, logfilename)));
804 ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
805 " &T for time, and &H for host name)",
806 HELPCTX(logging_filename));
807 ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
808 HELPCTX(logging_exists),
809 dlg_stdradiobutton_handler, I(offsetof(Config,logxfovr)),
810 "Always overwrite it", I(LGXF_OVR),
811 "Always append to the end of it", I(LGXF_APN),
812 "Ask the user every time", I(LGXF_ASK), NULL);
813
814 /*
815 * The Terminal panel.
816 */
817 ctrl_settitle(b, "Terminal", "Options controlling the terminal emulation");
818
819 s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
820 ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
821 HELPCTX(terminal_autowrap),
822 dlg_stdcheckbox_handler, I(offsetof(Config,wrap_mode)));
823 ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
824 HELPCTX(terminal_decom),
825 dlg_stdcheckbox_handler, I(offsetof(Config,dec_om)));
826 ctrl_checkbox(s, "Implicit CR in every LF", 'r',
827 HELPCTX(terminal_lfhascr),
828 dlg_stdcheckbox_handler, I(offsetof(Config,lfhascr)));
829 ctrl_checkbox(s, "Use background colour to erase screen", 'e',
830 HELPCTX(terminal_bce),
831 dlg_stdcheckbox_handler, I(offsetof(Config,bce)));
832 ctrl_checkbox(s, "Enable blinking text", 'n',
833 HELPCTX(terminal_blink),
834 dlg_stdcheckbox_handler, I(offsetof(Config,blinktext)));
835 ctrl_editbox(s, "Answerback to ^E:", 's', 100,
836 HELPCTX(terminal_answerback),
837 dlg_stdeditbox_handler, I(offsetof(Config,answerback)),
838 I(sizeof(((Config *)0)->answerback)));
839
840 s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
841 ctrl_radiobuttons(s, "Local echo:", 'l', 3,
842 HELPCTX(terminal_localecho),
843 dlg_stdradiobutton_handler,I(offsetof(Config,localecho)),
844 "Auto", I(AUTO),
845 "Force on", I(FORCE_ON),
846 "Force off", I(FORCE_OFF), NULL);
847 ctrl_radiobuttons(s, "Local line editing:", 't', 3,
848 HELPCTX(terminal_localedit),
849 dlg_stdradiobutton_handler,I(offsetof(Config,localedit)),
850 "Auto", I(AUTO),
851 "Force on", I(FORCE_ON),
852 "Force off", I(FORCE_OFF), NULL);
853
854 s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
855 ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100,
856 HELPCTX(terminal_printing),
857 printerbox_handler, P(NULL), P(NULL));
858
859 /*
860 * The Terminal/Keyboard panel.
861 */
862 ctrl_settitle(b, "Terminal/Keyboard",
863 "Options controlling the effects of keys");
864
865 s = ctrl_getset(b, "Terminal/Keyboard", "mappings",
866 "Change the sequences sent by:");
867 ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
868 HELPCTX(keyboard_backspace),
869 dlg_stdradiobutton_handler,
870 I(offsetof(Config, bksp_is_delete)),
871 "Control-H", I(0), "Control-? (127)", I(1), NULL);
872 ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
873 HELPCTX(keyboard_homeend),
874 dlg_stdradiobutton_handler,
875 I(offsetof(Config, rxvt_homeend)),
876 "Standard", I(0), "rxvt", I(1), NULL);
877 ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3,
878 HELPCTX(keyboard_funkeys),
879 dlg_stdradiobutton_handler,
880 I(offsetof(Config, funky_type)),
881 "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2),
882 "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL);
883
884 s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad",
885 "Application keypad settings:");
886 ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
887 HELPCTX(keyboard_appcursor),
888 dlg_stdradiobutton_handler,
889 I(offsetof(Config, app_cursor)),
890 "Normal", I(0), "Application", I(1), NULL);
891 ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
892 HELPCTX(keyboard_appkeypad),
893 numeric_keypad_handler, P(NULL),
894 "Normal", I(0), "Application", I(1), "NetHack", I(2),
895 NULL);
896
897 /*
898 * The Terminal/Bell panel.
899 */
900 ctrl_settitle(b, "Terminal/Bell",
901 "Options controlling the terminal bell");
902
903 s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
904 ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
905 HELPCTX(bell_style),
906 dlg_stdradiobutton_handler, I(offsetof(Config, beep)),
907 "None (bell disabled)", I(BELL_DISABLED),
908 "Make default system alert sound", I(BELL_DEFAULT),
909 "Visual bell (flash window)", I(BELL_VISUAL), NULL);
910
911 s = ctrl_getset(b, "Terminal/Bell", "overload",
912 "Control the bell overload behaviour");
913 ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
914 HELPCTX(bell_overload),
915 dlg_stdcheckbox_handler, I(offsetof(Config,bellovl)));
916 ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
917 HELPCTX(bell_overload),
918 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_n)), I(-1));
919 ctrl_editbox(s, "... in this many seconds", 't', 20,
920 HELPCTX(bell_overload),
921 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_t)),
922 I(-1000));
923 ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
924 HELPCTX(bell_overload));
925 ctrl_editbox(s, "Seconds of silence required", 's', 20,
926 HELPCTX(bell_overload),
927 dlg_stdeditbox_handler, I(offsetof(Config,bellovl_s)),
928 I(-1000));
929
930 /*
931 * The Terminal/Features panel.
932 */
933 ctrl_settitle(b, "Terminal/Features",
934 "Enabling and disabling advanced terminal features");
935
936 s = ctrl_getset(b, "Terminal/Features", "main", NULL);
937 ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
938 HELPCTX(features_application),
939 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_c)));
940 ctrl_checkbox(s, "Disable application keypad mode", 'k',
941 HELPCTX(features_application),
942 dlg_stdcheckbox_handler, I(offsetof(Config,no_applic_k)));
943 ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
944 HELPCTX(features_mouse),
945 dlg_stdcheckbox_handler, I(offsetof(Config,no_mouse_rep)));
946 ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
947 HELPCTX(features_resize),
948 dlg_stdcheckbox_handler,
949 I(offsetof(Config,no_remote_resize)));
950 ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
951 HELPCTX(features_altscreen),
952 dlg_stdcheckbox_handler, I(offsetof(Config,no_alt_screen)));
953 ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
954 HELPCTX(features_retitle),
955 dlg_stdcheckbox_handler,
956 I(offsetof(Config,no_remote_wintitle)));
957 ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
958 HELPCTX(features_dbackspace),
959 dlg_stdcheckbox_handler, I(offsetof(Config,no_dbackspace)));
960 ctrl_checkbox(s, "Disable remote-controlled character set configuration",
961 'r', HELPCTX(features_charset), dlg_stdcheckbox_handler,
962 I(offsetof(Config,no_remote_charset)));
963
964 /*
965 * The Window panel.
966 */
967 ctrl_settitle(b, "Window", "Options controlling PuTTY's window");
968
969 s = ctrl_getset(b, "Window", "size", "Set the size of the window");
970 ctrl_columns(s, 2, 50, 50);
971 c = ctrl_editbox(s, "Rows", 'r', 100,
972 HELPCTX(window_size),
973 dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
974 c->generic.column = 0;
975 c = ctrl_editbox(s, "Columns", 'm', 100,
976 HELPCTX(window_size),
977 dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
978 c->generic.column = 1;
979 ctrl_columns(s, 1, 100);
980
981 s = ctrl_getset(b, "Window", "scrollback",
982 "Control the scrollback in the window");
983 ctrl_editbox(s, "Lines of scrollback", 's', 50,
984 HELPCTX(window_scrollback),
985 dlg_stdeditbox_handler, I(offsetof(Config,savelines)), I(-1));
986 ctrl_checkbox(s, "Display scrollbar", 'd',
987 HELPCTX(window_scrollback),
988 dlg_stdcheckbox_handler, I(offsetof(Config,scrollbar)));
989 ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
990 HELPCTX(window_scrollback),
991 dlg_stdcheckbox_handler,
992 I(offsetof(Config,scrollbar_in_fullscreen)));
993 ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
994 HELPCTX(window_scrollback),
995 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_key)));
996 ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
997 HELPCTX(window_scrollback),
998 dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp)));
876e5d5e 999 ctrl_checkbox(s, "Push erased text into scrollback", 'e',
1000 HELPCTX(window_erased),
1001 dlg_stdcheckbox_handler,
1002 I(offsetof(Config,erase_to_scrollback)));
fe8abbf4 1003
1004 /*
1005 * The Window/Appearance panel.
1006 */
1007 ctrl_settitle(b, "Window/Appearance",
1008 "Configure the appearance of PuTTY's window");
1009
1010 s = ctrl_getset(b, "Window/Appearance", "cursor",
1011 "Adjust the use of the cursor");
1012 ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
1013 HELPCTX(appearance_cursor),
1014 dlg_stdradiobutton_handler,
1015 I(offsetof(Config, cursor_type)),
1016 "Block", 'l', I(0),
1017 "Underline", 'u', I(1),
1018 "Vertical line", 'v', I(2), NULL);
1019 ctrl_checkbox(s, "Cursor blinks", 'b',
1020 HELPCTX(appearance_cursor),
1021 dlg_stdcheckbox_handler, I(offsetof(Config,blink_cur)));
1022
1023 s = ctrl_getset(b, "Window/Appearance", "font",
1024 "Font settings");
1025 ctrl_fontsel(s, "Font used in the terminal window", 'n',
1026 HELPCTX(appearance_font),
1027 dlg_stdfontsel_handler, I(offsetof(Config, font)));
1028
1029 s = ctrl_getset(b, "Window/Appearance", "mouse",
1030 "Adjust the use of the mouse pointer");
1031 ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
1032 HELPCTX(appearance_hidemouse),
1033 dlg_stdcheckbox_handler, I(offsetof(Config,hide_mouseptr)));
1034
1035 s = ctrl_getset(b, "Window/Appearance", "border",
1036 "Adjust the window border");
1037 ctrl_editbox(s, "Gap between text and window edge:", NO_SHORTCUT, 20,
1038 HELPCTX(appearance_border),
1039 dlg_stdeditbox_handler,
1040 I(offsetof(Config,window_border)), I(-1));
1041
1042 /*
1043 * The Window/Behaviour panel.
1044 */
1045 ctrl_settitle(b, "Window/Behaviour",
1046 "Configure the behaviour of PuTTY's window");
1047
1048 s = ctrl_getset(b, "Window/Behaviour", "title",
1049 "Adjust the behaviour of the window title");
1050 ctrl_editbox(s, "Window title:", 't', 100,
1051 HELPCTX(appearance_title),
1052 dlg_stdeditbox_handler, I(offsetof(Config,wintitle)),
1053 I(sizeof(((Config *)0)->wintitle)));
1054 ctrl_checkbox(s, "Separate window and icon titles", 'i',
1055 HELPCTX(appearance_title),
1056 dlg_stdcheckbox_handler,
1057 I(CHECKBOX_INVERT | offsetof(Config,win_name_always)));
1058
1059 s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
1060 ctrl_checkbox(s, "Warn before closing window", 'w',
1061 HELPCTX(behaviour_closewarn),
1062 dlg_stdcheckbox_handler, I(offsetof(Config,warn_on_close)));
1063
1064 /*
1065 * The Window/Translation panel.
1066 */
1067 ctrl_settitle(b, "Window/Translation",
1068 "Options controlling character set translation");
1069
1070 s = ctrl_getset(b, "Window/Translation", "trans",
1071 "Character set translation on received data");
1072 ctrl_combobox(s, "Received data assumed to be in which character set:",
1073 'r', 100, HELPCTX(translation_codepage),
1074 codepage_handler, P(NULL), P(NULL));
1075
1076 s = ctrl_getset(b, "Window/Translation", "linedraw",
1077 "Adjust how PuTTY displays line drawing characters");
1078 ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1,
1079 HELPCTX(translation_linedraw),
1080 dlg_stdradiobutton_handler,
1081 I(offsetof(Config, vtmode)),
1082 "Font has XWindows encoding", 'x', I(VT_XWINDOWS),
1083 "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN),
1084 "Unicode mode", 'u', I(VT_UNICODE), NULL);
1085
1086 /*
1087 * The Window/Selection panel.
1088 */
1089 ctrl_settitle(b, "Window/Selection", "Options controlling copy and paste");
1090
1091 s = ctrl_getset(b, "Window/Selection", "trans",
1092 "Translation of pasted characters");
1093 ctrl_checkbox(s, "Don't translate line drawing chars into +, - and |",'d',
1094 HELPCTX(selection_linedraw),
1095 dlg_stdcheckbox_handler, I(offsetof(Config,rawcnp)));
1096
1097 s = ctrl_getset(b, "Window/Selection", "mouse",
1098 "Control use of mouse");
1099 ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
1100 HELPCTX(selection_shiftdrag),
1101 dlg_stdcheckbox_handler, I(offsetof(Config,mouse_override)));
1102 ctrl_radiobuttons(s,
1103 "Default selection mode (Alt+drag does the other one):",
1104 NO_SHORTCUT, 2,
1105 HELPCTX(selection_rect),
1106 dlg_stdradiobutton_handler,
1107 I(offsetof(Config, rect_select)),
1108 "Normal", 'n', I(0),
1109 "Rectangular block", 'r', I(1), NULL);
1110
1111 s = ctrl_getset(b, "Window/Selection", "charclass",
1112 "Control the select-one-word-at-a-time mode");
1113 ccd = (struct charclass_data *)
1114 ctrl_alloc(b, sizeof(struct charclass_data));
1115 ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
1116 HELPCTX(selection_charclasses),
1117 charclass_handler, P(ccd));
1118 ccd->listbox->listbox.multisel = 1;
1119 ccd->listbox->listbox.ncols = 4;
1120 ccd->listbox->listbox.percentages = smalloc(4*sizeof(int));
1121 ccd->listbox->listbox.percentages[0] = 15;
1122 ccd->listbox->listbox.percentages[1] = 25;
1123 ccd->listbox->listbox.percentages[2] = 20;
1124 ccd->listbox->listbox.percentages[3] = 40;
1125 ctrl_columns(s, 2, 67, 33);
1126 ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
1127 HELPCTX(selection_charclasses),
1128 charclass_handler, P(ccd), P(NULL));
1129 ccd->editbox->generic.column = 0;
1130 ccd->button = ctrl_pushbutton(s, "Set", 's',
1131 HELPCTX(selection_charclasses),
1132 charclass_handler, P(ccd));
1133 ccd->button->generic.column = 1;
1134 ctrl_columns(s, 1, 100);
1135
1136 /*
1137 * The Window/Colours panel.
1138 */
1139 ctrl_settitle(b, "Window/Colours", "Options controlling use of colours");
1140
1141 s = ctrl_getset(b, "Window/Colours", "general",
1142 "General options for colour usage");
1143 ctrl_checkbox(s, "Bolded text is a different colour", 'b',
1144 HELPCTX(colours_bold),
1145 dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour)));
1146
1147 s = ctrl_getset(b, "Window/Colours", "adjust",
1148 "Adjust the precise colours PuTTY displays");
1149 ctrl_text(s, "Select a colour from the list, and then click the"
1150 " Modify button to change its appearance.",
1151 HELPCTX(colours_config));
1152 ctrl_columns(s, 2, 67, 33);
1153 cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data));
1154 cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u',
1155 HELPCTX(colours_config), colour_handler, P(cd));
1156 cd->listbox->generic.column = 0;
1157 c = ctrl_text(s, "RGB value:", HELPCTX(colours_config));
1158 c->generic.column = 1;
1159 cd->rgbtext = ctrl_text(s, "00/00/00", HELPCTX(colours_config));
1160 cd->rgbtext->generic.column = 1;
1161 cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config),
1162 colour_handler, P(cd));
1163 cd->button->generic.column = 1;
1164 ctrl_columns(s, 1, 100);
1165
1166 /*
1167 * The Connection panel.
1168 */
1169 ctrl_settitle(b, "Connection", "Options controlling the connection");
1170
1171 if (!midsession) {
1172 s = ctrl_getset(b, "Connection", "data", "Data to send to the server");
1173 ctrl_editbox(s, "Terminal-type string", 't', 50,
1174 HELPCTX(connection_termtype),
1175 dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
1176 I(sizeof(((Config *)0)->termtype)));
1177 ctrl_editbox(s, "Auto-login username", 'u', 50,
1178 HELPCTX(connection_username),
1179 dlg_stdeditbox_handler, I(offsetof(Config,username)),
1180 I(sizeof(((Config *)0)->username)));
1181 }
1182
1183 s = ctrl_getset(b, "Connection", "keepalive",
1184 "Sending of null packets to keep session active");
1185 ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
1186 HELPCTX(connection_keepalive),
1187 dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
1188 I(-1));
1189
1190 if (!midsession) {
1191 s = ctrl_getset(b, "Connection", "tcp",
1192 "Low-level TCP connection options");
1193 ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)", 'n',
1194 HELPCTX(connection_nodelay),
1195 dlg_stdcheckbox_handler,
1196 I(offsetof(Config,tcp_nodelay)));
1197 }
1198
1199 if (!midsession) {
1200 /*
1201 * The Connection/Proxy panel.
1202 */
1203 ctrl_settitle(b, "Connection/Proxy",
1204 "Options controlling proxy usage");
1205
1206 s = ctrl_getset(b, "Connection/Proxy", "basics", "Proxy basics");
1207 ctrl_radiobuttons(s, "Proxy type:", NO_SHORTCUT, 4,
1208 HELPCTX(proxy_type),
1209 dlg_stdradiobutton_handler,
1210 I(offsetof(Config, proxy_type)),
1211 "None", 'n', I(PROXY_NONE),
1212 "HTTP", 't', I(PROXY_HTTP),
1213 "SOCKS", 's', I(PROXY_SOCKS),
1214 "Telnet", 'l', I(PROXY_TELNET),
1215 NULL);
1216 ctrl_columns(s, 2, 80, 20);
1217 c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
1218 HELPCTX(proxy_main),
1219 dlg_stdeditbox_handler,
1220 I(offsetof(Config,proxy_host)),
1221 I(sizeof(((Config *)0)->proxy_host)));
1222 c->generic.column = 0;
1223 c = ctrl_editbox(s, "Port", 'p', 100,
1224 HELPCTX(proxy_main),
1225 dlg_stdeditbox_handler,
1226 I(offsetof(Config,proxy_port)),
1227 I(-1));
1228 c->generic.column = 1;
1229 ctrl_columns(s, 1, 100);
1230 ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
1231 HELPCTX(proxy_exclude),
1232 dlg_stdeditbox_handler,
1233 I(offsetof(Config,proxy_exclude_list)),
1234 I(sizeof(((Config *)0)->proxy_exclude_list)));
1235 ctrl_checkbox(s, "Consider proxying local host connections", 'x',
1236 HELPCTX(proxy_exclude),
1237 dlg_stdcheckbox_handler,
1238 I(offsetof(Config,even_proxy_localhost)));
1239 ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
1240 HELPCTX(proxy_dns),
1241 dlg_stdradiobutton_handler,
1242 I(offsetof(Config, proxy_dns)),
1243 "No", I(FORCE_OFF),
1244 "Auto", I(AUTO),
1245 "Yes", I(FORCE_ON), NULL);
1246 ctrl_editbox(s, "Username", 'u', 60,
1247 HELPCTX(proxy_auth),
1248 dlg_stdeditbox_handler,
1249 I(offsetof(Config,proxy_username)),
1250 I(sizeof(((Config *)0)->proxy_username)));
1251 c = ctrl_editbox(s, "Password", 'w', 60,
1252 HELPCTX(proxy_auth),
1253 dlg_stdeditbox_handler,
1254 I(offsetof(Config,proxy_password)),
1255 I(sizeof(((Config *)0)->proxy_password)));
1256 c->editbox.password = 1;
1257
1258 s = ctrl_getset(b, "Connection/Proxy", "misc",
1259 "Miscellaneous proxy settings");
1260 ctrl_editbox(s, "Telnet command", 'm', 100,
1261 HELPCTX(proxy_command),
1262 dlg_stdeditbox_handler,
1263 I(offsetof(Config,proxy_telnet_command)),
1264 I(sizeof(((Config *)0)->proxy_telnet_command)));
1265 ctrl_radiobuttons(s, "SOCKS Version", 'v', 2,
1266 HELPCTX(proxy_socksver),
1267 dlg_stdradiobutton_handler,
1268 I(offsetof(Config, proxy_socks_version)),
1269 "Version 5", I(5), "Version 4", I(4), NULL);
1270 }
1271
1272 /*
1273 * The Telnet panel exists in the base config box, and in a
1274 * mid-session reconfig box _if_ we're using Telnet.
1275 */
1276 if (!midsession || protocol == PROT_TELNET) {
1277 /*
1278 * The Connection/Telnet panel.
1279 */
1280 ctrl_settitle(b, "Connection/Telnet",
1281 "Options controlling Telnet connections");
1282
1283 if (!midsession) {
1284 s = ctrl_getset(b, "Connection/Telnet", "data",
1285 "Data to send to the server");
1286 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1287 HELPCTX(telnet_termspeed),
1288 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1289 I(sizeof(((Config *)0)->termspeed)));
1290 ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
1291 ctrl_columns(s, 2, 80, 20);
1292 ed = (struct environ_data *)
1293 ctrl_alloc(b, sizeof(struct environ_data));
1294 ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
1295 HELPCTX(telnet_environ),
1296 environ_handler, P(ed), P(NULL));
1297 ed->varbox->generic.column = 0;
1298 ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
1299 HELPCTX(telnet_environ),
1300 environ_handler, P(ed), P(NULL));
1301 ed->valbox->generic.column = 0;
1302 ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
1303 HELPCTX(telnet_environ),
1304 environ_handler, P(ed));
1305 ed->addbutton->generic.column = 1;
1306 ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1307 HELPCTX(telnet_environ),
1308 environ_handler, P(ed));
1309 ed->rembutton->generic.column = 1;
1310 ctrl_columns(s, 1, 100);
1311 ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1312 HELPCTX(telnet_environ),
1313 environ_handler, P(ed));
1314 ed->listbox->listbox.height = 3;
1315 }
1316
1317 s = ctrl_getset(b, "Connection/Telnet", "protocol",
1318 "Telnet protocol adjustments");
1319
1320 if (!midsession) {
1321 ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
1322 NO_SHORTCUT, 2,
1323 HELPCTX(telnet_oldenviron),
1324 dlg_stdradiobutton_handler,
1325 I(offsetof(Config, rfc_environ)),
1326 "BSD (commonplace)", 'b', I(0),
1327 "RFC 1408 (unusual)", 'f', I(1), NULL);
1328 ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
1329 HELPCTX(telnet_passive),
1330 dlg_stdradiobutton_handler,
1331 I(offsetof(Config, passive_telnet)),
1332 "Passive", I(1), "Active", I(0), NULL);
1333 }
1334 ctrl_checkbox(s, "Keyboard sends telnet Backspace and Interrupt", 'k',
1335 HELPCTX(telnet_specialkeys),
1336 dlg_stdcheckbox_handler,
1337 I(offsetof(Config,telnet_keyboard)));
1338 ctrl_checkbox(s, "Return key sends telnet New Line instead of ^M",
1339 NO_SHORTCUT, HELPCTX(telnet_newline),
1340 dlg_stdcheckbox_handler,
1341 I(offsetof(Config,telnet_newline)));
1342 }
1343
1344 if (!midsession) {
1345
1346 /*
1347 * The Connection/Rlogin panel.
1348 */
1349 ctrl_settitle(b, "Connection/Rlogin",
1350 "Options controlling Rlogin connections");
1351
1352 s = ctrl_getset(b, "Connection/Rlogin", "data",
1353 "Data to send to the server");
1354 ctrl_editbox(s, "Terminal-speed string", 's', 50,
1355 HELPCTX(rlogin_termspeed),
1356 dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
1357 I(sizeof(((Config *)0)->termspeed)));
1358 ctrl_editbox(s, "Local username:", 'l', 50,
1359 HELPCTX(rlogin_localuser),
1360 dlg_stdeditbox_handler, I(offsetof(Config,localusername)),
1361 I(sizeof(((Config *)0)->localusername)));
1362
1363 }
1364
1365 /*
1366 * All the SSH stuff is omitted in PuTTYtel.
1367 */
1368
1369 if (!midsession && backends[3].backend != NULL) {
1370
1371 /*
1372 * The Connection/SSH panel.
1373 */
1374 ctrl_settitle(b, "Connection/SSH",
1375 "Options controlling SSH connections");
1376
1377 s = ctrl_getset(b, "Connection/SSH", "data",
1378 "Data to send to the server");
1379 ctrl_editbox(s, "Remote command:", 'r', 100,
1380 HELPCTX(ssh_command),
1381 dlg_stdeditbox_handler, I(offsetof(Config,remote_cmd)),
1382 I(sizeof(((Config *)0)->remote_cmd)));
1383
1384 s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
1385 ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
1386 HELPCTX(ssh_nopty),
1387 dlg_stdcheckbox_handler,
1388 I(offsetof(Config,nopty)));
1389 ctrl_checkbox(s, "Enable compression", 'e',
1390 HELPCTX(ssh_compress),
1391 dlg_stdcheckbox_handler,
1392 I(offsetof(Config,compression)));
1393 ctrl_radiobuttons(s, "Preferred SSH protocol version:", NO_SHORTCUT, 4,
1394 HELPCTX(ssh_protocol),
1395 dlg_stdradiobutton_handler,
1396 I(offsetof(Config, sshprot)),
1397 "1 only", 'l', I(0),
1398 "1", '1', I(1),
1399 "2", '2', I(2),
1400 "2 only", 'n', I(3), NULL);
1401
1402 s = ctrl_getset(b, "Connection/SSH", "encryption", "Encryption options");
bb524800 1403 c = ctrl_draglist(s, "Encryption cipher selection policy:", 's',
1404 HELPCTX(ssh_ciphers),
1405 cipherlist_handler, P(NULL));
1406 c->listbox.height = 6;
1407
fe8abbf4 1408 ctrl_checkbox(s, "Enable non-standard use of single-DES in SSH 2", 'i',
1409 HELPCTX(ssh_ciphers),
1410 dlg_stdcheckbox_handler,
1411 I(offsetof(Config,ssh2_des_cbc)));
1412
1413 /*
1414 * The Connection/SSH/Auth panel.
1415 */
1416 ctrl_settitle(b, "Connection/SSH/Auth",
1417 "Options controlling SSH authentication");
1418
1419 s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
1420 "Authentication methods");
1421 ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH1)", 'm',
1422 HELPCTX(ssh_auth_tis),
1423 dlg_stdcheckbox_handler,
1424 I(offsetof(Config,try_tis_auth)));
1425 ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH2)",
1426 'i', HELPCTX(ssh_auth_ki),
1427 dlg_stdcheckbox_handler,
1428 I(offsetof(Config,try_ki_auth)));
1429
1430 s = ctrl_getset(b, "Connection/SSH/Auth", "params",
1431 "Authentication parameters");
1432 ctrl_checkbox(s, "Allow agent forwarding", 'f',
1433 HELPCTX(ssh_auth_agentfwd),
1434 dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
1435 ctrl_checkbox(s, "Allow attempted changes of username in SSH2", 'u',
1436 HELPCTX(ssh_auth_changeuser),
1437 dlg_stdcheckbox_handler,
1438 I(offsetof(Config,change_username)));
1439 ctrl_filesel(s, "Private key file for authentication:", 'k',
1440 FILTER_KEY_FILES, FALSE, "Select private key file",
1441 HELPCTX(ssh_auth_privkey),
1442 dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
1443
1444 /*
1445 * The Connection/SSH/Tunnels panel.
1446 */
1447 ctrl_settitle(b, "Connection/SSH/Tunnels",
1448 "Options controlling SSH tunnelling");
1449
1450 s = ctrl_getset(b, "Connection/SSH/Tunnels", "x11", "X11 forwarding");
1451 ctrl_checkbox(s, "Enable X11 forwarding", 'e',
1452 HELPCTX(ssh_tunnels_x11),
1453 dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
1454 ctrl_editbox(s, "X display location", 'x', 50,
1455 HELPCTX(ssh_tunnels_x11),
1456 dlg_stdeditbox_handler, I(offsetof(Config,x11_display)),
1457 I(sizeof(((Config *)0)->x11_display)));
1458 ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
1459 HELPCTX(ssh_tunnels_x11auth),
1460 dlg_stdradiobutton_handler,
1461 I(offsetof(Config, x11_auth)),
1462 "MIT-Magic-Cookie-1", I(X11_MIT),
1463 "XDM-Authorization-1", I(X11_XDM), NULL);
1464
1465 s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
1466 "Port forwarding");
1467 ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
1468 HELPCTX(ssh_tunnels_portfwd_localhost),
1469 dlg_stdcheckbox_handler,
1470 I(offsetof(Config,lport_acceptall)));
1471 ctrl_checkbox(s, "Remote ports do the same (SSH v2 only)", 'p',
1472 HELPCTX(ssh_tunnels_portfwd_localhost),
1473 dlg_stdcheckbox_handler,
1474 I(offsetof(Config,rport_acceptall)));
1475
1476 ctrl_columns(s, 3, 55, 20, 25);
1477 c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
1478 c->generic.column = COLUMN_FIELD(0,2);
1479 /* You want to select from the list, _then_ hit Remove. So tab order
1480 * should be that way round. */
1481 pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data));
1482 pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r',
1483 HELPCTX(ssh_tunnels_portfwd),
1484 portfwd_handler, P(pfd));
1485 pfd->rembutton->generic.column = 2;
1486 pfd->rembutton->generic.tabdelay = 1;
1487 pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
1488 HELPCTX(ssh_tunnels_portfwd),
1489 portfwd_handler, P(pfd));
1490 pfd->listbox->listbox.height = 3;
1491 ctrl_tabdelay(s, pfd->rembutton);
1492 ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
1493 /* You want to enter source, destination and type, _then_ hit Add.
1494 * Again, we adjust the tab order to reflect this. */
1495 pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
1496 HELPCTX(ssh_tunnels_portfwd),
1497 portfwd_handler, P(pfd));
1498 pfd->addbutton->generic.column = 2;
1499 pfd->addbutton->generic.tabdelay = 1;
1500 pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40,
1501 HELPCTX(ssh_tunnels_portfwd),
1502 portfwd_handler, P(pfd), P(NULL));
1503 pfd->sourcebox->generic.column = 0;
1504 pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67,
1505 HELPCTX(ssh_tunnels_portfwd),
1506 portfwd_handler, P(pfd), P(NULL));
1507 pfd->direction = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 2,
1508 HELPCTX(ssh_tunnels_portfwd),
1509 portfwd_handler, P(pfd),
1510 "Local", 'l', P(NULL),
1511 "Remote", 'm', P(NULL), NULL);
1512 ctrl_tabdelay(s, pfd->addbutton);
1513 ctrl_columns(s, 1, 100);
1514
1515 /*
1516 * The Connection/SSH/Bugs panel.
1517 */
1518 ctrl_settitle(b, "Connection/SSH/Bugs",
1519 "Workarounds for SSH server bugs");
1520
1521 s = ctrl_getset(b, "Connection/SSH/Bugs", "main",
1522 "Detection of known bugs in SSH servers");
1523 ctrl_droplist(s, "Chokes on SSH1 ignore messages", 'i', 20,
1524 HELPCTX(ssh_bugs_ignore1),
1525 sshbug_handler, I(offsetof(Config,sshbug_ignore1)));
1526 ctrl_droplist(s, "Refuses all SSH1 password camouflage", 's', 20,
1527 HELPCTX(ssh_bugs_plainpw1),
1528 sshbug_handler, I(offsetof(Config,sshbug_plainpw1)));
1529 ctrl_droplist(s, "Chokes on SSH1 RSA authentication", 'r', 20,
1530 HELPCTX(ssh_bugs_rsa1),
1531 sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
1532 ctrl_droplist(s, "Miscomputes SSH2 HMAC keys", 'm', 20,
1533 HELPCTX(ssh_bugs_hmac2),
1534 sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
1535 ctrl_droplist(s, "Miscomputes SSH2 encryption keys", 'e', 20,
1536 HELPCTX(ssh_bugs_derivekey2),
1537 sshbug_handler, I(offsetof(Config,sshbug_derivekey2)));
1538 ctrl_droplist(s, "Requires padding on SSH2 RSA signatures", 'p', 20,
1539 HELPCTX(ssh_bugs_rsapad2),
1540 sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
1541 ctrl_droplist(s, "Chokes on Diffie-Hellman group exchange", 'd', 20,
1542 HELPCTX(ssh_bugs_dhgex2),
1543 sshbug_handler, I(offsetof(Config,sshbug_dhgex2)));
1544 ctrl_droplist(s, "Misuses the session ID in PK auth", 'n', 20,
1545 HELPCTX(ssh_bugs_pksessid2),
1546 sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));
1547 }
1548}