aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/speakup/varhandlers.c
diff options
context:
space:
mode:
authorWilliam Hubbs <w.d.hubbs@gmail.com>2010-10-07 14:20:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-07 22:22:31 -0400
commitc6e3fd22cd538365bfeb82997d5b89562e077d42 (patch)
tree5eaa170c9003abc7b24ab340ccabe889cba47992 /drivers/staging/speakup/varhandlers.c
parente59fe083f683ca2ca56abefad290d110808a6fb5 (diff)
Staging: add speakup to the staging directory
Speakup is a kernel based screen review package for the linux operating system. It allows blind users to interact with applications on the linux console by means of synthetic speech. The authors and maintainers of this code include the following: Kirk Reiser, Andy Berdan, John Covici, Brian and David Borowski, Christopher Brannon, Samuel Thibault and William Hubbs. Signed-off-by: William Hubbs <w.d.hubbs@gmail.com> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/speakup/varhandlers.c')
-rw-r--r--drivers/staging/speakup/varhandlers.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
new file mode 100644
index 00000000000..2d137bd84df
--- /dev/null
+++ b/drivers/staging/speakup/varhandlers.c
@@ -0,0 +1,403 @@
1#include <linux/ctype.h>
2#include "spk_types.h"
3#include "spk_priv.h"
4#include "speakup.h"
5
6static struct st_var_header var_headers[] = {
7 { "version", VERSION, VAR_PROC, NULL, NULL },
8 { "synth_name", SYNTH, VAR_PROC, NULL, NULL },
9 { "keymap", KEYMAP, VAR_PROC, NULL, NULL },
10 { "silent", SILENT, VAR_PROC, NULL, NULL },
11 { "punc_some", PUNC_SOME, VAR_PROC, NULL, NULL },
12 { "punc_most", PUNC_MOST, VAR_PROC, NULL, NULL },
13 { "punc_all", PUNC_ALL, VAR_PROC, NULL, NULL },
14 { "delimiters", DELIM, VAR_PROC, NULL, NULL },
15 { "repeats", REPEATS, VAR_PROC, NULL, NULL },
16 { "ex_num", EXNUMBER, VAR_PROC, NULL, NULL },
17 { "characters", CHARS, VAR_PROC, NULL, NULL },
18 { "synth_direct", SYNTH_DIRECT, VAR_PROC, NULL, NULL },
19 { "caps_start", CAPS_START, VAR_STRING, str_caps_start, NULL },
20 { "caps_stop", CAPS_STOP, VAR_STRING, str_caps_stop, NULL },
21 { "delay_time", DELAY, VAR_TIME, NULL, NULL },
22 { "trigger_time", TRIGGER, VAR_TIME, NULL, NULL },
23 { "jiffy_delta", JIFFY, VAR_TIME, NULL, NULL },
24 { "full_time", FULL, VAR_TIME, NULL, NULL },
25 { "spell_delay", SPELL_DELAY, VAR_NUM, &spell_delay, NULL },
26 { "bleeps", BLEEPS, VAR_NUM, &bleeps, NULL },
27 { "attrib_bleep", ATTRIB_BLEEP, VAR_NUM, &attrib_bleep, NULL },
28 { "bleep_time", BLEEP_TIME, VAR_TIME, &bleep_time, NULL },
29 { "cursor_time", CURSOR_TIME, VAR_TIME, NULL, NULL },
30 { "punc_level", PUNC_LEVEL, VAR_NUM, &punc_level, NULL },
31 { "reading_punc", READING_PUNC, VAR_NUM, &reading_punc, NULL },
32 { "say_control", SAY_CONTROL, VAR_NUM, &say_ctrl, NULL },
33 { "say_word_ctl", SAY_WORD_CTL, VAR_NUM, &say_word_ctl, NULL },
34 { "no_interrupt", NO_INTERRUPT, VAR_NUM, &no_intr, NULL },
35 { "key_echo", KEY_ECHO, VAR_NUM, &key_echo, NULL },
36 { "bell_pos", BELL_POS, VAR_NUM, &bell_pos, NULL },
37 { "rate", RATE, VAR_NUM, NULL, NULL },
38 { "pitch", PITCH, VAR_NUM, NULL, NULL },
39 { "vol", VOL, VAR_NUM, NULL, NULL },
40 { "tone", TONE, VAR_NUM, NULL, NULL },
41 { "punct", PUNCT, VAR_NUM, NULL, NULL },
42 { "voice", VOICE, VAR_NUM, NULL, NULL },
43 { "freq", FREQUENCY, VAR_NUM, NULL, NULL },
44 { "lang", LANG, VAR_NUM, NULL, NULL },
45 { "chartab", CHARTAB, VAR_PROC, NULL, NULL },
46 { "direct", DIRECT, VAR_NUM, NULL, NULL },
47};
48
49static struct st_var_header *var_ptrs[MAXVARS] = { 0, 0, 0 };
50
51static struct punc_var_t punc_vars[] = {
52 { PUNC_SOME, 1 },
53 { PUNC_MOST, 2 },
54 { PUNC_ALL, 3 },
55 { DELIM, 4 },
56 { REPEATS, 5 },
57 { EXNUMBER, 6 },
58 { -1, -1 },
59};
60
61int chartab_get_value(char *keyword)
62{
63 int value = 0;
64
65 if (!strcmp(keyword, "ALPHA"))
66 value = ALPHA;
67 else if (!strcmp(keyword, "B_CTL"))
68 value = B_CTL;
69 else if (!strcmp(keyword, "WDLM"))
70 value = WDLM;
71 else if (!strcmp(keyword, "A_PUNC"))
72 value = A_PUNC;
73 else if (!strcmp(keyword, "PUNC"))
74 value = PUNC;
75 else if (!strcmp(keyword, "NUM"))
76 value = NUM;
77 else if (!strcmp(keyword, "A_CAP"))
78 value = A_CAP;
79 else if (!strcmp(keyword, "B_CAPSYM"))
80 value = B_CAPSYM;
81 else if (!strcmp(keyword, "B_SYM"))
82 value = B_SYM;
83 return value;
84}
85
86void speakup_register_var(struct var_t *var)
87{
88 static char nothing[2] = "\0";
89 int i;
90 struct st_var_header *p_header;
91
92 BUG_ON(!var || var->var_id < 0 || var->var_id >= MAXVARS);
93 if (var_ptrs[0] == NULL) {
94 for (i = 0; i < MAXVARS; i++) {
95 p_header = &var_headers[i];
96 var_ptrs[p_header->var_id] = p_header;
97 p_header->data = NULL;
98 }
99 }
100 p_header = var_ptrs[var->var_id];
101 if (p_header->data != NULL)
102 return;
103 p_header->data = var;
104 switch (p_header->var_type) {
105 case VAR_STRING:
106 set_string_var(nothing, p_header, 0);
107 break;
108 case VAR_NUM:
109 case VAR_TIME:
110 set_num_var(0, p_header, E_DEFAULT);
111 break;
112 default:
113 break;
114 }
115 return;
116}
117
118void speakup_unregister_var(enum var_id_t var_id)
119{
120 struct st_var_header *p_header;
121 BUG_ON(var_id < 0 || var_id >= MAXVARS);
122 p_header = var_ptrs[var_id];
123 p_header->data = NULL;
124}
125
126struct st_var_header *get_var_header(enum var_id_t var_id)
127{
128 struct st_var_header *p_header;
129 if (var_id < 0 || var_id >= MAXVARS)
130 return NULL;
131 p_header = var_ptrs[var_id];
132 if (p_header->data == NULL)
133 return NULL;
134 return p_header;
135}
136
137struct st_var_header *var_header_by_name(const char *name)
138{
139 int i;
140 struct st_var_header *where = NULL;
141
142 if (name != NULL) {
143 i = 0;
144 while ((i < MAXVARS) && (where == NULL)) {
145 if (strcmp(name, var_ptrs[i]->name) == 0)
146 where = var_ptrs[i];
147 else
148 i++;
149 }
150 }
151 return where;
152}
153
154struct var_t *get_var(enum var_id_t var_id)
155{
156 BUG_ON(var_id < 0 || var_id >= MAXVARS);
157 BUG_ON(! var_ptrs[var_id]);
158 return (var_ptrs[var_id]->data);
159}
160EXPORT_SYMBOL_GPL(get_var);
161
162struct punc_var_t *get_punc_var(enum var_id_t var_id)
163{
164 struct punc_var_t *rv = NULL;
165 struct punc_var_t *where;
166
167 where = punc_vars;
168 while ((where->var_id != -1) && (rv == NULL)) {
169 if (where->var_id == var_id)
170 rv = where;
171 else
172 where++;
173 }
174 return rv;
175}
176
177/* handlers for setting vars */
178int set_num_var(int input, struct st_var_header *var, int how)
179{
180 int val;
181 short ret = 0;
182 int *p_val = var->p_val;
183 int l;
184 char buf[32];
185 char *cp;
186 struct var_t *var_data = var->data;
187 if (var_data == NULL)
188 return E_UNDEF;
189
190 if (how == E_NEW_DEFAULT) {
191 if (input < var_data->u.n.low || input > var_data->u.n.high)
192 ret = E_RANGE;
193 else
194 var_data->u.n.default_val = input;
195 return ret;
196 }
197 if (how == E_DEFAULT) {
198 val = var_data->u.n.default_val;
199 ret = SET_DEFAULT;
200 } else {
201 if (how == E_SET)
202 val = input;
203 else
204 val = var_data->u.n.value;
205 if (how == E_INC)
206 val += input;
207 else if (how == E_DEC)
208 val -= input;
209 if (val < var_data->u.n.low || val > var_data->u.n.high)
210 return E_RANGE;
211 }
212 var_data->u.n.value = val;
213 if (var->var_type == VAR_TIME && p_val != NULL) {
214 *p_val = msecs_to_jiffies(val);
215 return ret;
216 }
217 if (p_val != NULL)
218 *p_val = val;
219 if (var->var_id == PUNC_LEVEL) {
220 punc_mask = punc_masks[val];
221 return ret;
222 }
223 if (var_data->u.n.multiplier != 0)
224 val *= var_data->u.n.multiplier;
225 val += var_data->u.n.offset;
226 if (var->var_id < FIRST_SYNTH_VAR || synth == NULL)
227 return ret;
228 if (synth->synth_adjust != NULL) {
229 int status = synth->synth_adjust(var);
230 return (status != 0) ? status : ret;
231 }
232 if (!var_data->u.n.synth_fmt)
233 return ret;
234 if (var->var_id == PITCH)
235 cp = pitch_buff;
236 else
237 cp = buf;
238 if (!var_data->u.n.out_str)
239 l = sprintf(cp, var_data->u.n.synth_fmt, (int)val);
240 else
241 l = sprintf(cp, var_data->u.n.synth_fmt, var_data->u.n.out_str[val]);
242 synth_printf("%s", cp);
243 return ret;
244}
245
246int set_string_var(const char *page, struct st_var_header *var, int len)
247{
248 int ret = 0;
249 struct var_t *var_data = var->data;
250 if (var_data == NULL)
251 return E_UNDEF;
252 if (len > MAXVARLEN)
253 return -E_TOOLONG;
254 if (!len) {
255 if (!var_data->u.s.default_val)
256 return 0;
257 ret = SET_DEFAULT;
258 if (!var->p_val)
259 var->p_val = var_data->u.s.default_val;
260 if (var->p_val != var_data->u.s.default_val)
261 strcpy((char *)var->p_val, var_data->u.s.default_val);
262 } else if (var->p_val)
263 strcpy((char *)var->p_val, page);
264 else
265 return -E_TOOLONG;
266 return ret;
267}
268
269/* set_mask_bits sets or clears the punc/delim/repeat bits,
270 * if input is null uses the defaults.
271 * values for how: 0 clears bits of chars supplied,
272 * 1 clears allk, 2 sets bits for chars */
273int set_mask_bits(const char *input, const int which, const int how)
274{
275 u_char *cp;
276 short mask = punc_info[which].mask;
277 if (how&1) {
278 for (cp = (u_char *)punc_info[3].value; *cp; cp++)
279 spk_chartab[*cp] &= ~mask;
280 }
281 cp = (u_char *)input;
282 if (cp == 0)
283 cp = punc_info[which].value;
284 else {
285 for ( ; *cp; cp++) {
286 if (*cp < SPACE)
287 break;
288 if (mask < PUNC) {
289 if (!(spk_chartab[*cp]&PUNC))
290 break;
291 } else if (spk_chartab[*cp]&B_NUM)
292 break;
293 }
294 if (*cp)
295 return -EINVAL;
296 cp = (u_char *)input;
297 }
298 if (how&2) {
299 for ( ; *cp; cp++)
300 if (*cp > SPACE)
301 spk_chartab[*cp] |= mask;
302 } else {
303 for ( ; *cp; cp++)
304 if (*cp > SPACE)
305 spk_chartab[*cp] &= ~mask;
306 }
307 return 0;
308}
309
310char *strlwr(char *s)
311{
312 char *p;
313 if (s == NULL)
314 return NULL;
315
316 for (p = s; *p; p++)
317 *p = tolower(*p);
318 return s;
319}
320
321char *speakup_s2i(char *start, int *dest)
322{
323 int val;
324 char ch = *start;
325 if (ch == '-' || ch == '+')
326 start++;
327 if (*start < '0' || *start > '9')
328 return start;
329 val = (*start) - '0';
330 start++;
331 while (*start >= '0' && *start <= '9') {
332 val *= 10;
333 val += (*start) - '0';
334 start++;
335 }
336 if (ch == '-')
337 *dest = -val;
338 else
339 *dest = val;
340 return start;
341}
342
343char *s2uchar(char *start, char *dest)
344{
345 int val = 0;
346 while (*start && *start <= SPACE)
347 start++;
348 while (*start >= '0' && *start <= '9') {
349 val *= 10;
350 val += (*start) - '0';
351 start++;
352 }
353 if (*start == ',')
354 start++;
355 *dest = (u_char)val;
356 return start;
357}
358
359char *xlate(char *s)
360{
361 static const char finds[] = "nrtvafe";
362 static const char subs[] = "\n\r\t\013\001\014\033";
363 static const char hx[] = "0123456789abcdefABCDEF";
364 char *p = s, *p1, *p2, c;
365 int num;
366 while ((p = strchr(p, '\\'))) {
367 p1 = p+1;
368 p2 = strchr(finds, *p1);
369 if (p2) {
370 *p++ = subs[p2-finds];
371 p1++;
372 } else if (*p1 >= '0' && *p1 <= '7') {
373 num = (*p1++)&7;
374 while (num < 256 && *p1 >= '0' && *p1 <= '7') {
375 num <<= 3;
376 num = (*p1++)&7;
377 }
378 *p++ = num;
379 } else if (*p1 == 'x' &&
380 strchr(hx, p1[1]) && strchr(hx, p1[2])) {
381 p1++;
382 c = *p1++;
383 if (c > '9')
384 c = (c - '7') & 0x0f;
385 else
386 c -= '0';
387 num = c << 4;
388 c = *p1++;
389 if (c > '9')
390 c = (c-'7')&0x0f;
391 else
392 c -= '0';
393 num += c;
394 *p++ = num;
395 } else
396 *p++ = *p1++;
397 p2 = p;
398 while (*p1)
399 *p2++ = *p1++;
400 *p2 = '\0';
401 }
402 return s;
403}