1/*
2 * Copyright 1999-2009 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Jeremy Friesner
7 */
8
9
10#include "KeyInfos.h"
11
12#include <ctype.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <strings.h>
16
17#include <InterfaceDefs.h>
18
19
20#define NUM_KEYS 128
21#define MAX_UTF8_LENGTH 5
22	// up to 4 chars, plus a \0 terminator
23
24
25struct KeyLabelMap {
26	const char* fLabel;
27	uint8 fKeyCode;
28};
29
30
31// This is a table of keys-codes that have special, hard-coded labels.
32static const struct KeyLabelMap keyLabels[] = {
33	{"<unset>",		0},
34	{"Esc",			1},
35	{"F1",			2},
36	{"F2",			3},
37	{"F3",			4},
38	{"F4",			5},
39	{"F5",			6},
40	{"F6",			7},
41	{"F7",			8},
42	{"F8",			9},
43	{"F9",			10},
44	{"F10",			11},
45	{"F11",			12},
46	{"F12",			13},
47	{"SysRq",		14},
48	{"ScrlLck",		15},
49	{"Pause",		16},
50	{"Bcksp",		30},
51	{"Insert",		31},
52	{"Home",		32},
53	{"PgUp",		33},
54	{"Num Lock",	34},
55	{"Kpd /",		35},
56	{"Kpd *",		36},
57	{"Kpd -",		37},
58	{"Tab",			38},
59	{"Delete",		52},
60	{"End",			53},
61	{"PgDn",		54},
62	{"Kpd 7",		55},
63	{"Kpd 8",		56},
64	{"Kpd 9",		57},
65	{"Kpd +",		58},
66	{"Caps Lock",	59},
67	{"Enter",		71},
68	{"Kpd 4",		72},
69	{"Kpd 5",		73},
70	{"Kpd 6",		74},
71	{"L.Shift",		75},
72	{"R.Shift",		86},
73	{"Up",			87},
74	{"Kpd 1",		88},
75	{"Kpd 2",		89},
76	{"Kpd 3",		90},
77	{"Kpd Entr",	91},
78	{"L.Control",	92},
79	{"L.Alt",		93},
80	{"Space",		94},
81	{"R.Alt",		95},
82	{"R.Control",	96},
83	{"Left",		97},
84	{"Down",		98},
85	{"Right",		99},
86	{"Kpd 0",		100},
87	{"Kpd .",		101},
88	{"L.Command",	102},
89	{"R.Command",	103},
90	{"Menu",		104},
91	{"PowerOn",		107},
92};
93
94
95// Key description strings (e.g. "A" or "Escape"). NULL if no description is
96// available.
97static const char* keyDescriptions[NUM_KEYS];
98
99
100// series of optional up-to-(4+1)-byte terminated UTF-8 character strings...
101static char utfDescriptions[NUM_KEYS * MAX_UTF8_LENGTH];
102
103
104static const char*
105FindSpecialKeyLabelFor(uint8 keyCode, uint32& last)
106{
107	while ((keyLabels[last].fKeyCode < keyCode)
108		&& (last < (sizeof(keyLabels) / sizeof(struct KeyLabelMap)) - 1)) {
109		last++;
110	}
111
112	if (keyLabels[last].fKeyCode == keyCode)
113		return keyLabels[last].fLabel;
114	else
115		return NULL;
116}
117
118
119void
120InitKeyIndices()
121{
122	uint32 nextSpecial = 0;
123	key_map* map;
124	char* keys;
125	get_key_map(&map, &keys);
126
127	for (uint8 j = 0; j < NUM_KEYS; j++) {
128		keyDescriptions[j] = NULL;
129			// default
130
131		const char* specialLabel = FindSpecialKeyLabelFor(j, nextSpecial);
132		int32 keyCode = map->normal_map[j];
133
134		if (keyCode >= 0) {
135			const char* mapDesc = &keys[keyCode];
136			uint8 length = *mapDesc;
137
138			for (int m = 0; m < MAX_UTF8_LENGTH; m++)
139				if (m < length)
140					utfDescriptions[j * MAX_UTF8_LENGTH + m] = mapDesc[m + 1];
141				else
142					utfDescriptions[j * MAX_UTF8_LENGTH + m] = '\0';
143
144			if (specialLabel != NULL)
145				keyDescriptions[j] = specialLabel;
146			else {
147				// If it's an ASCII letter, capitalize it.
148				char& c = utfDescriptions[j * MAX_UTF8_LENGTH];
149
150				if ((length == 1) && (isalpha(c)))
151					c = toupper(c);
152
153				if (length > 1 || (length == 1 && c > ' '))
154					keyDescriptions[j] = &c;
155			}
156		} else
157			utfDescriptions[j * MAX_UTF8_LENGTH] = 0x00;
158	}
159
160	free(keys);
161	free(map);
162}
163
164
165const char*
166GetKeyUTF8(uint8 keyIndex)
167{
168	return &utfDescriptions[keyIndex * MAX_UTF8_LENGTH];
169}
170
171
172const char*
173GetKeyName(uint8 keyIndex)
174{
175	return keyDescriptions[keyIndex];
176}
177
178
179int
180GetNumKeyIndices()
181{
182	return NUM_KEYS;
183}
184
185
186uint8
187FindKeyCode(const char* keyName)
188{
189	for (uint8 i = 0; i < NUM_KEYS; i++) {
190		if ((keyDescriptions[i])
191			&& (strcasecmp(keyName, keyDescriptions[i]) == 0)) {
192			return i;
193		}
194	}
195
196	return 0;
197		// default to sentinel value
198}
199