root/drivers/char/consolemap.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_inverse_transl
  2. set_translate
  3. inverse_translate
  4. con_set_trans
  5. con_get_trans
  6. con_clear_unimap
  7. con_set_unimap
  8. con_get_unimap
  9. conv_uni_to_pc

   1 /*
   2  * consolemap.c
   3  *
   4  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
   5  * to font positions.
   6  *
   7  * aeb, 950210
   8  */
   9 
  10 #include <linux/kd.h>
  11 #include <linux/errno.h>
  12 #include <linux/mm.h>
  13 #include <linux/malloc.h>
  14 #include <asm/segment.h>
  15 #include "consolemap.h"
  16 
  17 static unsigned char * translations[] = {
  18 /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
  19 (unsigned char *)
  20         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  21         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
  22         " !\"#$%&'()*+,-./0123456789:;<=>?"
  23         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
  24         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
  25         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  26         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  27         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
  28         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
  29         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  30         "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
  31         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
  32         "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
  33 /* vt100 graphics */
  34 (unsigned char *)
  35         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  36         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
  37         " !\"#$%&'()*+,-./0123456789:;<=>?"
  38         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
  39         "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
  40         "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
  41         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  42         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  43         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
  44         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
  45         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  46         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
  47         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
  48         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
  49 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
  50 (unsigned char *)
  51         "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
  52         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
  53         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
  54         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
  55         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
  56         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
  57         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
  58         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
  59         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
  60         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
  61         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
  62         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
  63         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
  64         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
  65         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
  66         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
  67  /* USER: customizable mappings, initialized as the previous one (IBM) */
  68 (unsigned char *)
  69         "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
  70         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
  71         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
  72         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
  73         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
  74         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
  75         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
  76         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
  77         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
  78         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
  79         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
  80         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
  81         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
  82         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
  83         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
  84         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
  85 };
  86 
  87 /* the above mappings are not invertible - this is just a best effort */
  88 static unsigned char * inv_translate = NULL;
  89 static unsigned char inv_norm_transl[E_TABSZ];
  90 static unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
  91 
  92 static void set_inverse_transl(int i)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         int j;
  95         unsigned char *p = translations[i];
  96         unsigned char *q = inverse_translations[i];
  97 
  98         if (!q) {
  99                 /* slightly messy to avoid calling kmalloc too early */
 100                 q = inverse_translations[i] = ((i == NORM_MAP)
 101                         ? inv_norm_transl
 102                         : (unsigned char *) kmalloc(E_TABSZ, GFP_KERNEL));
 103                 if (!q)
 104                         return;
 105         }
 106         for (j=0; j<E_TABSZ; j++)
 107                 q[j] = 0;
 108         for (j=0; j<E_TABSZ; j++)
 109                 if (q[p[j]] < 32)       /* prefer '-' above SHY etc. */
 110                         q[p[j]] = j;
 111 }
 112 
 113 unsigned char *set_translate(int m)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         if (!inverse_translations[m])
 116                 set_inverse_transl(m);
 117         inv_translate = inverse_translations[m];
 118         return translations[m];
 119 }
 120 
 121 /*
 122  * Inverse translation is impossible for several reasons:
 123  * 1. The translation maps are not 1-1
 124  * 2. The text may have been written while a different translation map
 125  *    was active
 126  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
 127  */
 128 unsigned char inverse_translate(unsigned char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
 129         return ((inv_translate && inv_translate[c]) ? inv_translate[c] : c);
 130 }
 131 
 132 /*
 133  * Load customizable translation table
 134  * arg points to a 256 byte translation table.
 135  */
 136 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         int i;
 139         unsigned char *p = translations[USER_MAP];
 140 
 141         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
 142         if (i)
 143                 return i;
 144 
 145         for (i=0; i<E_TABSZ ; i++)
 146                 p[i] = get_fs_byte(arg+i);
 147         p[012] = p[014] = p[015] = p[033] = 0;
 148         set_inverse_transl(USER_MAP);
 149         return 0;
 150 }
 151 
 152 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         int i;
 155         unsigned char *p = translations[USER_MAP];
 156 
 157         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
 158         if (i)
 159                 return i;
 160 
 161         for (i=0; i<E_TABSZ ; i++) put_fs_byte(p[i],arg+i);
 162         return 0;
 163 }
 164 
 165 /*
 166  * Unicode -> current font conversion 
 167  *
 168  * A font has at most 512 chars, usually 256.
 169  * But one font position may represent several Unicode chars
 170  * (and moreover, hashtables work best when they are not too full),
 171  * so pick HASHSIZE somewhat larger than 512.
 172  * Since there are likely to be long consecutive stretches
 173  * (like U+0000 to U+00FF), HASHSTEP should not be too small.
 174  * Searches longer than MAXHASHLEVEL steps are refused, unless
 175  * requested explicitly.
 176  *
 177  * Note: no conversion tables are compiled in, so the user
 178  * must supply an explicit mapping herself. See kbd-0.90 (or an
 179  * earlier kernel version) for the default Unicode-to-PC mapping.
 180  * Usually, the mapping will be loaded simultaneously with the font.
 181  */
 182 
 183 #define HASHSIZE   641
 184 #define HASHSTEP   189          /* yields hashlevel = 3 initially */
 185 #define MAXHASHLEVEL 6
 186 static struct unipair hashtable[HASHSIZE];
 187 
 188 int hashtable_contents_valid = 0;       /* cleared by setfont */
 189 
 190 static unsigned int hashsize;
 191 static unsigned int hashstep;
 192 static unsigned int hashlevel;
 193 static unsigned int maxhashlevel;
 194 
 195 void
 196 con_clear_unimap(struct unimapinit *ui) {
     /* [previous][next][first][last][top][bottom][index][help] */
 197         int i;
 198 
 199         /* read advisory values for hash algorithm */
 200         hashsize = ui->advised_hashsize;
 201         if (hashsize < 256 || hashsize > HASHSIZE)
 202           hashsize = HASHSIZE;
 203         hashstep = (ui->advised_hashstep % hashsize);
 204         if (hashstep < 64)
 205           hashstep = HASHSTEP;
 206         maxhashlevel = ui->advised_hashlevel;
 207         if (!maxhashlevel)
 208           maxhashlevel = MAXHASHLEVEL;
 209         if (maxhashlevel > hashsize)
 210           maxhashlevel = hashsize;
 211 
 212         /* initialize */
 213         hashlevel = 0;
 214         for (i=0; i<hashsize; i++)
 215           hashtable[i].unicode = 0xffff;
 216         hashtable_contents_valid = 1;
 217 }
 218 
 219 int
 220 con_set_unimap(ushort ct, struct unipair *list){
     /* [previous][next][first][last][top][bottom][index][help] */
 221         int i, lct;
 222         ushort u, hu;
 223         struct unimapinit hashdefaults = { 0, 0, 0 };
 224 
 225         if (!hashtable_contents_valid)
 226           con_clear_unimap(&hashdefaults);
 227         while(ct) {
 228             u = get_fs_word(&list->unicode);
 229             i = u % hashsize;
 230             lct = 1;
 231             while ((hu = hashtable[i].unicode) != 0xffff && hu != u) {
 232                 if (lct++ >=  maxhashlevel)
 233                   return -ENOMEM;
 234                 i += hashstep;
 235                 if (i >= hashsize)
 236                   i -= hashsize;
 237             }
 238             if (lct > hashlevel)
 239               hashlevel = lct;
 240             hashtable[i].unicode = u;
 241             hashtable[i].fontpos = get_fs_word(&list->fontpos);
 242             list++;
 243             ct--;
 244         }
 245         return 0;
 246 }
 247 
 248 int
 249 con_get_unimap(ushort ct, ushort *uct, struct unipair *list){
     /* [previous][next][first][last][top][bottom][index][help] */
 250         int i, ect;
 251 
 252         ect = 0;
 253         if (hashtable_contents_valid)
 254           for (i = 0; i<hashsize; i++)
 255             if (hashtable[i].unicode != 0xffff) {
 256                 if (ect++ < ct) {
 257                     put_fs_word(hashtable[i].unicode, &list->unicode);
 258                     put_fs_word(hashtable[i].fontpos, &list->fontpos);
 259                     list++;
 260                 }
 261             }
 262         put_fs_word(ect, uct);
 263         return ((ect <= ct) ? 0 : -ENOMEM);
 264 }
 265 
 266 int
 267 conv_uni_to_pc(unsigned long ucs) {
     /* [previous][next][first][last][top][bottom][index][help] */
 268       int i, h;
 269 
 270       if (!hashtable_contents_valid || ucs < 0x20)
 271         return -3;
 272       if (ucs == 0xffff || ucs == 0xfffe)
 273         return -1;
 274       if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
 275         return -2;
 276       
 277       h = ucs % hashsize;
 278       for (i = 0; i < hashlevel; i++) {
 279           if (hashtable[h].unicode == ucs)
 280             return hashtable[h].fontpos;
 281           if ((h += hashstep) >= hashsize)
 282             h -= hashsize;
 283       }
 284 
 285       return -4;                /* not found */
 286 }

/* [previous][next][first][last][top][bottom][index][help] */