Removed obsolete (and apparently unneeded) AM_C_PROTOTYPES line, which
[AROS.git] / rom / keymap / mapansi.c
blob87657e2e1aa0bfafbc11b522817c685f9e8b239a
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
8 #include "keymap_intern.h"
9 #include <devices/inputevent.h>
11 #include <aros/debug.h>
12 #define DEBUG_MAPANSI(x) D(x)
14 /*****************************************************************************
16 NAME */
17 #include <clib/keymap_protos.h>
19 AROS_LH5(LONG, MapANSI,
21 /* SYNOPSIS */
22 AROS_LHA(STRPTR , string, A0),
23 AROS_LHA(LONG , count, D0),
24 AROS_LHA(STRPTR , buffer, A1),
25 AROS_LHA(LONG , length, D1),
26 AROS_LHA(struct KeyMap *, keyMap, A2),
28 /* LOCATION */
29 struct Library *, KeymapBase, 8, Keymap)
31 /* FUNCTION
32 Convert an ANSI byte string to rawkey codes
34 INPUTS
35 string - the ANSI byte string to convert
37 count - the number of characters in string
39 buffer - a byte buffer which must be large enough
40 to hold all anticipated code/qualifier pairs
41 which are generated by this function
43 length - maximum anticipation, ie. the buffer size in
44 WORDs (buffer size in bytes divided by two).
45 WORDs, because one code/qualifier pair consists
46 of 2 bytes.
48 RESULT
49 actual - the number of code/qualifier pairs this function
50 generated in buffer. Or an negative value to indicate
51 an error.
52 NOTES
54 EXAMPLE
56 BUGS
58 SEE ALSO
60 INTERNALS
61 Contributed by MorphOS team
63 HISTORY
64 27-11-96 digulla automatically created from
65 keymap_lib.fd and clib/keymap_protos.h
67 *****************************************************************************/
69 AROS_LIBFUNC_INIT
71 LONG OrigLength=length;
72 int MaxDeadIndex=0;
73 int MaxDoubleDeadIndex=0;
74 int NumDeads=0;
75 UBYTE DeadCode[16];
76 UBYTE DeadQual[16];
77 UBYTE DoubleDeadCode[16];
78 UBYTE DoubleDeadQual[16];
79 CONST UBYTE *Types;
80 CONST IPTR *Descrs;
81 int BaseCode;
82 int Code;
83 int k;
85 static const UBYTE NumKeys[] = { 1, 2, 2, 4, 2, 4, 4, 4 };
86 static const UWORD Qualifiers[8][4] =
88 { 0, },
89 { 0, IEQUALIFIER_LSHIFT, },
90 { 0, IEQUALIFIER_LALT, },
91 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT | IEQUALIFIER_LALT },
92 { 0, IEQUALIFIER_CONTROL, },
93 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_CONTROL, IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL },
94 { 0, IEQUALIFIER_LALT, IEQUALIFIER_CONTROL, IEQUALIFIER_LALT | IEQUALIFIER_CONTROL },
95 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT | IEQUALIFIER_LALT },
97 static const UBYTE NumKeys2[] = { 1, 2, 2, 4, 2, 4, 4, 8 };
98 static const UWORD Qualifiers2[8][8] =
100 { 0, },
101 { 0, IEQUALIFIER_LSHIFT, },
102 { 0, IEQUALIFIER_LALT, },
103 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT | IEQUALIFIER_LALT },
104 { 0, IEQUALIFIER_CONTROL, },
105 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_CONTROL, IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL },
106 { 0, IEQUALIFIER_LALT, IEQUALIFIER_CONTROL, IEQUALIFIER_LALT | IEQUALIFIER_CONTROL },
107 { 0, IEQUALIFIER_LSHIFT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT | IEQUALIFIER_LALT,
108 IEQUALIFIER_CONTROL, IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT,
109 IEQUALIFIER_CONTROL | IEQUALIFIER_LALT,
110 IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT },
113 DEBUG_MAPANSI(bug("MapANSI: string 0x%lx count %ld buffer 0x%lx length %ld KeyMap 0x%lx\n",
114 string, count, buffer, length, keyMap));
116 if (keyMap == NULL)
118 keyMap = KMBase(KeymapBase)->DefaultKeymap;
119 DEBUG_MAPANSI(bug("MapANSI: KeyMap 0x%lx\n", keyMap));
123 /* First get the list of dead keys.
126 Types = keyMap->km_HiKeyMapTypes + (0x68 - 0x40);
127 Descrs = keyMap->km_HiKeyMap + (0x68 - 0x40);
128 BaseCode = 0x40;
129 Code = 0x67 - 0x40;
131 for (k = 0; k < sizeof(DeadQual); ++k)
133 DeadQual[k] = 0xff;
134 DoubleDeadQual[k] = 0xff;
141 unsigned Type = *--Types;
142 IPTR Descr = *--Descrs;
144 DEBUG_MAPANSI(bug("MapANSI: Code 0x%02x Type 0x%02x Descr 0x%08lx\n",
145 BaseCode + Code, Type, Descr));
147 if ((Type & KCF_NOP) == 0 && (Type & KCF_DEAD) != 0)
149 int Num = NumKeys2[Type & 7];
150 int k;
151 UBYTE *StrDescr = (UBYTE *)Descr;
153 for (k = 0; k < Num; ++k)
155 if (StrDescr[2 * k] == DPF_DEAD)
157 int Index = StrDescr[2 * k + 1] & DP_2DINDEXMASK;
158 int DoubleDead = StrDescr[2 * k + 1] >> DP_2DFACSHIFT;
159 UBYTE MyQual = Qualifiers2[Type & 7][k];
161 DEBUG_MAPANSI(bug("MapANSI: found dead key index 0x%02lx at 0x%02lx\n",
162 StrDescr[2 * k + 1], BaseCode + Code));
164 if (Index > MaxDeadIndex ||
165 (DeadQual[Index] & MyQual) == MyQual)
167 DeadCode[Index] = BaseCode + Code;
168 DeadQual[Index] = MyQual;
170 if (Index > MaxDeadIndex)
172 MaxDeadIndex = Index;
176 if (DoubleDead)
178 if (Index > MaxDoubleDeadIndex ||
179 (DoubleDeadQual[Index] & MyQual) == MyQual)
181 DoubleDeadCode[Index] = BaseCode + Code;
182 DoubleDeadQual[Index] = MyQual;
184 if (Index > MaxDoubleDeadIndex)
186 MaxDoubleDeadIndex = Index;
194 while (--Code >= 0);
196 Types = keyMap->km_LoKeyMapTypes + 0x40;
197 Descrs = keyMap->km_LoKeyMap + 0x40;
198 BaseCode -= 0x40;
199 Code = 0x3f;
201 while (BaseCode >= 0);
203 NumDeads = (MaxDoubleDeadIndex + 1) * (MaxDeadIndex + 1);
205 DEBUG_MAPANSI(bug("MapANSI: MaxDeadIndex %ld MaxDoubleDeadIndex %ld NumDeads %ld\n",
206 MaxDeadIndex, MaxDoubleDeadIndex, NumDeads));
208 /* Now do the real work.
210 while (count)
212 LONG FoundLen = 0;
213 unsigned FoundCode = 0;
214 unsigned FoundQual = ~0U;
215 unsigned DeadKeyIndex = 0;
216 UBYTE MyChar = *string;
218 DEBUG_MAPANSI(bug("MapANSI: MyChar 0x%02lx count %ld\n",
219 MyChar, count));
221 Types = keyMap->km_HiKeyMapTypes + (0x68 - 0x40);
222 Descrs = keyMap->km_HiKeyMap + (0x68 - 0x40);
223 BaseCode = 0x40;
224 Code = 0x67 - 0x40;
230 unsigned Type = *--Types;
231 IPTR Descr = *--Descrs;
233 if (Type & KCF_NOP)
236 else if (Type & KCF_DEAD)
238 if (FoundLen <= 1)
240 int Num = NumKeys2[Type & 7];
241 int k;
242 UBYTE *StrDescr = (UBYTE *)Descr;
244 for (k = 0; k < Num; ++k)
246 switch (StrDescr[2 * k])
248 case 0:
249 if (StrDescr[2 * k + 1] == MyChar)
251 unsigned MyQual = Qualifiers2[Type & 7][k];
253 if ((FoundQual & MyQual) == MyQual)
255 FoundLen = 1;
256 FoundCode = BaseCode + Code;
257 FoundQual = MyQual;
258 DeadKeyIndex = 0;
261 break;
263 case DPF_MOD:
265 UBYTE *DeadKeys = StrDescr + StrDescr[2 * k + 1];
266 int l;
268 for (l = 0; l < NumDeads; ++l)
270 if (DeadKeys[l] == MyChar)
272 unsigned MyQual = Qualifiers2[Type & 7][k];
274 if (FoundLen == 0 ||
275 (l <= DeadKeyIndex &&
276 (FoundQual & MyQual) == MyQual))
278 FoundLen = 1;
279 FoundCode = BaseCode + Code;
280 FoundQual = MyQual;
281 DeadKeyIndex = l;
286 break;
291 else if (Type & KCF_STRING)
293 int Num = NumKeys2[Type & 7];
294 int k;
295 UBYTE *StrDescr = (UBYTE *)Descr;
297 for (k = 0; k < Num; ++k)
299 int Len = StrDescr[2 * k];
300 UBYTE *KeyStr = StrDescr + StrDescr[2 * k + 1];
302 if (Len <= count && Len >= FoundLen)
304 int i = 0;
306 while (i < Len && string[i] == KeyStr[i])
308 ++i;
311 if (i == Len)
313 unsigned MyQual = Qualifiers2[Type & 7][k];
315 if (Len > FoundLen || DeadKeyIndex ||
316 (FoundQual & MyQual) == MyQual)
318 FoundLen = Len;
319 FoundCode = BaseCode + Code;
320 FoundQual = MyQual;
321 DeadKeyIndex = 0;
327 else if (FoundLen <= 1)
329 int Num = NumKeys[Type & 7];
330 int k;
331 IPTR Descr2 = Descr;
333 for (k = 0; k < Num; ++k)
335 if ((UBYTE)Descr == MyChar)
337 unsigned MyQual = Qualifiers[Type & 7][k];
339 if (DeadKeyIndex || (FoundQual & MyQual) == MyQual)
341 FoundLen = 1;
342 FoundCode = BaseCode + Code;
343 FoundQual = MyQual;
344 DeadKeyIndex = 0;
346 break;
348 Descr >>= 8;
351 if (Type == KC_VANILLA && (MyChar & 0x60) == 0 &&
352 (FoundLen == 0 || DeadKeyIndex != 0))
354 UBYTE MyQual = IEQUALIFIER_CONTROL;
356 if (MyChar & 0x80)
358 MyQual |= IEQUALIFIER_LALT;
359 Descr2 = (Descr2 >> 16) | (Descr2 << 16);
362 if ((Descr2 & 0xc0) == 0x40 && (Descr2 & 0x1f) != (MyChar & 0x1f))
364 MyQual |= IEQUALIFIER_LSHIFT;
365 Descr2 >>= 8;
368 k = 0;
369 while (k < 4 && (Descr2 & 0xc0) != 0x40)
371 ++k;
372 Descr2 >>= 8;
375 if (k < 4 && (Descr2 & 0x1f) == (MyChar & 0x1f))
377 FoundLen = 1;
378 FoundCode = BaseCode + Code;
379 FoundQual = MyQual;
380 DeadKeyIndex = 0;
385 while (--Code >= 0);
387 Types = keyMap->km_LoKeyMapTypes + 0x40;
388 Descrs = keyMap->km_LoKeyMap + 0x40;
389 BaseCode -= 0x40;
390 Code = 0x3f;
392 while (BaseCode >= 0);
394 if (FoundLen == 0)
396 DEBUG_MAPANSI(bug("MapANSI: not found\n"));
397 return 0;
400 length -= 1 + (DeadKeyIndex != 0) + (DeadKeyIndex > MaxDeadIndex);
401 if (length < 0)
403 DEBUG_MAPANSI(bug("MapANSI: buffer overflow\n"));
404 return -1;
407 DEBUG_MAPANSI(bug("MapANSI: FoundLen %ld Code 0x%02lx Qual 0x%02lx DeadKeyIndex %ld\n",
408 FoundLen, FoundCode, FoundQual, DeadKeyIndex));
410 if (DeadKeyIndex != 0)
412 if (DeadKeyIndex > MaxDeadIndex)
414 *buffer++ = DoubleDeadCode[DeadKeyIndex % (MaxDeadIndex + 1)];
415 *buffer++ = DoubleDeadQual[DeadKeyIndex % (MaxDeadIndex + 1)];
416 DeadKeyIndex /= (MaxDeadIndex + 1);
417 *buffer++ = DoubleDeadCode[DeadKeyIndex];
418 *buffer++ = DoubleDeadQual[DeadKeyIndex];
420 else
422 *buffer++ = DeadCode[DeadKeyIndex];
423 *buffer++ = DeadQual[DeadKeyIndex];
426 *buffer++ = FoundCode;
427 *buffer++ = FoundQual;
429 count -= FoundLen;
430 string += FoundLen;
433 return OrigLength - length;
435 AROS_LIBFUNC_EXIT
437 } /* MapANSI */