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