wincfg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * wincfg.c - the Windows-specific parts of the PuTTY configuration
  3. * box.
  4. */
  5. #include <assert.h>
  6. #include <stdlib.h>
  7. #include "putty.h"
  8. #include "dialog.h"
  9. #include "storage.h"
  10. static void about_handler(union control *ctrl, void *dlg,
  11. void *data, int event)
  12. {
  13. HWND *hwndp = (HWND *)ctrl->generic.context.p;
  14. if (event == EVENT_ACTION) {
  15. modal_about_box(*hwndp);
  16. }
  17. }
  18. static void help_handler(union control *ctrl, void *dlg,
  19. void *data, int event)
  20. {
  21. HWND *hwndp = (HWND *)ctrl->generic.context.p;
  22. if (event == EVENT_ACTION) {
  23. show_help(*hwndp);
  24. }
  25. }
  26. void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
  27. int midsession)
  28. {
  29. struct controlset *s;
  30. union control *c;
  31. char *str;
  32. if (!midsession) {
  33. /*
  34. * Add the About and Help buttons to the standard panel.
  35. */
  36. s = ctrl_getset(b, "", "", "");
  37. c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
  38. about_handler, P(hwndp));
  39. c->generic.column = 0;
  40. if (has_help) {
  41. c = ctrl_pushbutton(s, "Help", 'h', HELPCTX(no_help),
  42. help_handler, P(hwndp));
  43. c->generic.column = 1;
  44. }
  45. }
  46. /*
  47. * Full-screen mode is a Windows peculiarity; hence
  48. * scrollbar_in_fullscreen is as well.
  49. */
  50. s = ctrl_getset(b, "Window", "scrollback",
  51. "Control the scrollback in the window");
  52. ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
  53. HELPCTX(window_scrollback),
  54. dlg_stdcheckbox_handler,
  55. I(offsetof(Config,scrollbar_in_fullscreen)));
  56. /*
  57. * Really this wants to go just after `Display scrollbar'. See
  58. * if we can find that control, and do some shuffling.
  59. */
  60. {
  61. int i;
  62. for (i = 0; i < s->ncontrols; i++) {
  63. c = s->ctrls[i];
  64. if (c->generic.type == CTRL_CHECKBOX &&
  65. c->generic.context.i == offsetof(Config,scrollbar)) {
  66. /*
  67. * Control i is the scrollbar checkbox.
  68. * Control s->ncontrols-1 is the scrollbar-in-FS one.
  69. */
  70. if (i < s->ncontrols-2) {
  71. c = s->ctrls[s->ncontrols-1];
  72. memmove(s->ctrls+i+2, s->ctrls+i+1,
  73. (s->ncontrols-i-2)*sizeof(union control *));
  74. s->ctrls[i+1] = c;
  75. }
  76. break;
  77. }
  78. }
  79. }
  80. /*
  81. * Windows has the AltGr key, which has various Windows-
  82. * specific options.
  83. */
  84. s = ctrl_getset(b, "Terminal/Keyboard", "features",
  85. "Enable extra keyboard features:");
  86. ctrl_checkbox(s, "AltGr acts as Compose key", 't',
  87. HELPCTX(keyboard_compose),
  88. dlg_stdcheckbox_handler, I(offsetof(Config,compose_key)));
  89. ctrl_checkbox(s, "Control-Alt is different from AltGr", 'd',
  90. HELPCTX(keyboard_ctrlalt),
  91. dlg_stdcheckbox_handler, I(offsetof(Config,ctrlaltkeys)));
  92. /*
  93. * Windows allows an arbitrary .WAV to be played as a bell, and
  94. * also the use of the PC speaker. For this we must search the
  95. * existing controlset for the radio-button set controlling the
  96. * `beep' option, and add extra buttons to it.
  97. *
  98. * Note that although this _looks_ like a hideous hack, it's
  99. * actually all above board. The well-defined interface to the
  100. * per-platform dialog box code is the _data structures_ `union
  101. * control', `struct controlset' and so on; so code like this
  102. * that reaches into those data structures and changes bits of
  103. * them is perfectly legitimate and crosses no boundaries. All
  104. * the ctrl_* routines that create most of the controls are
  105. * convenient shortcuts provided on the cross-platform side of
  106. * the interface, and template creation code is under no actual
  107. * obligation to use them.
  108. */
  109. s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
  110. {
  111. int i;
  112. for (i = 0; i < s->ncontrols; i++) {
  113. c = s->ctrls[i];
  114. if (c->generic.type == CTRL_RADIO &&
  115. c->generic.context.i == offsetof(Config, beep)) {
  116. assert(c->generic.handler == dlg_stdradiobutton_handler);
  117. c->radio.nbuttons += 2;
  118. c->radio.buttons =
  119. sresize(c->radio.buttons, c->radio.nbuttons, char *);
  120. c->radio.buttons[c->radio.nbuttons-1] =
  121. dupstr("Play a custom sound file");
  122. c->radio.buttons[c->radio.nbuttons-2] =
  123. dupstr("Beep using the PC speaker");
  124. c->radio.buttondata =
  125. sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
  126. c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
  127. c->radio.buttondata[c->radio.nbuttons-2] = I(BELL_PCSPEAKER);
  128. if (c->radio.shortcuts) {
  129. c->radio.shortcuts =
  130. sresize(c->radio.shortcuts, c->radio.nbuttons, char);
  131. c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
  132. c->radio.shortcuts[c->radio.nbuttons-2] = NO_SHORTCUT;
  133. }
  134. break;
  135. }
  136. }
  137. }
  138. ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,
  139. FILTER_WAVE_FILES, FALSE, "Select bell sound file",
  140. HELPCTX(bell_style),
  141. dlg_stdfilesel_handler, I(offsetof(Config, bell_wavefile)));
  142. /*
  143. * While we've got this box open, taskbar flashing on a bell is
  144. * also Windows-specific.
  145. */
  146. ctrl_radiobuttons(s, "Taskbar/caption indication on bell:", 'i', 3,
  147. HELPCTX(bell_taskbar),
  148. dlg_stdradiobutton_handler,
  149. I(offsetof(Config, beep_ind)),
  150. "Disabled", I(B_IND_DISABLED),
  151. "Flashing", I(B_IND_FLASH),
  152. "Steady", I(B_IND_STEADY), NULL);
  153. /*
  154. * The sunken-edge border is a Windows GUI feature.
  155. */
  156. s = ctrl_getset(b, "Window/Appearance", "border",
  157. "Adjust the window border");
  158. ctrl_checkbox(s, "Sunken-edge border (slightly thicker)", 's',
  159. HELPCTX(appearance_border),
  160. dlg_stdcheckbox_handler, I(offsetof(Config,sunken_edge)));
  161. /*
  162. * Cyrillic Lock is a horrid misfeature even on Windows, and
  163. * the least we can do is ensure it never makes it to any other
  164. * platform (at least unless someone fixes it!).
  165. */
  166. s = ctrl_getset(b, "Window/Translation", "input",
  167. "Enable character set translation on input data");
  168. ctrl_checkbox(s, "Caps Lock acts as Cyrillic switch", 's',
  169. HELPCTX(translation_cyrillic),
  170. dlg_stdcheckbox_handler,
  171. I(offsetof(Config,xlat_capslockcyr)));
  172. /*
  173. * Windows has the weird OEM font mode, which gives us some
  174. * additional options when working with line-drawing
  175. * characters.
  176. */
  177. str = dupprintf("Adjust how %s displays line drawing characters", appname);
  178. s = ctrl_getset(b, "Window/Translation", "linedraw", str);
  179. sfree(str);
  180. {
  181. int i;
  182. for (i = 0; i < s->ncontrols; i++) {
  183. c = s->ctrls[i];
  184. if (c->generic.type == CTRL_RADIO &&
  185. c->generic.context.i == offsetof(Config, vtmode)) {
  186. assert(c->generic.handler == dlg_stdradiobutton_handler);
  187. c->radio.nbuttons += 3;
  188. c->radio.buttons =
  189. sresize(c->radio.buttons, c->radio.nbuttons, char *);
  190. c->radio.buttons[c->radio.nbuttons-3] =
  191. dupstr("Font has XWindows encoding");
  192. c->radio.buttons[c->radio.nbuttons-2] =
  193. dupstr("Use font in both ANSI and OEM modes");
  194. c->radio.buttons[c->radio.nbuttons-1] =
  195. dupstr("Use font in OEM mode only");
  196. c->radio.buttondata =
  197. sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
  198. c->radio.buttondata[c->radio.nbuttons-3] = I(VT_XWINDOWS);
  199. c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
  200. c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
  201. if (!c->radio.shortcuts) {
  202. int j;
  203. c->radio.shortcuts = snewn(c->radio.nbuttons, char);
  204. for (j = 0; j < c->radio.nbuttons; j++)
  205. c->radio.shortcuts[j] = NO_SHORTCUT;
  206. } else {
  207. c->radio.shortcuts = sresize(c->radio.shortcuts,
  208. c->radio.nbuttons, char);
  209. }
  210. c->radio.shortcuts[c->radio.nbuttons-3] = 'x';
  211. c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
  212. c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
  213. break;
  214. }
  215. }
  216. }
  217. /*
  218. * RTF paste is Windows-specific.
  219. */
  220. s = ctrl_getset(b, "Window/Selection", "format",
  221. "Formatting of pasted characters");
  222. ctrl_checkbox(s, "Paste to clipboard in RTF as well as plain text", 'f',
  223. HELPCTX(selection_rtf),
  224. dlg_stdcheckbox_handler, I(offsetof(Config,rtf_paste)));
  225. /*
  226. * Windows often has no middle button, so we supply a selection
  227. * mode in which the more critical Paste action is available on
  228. * the right button instead.
  229. */
  230. s = ctrl_getset(b, "Window/Selection", "mouse",
  231. "Control use of mouse");
  232. ctrl_radiobuttons(s, "Action of mouse buttons:", 'm', 1,
  233. HELPCTX(selection_buttons),
  234. dlg_stdradiobutton_handler,
  235. I(offsetof(Config, mouse_is_xterm)),
  236. "Windows (Middle extends, Right brings up menu)", I(2),
  237. "Compromise (Middle extends, Right pastes)", I(0),
  238. "xterm (Right extends, Middle pastes)", I(1), NULL);
  239. /*
  240. * This really ought to go at the _top_ of its box, not the
  241. * bottom, so we'll just do some shuffling now we've set it
  242. * up...
  243. */
  244. c = s->ctrls[s->ncontrols-1]; /* this should be the new control */
  245. memmove(s->ctrls+1, s->ctrls, (s->ncontrols-1)*sizeof(union control *));
  246. s->ctrls[0] = c;
  247. /*
  248. * Logical palettes don't even make sense anywhere except Windows.
  249. */
  250. s = ctrl_getset(b, "Window/Colours", "general",
  251. "General options for colour usage");
  252. ctrl_checkbox(s, "Attempt to use logical palettes", 'l',
  253. HELPCTX(colours_logpal),
  254. dlg_stdcheckbox_handler, I(offsetof(Config,try_palette)));
  255. ctrl_checkbox(s, "Use system colours", 's',
  256. HELPCTX(colours_system),
  257. dlg_stdcheckbox_handler, I(offsetof(Config,system_colour)));
  258. /*
  259. * Resize-by-changing-font is a Windows insanity.
  260. */
  261. s = ctrl_getset(b, "Window", "size", "Set the size of the window");
  262. ctrl_radiobuttons(s, "When window is resized:", 'z', 1,
  263. HELPCTX(window_resize),
  264. dlg_stdradiobutton_handler,
  265. I(offsetof(Config, resize_action)),
  266. "Change the number of rows and columns", I(RESIZE_TERM),
  267. "Change the size of the font", I(RESIZE_FONT),
  268. "Change font size only when maximised", I(RESIZE_EITHER),
  269. "Forbid resizing completely", I(RESIZE_DISABLED), NULL);
  270. /*
  271. * Most of the Window/Behaviour stuff is there to mimic Windows
  272. * conventions which PuTTY can optionally disregard. Hence,
  273. * most of these options are Windows-specific.
  274. */
  275. s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
  276. ctrl_checkbox(s, "Window closes on ALT-F4", '4',
  277. HELPCTX(behaviour_altf4),
  278. dlg_stdcheckbox_handler, I(offsetof(Config,alt_f4)));
  279. ctrl_checkbox(s, "System menu appears on ALT-Space", 'y',
  280. HELPCTX(behaviour_altspace),
  281. dlg_stdcheckbox_handler, I(offsetof(Config,alt_space)));
  282. ctrl_checkbox(s, "System menu appears on ALT alone", 'l',
  283. HELPCTX(behaviour_altonly),
  284. dlg_stdcheckbox_handler, I(offsetof(Config,alt_only)));
  285. ctrl_checkbox(s, "Ensure window is always on top", 'e',
  286. HELPCTX(behaviour_alwaysontop),
  287. dlg_stdcheckbox_handler, I(offsetof(Config,alwaysontop)));
  288. ctrl_checkbox(s, "Full screen on Alt-Enter", 'f',
  289. HELPCTX(behaviour_altenter),
  290. dlg_stdcheckbox_handler,
  291. I(offsetof(Config,fullscreenonaltenter)));
  292. }