]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/wincfg.c
first pass
[PuTTY.git] / windows / wincfg.c
1 /*
2  * wincfg.c - the Windows-specific parts of the PuTTY configuration
3  * 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 static void about_handler(union control *ctrl, void *dlg,
14                           void *data, int event)
15 {
16     HWND *hwndp = (HWND *)ctrl->generic.context.p;
17
18     if (event == EVENT_ACTION) {
19         modal_about_box(*hwndp);
20     }
21 }
22
23 static void help_handler(union control *ctrl, void *dlg,
24                          void *data, int event)
25 {
26     HWND *hwndp = (HWND *)ctrl->generic.context.p;
27
28     if (event == EVENT_ACTION) {
29         show_help(*hwndp);
30     }
31 }
32
33 static void variable_pitch_handler(union control *ctrl, void *dlg,
34                                    void *data, int event)
35 {
36     if (event == EVENT_REFRESH) {
37         dlg_checkbox_set(ctrl, dlg, !dlg_get_fixed_pitch_flag(dlg));
38     } else if (event == EVENT_VALCHANGE) {
39         dlg_set_fixed_pitch_flag(dlg, !dlg_checkbox_get(ctrl, dlg));
40     }
41 }
42
43 void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
44                           int midsession, int protocol)
45 {
46     struct controlset *s;
47     union control *c;
48     char *str;
49
50     if (!midsession) {
51         /*
52          * Add the About and Help buttons to the standard panel.
53          */
54         s = ctrl_getset(b, "", "", "");
55         c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
56                             about_handler, P(hwndp));
57         c->generic.column = 0;
58         if (has_help) {
59             c = ctrl_pushbutton(s, "Help", 'h', HELPCTX(no_help),
60                                 help_handler, P(hwndp));
61             c->generic.column = 1;
62         }
63     }
64
65     /*
66      * Full-screen mode is a Windows peculiarity; hence
67      * scrollbar_in_fullscreen is as well.
68      */
69     s = ctrl_getset(b, "Window", "scrollback",
70                     "Control the scrollback in the window");
71     ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
72                   HELPCTX(window_scrollback),
73                   conf_checkbox_handler,
74                   I(CONF_scrollbar_in_fullscreen));
75     /*
76      * Really this wants to go just after `Display scrollbar'. See
77      * if we can find that control, and do some shuffling.
78      */
79     {
80         int i;
81         for (i = 0; i < s->ncontrols; i++) {
82             c = s->ctrls[i];
83             if (c->generic.type == CTRL_CHECKBOX &&
84                 c->generic.context.i == CONF_scrollbar) {
85                 /*
86                  * Control i is the scrollbar checkbox.
87                  * Control s->ncontrols-1 is the scrollbar-in-FS one.
88                  */
89                 if (i < s->ncontrols-2) {
90                     c = s->ctrls[s->ncontrols-1];
91                     memmove(s->ctrls+i+2, s->ctrls+i+1,
92                             (s->ncontrols-i-2)*sizeof(union control *));
93                     s->ctrls[i+1] = c;
94                 }
95                 break;
96             }
97         }
98     }
99
100     /*
101      * Windows has the AltGr key, which has various Windows-
102      * specific options.
103      */
104     s = ctrl_getset(b, "Terminal/Keyboard", "features",
105                     "Enable extra keyboard features:");
106     ctrl_checkbox(s, "AltGr acts as Compose key", 't',
107                   HELPCTX(keyboard_compose),
108                   conf_checkbox_handler, I(CONF_compose_key));
109     ctrl_checkbox(s, "Control-Alt is different from AltGr", 'd',
110                   HELPCTX(keyboard_ctrlalt),
111                   conf_checkbox_handler, I(CONF_ctrlaltkeys));
112
113     /*
114      * Windows allows an arbitrary .WAV to be played as a bell, and
115      * also the use of the PC speaker. For this we must search the
116      * existing controlset for the radio-button set controlling the
117      * `beep' option, and add extra buttons to it.
118      * 
119      * Note that although this _looks_ like a hideous hack, it's
120      * actually all above board. The well-defined interface to the
121      * per-platform dialog box code is the _data structures_ `union
122      * control', `struct controlset' and so on; so code like this
123      * that reaches into those data structures and changes bits of
124      * them is perfectly legitimate and crosses no boundaries. All
125      * the ctrl_* routines that create most of the controls are
126      * convenient shortcuts provided on the cross-platform side of
127      * the interface, and template creation code is under no actual
128      * obligation to use them.
129      */
130     s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
131     {
132         int i;
133         for (i = 0; i < s->ncontrols; i++) {
134             c = s->ctrls[i];
135             if (c->generic.type == CTRL_RADIO &&
136                 c->generic.context.i == CONF_beep) {
137                 assert(c->generic.handler == conf_radiobutton_handler);
138                 c->radio.nbuttons += 2;
139                 c->radio.buttons =
140                     sresize(c->radio.buttons, c->radio.nbuttons, char *);
141                 c->radio.buttons[c->radio.nbuttons-1] =
142                     dupstr("Play a custom sound file");
143                 c->radio.buttons[c->radio.nbuttons-2] =
144                     dupstr("Beep using the PC speaker");
145                 c->radio.buttondata =
146                     sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
147                 c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
148                 c->radio.buttondata[c->radio.nbuttons-2] = I(BELL_PCSPEAKER);
149                 if (c->radio.shortcuts) {
150                     c->radio.shortcuts =
151                         sresize(c->radio.shortcuts, c->radio.nbuttons, char);
152                     c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
153                     c->radio.shortcuts[c->radio.nbuttons-2] = NO_SHORTCUT;
154                 }
155                 break;
156             }
157         }
158     }
159     ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,
160                  FILTER_WAVE_FILES, FALSE, "Select bell sound file",
161                  HELPCTX(bell_style),
162                  conf_filesel_handler, I(CONF_bell_wavefile));
163
164     /*
165      * While we've got this box open, taskbar flashing on a bell is
166      * also Windows-specific.
167      */
168     ctrl_radiobuttons(s, "Taskbar/caption indication on bell:", 'i', 3,
169                       HELPCTX(bell_taskbar),
170                       conf_radiobutton_handler,
171                       I(CONF_beep_ind),
172                       "Disabled", I(B_IND_DISABLED),
173                       "Flashing", I(B_IND_FLASH),
174                       "Steady", I(B_IND_STEADY), NULL);
175
176     /*
177      * The sunken-edge border is a Windows GUI feature.
178      */
179     s = ctrl_getset(b, "Window/Appearance", "border",
180                     "Adjust the window border");
181     ctrl_checkbox(s, "Sunken-edge border (slightly thicker)", 's',
182                   HELPCTX(appearance_border),
183                   conf_checkbox_handler, I(CONF_sunken_edge));
184
185     /*
186      * Configurable font quality settings for Windows.
187      */
188     s = ctrl_getset(b, "Window/Appearance", "font",
189                     "Font settings");
190     ctrl_checkbox(s, "Allow selection of variable-pitch fonts", NO_SHORTCUT,
191                   HELPCTX(appearance_font), variable_pitch_handler, I(0));
192     ctrl_radiobuttons(s, "Font quality:", 'q', 2,
193                       HELPCTX(appearance_font),
194                       conf_radiobutton_handler,
195                       I(CONF_font_quality),
196                       "Antialiased", I(FQ_ANTIALIASED),
197                       "Non-Antialiased", I(FQ_NONANTIALIASED),
198                       "ClearType", I(FQ_CLEARTYPE),
199                       "Default", I(FQ_DEFAULT), NULL);
200
201     /*
202      * Cyrillic Lock is a horrid misfeature even on Windows, and
203      * the least we can do is ensure it never makes it to any other
204      * platform (at least unless someone fixes it!).
205      */
206     s = ctrl_getset(b, "Window/Translation", "tweaks", NULL);
207     ctrl_checkbox(s, "Caps Lock acts as Cyrillic switch", 's',
208                   HELPCTX(translation_cyrillic),
209                   conf_checkbox_handler,
210                   I(CONF_xlat_capslockcyr));
211
212     /*
213      * On Windows we can use but not enumerate translation tables
214      * from the operating system. Briefly document this.
215      */
216     s = ctrl_getset(b, "Window/Translation", "trans",
217                     "Character set translation on received data");
218     ctrl_text(s, "(Codepages supported by Windows but not listed here, "
219               "such as CP866 on many systems, can be entered manually)",
220               HELPCTX(translation_codepage));
221
222     /*
223      * Windows has the weird OEM font mode, which gives us some
224      * additional options when working with line-drawing
225      * characters.
226      */
227     str = dupprintf("Adjust how %s displays line drawing characters", appname);
228     s = ctrl_getset(b, "Window/Translation", "linedraw", str);
229     sfree(str);
230     {
231         int i;
232         for (i = 0; i < s->ncontrols; i++) {
233             c = s->ctrls[i];
234             if (c->generic.type == CTRL_RADIO &&
235                 c->generic.context.i == CONF_vtmode) {
236                 assert(c->generic.handler == conf_radiobutton_handler);
237                 c->radio.nbuttons += 3;
238                 c->radio.buttons =
239                     sresize(c->radio.buttons, c->radio.nbuttons, char *);
240                 c->radio.buttons[c->radio.nbuttons-3] =
241                     dupstr("Font has XWindows encoding");
242                 c->radio.buttons[c->radio.nbuttons-2] =
243                     dupstr("Use font in both ANSI and OEM modes");
244                 c->radio.buttons[c->radio.nbuttons-1] =
245                     dupstr("Use font in OEM mode only");
246                 c->radio.buttondata =
247                     sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
248                 c->radio.buttondata[c->radio.nbuttons-3] = I(VT_XWINDOWS);
249                 c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
250                 c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
251                 if (!c->radio.shortcuts) {
252                     int j;
253                     c->radio.shortcuts = snewn(c->radio.nbuttons, char);
254                     for (j = 0; j < c->radio.nbuttons; j++)
255                         c->radio.shortcuts[j] = NO_SHORTCUT;
256                 } else {
257                     c->radio.shortcuts = sresize(c->radio.shortcuts,
258                                                  c->radio.nbuttons, char);
259                 }
260                 c->radio.shortcuts[c->radio.nbuttons-3] = 'x';
261                 c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
262                 c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
263                 break;
264             }
265         }
266     }
267
268     /*
269      * RTF paste is Windows-specific.
270      */
271     s = ctrl_getset(b, "Window/Selection", "format",
272                     "Formatting of pasted characters");
273     ctrl_checkbox(s, "Paste to clipboard in RTF as well as plain text", 'f',
274                   HELPCTX(selection_rtf),
275                   conf_checkbox_handler, I(CONF_rtf_paste));
276
277     /*
278      * Windows often has no middle button, so we supply a selection
279      * mode in which the more critical Paste action is available on
280      * the right button instead.
281      */
282     s = ctrl_getset(b, "Window/Selection", "mouse",
283                     "Control use of mouse");
284     ctrl_radiobuttons(s, "Action of mouse buttons:", 'm', 1,
285                       HELPCTX(selection_buttons),
286                       conf_radiobutton_handler,
287                       I(CONF_mouse_is_xterm),
288                       "Windows (Middle extends, Right brings up menu)", I(2),
289                       "Compromise (Middle extends, Right pastes)", I(0),
290                       "xterm (Right extends, Middle pastes)", I(1), NULL);
291     /*
292      * This really ought to go at the _top_ of its box, not the
293      * bottom, so we'll just do some shuffling now we've set it
294      * up...
295      */
296     c = s->ctrls[s->ncontrols-1];      /* this should be the new control */
297     memmove(s->ctrls+1, s->ctrls, (s->ncontrols-1)*sizeof(union control *));
298     s->ctrls[0] = c;
299
300     /*
301      * Logical palettes don't even make sense anywhere except Windows.
302      */
303     s = ctrl_getset(b, "Window/Colours", "general",
304                     "General options for colour usage");
305     ctrl_checkbox(s, "Attempt to use logical palettes", 'l',
306                   HELPCTX(colours_logpal),
307                   conf_checkbox_handler, I(CONF_try_palette));
308     ctrl_checkbox(s, "Use system colours", 's',
309                   HELPCTX(colours_system),
310                   conf_checkbox_handler, I(CONF_system_colour));
311
312
313     /*
314      * Resize-by-changing-font is a Windows insanity.
315      */
316     s = ctrl_getset(b, "Window", "size", "Set the size of the window");
317     ctrl_radiobuttons(s, "When window is resized:", 'z', 1,
318                       HELPCTX(window_resize),
319                       conf_radiobutton_handler,
320                       I(CONF_resize_action),
321                       "Change the number of rows and columns", I(RESIZE_TERM),
322                       "Change the size of the font", I(RESIZE_FONT),
323                       "Change font size only when maximised", I(RESIZE_EITHER),
324                       "Forbid resizing completely", I(RESIZE_DISABLED), NULL);
325
326     /*
327      * Most of the Window/Behaviour stuff is there to mimic Windows
328      * conventions which PuTTY can optionally disregard. Hence,
329      * most of these options are Windows-specific.
330      */
331     s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
332     ctrl_checkbox(s, "Window closes on ALT-F4", '4',
333                   HELPCTX(behaviour_altf4),
334                   conf_checkbox_handler, I(CONF_alt_f4));
335     ctrl_checkbox(s, "System menu appears on ALT-Space", 'y',
336                   HELPCTX(behaviour_altspace),
337                   conf_checkbox_handler, I(CONF_alt_space));
338     ctrl_checkbox(s, "System menu appears on ALT alone", 'l',
339                   HELPCTX(behaviour_altonly),
340                   conf_checkbox_handler, I(CONF_alt_only));
341     ctrl_checkbox(s, "Ensure window is always on top", 'e',
342                   HELPCTX(behaviour_alwaysontop),
343                   conf_checkbox_handler, I(CONF_alwaysontop));
344     ctrl_checkbox(s, "Full screen on Alt-Enter", 'f',
345                   HELPCTX(behaviour_altenter),
346                   conf_checkbox_handler,
347                   I(CONF_fullscreenonaltenter));
348
349     /*
350      * Windows supports a local-command proxy. This also means we
351      * must adjust the text on the `Telnet command' control.
352      */
353     if (!midsession) {
354         int i;
355         s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
356         for (i = 0; i < s->ncontrols; i++) {
357             c = s->ctrls[i];
358             if (c->generic.type == CTRL_RADIO &&
359                 c->generic.context.i == CONF_proxy_type) {
360                 assert(c->generic.handler == conf_radiobutton_handler);
361                 c->radio.nbuttons++;
362                 c->radio.buttons =
363                     sresize(c->radio.buttons, c->radio.nbuttons, char *);
364                 c->radio.buttons[c->radio.nbuttons-1] =
365                     dupstr("Local");
366                 c->radio.buttondata =
367                     sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
368                 c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD);
369                 break;
370             }
371         }
372
373         for (i = 0; i < s->ncontrols; i++) {
374             c = s->ctrls[i];
375             if (c->generic.type == CTRL_EDITBOX &&
376                 c->generic.context.i == CONF_proxy_telnet_command) {
377                 assert(c->generic.handler == conf_editbox_handler);
378                 sfree(c->generic.label);
379                 c->generic.label = dupstr("Telnet command, or local"
380                                           " proxy command");
381                 break;
382             }
383         }
384     }
385
386     /*
387      * Serial back end is available on Windows.
388      */
389     if (!midsession || (protocol == PROT_SERIAL))
390         ser_setup_config_box(b, midsession, 0x1F, 0x0F);
391
392     /*
393      * $XAUTHORITY is not reliable on Windows, so we provide a
394      * means to override it.
395      */
396     if (!midsession && backend_from_proto(PROT_SSH)) {
397         s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
398         ctrl_filesel(s, "X authority file for local display", 't',
399                      NULL, FALSE, "Select X authority file",
400                      HELPCTX(ssh_tunnels_xauthority),
401                      conf_filesel_handler, I(CONF_xauthfile));
402     }
403 }