aboutsummaryrefslogtreecommitdiffstats
path: root/util/alevt/lang.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/alevt/lang.c')
-rw-r--r--util/alevt/lang.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/util/alevt/lang.c b/util/alevt/lang.c
new file mode 100644
index 0000000..3a49307
--- /dev/null
+++ b/util/alevt/lang.c
@@ -0,0 +1,393 @@
+#include <string.h>
+#include <ctype.h>
+#include "misc.h"
+#include "vt.h"
+#include "lang.h"
+
+int latin1 = -1;
+
+
+static u8 lang_char[256];
+static u8 lang_chars[1+8+8][16] =
+{
+ { 0, 0x23,0x24,0x40,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x7b,0x7c,0x7d,0x7e },
+
+ // for latin-1 font
+ // English (100%)
+ { 0, '£', '$', '@', '«', '½', '»', '¬', '#', '­', '¼', '¦', '¾', '÷' },
+ // German (100%)
+ { 0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', '°', 'ä', 'ö', 'ü', 'ß' },
+ // Swedish/Finnish/Hungarian (100%)
+ { 0, '#', '¤', 'É', 'Ä', 'Ö', 'Å', 'Ü', '_', 'é', 'ä', 'ö', 'å', 'ü' },
+ // Italian (100%)
+ { 0, '£', '$', 'é', '°', 'ç', '»', '¬', '#', 'ù', 'à', 'ò', 'è', 'ì' },
+ // French (100%)
+ { 0, 'é', 'ï', 'à', 'ë', 'ê', 'ù', 'î', '#', 'è', 'â', 'ô', 'û', 'ç' },
+ // Portuguese/Spanish (100%)
+ { 0, 'ç', '$', '¡', 'á', 'é', 'í', 'ó', 'ú', '¿', 'ü', 'ñ', 'è', 'à' },
+ // Czech/Slovak (60%)
+ { 0, '#', 'u', 'c', 't', 'z', 'ý', 'í', 'r', 'é', 'á', 'e', 'ú', 's' },
+ // reserved (English mapping)
+ { 0, '£', '$', '@', '«', '½', '»', '¬', '#', '­', '¼', '¦', '¾', '÷' },
+
+ // for latin-2 font
+ // Polish (100%)
+ { 0, '#', 'ñ', '±', '¯', '¦', '£', 'æ', 'ó', 'ê', '¿', '¶', '³', '¼' },
+ // German (100%)
+ { 0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', '°', 'ä', 'ö', 'ü', 'ß' },
+ // Estonian (100%)
+ { 0, '#', 'õ', '©', 'Ä', 'Ö', '®', 'Ü', 'Õ', '¹', 'ä', 'ö', '¾', 'ü' },
+ // Lettish/Lithuanian (90%)
+ { 0, '#', '$', '©', 'ë', 'ê', '®', 'è', 'ü', '¹', '±', 'u', '¾', 'i' },
+ // French (90%)
+ { 0, 'é', 'i', 'a', 'ë', 'ì', 'u', 'î', '#', 'e', 'â', 'ô', 'u', 'ç' },
+ // Serbian/Croation/Slovenian (100%)
+ { 0, '#', 'Ë', 'È', 'Æ', '®', 'Ð', '©', 'ë', 'è', 'æ', '®', 'ð', '¹' },
+ // Czech/Slovak (100%)
+ { 0, '#', 'ù', 'è', '»', '¾', 'ý', 'í', 'ø', 'é', 'á', 'ì', 'ú', '¹' },
+ // Rumanian (95%)
+ { 0, '#', '¢', 'Þ', 'Â', 'ª', 'Ã', 'Î', 'i', 'þ', 'â', 'º', 'ã', 'î' },
+};
+
+/* Yankable latin charset :-)
+ !"#$%&'()*+,-./0123456789:;<=>?
+ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
+ `abcdefghijklmnopqrstuvwxyz{|}~
+ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿
+ ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
+ àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+*/
+
+
+static struct mark { u8 *g0, *latin1, *latin2; } marks[16] =
+{
+ /* none */ { "#",
+ "¤",
+ "$" },
+ /* grave - ` */ { " aeiouAEIOU",
+ "`àèìòùÀÈÌÒÙ",
+ "`aeiouAEIOU" },
+ /* acute - ' */ { " aceilnorsuyzACEILNORSUYZ",
+ "'ácéílnórsúýzÁCÉÍLNÓRSÚÝZ",
+ "'áæéíåñóà¶úý¼ÁÆÉÍÅÑÓÀ¦Úݬ" },
+ /* cirumflex - ^ */ { " aeiouAEIOU",
+ "^âêîôûÂÊÎÔÛ",
+ "^âeîôuÂEÎÔU" },
+ /* tilde - ~ */ { " anoANO",
+ "~ãñõÃÑÕ",
+ "~anoANO" },
+ /* ??? - ¯ */ { "",
+ "",
+ "" },
+ /* breve - u */ { "aA",
+ "aA",
+ "ãÃ" },
+ /* abovedot - · */ { "zZ",
+ "zZ",
+ "¿¯" },
+ /* diaeresis ¨ */ { "aeiouAEIOU",
+ "äëïöüÄËÏÖÜ",
+ "äëiöüÄËIÖÜ" },
+ /* ??? - . */ { "",
+ "",
+ "" },
+ /* ringabove - ° */ { " auAU",
+ "°åuÅU",
+ "°aùAÙ" },
+ /* cedilla - ¸ */ { "cstCST",
+ "çstÇST",
+ "çºþǪÞ" },
+ /* ??? - _ */ { " ",
+ "_",
+ "_" },
+ /* dbl acute - " */ { " ouOU",
+ "\"ouOU",
+ "\"õûÕÛ" },
+ /* ogonek - \, */ { "aeAE",
+ "aeAE",
+ "±ê¡Ê" },
+ /* caron - v */ { "cdelnrstzCDELNRSTZ",
+ "cdelnrstzCDELNRSTZ",
+ "èïìµòø¹»¾ÈÏÌ¥ÒØ©«®" },
+};
+
+
+static u8 g2map_latin1[] =
+ /*0123456789abcdef*/
+ " ¡¢£$¥#§¤'\"« "
+ "°±²³×µ¶·÷'\"»¼½¾¿"
+ " `´^~ ¨.°¸_\" "
+ "_¹®© "
+ " ÆЪH ILLØ ºÞTNn"
+ "Kædðhiillø ßþtn\x7f";
+
+
+static u8 g2map_latin2[] =
+ /*0123456789abcdef*/
+ " icL$Y#§¤'\"< "
+ "° ×u ÷'\"> "
+ " `´^~ ¢ÿ¨.°¸_½²·"
+ "- RC "
+ " ÐaH iL£O opTNn"
+ "K ðdhiil³o ßptn\x7f";
+
+
+void lang_init(void)
+{
+ int i;
+
+ memset(lang_char, 0, sizeof(lang_char));
+ for (i = 1; i <= 13; i++)
+ lang_char[lang_chars[0][i]] = i;
+}
+
+
+void conv2latin(u8 *p, int n, int lang)
+{
+ int c, gfx = 0, lat=0;
+
+ if ((latin1 == KOI8) && lang==12) { /* russian */
+ while (n--) {
+ c=*p;
+
+ if(c==0x1b) lat = !lat; /* ESC switches languages inside page */
+
+ if ( is_koi(c)) {
+ if (not gfx || (c & 0xa0) != 0x20) {
+ if(!lat) conv2koi8(p);
+ }
+ }
+ else if ((c & 0xe8) == 0)
+ gfx = c & 0x10;
+ p++;
+ }
+ }
+else if ((latin1 == GREEK) && lang==15) { /* Hellas */
+ while (n--) {
+ c=*p;
+
+ if(c==0x1b) lat = !lat; /* ESC switches languages inside page */
+
+ if ( is_greek(c)) {
+ if (not gfx || (c & 0xa0) != 0x20) {
+ if(!lat) conv2greek(p);
+ }
+ }
+ else if ((c & 0xe8) == 0)
+ gfx = c & 0x10;
+ p++;
+ }
+ }
+
+ else {
+ while (n--)
+ {
+ if (lang_char[c = *p])
+ {
+ if (not gfx || (c & 0xa0) != 0x20)
+ *p = lang_chars[lang + 1][lang_char[c]];
+ }
+ else if ((c & 0xe8) == 0)
+ gfx = c & 0x10;
+ p++;
+ }
+ }
+}
+
+
+/* check for Greek chars - needs locale iso8859-7 set */
+int is_greek(int c)
+{
+ if( isalpha(c | 0x80)) return 1;
+ return 0;
+}
+
+
+/* check for russian chars - needs locale KOI8-R set */
+int is_koi(int c)
+{
+ if( isalpha(c | 0x80)) return 1;
+ if( c=='&' ) return 1;
+ return 0;
+}
+
+
+/* teletext to koi8-r conversion */
+void conv2koi8(u8 *p)
+{
+ u8 c;
+ static u8 l2koi[]={
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9,
+ 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3,
+ 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFF, 0xFA, 0xFB, 0xFC, 0xFD,
+ 0xFE, 0xF9, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1,
+ 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
+ 0xDC, 0xDD, 0xDE, 0xDF
+ };
+
+ c= *p;
+ if ( (c >= 0x40) && (c <= 0x7f)) *p=l2koi[(c & 0x7f) - 0x40];
+ if (c=='&') *p='Ù';
+}
+
+
+/* teletext to iso8859-7 conversion */
+void conv2greek(u8 *p)
+{
+ u8 c;
+ static u8 l2greek[]={
+/* 1 @ 0x40->ú*/0xc0,
+/* 2 A 0x41->Á*/0xc1,
+/* 3 B 0x42->Â*/0xc2,
+/* 4 C 0x43->Ã*/0xc3,
+/* 5 D 0x44->Ä*/0xc4,
+/* 6 E 0x45->Å*/0xc5,
+/* 7 F 0x46->Æ*/0xc6,
+/* 8 G 0x47->Ç*/0xc7,
+/* 9 H 0x48->È*/0xc8,
+/*10 I 0x49->É*/0xc9,
+/*11 J 0x4a->Ê*/0xca,
+/*12 K 0x4b->Ë*/0xcb,
+/*13 L 0x4c->Ì*/0xcc,
+/*14 M 0x4d->Í*/0xcd,
+/*15 N 0x4e->Î*/0xce,
+/*16 O 0x4f->Ï*/0xcf,
+/*17 P 0x50->Ð*/0xd0,
+/*18 Q 0x51->Ñ*/0xd1,
+/*19 R 0x52->?*/0x52,
+/*20 S 0x53->Ó*/0xd3,
+/*21 T 0x54->Ô*/0xd4,
+/*22 U 0x55->Õ*/0xd5,
+/*23 V 0x56->Ö*/0xd6,
+/*24 W 0x57->÷*/0xd7,
+/*25 X 0x58->Ø*/0xd8,
+/*26 Y 0x59->Ù*/0xd9,
+/*27 Z 0x5a->?*/0x5a,
+/*28 [ 0x5b->?*/0x5b,
+/*!29 \ 0x5c->Ü*/0xdc,
+/*!30 ] 0x5d->Ý*/0xdd,
+/*!31 ^ 0x5e->Þ*/0xde,
+/*!32 _ 0x5f->ß*/0xdf,
+/*33 ` 0x60->?*/0x60,
+/*!34 a 0x61->á*/0xe1,
+/*!35 b 0x62->â*/0xe2,
+/*!36 c 0x63->ã*/0xe3,
+/*!37 d 0x64->ä*/0xe4,
+/*!38 e 0x65->å*/0xe5,
+/*!39 f 0x66->æ*/0xe6,
+/*!40 g 0x67->ç*/0xe7,
+/*!41 h 0x68->è*/0xe8,
+/*!42 i 0x69->é*/0xe9,
+/*!43 j 0x6a->ê*/0xea,
+/*!44 k 0x6b->ë*/0xeb,
+/*!45 l 0x6c->ì*/0xec,
+/*!46 m 0x6d->í*/0xed,
+/*!47 n 0x6e->î*/0xee,
+/*!48 o 0x6f->ï*/0xef,
+/*!49 p 0x70->ð*/0xf0,
+/*!50 q 0x71->ñ*/0xf1,
+/*!51 r 0x72->ò*/0xf2,
+/*!52 s 0x73->ó*/0xf3,
+/*!53 t 0x74->ô*/0xf4,
+/*!54 u 0x75->õ*/0xf5,
+/*!55 v 0x76->ö*/0xf6,
+/*!56 w 0x77->÷*/0xf7,
+/*!57 x 0x78->ø*/0xf8,
+/*!58 y 0x79->ù*/0xf9,
+/*59 z 0x7a->ú(ìå ôüíï)*/0xc0,
+/*60 { 0x7b->?*/0x7b,
+/*!61 | 0x7c->ü*/0xfc,
+/*!62 } 0x7d->ý*/0xfd,
+/*!63 ~ 0x7e->þ*/0xfe,
+/*64 0x7f->?*/0x7f
+ };
+ c= *p;
+ if ( (c >= 0x40) && (c <= 0x7f)) *p=l2greek[(c & 0x7f) - 0x40];
+}
+
+
+void init_enhance(struct enhance *eh)
+{
+ eh->next_des = 0;
+}
+
+
+void add_enhance(struct enhance *eh, int dcode, u32 *t)
+{
+
+ if (dcode == eh->next_des)
+ {
+ memcpy(eh->trip + dcode * 13, t, 13 * sizeof(*t));
+ eh->next_des++;
+ }
+ else
+ eh->next_des = -1;
+}
+
+
+void enhance(struct enhance *eh, struct vt_page *vtp)
+{
+ int row = 0;
+ u32 *p, *e;
+
+ if (eh->next_des < 1)
+ return;
+
+ for (p = eh->trip, e = p + eh->next_des * 13; p < e; p++)
+ if (*p % 2048 != 2047)
+ {
+ int adr = *p % 64;
+ int mode = *p / 64 % 32;
+ int data = *p / 2048 % 128;
+
+ if (adr < 40)
+ {
+ // col functions
+ switch (mode)
+ {
+ case 15: // char from G2 set
+ if (adr < W && row < H)
+ if (latin1==LATIN1)
+ vtp->data[row][adr] = g2map_latin1[data-32];
+ else if (latin1==LATIN2)
+ vtp->data[row][adr] = g2map_latin2[data-32];
+ break;
+ case 16 ... 31: // char from G0 set with diacritical mark
+ if (adr < W && row < H)
+ {
+ struct mark *mark = marks + (mode - 16);
+ u8 *x;
+
+ if (x = strchr(mark->g0, data))
+ if (latin1==LATIN1)
+ data = mark->latin1[x - mark->g0];
+ else if (latin1==LATIN2)
+ data = mark->latin2[x - mark->g0];
+ vtp->data[row][adr] = data;
+ }
+ break;
+ }
+ }
+ else
+ {
+ // row functions
+ if ((adr -= 40) == 0)
+ adr = 24;
+
+ switch (mode)
+ {
+ case 1: // full row color
+ row = adr;
+ break;
+ case 4: // set active position
+ row = adr;
+ break;
+ case 7: // address row 0 (+ full row color)
+ if (adr == 23)
+ row = 0;
+ break;
+ }
+ }
+ }
+}