OSDN Git Service

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