4 * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
9 * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
11 * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
15 #include <linux/errno.h>
17 #include <linux/malloc.h>
18 #include <linux/init.h>
19 #include <asm/uaccess.h>
20 #include <linux/consolemap.h>
21 #include <linux/console_struct.h>
22 #include <linux/vt_kern.h>
24 static unsigned short translations
[][256] = {
25 /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
27 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
28 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
29 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
30 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
31 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
32 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
33 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
34 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
35 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
36 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
37 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
38 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
39 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
40 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
41 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
42 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
43 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
44 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
45 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
46 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
47 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
48 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
49 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
50 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
51 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
52 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
53 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
54 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
55 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
56 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
57 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
58 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
60 /* VT100 graphics mapped to Unicode */
62 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
63 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
64 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
65 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
66 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
67 0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
68 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
69 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
70 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
71 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
72 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
73 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
74 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
75 0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0xf800,
76 0xf801, 0x2500, 0xf803, 0xf804, 0x251c, 0x2524, 0x2534, 0x252c,
77 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
78 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
79 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
80 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
81 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
82 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
83 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
84 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
85 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
86 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
87 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
88 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
89 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
90 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
91 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
92 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
93 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
95 /* IBM Codepage 437 mapped to Unicode */
97 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
98 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
99 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
100 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
101 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
102 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
103 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
104 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
105 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
106 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
107 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
108 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
109 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
110 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
111 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
112 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
113 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
114 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
115 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
116 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
117 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
118 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
119 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
120 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
121 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
122 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
123 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
124 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
125 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
126 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
127 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
128 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
130 /* User mapping -- default to codes for direct font mapping */
132 0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
133 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
134 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
135 0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
136 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
137 0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
138 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
139 0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
140 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
141 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
142 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
143 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
144 0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
145 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
146 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
147 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
148 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
149 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
150 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
151 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
152 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
153 0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
154 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
155 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
156 0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
157 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
158 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
159 0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
160 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
161 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
162 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
163 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
167 /* The standard kernel character-to-font mappings are not invertible
168 -- this is just a best effort. */
170 #define MAX_GLYPH 512 /* Max possible glyph value */
172 static int inv_translate
[MAX_NR_CONSOLES
];
176 unsigned long refcount
;
178 unsigned char *inverse_translations
[4];
182 static struct uni_pagedir
*dflt
;
184 static void set_inverse_transl(struct vc_data
*conp
, struct uni_pagedir
*p
, int i
)
187 unsigned short *t
= translations
[i
];
191 q
= p
->inverse_translations
[i
];
194 q
= p
->inverse_translations
[i
] = (unsigned char *)
195 kmalloc(MAX_GLYPH
, GFP_KERNEL
);
198 memset(q
, 0, MAX_GLYPH
);
200 for (j
= 0; j
< E_TABSZ
; j
++) {
201 glyph
= conv_uni_to_pc(conp
, t
[j
]);
202 if (glyph
>= 0 && glyph
< MAX_GLYPH
&& q
[glyph
] < 32) {
203 /* prefer '-' above SHY etc. */
209 unsigned short *set_translate(int m
,int currcons
)
211 inv_translate
[currcons
] = m
;
212 return translations
[m
];
216 * Inverse translation is impossible for several reasons:
217 * 1. The font<->character maps are not 1-1.
218 * 2. The text may have been written while a different translation map
219 * was active, or using Unicode.
220 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
222 unsigned char inverse_translate(struct vc_data
*conp
, int glyph
)
224 struct uni_pagedir
*p
;
225 if (glyph
< 0 || glyph
>= MAX_GLYPH
)
227 else if (!(p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
) ||
228 !p
->inverse_translations
[inv_translate
[conp
->vc_num
]])
231 return p
->inverse_translations
[inv_translate
[conp
->vc_num
]][glyph
];
234 static void update_user_maps(void)
237 struct uni_pagedir
*p
, *q
= NULL
;
239 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
240 if (!vc_cons_allocated(i
))
242 p
= (struct uni_pagedir
*)*vc_cons
[i
].d
->vc_uni_pagedir_loc
;
244 set_inverse_transl(vc_cons
[i
].d
, p
, USER_MAP
);
251 * Load customizable translation table
252 * arg points to a 256 byte translation table.
254 * The "old" variants are for translation directly to font (using the
255 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
256 * Unicodes explicitly.
258 int con_set_trans_old(unsigned char * arg
)
261 unsigned short *p
= translations
[USER_MAP
];
263 i
= verify_area(VERIFY_READ
, (void *)arg
, E_TABSZ
);
267 for (i
=0; i
<E_TABSZ
; i
++) {
269 __get_user(uc
, arg
+i
);
270 p
[i
] = UNI_DIRECT_BASE
| uc
;
277 int con_get_trans_old(unsigned char * arg
)
280 unsigned short *p
= translations
[USER_MAP
];
282 i
= verify_area(VERIFY_WRITE
, (void *)arg
, E_TABSZ
);
286 for (i
=0; i
<E_TABSZ
; i
++)
288 ch
= conv_uni_to_pc(vc_cons
[fg_console
].d
, p
[i
]);
289 __put_user((ch
& ~0xff) ? 0 : ch
, arg
+i
);
294 int con_set_trans_new(ushort
* arg
)
297 unsigned short *p
= translations
[USER_MAP
];
299 i
= verify_area(VERIFY_READ
, (void *)arg
,
300 E_TABSZ
*sizeof(unsigned short));
304 for (i
=0; i
<E_TABSZ
; i
++) {
306 __get_user(us
, arg
+i
);
314 int con_get_trans_new(ushort
* arg
)
317 unsigned short *p
= translations
[USER_MAP
];
319 i
= verify_area(VERIFY_WRITE
, (void *)arg
,
320 E_TABSZ
*sizeof(unsigned short));
324 for (i
=0; i
<E_TABSZ
; i
++)
325 __put_user(p
[i
], arg
+i
);
331 * Unicode -> current font conversion
333 * A font has at most 512 chars, usually 256.
334 * But one font position may represent several Unicode chars.
335 * A hashtable is somewhat of a pain to deal with, so use a
336 * "paged table" instead. Simulation has shown the memory cost of
337 * this 3-level paged table scheme to be comparable to a hash table.
340 extern u8 dfont_unicount
[]; /* Defined in console_defmap.c */
341 extern u16 dfont_unitable
[];
343 static void con_release_unimap(struct uni_pagedir
*p
)
348 if (p
== dflt
) dflt
= NULL
;
349 for (i
= 0; i
< 32; i
++) {
350 if ((p1
= p
->uni_pgdir
[i
]) != NULL
) {
351 for (j
= 0; j
< 32; j
++)
356 p
->uni_pgdir
[i
] = NULL
;
358 for (i
= 0; i
< 4; i
++)
359 if (p
->inverse_translations
[i
]) {
360 kfree(p
->inverse_translations
[i
]);
361 p
->inverse_translations
[i
] = NULL
;
365 void con_free_unimap(int con
)
367 struct uni_pagedir
*p
;
368 struct vc_data
*conp
= vc_cons
[con
].d
;
370 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
372 *conp
->vc_uni_pagedir_loc
= 0;
373 if (--p
->refcount
) return;
374 con_release_unimap(p
);
378 static int con_unify_unimap(struct vc_data
*conp
, struct uni_pagedir
*p
)
381 struct uni_pagedir
*q
;
383 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
384 if (!vc_cons_allocated(i
))
386 q
= (struct uni_pagedir
*)*vc_cons
[i
].d
->vc_uni_pagedir_loc
;
387 if (!q
|| q
== p
|| q
->sum
!= p
->sum
)
389 for (j
= 0; j
< 32; j
++) {
391 p1
= p
->uni_pgdir
[j
]; q1
= q
->uni_pgdir
[j
];
396 for (k
= 0; k
< 32; k
++) {
397 if (!p1
[k
] && !q1
[k
])
399 if (!p1
[k
] || !q1
[k
])
401 if (memcmp(p1
[k
], q1
[k
], 64*sizeof(u16
)))
409 *conp
->vc_uni_pagedir_loc
= (unsigned long)q
;
410 con_release_unimap(p
);
419 con_insert_unipair(struct uni_pagedir
*p
, u_short unicode
, u_short fontpos
)
424 if (!(p1
= p
->uni_pgdir
[n
= unicode
>> 11])) {
425 p1
= p
->uni_pgdir
[n
] = kmalloc(32*sizeof(u16
*), GFP_KERNEL
);
426 if (!p1
) return -ENOMEM
;
427 for (i
= 0; i
< 32; i
++)
431 if (!(p2
= p1
[n
= (unicode
>> 6) & 0x1f])) {
432 p2
= p1
[n
] = kmalloc(64*sizeof(u16
), GFP_KERNEL
);
433 if (!p2
) return -ENOMEM
;
434 memset(p2
, 0xff, 64*sizeof(u16
)); /* No glyphs for the characters (yet) */
437 p2
[unicode
& 0x3f] = fontpos
;
439 p
->sum
+= (fontpos
<< 20) + unicode
;
444 /* ui is a leftover from using a hashtable, but might be used again */
445 int con_clear_unimap(int con
, struct unimapinit
*ui
)
447 struct uni_pagedir
*p
, *q
;
448 struct vc_data
*conp
= vc_cons
[con
].d
;
450 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
451 if (p
&& p
->readonly
) return -EIO
;
452 if (!p
|| --p
->refcount
) {
453 q
= (struct uni_pagedir
*)kmalloc(sizeof(*p
), GFP_KERNEL
);
455 if (p
) p
->refcount
++;
458 memset(q
, 0, sizeof(*q
));
460 *conp
->vc_uni_pagedir_loc
= (unsigned long)q
;
462 if (p
== dflt
) dflt
= NULL
;
465 con_release_unimap(p
);
471 con_set_unimap(int con
, ushort ct
, struct unipair
*list
)
473 int err
= 0, err1
, i
;
474 struct uni_pagedir
*p
, *q
;
475 struct vc_data
*conp
= vc_cons
[con
].d
;
477 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
478 if (p
->readonly
) return -EIO
;
482 if (p
->refcount
> 1) {
486 err1
= con_clear_unimap(con
, NULL
);
487 if (err1
) return err1
;
489 q
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
490 for (i
= 0, l
= 0; i
< 32; i
++)
491 if ((p1
= p
->uni_pgdir
[i
]))
492 for (j
= 0; j
< 32; j
++)
494 for (k
= 0; k
< 64; k
++, l
++)
495 if (p2
[k
] != 0xffff) {
496 err1
= con_insert_unipair(q
, l
, p2
[k
]);
499 *conp
->vc_uni_pagedir_loc
= (unsigned long)p
;
500 con_release_unimap(q
);
506 } else if (p
== dflt
)
510 unsigned short unicode
, fontpos
;
511 __get_user(unicode
, &list
->unicode
);
512 __get_user(fontpos
, &list
->fontpos
);
513 if ((err1
= con_insert_unipair(p
, unicode
,fontpos
)) != 0)
518 if (con_unify_unimap(conp
, p
))
521 for (i
= 0; i
<= 3; i
++)
522 set_inverse_transl(conp
, p
, i
); /* Update all inverse translations */
527 /* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
528 The representation used was the most compact I could come up
529 with. This routine is executed at sys_setup time, and when the
530 PIO_FONTRESET ioctl is called. */
533 con_set_default_unimap(int con
)
535 int i
, j
, err
= 0, err1
;
537 struct uni_pagedir
*p
;
538 struct vc_data
*conp
= vc_cons
[con
].d
;
541 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
545 *conp
->vc_uni_pagedir_loc
= (unsigned long)dflt
;
546 if (p
&& --p
->refcount
) {
547 con_release_unimap(p
);
553 /* The default font is always 256 characters */
555 err
= con_clear_unimap(con
,NULL
);
558 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
561 for (i
= 0; i
< 256; i
++)
562 for (j
= dfont_unicount
[i
]; j
; j
--) {
563 err1
= con_insert_unipair(p
, *(q
++), i
);
568 if (con_unify_unimap(conp
, p
)) {
569 dflt
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
573 for (i
= 0; i
<= 3; i
++)
574 set_inverse_transl(conp
, p
, i
); /* Update all inverse translations */
580 con_copy_unimap(int dstcon
, int srccon
)
582 struct vc_data
*sconp
= vc_cons
[srccon
].d
;
583 struct vc_data
*dconp
= vc_cons
[dstcon
].d
;
584 struct uni_pagedir
*q
;
586 if (!vc_cons_allocated(srccon
) || !*sconp
->vc_uni_pagedir_loc
)
588 if (*dconp
->vc_uni_pagedir_loc
== *sconp
->vc_uni_pagedir_loc
)
590 con_free_unimap(dstcon
);
591 q
= (struct uni_pagedir
*)*sconp
->vc_uni_pagedir_loc
;
593 *dconp
->vc_uni_pagedir_loc
= (long)q
;
598 con_get_unimap(int con
, ushort ct
, ushort
*uct
, struct unipair
*list
)
602 struct uni_pagedir
*p
;
603 struct vc_data
*conp
= vc_cons
[con
].d
;
606 if (*conp
->vc_uni_pagedir_loc
) {
607 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
608 for (i
= 0; i
< 32; i
++)
609 if ((p1
= p
->uni_pgdir
[i
]))
610 for (j
= 0; j
< 32; j
++)
612 for (k
= 0; k
< 64; k
++) {
613 if (*p2
< MAX_GLYPH
&& ect
++ < ct
) {
614 __put_user((u_short
)((i
<<11)+(j
<<6)+k
),
616 __put_user((u_short
) *p2
,
623 __put_user(ect
, uct
);
624 return ((ect
<= ct
) ? 0 : -ENOMEM
);
627 void con_protect_unimap(int con
, int rdonly
)
629 struct uni_pagedir
*p
= (struct uni_pagedir
*)
630 *vc_cons
[con
].d
->vc_uni_pagedir_loc
;
632 if (p
) p
->readonly
= rdonly
;
636 conv_uni_to_pc(struct vc_data
*conp
, long ucs
)
640 struct uni_pagedir
*p
;
642 /* Only 16-bit codes supported at this time */
644 ucs
= 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */
645 else if (ucs
< 0x20 || ucs
>= 0xfffe)
646 return -1; /* Not a printable character */
647 else if (ucs
== 0xfeff || (ucs
>= 0x200a && ucs
<= 0x200f))
648 return -2; /* Zero-width space */
650 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
651 * which always has a 1:1 mapping to the currently loaded font. The
652 * UNI_DIRECT_MASK indicates the bit span of the region.
654 else if ((ucs
& ~UNI_DIRECT_MASK
) == UNI_DIRECT_BASE
)
655 return ucs
& UNI_DIRECT_MASK
;
657 if (!*conp
->vc_uni_pagedir_loc
)
660 p
= (struct uni_pagedir
*)*conp
->vc_uni_pagedir_loc
;
661 if ((p1
= p
->uni_pgdir
[ucs
>> 11]) &&
662 (p2
= p1
[(ucs
>> 6) & 0x1f]) &&
663 (h
= p2
[ucs
& 0x3f]) < MAX_GLYPH
)
666 return -4; /* not found */
670 * This is called at sys_setup time, after memory and the console are
671 * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
672 * from this function, hence the call from sys_setup.
675 console_map_init(void)
679 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++)
680 if (vc_cons_allocated(i
) && !*vc_cons
[i
].d
->vc_uni_pagedir_loc
)
681 con_set_default_unimap(i
);