liblouis-rb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +520 -0
  3. data/README.md +100 -0
  4. data/Rakefile +80 -0
  5. data/ext/liblouis/braille_character.c +200 -0
  6. data/ext/liblouis/braille_table.c +198 -0
  7. data/ext/liblouis/braille_text.c +223 -0
  8. data/ext/liblouis/extconf.rb +73 -0
  9. data/ext/liblouis/liblouis.c +168 -0
  10. data/ext/liblouis/liblouis_ext.h +49 -0
  11. data/ext/liblouis/table_source.c +161 -0
  12. data/ext/liblouis/translation.c +443 -0
  13. data/liblouis-rb.gemspec +49 -0
  14. data/spec/liblouis_spec.rb +62 -0
  15. data/test/integration/packaging_test.rb +82 -0
  16. data/test/table_source_cases.rb +9 -0
  17. data/test/test_braille_character.rb +62 -0
  18. data/test/test_braille_table.rb +379 -0
  19. data/test/test_braille_text.rb +30 -0
  20. data/test/test_helper.rb +7 -0
  21. data/test/translation_cases.rb +33 -0
  22. data/vendor/liblouis/COPYING +674 -0
  23. data/vendor/liblouis/COPYING.LESSER +502 -0
  24. data/vendor/liblouis/configure.ac +290 -0
  25. data/vendor/liblouis/liblouis/commonTranslationFunctions.c +95 -0
  26. data/vendor/liblouis/liblouis/compileTranslationTable.c +5515 -0
  27. data/vendor/liblouis/liblouis/internal.h +781 -0
  28. data/vendor/liblouis/liblouis/liblouis.h.in +514 -0
  29. data/vendor/liblouis/liblouis/logging.c +233 -0
  30. data/vendor/liblouis/liblouis/lou_backTranslateString.c +1855 -0
  31. data/vendor/liblouis/liblouis/lou_translateString.c +4177 -0
  32. data/vendor/liblouis/liblouis/maketable.c +463 -0
  33. data/vendor/liblouis/liblouis/metadata.c +1258 -0
  34. data/vendor/liblouis/liblouis/pattern.c +1632 -0
  35. data/vendor/liblouis/liblouis/utils.c +448 -0
  36. data/vendor/liblouis/tables/Es-Es-G0.utb +248 -0
  37. data/vendor/liblouis/tables/IPA-unicode-range.uti +200 -0
  38. data/vendor/liblouis/tables/IPA.utb +164 -0
  39. data/vendor/liblouis/tables/Lv-Lv-g1.utb +509 -0
  40. data/vendor/liblouis/tables/Makefile.am +503 -0
  41. data/vendor/liblouis/tables/Pl-Pl-g1.utb +312 -0
  42. data/vendor/liblouis/tables/README +6 -0
  43. data/vendor/liblouis/tables/afr-za-g1.ctb +63 -0
  44. data/vendor/liblouis/tables/afr-za-g2.ctb +1050 -0
  45. data/vendor/liblouis/tables/akk-borger.utb +997 -0
  46. data/vendor/liblouis/tables/akk.utb +1002 -0
  47. data/vendor/liblouis/tables/ancient-languages-borger.utb +114 -0
  48. data/vendor/liblouis/tables/ancient-languages-us.utb +114 -0
  49. data/vendor/liblouis/tables/ar-ar-comp8.utb +293 -0
  50. data/vendor/liblouis/tables/ar-ar-g1-core.uti +291 -0
  51. data/vendor/liblouis/tables/ar-ar-g1.utb +26 -0
  52. data/vendor/liblouis/tables/ar-ar-g2.ctb +447 -0
  53. data/vendor/liblouis/tables/ar-ar-math.uti +501 -0
  54. data/vendor/liblouis/tables/ar.tbl +17 -0
  55. data/vendor/liblouis/tables/as-in-g1.utb +27 -0
  56. data/vendor/liblouis/tables/as.tbl +18 -0
  57. data/vendor/liblouis/tables/aw-in-g1.utb +27 -0
  58. data/vendor/liblouis/tables/awa.tbl +18 -0
  59. data/vendor/liblouis/tables/ba.utb +64 -0
  60. data/vendor/liblouis/tables/be-in-g1.utb +27 -0
  61. data/vendor/liblouis/tables/bel-comp.utb +42 -0
  62. data/vendor/liblouis/tables/bel-detailed.utb +32 -0
  63. data/vendor/liblouis/tables/bel.utb +61 -0
  64. data/vendor/liblouis/tables/bengali.cti +238 -0
  65. data/vendor/liblouis/tables/bg.ctb +215 -0
  66. data/vendor/liblouis/tables/bg.dis +84 -0
  67. data/vendor/liblouis/tables/bg.tbl +21 -0
  68. data/vendor/liblouis/tables/bg.utb +454 -0
  69. data/vendor/liblouis/tables/bh.ctb +24 -0
  70. data/vendor/liblouis/tables/bh.tbl +17 -0
  71. data/vendor/liblouis/tables/bn.tbl +18 -0
  72. data/vendor/liblouis/tables/bo.ctb +184 -0
  73. data/vendor/liblouis/tables/bo.tbl +21 -0
  74. data/vendor/liblouis/tables/boxes.ctb +162 -0
  75. data/vendor/liblouis/tables/br-in-g1.utb +27 -0
  76. data/vendor/liblouis/tables/bra.tbl +18 -0
  77. data/vendor/liblouis/tables/braille-patterns.cti +287 -0
  78. data/vendor/liblouis/tables/ca-chardefs.cti +225 -0
  79. data/vendor/liblouis/tables/ca-g1.ctb +46 -0
  80. data/vendor/liblouis/tables/ca.tbl +18 -0
  81. data/vendor/liblouis/tables/chr-us-g1.ctb +180 -0
  82. data/vendor/liblouis/tables/ckb-chardefs.cti +219 -0
  83. data/vendor/liblouis/tables/ckb-g1.ctb +31 -0
  84. data/vendor/liblouis/tables/ckb-translation.cti +131 -0
  85. data/vendor/liblouis/tables/ckb.tbl +18 -0
  86. data/vendor/liblouis/tables/compress.cti +44 -0
  87. data/vendor/liblouis/tables/controlchars.cti +27 -0
  88. data/vendor/liblouis/tables/cop-eg-comp8.utb +255 -0
  89. data/vendor/liblouis/tables/cop.utb +231 -0
  90. data/vendor/liblouis/tables/corrections.cti +47 -0
  91. data/vendor/liblouis/tables/countries.cti +263 -0
  92. data/vendor/liblouis/tables/critical-apparatus.uti +54 -0
  93. data/vendor/liblouis/tables/cs-chardefs.cti +385 -0
  94. data/vendor/liblouis/tables/cs-comp8.utb +405 -0
  95. data/vendor/liblouis/tables/cs-g1.ctb +37 -0
  96. data/vendor/liblouis/tables/cs-translation.cti +63 -0
  97. data/vendor/liblouis/tables/cs.tbl +20 -0
  98. data/vendor/liblouis/tables/cuneiform-transliterated-compact.utb +432 -0
  99. data/vendor/liblouis/tables/cuneiform-transliterated.utb +160 -0
  100. data/vendor/liblouis/tables/cy-cy-g1.utb +487 -0
  101. data/vendor/liblouis/tables/cy-cy-g2.ctb +199 -0
  102. data/vendor/liblouis/tables/cy.tbl +19 -0
  103. data/vendor/liblouis/tables/da-dk-6miscChars.cti +385 -0
  104. data/vendor/liblouis/tables/da-dk-6miscChars_1993.cti +412 -0
  105. data/vendor/liblouis/tables/da-dk-8miscChars.cti +90 -0
  106. data/vendor/liblouis/tables/da-dk-8miscChars_1993.cti +102 -0
  107. data/vendor/liblouis/tables/da-dk-g08.ctb +290 -0
  108. data/vendor/liblouis/tables/da-dk-g08_1993.ctb +331 -0
  109. data/vendor/liblouis/tables/da-dk-g16-lit_1993.ctb +294 -0
  110. data/vendor/liblouis/tables/da-dk-g16.ctb +289 -0
  111. data/vendor/liblouis/tables/da-dk-g16_1993.ctb +305 -0
  112. data/vendor/liblouis/tables/da-dk-g18.ctb +545 -0
  113. data/vendor/liblouis/tables/da-dk-g18_1993.ctb +563 -0
  114. data/vendor/liblouis/tables/da-dk-g2.dic +7439 -0
  115. data/vendor/liblouis/tables/da-dk-g26-lit_1993.ctb +898 -0
  116. data/vendor/liblouis/tables/da-dk-g26.ctb +1345 -0
  117. data/vendor/liblouis/tables/da-dk-g26_1993.ctb +1127 -0
  118. data/vendor/liblouis/tables/da-dk-g26l-lit_1993.ctb +588 -0
  119. data/vendor/liblouis/tables/da-dk-g26l_1993.ctb +604 -0
  120. data/vendor/liblouis/tables/da-dk-g28.ctb +2426 -0
  121. data/vendor/liblouis/tables/da-dk-g28_1993.ctb +2063 -0
  122. data/vendor/liblouis/tables/da-dk-g28l_1993.ctb +1594 -0
  123. data/vendor/liblouis/tables/da-dk-octobraille.dis +316 -0
  124. data/vendor/liblouis/tables/da-dk-octobraille_1993.dis +313 -0
  125. data/vendor/liblouis/tables/de-accents-detailed.cti +214 -0
  126. data/vendor/liblouis/tables/de-accents.cti +214 -0
  127. data/vendor/liblouis/tables/de-chardefs6.cti +289 -0
  128. data/vendor/liblouis/tables/de-chardefs8.cti +278 -0
  129. data/vendor/liblouis/tables/de-chess.ctb +37 -0
  130. data/vendor/liblouis/tables/de-comp6.utb +226 -0
  131. data/vendor/liblouis/tables/de-de-comp8.ctb +492 -0
  132. data/vendor/liblouis/tables/de-de.dis +331 -0
  133. data/vendor/liblouis/tables/de-eurobrl6.dis +101 -0
  134. data/vendor/liblouis/tables/de-eurobrl6u.dis +96 -0
  135. data/vendor/liblouis/tables/de-g0-core.uti +732 -0
  136. data/vendor/liblouis/tables/de-g0-detailed.utb +84 -0
  137. data/vendor/liblouis/tables/de-g0.utb +57 -0
  138. data/vendor/liblouis/tables/de-g1-core-patterns.dic +4863 -0
  139. data/vendor/liblouis/tables/de-g1-core.cti +67 -0
  140. data/vendor/liblouis/tables/de-g1-detailed.ctb +79 -0
  141. data/vendor/liblouis/tables/de-g1.ctb +54 -0
  142. data/vendor/liblouis/tables/de-g2-core-patterns.dic +26711 -0
  143. data/vendor/liblouis/tables/de-g2-core.cti +607 -0
  144. data/vendor/liblouis/tables/de-g2-detailed.ctb +60 -0
  145. data/vendor/liblouis/tables/de-g2.ctb +57 -0
  146. data/vendor/liblouis/tables/devanagari.cti +325 -0
  147. data/vendor/liblouis/tables/digits6Dots.uti +30 -0
  148. data/vendor/liblouis/tables/digits6DotsPlusDot6.uti +30 -0
  149. data/vendor/liblouis/tables/digits8Dots.uti +30 -0
  150. data/vendor/liblouis/tables/dra.ctb +23 -0
  151. data/vendor/liblouis/tables/dra.tbl +21 -0
  152. data/vendor/liblouis/tables/el.ctb +775 -0
  153. data/vendor/liblouis/tables/en-GB-g2.ctb +829 -0
  154. data/vendor/liblouis/tables/en-chardefs.cti +193 -0
  155. data/vendor/liblouis/tables/en-chess.ctb +37 -0
  156. data/vendor/liblouis/tables/en-g3-patterns.dic +11194 -0
  157. data/vendor/liblouis/tables/en-g3.ctb +2261 -0
  158. data/vendor/liblouis/tables/en-gb-comp8.ctb +282 -0
  159. data/vendor/liblouis/tables/en-gb-g1.utb +527 -0
  160. data/vendor/liblouis/tables/en-in-g1.ctb +162 -0
  161. data/vendor/liblouis/tables/en-nabcc.utb +166 -0
  162. data/vendor/liblouis/tables/en-nz-g1.utb +65 -0
  163. data/vendor/liblouis/tables/en-nz-g2.ctb +46 -0
  164. data/vendor/liblouis/tables/en-ueb-chardefs.uti +938 -0
  165. data/vendor/liblouis/tables/en-ueb-g1.ctb +167 -0
  166. data/vendor/liblouis/tables/en-ueb-g2.ctb +3925 -0
  167. data/vendor/liblouis/tables/en-ueb-math.ctb +71 -0
  168. data/vendor/liblouis/tables/en-us-brf.dis +102 -0
  169. data/vendor/liblouis/tables/en-us-comp6.ctb +149 -0
  170. data/vendor/liblouis/tables/en-us-comp8-ext.utb +626 -0
  171. data/vendor/liblouis/tables/en-us-comp8.ctb +62 -0
  172. data/vendor/liblouis/tables/en-us-compbrl.uti +69 -0
  173. data/vendor/liblouis/tables/en-us-emphasis.uti +45 -0
  174. data/vendor/liblouis/tables/en-us-g1.ctb +199 -0
  175. data/vendor/liblouis/tables/en-us-g2.ctb +1081 -0
  176. data/vendor/liblouis/tables/en-us-interline.ctb +1126 -0
  177. data/vendor/liblouis/tables/en-us-mathtext.ctb +880 -0
  178. data/vendor/liblouis/tables/en_CA.ctb +195 -0
  179. data/vendor/liblouis/tables/en_CA.tbl +21 -0
  180. data/vendor/liblouis/tables/en_GB.tbl +26 -0
  181. data/vendor/liblouis/tables/en_US-comp8-ext.tbl +15 -0
  182. data/vendor/liblouis/tables/en_US.tbl +26 -0
  183. data/vendor/liblouis/tables/eo-g1-x-system.ctb +85 -0
  184. data/vendor/liblouis/tables/eo-g1.ctb +165 -0
  185. data/vendor/liblouis/tables/eo.tbl +14 -0
  186. data/vendor/liblouis/tables/es-chardefs.cti +206 -0
  187. data/vendor/liblouis/tables/es-g1.ctb +36 -0
  188. data/vendor/liblouis/tables/es-g2.ctb +955 -0
  189. data/vendor/liblouis/tables/es-new.dis +284 -0
  190. data/vendor/liblouis/tables/es-no.utb +79 -0
  191. data/vendor/liblouis/tables/es-old.dis +284 -0
  192. data/vendor/liblouis/tables/es.tbl +19 -0
  193. data/vendor/liblouis/tables/et-6dot.utb +269 -0
  194. data/vendor/liblouis/tables/et-g0.utb +139 -0
  195. data/vendor/liblouis/tables/ethio-g1.ctb +335 -0
  196. data/vendor/liblouis/tables/eurodefs.cti +107 -0
  197. data/vendor/liblouis/tables/fa-ir-comp8.ctb +250 -0
  198. data/vendor/liblouis/tables/fa-ir-g1.utb +311 -0
  199. data/vendor/liblouis/tables/fi-fi-8dot.ctb +278 -0
  200. data/vendor/liblouis/tables/fi.utb +354 -0
  201. data/vendor/liblouis/tables/fil-g2.ctb +491 -0
  202. data/vendor/liblouis/tables/fr-bfu-comp6-puncs-math.uti +351 -0
  203. data/vendor/liblouis/tables/fr-bfu-comp6.utb +238 -0
  204. data/vendor/liblouis/tables/fr-bfu-comp68.cti +251 -0
  205. data/vendor/liblouis/tables/fr-bfu-comp8.utb +323 -0
  206. data/vendor/liblouis/tables/fr-bfu-g2.ctb +4644 -0
  207. data/vendor/liblouis/tables/ga-g1.utb +95 -0
  208. data/vendor/liblouis/tables/ga-g2.ctb +231 -0
  209. data/vendor/liblouis/tables/gd.ctb +123 -0
  210. data/vendor/liblouis/tables/gd.tbl +21 -0
  211. data/vendor/liblouis/tables/gez.tbl +21 -0
  212. data/vendor/liblouis/tables/gon.ctb +25 -0
  213. data/vendor/liblouis/tables/gon.tbl +17 -0
  214. data/vendor/liblouis/tables/gr-pl-comp8.uti +256 -0
  215. data/vendor/liblouis/tables/grc-international-common.uti +104 -0
  216. data/vendor/liblouis/tables/grc-international-composed.uti +268 -0
  217. data/vendor/liblouis/tables/grc-international-decomposed.uti +268 -0
  218. data/vendor/liblouis/tables/grc-international-en-composed.utb +54 -0
  219. data/vendor/liblouis/tables/grc-international-en.utb +206 -0
  220. data/vendor/liblouis/tables/grc-international-es.utb +228 -0
  221. data/vendor/liblouis/tables/gu-in-g1.utb +27 -0
  222. data/vendor/liblouis/tables/gu.tbl +18 -0
  223. data/vendor/liblouis/tables/gujarati.cti +221 -0
  224. data/vendor/liblouis/tables/gurumuki.cti +393 -0
  225. data/vendor/liblouis/tables/haw-us-g1.ctb +54 -0
  226. data/vendor/liblouis/tables/hbo-cantillated-rules.uti +71 -0
  227. data/vendor/liblouis/tables/hbo-cantillated.utb +109 -0
  228. data/vendor/liblouis/tables/hbo-common-rules.uti +152 -0
  229. data/vendor/liblouis/tables/hbo-ihbc-rules.uti +58 -0
  230. data/vendor/liblouis/tables/hbo-slim-rules.uti +68 -0
  231. data/vendor/liblouis/tables/hbo-slim.utb +100 -0
  232. data/vendor/liblouis/tables/hbo.utb +107 -0
  233. data/vendor/liblouis/tables/he-IL-comp8.utb +464 -0
  234. data/vendor/liblouis/tables/he-IL.utb +406 -0
  235. data/vendor/liblouis/tables/he-common-consonants.uti +102 -0
  236. data/vendor/liblouis/tables/he-common-vowels-ihbc.uti +161 -0
  237. data/vendor/liblouis/tables/hi-in-g1.utb +27 -0
  238. data/vendor/liblouis/tables/hi.tbl +18 -0
  239. data/vendor/liblouis/tables/hr-chardefs.cti +278 -0
  240. data/vendor/liblouis/tables/hr-comp8.tbl +21 -0
  241. data/vendor/liblouis/tables/hr-comp8.utb +239 -0
  242. data/vendor/liblouis/tables/hr-digits.uti +40 -0
  243. data/vendor/liblouis/tables/hr-g1.ctb +36 -0
  244. data/vendor/liblouis/tables/hr-g1.tbl +9 -0
  245. data/vendor/liblouis/tables/hr-translation.cti +364 -0
  246. data/vendor/liblouis/tables/ht-frenchcompatibility.uti +61 -0
  247. data/vendor/liblouis/tables/ht-g1.utb +114 -0
  248. data/vendor/liblouis/tables/hu-backtranslate-correction.dis +38 -0
  249. data/vendor/liblouis/tables/hu-backtranslate-word-corrections.cti +4293 -0
  250. data/vendor/liblouis/tables/hu-chardefs.cti +298 -0
  251. data/vendor/liblouis/tables/hu-exceptionwords.cti +3204 -0
  252. data/vendor/liblouis/tables/hu-hu-comp8.ctb +183 -0
  253. data/vendor/liblouis/tables/hu-hu-g1.ctb +129 -0
  254. data/vendor/liblouis/tables/hu-hu-g1_braille_input.cti +486 -0
  255. data/vendor/liblouis/tables/hu-hu-g2.ctb +270 -0
  256. data/vendor/liblouis/tables/hu-hu-g2_exceptions.cti +1164 -0
  257. data/vendor/liblouis/tables/hy.ctb +121 -0
  258. data/vendor/liblouis/tables/hy.tbl +21 -0
  259. data/vendor/liblouis/tables/hyph_cs_CZ.dic +3637 -0
  260. data/vendor/liblouis/tables/hyph_da_DK.dic +8896 -0
  261. data/vendor/liblouis/tables/hyph_de_DE.dic +5799 -0
  262. data/vendor/liblouis/tables/hyph_en_US.dic +5537 -0
  263. data/vendor/liblouis/tables/hyph_eo.dic +1024 -0
  264. data/vendor/liblouis/tables/hyph_es_ES.dic +877 -0
  265. data/vendor/liblouis/tables/hyph_fr_FR.dic +1067 -0
  266. data/vendor/liblouis/tables/hyph_hu_HU.dic +98519 -0
  267. data/vendor/liblouis/tables/hyph_it_IT.dic +410 -0
  268. data/vendor/liblouis/tables/hyph_nb_NO.dic +27142 -0
  269. data/vendor/liblouis/tables/hyph_nl_NL.dic +12725 -0
  270. data/vendor/liblouis/tables/hyph_nn_NO.dic +27142 -0
  271. data/vendor/liblouis/tables/hyph_pl_PL.dic +4074 -0
  272. data/vendor/liblouis/tables/hyph_pt_PT.dic +308 -0
  273. data/vendor/liblouis/tables/hyph_ru.dic +6480 -0
  274. data/vendor/liblouis/tables/hyph_sv_SE.dic +4697 -0
  275. data/vendor/liblouis/tables/is-chardefs6.cti +170 -0
  276. data/vendor/liblouis/tables/is-chardefs8.cti +293 -0
  277. data/vendor/liblouis/tables/is.ctb +157 -0
  278. data/vendor/liblouis/tables/is.tbl +18 -0
  279. data/vendor/liblouis/tables/it-it-comp6.utb +404 -0
  280. data/vendor/liblouis/tables/it-it-comp8.utb +663 -0
  281. data/vendor/liblouis/tables/iu-ca-g1.ctb +236 -0
  282. data/vendor/liblouis/tables/ja-kantenji-ucs2.utb +11448 -0
  283. data/vendor/liblouis/tables/ja-kantenji.utb +53 -0
  284. data/vendor/liblouis/tables/ja-rokutenkanji.utb +8710 -0
  285. data/vendor/liblouis/tables/ka-in-g1.utb +27 -0
  286. data/vendor/liblouis/tables/ka.utb +128 -0
  287. data/vendor/liblouis/tables/kannada.cti +282 -0
  288. data/vendor/liblouis/tables/kh-in-g1.utb +26 -0
  289. data/vendor/liblouis/tables/kha.tbl +18 -0
  290. data/vendor/liblouis/tables/kk.utb +77 -0
  291. data/vendor/liblouis/tables/km-g1.utb +412 -0
  292. data/vendor/liblouis/tables/kmr.tbl +108 -0
  293. data/vendor/liblouis/tables/kn.tbl +18 -0
  294. data/vendor/liblouis/tables/ko-2006-g1.ctb +49 -0
  295. data/vendor/liblouis/tables/ko-2006-g2.ctb +53 -0
  296. data/vendor/liblouis/tables/ko-2006.cti +190 -0
  297. data/vendor/liblouis/tables/ko-chars.cti +15140 -0
  298. data/vendor/liblouis/tables/ko-g1-rules.cti +634 -0
  299. data/vendor/liblouis/tables/ko-g1.ctb +48 -0
  300. data/vendor/liblouis/tables/ko-g2-rules.cti +9263 -0
  301. data/vendor/liblouis/tables/ko-g2.ctb +52 -0
  302. data/vendor/liblouis/tables/ko.cti +223 -0
  303. data/vendor/liblouis/tables/kok.ctb +24 -0
  304. data/vendor/liblouis/tables/kok.tbl +17 -0
  305. data/vendor/liblouis/tables/kru.ctb +24 -0
  306. data/vendor/liblouis/tables/kru.tbl +17 -0
  307. data/vendor/liblouis/tables/ks-in-g1.utb +27 -0
  308. data/vendor/liblouis/tables/latinLetterDef6Dots.uti +78 -0
  309. data/vendor/liblouis/tables/latinLetterDef8Dots.uti +75 -0
  310. data/vendor/liblouis/tables/latinLowercase.uti +389 -0
  311. data/vendor/liblouis/tables/latinUppercaseComp6.uti +78 -0
  312. data/vendor/liblouis/tables/lg-ug-g1.utb +60 -0
  313. data/vendor/liblouis/tables/litdigits6Dots.uti +30 -0
  314. data/vendor/liblouis/tables/litdigits6DotsPlusDot6.uti +30 -0
  315. data/vendor/liblouis/tables/lo-g1.utb +3127 -0
  316. data/vendor/liblouis/tables/loweredDigits6Dots.uti +30 -0
  317. data/vendor/liblouis/tables/loweredDigits8Dots.uti +30 -0
  318. data/vendor/liblouis/tables/lt-6dot.utb +308 -0
  319. data/vendor/liblouis/tables/lt-8dot.utb +281 -0
  320. data/vendor/liblouis/tables/lt.ctb +313 -0
  321. data/vendor/liblouis/tables/lv.tbl +22 -0
  322. data/vendor/liblouis/tables/maketablelist.sh +52 -0
  323. data/vendor/liblouis/tables/malayalam.cti +674 -0
  324. data/vendor/liblouis/tables/mao-nz-g1.ctb +65 -0
  325. data/vendor/liblouis/tables/marburg_single_cell_defs.cti +66 -0
  326. data/vendor/liblouis/tables/marburg_unicode_defs.cti +297 -0
  327. data/vendor/liblouis/tables/mk-g1.utb +240 -0
  328. data/vendor/liblouis/tables/ml-in-g1.utb +27 -0
  329. data/vendor/liblouis/tables/ml.tbl +21 -0
  330. data/vendor/liblouis/tables/mn-MN-common.cti +110 -0
  331. data/vendor/liblouis/tables/mn-MN-g1.utb +52 -0
  332. data/vendor/liblouis/tables/mn-MN-g2.ctb +50 -0
  333. data/vendor/liblouis/tables/mn-in-g1.utb +27 -0
  334. data/vendor/liblouis/tables/mni.tbl +18 -0
  335. data/vendor/liblouis/tables/mr-in-g1.utb +27 -0
  336. data/vendor/liblouis/tables/mr.tbl +18 -0
  337. data/vendor/liblouis/tables/ms-my-g2.ctb +4897 -0
  338. data/vendor/liblouis/tables/mt.ctb +114 -0
  339. data/vendor/liblouis/tables/mt.tbl +21 -0
  340. data/vendor/liblouis/tables/mun.ctb +24 -0
  341. data/vendor/liblouis/tables/mun.tbl +17 -0
  342. data/vendor/liblouis/tables/mwr.ctb +24 -0
  343. data/vendor/liblouis/tables/mwr.tbl +17 -0
  344. data/vendor/liblouis/tables/my-g1.utb +771 -0
  345. data/vendor/liblouis/tables/my-g2.ctb +3805 -0
  346. data/vendor/liblouis/tables/ne.ctb +22 -0
  347. data/vendor/liblouis/tables/ne.tbl +18 -0
  348. data/vendor/liblouis/tables/nemethdefs.cti +382 -0
  349. data/vendor/liblouis/tables/nl-BE.dis +532 -0
  350. data/vendor/liblouis/tables/nl-NL-g0.utb.in +646 -0
  351. data/vendor/liblouis/tables/nl-chardefs.uti.in +455 -0
  352. data/vendor/liblouis/tables/nl-comp8.utb +411 -0
  353. data/vendor/liblouis/tables/nl-print.dis +551 -0
  354. data/vendor/liblouis/tables/nl-unicode.dis +540 -0
  355. data/vendor/liblouis/tables/no-no-8dot-fallback-6dot-g0.utb +59 -0
  356. data/vendor/liblouis/tables/no-no-8dot.utb +629 -0
  357. data/vendor/liblouis/tables/no-no-braillo-047-01.dis +247 -0
  358. data/vendor/liblouis/tables/no-no-chardefs6.uti +305 -0
  359. data/vendor/liblouis/tables/no-no-comp8.ctb +323 -0
  360. data/vendor/liblouis/tables/no-no-cyrillic6dot.uti +95 -0
  361. data/vendor/liblouis/tables/no-no-g0.utb +320 -0
  362. data/vendor/liblouis/tables/no-no-g1.ctb +272 -0
  363. data/vendor/liblouis/tables/no-no-g2.ctb +737 -0
  364. data/vendor/liblouis/tables/no-no-g3.ctb +3597 -0
  365. data/vendor/liblouis/tables/no-no-generic.ctb +295 -0
  366. data/vendor/liblouis/tables/no-no-generic.dis +295 -0
  367. data/vendor/liblouis/tables/no-no-latinLetterDef6Dots_diacritics.uti +852 -0
  368. data/vendor/liblouis/tables/no-no.dis +291 -0
  369. data/vendor/liblouis/tables/np-in-g1.utb +27 -0
  370. data/vendor/liblouis/tables/nso-za-g1.utb +38 -0
  371. data/vendor/liblouis/tables/nso-za-g2.ctb +38 -0
  372. data/vendor/liblouis/tables/ny-mw.utb +70 -0
  373. data/vendor/liblouis/tables/or-in-g1.utb +27 -0
  374. data/vendor/liblouis/tables/or.tbl +18 -0
  375. data/vendor/liblouis/tables/oriya.cti +238 -0
  376. data/vendor/liblouis/tables/ovd-6g0.utb +64 -0
  377. data/vendor/liblouis/tables/ovd-8g0.utb +81 -0
  378. data/vendor/liblouis/tables/pa.tbl +18 -0
  379. data/vendor/liblouis/tables/pi.ctb +24 -0
  380. data/vendor/liblouis/tables/pi.tbl +17 -0
  381. data/vendor/liblouis/tables/pl-pl-comp8.ctb +658 -0
  382. data/vendor/liblouis/tables/pl.tbl +12 -0
  383. data/vendor/liblouis/tables/printables.cti +70 -0
  384. data/vendor/liblouis/tables/pt-comp6.utb +299 -0
  385. data/vendor/liblouis/tables/pt-pt-comp8.ctb +395 -0
  386. data/vendor/liblouis/tables/pt-pt-g1.utb +1312 -0
  387. data/vendor/liblouis/tables/pt-pt-g2.ctb +874 -0
  388. data/vendor/liblouis/tables/pt.tbl +20 -0
  389. data/vendor/liblouis/tables/pu-in-g1.utb +42 -0
  390. data/vendor/liblouis/tables/quotation-marks.uti +30 -0
  391. data/vendor/liblouis/tables/ro-g0.utb +85 -0
  392. data/vendor/liblouis/tables/ro.ctb +126 -0
  393. data/vendor/liblouis/tables/ro.tbl +21 -0
  394. data/vendor/liblouis/tables/ru-brf.dis +116 -0
  395. data/vendor/liblouis/tables/ru-comp6.utb +258 -0
  396. data/vendor/liblouis/tables/ru-comp8.utb +740 -0
  397. data/vendor/liblouis/tables/ru-letters.dis +145 -0
  398. data/vendor/liblouis/tables/ru-litbrl-detailed.utb +77 -0
  399. data/vendor/liblouis/tables/ru-litbrl.ctb +857 -0
  400. data/vendor/liblouis/tables/ru-math.uti +395 -0
  401. data/vendor/liblouis/tables/ru-ru-g1.ctb +804 -0
  402. data/vendor/liblouis/tables/ru-unicode.dis +121 -0
  403. data/vendor/liblouis/tables/rw-rw-g1.utb +133 -0
  404. data/vendor/liblouis/tables/sa-in-g1.utb +27 -0
  405. data/vendor/liblouis/tables/sa.tbl +18 -0
  406. data/vendor/liblouis/tables/sah.utb +72 -0
  407. data/vendor/liblouis/tables/sd.tbl +18 -0
  408. data/vendor/liblouis/tables/se-se.ctb +246 -0
  409. data/vendor/liblouis/tables/se-se.dis +334 -0
  410. data/vendor/liblouis/tables/si-in-g1.utb +27 -0
  411. data/vendor/liblouis/tables/sin.cti +213 -0
  412. data/vendor/liblouis/tables/sin.utb +35 -0
  413. data/vendor/liblouis/tables/sk-g1.ctb +1019 -0
  414. data/vendor/liblouis/tables/sk-sk-g1.utb +206 -0
  415. data/vendor/liblouis/tables/sk-sk.utb +112 -0
  416. data/vendor/liblouis/tables/sl-si-comp8.ctb +204 -0
  417. data/vendor/liblouis/tables/sl-si-g1.utb +471 -0
  418. data/vendor/liblouis/tables/sl.tbl +20 -0
  419. data/vendor/liblouis/tables/smi-6g0.utb +64 -0
  420. data/vendor/liblouis/tables/smi-8g0.utb +61 -0
  421. data/vendor/liblouis/tables/sot-za-g1.ctb +72 -0
  422. data/vendor/liblouis/tables/sot-za-g2.ctb +244 -0
  423. data/vendor/liblouis/tables/spaces.uti +62 -0
  424. data/vendor/liblouis/tables/sr-Cyrl.ctb +59 -0
  425. data/vendor/liblouis/tables/sr-common.cti +161 -0
  426. data/vendor/liblouis/tables/sr-cyrletters.cti +92 -0
  427. data/vendor/liblouis/tables/sr-g1.ctb +57 -0
  428. data/vendor/liblouis/tables/sr-latletters.cti +45 -0
  429. data/vendor/liblouis/tables/sv-1989.ctb +241 -0
  430. data/vendor/liblouis/tables/sv-1996.ctb +180 -0
  431. data/vendor/liblouis/tables/sv-6common.uti +1199 -0
  432. data/vendor/liblouis/tables/sv-6g0d.utb +508 -0
  433. data/vendor/liblouis/tables/sv-6g0p.utb +61 -0
  434. data/vendor/liblouis/tables/sv-6g1.uti +106 -0
  435. data/vendor/liblouis/tables/sv-6g1d.ctb +57 -0
  436. data/vendor/liblouis/tables/sv-6g2.uti +254 -0
  437. data/vendor/liblouis/tables/sv-6g2d.ctb +57 -0
  438. data/vendor/liblouis/tables/sv-8g0d.utb +495 -0
  439. data/vendor/liblouis/tables/sv-8g0n.utb +1236 -0
  440. data/vendor/liblouis/tables/sv-8g1.uti +199 -0
  441. data/vendor/liblouis/tables/sv-8g1d.ctb +73 -0
  442. data/vendor/liblouis/tables/sv-8g1n.ctb +73 -0
  443. data/vendor/liblouis/tables/sv-8g2.uti +486 -0
  444. data/vendor/liblouis/tables/sv-8g2d.ctb +73 -0
  445. data/vendor/liblouis/tables/sv-8g2n.ctb +73 -0
  446. data/vendor/liblouis/tables/sv-g0.utb +65 -0
  447. data/vendor/liblouis/tables/sv-g1.ctb +57 -0
  448. data/vendor/liblouis/tables/sv-g2.ctb +57 -0
  449. data/vendor/liblouis/tables/sv-phon.uti +241 -0
  450. data/vendor/liblouis/tables/sw-ke-g1-2.ctb +90 -0
  451. data/vendor/liblouis/tables/sw-ke-g1-3.ctb +109 -0
  452. data/vendor/liblouis/tables/sw-ke-g1-4.ctb +107 -0
  453. data/vendor/liblouis/tables/sw-ke-g1-5.ctb +73 -0
  454. data/vendor/liblouis/tables/sw-ke-g1.utb +278 -0
  455. data/vendor/liblouis/tables/sw-ke-g2.ctb +276 -0
  456. data/vendor/liblouis/tables/syc.utb +195 -0
  457. data/vendor/liblouis/tables/ta-ta-g1.ctb +167 -0
  458. data/vendor/liblouis/tables/ta.ctb +24 -0
  459. data/vendor/liblouis/tables/ta.tbl +21 -0
  460. data/vendor/liblouis/tables/tamil.cti +86 -0
  461. data/vendor/liblouis/tables/te-in-g1.utb +27 -0
  462. data/vendor/liblouis/tables/te.tbl +18 -0
  463. data/vendor/liblouis/tables/telugu.cti +239 -0
  464. data/vendor/liblouis/tables/text_nabcc.dis +426 -0
  465. data/vendor/liblouis/tables/th-comp8-backward.utb +226 -0
  466. data/vendor/liblouis/tables/th-g0.utb +177 -0
  467. data/vendor/liblouis/tables/th-g1.utb +89 -0
  468. data/vendor/liblouis/tables/th-g1.uti +315 -0
  469. data/vendor/liblouis/tables/th-g2.ctb +616 -0
  470. data/vendor/liblouis/tables/tr-g1.ctb +254 -0
  471. data/vendor/liblouis/tables/tr-g2.ctb +863 -0
  472. data/vendor/liblouis/tables/tr-g2.tbl +20 -0
  473. data/vendor/liblouis/tables/tr.ctb +324 -0
  474. data/vendor/liblouis/tables/tr.tbl +21 -0
  475. data/vendor/liblouis/tables/tsn-za-g1.ctb +33 -0
  476. data/vendor/liblouis/tables/tsn-za-g2.ctb +33 -0
  477. data/vendor/liblouis/tables/tt.utb +74 -0
  478. data/vendor/liblouis/tables/uga.utb +86 -0
  479. data/vendor/liblouis/tables/uk-comp.utb +53 -0
  480. data/vendor/liblouis/tables/uk-detailed.utb +32 -0
  481. data/vendor/liblouis/tables/uk.utb +101 -0
  482. data/vendor/liblouis/tables/ukchardefs.cti +106 -0
  483. data/vendor/liblouis/tables/ukmaths_single_cell_defs.cti +65 -0
  484. data/vendor/liblouis/tables/ukmaths_unicode_defs.cti +298 -0
  485. data/vendor/liblouis/tables/uni-text.dis +330 -0
  486. data/vendor/liblouis/tables/unicode-braille.utb +291 -0
  487. data/vendor/liblouis/tables/unicode-without-blank.dis +24 -0
  488. data/vendor/liblouis/tables/unicode.dis +278 -0
  489. data/vendor/liblouis/tables/ur-pk-g1.utb +248 -0
  490. data/vendor/liblouis/tables/ur-pk-g2.ctb +641 -0
  491. data/vendor/liblouis/tables/us-table.dis +67 -0
  492. data/vendor/liblouis/tables/uz-g1.utb +117 -0
  493. data/vendor/liblouis/tables/ve-za-g1.utb +69 -0
  494. data/vendor/liblouis/tables/ve-za-g2.ctb +208 -0
  495. data/vendor/liblouis/tables/vi-cb8.utb +49 -0
  496. data/vendor/liblouis/tables/vi-charsdef.uti +36 -0
  497. data/vendor/liblouis/tables/vi-lettersdef.uti +401 -0
  498. data/vendor/liblouis/tables/vi-puncsdef.uti +446 -0
  499. data/vendor/liblouis/tables/vi-saigon-g1.ctb +530 -0
  500. data/vendor/liblouis/tables/vi-vn-g0.utb +135 -0
  501. data/vendor/liblouis/tables/vi-vn-g1.ctb +574 -0
  502. data/vendor/liblouis/tables/vi-vn-g2.ctb +743 -0
  503. data/vendor/liblouis/tables/wiskunde-chardefs.cti +261 -0
  504. data/vendor/liblouis/tables/wordcx.dis +91 -0
  505. data/vendor/liblouis/tables/xh-za-g1.utb +61 -0
  506. data/vendor/liblouis/tables/xh-za-g2.ctb +386 -0
  507. data/vendor/liblouis/tables/yi.utb +236 -0
  508. data/vendor/liblouis/tables/zh-chn.ctb +45011 -0
  509. data/vendor/liblouis/tables/zh-hk.ctb +10461 -0
  510. data/vendor/liblouis/tables/zh-tw.ctb +53810 -0
  511. data/vendor/liblouis/tables/zh_CHN.tbl +23 -0
  512. data/vendor/liblouis/tables/zhcn-cbs.ctb +31523 -0
  513. data/vendor/liblouis/tables/zhcn-g1.ctb +26523 -0
  514. data/vendor/liblouis/tables/zhcn-g2.ctb +26519 -0
  515. data/vendor/liblouis/tables/zu-za-g1.utb +33 -0
  516. data/vendor/liblouis/tables/zu-za-g2.ctb +33 -0
  517. metadata +558 -0
