lang.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include <string.h>
  2. #include <ctype.h>
  3. #include "misc.h"
  4. #include "vt.h"
  5. #include "lang.h"
  6. int latin1 = -1;
  7. static u8 lang_char[256];
  8. static u8 lang_chars[1+8+8][16] =
  9. {
  10. { 0, 0x23,0x24,0x40,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x7b,0x7c,0x7d,0x7e },
  11. // for latin-1 font
  12. // English (100%)
  13. { 0, '£', '$', '@', '«', '½', '»', '¬', '#', '­', '¼', '¦', '¾', '÷' },
  14. // German (100%)
  15. { 0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', '°', 'ä', 'ö', 'ü', 'ß' },
  16. // Swedish/Finnish/Hungarian (100%)
  17. { 0, '#', '¤', 'É', 'Ä', 'Ö', 'Å', 'Ü', '_', 'é', 'ä', 'ö', 'å', 'ü' },
  18. // Italian (100%)
  19. { 0, '£', '$', 'é', '°', 'ç', '»', '¬', '#', 'ù', 'à', 'ò', 'è', 'ì' },
  20. // French (100%)
  21. { 0, 'é', 'ï', 'à', 'ë', 'ê', 'ù', 'î', '#', 'è', 'â', 'ô', 'û', 'ç' },
  22. // Portuguese/Spanish (100%)
  23. { 0, 'ç', '$', '¡', 'á', 'é', 'í', 'ó', 'ú', '¿', 'ü', 'ñ', 'è', 'à' },
  24. // Czech/Slovak (60%)
  25. { 0, '#', 'u', 'c', 't', 'z', 'ý', 'í', 'r', 'é', 'á', 'e', 'ú', 's' },
  26. // reserved (English mapping)
  27. { 0, '£', '$', '@', '«', '½', '»', '¬', '#', '­', '¼', '¦', '¾', '÷' },
  28. // for latin-2 font
  29. // Polish (100%)
  30. { 0, '#', 'ñ', '±', '¯', '¦', '£', 'æ', 'ó', 'ê', '¿', '¶', '³', '¼' },
  31. // German (100%)
  32. { 0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', '°', 'ä', 'ö', 'ü', 'ß' },
  33. // Estonian (100%)
  34. { 0, '#', 'õ', '©', 'Ä', 'Ö', '®', 'Ü', 'Õ', '¹', 'ä', 'ö', '¾', 'ü' },
  35. // Lettish/Lithuanian (90%)
  36. { 0, '#', '$', '©', 'ë', 'ê', '®', 'è', 'ü', '¹', '±', 'u', '¾', 'i' },
  37. // French (90%)
  38. { 0, 'é', 'i', 'a', 'ë', 'ì', 'u', 'î', '#', 'e', 'â', 'ô', 'u', 'ç' },
  39. // Serbian/Croation/Slovenian (100%)
  40. { 0, '#', 'Ë', 'È', 'Æ', '®', 'Ð', '©', 'ë', 'è', 'æ', '®', 'ð', '¹' },
  41. // Czech/Slovak (100%)
  42. { 0, '#', 'ù', 'è', '»', '¾', 'ý', 'í', 'ø', 'é', 'á', 'ì', 'ú', '¹' },
  43. // Rumanian (95%)
  44. { 0, '#', '¢', 'Þ', 'Â', 'ª', 'Ã', 'Î', 'i', 'þ', 'â', 'º', 'ã', 'î' },
  45. };
  46. /* Yankable latin charset :-)
  47. !"#$%&'()*+,-./0123456789:;<=>?
  48. @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
  49. `abcdefghijklmnopqrstuvwxyz{|}~
  50. ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿
  51. ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß
  52. àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
  53. */
  54. static struct mark { u8 *g0, *latin1, *latin2; } marks[16] =
  55. {
  56. /* none */ { "#",
  57. "¤",
  58. "$" },
  59. /* grave - ` */ { " aeiouAEIOU",
  60. "`àèìòùÀÈÌÒÙ",
  61. "`aeiouAEIOU" },
  62. /* acute - ' */ { " aceilnorsuyzACEILNORSUYZ",
  63. "'ácéílnórsúýzÁCÉÍLNÓRSÚÝZ",
  64. "'áæéíåñóà¶úý¼ÁÆÉÍÅÑÓÀ¦Úݬ" },
  65. /* cirumflex - ^ */ { " aeiouAEIOU",
  66. "^âêîôûÂÊÎÔÛ",
  67. "^âeîôuÂEÎÔU" },
  68. /* tilde - ~ */ { " anoANO",
  69. "~ãñõÃÑÕ",
  70. "~anoANO" },
  71. /* ??? - ¯ */ { "",
  72. "",
  73. "" },
  74. /* breve - u */ { "aA",
  75. "aA",
  76. "ãÃ" },
  77. /* abovedot - · */ { "zZ",
  78. "zZ",
  79. "¿¯" },
  80. /* diaeresis ¨ */ { "aeiouAEIOU",
  81. "äëïöüÄËÏÖÜ",
  82. "äëiöüÄËIÖÜ" },
  83. /* ??? - . */ { "",
  84. "",
  85. "" },
  86. /* ringabove - ° */ { " auAU",
  87. "°åuÅU",
  88. "°aùAÙ" },
  89. /* cedilla - ¸ */ { "cstCST",
  90. "çstÇST",
  91. "çºþǪÞ" },
  92. /* ??? - _ */ { " ",
  93. "_",
  94. "_" },
  95. /* dbl acute - " */ { " ouOU",
  96. "\"ouOU",
  97. "\"õûÕÛ" },
  98. /* ogonek - \, */ { "aeAE",
  99. "aeAE",
  100. "±ê¡Ê" },
  101. /* caron - v */ { "cdelnrstzCDELNRSTZ",
  102. "cdelnrstzCDELNRSTZ",
  103. "èïìµòø¹»¾ÈÏÌ¥ÒØ©«®" },
  104. };
  105. static u8 g2map_latin1[] =
  106. /*0123456789abcdef*/
  107. " ¡¢£$¥#§¤'\"« "
  108. "°±²³×µ¶·÷'\"»¼½¾¿"
  109. " `´^~ ¨.°¸_\" "
  110. "_¹®© "
  111. " ÆÐªH ILLØ ºÞTNn"
  112. "Kædðhiillø ßþtn\x7f";
  113. static u8 g2map_latin2[] =
  114. /*0123456789abcdef*/
  115. " icL$Y#§¤'\"< "
  116. "° ×u ÷'\"> "
  117. " `´^~ ¢ÿ¨.°¸_½²·"
  118. "- RC "
  119. " ÐaH iL£O opTNn"
  120. "K ðdhiil³o ßptn\x7f";
  121. void lang_init(void)
  122. {
  123. int i;
  124. memset(lang_char, 0, sizeof(lang_char));
  125. for (i = 1; i <= 13; i++)
  126. lang_char[lang_chars[0][i]] = i;
  127. }
  128. void conv2latin(u8 *p, int n, int lang)
  129. {
  130. int c, gfx = 0, lat=0;
  131. if ((latin1 == KOI8) && lang==12) { /* russian */
  132. while (n--) {
  133. c=*p;
  134. if(c==0x1b) lat = !lat; /* ESC switches languages inside page */
  135. if ( is_koi(c)) {
  136. if (not gfx || (c & 0xa0) != 0x20) {
  137. if(!lat) conv2koi8(p);
  138. }
  139. }
  140. else if ((c & 0xe8) == 0)
  141. gfx = c & 0x10;
  142. p++;
  143. }
  144. }
  145. else if ((latin1 == GREEK) && lang==15) { /* Hellas */
  146. while (n--) {
  147. c=*p;
  148. if(c==0x1b) lat = !lat; /* ESC switches languages inside page */
  149. if ( is_greek(c)) {
  150. if (not gfx || (c & 0xa0) != 0x20) {
  151. if(!lat) conv2greek(p);
  152. }
  153. }
  154. else if ((c & 0xe8) == 0)
  155. gfx = c & 0x10;
  156. p++;
  157. }
  158. }
  159. else {
  160. while (n--)
  161. {
  162. if (lang_char[c = *p])
  163. {
  164. if (not gfx || (c & 0xa0) != 0x20)
  165. *p = lang_chars[lang + 1][lang_char[c]];
  166. }
  167. else if ((c & 0xe8) == 0)
  168. gfx = c & 0x10;
  169. p++;
  170. }
  171. }
  172. }
  173. /* check for Greek chars - needs locale iso8859-7 set */
  174. int is_greek(int c)
  175. {
  176. if( isalpha(c | 0x80)) return 1;
  177. return 0;
  178. }
  179. /* check for russian chars - needs locale KOI8-R set */
  180. int is_koi(int c)
  181. {
  182. if( isalpha(c | 0x80)) return 1;
  183. if( c=='&' ) return 1;
  184. return 0;
  185. }
  186. /* teletext to koi8-r conversion */
  187. void conv2koi8(u8 *p)
  188. {
  189. u8 c;
  190. static u8 l2koi[]={
  191. 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
  192. 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
  193. 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFF, 0xFA, 0xFB, 0xFC, 0xFD,
  194. 0xFE, 0xF9, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
  195. 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1,
  196. 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
  197. 0xDC, 0xDD, 0xDE, 0xDF
  198. };
  199. c= *p;
  200. if ( (c >= 0x40) && (c <= 0x7f)) *p=l2koi[(c & 0x7f) - 0x40];
  201. if (c=='&') *p='Ù';
  202. }
  203. /* teletext to iso8859-7 conversion */
  204. void conv2greek(u8 *p)
  205. {
  206. u8 c;
  207. static u8 l2greek[]={
  208. /* 1 @ 0x40->ú*/0xc0,
  209. /* 2 A 0x41->Á*/0xc1,
  210. /* 3 B 0x42->Â*/0xc2,
  211. /* 4 C 0x43->Ã*/0xc3,
  212. /* 5 D 0x44->Ä*/0xc4,
  213. /* 6 E 0x45->Å*/0xc5,
  214. /* 7 F 0x46->Æ*/0xc6,
  215. /* 8 G 0x47->Ç*/0xc7,
  216. /* 9 H 0x48->È*/0xc8,
  217. /*10 I 0x49->É*/0xc9,
  218. /*11 J 0x4a->Ê*/0xca,
  219. /*12 K 0x4b->Ë*/0xcb,
  220. /*13 L 0x4c->Ì*/0xcc,
  221. /*14 M 0x4d->Í*/0xcd,
  222. /*15 N 0x4e->Î*/0xce,
  223. /*16 O 0x4f->Ï*/0xcf,
  224. /*17 P 0x50->Ð*/0xd0,
  225. /*18 Q 0x51->Ñ*/0xd1,
  226. /*19 R 0x52->?*/0x52,
  227. /*20 S 0x53->Ó*/0xd3,
  228. /*21 T 0x54->Ô*/0xd4,
  229. /*22 U 0x55->Õ*/0xd5,
  230. /*23 V 0x56->Ö*/0xd6,
  231. /*24 W 0x57->÷*/0xd7,
  232. /*25 X 0x58->Ø*/0xd8,
  233. /*26 Y 0x59->Ù*/0xd9,
  234. /*27 Z 0x5a->?*/0x5a,
  235. /*28 [ 0x5b->?*/0x5b,
  236. /*!29 \ 0x5c->Ü*/0xdc,
  237. /*!30 ] 0x5d->Ý*/0xdd,
  238. /*!31 ^ 0x5e->Þ*/0xde,
  239. /*!32 _ 0x5f->ß*/0xdf,
  240. /*33 ` 0x60->?*/0x60,
  241. /*!34 a 0x61->á*/0xe1,
  242. /*!35 b 0x62->â*/0xe2,
  243. /*!36 c 0x63->ã*/0xe3,
  244. /*!37 d 0x64->ä*/0xe4,
  245. /*!38 e 0x65->å*/0xe5,
  246. /*!39 f 0x66->æ*/0xe6,
  247. /*!40 g 0x67->ç*/0xe7,
  248. /*!41 h 0x68->è*/0xe8,
  249. /*!42 i 0x69->é*/0xe9,
  250. /*!43 j 0x6a->ê*/0xea,
  251. /*!44 k 0x6b->ë*/0xeb,
  252. /*!45 l 0x6c->ì*/0xec,
  253. /*!46 m 0x6d->í*/0xed,
  254. /*!47 n 0x6e->î*/0xee,
  255. /*!48 o 0x6f->ï*/0xef,
  256. /*!49 p 0x70->ð*/0xf0,
  257. /*!50 q 0x71->ñ*/0xf1,
  258. /*!51 r 0x72->ò*/0xf2,
  259. /*!52 s 0x73->ó*/0xf3,
  260. /*!53 t 0x74->ô*/0xf4,
  261. /*!54 u 0x75->õ*/0xf5,
  262. /*!55 v 0x76->ö*/0xf6,
  263. /*!56 w 0x77->÷*/0xf7,
  264. /*!57 x 0x78->ø*/0xf8,
  265. /*!58 y 0x79->ù*/0xf9,
  266. /*59 z 0x7a->ú(ìå ôüíï)*/0xc0,
  267. /*60 { 0x7b->?*/0x7b,
  268. /*!61 | 0x7c->ü*/0xfc,
  269. /*!62 } 0x7d->ý*/0xfd,
  270. /*!63 ~ 0x7e->þ*/0xfe,
  271. /*64 0x7f->?*/0x7f
  272. };
  273. c= *p;
  274. if ( (c >= 0x40) && (c <= 0x7f)) *p=l2greek[(c & 0x7f) - 0x40];
  275. }
  276. void init_enhance(struct enhance *eh)
  277. {
  278. eh->next_des = 0;
  279. }
  280. void add_enhance(struct enhance *eh, int dcode, u32 *t)
  281. {
  282. if (dcode == eh->next_des)
  283. {
  284. memcpy(eh->trip + dcode * 13, t, 13 * sizeof(*t));
  285. eh->next_des++;
  286. }
  287. else
  288. eh->next_des = -1;
  289. }
  290. void enhance(struct enhance *eh, struct vt_page *vtp)
  291. {
  292. int row = 0;
  293. u32 *p, *e;
  294. if (eh->next_des < 1)
  295. return;
  296. for (p = eh->trip, e = p + eh->next_des * 13; p < e; p++)
  297. if (*p % 2048 != 2047)
  298. {
  299. int adr = *p % 64;
  300. int mode = *p / 64 % 32;
  301. int data = *p / 2048 % 128;
  302. if (adr < 40)
  303. {
  304. // col functions
  305. switch (mode)
  306. {
  307. case 15: // char from G2 set
  308. if (adr < W && row < H)
  309. if (latin1==LATIN1)
  310. vtp->data[row][adr] = g2map_latin1[data-32];
  311. else if (latin1==LATIN2)
  312. vtp->data[row][adr] = g2map_latin2[data-32];
  313. break;
  314. case 16 ... 31: // char from G0 set with diacritical mark
  315. if (adr < W && row < H)
  316. {
  317. struct mark *mark = marks + (mode - 16);
  318. u8 *x;
  319. if (x = strchr(mark->g0, data))
  320. if (latin1==LATIN1)
  321. data = mark->latin1[x - mark->g0];
  322. else if (latin1==LATIN2)
  323. data = mark->latin2[x - mark->g0];
  324. vtp->data[row][adr] = data;
  325. }
  326. break;
  327. }
  328. }
  329. else
  330. {
  331. // row functions
  332. if ((adr -= 40) == 0)
  333. adr = 24;
  334. switch (mode)
  335. {
  336. case 1: // full row color
  337. row = adr;
  338. break;
  339. case 4: // set active position
  340. row = adr;
  341. break;
  342. case 7: // address row 0 (+ full row color)
  343. if (adr == 23)
  344. row = 0;
  345. break;
  346. }
  347. }
  348. }
  349. }