]> git.ipfire.org Git - people/ms/putty.git/blob - sercfg.c
Drop tag for 0.61 release.
[people/ms/putty.git] / sercfg.c
1 /*
2 * sercfg.c - the serial-port specific parts of the PuTTY
3 * configuration box. Centralised as cross-platform code because
4 * more than one platform will want to use it, but not part of the
5 * main configuration. The expectation is that each platform's
6 * local config function will call out to ser_setup_config_box() if
7 * it needs to set up the standard serial stuff. (Of course, it can
8 * then apply local tweaks after ser_setup_config_box() returns, if
9 * it needs to.)
10 */
11
12 #include <assert.h>
13 #include <stdlib.h>
14
15 #include "putty.h"
16 #include "dialog.h"
17 #include "storage.h"
18
19 static void serial_parity_handler(union control *ctrl, void *dlg,
20 void *data, int event)
21 {
22 static const struct {
23 const char *name;
24 int val;
25 } parities[] = {
26 {"None", SER_PAR_NONE},
27 {"Odd", SER_PAR_ODD},
28 {"Even", SER_PAR_EVEN},
29 {"Mark", SER_PAR_MARK},
30 {"Space", SER_PAR_SPACE},
31 };
32 int mask = ctrl->listbox.context.i;
33 int i, j;
34 Config *cfg = (Config *)data;
35
36 if (event == EVENT_REFRESH) {
37 int oldparity = cfg->serparity;/* preserve past reentrant calls */
38 dlg_update_start(ctrl, dlg);
39 dlg_listbox_clear(ctrl, dlg);
40 for (i = 0; i < lenof(parities); i++) {
41 if (mask & (1 << i))
42 dlg_listbox_addwithid(ctrl, dlg, parities[i].name,
43 parities[i].val);
44 }
45 for (i = j = 0; i < lenof(parities); i++) {
46 if (mask & (1 << i)) {
47 if (oldparity == parities[i].val) {
48 dlg_listbox_select(ctrl, dlg, j);
49 break;
50 }
51 j++;
52 }
53 }
54 if (i == lenof(parities)) { /* an unsupported setting was chosen */
55 dlg_listbox_select(ctrl, dlg, 0);
56 oldparity = SER_PAR_NONE;
57 }
58 dlg_update_done(ctrl, dlg);
59 cfg->serparity = oldparity; /* restore */
60 } else if (event == EVENT_SELCHANGE) {
61 int i = dlg_listbox_index(ctrl, dlg);
62 if (i < 0)
63 i = SER_PAR_NONE;
64 else
65 i = dlg_listbox_getid(ctrl, dlg, i);
66 cfg->serparity = i;
67 }
68 }
69
70 static void serial_flow_handler(union control *ctrl, void *dlg,
71 void *data, int event)
72 {
73 static const struct {
74 const char *name;
75 int val;
76 } flows[] = {
77 {"None", SER_FLOW_NONE},
78 {"XON/XOFF", SER_FLOW_XONXOFF},
79 {"RTS/CTS", SER_FLOW_RTSCTS},
80 {"DSR/DTR", SER_FLOW_DSRDTR},
81 };
82 int mask = ctrl->listbox.context.i;
83 int i, j;
84 Config *cfg = (Config *)data;
85
86 if (event == EVENT_REFRESH) {
87 int oldflow = cfg->serflow; /* preserve past reentrant calls */
88 dlg_update_start(ctrl, dlg);
89 dlg_listbox_clear(ctrl, dlg);
90 for (i = 0; i < lenof(flows); i++) {
91 if (mask & (1 << i))
92 dlg_listbox_addwithid(ctrl, dlg, flows[i].name, flows[i].val);
93 }
94 for (i = j = 0; i < lenof(flows); i++) {
95 if (mask & (1 << i)) {
96 if (oldflow == flows[i].val) {
97 dlg_listbox_select(ctrl, dlg, j);
98 break;
99 }
100 j++;
101 }
102 }
103 if (i == lenof(flows)) { /* an unsupported setting was chosen */
104 dlg_listbox_select(ctrl, dlg, 0);
105 oldflow = SER_FLOW_NONE;
106 }
107 dlg_update_done(ctrl, dlg);
108 cfg->serflow = oldflow; /* restore */
109 } else if (event == EVENT_SELCHANGE) {
110 int i = dlg_listbox_index(ctrl, dlg);
111 if (i < 0)
112 i = SER_FLOW_NONE;
113 else
114 i = dlg_listbox_getid(ctrl, dlg, i);
115 cfg->serflow = i;
116 }
117 }
118
119 void ser_setup_config_box(struct controlbox *b, int midsession,
120 int parity_mask, int flow_mask)
121 {
122 struct controlset *s;
123 union control *c;
124
125 if (!midsession) {
126 int i;
127 extern void config_protocolbuttons_handler(union control *, void *,
128 void *, int);
129
130 /*
131 * Add the serial back end to the protocols list at the
132 * top of the config box.
133 */
134 s = ctrl_getset(b, "Session", "hostport",
135 "Specify the destination you want to connect to");
136
137 for (i = 0; i < s->ncontrols; i++) {
138 c = s->ctrls[i];
139 if (c->generic.type == CTRL_RADIO &&
140 c->generic.handler == config_protocolbuttons_handler) {
141 c->radio.nbuttons++;
142 c->radio.ncolumns++;
143 c->radio.buttons =
144 sresize(c->radio.buttons, c->radio.nbuttons, char *);
145 c->radio.buttons[c->radio.nbuttons-1] =
146 dupstr("Serial");
147 c->radio.buttondata =
148 sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
149 c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);
150 if (c->radio.shortcuts) {
151 c->radio.shortcuts =
152 sresize(c->radio.shortcuts, c->radio.nbuttons, char);
153 c->radio.shortcuts[c->radio.nbuttons-1] = 'r';
154 }
155 }
156 }
157 }
158
159 /*
160 * Entirely new Connection/Serial panel for serial port
161 * configuration.
162 */
163 ctrl_settitle(b, "Connection/Serial",
164 "Options controlling local serial lines");
165
166 if (!midsession) {
167 /*
168 * We don't permit switching to a different serial port in
169 * midflight, although we do allow all other
170 * reconfiguration.
171 */
172 s = ctrl_getset(b, "Connection/Serial", "serline",
173 "Select a serial line");
174 ctrl_editbox(s, "Serial line to connect to", 'l', 40,
175 HELPCTX(serial_line),
176 dlg_stdeditbox_handler, I(offsetof(Config,serline)),
177 I(sizeof(((Config *)0)->serline)));
178 }
179
180 s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
181 ctrl_editbox(s, "Speed (baud)", 's', 40,
182 HELPCTX(serial_speed),
183 dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1));
184 ctrl_editbox(s, "Data bits", 'b', 40,
185 HELPCTX(serial_databits),
186 dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1));
187 /*
188 * Stop bits come in units of one half.
189 */
190 ctrl_editbox(s, "Stop bits", 't', 40,
191 HELPCTX(serial_stopbits),
192 dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2));
193 ctrl_droplist(s, "Parity", 'p', 40,
194 HELPCTX(serial_parity),
195 serial_parity_handler, I(parity_mask));
196 ctrl_droplist(s, "Flow control", 'f', 40,
197 HELPCTX(serial_flow),
198 serial_flow_handler, I(flow_mask));
199 }