@@ -0,0 +1,1855 @@
1
+ /* liblouis Braille Translation and Back-Translation Library
2
+
3
+ Based on the Linux screenreader BRLTTY, copyright (C) 1999-2006 by The
4
+ BRLTTY Team
5
+
6
+ Copyright (C) 2004, 2005, 2006 ViewPlus Technologies, Inc. www.viewplus.com
7
+ Copyright (C) 2004, 2005, 2006 JJB Software, Inc. www.jjb-software.com
8
+
9
+ This file is part of liblouis.
10
+
11
+ liblouis is free software: you can redistribute it and/or modify it
12
+ under the terms of the GNU Lesser General Public License as published
13
+ by the Free Software Foundation, either version 2.1 of the License, or
14
+ (at your option) any later version.
15
+
16
+ liblouis is distributed in the hope that it will be useful, but
17
+ WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
+ Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public
22
+ License along with liblouis. If not, see <http://www.gnu.org/licenses/>.
23
+ */
24
+
25
+ /**
26
+ * @file
27
+ * @brief Translate from braille
28
+ */
29
+
30
+ #include "config.h"
31
+
32
+ #include <stdio.h>
33
+ #include <stdlib.h>
34
+ #include <string.h>
35
+
36
+ #include "internal.h"
37
+
38
+ typedef struct {
39
+ int size;
40
+ widechar **buffers;
41
+ int *inUse;
42
+ widechar *(*alloc)(int index, int length);
43
+ void (*free)(widechar *);
44
+ } StringBufferPool;
45
+
46
+ /* noContractMode states: tracks nocontractsign scope during back-translation */
47
+ /* Note that the LAPSED state is necessary as a stop-gap measure to
48
+ * approximate seqdelimiter behavior. Without it, begword rules could
49
+ * e.g. not fire after a hyphen. In forward translation, the
50
+ * equivalent scenario is handled by seqdelimiter (and seqbeforechars,
51
+ * seqafterchars and seqafterpattern), but the backward translation
52
+ * code does not take into account seqdelimiter yet.
53
+ */
54
+ #define NO_CONTRACT_OFF 0 /* not in nocontractsign scope */
55
+ #define NO_CONTRACT_ACTIVE 1 /* after nocontractsign, contractions suppressed */
56
+ #define NO_CONTRACT_LAPSED 2 /* crossed non-letter, whole-word suppressed */
57
+
58
+ typedef struct {
59
+ int nextUpper;
60
+ int allUpper;
61
+ int allUpperPhrase;
62
+ int itsANumber;
63
+ int noContractMode;
64
+ formtype
65
+ activeWordEmphasis; /* emphasis for current word (cleared at word boundary) */
66
+ formtype activePhraseEmphasis; /* emphasis for current phrase (cleared by explicit
67
+ end) */
68
+ formtype nextCharEmphasis; /* emphasis for next character only (letter indicators) */
69
+ } TranslationContext;
70
+
71
+ static widechar *
72
+ allocStringBuffer(int index, int length) {
73
+ return _lou_allocMem(alloc_passbuf, index, 0, length);
74
+ }
75
+
76
+ static const StringBufferPool *stringBufferPool = NULL;
77
+
78
+ static void
79
+ initStringBufferPool() {
80
+ static widechar *stringBuffers[MAXPASSBUF] = { NULL };
81
+ static int stringBuffersInUse[MAXPASSBUF] = { 0 };
82
+ StringBufferPool *pool = malloc(sizeof(StringBufferPool));
83
+ pool->size = MAXPASSBUF;
84
+ pool->buffers = stringBuffers;
85
+ pool->inUse = stringBuffersInUse;
86
+ pool->alloc = &allocStringBuffer;
87
+ pool->free = NULL;
88
+ stringBufferPool = pool;
89
+ }
90
+
91
+ static int
92
+ getStringBuffer(int length) {
93
+ int i;
94
+
95
+ if (!stringBufferPool) initStringBufferPool();
96
+
97
+ for (i = 0; i < stringBufferPool->size; i++) {
98
+ if (!stringBufferPool->inUse[i]) {
99
+ stringBufferPool->buffers[i] = stringBufferPool->alloc(i, length);
100
+ stringBufferPool->inUse[i] = 1;
101
+ return i;
102
+ }
103
+ }
104
+ _lou_outOfMemory();
105
+ return -1;
106
+ }
107
+
108
+ static int
109
+ releaseStringBuffer(int idx) {
110
+ if (!stringBufferPool) {
111
+ _lou_logMessage(LOU_LOG_ERROR,
112
+ "Attempt to free string buffer prior to initialization of pool");
113
+ return 0;
114
+ }
115
+
116
+ if (idx >= 0 && idx < stringBufferPool->size) {
117
+ int inUse = stringBufferPool->inUse[idx];
118
+ if (inUse && stringBufferPool->free)
119
+ stringBufferPool->free(stringBufferPool->buffers[idx]);
120
+ stringBufferPool->inUse[idx] = 0;
121
+ return inUse;
122
+ }
123
+ return 0;
124
+ }
125
+
126
+ typedef struct {
127
+ int bufferIndex;
128
+ const widechar *chars;
129
+ int length;
130
+ } InString;
131
+
132
+ typedef struct {
133
+ int bufferIndex;
134
+ widechar *chars;
135
+ int maxlength;
136
+ int length;
137
+ } OutString;
138
+
139
+ typedef struct {
140
+ int startMatch;
141
+ int startReplace;
142
+ int endReplace;
143
+ int endMatch;
144
+ } PassRuleMatch;
145
+
146
+ static int
147
+ backTranslateString(const TranslationTableHeader *table, int mode, int currentPass,
148
+ const InString *input, OutString *output, unsigned char *typebuf, int *posMapping,
149
+ int *realInlen, int *cursorPosition, int *cursorStatus,
150
+ const TranslationTableRule **appliedRules, int *appliedRulesCount,
151
+ int maxAppliedRules);
152
+ static int
153
+ makeCorrections(const TranslationTableHeader *table, int mode, int currentPass,
154
+ const InString *input, OutString *output, int *posMapping, int *realInlen,
155
+ int *cursorPosition, int *cursorStatus, const TranslationTableRule **appliedRules,
156
+ int *appliedRulesCount, int maxAppliedRules);
157
+ static int
158
+ translatePass(const TranslationTableHeader *table, int mode, int currentPass,
159
+ const InString *input, OutString *output, int *posMapping, int *realInlen,
160
+ int *cursorPosition, int *cursorStatus, const TranslationTableRule **appliedRules,
161
+ int *appliedRulesCount, int maxAppliedRules);
162
+ static void
163
+ passSelectRule(const TranslationTableHeader *table, int pos, int currentPass,
164
+ const InString *input, TranslationTableOpcode *currentOpcode,
165
+ const TranslationTableRule **currentRule, const widechar **passInstructions,
166
+ int *passIC, PassRuleMatch *match);
167
+
168
+ int EXPORT_CALL
169
+ lou_backTranslateString(const char *tableList, const widechar *inbuf, int *inlen,
170
+ widechar *outbuf, int *outlen, formtype *typeform, char *spacing, int modex) {
171
+ return lou_backTranslate(tableList, inbuf, inlen, outbuf, outlen, typeform, spacing,
172
+ NULL, NULL, NULL, modex);
173
+ }
174
+
175
+ int EXPORT_CALL
176
+ lou_backTranslate(const char *tableList, const widechar *inbuf, int *inlen,
177
+ widechar *outbuf, int *outlen, formtype *typeform, char *spacing, int *outputPos,
178
+ int *inputPos, int *cursorPos, int modex) {
179
+ return _lou_backTranslate(tableList, tableList, inbuf, inlen, outbuf, outlen,
180
+ typeform, spacing, outputPos, inputPos, cursorPos, modex, NULL, NULL);
181
+ }
182
+
183
+ int EXPORT_CALL
184
+ _lou_backTranslate(const char *tableList, const char *displayTableList,
185
+ const widechar *inbuf, int *inlen, widechar *outbuf, int *outlen,
186
+ formtype *typeform, char *spacing, int *outputPos, int *inputPos, int *cursorPos,
187
+ int mode, const TranslationTableRule **rules, int *rulesLen) {
188
+ const TranslationTableHeader *table;
189
+ const DisplayTableHeader *displayTable;
190
+ InString input;
191
+ OutString output;
192
+ unsigned char *typebuf = NULL;
193
+ // posMapping contains position mapping info between the output of the current pass
194
+ // and the initial input. It is 1 longer than the (consumed) input. The values are
195
+ // monotonically increasing and can range between -1 and the output length. At the end
196
+ // the position info is passed to the user as an inputPos and outputPos array.
197
+ // inputPos has the length of the final output and has values ranging from 0 to
198
+ // inlen-1. outputPos has the length of the (consumed) initial input and has values
199
+ // ranging from 0 to outlen-1.
200
+ int *posMapping = NULL;
201
+ int *posMapping1;
202
+ int *posMapping2;
203
+ int *posMapping3;
204
+ int cursorPosition;
205
+ int cursorStatus;
206
+ const TranslationTableRule **appliedRules;
207
+ int maxAppliedRules;
208
+ int appliedRulesCount;
209
+ int k;
210
+ int idx;
211
+ if (tableList == NULL || inbuf == NULL || inlen == NULL || outbuf == NULL ||
212
+ outlen == NULL)
213
+ return 0;
214
+ if (displayTableList == NULL) displayTableList = tableList;
215
+ _lou_getTable(tableList, displayTableList, &table, &displayTable);
216
+ if (table == NULL) return 0;
217
+ if (*inlen < 0 || *outlen < 0) return 0;
218
+
219
+ if (!_lou_isValidMode(mode))
220
+ _lou_logMessage(LOU_LOG_ERROR, "Invalid mode parameter: %d", mode);
221
+
222
+ if (!stringBufferPool) initStringBufferPool();
223
+ for (idx = 0; idx < stringBufferPool->size; idx++) releaseStringBuffer(idx);
224
+ {
225
+ widechar *passbuf1;
226
+ int srcmax;
227
+ k = 0;
228
+ while (k < *inlen && inbuf[k]) k++;
229
+ srcmax = k;
230
+ idx = getStringBuffer(srcmax);
231
+ passbuf1 = stringBufferPool->buffers[idx];
232
+ for (k = 0; k < srcmax; k++)
233
+ if ((mode & dotsIO))
234
+ if ((mode & ucBrl))
235
+ passbuf1[k] = (inbuf[k] & 0xff) | LOU_DOTS;
236
+ else
237
+ passbuf1[k] = inbuf[k] | LOU_DOTS;
238
+ else
239
+ passbuf1[k] = _lou_getDotsForChar(inbuf[k], displayTable);
240
+ passbuf1[srcmax] = _lou_getDotsForChar(' ', displayTable);
241
+ input = (InString){ .chars = passbuf1, .length = srcmax, .bufferIndex = idx };
242
+ }
243
+ idx = getStringBuffer(*outlen);
244
+ output = (OutString){ .chars = stringBufferPool->buffers[idx],
245
+ .maxlength = *outlen,
246
+ .length = 0,
247
+ .bufferIndex = idx };
248
+ typebuf = (unsigned char *)typeform;
249
+ if (spacing != NULL)
250
+ _lou_logMessage(LOU_LOG_WARN,
251
+ "warning: the spacing parameter is deprecated and ignored; pass NULL");
252
+ if (outputPos != NULL)
253
+ for (k = 0; k < input.length; k++) outputPos[k] = -1;
254
+ if (cursorPos != NULL)
255
+ cursorPosition = *cursorPos;
256
+ else
257
+ cursorPosition = -1;
258
+ cursorStatus = 0;
259
+ if (typebuf != NULL) memset(typebuf, 0, *outlen * sizeof(formtype));
260
+ if (!(posMapping1 = _lou_allocMem(alloc_posMapping1, 0, input.length, *outlen)))
261
+ return 0;
262
+ if (table->numPasses > 1 || table->corrections) {
263
+ if (!(posMapping2 = _lou_allocMem(alloc_posMapping2, 0, input.length, *outlen)))
264
+ return 0;
265
+ if (!(posMapping3 = _lou_allocMem(alloc_posMapping3, 0, input.length, *outlen)))
266
+ return 0;
267
+ }
268
+ appliedRulesCount = 0;
269
+ if (rules != NULL && rulesLen != NULL) {
270
+ appliedRules = rules;
271
+ maxAppliedRules = *rulesLen;
272
+ } else {
273
+ appliedRules = NULL;
274
+ maxAppliedRules = 0;
275
+ }
276
+
277
+ posMapping = posMapping1;
278
+ int currentPass = table->numPasses;
279
+ int lastPass = table->corrections ? 0 : 1;
280
+ int *passPosMapping = posMapping;
281
+ while (1) {
282
+ int realInlen;
283
+ switch (currentPass) {
284
+ case 1:
285
+ if (!backTranslateString(table, mode, currentPass, &input, &output, typebuf,
286
+ passPosMapping, &realInlen, &cursorPosition, &cursorStatus,
287
+ appliedRules, &appliedRulesCount, maxAppliedRules))
288
+ return 0;
289
+ break;
290
+ case 0:
291
+ if (!makeCorrections(table, mode, currentPass, &input, &output,
292
+ passPosMapping, &realInlen, &cursorPosition, &cursorStatus,
293
+ appliedRules, &appliedRulesCount, maxAppliedRules))
294
+ return 0;
295
+ break;
296
+ default:
297
+ if (!translatePass(table, mode, currentPass, &input, &output, passPosMapping,
298
+ &realInlen, &cursorPosition, &cursorStatus, appliedRules,
299
+ &appliedRulesCount, maxAppliedRules))
300
+ return 0;
301
+ break;
302
+ }
303
+
304
+ currentPass--;
305
+ passPosMapping[realInlen] = output.length;
306
+ if (passPosMapping == posMapping) {
307
+ passPosMapping = posMapping2;
308
+ if (realInlen < input.length) *inlen = realInlen;
309
+ } else {
310
+ int *prevPosMapping = posMapping3;
311
+ memcpy((int *)prevPosMapping, posMapping, (*inlen + 1) * sizeof(int));
312
+ for (k = 0; k <= *inlen; k++) {
313
+ if (prevPosMapping[k] < 0)
314
+ posMapping[k] = passPosMapping[0];
315
+ else if (prevPosMapping[k] < realInlen)
316
+ posMapping[k] = passPosMapping[prevPosMapping[k]];
317
+ else if (prevPosMapping[k] == realInlen) {
318
+ // outputPos is allowed to point to right after the last output
319
+ // character if the input character was deleted
320
+ if (realInlen < input.length) {
321
+ // however if there was back-tracking, we know that this is not
322
+ // the case
323
+ *inlen = k;
324
+ posMapping[k] = output.length;
325
+ break;
326
+ } else
327
+ posMapping[k] = passPosMapping[prevPosMapping[k]];
328
+ } else {
329
+ // this means there has been back-tracking to a point within a segment
330
+ // that was atomic in the previous pass
331
+ // it is not clear what should happen in this case
332
+ *inlen = k;
333
+ posMapping[k] = output.length;
334
+ break;
335
+ }
336
+ }
337
+ }
338
+ if (currentPass >= lastPass) {
339
+ releaseStringBuffer(input.bufferIndex);
340
+ input = (InString){ .chars = output.chars,
341
+ .length = output.length,
342
+ .bufferIndex = output.bufferIndex };
343
+ idx = getStringBuffer(*outlen);
344
+ output = (OutString){ .chars = stringBufferPool->buffers[idx],
345
+ .maxlength = *outlen,
346
+ .length = 0,
347
+ .bufferIndex = idx };
348
+ continue;
349
+ }
350
+ break;
351
+ }
352
+ for (k = 0; k < output.length; k++) outbuf[k] = output.chars[k];
353
+ *outlen = output.length;
354
+ if (inputPos != NULL) {
355
+ int inpos = -1;
356
+ int outpos = -1;
357
+ for (k = 0; k < *inlen; k++)
358
+ if (posMapping[k] > outpos) {
359
+ while (outpos < posMapping[k]) {
360
+ if (outpos >= 0 && outpos < *outlen)
361
+ inputPos[outpos] = inpos < 0 ? 0 : inpos;
362
+ outpos++;
363
+ }
364
+ inpos = k;
365
+ }
366
+ if (outpos < 0) outpos = 0;
367
+ while (outpos < *outlen) inputPos[outpos++] = inpos;
368
+ }
369
+ if (outputPos != NULL) {
370
+ for (k = 0; k < *inlen; k++)
371
+ if (posMapping[k] < 0)
372
+ outputPos[k] = 0;
373
+ else if (posMapping[k] > *outlen - 1)
374
+ outputPos[k] = *outlen - 1;
375
+ else
376
+ outputPos[k] = posMapping[k];
377
+ }
378
+ if (cursorPos != NULL && *cursorPos != -1) {
379
+ if (outputPos != NULL)
380
+ *cursorPos = outputPos[*cursorPos];
381
+ else
382
+ *cursorPos = cursorPosition;
383
+ }
384
+ if (rulesLen != NULL) *rulesLen = appliedRulesCount;
385
+ return 1;
386
+ }
387
+
388
+ static TranslationTableCharacter *
389
+ getChar(widechar c, const TranslationTableHeader *table) {
390
+ static TranslationTableCharacter notFound = { NULL, -1, 0, 0, 0, CTC_Space, 0, 0, 32,
391
+ 0, 0 };
392
+ unsigned long int makeHash = _lou_charHash(c);
393
+ TranslationTableOffset bucket = table->characters[makeHash];
394
+ while (bucket) {
395
+ TranslationTableCharacter *character =
396
+ (TranslationTableCharacter *)&table->ruleArea[bucket];
397
+ if (character->value == c) return character;
398
+ bucket = character->next;
399
+ }
400
+ notFound.value = c;
401
+ return &notFound;
402
+ }
403
+
404
+ static TranslationTableCharacter *
405
+ getDots(widechar c, const TranslationTableHeader *table) {
406
+ static TranslationTableCharacter notFound = { NULL, -1, 0, 0, 0, CTC_Space, 0, 0,
407
+ LOU_DOTS, 0, 0 };
408
+ unsigned long int makeHash = _lou_charHash(c);
409
+ TranslationTableOffset bucket = table->dots[makeHash];
410
+ while (bucket) {
411
+ TranslationTableCharacter *character =
412
+ (TranslationTableCharacter *)&table->ruleArea[bucket];
413
+ if (character->value == c) return character;
414
+ bucket = character->next;
415
+ }
416
+ notFound.value = c;
417
+ return &notFound;
418
+ }
419
+
420
+ static int
421
+ checkDotsAttr(const widechar d, const TranslationTableCharacterAttributes a,
422
+ const TranslationTableHeader *table) {
423
+ static widechar prevd = 0;
424
+ static TranslationTableCharacterAttributes preva = 0;
425
+ if (d != prevd) {
426
+ preva = (getDots(d, table))->attributes;
427
+ prevd = d;
428
+ }
429
+ return ((preva & a) ? 1 : 0);
430
+ }
431
+
432
+ static int
433
+ compareDots(const widechar *address1, const widechar *address2, int count) {
434
+ int k;
435
+ if (!count) return 0;
436
+ for (k = 0; k < count; k++)
437
+ if (address1[k] != address2[k]) return 0;
438
+ return 1;
439
+ }
440
+
441
+ static void
442
+ back_setBefore(const TranslationTableHeader *table, OutString *output,
443
+ TranslationTableCharacterAttributes *beforeAttributes) {
444
+ widechar before = (output->length == 0) ? ' ' : output->chars[output->length - 1];
445
+ *beforeAttributes = (getChar(before, table))->attributes;
446
+ }
447
+
448
+ static void
449
+ back_setAfter(int length, const TranslationTableHeader *table, int pos,
450
+ const InString *input, TranslationTableCharacterAttributes *afterAttributes) {
451
+ widechar after = (pos + length < input->length) ? input->chars[pos + length] : ' ';
452
+ *afterAttributes = (getDots(after, table))->attributes;
453
+ }
454
+
455
+ static int
456
+ isBegWord(const TranslationTableHeader *table, OutString *output) {
457
+ /* See if this is really the beginning of a word. Look at what has
458
+ * already been translated. */
459
+ int k;
460
+ if (output->length == 0) return 1;
461
+ for (k = output->length - 1; k >= 0; k--) {
462
+ const TranslationTableCharacter *ch = getChar(output->chars[k], table);
463
+ if (ch->attributes & CTC_Space) break;
464
+ if (ch->attributes & (CTC_Letter | CTC_Digit | CTC_Math | CTC_Sign)) return 0;
465
+ }
466
+ return 1;
467
+ }
468
+
469
+ static int
470
+ isEndWord(const TranslationTableHeader *table, int pos, int mode, const InString *input,
471
+ int currentDotslen) {
472
+ if (mode & partialTrans) return 0;
473
+ /* See if this is really the end of a word. */
474
+ int k;
475
+ const TranslationTableCharacter *dots;
476
+ TranslationTableOffset testRuleOffset;
477
+ TranslationTableRule *testRule;
478
+ for (k = pos + currentDotslen; k < input->length; k++) {
479
+ int postpuncFound = 0;
480
+ int TranslationFound = 0;
481
+ dots = getDots(input->chars[k], table);
482
+ testRuleOffset = dots->otherRules;
483
+ if (dots->attributes & CTC_Space) break;
484
+ if (dots->attributes & CTC_Letter) return 0;
485
+ while (testRuleOffset) {
486
+ testRule = (TranslationTableRule *)&table->ruleArea[testRuleOffset];
487
+ /* #360: Don't treat begword/midword as definite translations here
488
+ * because we don't know whether they apply yet. Subsequent
489
+ * input will allow us to determine whether the word continues.
490
+ */
491
+ if (testRule->charslen > 1 && testRule->opcode != CTO_BegWord &&
492
+ testRule->opcode != CTO_MidWord)
493
+ TranslationFound = 1;
494
+ if (testRule->opcode == CTO_PostPunc) postpuncFound = 1;
495
+ if (testRule->opcode == CTO_Hyphen) return 1;
496
+ testRuleOffset = testRule->dotsnext;
497
+ }
498
+ if (TranslationFound && !postpuncFound) return 0;
499
+ }
500
+ return 1;
501
+ }
502
+ static int
503
+ findBrailleIndicatorRule(TranslationTableOffset offset,
504
+ const TranslationTableHeader *table, int *currentDotslen,
505
+ TranslationTableOpcode *currentOpcode, const TranslationTableRule **currentRule) {
506
+ if (!offset) return 0;
507
+ *currentRule = (TranslationTableRule *)&table->ruleArea[offset];
508
+ *currentOpcode = (*currentRule)->opcode;
509
+ *currentDotslen = (*currentRule)->dotslen;
510
+ return 1;
511
+ }
512
+
513
+ /* Identify which emphasis class and indicator type a emphasis rule belongs to.
514
+ * Returns the emphasis class index (0 to MAX_EMPH_CLASSES-1) and sets
515
+ * indicatorType to the EmphCodeOffset value. Returns -1 if not found. */
516
+ static int
517
+ findEmphasisClass(const TranslationTableHeader *table, const TranslationTableRule *rule,
518
+ int *indicatorType) {
519
+ int i;
520
+ /* Calculate rule offset: ruleArea is an array of TranslationTableData (8 bytes each),
521
+ * and offsets stored in emphRules are indices into this array */
522
+ TranslationTableOffset ruleOffset =
523
+ (TranslationTableOffset)(((char *)rule - (char *)&table->ruleArea[0]) /
524
+ sizeof(TranslationTableData));
525
+
526
+ for (i = 0; i < MAX_EMPH_CLASSES; i++) {
527
+ if (table->emphClasses[i].value == 0) continue; /* class not defined */
528
+
529
+ /* Check all indicator types for this emphasis class */
530
+ if (table->emphRules[i][letterOffset] == ruleOffset) {
531
+ *indicatorType = letterOffset;
532
+ return i;
533
+ }
534
+ if (table->emphRules[i][begWordOffset] == ruleOffset) {
535
+ *indicatorType = begWordOffset;
536
+ return i;
537
+ }
538
+ if (table->emphRules[i][endWordOffset] == ruleOffset) {
539
+ *indicatorType = endWordOffset;
540
+ return i;
541
+ }
542
+ if (table->emphRules[i][begPhraseOffset] == ruleOffset) {
543
+ *indicatorType = begPhraseOffset;
544
+ return i;
545
+ }
546
+ if (table->emphRules[i][endPhraseBeforeOffset] == ruleOffset) {
547
+ *indicatorType = endPhraseBeforeOffset;
548
+ return i;
549
+ }
550
+ if (table->emphRules[i][endPhraseAfterOffset] == ruleOffset) {
551
+ *indicatorType = endPhraseAfterOffset;
552
+ return i;
553
+ }
554
+ if (table->emphRules[i][begOffset] == ruleOffset) {
555
+ *indicatorType = begOffset;
556
+ return i;
557
+ }
558
+ if (table->emphRules[i][endOffset] == ruleOffset) {
559
+ *indicatorType = endOffset;
560
+ return i;
561
+ }
562
+ }
563
+ return -1;
564
+ }
565
+
566
+ static int
567
+ handleMultind(const TranslationTableHeader *table, int *currentDotslen,
568
+ TranslationTableOpcode *currentOpcode, const TranslationTableRule **currentRule,
569
+ int *doingMultind, const TranslationTableRule *multindRule) {
570
+ /* Handle multille braille indicators */
571
+ int found = 0;
572
+ if (!*doingMultind) return 0;
573
+ switch (multindRule->charsdots[multindRule->charslen - *doingMultind]) {
574
+ case CTO_CapsLetter: // FIXME: make sure this works
575
+ found = findBrailleIndicatorRule(table->emphRules[MAX_EMPH_CLASSES][letterOffset],
576
+ table, currentDotslen, currentOpcode, currentRule);
577
+ break;
578
+ // NOTE: following fixme is based on the names at the time of
579
+ // commit f22f91eb510cb4eef33dfb4950a297235dd2f9f1.
580
+ // FIXME: the next two opcodes were begcaps/endcaps,
581
+ // and they were aliased to opcodes capsword/capswordstop.
582
+ // However, the table attributes they use are
583
+ // table->beginCapitalSign and table->endCapitalSign.
584
+ // These are actually compiled with firstlettercaps/lastlettercaps.
585
+ // Which to use here?
586
+ case CTO_BegCapsWord:
587
+ found = findBrailleIndicatorRule(
588
+ table->emphRules[MAX_EMPH_CLASSES][begWordOffset], table, currentDotslen,
589
+ currentOpcode, currentRule);
590
+ break;
591
+ case CTO_EndCapsWord:
592
+ found = findBrailleIndicatorRule(
593
+ table->emphRules[MAX_EMPH_CLASSES][endWordOffset], table, currentDotslen,
594
+ currentOpcode, currentRule);
595
+ break;
596
+ case CTO_LetterSign:
597
+ found = findBrailleIndicatorRule(
598
+ table->letterSign, table, currentDotslen, currentOpcode, currentRule);
599
+ break;
600
+ case CTO_NoContractSign:
601
+ found = findBrailleIndicatorRule(
602
+ table->noContractSign, table, currentDotslen, currentOpcode, currentRule);
603
+ break;
604
+ case CTO_NumberSign:
605
+ found = findBrailleIndicatorRule(
606
+ table->numberSign, table, currentDotslen, currentOpcode, currentRule);
607
+ break;
608
+ case CTO_NoNumberSign:
609
+ found = findBrailleIndicatorRule(
610
+ table->noNumberSign, table, currentDotslen, currentOpcode, currentRule);
611
+ break;
612
+ case CTO_BegComp:
613
+ found = findBrailleIndicatorRule(
614
+ table->begComp, table, currentDotslen, currentOpcode, currentRule);
615
+ break;
616
+ case CTO_EndComp:
617
+ found = findBrailleIndicatorRule(
618
+ table->endComp, table, currentDotslen, currentOpcode, currentRule);
619
+ break;
620
+ default:
621
+ found = 0;
622
+ break;
623
+ }
624
+ (*doingMultind)--;
625
+ return found;
626
+ }
627
+
628
+ static int
629
+ back_passDoTest(const TranslationTableHeader *table, int pos, const InString *input,
630
+ TranslationTableOpcode currentOpcode, const TranslationTableRule *currentRule,
631
+ const widechar **passInstructions, int *passIC, PassRuleMatch *match);
632
+ static int
633
+ back_passDoAction(const TranslationTableHeader *table, int *pos, int mode,
634
+ const InString *input, OutString *output, int *posMapping, int *cursorPosition,
635
+ int *cursorStatus, TranslationContext *ctx, TranslationTableOpcode currentOpcode,
636
+ const TranslationTableRule *currentRule, const widechar *passInstructions,
637
+ int passIC, PassRuleMatch match);
638
+
639
+ static int
640
+ findBackPassRule(const TranslationTableHeader *table, int pos, int currentPass,
641
+ const InString *input, TranslationTableOpcode *currentOpcode,
642
+ const TranslationTableRule **currentRule, const widechar **passInstructions,
643
+ int *passIC, PassRuleMatch *match) {
644
+ TranslationTableOffset ruleOffset;
645
+ ruleOffset = table->backPassRules[currentPass];
646
+
647
+ while (ruleOffset) {
648
+ *currentRule = (TranslationTableRule *)&table->ruleArea[ruleOffset];
649
+ *currentOpcode = (*currentRule)->opcode;
650
+
651
+ switch (*currentOpcode) {
652
+ case CTO_Correct:
653
+ if (currentPass != 0) goto NEXT_RULE;
654
+ break;
655
+ case CTO_Context:
656
+ if (currentPass != 1) goto NEXT_RULE;
657
+ break;
658
+ case CTO_Pass2:
659
+ if (currentPass != 2) goto NEXT_RULE;
660
+ break;
661
+ case CTO_Pass3:
662
+ if (currentPass != 3) goto NEXT_RULE;
663
+ break;
664
+ case CTO_Pass4:
665
+ if (currentPass != 4) goto NEXT_RULE;
666
+ break;
667
+ default:
668
+ goto NEXT_RULE;
669
+ }
670
+
671
+ if (back_passDoTest(table, pos, input, *currentOpcode, *currentRule,
672
+ passInstructions, passIC, match))
673
+ return 1;
674
+
675
+ NEXT_RULE:
676
+ ruleOffset = (*currentRule)->dotsnext;
677
+ }
678
+
679
+ return 0;
680
+ }
681
+
682
+ static void
683
+ back_selectRule(const TranslationTableHeader *table, int pos, int mode,
684
+ const InString *input, OutString *output, const TranslationContext ctx,
685
+ int *currentDotslen, TranslationTableOpcode *currentOpcode,
686
+ const TranslationTableRule **currentRule, TranslationTableOpcode previousOpcode,
687
+ int *doingMultind, const TranslationTableRule **multindRule,
688
+ TranslationTableCharacterAttributes beforeAttributes,
689
+ const widechar **passInstructions, int *passIC, PassRuleMatch *patternMatch,
690
+ int hasTypebuf) {
691
+ /* check for valid back-translations */
692
+ int length = input->length - pos;
693
+ TranslationTableOffset ruleOffset = 0;
694
+ static TranslationTableRule pseudoRule = { 0 };
695
+ unsigned long int makeHash = 0;
696
+ const TranslationTableCharacter *dots = getDots(input->chars[pos], table);
697
+ int tryThis;
698
+ if (handleMultind(table, currentDotslen, currentOpcode, currentRule, doingMultind,
699
+ *multindRule))
700
+ return;
701
+ for (tryThis = 0; tryThis < 3; tryThis++) {
702
+ switch (tryThis) {
703
+ case 0:
704
+ if (length < 2 || (ctx.itsANumber && (dots->attributes & CTC_LitDigit)))
705
+ break;
706
+ /* Hash function optimized for backward translation */
707
+ makeHash = (unsigned long int)dots->value << 8;
708
+ makeHash += (unsigned long int)(getDots(input->chars[pos + 1], table))->value;
709
+ makeHash %= HASHNUM;
710
+ ruleOffset = table->backRules[makeHash];
711
+ break;
712
+ case 1:
713
+ if (!(length >= 1)) break;
714
+ length = 1;
715
+ ruleOffset = dots->otherRules;
716
+ break;
717
+ case 2: /* No rule found */
718
+ *currentRule = &pseudoRule;
719
+ *currentOpcode = pseudoRule.opcode = CTO_None;
720
+ *currentDotslen = pseudoRule.dotslen = 1;
721
+ pseudoRule.charsdots[0] = input->chars[pos];
722
+ pseudoRule.charslen = 0;
723
+ return;
724
+ break;
725
+ }
726
+ while (ruleOffset) {
727
+ const widechar *currentDots;
728
+ *currentRule = (TranslationTableRule *)&table->ruleArea[ruleOffset];
729
+ *currentOpcode = (*currentRule)->opcode;
730
+ if (*currentOpcode == CTO_Context) {
731
+ currentDots = &(*currentRule)->charsdots[0];
732
+ *currentDotslen = (*currentRule)->charslen;
733
+ } else {
734
+ currentDots = &(*currentRule)->charsdots[(*currentRule)->charslen];
735
+ *currentDotslen = (*currentRule)->dotslen;
736
+ }
737
+ if (((*currentDotslen <= length) &&
738
+ compareDots(&input->chars[pos], currentDots, *currentDotslen))) {
739
+ TranslationTableCharacterAttributes afterAttributes;
740
+ /* check this rule */
741
+ back_setAfter(*currentDotslen, table, pos, input, &afterAttributes);
742
+ if ((!((*currentRule)->after & ~CTC_EmpMatch) ||
743
+ (beforeAttributes & (*currentRule)->after)) &&
744
+ (!((*currentRule)->before & ~CTC_EmpMatch) ||
745
+ (afterAttributes & (*currentRule)->before))) {
746
+ switch (*currentOpcode) { /* check validity of this Translation */
747
+ case CTO_Context:
748
+ if (back_passDoTest(table, pos, input, *currentOpcode,
749
+ *currentRule, passInstructions, passIC, patternMatch))
750
+ return;
751
+ break;
752
+ case CTO_Space:
753
+ case CTO_Digit:
754
+ case CTO_Letter:
755
+ case CTO_UpperCase:
756
+ case CTO_LowerCase:
757
+ case CTO_Punctuation:
758
+ case CTO_Math:
759
+ case CTO_Sign:
760
+ case CTO_ExactDots:
761
+ case CTO_Repeated:
762
+ case CTO_Hyphen:
763
+ return;
764
+ case CTO_LitDigit:
765
+ if (ctx.itsANumber) return;
766
+ break;
767
+ case CTO_CapsLetter:
768
+ case CTO_BegCaps:
769
+ case CTO_EndCaps:
770
+ case CTO_BegCapsWord:
771
+ case CTO_EndCapsWord:
772
+ case CTO_BegEmph:
773
+ case CTO_EndEmph:
774
+ case CTO_NumberSign:
775
+ case CTO_BegComp:
776
+ case CTO_EndComp:
777
+ return;
778
+ case CTO_EmphLetter:
779
+ case CTO_BegEmphWord:
780
+ case CTO_EndEmphWord:
781
+ case CTO_BegEmphPhrase:
782
+ case CTO_EndEmphPhrase:
783
+ if (hasTypebuf) return;
784
+ break;
785
+ case CTO_NoContractSign:
786
+ /* This is just a heuristic test. During forward translation, the
787
+ nocontractsign is inserted when the following character is a
788
+ contraction, so CTC_Letter | CTC_Sign */
789
+ if ((afterAttributes & (CTC_Letter | CTC_Sign))) return;
790
+ break;
791
+ case CTO_LetterSign:
792
+ case CTO_NoNumberSign:
793
+ /* This is just a heuristic test. During forward translation, the
794
+ nonumsign is inserted when in numeric mode and the next
795
+ character is not numeric (CTC_Digit | CTC_LitDigit |
796
+ CTC_NumericMode | CTC_MidEndNumericMode) */
797
+ if (!(beforeAttributes & CTC_Letter) &&
798
+ (afterAttributes & (CTC_Letter | CTC_Sign)))
799
+ return;
800
+ break;
801
+ case CTO_MultInd:
802
+ *doingMultind = *currentDotslen;
803
+ *multindRule = *currentRule;
804
+ if (handleMultind(table, currentDotslen, currentOpcode,
805
+ currentRule, doingMultind, *multindRule))
806
+ return;
807
+ break;
808
+ case CTO_LargeSign:
809
+ return;
810
+ case CTO_WholeWord:
811
+ if (mode & partialTrans) break;
812
+ if (ctx.noContractMode || ctx.itsANumber) break;
813
+ if ((beforeAttributes & (CTC_Space | CTC_Punctuation)) &&
814
+ ((afterAttributes & CTC_Space) ||
815
+ isEndWord(table, pos, mode, input,
816
+ *currentDotslen)))
817
+ return;
818
+ break;
819
+ case CTO_LowWord:
820
+ if (mode & partialTrans) break;
821
+ if ((beforeAttributes & CTC_Space) &&
822
+ (afterAttributes & CTC_Space) &&
823
+ (previousOpcode != CTO_JoinableWord))
824
+ return;
825
+ break;
826
+ case CTO_JoinNum:
827
+ case CTO_JoinableWord:
828
+ if ((beforeAttributes & (CTC_Space | CTC_Punctuation)) &&
829
+ (!(afterAttributes & CTC_Space) || mode & partialTrans))
830
+ return;
831
+ break;
832
+ case CTO_SuffixableWord:
833
+ if (ctx.noContractMode || ctx.itsANumber) break;
834
+ if (beforeAttributes & (CTC_Space | CTC_Punctuation)) return;
835
+ break;
836
+ case CTO_PrefixableWord:
837
+ if (ctx.noContractMode || ctx.itsANumber) break;
838
+ if ((beforeAttributes &
839
+ (CTC_Space | CTC_Letter | CTC_Punctuation)) &&
840
+ isEndWord(table, pos, mode, input, *currentDotslen))
841
+ return;
842
+ break;
843
+ case CTO_BegWord:
844
+ if (ctx.noContractMode == NO_CONTRACT_ACTIVE) break;
845
+ if ((beforeAttributes & (CTC_Space | CTC_Punctuation)) &&
846
+ (!isEndWord(table, pos, mode, input, *currentDotslen)))
847
+ return;
848
+ break;
849
+ case CTO_BegMidWord:
850
+ if ((beforeAttributes &
851
+ (CTC_Letter | CTC_Space | CTC_Punctuation)) &&
852
+ (!isEndWord(table, pos, mode, input, *currentDotslen)))
853
+ return;
854
+ break;
855
+ case CTO_PartWord:
856
+ if (!(beforeAttributes & CTC_LitDigit) &&
857
+ (beforeAttributes & CTC_Letter ||
858
+ !isEndWord(table, pos, mode, input,
859
+ *currentDotslen)))
860
+ return;
861
+ break;
862
+ case CTO_MidWord:
863
+ if (beforeAttributes & CTC_Letter &&
864
+ !isEndWord(table, pos, mode, input, *currentDotslen))
865
+ return;
866
+ break;
867
+ case CTO_MidEndWord:
868
+ if ((beforeAttributes & CTC_Letter)) return;
869
+ break;
870
+ case CTO_EndWord:
871
+ if ((beforeAttributes & CTC_Letter) &&
872
+ isEndWord(table, pos, mode, input, *currentDotslen))
873
+ return;
874
+ break;
875
+ case CTO_BegNum:
876
+ if (beforeAttributes & (CTC_Space | CTC_Punctuation) &&
877
+ (afterAttributes & (CTC_LitDigit | CTC_Sign)))
878
+ return;
879
+ break;
880
+ case CTO_MidNum:
881
+ if (beforeAttributes & CTC_Digit &&
882
+ afterAttributes & CTC_LitDigit)
883
+ return;
884
+ break;
885
+ case CTO_EndNum:
886
+ if (ctx.itsANumber && !(afterAttributes & CTC_LitDigit)) return;
887
+ break;
888
+ case CTO_DecPoint:
889
+ if (afterAttributes & (CTC_Digit | CTC_LitDigit)) return;
890
+ break;
891
+ case CTO_PrePunc:
892
+ if (isBegWord(table, output)) return;
893
+ break;
894
+
895
+ case CTO_PostPunc:
896
+ if (isEndWord(table, pos, mode, input, *currentDotslen)) return;
897
+ break;
898
+ case CTO_Always:
899
+ if ((beforeAttributes & CTC_LitDigit) &&
900
+ (afterAttributes & CTC_LitDigit) &&
901
+ (*currentRule)->charslen > 1)
902
+ break;
903
+ return;
904
+
905
+ case CTO_BackMatch: {
906
+ widechar *patterns, *pattern;
907
+
908
+ // if(dontContract || (mode & noContractions))
909
+ // break;
910
+ // if(checkEmphasisChange(0))
911
+ // break;
912
+
913
+ patterns = (widechar *)&table->ruleArea[(*currentRule)->patterns];
914
+
915
+ /* check before pattern */
916
+ pattern = &patterns[1];
917
+ if (!_lou_pattern_check(
918
+ input->chars, pos - 1, -1, -1, pattern, table))
919
+ break;
920
+
921
+ /* check after pattern */
922
+ pattern = &patterns[patterns[0]];
923
+ if (!_lou_pattern_check(input->chars,
924
+ pos + (*currentRule)->dotslen, input->length, 1,
925
+ pattern, table))
926
+ break;
927
+
928
+ return;
929
+ }
930
+ default:
931
+ break;
932
+ }
933
+ }
934
+ } /* Done with checking this rule */
935
+ ruleOffset = (*currentRule)->dotsnext;
936
+ }
937
+ }
938
+ }
939
+
940
+ static widechar
941
+ toLowercase(
942
+ const TranslationTableHeader *table, const TranslationTableCharacter *character) {
943
+ if (character->mode & CTC_UpperCase) {
944
+ const TranslationTableCharacter *c = character;
945
+ if (c->basechar) c = (TranslationTableCharacter *)&table->ruleArea[c->basechar];
946
+ while (1) {
947
+ if ((c->mode & (character->mode & ~CTC_UpperCase)) ==
948
+ (character->mode & ~CTC_UpperCase))
949
+ return c->value;
950
+ if (!c->linked) break;
951
+ c = (TranslationTableCharacter *)&table->ruleArea[c->linked];
952
+ }
953
+ }
954
+ return character->value;
955
+ }
956
+
957
+ static widechar
958
+ toUppercase(
959
+ const TranslationTableHeader *table, const TranslationTableCharacter *character) {
960
+ const TranslationTableCharacter *c = character;
961
+ if (c->basechar) c = (TranslationTableCharacter *)&table->ruleArea[c->basechar];
962
+ while (c->linked) {
963
+ c = (TranslationTableCharacter *)&table->ruleArea[c->linked];
964
+ if ((c->mode & (character->mode | CTC_UpperCase)) ==
965
+ (character->mode | CTC_UpperCase))
966
+ return c->value;
967
+ }
968
+ return character->value;
969
+ }
970
+
971
+ static int
972
+ putchars(const widechar *chars, int count, const TranslationTableHeader *table,
973
+ OutString *output, TranslationContext *ctx) {
974
+ int k = 0;
975
+ if (!count || (output->length + count) > output->maxlength) return 0;
976
+ if (ctx->nextUpper) {
977
+ output->chars[(output->length)++] =
978
+ toUppercase(table, getChar(chars[k++], table));
979
+ ctx->nextUpper = 0;
980
+ }
981
+ if (!ctx->allUpper && !ctx->allUpperPhrase) {
982
+ memcpy(&output->chars[output->length], &chars[k], CHARSIZE * (count - k));
983
+ output->length += count - k;
984
+ } else
985
+ for (; k < count; k++) {
986
+ const TranslationTableCharacter *c = getChar(chars[k], table);
987
+ /* In capsword mode, a non-letter non-capsmode character terminates
988
+ * the capsword. This is needed here because multi-character rules
989
+ * (e.g. endword 's) output multiple chars in one putchars call,
990
+ * bypassing the main loop's per-iteration termination
991
+ * check. Capsphrase is not affected. */
992
+ if (ctx->allUpper == 2 && !ctx->allUpperPhrase &&
993
+ !(c->attributes & CTC_Letter) && !(c->attributes & CTC_CapsMode)) {
994
+ ctx->allUpper = 0;
995
+ memcpy(&output->chars[output->length], &chars[k], CHARSIZE * (count - k));
996
+ output->length += count - k;
997
+ return 1;
998
+ }
999
+ output->chars[(output->length)++] = toUppercase(table, c);
1000
+ }
1001
+ return 1;
1002
+ }
1003
+
1004
+ static int
1005
+ back_updatePositions(const widechar *outChars, int inLength, int outLength,
1006
+ const TranslationTableHeader *table, int pos, const InString *input,
1007
+ OutString *output, int *posMapping, int *cursorPosition, int *cursorStatus,
1008
+ TranslationContext *ctx) {
1009
+ int k;
1010
+ if ((output->length + outLength) > output->maxlength ||
1011
+ (pos + inLength) > input->length)
1012
+ return 0;
1013
+ if (!*cursorStatus && *cursorPosition >= pos && *cursorPosition < (pos + inLength)) {
1014
+ *cursorPosition = output->length + outLength / 2;
1015
+ *cursorStatus = 1;
1016
+ }
1017
+ for (k = 0; k < inLength; k++) posMapping[pos + k] = output->length;
1018
+ return putchars(outChars, outLength, table, output, ctx);
1019
+ }
1020
+
1021
+ static int
1022
+ undefinedDots(widechar dots, int mode, OutString *output, int pos, int *posMapping) {
1023
+ posMapping[pos] = output->length;
1024
+ if (mode & noUndefined) return 1;
1025
+
1026
+ /* Print out dot numbers */
1027
+ const char *buffer = _lou_unknownDots(dots);
1028
+ size_t buflen = strlen(buffer);
1029
+ if ((output->length + (int)buflen) > output->maxlength) return 0;
1030
+
1031
+ for (unsigned int k = 0; k < buflen; k += 1) {
1032
+ output->chars[output->length++] = buffer[k];
1033
+ }
1034
+
1035
+ return 1;
1036
+ }
1037
+
1038
+ static int
1039
+ putCharacter(widechar dots, const TranslationTableHeader *table, int pos, int mode,
1040
+ const InString *input, OutString *output, int *posMapping, int *cursorPosition,
1041
+ int *cursorStatus, TranslationContext *ctx) {
1042
+ /* Output character(s) corresponding to a Unicode braille Character */
1043
+ TranslationTableOffset offset = (getDots(dots, table))->definitionRule;
1044
+ if (offset) {
1045
+ const TranslationTableRule *rule =
1046
+ (TranslationTableRule *)&table->ruleArea[offset];
1047
+ return back_updatePositions(&rule->charsdots[0], rule->dotslen, rule->charslen,
1048
+ table, pos, input, output, posMapping, cursorPosition, cursorStatus, ctx);
1049
+ }
1050
+ return undefinedDots(dots, mode, output, pos, posMapping);
1051
+ }
1052
+
1053
+ static int
1054
+ putCharacters(const widechar *characters, int count, const TranslationTableHeader *table,
1055
+ int pos, int mode, const InString *input, OutString *output, int *posMapping,
1056
+ int *cursorPosition, int *cursorStatus, TranslationContext *ctx) {
1057
+ int k;
1058
+ for (k = 0; k < count; k++)
1059
+ if (!putCharacter(characters[k], table, pos, mode, input, output, posMapping,
1060
+ cursorPosition, cursorStatus, ctx))
1061
+ return 0;
1062
+ return 1;
1063
+ }
1064
+
1065
+ static int
1066
+ insertSpace(const TranslationTableHeader *table, int pos, const InString *input,
1067
+ OutString *output, int *posMapping, int *cursorPosition, int *cursorStatus,
1068
+ TranslationContext *ctx) {
1069
+ widechar c = ' ';
1070
+ if (!back_updatePositions(&c, 1, 1, table, pos, input, output, posMapping,
1071
+ cursorPosition, cursorStatus, ctx))
1072
+ return 0;
1073
+ return 1;
1074
+ }
1075
+
1076
+ static int
1077
+ compareChars(const widechar *address1, const widechar *address2, int count,
1078
+ const TranslationTableHeader *table) {
1079
+ int k;
1080
+ if (!count) return 0;
1081
+ for (k = 0; k < count; k++)
1082
+ if (toLowercase(table, getChar(address1[k], table)) !=
1083
+ toLowercase(table, getChar(address2[k], table)))
1084
+ return 0;
1085
+ return 1;
1086
+ }
1087
+
1088
+ static int
1089
+ makeCorrections(const TranslationTableHeader *table, int mode, int currentPass,
1090
+ const InString *input, OutString *output, int *posMapping, int *realInlen,
1091
+ int *cursorPosition, int *cursorStatus, const TranslationTableRule **appliedRules,
1092
+ int *appliedRulesCount, int maxAppliedRules) {
1093
+ int pos;
1094
+ int posIncremented = 1;
1095
+ TranslationContext ctx = { .nextUpper = 0,
1096
+ .allUpper = 0,
1097
+ .allUpperPhrase = 0,
1098
+ .itsANumber = 0,
1099
+ .noContractMode = NO_CONTRACT_OFF };
1100
+ if (!table->corrections) return 1;
1101
+ pos = 0;
1102
+ output->length = 0;
1103
+ _lou_resetPassVariables();
1104
+ while (pos < input->length) {
1105
+ int posBefore = pos;
1106
+ TranslationTableOpcode currentOpcode;
1107
+ const TranslationTableRule *currentRule; /* pointer to current rule in table */
1108
+ const widechar *passInstructions;
1109
+ int passIC; /* Instruction counter */
1110
+ PassRuleMatch patternMatch;
1111
+ int length = input->length - pos;
1112
+ const TranslationTableCharacter *character = getChar(input->chars[pos], table);
1113
+ const TranslationTableCharacter *character2;
1114
+ int tryThis = 0;
1115
+ if (!(posIncremented &&
1116
+ findBackPassRule(table, pos, currentPass, input, &currentOpcode,
1117
+ &currentRule, &passInstructions, &passIC, &patternMatch)))
1118
+ while (tryThis < 3) {
1119
+ TranslationTableOffset ruleOffset = 0;
1120
+ unsigned long int makeHash = 0;
1121
+ switch (tryThis) {
1122
+ case 0:
1123
+ if (!(length >= 2)) break;
1124
+ makeHash = (unsigned long int)toLowercase(table, character) << 8;
1125
+ character2 = getChar(input->chars[pos + 1], table);
1126
+ makeHash += (unsigned long int)toLowercase(table, character2);
1127
+ makeHash %= HASHNUM;
1128
+ ruleOffset = table->backRules[makeHash];
1129
+ break;
1130
+ case 1:
1131
+ if (!(length >= 1)) break;
1132
+ length = 1;
1133
+ ruleOffset = character->otherRules;
1134
+ break;
1135
+ case 2: /* No rule found */
1136
+ currentOpcode = CTO_Always;
1137
+ ruleOffset = 0;
1138
+ break;
1139
+ }
1140
+ while (ruleOffset) {
1141
+ currentRule = (TranslationTableRule *)&table->ruleArea[ruleOffset];
1142
+ currentOpcode = currentRule->opcode;
1143
+ int currentCharslen = currentRule->charslen;
1144
+ if (tryThis == 1 ||
1145
+ (currentCharslen <= length &&
1146
+ compareChars(&currentRule->charsdots[0],
1147
+ &input->chars[pos], currentCharslen,
1148
+ table))) {
1149
+ if (currentOpcode == CTO_Correct &&
1150
+ back_passDoTest(table, pos, input, currentOpcode,
1151
+ currentRule, &passInstructions, &passIC,
1152
+ &patternMatch)) {
1153
+ tryThis = 4;
1154
+ break;
1155
+ }
1156
+ }
1157
+ ruleOffset = currentRule->dotsnext;
1158
+ }
1159
+ tryThis++;
1160
+ }
1161
+ switch (currentOpcode) {
1162
+ case CTO_Always:
1163
+ if (output->length >= output->maxlength) goto failure;
1164
+ posMapping[pos] = output->length;
1165
+ output->chars[(output->length)++] = input->chars[pos++];
1166
+ break;
1167
+ case CTO_Correct:
1168
+ if (appliedRules != NULL && *appliedRulesCount < maxAppliedRules)
1169
+ appliedRules[(*appliedRulesCount)++] = currentRule;
1170
+ if (!back_passDoAction(table, &pos, mode, input, output, posMapping,
1171
+ cursorPosition, cursorStatus, &ctx, currentOpcode, currentRule,
1172
+ passInstructions, passIC, patternMatch))
1173
+ goto failure;
1174
+ break;
1175
+ default:
1176
+ break;
1177
+ }
1178
+ posIncremented = pos > posBefore;
1179
+ }
1180
+ failure:
1181
+ *realInlen = pos;
1182
+ return 1;
1183
+ }
1184
+
1185
+ static int
1186
+ backTranslateString(const TranslationTableHeader *table, int mode, int currentPass,
1187
+ const InString *input, OutString *output, unsigned char *typebuf, int *posMapping,
1188
+ int *realInlen, int *cursorPosition, int *cursorStatus,
1189
+ const TranslationTableRule **appliedRules, int *appliedRulesCount,
1190
+ int maxAppliedRules) {
1191
+ int pos;
1192
+ TranslationContext ctx = { .nextUpper = 0,
1193
+ .allUpper = 0,
1194
+ .allUpperPhrase = 0,
1195
+ .itsANumber = 0,
1196
+ .noContractMode = NO_CONTRACT_OFF,
1197
+ .activeWordEmphasis = 0,
1198
+ .activePhraseEmphasis = 0,
1199
+ .nextCharEmphasis = 0 };
1200
+ /* Back translation */
1201
+ int srcword = 0;
1202
+ int destword = 0; /* last word translated */
1203
+ TranslationTableOpcode previousOpcode;
1204
+ int doingMultind = 0;
1205
+ const TranslationTableRule *multindRule;
1206
+ _lou_resetPassVariables();
1207
+ translation_direction = 0;
1208
+ previousOpcode = CTO_None;
1209
+ pos = output->length = 0;
1210
+ while (pos < input->length) {
1211
+ /* the main translation loop */
1212
+ int currentDotslen; /* length of current find string */
1213
+ TranslationTableOpcode currentOpcode;
1214
+ const TranslationTableRule *currentRule; /* pointer to current rule in table */
1215
+ TranslationTableCharacterAttributes beforeAttributes;
1216
+ const widechar *passInstructions;
1217
+ int passIC; /* Instruction counter */
1218
+ PassRuleMatch patternMatch;
1219
+ int prevOutputLength = output->length; /* track output for typeform population */
1220
+ back_setBefore(table, output, &beforeAttributes);
1221
+ if ((ctx.allUpper == 1) && (beforeAttributes & CTC_UpperCase))
1222
+ // Capsword in progress
1223
+ ctx.allUpper = 2;
1224
+ else if ((ctx.allUpper == 2) && !(beforeAttributes & CTC_UpperCase) &&
1225
+ !(beforeAttributes & CTC_CapsMode))
1226
+ // terminate capsword
1227
+ ctx.allUpper = 0;
1228
+ if ((ctx.itsANumber == 2) && output->length > 0 &&
1229
+ !(beforeAttributes & CTC_LitDigit) &&
1230
+ !(beforeAttributes & CTC_NumericMode) &&
1231
+ !(beforeAttributes & CTC_MidEndNumericMode))
1232
+ ctx.itsANumber = 0;
1233
+ back_selectRule(table, pos, mode, input, output, ctx, &currentDotslen,
1234
+ &currentOpcode, &currentRule, previousOpcode, &doingMultind, &multindRule,
1235
+ beforeAttributes, &passInstructions, &passIC, &patternMatch,
1236
+ typebuf != NULL);
1237
+ if (appliedRules != NULL && *appliedRulesCount < maxAppliedRules)
1238
+ appliedRules[(*appliedRulesCount)++] = currentRule;
1239
+ /* processing before replacement */
1240
+ switch (currentOpcode) {
1241
+ case CTO_LargeSign:
1242
+ if (previousOpcode == CTO_LargeSign)
1243
+ if (!insertSpace(table, pos, input, output, posMapping, cursorPosition,
1244
+ cursorStatus, &ctx))
1245
+ goto failure;
1246
+ break;
1247
+ case CTO_CapsLetter:
1248
+ ctx.nextUpper = 1;
1249
+ ctx.allUpper = 0;
1250
+ ctx.itsANumber = 0;
1251
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1252
+ continue;
1253
+ break;
1254
+ case CTO_BegCapsWord:
1255
+ ctx.allUpper = 1;
1256
+ ctx.itsANumber = 0;
1257
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1258
+ continue;
1259
+ break;
1260
+ case CTO_BegCaps:
1261
+ ctx.allUpperPhrase = 1;
1262
+ ctx.itsANumber = 0;
1263
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1264
+ continue;
1265
+ break;
1266
+ case CTO_EndCapsWord:
1267
+ ctx.allUpper = 0;
1268
+ ctx.itsANumber = 0;
1269
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1270
+ continue;
1271
+ break;
1272
+ case CTO_EndCaps:
1273
+ ctx.allUpperPhrase = 0;
1274
+ ctx.itsANumber = 0;
1275
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1276
+ continue;
1277
+ break;
1278
+ case CTO_LetterSign:
1279
+ case CTO_NoNumberSign:
1280
+ case CTO_NoContractSign:
1281
+ ctx.noContractMode = NO_CONTRACT_ACTIVE;
1282
+ ctx.itsANumber = 0;
1283
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1284
+ continue;
1285
+ break;
1286
+ case CTO_NumberSign:
1287
+ ctx.itsANumber = 1; // Starting number
1288
+ ctx.allUpper = 0;
1289
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1290
+ continue;
1291
+ break;
1292
+ case CTO_LitDigit:
1293
+ ctx.itsANumber = 2; // In the middle of a number
1294
+ break;
1295
+ case CTO_BegComp:
1296
+ ctx.itsANumber = 0;
1297
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1298
+ continue;
1299
+ break;
1300
+ case CTO_EndComp:
1301
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1302
+ continue;
1303
+ break;
1304
+ case CTO_EmphLetter:
1305
+ case CTO_BegEmphWord:
1306
+ case CTO_EndEmphWord:
1307
+ case CTO_BegEmph:
1308
+ case CTO_EndEmph:
1309
+ case CTO_BegEmphPhrase:
1310
+ case CTO_EndEmphPhrase: {
1311
+ int indicatorType = -1;
1312
+ int emphClass = findEmphasisClass(table, currentRule, &indicatorType);
1313
+ if (emphClass >= 0) {
1314
+ formtype emphBit = table->emphClasses[emphClass].typeform;
1315
+ switch (currentOpcode) {
1316
+ case CTO_EmphLetter:
1317
+ /* Single letter emphasis - applies to next character only */
1318
+ ctx.nextCharEmphasis |= emphBit;
1319
+ break;
1320
+ case CTO_BegEmphWord:
1321
+ /* Begin word emphasis */
1322
+ ctx.activeWordEmphasis |= emphBit;
1323
+ break;
1324
+ case CTO_EndEmphWord:
1325
+ /* End word emphasis. In UEB, endemphword and endemphphrase
1326
+ * share the same dot pattern (e.g., 45-3 for bold). If we
1327
+ * match endemphword but there's no active word emphasis for
1328
+ * this class, check if there's active phrase emphasis and
1329
+ * end that instead - this handles the ambiguity correctly. */
1330
+ if (ctx.activeWordEmphasis & emphBit) {
1331
+ ctx.activeWordEmphasis &= ~emphBit;
1332
+ } else if (ctx.activePhraseEmphasis & emphBit) {
1333
+ ctx.activePhraseEmphasis &= ~emphBit;
1334
+ }
1335
+ break;
1336
+ case CTO_BegEmphPhrase:
1337
+ /* Begin phrase emphasis */
1338
+ ctx.activePhraseEmphasis |= emphBit;
1339
+ break;
1340
+ case CTO_EndEmphPhrase:
1341
+ /* End phrase emphasis */
1342
+ ctx.activePhraseEmphasis &= ~emphBit;
1343
+ break;
1344
+ case CTO_BegEmph:
1345
+ /* Generic begin (firstletter style) - treat as word */
1346
+ ctx.activeWordEmphasis |= emphBit;
1347
+ break;
1348
+ case CTO_EndEmph:
1349
+ /* Generic end (lastletter style). Like CTO_EndEmphWord,
1350
+ * handle the ambiguity when endemph could mean either
1351
+ * word or phrase termination. */
1352
+ if (ctx.activeWordEmphasis & emphBit) {
1353
+ ctx.activeWordEmphasis &= ~emphBit;
1354
+ } else if (ctx.activePhraseEmphasis & emphBit) {
1355
+ ctx.activePhraseEmphasis &= ~emphBit;
1356
+ }
1357
+ break;
1358
+ default:
1359
+ break;
1360
+ }
1361
+ }
1362
+ while (currentDotslen-- > 0) posMapping[pos++] = output->length;
1363
+ continue;
1364
+ break;
1365
+ }
1366
+
1367
+ default:
1368
+ break;
1369
+ }
1370
+
1371
+ /* replacement processing */
1372
+ switch (currentOpcode) {
1373
+ case CTO_Context:
1374
+ if (!back_passDoAction(table, &pos, mode, input, output, posMapping,
1375
+ cursorPosition, cursorStatus, &ctx, currentOpcode, currentRule,
1376
+ passInstructions, passIC, patternMatch))
1377
+ return 0;
1378
+ break;
1379
+ case CTO_None:
1380
+ if (!undefinedDots(input->chars[pos], mode, output, pos, posMapping))
1381
+ goto failure;
1382
+ pos++;
1383
+ break;
1384
+ case CTO_BegNum:
1385
+ ctx.itsANumber = 1;
1386
+ goto insertChars;
1387
+ case CTO_EndNum:
1388
+ ctx.itsANumber = 0;
1389
+ goto insertChars;
1390
+ case CTO_Space:
1391
+ ctx.noContractMode = NO_CONTRACT_OFF;
1392
+ ctx.itsANumber = ctx.allUpper = ctx.nextUpper = 0;
1393
+ goto insertChars;
1394
+ default:
1395
+ insertChars:
1396
+ if (ctx.noContractMode == NO_CONTRACT_ACTIVE && currentOpcode != CTO_Letter &&
1397
+ currentOpcode != CTO_UpperCase && currentOpcode != CTO_LowerCase)
1398
+ ctx.noContractMode = NO_CONTRACT_LAPSED;
1399
+ if (currentRule->charslen) {
1400
+ if (!back_updatePositions(&currentRule->charsdots[0],
1401
+ currentRule->dotslen, currentRule->charslen, table, pos,
1402
+ input, output, posMapping, cursorPosition, cursorStatus,
1403
+ &ctx))
1404
+ goto failure;
1405
+ pos += currentDotslen;
1406
+ } else {
1407
+ int srclim = pos + currentDotslen;
1408
+ while (1) {
1409
+ if (!putCharacter(input->chars[pos], table, pos, mode, input, output,
1410
+ posMapping, cursorPosition, cursorStatus, &ctx))
1411
+ goto failure;
1412
+ if (++pos == srclim) break;
1413
+ }
1414
+ }
1415
+ }
1416
+
1417
+ /* Save opcode before passSelectRule may overwrite it.
1418
+ * When processing space characters, passSelectRule() in the default
1419
+ * switch case could overwrite currentOpcode before the word-emphasis
1420
+ * clearing check. This would cause word emphasis to persist across
1421
+ * space boundaries, affecting all subsequent text instead of just
1422
+ * the emphasized word. */
1423
+ TranslationTableOpcode opcodeForEmphasis = currentOpcode;
1424
+
1425
+ /* processing after replacement */
1426
+ switch (currentOpcode) {
1427
+ case CTO_JoinNum:
1428
+ case CTO_JoinableWord:
1429
+ if (!insertSpace(table, pos, input, output, posMapping, cursorPosition,
1430
+ cursorStatus, &ctx))
1431
+ goto failure;
1432
+ break;
1433
+ default:
1434
+ passSelectRule(table, pos, currentPass, input, &currentOpcode, &currentRule,
1435
+ &passInstructions, &passIC, &patternMatch);
1436
+ if (currentOpcode == CTO_Context) {
1437
+ if (appliedRules != NULL && *appliedRulesCount < maxAppliedRules)
1438
+ appliedRules[(*appliedRulesCount)++] = currentRule;
1439
+ back_passDoAction(table, &pos, mode, input, output, posMapping,
1440
+ cursorPosition, cursorStatus, &ctx, currentOpcode, currentRule,
1441
+ passInstructions, passIC, patternMatch);
1442
+ }
1443
+ break;
1444
+ }
1445
+
1446
+ /* Populate typeform buffer for newly output characters */
1447
+ if (typebuf != NULL && output->length > prevOutputLength) {
1448
+ formtype currentEmphasis = ctx.activePhraseEmphasis | ctx.activeWordEmphasis |
1449
+ ctx.nextCharEmphasis;
1450
+ formtype *typeformBuf = (formtype *)typebuf;
1451
+ int k;
1452
+ for (k = prevOutputLength; k < output->length; k++) {
1453
+ typeformBuf[k] = currentEmphasis;
1454
+ }
1455
+ /* Clear single-character emphasis after it's been applied */
1456
+ ctx.nextCharEmphasis = 0;
1457
+ }
1458
+
1459
+ /* Clear word-level emphasis at word boundaries.
1460
+ * NOTE: This currently only checks for spaces. The forward translator also
1461
+ * consults emphmodechars to determine which non-letter characters cancel
1462
+ * word emphasis (see resetsEmphMode() in lou_translateString.c). Tables
1463
+ * that declare emphmodechars (e.g. Dutch, German) may produce incorrect
1464
+ * typeforms here. */
1465
+ if (opcodeForEmphasis == CTO_Space) {
1466
+ ctx.activeWordEmphasis = 0;
1467
+ }
1468
+
1469
+ if (((pos > 0) && checkDotsAttr(input->chars[pos - 1], CTC_Space, table) &&
1470
+ (currentOpcode != CTO_JoinableWord))) {
1471
+ srcword = pos;
1472
+ destword = output->length;
1473
+ }
1474
+ if ((currentOpcode >= CTO_Always && currentOpcode <= CTO_None) ||
1475
+ (currentOpcode >= CTO_Digit && currentOpcode <= CTO_LitDigit))
1476
+ previousOpcode = currentOpcode;
1477
+ } /* end of translation loop */
1478
+ failure:
1479
+
1480
+ if (destword != 0 && pos < input->length &&
1481
+ !checkDotsAttr(input->chars[pos], CTC_Space, table)) {
1482
+ pos = srcword;
1483
+ output->length = destword;
1484
+ }
1485
+ if (pos < input->length) {
1486
+ while (checkDotsAttr(input->chars[pos], CTC_Space, table))
1487
+ if (++pos == input->length) break;
1488
+ }
1489
+ *realInlen = pos;
1490
+ return 1;
1491
+ } /* translation completed */
1492
+
1493
+ /* Multipass translation */
1494
+
1495
+ static int
1496
+ matchCurrentInput(
1497
+ const InString *input, int pos, const widechar *passInstructions, int passIC) {
1498
+ int k;
1499
+ int kk = pos;
1500
+ for (k = passIC + 2; k < passIC + 2 + passInstructions[passIC + 1]; k++)
1501
+ if (passInstructions[k] != input->chars[kk++]) return 0;
1502
+ return 1;
1503
+ }
1504
+
1505
+ static int
1506
+ back_swapTest(const TranslationTableHeader *table, const InString *input, int *pos,
1507
+ const widechar *passInstructions, int passIC) {
1508
+ int curLen;
1509
+ int curTest;
1510
+ int curSrc = *pos;
1511
+ TranslationTableOffset swapRuleOffset;
1512
+ TranslationTableRule *swapRule;
1513
+ swapRuleOffset = (passInstructions[passIC + 1] << 16) | passInstructions[passIC + 2];
1514
+ swapRule = (TranslationTableRule *)&table->ruleArea[swapRuleOffset];
1515
+ for (curLen = 0; curLen < passInstructions[passIC] + 3; curLen++) {
1516
+ for (curTest = 0; curTest < swapRule->charslen; curTest++) {
1517
+ if (input->chars[curSrc] == swapRule->charsdots[curTest]) break;
1518
+ }
1519
+ if (curTest == swapRule->charslen) return 0;
1520
+ curSrc++;
1521
+ }
1522
+ if (passInstructions[passIC + 2] == passInstructions[passIC + 3]) {
1523
+ *pos = curSrc;
1524
+ return 1;
1525
+ }
1526
+ while (curLen < passInstructions[passIC + 4]) {
1527
+ for (curTest = 0; curTest < swapRule->charslen; curTest++) {
1528
+ if (input->chars[curSrc] != swapRule->charsdots[curTest]) break;
1529
+ }
1530
+ if (curTest < swapRule->charslen) {
1531
+ *pos = curSrc;
1532
+ return 1;
1533
+ }
1534
+ curSrc++;
1535
+ curLen++;
1536
+ }
1537
+ *pos = curSrc;
1538
+ return 1;
1539
+ }
1540
+
1541
+ static int
1542
+ back_swapReplace(int start, int end, const TranslationTableHeader *table,
1543
+ const InString *input, OutString *output, int *posMapping,
1544
+ const widechar *passInstructions, int passIC) {
1545
+ TranslationTableOffset swapRuleOffset;
1546
+ TranslationTableRule *swapRule;
1547
+ widechar *replacements;
1548
+ int p;
1549
+ int lastPos = 0;
1550
+ int lastRep = 0;
1551
+ swapRuleOffset = (passInstructions[passIC + 1] << 16) | passInstructions[passIC + 2];
1552
+ swapRule = (TranslationTableRule *)&table->ruleArea[swapRuleOffset];
1553
+ replacements = &swapRule->charsdots[swapRule->charslen];
1554
+ for (p = start; p < end; p++) {
1555
+ int rep;
1556
+ int test;
1557
+ int k;
1558
+ for (test = 0; test < swapRule->charslen; test++)
1559
+ if (input->chars[p] == swapRule->charsdots[test]) break;
1560
+ if (test == swapRule->charslen) return p;
1561
+ if (test >= lastRep) {
1562
+ k = lastPos;
1563
+ rep = lastRep;
1564
+ } else {
1565
+ k = 0;
1566
+ rep = 0;
1567
+ }
1568
+ while (k < swapRule->dotslen) {
1569
+ if (rep == test) {
1570
+ int l = replacements[k] - 1;
1571
+ if (output->length + l >= output->maxlength) return 0;
1572
+ posMapping[p] = output->length;
1573
+ memcpy(&output->chars[output->length], &replacements[k + 1],
1574
+ l * CHARSIZE);
1575
+ output->length += l;
1576
+ lastPos = k;
1577
+ lastRep = rep;
1578
+ break;
1579
+ }
1580
+ rep++;
1581
+ k += replacements[k];
1582
+ }
1583
+ }
1584
+ return p;
1585
+ }
1586
+
1587
+ static int
1588
+ back_passDoTest(const TranslationTableHeader *table, int pos, const InString *input,
1589
+ TranslationTableOpcode currentOpcode, const TranslationTableRule *currentRule,
1590
+ const widechar **passInstructions, int *passIC, PassRuleMatch *match) {
1591
+ int k;
1592
+ int m;
1593
+ int notOperator = 0;
1594
+ TranslationTableCharacterAttributes attributes;
1595
+ *passInstructions = &currentRule->charsdots[currentRule->charslen];
1596
+ *passIC = 0;
1597
+ match->startMatch = match->endMatch = pos;
1598
+ match->startReplace = -1;
1599
+ if (currentOpcode == CTO_Correct)
1600
+ m = 0;
1601
+ else
1602
+ m = 1;
1603
+ while (*passIC < currentRule->dotslen) {
1604
+ int itsTrue = 1;
1605
+ if (pos > input->length) return 0;
1606
+ switch ((*passInstructions)[*passIC]) {
1607
+ case pass_first:
1608
+ if (pos != 0) itsTrue = 0;
1609
+ (*passIC)++;
1610
+ break;
1611
+ case pass_last:
1612
+ if (pos != input->length) itsTrue = 0;
1613
+ (*passIC)++;
1614
+ break;
1615
+ case pass_lookback:
1616
+ pos -= (*passInstructions)[*passIC + 1];
1617
+ if (pos < 0) {
1618
+ pos = 0;
1619
+ itsTrue = 0;
1620
+ }
1621
+ *passIC += 2;
1622
+ break;
1623
+ case pass_not:
1624
+ notOperator = !notOperator;
1625
+ (*passIC)++;
1626
+ continue;
1627
+ case pass_string:
1628
+ case pass_dots:
1629
+ itsTrue = matchCurrentInput(input, pos, *passInstructions, *passIC);
1630
+ pos += (*passInstructions)[*passIC + 1];
1631
+ *passIC += (*passInstructions)[*passIC + 1] + 2;
1632
+ break;
1633
+ case pass_startReplace:
1634
+ match->startReplace = pos;
1635
+ (*passIC)++;
1636
+ break;
1637
+ case pass_endReplace:
1638
+ match->endReplace = pos;
1639
+ (*passIC)++;
1640
+ break;
1641
+ case pass_attributes:
1642
+ attributes = (*passInstructions)[*passIC + 1];
1643
+ attributes <<= 16;
1644
+ attributes |= (*passInstructions)[*passIC + 2];
1645
+ attributes <<= 16;
1646
+ attributes |= (*passInstructions)[*passIC + 3];
1647
+ attributes <<= 16;
1648
+ attributes |= (*passInstructions)[*passIC + 4];
1649
+ for (k = 0; k < (*passInstructions)[*passIC + 5]; k++) {
1650
+ if (pos >= input->length) {
1651
+ itsTrue = 0;
1652
+ break;
1653
+ }
1654
+ if (!((m ? getDots(input->chars[pos], table)
1655
+ : getChar(input->chars[pos], table))
1656
+ ->attributes &
1657
+ attributes)) {
1658
+ itsTrue = 0;
1659
+ break;
1660
+ }
1661
+ pos++;
1662
+ }
1663
+ if (itsTrue) {
1664
+ for (k = (*passInstructions)[*passIC + 5];
1665
+ k < (*passInstructions)[*passIC + 6] && pos < input->length;
1666
+ k++) {
1667
+ if (!((m ? getDots(input->chars[pos], table)
1668
+ : getChar(input->chars[pos], table))
1669
+ ->attributes &
1670
+ attributes))
1671
+ break;
1672
+ pos++;
1673
+ }
1674
+ }
1675
+ *passIC += 7;
1676
+ break;
1677
+ case pass_swap:
1678
+ itsTrue = back_swapTest(table, input, &pos, *passInstructions, *passIC);
1679
+ *passIC += 5;
1680
+ break;
1681
+ case pass_endTest: {
1682
+ (*passIC)++;
1683
+ match->endMatch = pos;
1684
+ if (match->startReplace == -1) {
1685
+ match->startReplace = match->startMatch;
1686
+ match->endReplace = match->endMatch;
1687
+ }
1688
+ return 1;
1689
+ break;
1690
+ }
1691
+ default:
1692
+ if (_lou_handlePassVariableTest(*passInstructions, passIC, &itsTrue)) break;
1693
+ return 0;
1694
+ }
1695
+ if ((!notOperator && !itsTrue) || (notOperator && itsTrue)) return 0;
1696
+ notOperator = 0;
1697
+ }
1698
+ return 0;
1699
+ }
1700
+
1701
+ static int
1702
+ copyCharacters(int from, int to, const TranslationTableHeader *table, int mode,
1703
+ const InString *input, OutString *output, int *posMapping, int *cursorPosition,
1704
+ int *cursorStatus, TranslationContext *ctx,
1705
+ TranslationTableOpcode currentOpcode) {
1706
+ if (currentOpcode == CTO_Context) {
1707
+ while (from < to) {
1708
+ if (!putCharacter(input->chars[from], table, from, mode, input, output,
1709
+ posMapping, cursorPosition, cursorStatus, ctx))
1710
+ return 0;
1711
+ from++;
1712
+ }
1713
+ } else {
1714
+ if (to > from) {
1715
+ if ((output->length + to - from) > output->maxlength) return 0;
1716
+ while (to > from) {
1717
+ posMapping[from] = output->length;
1718
+ output->chars[output->length] = input->chars[from];
1719
+ output->length++;
1720
+ from++;
1721
+ }
1722
+ }
1723
+ }
1724
+
1725
+ return 1;
1726
+ }
1727
+
1728
+ static int
1729
+ back_passDoAction(const TranslationTableHeader *table, int *pos, int mode,
1730
+ const InString *input, OutString *output, int *posMapping, int *cursorPosition,
1731
+ int *cursorStatus, TranslationContext *ctx, TranslationTableOpcode currentOpcode,
1732
+ const TranslationTableRule *currentRule, const widechar *passInstructions,
1733
+ int passIC, PassRuleMatch match) {
1734
+ int k;
1735
+ int destStartMatch = output->length;
1736
+ int destStartReplace;
1737
+ int newPos = match.endReplace;
1738
+
1739
+ if (!copyCharacters(match.startMatch, match.startReplace, table, mode, input, output,
1740
+ posMapping, cursorPosition, cursorStatus, ctx, currentOpcode))
1741
+ return 0;
1742
+ destStartReplace = output->length;
1743
+
1744
+ for (k = match.startReplace; k < match.endReplace; k++)
1745
+ posMapping[k] = output->length;
1746
+ while (passIC < currentRule->dotslen) switch (passInstructions[passIC]) {
1747
+ case pass_string:
1748
+ case pass_dots:
1749
+ if ((output->length + passInstructions[passIC + 1]) > output->maxlength)
1750
+ return 0;
1751
+ memcpy(&output->chars[output->length], &passInstructions[passIC + 2],
1752
+ passInstructions[passIC + 1] * sizeof(*output->chars));
1753
+ output->length += passInstructions[passIC + 1];
1754
+ passIC += passInstructions[passIC + 1] + 2;
1755
+ break;
1756
+ case pass_swap:
1757
+ if (!back_swapReplace(match.startReplace, match.endReplace, table, input,
1758
+ output, posMapping, passInstructions, passIC))
1759
+ return 0;
1760
+ passIC += 3;
1761
+ break;
1762
+ case pass_omit:
1763
+ passIC++;
1764
+ break;
1765
+ case pass_copy: {
1766
+ int count = destStartReplace - destStartMatch;
1767
+ if (count > 0) {
1768
+ memmove(&output->chars[destStartMatch], &output->chars[destStartReplace],
1769
+ (output->length - destStartReplace) * sizeof(*output->chars));
1770
+ output->length -= count;
1771
+ destStartReplace = destStartMatch;
1772
+ }
1773
+ }
1774
+
1775
+ if (!copyCharacters(match.startReplace, match.endReplace, table, mode, input,
1776
+ output, posMapping, cursorPosition, cursorStatus, ctx,
1777
+ currentOpcode))
1778
+ return 0;
1779
+ newPos = match.endMatch;
1780
+ passIC++;
1781
+ break;
1782
+ default:
1783
+ if (_lou_handlePassVariableAction(passInstructions, &passIC)) break;
1784
+ return 0;
1785
+ }
1786
+ *pos = newPos;
1787
+ return 1;
1788
+ }
1789
+
1790
+ static void
1791
+ passSelectRule(const TranslationTableHeader *table, int pos, int currentPass,
1792
+ const InString *input, TranslationTableOpcode *currentOpcode,
1793
+ const TranslationTableRule **currentRule, const widechar **passInstructions,
1794
+ int *passIC, PassRuleMatch *match) {
1795
+ if (!findBackPassRule(table, pos, currentPass, input, currentOpcode, currentRule,
1796
+ passInstructions, passIC, match)) {
1797
+ *currentOpcode = CTO_Always;
1798
+ }
1799
+ }
1800
+
1801
+ static int
1802
+ translatePass(const TranslationTableHeader *table, int mode, int currentPass,
1803
+ const InString *input, OutString *output, int *posMapping, int *realInlen,
1804
+ int *cursorPosition, int *cursorStatus, const TranslationTableRule **appliedRules,
1805
+ int *appliedRulesCount, int maxAppliedRules) {
1806
+ int pos;
1807
+ int posIncremented = 1;
1808
+ TranslationContext ctx = { .nextUpper = 0,
1809
+ .allUpper = 0,
1810
+ .allUpperPhrase = 0,
1811
+ .itsANumber = 0,
1812
+ .noContractMode = NO_CONTRACT_OFF };
1813
+ pos = output->length = 0;
1814
+ _lou_resetPassVariables();
1815
+ while (pos < input->length) { /* the main multipass translation loop */
1816
+ int posBefore = pos;
1817
+ TranslationTableOpcode currentOpcode;
1818
+ const TranslationTableRule *currentRule; /* pointer to current rule in table */
1819
+ const widechar *passInstructions;
1820
+ int passIC; /* Instruction counter */
1821
+ PassRuleMatch patternMatch;
1822
+ if (!posIncremented)
1823
+ currentOpcode = CTO_Always;
1824
+ else
1825
+ passSelectRule(table, pos, currentPass, input, &currentOpcode, &currentRule,
1826
+ &passInstructions, &passIC, &patternMatch);
1827
+ switch (currentOpcode) {
1828
+ case CTO_Pass2:
1829
+ case CTO_Pass3:
1830
+ case CTO_Pass4:
1831
+ if (appliedRules != NULL && *appliedRulesCount < maxAppliedRules)
1832
+ appliedRules[(*appliedRulesCount)++] = currentRule;
1833
+ if (!back_passDoAction(table, &pos, mode, input, output, posMapping,
1834
+ cursorPosition, cursorStatus, &ctx, currentOpcode, currentRule,
1835
+ passInstructions, passIC, patternMatch))
1836
+ goto failure;
1837
+ break;
1838
+ case CTO_Always:
1839
+ if ((output->length + 1) > output->maxlength) goto failure;
1840
+ posMapping[pos] = output->length;
1841
+ output->chars[(output->length)++] = input->chars[pos++];
1842
+ break;
1843
+ default:
1844
+ goto failure;
1845
+ }
1846
+ posIncremented = pos > posBefore;
1847
+ }
1848
+ failure:
1849
+ if (pos < input->length) {
1850
+ while (checkDotsAttr(input->chars[pos], CTC_Space, table))
1851
+ if (++pos == input->length) break;
1852
+ }
1853
+ *realInlen = pos;
1854
+ return 1;
1855
+ }