xref: /linux/drivers/accessibility/speakup/main.c (revision a67c43ac37f80b5e7e1876e8f5f7df62027445c8)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* speakup.c
3  * review functions for the speakup screen review package.
4  * originally written by: Kirk Reiser and Andy Berdan.
5  *
6  * extensively modified by David Borowski.
7  *
8  ** Copyright (C) 1998  Kirk Reiser.
9  *  Copyright (C) 2003  David Borowski.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/vt.h>
14 #include <linux/tty.h>
15 #include <linux/mm.h>		/* __get_free_page() and friends */
16 #include <linux/vt_kern.h>
17 #include <linux/ctype.h>
18 #include <linux/selection.h>
19 #include <linux/unistd.h>
20 #include <linux/jiffies.h>
21 #include <linux/kthread.h>
22 #include <linux/keyboard.h>	/* for KT_SHIFT */
23 #include <linux/kbd_kern.h>	/* for vc_kbd_* and friends */
24 #include <linux/input.h>
25 #include <linux/kmod.h>
26 
27 /* speakup_*_selection */
28 #include <linux/module.h>
29 #include <linux/sched.h>
30 #include <linux/slab.h>
31 #include <linux/types.h>
32 #include <linux/consolemap.h>
33 
34 #include <linux/spinlock.h>
35 #include <linux/notifier.h>
36 
37 #include <linux/uaccess.h>	/* copy_from|to|user() and others */
38 
39 #include "spk_priv.h"
40 #include "speakup.h"
41 
42 #define MAX_DELAY msecs_to_jiffies(500)
43 #define MINECHOCHAR SPACE
44 
45 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
46 MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>");
47 MODULE_DESCRIPTION("Speakup console speech");
48 MODULE_LICENSE("GPL");
49 MODULE_VERSION(SPEAKUP_VERSION);
50 
51 char *synth_name;
52 module_param_named(synth, synth_name, charp, 0444);
53 module_param_named(quiet, spk_quiet_boot, bool, 0444);
54 
55 MODULE_PARM_DESC(synth, "Synth to start if speakup is built in.");
56 MODULE_PARM_DESC(quiet, "Do not announce when the synthesizer is found.");
57 
58 special_func spk_special_handler;
59 
60 short spk_pitch_shift, synth_flags;
61 static u16 buf[256];
62 int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10;
63 int spk_no_intr, spk_spell_delay;
64 int spk_key_echo, spk_say_word_ctl;
65 int spk_say_ctrl, spk_bell_pos;
66 short spk_punc_mask;
67 int spk_punc_level, spk_reading_punc;
68 char spk_str_caps_start[MAXVARLEN + 1] = "\0";
69 char spk_str_caps_stop[MAXVARLEN + 1] = "\0";
70 char spk_str_pause[MAXVARLEN + 1] = "\0";
71 bool spk_paused;
72 const struct st_bits_data spk_punc_info[] = {
73 	{"none", "", 0},
74 	{"some", "/$%&@", SOME},
75 	{"most", "$%&#()=+*/@^<>|\\", MOST},
76 	{"all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC},
77 	{"delimiters", "", B_WDLM},
78 	{"repeats", "()", CH_RPT},
79 	{"extended numeric", "", B_EXNUM},
80 	{"symbols", "", B_SYM},
81 	{NULL, NULL}
82 };
83 
84 static char mark_cut_flag;
85 #define MAX_KEY 160
86 static u_char *spk_shift_table;
87 u_char *spk_our_keys[MAX_KEY];
88 u_char spk_key_buf[600];
89 const u_char spk_key_defaults[] = {
90 #include "speakupmap.h"
91 };
92 
93 /* cursor track modes, must be ordered same as cursor_msgs in enum msg_index_t */
94 enum cursor_track {
95 	CT_Off = 0,
96 	CT_On,
97 	CT_Highlight,
98 	CT_Window,
99 	CT_Max,
100 	read_all_mode = CT_Max,
101 };
102 
103 /* Speakup Cursor Track Variables */
104 static enum cursor_track cursor_track = 1, prev_cursor_track = 1;
105 
106 static struct tty_struct *tty;
107 
108 static void spkup_write(const u16 *in_buf, int count);
109 
110 static char *phonetic[] = {
111 	"alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
112 	"india", "juliett", "keelo", "leema", "mike", "november", "oscar",
113 	    "papa",
114 	"keh beck", "romeo", "sierra", "tango", "uniform", "victer", "whiskey",
115 	"x ray", "yankee", "zulu"
116 };
117 
118 /* array of 256 char pointers (one for each character description)
119  * initialized to default_chars and user selectable via
120  * /proc/speakup/characters
121  */
122 char *spk_characters[256];
123 
124 char *spk_default_chars[256] = {
125 /*000*/ "null", "^a", "^b", "^c", "^d", "^e", "^f", "^g",
126 /*008*/ "^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o",
127 /*016*/ "^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w",
128 /*024*/ "^x", "^y", "^z", "control", "control", "control", "control",
129 	    "control",
130 /*032*/ "space", "bang!", "quote", "number", "dollar", "percent", "and",
131 	    "tick",
132 /*040*/ "left paren", "right paren", "star", "plus", "comma", "dash",
133 	    "dot",
134 	"slash",
135 /*048*/ "zero", "one", "two", "three", "four", "five", "six", "seven",
136 	"eight", "nine",
137 /*058*/ "colon", "semmy", "less", "equals", "greater", "question", "at",
138 /*065*/ "EIGH", "B", "C", "D", "E", "F", "G",
139 /*072*/ "H", "I", "J", "K", "L", "M", "N", "O",
140 /*080*/ "P", "Q", "R", "S", "T", "U", "V", "W", "X",
141 /*089*/ "Y", "ZED", "left bracket", "backslash", "right bracket",
142 	    "caret",
143 	"line",
144 /*096*/ "accent", "a", "b", "c", "d", "e", "f", "g",
145 /*104*/ "h", "i", "j", "k", "l", "m", "n", "o",
146 /*112*/ "p", "q", "r", "s", "t", "u", "v", "w",
147 /*120*/ "x", "y", "zed", "left brace", "bar", "right brace", "tihlduh",
148 /*127*/ "del", "control", "control", "control", "control", "control",
149 	    "control", "control", "control", "control", "control",
150 /*138*/ "control", "control", "control", "control", "control",
151 	    "control", "control", "control", "control", "control",
152 	    "control", "control",
153 /*150*/ "control", "control", "control", "control", "control",
154 	    "control", "control", "control", "control", "control",
155 /*160*/ "nbsp", "inverted bang",
156 /*162*/ "cents", "pounds", "currency", "yen", "broken bar", "section",
157 /*168*/ "diaeresis", "copyright", "female ordinal", "double left angle",
158 /*172*/ "not", "soft hyphen", "registered", "macron",
159 /*176*/ "degrees", "plus or minus", "super two", "super three",
160 /*180*/ "acute accent", "micro", "pilcrow", "middle dot",
161 /*184*/ "cedilla", "super one", "male ordinal", "double right angle",
162 /*188*/ "one quarter", "one half", "three quarters",
163 	    "inverted question",
164 /*192*/ "A GRAVE", "A ACUTE", "A CIRCUMFLEX", "A TILDE", "A OOMLAUT",
165 	    "A RING",
166 /*198*/ "AE", "C CIDELLA", "E GRAVE", "E ACUTE", "E CIRCUMFLEX",
167 	    "E OOMLAUT",
168 /*204*/ "I GRAVE", "I ACUTE", "I CIRCUMFLEX", "I OOMLAUT", "ETH",
169 	    "N TILDE",
170 /*210*/ "O GRAVE", "O ACUTE", "O CIRCUMFLEX", "O TILDE", "O OOMLAUT",
171 /*215*/ "multiplied by", "O STROKE", "U GRAVE", "U ACUTE",
172 	    "U CIRCUMFLEX",
173 /*220*/ "U OOMLAUT", "Y ACUTE", "THORN", "sharp s", "a grave",
174 /*225*/ "a acute", "a circumflex", "a tilde", "a oomlaut", "a ring",
175 /*230*/ "ae", "c cidella", "e grave", "e acute",
176 /*234*/ "e circumflex", "e oomlaut", "i grave", "i acute",
177 	    "i circumflex",
178 /*239*/ "i oomlaut", "eth", "n tilde", "o grave", "o acute",
179 	    "o circumflex",
180 /*245*/ "o tilde", "o oomlaut", "divided by", "o stroke", "u grave",
181 	    "u acute",
182 /* 251 */ "u circumflex", "u oomlaut", "y acute", "thorn", "y oomlaut"
183 };
184 
185 /* array of 256 u_short (one for each character)
186  * initialized to default_chartab and user selectable via
187  * /sys/module/speakup/parameters/chartab
188  */
189 u_short spk_chartab[256];
190 
191 static u_short default_chartab[256] = {
192 	B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL,	/* 0-7 */
193 	B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL,	/* 8-15 */
194 	B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL,	/*16-23 */
195 	B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL,	/* 24-31 */
196 	WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,	/*  !"#$%&' */
197 	PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC,	/* ()*+, -./ */
198 	NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM,	/* 01234567 */
199 	NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,	/* 89:;<=>? */
200 	PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,	/* @ABCDEFG */
201 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,	/* HIJKLMNO */
202 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,	/* PQRSTUVW */
203 	A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC,	/* XYZ[\]^_ */
204 	PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,	/* `abcdefg */
205 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,	/* hijklmno */
206 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,	/* pqrstuvw */
207 	ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0,	/* xyz{|}~ */
208 	B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-134 */
209 	B_SYM,	/* 135 */
210 	B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 136-142 */
211 	B_CAPSYM,	/* 143 */
212 	B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /* 144-150 */
213 	B_SYM,	/* 151 */
214 	B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /*152-158 */
215 	B_SYM,	/* 159 */
216 	WDLM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 160-166 */
217 	B_SYM,	/* 167 */
218 	B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM,	/* 168-175 */
219 	B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM,	/* 176-183 */
220 	B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM,	/* 184-191 */
221 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,	/* 192-199 */
222 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,	/* 200-207 */
223 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, B_SYM,	/* 208-215 */
224 	A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, ALPHA,	/* 216-223 */
225 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,	/* 224-231 */
226 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,	/* 232-239 */
227 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, B_SYM,	/* 240-247 */
228 	ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA	/* 248-255 */
229 };
230 
231 struct task_struct *speakup_task;
232 struct bleep spk_unprocessed_sound;
233 static int spk_keydown;
234 static u16 spk_lastkey;
235 static u_char spk_close_press, keymap_flags;
236 static u_char last_keycode, this_speakup_key;
237 static u_long last_spk_jiffy;
238 
239 struct st_spk_t *speakup_console[MAX_NR_CONSOLES];
240 
241 DEFINE_MUTEX(spk_mutex);
242 
243 static int keyboard_notifier_call(struct notifier_block *,
244 				  unsigned long code, void *param);
245 
246 static struct notifier_block keyboard_notifier_block = {
247 	.notifier_call = keyboard_notifier_call,
248 };
249 
250 static int vt_notifier_call(struct notifier_block *,
251 			    unsigned long code, void *param);
252 
253 static struct notifier_block vt_notifier_block = {
254 	.notifier_call = vt_notifier_call,
255 };
256 
257 static unsigned char get_attributes(struct vc_data *vc, u16 *pos)
258 {
259 	pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, true);
260 	return (scr_readw(pos) & ~vc->vc_hi_font_mask) >> 8;
261 }
262 
263 static void speakup_date(struct vc_data *vc)
264 {
265 	spk_x = spk_cx = vc->state.x;
266 	spk_y = spk_cy = vc->state.y;
267 	spk_pos = spk_cp = vc->vc_pos;
268 	spk_old_attr = spk_attr;
269 	spk_attr = get_attributes(vc, (u_short *)spk_pos);
270 }
271 
272 static void bleep(u_short val)
273 {
274 	static const short vals[] = {
275 		350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659
276 	};
277 	short freq;
278 	int time = spk_bleep_time;
279 
280 	freq = vals[val % 12];
281 	if (val > 11)
282 		freq *= (1 << (val / 12));
283 	spk_unprocessed_sound.freq = freq;
284 	spk_unprocessed_sound.jiffies = msecs_to_jiffies(time);
285 	spk_unprocessed_sound.active = 1;
286 	/* We can only have 1 active sound at a time. */
287 }
288 
289 static void speakup_shut_up(struct vc_data *vc)
290 {
291 	if (spk_killed)
292 		return;
293 	spk_shut_up |= 0x01;
294 	spk_parked &= 0xfe;
295 	speakup_date(vc);
296 	if (synth)
297 		spk_do_flush();
298 }
299 
300 static void speech_kill(struct vc_data *vc)
301 {
302 	char val = synth->is_alive(synth);
303 
304 	if (val == 0)
305 		return;
306 
307 	/* re-enables synth, if disabled */
308 	if (val == 2 || spk_killed) {
309 		/* dead */
310 		spk_shut_up &= ~0x40;
311 		synth_printf("%s\n", spk_msg_get(MSG_IAM_ALIVE));
312 	} else {
313 		synth_printf("%s\n", spk_msg_get(MSG_YOU_KILLED_SPEAKUP));
314 		spk_shut_up |= 0x40;
315 	}
316 }
317 
318 static void speakup_off(struct vc_data *vc)
319 {
320 	if (spk_shut_up & 0x80) {
321 		spk_shut_up &= 0x7f;
322 		synth_printf("%s\n", spk_msg_get(MSG_HEY_THATS_BETTER));
323 	} else {
324 		spk_shut_up |= 0x80;
325 		synth_printf("%s\n", spk_msg_get(MSG_YOU_TURNED_ME_OFF));
326 	}
327 	speakup_date(vc);
328 }
329 
330 static void speakup_parked(struct vc_data *vc)
331 {
332 	if (spk_parked & 0x80) {
333 		spk_parked = 0;
334 		synth_printf("%s\n", spk_msg_get(MSG_UNPARKED));
335 	} else {
336 		spk_parked |= 0x80;
337 		synth_printf("%s\n", spk_msg_get(MSG_PARKED));
338 	}
339 }
340 
341 static void speakup_cut(struct vc_data *vc)
342 {
343 	static const char err_buf[] = "set selection failed";
344 	int ret;
345 
346 	if (!mark_cut_flag) {
347 		mark_cut_flag = 1;
348 		spk_xs = (u_short)spk_x;
349 		spk_ys = (u_short)spk_y;
350 		spk_sel_cons = vc;
351 		synth_printf("%s\n", spk_msg_get(MSG_MARK));
352 		return;
353 	}
354 	spk_xe = (u_short)spk_x;
355 	spk_ye = (u_short)spk_y;
356 	mark_cut_flag = 0;
357 	synth_printf("%s\n", spk_msg_get(MSG_CUT));
358 
359 	speakup_clear_selection();
360 	ret = speakup_set_selection(tty);
361 
362 	switch (ret) {
363 	case 0:
364 		break;		/* no error */
365 	case -EFAULT:
366 		pr_warn("%sEFAULT\n", err_buf);
367 		break;
368 	case -EINVAL:
369 		pr_warn("%sEINVAL\n", err_buf);
370 		break;
371 	case -ENOMEM:
372 		pr_warn("%sENOMEM\n", err_buf);
373 		break;
374 	}
375 }
376 
377 static void speakup_paste(struct vc_data *vc)
378 {
379 	if (mark_cut_flag) {
380 		mark_cut_flag = 0;
381 		synth_printf("%s\n", spk_msg_get(MSG_MARK_CLEARED));
382 	} else {
383 		synth_printf("%s\n", spk_msg_get(MSG_PASTE));
384 		speakup_paste_selection(tty);
385 	}
386 }
387 
388 static void say_attributes(struct vc_data *vc)
389 {
390 	int fg = spk_attr & 0x0f;
391 	int bg = spk_attr >> 4;
392 
393 	if (fg > 8) {
394 		synth_printf("%s ", spk_msg_get(MSG_BRIGHT));
395 		fg -= 8;
396 	}
397 	synth_printf("%s", spk_msg_get(MSG_COLORS_START + fg));
398 	if (bg > 7) {
399 		synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING));
400 		bg -= 8;
401 	} else {
402 		synth_printf(" %s ", spk_msg_get(MSG_ON));
403 	}
404 	synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg));
405 }
406 
407 /* must be ordered same as edge_msgs in enum msg_index_t */
408 enum edge {
409 	edge_none = 0,
410 	edge_top,
411 	edge_bottom,
412 	edge_left,
413 	edge_right,
414 	edge_quiet
415 };
416 
417 static void announce_edge(struct vc_data *vc, enum edge msg_id)
418 {
419 	if (spk_bleeps & 1)
420 		bleep(spk_y);
421 	if ((spk_bleeps & 2) && (msg_id < edge_quiet))
422 		synth_printf("%s\n",
423 			     spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
424 }
425 
426 static void speak_char(u16 ch)
427 {
428 	char *cp;
429 	struct var_t *direct = spk_get_var(DIRECT);
430 
431 	if (ch >= 0x100 || (direct && direct->u.n.value)) {
432 		if (ch < 0x100 && IS_CHAR(ch, B_CAP)) {
433 			spk_pitch_shift++;
434 			synth_printf("%s", spk_str_caps_start);
435 		}
436 		synth_putwc_s(ch);
437 		if (ch < 0x100 && IS_CHAR(ch, B_CAP))
438 			synth_printf("%s", spk_str_caps_stop);
439 		return;
440 	}
441 
442 	cp = spk_characters[ch];
443 	if (!cp) {
444 		pr_info("%s: cp == NULL!\n", __func__);
445 		return;
446 	}
447 	if (IS_CHAR(ch, B_CAP)) {
448 		spk_pitch_shift++;
449 		synth_printf("%s %s %s",
450 			     spk_str_caps_start, cp, spk_str_caps_stop);
451 	} else {
452 		if (*cp == '^') {
453 			cp++;
454 			synth_printf(" %s%s ", spk_msg_get(MSG_CTRL), cp);
455 		} else {
456 			synth_printf(" %s ", cp);
457 		}
458 	}
459 }
460 
461 static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs)
462 {
463 	u16 ch = ' ';
464 
465 	if (vc && pos) {
466 		u16 w;
467 		u16 c;
468 
469 		pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, true);
470 		w = scr_readw(pos);
471 		c = w & 0xff;
472 
473 		if (w & vc->vc_hi_font_mask) {
474 			w &= ~vc->vc_hi_font_mask;
475 			c |= 0x100;
476 		}
477 
478 		ch = inverse_translate(vc, c, 1);
479 		*attribs = (w & 0xff00) >> 8;
480 	}
481 	return ch;
482 }
483 
484 static void say_char(struct vc_data *vc)
485 {
486 	u16 ch;
487 
488 	spk_old_attr = spk_attr;
489 	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
490 	if (spk_attr != spk_old_attr) {
491 		if (spk_attrib_bleep & 1)
492 			bleep(spk_y);
493 		if (spk_attrib_bleep & 2)
494 			say_attributes(vc);
495 	}
496 	speak_char(ch);
497 }
498 
499 static void say_phonetic_char(struct vc_data *vc)
500 {
501 	u16 ch;
502 
503 	spk_old_attr = spk_attr;
504 	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
505 	if (ch <= 0x7f && isalpha(ch)) {
506 		ch &= 0x1f;
507 		synth_printf("%s\n", phonetic[--ch]);
508 	} else {
509 		if (ch < 0x100 && IS_CHAR(ch, B_NUM))
510 			synth_printf("%s ", spk_msg_get(MSG_NUMBER));
511 		speak_char(ch);
512 	}
513 }
514 
515 static void say_prev_char(struct vc_data *vc)
516 {
517 	spk_parked |= 0x01;
518 	if (spk_x == 0) {
519 		announce_edge(vc, edge_left);
520 		return;
521 	}
522 	spk_x--;
523 	spk_pos -= 2;
524 	say_char(vc);
525 }
526 
527 static void say_next_char(struct vc_data *vc)
528 {
529 	spk_parked |= 0x01;
530 	if (spk_x == vc->vc_cols - 1) {
531 		announce_edge(vc, edge_right);
532 		return;
533 	}
534 	spk_x++;
535 	spk_pos += 2;
536 	say_char(vc);
537 }
538 
539 /* get_word - will first check to see if the character under the
540  * reading cursor is a space and if spk_say_word_ctl is true it will
541  * return the word space.  If spk_say_word_ctl is not set it will check to
542  * see if there is a word starting on the next position to the right
543  * and return that word if it exists.  If it does not exist it will
544  * move left to the beginning of any previous word on the line or the
545  * beginning off the line whichever comes first..
546  */
547 
548 static u_long get_word(struct vc_data *vc)
549 {
550 	u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
551 	u16 ch;
552 	u16 attr_ch;
553 	u_char temp;
554 
555 	spk_old_attr = spk_attr;
556 	ch = get_char(vc, (u_short *)tmp_pos, &temp);
557 
558 /* decided to take out the sayword if on a space (mis-information */
559 	if (spk_say_word_ctl && ch == SPACE) {
560 		*buf = '\0';
561 		synth_printf("%s\n", spk_msg_get(MSG_SPACE));
562 		return 0;
563 	} else if (tmpx < vc->vc_cols - 2 &&
564 		   (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
565 		   get_char(vc, (u_short *)tmp_pos + 1, &temp) > SPACE) {
566 		tmp_pos += 2;
567 		tmpx++;
568 	} else {
569 		while (tmpx > 0) {
570 			ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
571 			if ((ch == SPACE || ch == 0 ||
572 			     (ch < 0x100 && IS_WDLM(ch))) &&
573 			    get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
574 				break;
575 			tmp_pos -= 2;
576 			tmpx--;
577 		}
578 	}
579 	attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
580 	buf[cnt++] = attr_ch;
581 	while (tmpx < vc->vc_cols - 1) {
582 		tmp_pos += 2;
583 		tmpx++;
584 		ch = get_char(vc, (u_short *)tmp_pos, &temp);
585 		if (ch == SPACE || ch == 0 ||
586 		    (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
587 		     ch > SPACE))
588 			break;
589 		buf[cnt++] = ch;
590 	}
591 	buf[cnt] = '\0';
592 	return cnt;
593 }
594 
595 static void say_word(struct vc_data *vc)
596 {
597 	u_long cnt = get_word(vc);
598 	u_short saved_punc_mask = spk_punc_mask;
599 
600 	if (cnt == 0)
601 		return;
602 	spk_punc_mask = PUNC;
603 	buf[cnt++] = SPACE;
604 	spkup_write(buf, cnt);
605 	spk_punc_mask = saved_punc_mask;
606 }
607 
608 static void say_prev_word(struct vc_data *vc)
609 {
610 	u_char temp;
611 	u16 ch;
612 	enum edge edge_said = edge_none;
613 	u_short last_state = 0, state = 0;
614 
615 	spk_parked |= 0x01;
616 
617 	if (spk_x == 0) {
618 		if (spk_y == 0) {
619 			announce_edge(vc, edge_top);
620 			return;
621 		}
622 		spk_y--;
623 		spk_x = vc->vc_cols;
624 		edge_said = edge_quiet;
625 	}
626 	while (1) {
627 		if (spk_x == 0) {
628 			if (spk_y == 0) {
629 				edge_said = edge_top;
630 				break;
631 			}
632 			if (edge_said != edge_quiet)
633 				edge_said = edge_left;
634 			if (state > 0)
635 				break;
636 			spk_y--;
637 			spk_x = vc->vc_cols - 1;
638 		} else {
639 			spk_x--;
640 		}
641 		spk_pos -= 2;
642 		ch = get_char(vc, (u_short *)spk_pos, &temp);
643 		if (ch == SPACE || ch == 0)
644 			state = 0;
645 		else if (ch < 0x100 && IS_WDLM(ch))
646 			state = 1;
647 		else
648 			state = 2;
649 		if (state < last_state) {
650 			spk_pos += 2;
651 			spk_x++;
652 			break;
653 		}
654 		last_state = state;
655 	}
656 	if (spk_x == 0 && edge_said == edge_quiet)
657 		edge_said = edge_left;
658 	if (edge_said > edge_none && edge_said < edge_quiet)
659 		announce_edge(vc, edge_said);
660 	say_word(vc);
661 }
662 
663 static void say_next_word(struct vc_data *vc)
664 {
665 	u_char temp;
666 	u16 ch;
667 	enum edge edge_said = edge_none;
668 	u_short last_state = 2, state = 0;
669 
670 	spk_parked |= 0x01;
671 	if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
672 		announce_edge(vc, edge_bottom);
673 		return;
674 	}
675 	while (1) {
676 		ch = get_char(vc, (u_short *)spk_pos, &temp);
677 		if (ch == SPACE || ch == 0)
678 			state = 0;
679 		else if (ch < 0x100 && IS_WDLM(ch))
680 			state = 1;
681 		else
682 			state = 2;
683 		if (state > last_state)
684 			break;
685 		if (spk_x >= vc->vc_cols - 1) {
686 			if (spk_y == vc->vc_rows - 1) {
687 				edge_said = edge_bottom;
688 				break;
689 			}
690 			state = 0;
691 			spk_y++;
692 			spk_x = 0;
693 			edge_said = edge_right;
694 		} else {
695 			spk_x++;
696 		}
697 		spk_pos += 2;
698 		last_state = state;
699 	}
700 	if (edge_said > edge_none)
701 		announce_edge(vc, edge_said);
702 	say_word(vc);
703 }
704 
705 static void spell_word(struct vc_data *vc)
706 {
707 	static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
708 	u16 *cp = buf;
709 	char *cp1;
710 	char *str_cap = spk_str_caps_stop;
711 	char *last_cap = spk_str_caps_stop;
712 	struct var_t *direct = spk_get_var(DIRECT);
713 	u16 ch;
714 
715 	if (!get_word(vc))
716 		return;
717 	while ((ch = *cp)) {
718 		if (cp != buf)
719 			synth_printf(" %s ", delay_str[spk_spell_delay]);
720 		/* FIXME: Non-latin1 considered as lower case */
721 		if (ch < 0x100 && IS_CHAR(ch, B_CAP)) {
722 			str_cap = spk_str_caps_start;
723 			if (*spk_str_caps_stop)
724 				spk_pitch_shift++;
725 			else	/* synth has no pitch */
726 				last_cap = spk_str_caps_stop;
727 		} else {
728 			str_cap = spk_str_caps_stop;
729 		}
730 		if (str_cap != last_cap) {
731 			synth_printf("%s", str_cap);
732 			last_cap = str_cap;
733 		}
734 		if (ch >= 0x100 || (direct && direct->u.n.value)) {
735 			synth_putwc_s(ch);
736 		} else if (this_speakup_key == SPELL_PHONETIC &&
737 		    ch <= 0x7f && isalpha(ch)) {
738 			ch &= 0x1f;
739 			cp1 = phonetic[--ch];
740 			synth_printf("%s", cp1);
741 		} else {
742 			cp1 = spk_characters[ch];
743 			if (*cp1 == '^') {
744 				synth_printf("%s", spk_msg_get(MSG_CTRL));
745 				cp1++;
746 			}
747 			synth_printf("%s", cp1);
748 		}
749 		cp++;
750 	}
751 	if (str_cap != spk_str_caps_stop)
752 		synth_printf("%s", spk_str_caps_stop);
753 }
754 
755 static int get_line(struct vc_data *vc)
756 {
757 	u_long tmp = spk_pos - (spk_x * 2);
758 	int i = 0;
759 	u_char tmp2;
760 
761 	spk_old_attr = spk_attr;
762 	spk_attr = get_attributes(vc, (u_short *)spk_pos);
763 	for (i = 0; i < vc->vc_cols; i++) {
764 		buf[i] = get_char(vc, (u_short *)tmp, &tmp2);
765 		tmp += 2;
766 	}
767 	for (--i; i >= 0; i--)
768 		if (buf[i] != SPACE)
769 			break;
770 	return ++i;
771 }
772 
773 static void say_line(struct vc_data *vc)
774 {
775 	int i = get_line(vc);
776 	u16 *cp;
777 	u_short saved_punc_mask = spk_punc_mask;
778 
779 	if (i == 0) {
780 		synth_printf("%s\n", spk_msg_get(MSG_BLANK));
781 		return;
782 	}
783 	buf[i++] = '\n';
784 	if (this_speakup_key == SAY_LINE_INDENT) {
785 		cp = buf;
786 		while (*cp == SPACE)
787 			cp++;
788 		synth_printf("%zd, ", (cp - buf) + 1);
789 	}
790 	spk_punc_mask = spk_punc_masks[spk_reading_punc];
791 	spkup_write(buf, i);
792 	spk_punc_mask = saved_punc_mask;
793 }
794 
795 static void say_prev_line(struct vc_data *vc)
796 {
797 	spk_parked |= 0x01;
798 	if (spk_y == 0) {
799 		announce_edge(vc, edge_top);
800 		return;
801 	}
802 	spk_y--;
803 	spk_pos -= vc->vc_size_row;
804 	say_line(vc);
805 }
806 
807 static void say_next_line(struct vc_data *vc)
808 {
809 	spk_parked |= 0x01;
810 	if (spk_y == vc->vc_rows - 1) {
811 		announce_edge(vc, edge_bottom);
812 		return;
813 	}
814 	spk_y++;
815 	spk_pos += vc->vc_size_row;
816 	say_line(vc);
817 }
818 
819 static int say_from_to(struct vc_data *vc, u_long from, u_long to,
820 		       int read_punc)
821 {
822 	int i = 0;
823 	u_char tmp;
824 	u_short saved_punc_mask = spk_punc_mask;
825 
826 	spk_old_attr = spk_attr;
827 	spk_attr = get_attributes(vc, (u_short *)from);
828 	while (from < to) {
829 		buf[i++] = get_char(vc, (u_short *)from, &tmp);
830 		from += 2;
831 		if (i >= vc->vc_size_row)
832 			break;
833 	}
834 	for (--i; i >= 0; i--)
835 		if (buf[i] != SPACE)
836 			break;
837 	buf[++i] = SPACE;
838 	buf[++i] = '\0';
839 	if (i < 1)
840 		return i;
841 	if (read_punc)
842 		spk_punc_mask = spk_punc_info[spk_reading_punc].mask;
843 	spkup_write(buf, i);
844 	if (read_punc)
845 		spk_punc_mask = saved_punc_mask;
846 	return i - 1;
847 }
848 
849 static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
850 			     int read_punc)
851 {
852 	u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
853 	u_long end = start + (to * 2);
854 
855 	start += from * 2;
856 	if (say_from_to(vc, start, end, read_punc) <= 0)
857 		if (cursor_track != read_all_mode)
858 			synth_printf("%s\n", spk_msg_get(MSG_BLANK));
859 }
860 
861 /* Sentence Reading Commands */
862 
863 static int currsentence;
864 static int numsentences[2];
865 static u16 *sentbufend[2];
866 static u16 *sentmarks[2][10];
867 static int currbuf;
868 static int bn;
869 static u16 sentbuf[2][256];
870 
871 static int say_sentence_num(int num, int prev)
872 {
873 	bn = currbuf;
874 	currsentence = num + 1;
875 	if (prev && --bn == -1)
876 		bn = 1;
877 
878 	if (num > numsentences[bn])
879 		return 0;
880 
881 	spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
882 	return 1;
883 }
884 
885 static int get_sentence_buf(struct vc_data *vc, int read_punc)
886 {
887 	u_long start, end;
888 	int i, bn;
889 	u_char tmp;
890 
891 	currbuf++;
892 	if (currbuf == 2)
893 		currbuf = 0;
894 	bn = currbuf;
895 	start = vc->vc_origin + ((spk_y) * vc->vc_size_row);
896 	end = vc->vc_origin + ((spk_y) * vc->vc_size_row) + vc->vc_cols * 2;
897 
898 	numsentences[bn] = 0;
899 	sentmarks[bn][0] = &sentbuf[bn][0];
900 	i = 0;
901 	spk_old_attr = spk_attr;
902 	spk_attr = get_attributes(vc, (u_short *)start);
903 
904 	while (start < end) {
905 		sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
906 		if (i > 0) {
907 			if (sentbuf[bn][i] == SPACE &&
908 			    sentbuf[bn][i - 1] == '.' &&
909 			    numsentences[bn] < 9) {
910 				/* Sentence Marker */
911 				numsentences[bn]++;
912 				sentmarks[bn][numsentences[bn]] =
913 				    &sentbuf[bn][i];
914 			}
915 		}
916 		i++;
917 		start += 2;
918 		if (i >= vc->vc_size_row)
919 			break;
920 	}
921 
922 	for (--i; i >= 0; i--)
923 		if (sentbuf[bn][i] != SPACE)
924 			break;
925 
926 	if (i < 1)
927 		return -1;
928 
929 	sentbuf[bn][++i] = SPACE;
930 	sentbuf[bn][++i] = '\0';
931 
932 	sentbufend[bn] = &sentbuf[bn][i];
933 	return numsentences[bn];
934 }
935 
936 static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
937 {
938 	u_long start = vc->vc_origin, end;
939 
940 	if (from > 0)
941 		start += from * vc->vc_size_row;
942 	if (to > vc->vc_rows)
943 		to = vc->vc_rows;
944 	end = vc->vc_origin + (to * vc->vc_size_row);
945 	for (from = start; from < end; from = to) {
946 		to = from + vc->vc_size_row;
947 		say_from_to(vc, from, to, 1);
948 	}
949 }
950 
951 static void say_screen(struct vc_data *vc)
952 {
953 	say_screen_from_to(vc, 0, vc->vc_rows);
954 }
955 
956 static void speakup_win_say(struct vc_data *vc)
957 {
958 	u_long start, end, from, to;
959 
960 	if (win_start < 2) {
961 		synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
962 		return;
963 	}
964 	start = vc->vc_origin + (win_top * vc->vc_size_row);
965 	end = vc->vc_origin + (win_bottom * vc->vc_size_row);
966 	while (start <= end) {
967 		from = start + (win_left * 2);
968 		to = start + (win_right * 2);
969 		say_from_to(vc, from, to, 1);
970 		start += vc->vc_size_row;
971 	}
972 }
973 
974 static void top_edge(struct vc_data *vc)
975 {
976 	spk_parked |= 0x01;
977 	spk_pos = vc->vc_origin + 2 * spk_x;
978 	spk_y = 0;
979 	say_line(vc);
980 }
981 
982 static void bottom_edge(struct vc_data *vc)
983 {
984 	spk_parked |= 0x01;
985 	spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
986 	spk_y = vc->vc_rows - 1;
987 	say_line(vc);
988 }
989 
990 static void left_edge(struct vc_data *vc)
991 {
992 	spk_parked |= 0x01;
993 	spk_pos -= spk_x * 2;
994 	spk_x = 0;
995 	say_char(vc);
996 }
997 
998 static void right_edge(struct vc_data *vc)
999 {
1000 	spk_parked |= 0x01;
1001 	spk_pos += (vc->vc_cols - spk_x - 1) * 2;
1002 	spk_x = vc->vc_cols - 1;
1003 	say_char(vc);
1004 }
1005 
1006 static void say_first_char(struct vc_data *vc)
1007 {
1008 	int i, len = get_line(vc);
1009 	u16 ch;
1010 
1011 	spk_parked |= 0x01;
1012 	if (len == 0) {
1013 		synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1014 		return;
1015 	}
1016 	for (i = 0; i < len; i++)
1017 		if (buf[i] != SPACE)
1018 			break;
1019 	ch = buf[i];
1020 	spk_pos -= (spk_x - i) * 2;
1021 	spk_x = i;
1022 	synth_printf("%d, ", ++i);
1023 	speak_char(ch);
1024 }
1025 
1026 static void say_last_char(struct vc_data *vc)
1027 {
1028 	int len = get_line(vc);
1029 	u16 ch;
1030 
1031 	spk_parked |= 0x01;
1032 	if (len == 0) {
1033 		synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1034 		return;
1035 	}
1036 	ch = buf[--len];
1037 	spk_pos -= (spk_x - len) * 2;
1038 	spk_x = len;
1039 	synth_printf("%d, ", ++len);
1040 	speak_char(ch);
1041 }
1042 
1043 static void say_position(struct vc_data *vc)
1044 {
1045 	synth_printf(spk_msg_get(MSG_POS_INFO), spk_y + 1, spk_x + 1,
1046 		     vc->vc_num + 1);
1047 	synth_printf("\n");
1048 }
1049 
1050 /* Added by brianb */
1051 static void say_char_num(struct vc_data *vc)
1052 {
1053 	u_char tmp;
1054 	u16 ch = get_char(vc, (u_short *)spk_pos, &tmp);
1055 
1056 	synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
1057 }
1058 
1059 /* these are stub functions to keep keyboard.c happy. */
1060 
1061 static void say_from_top(struct vc_data *vc)
1062 {
1063 	say_screen_from_to(vc, 0, spk_y);
1064 }
1065 
1066 static void say_to_bottom(struct vc_data *vc)
1067 {
1068 	say_screen_from_to(vc, spk_y, vc->vc_rows);
1069 }
1070 
1071 static void say_from_left(struct vc_data *vc)
1072 {
1073 	say_line_from_to(vc, 0, spk_x, 1);
1074 }
1075 
1076 static void say_to_right(struct vc_data *vc)
1077 {
1078 	say_line_from_to(vc, spk_x, vc->vc_cols, 1);
1079 }
1080 
1081 /* end of stub functions. */
1082 
1083 static void spkup_write(const u16 *in_buf, int count)
1084 {
1085 	static int rep_count;
1086 	static u16 ch = '\0', old_ch = '\0';
1087 	static u_short char_type, last_type;
1088 	int in_count = count;
1089 
1090 	spk_keydown = 0;
1091 	while (count--) {
1092 		if (cursor_track == read_all_mode) {
1093 			/* Insert Sentence Index */
1094 			if ((in_buf == sentmarks[bn][currsentence]) &&
1095 			    (currsentence <= numsentences[bn]))
1096 				synth_insert_next_index(currsentence++);
1097 		}
1098 		ch = *in_buf++;
1099 		if (ch < 0x100)
1100 			char_type = spk_chartab[ch];
1101 		else
1102 			char_type = ALPHA;
1103 		if (ch == old_ch && !(char_type & B_NUM)) {
1104 			if (++rep_count > 2)
1105 				continue;
1106 		} else {
1107 			if ((last_type & CH_RPT) && rep_count > 2) {
1108 				synth_printf(" ");
1109 				synth_printf(spk_msg_get(MSG_REPEAT_DESC),
1110 					     ++rep_count);
1111 				synth_printf(" ");
1112 			}
1113 			rep_count = 0;
1114 		}
1115 		if (ch == spk_lastkey) {
1116 			rep_count = 0;
1117 			if (spk_key_echo == 1 && ch >= MINECHOCHAR)
1118 				speak_char(ch);
1119 		} else if (char_type & B_ALPHA) {
1120 			if ((synth_flags & SF_DEC) && (last_type & PUNC))
1121 				synth_buffer_add(SPACE);
1122 			synth_putwc_s(ch);
1123 		} else if (char_type & B_NUM) {
1124 			rep_count = 0;
1125 			synth_putwc_s(ch);
1126 		} else if (char_type & spk_punc_mask) {
1127 			speak_char(ch);
1128 			char_type &= ~PUNC;	/* for dec nospell processing */
1129 		} else if (char_type & SYNTH_OK) {
1130 			/* these are usually puncts like . and , which synth
1131 			 * needs for expression.
1132 			 * suppress multiple to get rid of long pauses and
1133 			 * clear repeat count
1134 			 * so if someone has
1135 			 * repeats on you don't get nothing repeated count
1136 			 */
1137 			if (ch != old_ch)
1138 				synth_putwc_s(ch);
1139 			else
1140 				rep_count = 0;
1141 		} else {
1142 /* send space and record position, if next is num overwrite space */
1143 			if (old_ch != ch)
1144 				synth_buffer_add(SPACE);
1145 			else
1146 				rep_count = 0;
1147 		}
1148 		old_ch = ch;
1149 		last_type = char_type;
1150 	}
1151 	spk_lastkey = 0;
1152 	if (in_count > 2 && rep_count > 2) {
1153 		if (last_type & CH_RPT) {
1154 			synth_printf(" ");
1155 			synth_printf(spk_msg_get(MSG_REPEAT_DESC2),
1156 				     ++rep_count);
1157 			synth_printf(" ");
1158 		}
1159 		rep_count = 0;
1160 	}
1161 }
1162 
1163 static const int NUM_CTL_LABELS = (MSG_CTL_END - MSG_CTL_START + 1);
1164 
1165 static void read_all_doc(struct vc_data *vc);
1166 static void cursor_done(struct timer_list *unused);
1167 static DEFINE_TIMER(cursor_timer, cursor_done);
1168 
1169 static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag)
1170 {
1171 	unsigned long flags;
1172 
1173 	if (!synth || up_flag || spk_killed)
1174 		return;
1175 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1176 	if (cursor_track == read_all_mode) {
1177 		switch (value) {
1178 		case KVAL(K_SHIFT):
1179 			del_timer(&cursor_timer);
1180 			spk_shut_up &= 0xfe;
1181 			spk_do_flush();
1182 			read_all_doc(vc);
1183 			break;
1184 		case KVAL(K_CTRL):
1185 			del_timer(&cursor_timer);
1186 			cursor_track = prev_cursor_track;
1187 			spk_shut_up &= 0xfe;
1188 			spk_do_flush();
1189 			break;
1190 		}
1191 	} else {
1192 		spk_shut_up &= 0xfe;
1193 		spk_do_flush();
1194 	}
1195 	if (spk_say_ctrl && value < NUM_CTL_LABELS)
1196 		synth_printf("%s", spk_msg_get(MSG_CTL_START + value));
1197 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1198 }
1199 
1200 static void do_handle_latin(struct vc_data *vc, u_char value, char up_flag)
1201 {
1202 	unsigned long flags;
1203 
1204 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1205 	if (up_flag) {
1206 		spk_lastkey = 0;
1207 		spk_keydown = 0;
1208 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1209 		return;
1210 	}
1211 	if (!synth || spk_killed) {
1212 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1213 		return;
1214 	}
1215 	spk_shut_up &= 0xfe;
1216 	spk_lastkey = value;
1217 	spk_keydown++;
1218 	spk_parked &= 0xfe;
1219 	if (spk_key_echo == 2 && value >= MINECHOCHAR)
1220 		speak_char(value);
1221 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1222 }
1223 
1224 int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
1225 {
1226 	int i = 0, states, key_data_len;
1227 	const u_char *cp = key_info;
1228 	u_char *cp1 = k_buffer;
1229 	u_char ch, version, num_keys;
1230 
1231 	version = *cp++;
1232 	if (version != KEY_MAP_VER) {
1233 		pr_debug("version found %d should be %d\n",
1234 			 version, KEY_MAP_VER);
1235 		return -EINVAL;
1236 	}
1237 	num_keys = *cp;
1238 	states = (int)cp[1];
1239 	key_data_len = (states + 1) * (num_keys + 1);
1240 	if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) {
1241 		pr_debug("too many key_infos (%d over %u)\n",
1242 			 key_data_len + SHIFT_TBL_SIZE + 4,
1243 			 (unsigned int)(sizeof(spk_key_buf)));
1244 		return -EINVAL;
1245 	}
1246 	memset(k_buffer, 0, SHIFT_TBL_SIZE);
1247 	memset(spk_our_keys, 0, sizeof(spk_our_keys));
1248 	spk_shift_table = k_buffer;
1249 	spk_our_keys[0] = spk_shift_table;
1250 	cp1 += SHIFT_TBL_SIZE;
1251 	memcpy(cp1, cp, key_data_len + 3);
1252 	/* get num_keys, states and data */
1253 	cp1 += 2;		/* now pointing at shift states */
1254 	for (i = 1; i <= states; i++) {
1255 		ch = *cp1++;
1256 		if (ch >= SHIFT_TBL_SIZE) {
1257 			pr_debug("(%d) not valid shift state (max_allowed = %d)\n",
1258 				 ch, SHIFT_TBL_SIZE);
1259 			return -EINVAL;
1260 		}
1261 		spk_shift_table[ch] = i;
1262 	}
1263 	keymap_flags = *cp1++;
1264 	while ((ch = *cp1)) {
1265 		if (ch >= MAX_KEY) {
1266 			pr_debug("(%d), not valid key, (max_allowed = %d)\n",
1267 				 ch, MAX_KEY);
1268 			return -EINVAL;
1269 		}
1270 		spk_our_keys[ch] = cp1;
1271 		cp1 += states + 1;
1272 	}
1273 	return 0;
1274 }
1275 
1276 static struct var_t spk_vars[] = {
1277 	/* bell must be first to set high limit */
1278 	{BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1279 	{SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1280 	{ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1281 	{BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1282 	{BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1283 	{PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1284 	{READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1285 	{CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1286 	{SAY_CONTROL, TOGGLE_0},
1287 	{SAY_WORD_CTL, TOGGLE_0},
1288 	{NO_INTERRUPT, TOGGLE_0},
1289 	{KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1290 	V_LAST_VAR
1291 };
1292 
1293 static void toggle_cursoring(struct vc_data *vc)
1294 {
1295 	if (cursor_track == read_all_mode)
1296 		cursor_track = prev_cursor_track;
1297 	if (++cursor_track >= CT_Max)
1298 		cursor_track = 0;
1299 	synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1300 }
1301 
1302 void spk_reset_default_chars(void)
1303 {
1304 	int i;
1305 
1306 	/* First, free any non-default */
1307 	for (i = 0; i < 256; i++) {
1308 		if (spk_characters[i] &&
1309 		    (spk_characters[i] != spk_default_chars[i]))
1310 			kfree(spk_characters[i]);
1311 	}
1312 
1313 	memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1314 }
1315 
1316 void spk_reset_default_chartab(void)
1317 {
1318 	memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1319 }
1320 
1321 static const struct st_bits_data *pb_edit;
1322 
1323 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1324 {
1325 	short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1326 
1327 	if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1328 		return -1;
1329 	if (ch == SPACE) {
1330 		synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1331 		spk_special_handler = NULL;
1332 		return 1;
1333 	}
1334 	if (mask < PUNC && !(ch_type & PUNC))
1335 		return -1;
1336 	spk_chartab[ch] ^= mask;
1337 	speak_char(ch);
1338 	synth_printf(" %s\n",
1339 		     (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1340 		     spk_msg_get(MSG_OFF));
1341 	return 1;
1342 }
1343 
1344 /* Allocation concurrency is protected by the console semaphore */
1345 static int speakup_allocate(struct vc_data *vc, gfp_t gfp_flags)
1346 {
1347 	int vc_num;
1348 
1349 	vc_num = vc->vc_num;
1350 	if (!speakup_console[vc_num]) {
1351 		speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1352 						  gfp_flags);
1353 		if (!speakup_console[vc_num])
1354 			return -ENOMEM;
1355 		speakup_date(vc);
1356 	} else if (!spk_parked) {
1357 		speakup_date(vc);
1358 	}
1359 
1360 	return 0;
1361 }
1362 
1363 static void speakup_deallocate(struct vc_data *vc)
1364 {
1365 	int vc_num;
1366 
1367 	vc_num = vc->vc_num;
1368 	kfree(speakup_console[vc_num]);
1369 	speakup_console[vc_num] = NULL;
1370 }
1371 
1372 enum read_all_command {
1373 	RA_NEXT_SENT = KVAL(K_DOWN)+1,
1374 	RA_PREV_LINE = KVAL(K_LEFT)+1,
1375 	RA_NEXT_LINE = KVAL(K_RIGHT)+1,
1376 	RA_PREV_SENT = KVAL(K_UP)+1,
1377 	RA_DOWN_ARROW,
1378 	RA_TIMER,
1379 	RA_FIND_NEXT_SENT,
1380 	RA_FIND_PREV_SENT,
1381 };
1382 
1383 static u_char is_cursor;
1384 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1385 static int cursor_con;
1386 
1387 static void reset_highlight_buffers(struct vc_data *);
1388 
1389 static enum read_all_command read_all_key;
1390 
1391 static int in_keyboard_notifier;
1392 
1393 static void start_read_all_timer(struct vc_data *vc, enum read_all_command command);
1394 
1395 static void kbd_fakekey2(struct vc_data *vc, enum read_all_command command)
1396 {
1397 	del_timer(&cursor_timer);
1398 	speakup_fake_down_arrow();
1399 	start_read_all_timer(vc, command);
1400 }
1401 
1402 static void read_all_doc(struct vc_data *vc)
1403 {
1404 	if ((vc->vc_num != fg_console) || !synth || spk_shut_up)
1405 		return;
1406 	if (!synth_supports_indexing())
1407 		return;
1408 	if (cursor_track != read_all_mode)
1409 		prev_cursor_track = cursor_track;
1410 	cursor_track = read_all_mode;
1411 	spk_reset_index_count(0);
1412 	if (get_sentence_buf(vc, 0) == -1) {
1413 		del_timer(&cursor_timer);
1414 		if (!in_keyboard_notifier)
1415 			speakup_fake_down_arrow();
1416 		start_read_all_timer(vc, RA_DOWN_ARROW);
1417 	} else {
1418 		say_sentence_num(0, 0);
1419 		synth_insert_next_index(0);
1420 		start_read_all_timer(vc, RA_TIMER);
1421 	}
1422 }
1423 
1424 static void stop_read_all(struct vc_data *vc)
1425 {
1426 	del_timer(&cursor_timer);
1427 	cursor_track = prev_cursor_track;
1428 	spk_shut_up &= 0xfe;
1429 	spk_do_flush();
1430 }
1431 
1432 static void start_read_all_timer(struct vc_data *vc, enum read_all_command command)
1433 {
1434 	struct var_t *cursor_timeout;
1435 
1436 	cursor_con = vc->vc_num;
1437 	read_all_key = command;
1438 	cursor_timeout = spk_get_var(CURSOR_TIME);
1439 	mod_timer(&cursor_timer,
1440 		  jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1441 }
1442 
1443 static void handle_cursor_read_all(struct vc_data *vc, enum read_all_command command)
1444 {
1445 	int indcount, sentcount, rv, sn;
1446 
1447 	switch (command) {
1448 	case RA_NEXT_SENT:
1449 		/* Get Current Sentence */
1450 		spk_get_index_count(&indcount, &sentcount);
1451 		/*printk("%d %d  ", indcount, sentcount); */
1452 		spk_reset_index_count(sentcount + 1);
1453 		if (indcount == 1) {
1454 			if (!say_sentence_num(sentcount + 1, 0)) {
1455 				kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1456 				return;
1457 			}
1458 			synth_insert_next_index(0);
1459 		} else {
1460 			sn = 0;
1461 			if (!say_sentence_num(sentcount + 1, 1)) {
1462 				sn = 1;
1463 				spk_reset_index_count(sn);
1464 			} else {
1465 				synth_insert_next_index(0);
1466 			}
1467 			if (!say_sentence_num(sn, 0)) {
1468 				kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1469 				return;
1470 			}
1471 			synth_insert_next_index(0);
1472 		}
1473 		start_read_all_timer(vc, RA_TIMER);
1474 		break;
1475 	case RA_PREV_SENT:
1476 		break;
1477 	case RA_NEXT_LINE:
1478 		read_all_doc(vc);
1479 		break;
1480 	case RA_PREV_LINE:
1481 		break;
1482 	case RA_DOWN_ARROW:
1483 		if (get_sentence_buf(vc, 0) == -1) {
1484 			kbd_fakekey2(vc, RA_DOWN_ARROW);
1485 		} else {
1486 			say_sentence_num(0, 0);
1487 			synth_insert_next_index(0);
1488 			start_read_all_timer(vc, RA_TIMER);
1489 		}
1490 		break;
1491 	case RA_FIND_NEXT_SENT:
1492 		rv = get_sentence_buf(vc, 0);
1493 		if (rv == -1)
1494 			read_all_doc(vc);
1495 		if (rv == 0) {
1496 			kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1497 		} else {
1498 			say_sentence_num(1, 0);
1499 			synth_insert_next_index(0);
1500 			start_read_all_timer(vc, RA_TIMER);
1501 		}
1502 		break;
1503 	case RA_FIND_PREV_SENT:
1504 		break;
1505 	case RA_TIMER:
1506 		spk_get_index_count(&indcount, &sentcount);
1507 		if (indcount < 2)
1508 			kbd_fakekey2(vc, RA_DOWN_ARROW);
1509 		else
1510 			start_read_all_timer(vc, RA_TIMER);
1511 		break;
1512 	}
1513 }
1514 
1515 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1516 {
1517 	unsigned long flags;
1518 
1519 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1520 	if (cursor_track == read_all_mode) {
1521 		spk_parked &= 0xfe;
1522 		if (!synth || up_flag || spk_shut_up) {
1523 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1524 			return NOTIFY_STOP;
1525 		}
1526 		del_timer(&cursor_timer);
1527 		spk_shut_up &= 0xfe;
1528 		spk_do_flush();
1529 		start_read_all_timer(vc, value + 1);
1530 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1531 		return NOTIFY_STOP;
1532 	}
1533 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1534 	return NOTIFY_OK;
1535 }
1536 
1537 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1538 {
1539 	unsigned long flags;
1540 	struct var_t *cursor_timeout;
1541 
1542 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1543 	spk_parked &= 0xfe;
1544 	if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) {
1545 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1546 		return;
1547 	}
1548 	spk_shut_up &= 0xfe;
1549 	if (spk_no_intr)
1550 		spk_do_flush();
1551 /* the key press flushes if !no_inter but we want to flush on cursor
1552  * moves regardless of no_inter state
1553  */
1554 	is_cursor = value + 1;
1555 	old_cursor_pos = vc->vc_pos;
1556 	old_cursor_x = vc->state.x;
1557 	old_cursor_y = vc->state.y;
1558 	speakup_console[vc->vc_num]->ht.cy = vc->state.y;
1559 	cursor_con = vc->vc_num;
1560 	if (cursor_track == CT_Highlight)
1561 		reset_highlight_buffers(vc);
1562 	cursor_timeout = spk_get_var(CURSOR_TIME);
1563 	mod_timer(&cursor_timer,
1564 		  jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1565 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1566 }
1567 
1568 static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
1569 {
1570 	int i, bi, hi;
1571 	int vc_num = vc->vc_num;
1572 
1573 	bi = (vc->vc_attr & 0x70) >> 4;
1574 	hi = speakup_console[vc_num]->ht.highsize[bi];
1575 
1576 	i = 0;
1577 	if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1578 		speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1579 		speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
1580 		speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
1581 	}
1582 	while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1583 		if (ic[i] > 32) {
1584 			speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1585 			hi++;
1586 		} else if ((ic[i] == 32) && (hi != 0)) {
1587 			if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1588 			    32) {
1589 				speakup_console[vc_num]->ht.highbuf[bi][hi] =
1590 				    ic[i];
1591 				hi++;
1592 			}
1593 		}
1594 		i++;
1595 	}
1596 	speakup_console[vc_num]->ht.highsize[bi] = hi;
1597 }
1598 
1599 static void reset_highlight_buffers(struct vc_data *vc)
1600 {
1601 	int i;
1602 	int vc_num = vc->vc_num;
1603 
1604 	for (i = 0; i < 8; i++)
1605 		speakup_console[vc_num]->ht.highsize[i] = 0;
1606 }
1607 
1608 static int count_highlight_color(struct vc_data *vc)
1609 {
1610 	int i, bg;
1611 	int cc;
1612 	int vc_num = vc->vc_num;
1613 	u16 ch;
1614 	u16 *start = (u16 *)vc->vc_origin;
1615 
1616 	for (i = 0; i < 8; i++)
1617 		speakup_console[vc_num]->ht.bgcount[i] = 0;
1618 
1619 	for (i = 0; i < vc->vc_rows; i++) {
1620 		u16 *end = start + vc->vc_cols * 2;
1621 		u16 *ptr;
1622 
1623 		for (ptr = start; ptr < end; ptr++) {
1624 			ch = get_attributes(vc, ptr);
1625 			bg = (ch & 0x70) >> 4;
1626 			speakup_console[vc_num]->ht.bgcount[bg]++;
1627 		}
1628 		start += vc->vc_size_row;
1629 	}
1630 
1631 	cc = 0;
1632 	for (i = 0; i < 8; i++)
1633 		if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1634 			cc++;
1635 	return cc;
1636 }
1637 
1638 static int get_highlight_color(struct vc_data *vc)
1639 {
1640 	int i, j;
1641 	unsigned int cptr[8];
1642 	int vc_num = vc->vc_num;
1643 
1644 	for (i = 0; i < 8; i++)
1645 		cptr[i] = i;
1646 
1647 	for (i = 0; i < 7; i++)
1648 		for (j = i + 1; j < 8; j++)
1649 			if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1650 			    speakup_console[vc_num]->ht.bgcount[cptr[j]])
1651 				swap(cptr[i], cptr[j]);
1652 
1653 	for (i = 0; i < 8; i++)
1654 		if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1655 			if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1656 				return cptr[i];
1657 	return -1;
1658 }
1659 
1660 static int speak_highlight(struct vc_data *vc)
1661 {
1662 	int hc, d;
1663 	int vc_num = vc->vc_num;
1664 
1665 	if (count_highlight_color(vc) == 1)
1666 		return 0;
1667 	hc = get_highlight_color(vc);
1668 	if (hc != -1) {
1669 		d = vc->state.y - speakup_console[vc_num]->ht.cy;
1670 		if ((d == 1) || (d == -1))
1671 			if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
1672 				return 0;
1673 		spk_parked |= 0x01;
1674 		spk_do_flush();
1675 		spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1676 			    speakup_console[vc_num]->ht.highsize[hc]);
1677 		spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1678 		spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1679 		spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1680 		return 1;
1681 	}
1682 	return 0;
1683 }
1684 
1685 static void cursor_done(struct timer_list *unused)
1686 {
1687 	struct vc_data *vc = vc_cons[cursor_con].d;
1688 	unsigned long flags;
1689 
1690 	del_timer(&cursor_timer);
1691 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1692 	if (cursor_con != fg_console) {
1693 		is_cursor = 0;
1694 		goto out;
1695 	}
1696 	speakup_date(vc);
1697 	if (win_enabled) {
1698 		if (vc->state.x >= win_left && vc->state.x <= win_right &&
1699 		    vc->state.y >= win_top && vc->state.y <= win_bottom) {
1700 			spk_keydown = 0;
1701 			is_cursor = 0;
1702 			goto out;
1703 		}
1704 	}
1705 	if (cursor_track == read_all_mode) {
1706 		handle_cursor_read_all(vc, read_all_key);
1707 		goto out;
1708 	}
1709 	if (cursor_track == CT_Highlight) {
1710 		if (speak_highlight(vc)) {
1711 			spk_keydown = 0;
1712 			is_cursor = 0;
1713 			goto out;
1714 		}
1715 	}
1716 	if (cursor_track == CT_Window)
1717 		speakup_win_say(vc);
1718 	else if (is_cursor == 1 || is_cursor == 4)
1719 		say_line_from_to(vc, 0, vc->vc_cols, 0);
1720 	else
1721 		say_char(vc);
1722 	spk_keydown = 0;
1723 	is_cursor = 0;
1724 out:
1725 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1726 }
1727 
1728 /* called by: vt_notifier_call() */
1729 static void speakup_bs(struct vc_data *vc)
1730 {
1731 	unsigned long flags;
1732 
1733 	if (!speakup_console[vc->vc_num])
1734 		return;
1735 	if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1736 		/* Speakup output, discard */
1737 		return;
1738 	if (!spk_parked)
1739 		speakup_date(vc);
1740 	if (spk_shut_up || !synth) {
1741 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1742 		return;
1743 	}
1744 	if (vc->vc_num == fg_console && spk_keydown) {
1745 		spk_keydown = 0;
1746 		if (!is_cursor)
1747 			say_char(vc);
1748 	}
1749 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1750 }
1751 
1752 /* called by: vt_notifier_call() */
1753 static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
1754 {
1755 	unsigned long flags;
1756 
1757 	if ((vc->vc_num != fg_console) || spk_shut_up || !synth)
1758 		return;
1759 	if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1760 		/* Speakup output, discard */
1761 		return;
1762 	if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
1763 		bleep(3);
1764 	if ((is_cursor) || (cursor_track == read_all_mode)) {
1765 		if (cursor_track == CT_Highlight)
1766 			update_color_buffer(vc, str, len);
1767 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1768 		return;
1769 	}
1770 	if (win_enabled) {
1771 		if (vc->state.x >= win_left && vc->state.x <= win_right &&
1772 		    vc->state.y >= win_top && vc->state.y <= win_bottom) {
1773 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1774 			return;
1775 		}
1776 	}
1777 
1778 	spkup_write(str, len);
1779 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1780 }
1781 
1782 static void speakup_con_update(struct vc_data *vc)
1783 {
1784 	unsigned long flags;
1785 
1786 	if (!speakup_console[vc->vc_num] || spk_parked)
1787 		return;
1788 	if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1789 		/* Speakup output, discard */
1790 		return;
1791 	speakup_date(vc);
1792 	if (vc->vc_mode == KD_GRAPHICS && !spk_paused && spk_str_pause[0]) {
1793 		synth_printf("%s", spk_str_pause);
1794 		spk_paused = true;
1795 	}
1796 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1797 }
1798 
1799 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1800 {
1801 	unsigned long flags;
1802 	int on_off = 2;
1803 	char *label;
1804 
1805 	if (!synth || up_flag || spk_killed)
1806 		return;
1807 	spin_lock_irqsave(&speakup_info.spinlock, flags);
1808 	spk_shut_up &= 0xfe;
1809 	if (spk_no_intr)
1810 		spk_do_flush();
1811 	switch (value) {
1812 	case KVAL(K_CAPS):
1813 		label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1814 		on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1815 		break;
1816 	case KVAL(K_NUM):
1817 		label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1818 		on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1819 		break;
1820 	case KVAL(K_HOLD):
1821 		label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1822 		on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1823 		if (speakup_console[vc->vc_num])
1824 			speakup_console[vc->vc_num]->tty_stopped = on_off;
1825 		break;
1826 	default:
1827 		spk_parked &= 0xfe;
1828 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1829 		return;
1830 	}
1831 	if (on_off < 2)
1832 		synth_printf("%s %s\n",
1833 			     label, spk_msg_get(MSG_STATUS_START + on_off));
1834 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1835 }
1836 
1837 static int inc_dec_var(u_char value)
1838 {
1839 	struct st_var_header *p_header;
1840 	struct var_t *var_data;
1841 	char num_buf[32];
1842 	char *cp = num_buf;
1843 	char *pn;
1844 	int var_id = (int)value - VAR_START;
1845 	int how = (var_id & 1) ? E_INC : E_DEC;
1846 
1847 	var_id = var_id / 2 + FIRST_SET_VAR;
1848 	p_header = spk_get_var_header(var_id);
1849 	if (!p_header)
1850 		return -1;
1851 	if (p_header->var_type != VAR_NUM)
1852 		return -1;
1853 	var_data = p_header->data;
1854 	if (spk_set_num_var(1, p_header, how) != 0)
1855 		return -1;
1856 	if (!spk_close_press) {
1857 		for (pn = p_header->name; *pn; pn++) {
1858 			if (*pn == '_')
1859 				*cp = SPACE;
1860 			else
1861 				*cp++ = *pn;
1862 		}
1863 	}
1864 	snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1865 		 var_data->u.n.value);
1866 	synth_printf("%s", num_buf);
1867 	return 0;
1868 }
1869 
1870 static void speakup_win_set(struct vc_data *vc)
1871 {
1872 	char info[40];
1873 
1874 	if (win_start > 1) {
1875 		synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1876 		return;
1877 	}
1878 	if (spk_x < win_left || spk_y < win_top) {
1879 		synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1880 		return;
1881 	}
1882 	if (win_start && spk_x == win_left && spk_y == win_top) {
1883 		win_left = 0;
1884 		win_right = vc->vc_cols - 1;
1885 		win_bottom = spk_y;
1886 		snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1887 			 (int)win_top + 1);
1888 	} else {
1889 		if (!win_start) {
1890 			win_top = spk_y;
1891 			win_left = spk_x;
1892 		} else {
1893 			win_bottom = spk_y;
1894 			win_right = spk_x;
1895 		}
1896 		snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1897 			 (win_start) ?
1898 				spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1899 			 (int)spk_y + 1, (int)spk_x + 1);
1900 	}
1901 	synth_printf("%s\n", info);
1902 	win_start++;
1903 }
1904 
1905 static void speakup_win_clear(struct vc_data *vc)
1906 {
1907 	win_top = 0;
1908 	win_bottom = 0;
1909 	win_left = 0;
1910 	win_right = 0;
1911 	win_start = 0;
1912 	synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1913 }
1914 
1915 static void speakup_win_enable(struct vc_data *vc)
1916 {
1917 	if (win_start < 2) {
1918 		synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1919 		return;
1920 	}
1921 	win_enabled ^= 1;
1922 	if (win_enabled)
1923 		synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1924 	else
1925 		synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1926 }
1927 
1928 static void speakup_bits(struct vc_data *vc)
1929 {
1930 	int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1931 
1932 	if (spk_special_handler || val < 1 || val > 6) {
1933 		synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1934 		return;
1935 	}
1936 	pb_edit = &spk_punc_info[val];
1937 	synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1938 	spk_special_handler = edit_bits;
1939 }
1940 
1941 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1942 {
1943 	static u_char goto_buf[8];
1944 	static int num;
1945 	int maxlen;
1946 	char *cp;
1947 	u16 wch;
1948 
1949 	if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1950 		goto do_goto;
1951 	if (type == KT_LATIN && ch == '\n')
1952 		goto do_goto;
1953 	if (type != 0)
1954 		goto oops;
1955 	if (ch == 8) {
1956 		u16 wch;
1957 
1958 		if (num == 0)
1959 			return -1;
1960 		wch = goto_buf[--num];
1961 		goto_buf[num] = '\0';
1962 		spkup_write(&wch, 1);
1963 		return 1;
1964 	}
1965 	if (ch < '+' || ch > 'y')
1966 		goto oops;
1967 	wch = ch;
1968 	goto_buf[num++] = ch;
1969 	goto_buf[num] = '\0';
1970 	spkup_write(&wch, 1);
1971 	maxlen = (*goto_buf >= '0') ? 3 : 4;
1972 	if ((ch == '+' || ch == '-') && num == 1)
1973 		return 1;
1974 	if (ch >= '0' && ch <= '9' && num < maxlen)
1975 		return 1;
1976 	if (num < maxlen - 1 || num > maxlen)
1977 		goto oops;
1978 	if (ch < 'x' || ch > 'y') {
1979 oops:
1980 		if (!spk_killed)
1981 			synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1982 		goto_buf[num = 0] = '\0';
1983 		spk_special_handler = NULL;
1984 		return 1;
1985 	}
1986 
1987 	/* Do not replace with kstrtoul: here we need cp to be updated */
1988 	goto_pos = simple_strtoul(goto_buf, &cp, 10);
1989 
1990 	if (*cp == 'x') {
1991 		if (*goto_buf < '0')
1992 			goto_pos += spk_x;
1993 		else if (goto_pos > 0)
1994 			goto_pos--;
1995 
1996 		if (goto_pos >= vc->vc_cols)
1997 			goto_pos = vc->vc_cols - 1;
1998 		goto_x = 1;
1999 	} else {
2000 		if (*goto_buf < '0')
2001 			goto_pos += spk_y;
2002 		else if (goto_pos > 0)
2003 			goto_pos--;
2004 
2005 		if (goto_pos >= vc->vc_rows)
2006 			goto_pos = vc->vc_rows - 1;
2007 		goto_x = 0;
2008 	}
2009 	goto_buf[num = 0] = '\0';
2010 do_goto:
2011 	spk_special_handler = NULL;
2012 	spk_parked |= 0x01;
2013 	if (goto_x) {
2014 		spk_pos -= spk_x * 2;
2015 		spk_x = goto_pos;
2016 		spk_pos += goto_pos * 2;
2017 		say_word(vc);
2018 	} else {
2019 		spk_y = goto_pos;
2020 		spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
2021 		say_line(vc);
2022 	}
2023 	return 1;
2024 }
2025 
2026 static void speakup_goto(struct vc_data *vc)
2027 {
2028 	if (spk_special_handler) {
2029 		synth_printf("%s\n", spk_msg_get(MSG_ERROR));
2030 		return;
2031 	}
2032 	synth_printf("%s\n", spk_msg_get(MSG_GOTO));
2033 	spk_special_handler = handle_goto;
2034 }
2035 
2036 static void speakup_help(struct vc_data *vc)
2037 {
2038 	spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
2039 }
2040 
2041 static void do_nothing(struct vc_data *vc)
2042 {
2043 	return;			/* flush done in do_spkup */
2044 }
2045 
2046 static u_char key_speakup, spk_key_locked;
2047 
2048 static void speakup_lock(struct vc_data *vc)
2049 {
2050 	if (!spk_key_locked) {
2051 		spk_key_locked = 16;
2052 		key_speakup = 16;
2053 	} else {
2054 		spk_key_locked = 0;
2055 		key_speakup = 0;
2056 	}
2057 }
2058 
2059 typedef void (*spkup_hand) (struct vc_data *);
2060 static spkup_hand spkup_handler[] = {
2061 	/* must be ordered same as defines in speakup.h */
2062 	do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2063 	speakup_cut, speakup_paste, say_first_char, say_last_char,
2064 	say_char, say_prev_char, say_next_char,
2065 	say_word, say_prev_word, say_next_word,
2066 	say_line, say_prev_line, say_next_line,
2067 	top_edge, bottom_edge, left_edge, right_edge,
2068 	spell_word, spell_word, say_screen,
2069 	say_position, say_attributes,
2070 	speakup_off, speakup_parked, say_line,	/* this is for indent */
2071 	say_from_top, say_to_bottom,
2072 	say_from_left, say_to_right,
2073 	say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2074 	speakup_bits, speakup_bits, speakup_bits,
2075 	speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2076 	speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2077 };
2078 
2079 static void do_spkup(struct vc_data *vc, u_char value)
2080 {
2081 	if (spk_killed && value != SPEECH_KILL)
2082 		return;
2083 	spk_keydown = 0;
2084 	spk_lastkey = 0;
2085 	spk_shut_up &= 0xfe;
2086 	this_speakup_key = value;
2087 	if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2088 		spk_do_flush();
2089 		(*spkup_handler[value]) (vc);
2090 	} else {
2091 		if (inc_dec_var(value) < 0)
2092 			bleep(9);
2093 	}
2094 }
2095 
2096 static const char *pad_chars = "0123456789+-*/\015,.?()";
2097 
2098 static int
2099 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2100 	    int up_flag)
2101 {
2102 	unsigned long flags;
2103 	int kh;
2104 	u_char *key_info;
2105 	u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2106 	u_char shift_info, offset;
2107 	int ret = 0;
2108 
2109 	if (!synth)
2110 		return 0;
2111 
2112 	spin_lock_irqsave(&speakup_info.spinlock, flags);
2113 	tty = vc->port.tty;
2114 	if (type >= 0xf0)
2115 		type -= 0xf0;
2116 	if (type == KT_PAD &&
2117 	    (vt_get_leds(fg_console, VC_NUMLOCK))) {
2118 		if (up_flag) {
2119 			spk_keydown = 0;
2120 			goto out;
2121 		}
2122 		value = pad_chars[value];
2123 		spk_lastkey = value;
2124 		spk_keydown++;
2125 		spk_parked &= 0xfe;
2126 		goto no_map;
2127 	}
2128 	if (keycode >= MAX_KEY)
2129 		goto no_map;
2130 	key_info = spk_our_keys[keycode];
2131 	if (!key_info)
2132 		goto no_map;
2133 	/* Check valid read all mode keys */
2134 	if ((cursor_track == read_all_mode) && (!up_flag)) {
2135 		switch (value) {
2136 		case KVAL(K_DOWN):
2137 		case KVAL(K_UP):
2138 		case KVAL(K_LEFT):
2139 		case KVAL(K_RIGHT):
2140 		case KVAL(K_PGUP):
2141 		case KVAL(K_PGDN):
2142 			break;
2143 		default:
2144 			stop_read_all(vc);
2145 			break;
2146 		}
2147 	}
2148 	shift_info = (shift_state & 0x0f) + key_speakup;
2149 	offset = spk_shift_table[shift_info];
2150 	if (offset) {
2151 		new_key = key_info[offset];
2152 		if (new_key) {
2153 			ret = 1;
2154 			if (new_key == SPK_KEY) {
2155 				if (!spk_key_locked)
2156 					key_speakup = (up_flag) ? 0 : 16;
2157 				if (up_flag || spk_killed)
2158 					goto out;
2159 				spk_shut_up &= 0xfe;
2160 				spk_do_flush();
2161 				goto out;
2162 			}
2163 			if (up_flag)
2164 				goto out;
2165 			if (last_keycode == keycode &&
2166 			    time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2167 				spk_close_press = 1;
2168 				offset = spk_shift_table[shift_info + 32];
2169 				/* double press? */
2170 				if (offset && key_info[offset])
2171 					new_key = key_info[offset];
2172 			}
2173 			last_keycode = keycode;
2174 			last_spk_jiffy = jiffies;
2175 			type = KT_SPKUP;
2176 			value = new_key;
2177 		}
2178 	}
2179 no_map:
2180 	if (type == KT_SPKUP && !spk_special_handler) {
2181 		do_spkup(vc, new_key);
2182 		spk_close_press = 0;
2183 		ret = 1;
2184 		goto out;
2185 	}
2186 	if (up_flag || spk_killed || type == KT_SHIFT)
2187 		goto out;
2188 	spk_shut_up &= 0xfe;
2189 	kh = (value == KVAL(K_DOWN)) ||
2190 	    (value == KVAL(K_UP)) ||
2191 	    (value == KVAL(K_LEFT)) ||
2192 	    (value == KVAL(K_RIGHT));
2193 	if ((cursor_track != read_all_mode) || !kh)
2194 		if (!spk_no_intr)
2195 			spk_do_flush();
2196 	if (spk_special_handler) {
2197 		if (type == KT_SPEC && value == 1) {
2198 			value = '\n';
2199 			type = KT_LATIN;
2200 		} else if (type == KT_LETTER) {
2201 			type = KT_LATIN;
2202 		} else if (value == 0x7f) {
2203 			value = 8;	/* make del = backspace */
2204 		}
2205 		ret = (*spk_special_handler) (vc, type, value, keycode);
2206 		spk_close_press = 0;
2207 		if (ret < 0)
2208 			bleep(9);
2209 		goto out;
2210 	}
2211 	last_keycode = 0;
2212 out:
2213 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2214 	return ret;
2215 }
2216 
2217 static int keyboard_notifier_call(struct notifier_block *nb,
2218 				  unsigned long code, void *_param)
2219 {
2220 	struct keyboard_notifier_param *param = _param;
2221 	struct vc_data *vc = param->vc;
2222 	int up = !param->down;
2223 	int ret = NOTIFY_OK;
2224 	static int keycode;	/* to hold the current keycode */
2225 
2226 	in_keyboard_notifier = 1;
2227 
2228 	if (vc->vc_mode == KD_GRAPHICS)
2229 		goto out;
2230 
2231 	/*
2232 	 * First, determine whether we are handling a fake keypress on
2233 	 * the current processor.  If we are, then return NOTIFY_OK,
2234 	 * to pass the keystroke up the chain.  This prevents us from
2235 	 * trying to take the Speakup lock while it is held by the
2236 	 * processor on which the simulated keystroke was generated.
2237 	 * Also, the simulated keystrokes should be ignored by Speakup.
2238 	 */
2239 
2240 	if (speakup_fake_key_pressed())
2241 		goto out;
2242 
2243 	switch (code) {
2244 	case KBD_KEYCODE:
2245 		/* speakup requires keycode and keysym currently */
2246 		keycode = param->value;
2247 		break;
2248 	case KBD_UNBOUND_KEYCODE:
2249 		/* not used yet */
2250 		break;
2251 	case KBD_UNICODE:
2252 		/* not used yet */
2253 		break;
2254 	case KBD_KEYSYM:
2255 		if (speakup_key(vc, param->shift, keycode, param->value, up))
2256 			ret = NOTIFY_STOP;
2257 		else if (KTYP(param->value) == KT_CUR)
2258 			ret = pre_handle_cursor(vc, KVAL(param->value), up);
2259 		break;
2260 	case KBD_POST_KEYSYM:{
2261 			unsigned char type = KTYP(param->value) - 0xf0;
2262 			unsigned char val = KVAL(param->value);
2263 
2264 			switch (type) {
2265 			case KT_SHIFT:
2266 				do_handle_shift(vc, val, up);
2267 				break;
2268 			case KT_LATIN:
2269 			case KT_LETTER:
2270 				do_handle_latin(vc, val, up);
2271 				break;
2272 			case KT_CUR:
2273 				do_handle_cursor(vc, val, up);
2274 				break;
2275 			case KT_SPEC:
2276 				do_handle_spec(vc, val, up);
2277 				break;
2278 			}
2279 			break;
2280 		}
2281 	}
2282 out:
2283 	in_keyboard_notifier = 0;
2284 	return ret;
2285 }
2286 
2287 static int vt_notifier_call(struct notifier_block *nb,
2288 			    unsigned long code, void *_param)
2289 {
2290 	struct vt_notifier_param *param = _param;
2291 	struct vc_data *vc = param->vc;
2292 
2293 	switch (code) {
2294 	case VT_ALLOCATE:
2295 		if (vc->vc_mode == KD_TEXT)
2296 			speakup_allocate(vc, GFP_ATOMIC);
2297 		break;
2298 	case VT_DEALLOCATE:
2299 		speakup_deallocate(vc);
2300 		break;
2301 	case VT_WRITE:
2302 		if (param->c == '\b') {
2303 			speakup_bs(vc);
2304 		} else {
2305 			u16 d = param->c;
2306 
2307 			speakup_con_write(vc, &d, 1);
2308 		}
2309 		break;
2310 	case VT_UPDATE:
2311 		speakup_con_update(vc);
2312 		break;
2313 	}
2314 	return NOTIFY_OK;
2315 }
2316 
2317 /* called by: module_exit() */
2318 static void __exit speakup_exit(void)
2319 {
2320 	int i;
2321 
2322 	unregister_keyboard_notifier(&keyboard_notifier_block);
2323 	unregister_vt_notifier(&vt_notifier_block);
2324 	speakup_unregister_devsynth();
2325 	speakup_cancel_selection();
2326 	speakup_cancel_paste();
2327 	del_timer_sync(&cursor_timer);
2328 	kthread_stop(speakup_task);
2329 	speakup_task = NULL;
2330 	mutex_lock(&spk_mutex);
2331 	synth_release();
2332 	mutex_unlock(&spk_mutex);
2333 	spk_ttyio_unregister_ldisc();
2334 
2335 	speakup_kobj_exit();
2336 
2337 	for (i = 0; i < MAX_NR_CONSOLES; i++)
2338 		kfree(speakup_console[i]);
2339 
2340 	speakup_remove_virtual_keyboard();
2341 
2342 	for (i = 0; i < MAXVARS; i++)
2343 		speakup_unregister_var(i);
2344 
2345 	for (i = 0; i < 256; i++) {
2346 		if (spk_characters[i] != spk_default_chars[i])
2347 			kfree(spk_characters[i]);
2348 	}
2349 
2350 	spk_free_user_msgs();
2351 }
2352 
2353 /* call by: module_init() */
2354 static int __init speakup_init(void)
2355 {
2356 	int i;
2357 	long err = 0;
2358 	struct vc_data *vc = vc_cons[fg_console].d;
2359 	struct var_t *var;
2360 
2361 	/* These first few initializations cannot fail. */
2362 	spk_initialize_msgs();	/* Initialize arrays for i18n. */
2363 	spk_reset_default_chars();
2364 	spk_reset_default_chartab();
2365 	spk_strlwr(synth_name);
2366 	spk_vars[0].u.n.high = vc->vc_cols;
2367 	for (var = spk_vars; var->var_id != MAXVARS; var++)
2368 		speakup_register_var(var);
2369 	for (var = synth_time_vars;
2370 	     (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2371 		speakup_register_var(var);
2372 	for (i = 1; spk_punc_info[i].mask != 0; i++)
2373 		spk_set_mask_bits(NULL, i, 2);
2374 
2375 	spk_set_key_info(spk_key_defaults, spk_key_buf);
2376 
2377 	/* From here on out, initializations can fail. */
2378 	err = speakup_add_virtual_keyboard();
2379 	if (err)
2380 		goto error_virtkeyboard;
2381 
2382 	for (i = 0; i < MAX_NR_CONSOLES; i++)
2383 		if (vc_cons[i].d) {
2384 			err = speakup_allocate(vc_cons[i].d, GFP_KERNEL);
2385 			if (err)
2386 				goto error_kobjects;
2387 		}
2388 
2389 	if (spk_quiet_boot)
2390 		spk_shut_up |= 0x01;
2391 
2392 	err = speakup_kobj_init();
2393 	if (err)
2394 		goto error_kobjects;
2395 
2396 	spk_ttyio_register_ldisc();
2397 	synth_init(synth_name);
2398 	speakup_register_devsynth();
2399 	/*
2400 	 * register_devsynth might fail, but this error is not fatal.
2401 	 * /dev/synth is an extra feature; the rest of Speakup
2402 	 * will work fine without it.
2403 	 */
2404 
2405 	err = register_keyboard_notifier(&keyboard_notifier_block);
2406 	if (err)
2407 		goto error_kbdnotifier;
2408 	err = register_vt_notifier(&vt_notifier_block);
2409 	if (err)
2410 		goto error_vtnotifier;
2411 
2412 	speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2413 
2414 	if (IS_ERR(speakup_task)) {
2415 		err = PTR_ERR(speakup_task);
2416 		goto error_task;
2417 	}
2418 
2419 	set_user_nice(speakup_task, 10);
2420 	wake_up_process(speakup_task);
2421 
2422 	pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2423 	pr_info("synth name on entry is: %s\n", synth_name);
2424 	goto out;
2425 
2426 error_task:
2427 	unregister_vt_notifier(&vt_notifier_block);
2428 
2429 error_vtnotifier:
2430 	unregister_keyboard_notifier(&keyboard_notifier_block);
2431 	del_timer(&cursor_timer);
2432 
2433 error_kbdnotifier:
2434 	speakup_unregister_devsynth();
2435 	mutex_lock(&spk_mutex);
2436 	synth_release();
2437 	mutex_unlock(&spk_mutex);
2438 	speakup_kobj_exit();
2439 
2440 error_kobjects:
2441 	for (i = 0; i < MAX_NR_CONSOLES; i++)
2442 		kfree(speakup_console[i]);
2443 
2444 	speakup_remove_virtual_keyboard();
2445 
2446 error_virtkeyboard:
2447 	for (i = 0; i < MAXVARS; i++)
2448 		speakup_unregister_var(i);
2449 
2450 	for (i = 0; i < 256; i++) {
2451 		if (spk_characters[i] != spk_default_chars[i])
2452 			kfree(spk_characters[i]);
2453 	}
2454 
2455 	spk_free_user_msgs();
2456 
2457 out:
2458 	return err;
2459 }
2460 
2461 module_init(speakup_init);
2462 module_exit(speakup_exit);
2463