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 * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
10 *
11 * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
12 */
13
14 #include <linux/kd.h>
15 #include <linux/errno.h>
16 #include <linux/mm.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>
23
24 static unsigned short translations[][256] = {
25 /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
26 {
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
59 },
60 /* VT100 graphics mapped to Unicode */
61 {
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
94 },
95 /* IBM Codepage 437 mapped to Unicode */
96 {
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
129 },
130 /* User mapping -- default to codes for direct font mapping */
131 {
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
164 }
165 };
166
167 /* The standard kernel character-to-font mappings are not invertible
168 -- this is just a best effort. */
169
170 #define MAX_GLYPH 512 /* Max possible glyph value */
171
172 static int inv_translate[MAX_NR_CONSOLES];
173
174 struct uni_pagedir {
175 u16 **uni_pgdir[32];
176 unsigned long refcount;
177 unsigned long sum;
178 unsigned char *inverse_translations[4];
179 int readonly;
180 };
181
182 static struct uni_pagedir *dflt;
183
184 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
185 {
186 int j, glyph;
187 unsigned short *t = translations[i];
188 unsigned char *q;
189
190 if (!p) return;
191 q = p->inverse_translations[i];
192
193 if (!q) {
194 q = p->inverse_translations[i] = (unsigned char *)
195 kmalloc(MAX_GLYPH, GFP_KERNEL);
196 if (!q) return;
197 }
198 memset(q, 0, MAX_GLYPH);
199
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. */
204 q[glyph] = j;
205 }
206 }
207 }
208
209 unsigned short *set_translate(int m,int currcons)
210 {
211 inv_translate[currcons] = m;
212 return translations[m];
213 }
214
215 /*
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.
221 */
222 unsigned char inverse_translate(struct vc_data *conp, int glyph)
223 {
224 struct uni_pagedir *p;
225 if (glyph < 0 || glyph >= MAX_GLYPH)
226 return 0;
227 else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
228 !p->inverse_translations[inv_translate[conp->vc_num]])
229 return glyph;
230 else
231 return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
232 }
233
234 static void update_user_maps(void)
235 {
236 int i;
237 struct uni_pagedir *p, *q = NULL;
238
239 for (i = 0; i < MAX_NR_CONSOLES; i++) {
240 if (!vc_cons_allocated(i))
241 continue;
242 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
243 if (p && p != q) {
244 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
245 q = p;
246 }
247 }
248 }
249
250 /*
251 * Load customizable translation table
252 * arg points to a 256 byte translation table.
253 *
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.
257 */
258 int con_set_trans_old(unsigned char * arg)
259 {
260 int i;
261 unsigned short *p = translations[USER_MAP];
262
263 i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
264 if (i)
265 return i;
266
267 for (i=0; i<E_TABSZ ; i++) {
268 unsigned char uc;
269 __get_user(uc, arg+i);
270 p[i] = UNI_DIRECT_BASE | uc;
271 }
272
273 update_user_maps();
274 return 0;
275 }
276
277 int con_get_trans_old(unsigned char * arg)
278 {
279 int i, ch;
280 unsigned short *p = translations[USER_MAP];
281
282 i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
283 if (i)
284 return i;
285
286 for (i=0; i<E_TABSZ ; i++)
287 {
288 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
289 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
290 }
291 return 0;
292 }
293
294 int con_set_trans_new(ushort * arg)
295 {
296 int i;
297 unsigned short *p = translations[USER_MAP];
298
299 i = verify_area(VERIFY_READ, (void *)arg,
300 E_TABSZ*sizeof(unsigned short));
301 if (i)
302 return i;
303
304 for (i=0; i<E_TABSZ ; i++) {
305 unsigned short us;
306 __get_user(us, arg+i);
307 p[i] = us;
308 }
309
310 update_user_maps();
311 return 0;
312 }
313
314 int con_get_trans_new(ushort * arg)
315 {
316 int i;
317 unsigned short *p = translations[USER_MAP];
318
319 i = verify_area(VERIFY_WRITE, (void *)arg,
320 E_TABSZ*sizeof(unsigned short));
321 if (i)
322 return i;
323
324 for (i=0; i<E_TABSZ ; i++)
325 __put_user(p[i], arg+i);
326
327 return 0;
328 }
329
330 /*
331 * Unicode -> current font conversion
332 *
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.
338 */
339
340 extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
341 extern u16 dfont_unitable[];
342
343 static void con_release_unimap(struct uni_pagedir *p)
344 {
345 u16 **p1;
346 int i, j;
347
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++)
352 if (p1[j])
353 kfree(p1[j]);
354 kfree(p1);
355 }
356 p->uni_pgdir[i] = NULL;
357 }
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;
362 }
363 }
364
365 void con_free_unimap(int con)
366 {
367 struct uni_pagedir *p;
368 struct vc_data *conp = vc_cons[con].d;
369
370 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
371 if (!p) return;
372 *conp->vc_uni_pagedir_loc = 0;
373 if (--p->refcount) return;
374 con_release_unimap(p);
375 kfree(p);
376 }
377
378 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
379 {
380 int i, j, k;
381 struct uni_pagedir *q;
382
383 for (i = 0; i < MAX_NR_CONSOLES; i++) {
384 if (!vc_cons_allocated(i))
385 continue;
386 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
387 if (!q || q == p || q->sum != p->sum)
388 continue;
389 for (j = 0; j < 32; j++) {
390 u16 **p1, **q1;
391 p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
392 if (!p1 && !q1)
393 continue;
394 if (!p1 || !q1)
395 break;
396 for (k = 0; k < 32; k++) {
397 if (!p1[k] && !q1[k])
398 continue;
399 if (!p1[k] || !q1[k])
400 break;
401 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
402 break;
403 }
404 if (k < 32)
405 break;
406 }
407 if (j == 32) {
408 q->refcount++;
409 *conp->vc_uni_pagedir_loc = (unsigned long)q;
410 con_release_unimap(p);
411 kfree(p);
412 return 1;
413 }
414 }
415 return 0;
416 }
417
418 static int
419 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
420 {
421 int i, n;
422 u16 **p1, *p2;
423
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++)
428 p1[i] = NULL;
429 }
430
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) */
435 }
436
437 p2[unicode & 0x3f] = fontpos;
438
439 p->sum += (fontpos << 20) + unicode;
440
441 return 0;
442 }
443
444 /* ui is a leftover from using a hashtable, but might be used again */
445 int con_clear_unimap(int con, struct unimapinit *ui)
446 {
447 struct uni_pagedir *p, *q;
448 struct vc_data *conp = vc_cons[con].d;
449
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);
454 if (!q) {
455 if (p) p->refcount++;
456 return -ENOMEM;
457 }
458 memset(q, 0, sizeof(*q));
459 q->refcount=1;
460 *conp->vc_uni_pagedir_loc = (unsigned long)q;
461 } else {
462 if (p == dflt) dflt = NULL;
463 p->refcount++;
464 p->sum = 0;
465 con_release_unimap(p);
466 }
467 return 0;
468 }
469
470 int
471 con_set_unimap(int con, ushort ct, struct unipair *list)
472 {
473 int err = 0, err1, i;
474 struct uni_pagedir *p, *q;
475 struct vc_data *conp = vc_cons[con].d;
476
477 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
478 if (p->readonly) return -EIO;
479
480 if (!ct) return 0;
481
482 if (p->refcount > 1) {
483 int j, k;
484 u16 **p1, *p2, l;
485
486 err1 = con_clear_unimap(con, NULL);
487 if (err1) return err1;
488
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++)
493 if ((p2 = p1[j]))
494 for (k = 0; k < 64; k++, l++)
495 if (p2[k] != 0xffff) {
496 err1 = con_insert_unipair(q, l, p2[k]);
497 if (err1) {
498 p->refcount++;
499 *conp->vc_uni_pagedir_loc = (unsigned long)p;
500 con_release_unimap(q);
501 kfree(q);
502 return err1;
503 }
504 }
505 p = q;
506 } else if (p == dflt)
507 dflt = NULL;
508
509 while (ct--) {
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)
514 err = err1;
515 list++;
516 }
517
518 if (con_unify_unimap(conp, p))
519 return err;
520
521 for (i = 0; i <= 3; i++)
522 set_inverse_transl(conp, p, i); /* Update all inverse translations */
523
524 return err;
525 }
526
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. */
531
532 int
533 con_set_default_unimap(int con)
534 {
535 int i, j, err = 0, err1;
536 u16 *q;
537 struct uni_pagedir *p;
538 struct vc_data *conp = vc_cons[con].d;
539
540 if (dflt) {
541 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
542 if (p == dflt)
543 return 0;
544 dflt->refcount++;
545 *conp->vc_uni_pagedir_loc = (unsigned long)dflt;
546 if (p && --p->refcount) {
547 con_release_unimap(p);
548 kfree(p);
549 }
550 return 0;
551 }
552
553 /* The default font is always 256 characters */
554
555 err = con_clear_unimap(con,NULL);
556 if (err) return err;
557
558 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
559 q = dfont_unitable;
560
561 for (i = 0; i < 256; i++)
562 for (j = dfont_unicount[i]; j; j--) {
563 err1 = con_insert_unipair(p, *(q++), i);
564 if (err1)
565 err = err1;
566 }
567
568 if (con_unify_unimap(conp, p)) {
569 dflt = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
570 return err;
571 }
572
573 for (i = 0; i <= 3; i++)
574 set_inverse_transl(conp, p, i); /* Update all inverse translations */
575 dflt = p;
576 return err;
577 }
578
579 int
580 con_copy_unimap(int dstcon, int srccon)
581 {
582 struct vc_data *sconp = vc_cons[srccon].d;
583 struct vc_data *dconp = vc_cons[dstcon].d;
584 struct uni_pagedir *q;
585
586 if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc)
587 return -EINVAL;
588 if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc)
589 return 0;
590 con_free_unimap(dstcon);
591 q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc;
592 q->refcount++;
593 *dconp->vc_uni_pagedir_loc = (long)q;
594 return 0;
595 }
596
597 int
598 con_get_unimap(int con, ushort ct, ushort *uct, struct unipair *list)
599 {
600 int i, j, k, ect;
601 u16 **p1, *p2;
602 struct uni_pagedir *p;
603 struct vc_data *conp = vc_cons[con].d;
604
605 ect = 0;
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++)
611 if ((p2 = *(p1++)))
612 for (k = 0; k < 64; k++) {
613 if (*p2 < MAX_GLYPH && ect++ < ct) {
614 __put_user((u_short)((i<<11)+(j<<6)+k),
615 &list->unicode);
616 __put_user((u_short) *p2,
617 &list->fontpos);
618 list++;
619 }
620 p2++;
621 }
622 }
623 __put_user(ect, uct);
624 return ((ect <= ct) ? 0 : -ENOMEM);
625 }
626
627 void con_protect_unimap(int con, int rdonly)
628 {
629 struct uni_pagedir *p = (struct uni_pagedir *)
630 *vc_cons[con].d->vc_uni_pagedir_loc;
631
632 if (p) p->readonly = rdonly;
633 }
634
635 int
636 conv_uni_to_pc(struct vc_data *conp, long ucs)
637 {
638 int h;
639 u16 **p1, *p2;
640 struct uni_pagedir *p;
641
642 /* Only 16-bit codes supported at this time */
643 if (ucs > 0xffff)
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 */
649 /*
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.
653 */
654 else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
655 return ucs & UNI_DIRECT_MASK;
656
657 if (!*conp->vc_uni_pagedir_loc)
658 return -3;
659
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)
664 return h;
665
666 return -4; /* not found */
667 }
668
669 /*
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.
673 */
674 void __init
675 console_map_init(void)
676 {
677 int i;
678
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);
682 }
683
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.