main.c 58 KB

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