1 /* NetHack 3.6 mhcmd.c $NHDT-Date: 1524689383 2018/04/25 20:49:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
2 /* Copyright (c) 2009 by Michael Allison */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "winMS.h"
6 #include <assert.h>
7 #include "mhcmd.h"
8 #include "mhinput.h"
9 #include "mhcolor.h"
10
11 static TCHAR szNHCmdWindowClass[] = TEXT("MSNethackCmdWndClass");
12
13 #ifndef C
14 #define C(c) (0x1f & (c))
15 #endif
16
17 /* cell status 0 */
18 #define NH_CST_CHECKED 1
19
20 /* fonts */
21 #define NH_CMDPAD_FONT_NORMAL 0
22 #define NH_CMDPAD_FONT_MAX 0
23
24 /* type of the cell */
25 #define NH_CELL_REG 0
26 #define NH_CELL_CTRL 1
27 #define NH_CELL_CAP 2
28 #define NH_CELL_SHIFT 3
29 #define NH_CELL_LAYOUT_NEW 4
30 #define NH_CELL_LAYOUT_MENU 5
31
32 #define NH_CMDSET_MAXSIZE 64
33
34 /* Keypad cell information
35
36 NHCmdPadCell.cell_type NHCmdPadCell.data
37 ----------- ----------
38 NH_CELL_REG (int)>=0 - index in the
39 current keypad layout set (loads a new layout)
40 -1 - restore default (saved) layout
41 NH_CELL_CTRL not used
42 NH_CELL_CAP not used
43 NH_CELL_SHIFT not used
44 NH_CELL_LAYOUT_NEW pointer to the new keypad layout
45 layout (NHCmdLayout*)
46 NH_CELL_LAYOUT_MENU pointer to the layout set (NHCmdSet* - if
47 NULL then nhcmdset_default is used)
48 */
49 typedef struct t_NHCmdPadCell {
50 UINT cmd_code; /* Windows command code (menu processing - not implemented
51 - set to -1) */
52 char f_char[16]; /* nethack char */
53 char text[16]; /* display text */
54 int image; /* >0 - image ID in IDB_KEYPAD bitmap
55 <=0 - absolute index of the font table */
56 int type; /* cell type */
57 int mult; /* cell width multiplier */
58 void *data; /* internal data for the cell type */
59 } NHCmdPadCell, *PNHCmdPadCell;
60
61 /* command layout */
62 typedef struct t_NHCmdLayout {
63 char name[64];
64 int rows;
65 int columns;
66 NHCmdPadCell cells[];
67 } NHCmdLayout, *PNHCmdLayout;
68
69 /* set of command layouts */
70 typedef struct t_NHCmdSet {
71 int count;
72 struct t_NHCmdSetElem {
73 PNHCmdLayout layout;
74 BOOL free_on_destroy;
75 } elements[NH_CMDSET_MAXSIZE];
76 } NHCmdSet, *PNHCmdSet;
77
78 /* display cell layout */
79 typedef struct t_NHCmdPadLayoutCell {
80 POINT orig; /* origin of the cell rect */
81 BYTE type; /* cell type */
82 int state; /* cell state */
83 } NHCmdPadLayoutCell, *PNHCmdPadLayoutCell;
84
85 /* command window data */
86 typedef struct mswin_nethack_cmd_window {
87 SIZE cell_size; /* cell size */
88 HFONT font[NH_CMDPAD_FONT_MAX + 1]; /* fonts for cell text */
89 HBITMAP images; /* key images map */
90 int active_cell; /* current active cell */
91
92 boolean is_caps; /* is CAPS selected */
93 boolean is_ctrl; /* is CRTL selected */
94 boolean is_shift; /* is SHIFT selected */
95
96 PNHCmdLayout layout_current; /* current layout */
97 PNHCmdLayout layout_save; /* saved layout */
98 PNHCmdPadLayoutCell cells; /* display cells */
99
100 #if defined(WIN_CE_SMARTPHONE)
101 PNHCmdLayout layout_selected; /* since we use
102 layout
103 command for menu also
104 we need to store the layout
105 that was
106 selected by a user
107 */
108 #endif
109 } NHCmdWindow, *PNHCmdWindow;
110
111 LRESULT CALLBACK NHCommandWndProc(HWND, UINT, WPARAM, LPARAM);
112 static void register_command_window_class();
113 static void LayoutCmdWindow(HWND hWnd);
114 static void SetCmdWindowLayout(HWND hWnd, PNHCmdLayout layout);
115 static int CellFromPoint(PNHCmdWindow data, POINT pt);
116 static void CalculateCellSize(HWND hWnd, LPSIZE pSize, LPSIZE windowSize);
117 static void HighlightCell(HWND hWnd, int cell, BOOL isSelected);
118 static void ActivateCell(HWND hWnd, int cell);
119 static void PushNethackCommand(const char *cmd_char_str, int is_ctrl);
120
121 /*------------------- keyboard keys layout functions -----------------------*/
122 PNHCmdLayout nhcmdlayout_create(const char *name, int rows, int columns);
123 void nhcmdlayout_init(PNHCmdLayout p, PNHCmdPadCell cells);
124 #define nhcmdlayout_rows(p) ((p)->rows)
125 #define nhcmdlayout_columns(p) ((p)->columns)
126 #define nhcmdlayout_row(p, x) (&((p)->cells[(p)->columns * (x)]))
127 #define nhcmdlayout_cell(p, x, y) (&((p)->cells[(p)->columns * (x) + (y)]))
128 #define nhcmdlayout_cell_direct(p, i) (&((p)->cells[(i)]))
129 void nhcmdlayout_destroy(PNHCmdLayout p);
130
131 /*----------------- keyboard keys layout set functions ---------------------*/
132 PNHCmdSet nhcmdset_create();
133 int nhcmdset_count(PNHCmdSet p);
134 PNHCmdLayout nhcmdset_get(PNHCmdSet p, int index);
135 const char *nhcmdset_get_name(PNHCmdSet p, int index);
136 void nhcmdset_add(PNHCmdSet p, PNHCmdLayout layout);
137 void nhcmdset_destroy(PNHCmdSet p);
138
139 /*-------------------- message handlers -----------------------------------*/
140 static void onPaint(HWND hWnd); // on WM_PAINT
141 static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam); // on WM_CREATE
142 static void onMouseDown(HWND hWnd, WPARAM wParam,
143 LPARAM lParam); // on WM_LBUTTONDOWN
144 static void onMouseMove(HWND hWnd, WPARAM wParam,
145 LPARAM lParam); // on WM_MOUSEMOVE
146 static void onMouseUp(HWND hWnd, WPARAM wParam,
147 LPARAM lParam); // on WM_LBUTTONUP
148
149 /*----------------------- static data -------------------------------------*/
150 static PNHCmdSet nhcmdset_current = 0;
151 static PNHCmdSet nhcmdset_default = 0;
152
153 /*---------------------- Pre-definde keyboard layouts --------------------*/
154 #ifdef WIN_CE_SMARTPHONE
155
156 /* dimensions of the command pad */
157 #define NH_CMDPAD_ROWS 4
158 #define NH_CMDPAD_COLS 3
159 #define NH_CMDPAD_CELLNUM (NH_CMDPAD_COLS * NH_CMDPAD_ROWS)
160
161 /* layout indexes */
162 #define NH_LAYOUT_GENERAL 0
163 #define NH_LAYOUT_MOVEMENT 1
164 #define NH_LAYOUT_ATTACK 2
165 #define NH_LAYOUT_ITEM_HANDLING 3
166 #define NH_LAYOUT_CONTROLS 4
167 #define NH_LAYOUT_ADV_MOVEMENT 5
168 #define NH_LAYOUT_ITEM_LOOKUP 6
169 #define NH_LAYOUT_WIZARD 7
170
171 /* template menu layout */
172 NHCmdPadCell cells_layout_menu[NH_CMDPAD_CELLNUM] = {
173 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
174 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
175 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
176 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
177 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
178 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
179 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
180 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
181 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
182 { -1, "", "<<", -NH_CMDPAD_FONT_NORMAL, NH_CELL_LAYOUT_NEW, 1, NULL },
183 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
184 { -1, "", ">>", -NH_CMDPAD_FONT_NORMAL, NH_CELL_LAYOUT_NEW, 1, NULL }
185 };
186
187 /* movement layout */
188 NHCmdPadCell cells_layout_movement[NH_CMDPAD_CELLNUM] = {
189 { -1, "7", "7", 1, NH_CELL_REG, 1, (void *) - 1 },
190 { -1, "8", "8", 2, NH_CELL_REG, 1, (void *) - 1 },
191 { -1, "9", "9", 3, NH_CELL_REG, 1, (void *) - 1 },
192 { -1, "4", "4", 4, NH_CELL_REG, 1, (void *) - 1 },
193 { -1, ".", ".", 5, NH_CELL_REG, 1, (void *) - 1 },
194 { -1, "6", "6", 6, NH_CELL_REG, 1, (void *) - 1 },
195 { -1, "1", "1", 7, NH_CELL_REG, 1, (void *) - 1 },
196 { -1, "2", "2", 8, NH_CELL_REG, 1, (void *) - 1 },
197 { -1, "3", "3", 9, NH_CELL_REG, 1, (void *) - 1 },
198 { -1, "<", "<", 10, NH_CELL_REG, 1, (void *) - 1 },
199 { -1, ">", ">", 12, NH_CELL_REG, 1, (void *) - 1 },
200 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
201 };
202
203 /* attack layout */
204 NHCmdPadCell cells_layout_attack[NH_CMDPAD_CELLNUM] = {
205 { -1, "t", "t", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
206 { -1, "w", "w", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
207 { -1, "x", "x", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
208 { -1, "f", "f", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
209 { -1, "z", "z", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
210 { -1, "Z", "Z", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
211 { -1, "r", "r", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
212 { -1, "a", "a", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
213 { -1, "q", "q", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
214 { -1, "\x04", "^D", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
215 (void *) - 1 },
216 { -1, "F", "F", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
217 (void *) NH_LAYOUT_MOVEMENT },
218 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
219 };
220
221 /* item handling layout */
222 NHCmdPadCell cells_layout_item_handling[NH_CMDPAD_CELLNUM] = {
223 { -1, "W", "W", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
224 { -1, "P", "P", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
225 { -1, "d", "d", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
226 { -1, "T", "T", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
227 { -1, "R", "R", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
228 { -1, "D", "D", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
229 { -1, "=", "=", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
230 { -1, "i", "i", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
231 { -1, "Q", "Q", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
232 { -1, "A", "A", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
233 { -1, "I", "I", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
234 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
235 };
236
237 /* General */
238 NHCmdPadCell cells_layout_general[NH_CMDPAD_CELLNUM] = {
239 { -1, "q", "q", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
240 { -1, "e", "e", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
241 { -1, "l", "l", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
242 { -1, "s", "s", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
243 { -1, "E", "E", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
244 { -1, "\x01", "^A", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
245 (void *) - 1 },
246 { -1, "c", "c", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
247 { -1, "o", "o", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
248 { -1, "p", "p", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
249 { -1, ":", ":", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
250 { -1, ",", ",", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
251 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
252 };
253
254 /* game controls layout */
255 NHCmdPadCell cells_layout_game[NH_CMDPAD_CELLNUM] = {
256 { -1, "S", "S", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
257 { -1, "h", "h", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
258 { -1, "C", "C", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
259 { -1, "@", "@", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
260 { -1, "\\", "\\", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
261 { -1, "O", "O", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
262 { -1, "&", "&", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
263 { -1, "\x18", "^X", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
264 (void *) - 1 },
265 { -1, "\x10", "^P", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
266 (void *) - 1 },
267 { -1, "X", "X", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
268 { -1, "#", "#", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
269 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
270 };
271
272 /* advanced movement layout */
273 NHCmdPadCell cells_layout_adv_movement[NH_CMDPAD_CELLNUM] = {
274 { -1, "g", "g", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
275 (void *) NH_LAYOUT_MOVEMENT },
276 { -1, "G", "G", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
277 (void *) NH_LAYOUT_MOVEMENT },
278 { -1, "m", "m", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
279 (void *) NH_LAYOUT_MOVEMENT },
280 { -1, "M", "M", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
281 (void *) NH_LAYOUT_MOVEMENT },
282 { -1, "_", "_", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
283 { -1, "\x14", "^T", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
284 (void *) - 1 },
285 { -1, "j", "j", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
286 { -1, "<", "<", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
287 { -1, ">", ">", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
288 { -1, "^", "^", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
289 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
290 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
291 };
292
293 /* item lookup layout */
294 NHCmdPadCell cells_layout_lookup[NH_CMDPAD_CELLNUM] = {
295 { -1, ";", ";", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
296 { -1, "^", "^", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
297 { -1, "]", "]", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
298 { -1, ")", ")", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
299 { -1, "=", "=", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
300 { -1, "*", "*", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
301 { -1, "(", "(", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
302 { -1, "\"", "\"", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
303 { -1, "$", "$", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
304 { -1, "+", "+", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
305 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
306 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
307 };
308
309 /* wizard mode layout */
310 NHCmdPadCell cells_layout_wizard[NH_CMDPAD_CELLNUM] = {
311 { -1, "\x05", "^e", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
312 (void *) - 1 },
313 { -1, "\x06", "^f", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
314 (void *) - 1 },
315 { -1, "\x07", "^g", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
316 (void *) - 1 },
317 { -1, "\x09", "^i", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
318 (void *) - 1 },
319 { -1, "\x0f", "^o", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
320 (void *) - 1 },
321 { -1, "\x16", "^v", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
322 (void *) - 1 },
323 { -1, "\x17", "^w", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
324 (void *) - 1 },
325 { -1, "\x14", "^T", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1,
326 (void *) - 1 },
327 { -1, "#", "#", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
328 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
329 { -1, "", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
330 { -1, "X", "X", 13, NH_CELL_LAYOUT_MENU, 1, 0 }
331 };
332
333 #else /* !WIN_CE_SMARTPHONE */
334
335 /* dimensions of the command pad */
336 #define NH_CMDPAD_ROWS 4
337 #define NH_CMDPAD_COLS 14
338 #define NH_CMDPAD_CELLNUM (NH_CMDPAD_COLS * NH_CMDPAD_ROWS)
339
340 /* lowercase layout */
341 NHCmdPadCell cells_layout_mod1[NH_CMDPAD_ROWS * NH_CMDPAD_COLS] = {
342 { -1, "7", "7", 1, NH_CELL_REG, 1, (void *) - 1 },
343 { -1, "8", "8", 2, NH_CELL_REG, 1, (void *) - 1 },
344 { -1, "9", "9", 3, NH_CELL_REG, 1, (void *) - 1 },
345 { -1, "\x1b", "Esc", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 2, NULL },
346 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
347 NULL }, /* complement for ESC */
348 { -1, "?", "?", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
349 { -1, "*", "*", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
350 { -1, ",", ",", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
351 { -1, "/", "/", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
352 { -1, ":", ":", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
353 { -1, ";", ";", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
354 { -1, "-", "-", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
355 { -1, "#", "#", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
356 { -1, "^", "^", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
357
358 { -1, "4", "4", 4, NH_CELL_REG, 1, (void *) - 1 },
359 { -1, "5", "5", 5, NH_CELL_REG, 1, (void *) - 1 },
360 { -1, "6", "6", 6, NH_CELL_REG, 1, (void *) - 1 },
361 { -1, " ", "CAP", -NH_CMDPAD_FONT_NORMAL, NH_CELL_CAP, 2, NULL },
362 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
363 NULL }, /* complement for CAPS */
364 { -1, "a", "a", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
365 { -1, "b", "b", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
366 { -1, "c", "c", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
367 { -1, "d", "d", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
368 { -1, "e", "e", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
369 { -1, "f", "f", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
370 { -1, "g", "g", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
371 { -1, "h", "h", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
372 { -1, "i", "i", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
373
374 { -1, "1", "1", 7, NH_CELL_REG, 1, (void *) - 1 },
375 { -1, "2", "2", 8, NH_CELL_REG, 1, (void *) - 1 },
376 { -1, "3", "3", 9, NH_CELL_REG, 1, (void *) - 1 },
377 { -1, " ", "Shft", -NH_CMDPAD_FONT_NORMAL, NH_CELL_SHIFT, 2, NULL },
378 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
379 NULL }, /* complement for shift */
380 { -1, "j", "j", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
381 { -1, "k", "k", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
382 { -1, "l", "l", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
383 { -1, "m", "m", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
384 { -1, "n", "n", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
385 { -1, "o", "o", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
386 { -1, "p", "p", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
387 { -1, "q", "q", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
388 { -1, "r", "r", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
389
390 { -1, "<", "<", 10, NH_CELL_REG, 1, (void *) - 1 },
391 { -1, ".", ".", 11, NH_CELL_REG, 1, (void *) - 1 },
392 { -1, ">", ">", 12, NH_CELL_REG, 1, (void *) - 1 },
393 { -1, " ", "Ctrl", -NH_CMDPAD_FONT_NORMAL, NH_CELL_CTRL, 2, NULL },
394 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
395 NULL }, /* complement for CTRL */
396 { -1, "s", "s", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
397 { -1, "t", "t", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
398 { -1, "u", "u", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
399 { -1, "v", "v", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
400 { -1, "w", "w", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
401 { -1, "x", "x", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
402 { -1, "y", "y", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
403 { -1, "z", "z", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
404 { -1, "\\", "\\", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 }
405 };
406
407 /* uppercase layout */
408 NHCmdPadCell cells_layout_mod2[-NH_CMDPAD_ROWS * -NH_CMDPAD_COLS] = {
409 { -1, "7", "7", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
410 { -1, "8", "8", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
411 { -1, "9", "9", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
412 { -1, "\x1b", "Esc", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 2, NULL },
413 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
414 NULL }, /* complement for ESC */
415 { -1, "?", "?", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
416 { -1, "*", "*", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
417 { -1, "[", "[", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
418 { -1, "(", "(", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
419 { -1, ")", ")", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
420 { -1, "+", "+", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
421 { -1, "=", "=", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
422 { -1, "\"", "\"", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
423 { -1, "$", "$", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
424
425 { -1, "4", "4", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
426 { -1, "5", "5", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
427 { -1, "6", "6", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
428 { -1, " ", "CAP", -NH_CMDPAD_FONT_NORMAL, NH_CELL_CAP, 2, NULL },
429 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
430 NULL }, /* complement for CAPS */
431 { -1, "A", "A", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
432 { -1, "B", "B", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
433 { -1, "C", "C", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
434 { -1, "D", "D", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
435 { -1, "E", "E", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
436 { -1, "F", "F", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
437 { -1, "G", "G", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
438 { -1, "H", "H", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
439 { -1, "I", "I", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
440
441 { -1, "1", "1", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
442 { -1, "2", "2", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
443 { -1, "3", "3", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
444 { -1, " ", "Shft", -NH_CMDPAD_FONT_NORMAL, NH_CELL_SHIFT, 2, NULL },
445 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
446 NULL }, /* complement for shift */
447 { -1, "J", "J", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
448 { -1, "K", "K", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
449 { -1, "L", "L", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
450 { -1, "M", "M", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
451 { -1, "N", "N", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
452 { -1, "O", "O", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
453 { -1, "P", "P", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
454 { -1, "Q", "Q", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
455 { -1, "R", "R", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
456
457 { -1, "<", "<", 10, NH_CELL_REG, 1, (void *) - 1 },
458 { -1, "0", "0", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
459 { -1, ">", ">", 12, NH_CELL_REG, 1, (void *) - 1 },
460 { -1, " ", "Ctrl", -NH_CMDPAD_FONT_NORMAL, NH_CELL_CTRL, 2, NULL },
461 { -1, " ", "", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 0,
462 NULL }, /* complement for CTRL */
463 { -1, "S", "S", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
464 { -1, "T", "T", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
465 { -1, "U", "U", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
466 { -1, "V", "V", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
467 { -1, "W", "W", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
468 { -1, "X", "X", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
469 { -1, "Y", "Y", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
470 { -1, "Z", "Z", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 },
471 { -1, "@", "@", -NH_CMDPAD_FONT_NORMAL, NH_CELL_REG, 1, (void *) - 1 }
472 };
473
474 #endif /* !WIN_CE_SMARTPHONE */
475
476 /*-------------------------------------------------------------------------*/
477 HWND
mswin_init_command_window()478 mswin_init_command_window()
479 {
480 static int run_once = 0;
481 HWND ret;
482
483 /* register window class */
484 if (!run_once) {
485 register_command_window_class();
486 run_once = 1;
487 }
488
489 /* create window */
490 ret = CreateWindow(
491 szNHCmdWindowClass, /* registered class name */
492 NULL, /* window name */
493 WS_CHILD | WS_CLIPSIBLINGS, /* window style */
494 0, /* horizontal position of window - set it later */
495 0, /* vertical position of window - set it later */
496 0, /* window width - set it later */
497 0, /* window height - set it later*/
498 GetNHApp()->hMainWnd, /* handle to parent or owner window */
499 NULL, /* menu handle or child identifier */
500 GetNHApp()->hApp, /* handle to application instance */
501 NULL); /* window-creation data */
502 if (!ret) {
503 panic("Cannot create command window");
504 }
505 return ret;
506 }
507 /*-------------------------------------------------------------------------*/
508 /* calculate mimimum window size */
509 void
mswin_command_window_size(HWND hwnd,LPSIZE sz)510 mswin_command_window_size(HWND hwnd, LPSIZE sz)
511 {
512 SIZE cell_size;
513 PNHCmdWindow data;
514 data = (PNHCmdWindow) GetWindowLong(hwnd, GWL_USERDATA);
515 if (!data) {
516 sz->cx = sz->cy = 0;
517 } else {
518 CalculateCellSize(hwnd, &cell_size, sz);
519 sz->cx = max(cell_size.cx * nhcmdlayout_columns(data->layout_current)
520 + 2 * GetSystemMetrics(SM_CXBORDER),
521 sz->cx);
522 sz->cy = max(cell_size.cy * nhcmdlayout_rows(data->layout_current)
523 + 2 * GetSystemMetrics(SM_CYBORDER),
524 sz->cy);
525 }
526 }
527 /*-------------------------------------------------------------------------*/
528 void
register_command_window_class()529 register_command_window_class()
530 {
531 WNDCLASS wcex;
532 PNHCmdLayout plt;
533 ZeroMemory(&wcex, sizeof(wcex));
534
535 /* window class */
536 wcex.style = CS_NOCLOSE;
537 wcex.lpfnWndProc = (WNDPROC) NHCommandWndProc;
538 wcex.cbClsExtra = 0;
539 wcex.cbWndExtra = 0;
540 wcex.hInstance = GetNHApp()->hApp;
541 wcex.hIcon = NULL;
542 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
543 wcex.hbrBackground = mswin_get_brush(NHW_KEYPAD, MSWIN_COLOR_BG);
544 wcex.lpszMenuName = NULL;
545 wcex.lpszClassName = szNHCmdWindowClass;
546
547 if (!RegisterClass(&wcex)) {
548 panic("cannot register Map window class");
549 }
550
551 /* create default command set */
552 nhcmdset_current = nhcmdset_default = nhcmdset_create();
553
554 #ifdef WIN_CE_SMARTPHONE
555 plt = nhcmdlayout_create("General", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
556 nhcmdlayout_init(plt, cells_layout_general);
557 nhcmdset_add(nhcmdset_current, plt);
558
559 plt = nhcmdlayout_create("Movement", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
560 nhcmdlayout_init(plt, cells_layout_movement);
561 nhcmdset_add(nhcmdset_current, plt);
562
563 plt = nhcmdlayout_create("Attack", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
564 nhcmdlayout_init(plt, cells_layout_attack);
565 nhcmdset_add(nhcmdset_current, plt);
566
567 plt = nhcmdlayout_create("Item Handling", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
568 nhcmdlayout_init(plt, cells_layout_item_handling);
569 nhcmdset_add(nhcmdset_current, plt);
570
571 plt = nhcmdlayout_create("Game Controls", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
572 nhcmdlayout_init(plt, cells_layout_game);
573 nhcmdset_add(nhcmdset_current, plt);
574
575 plt = nhcmdlayout_create("Advanced Movement", NH_CMDPAD_ROWS,
576 NH_CMDPAD_COLS);
577 nhcmdlayout_init(plt, cells_layout_adv_movement);
578 nhcmdset_add(nhcmdset_current, plt);
579
580 plt = nhcmdlayout_create("Item Lookup", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
581 nhcmdlayout_init(plt, cells_layout_lookup);
582 nhcmdset_add(nhcmdset_current, plt);
583
584 if (wizard) {
585 plt =
586 nhcmdlayout_create("Wizard Mode", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
587 nhcmdlayout_init(plt, cells_layout_wizard);
588 nhcmdset_add(nhcmdset_current, plt);
589 }
590
591 #else /* ! WIN_CE_SMARTPHONE */
592 plt = nhcmdlayout_create("lowercase", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
593 nhcmdlayout_init(plt, cells_layout_mod1);
594 nhcmdset_add(nhcmdset_current, plt);
595
596 plt = nhcmdlayout_create("uppercase", NH_CMDPAD_ROWS, NH_CMDPAD_COLS);
597 nhcmdlayout_init(plt, cells_layout_mod2);
598 nhcmdset_add(nhcmdset_current, plt);
599 #endif /* WIN_CE_SMARTPHONE */
600 }
601 /*-------------------------------------------------------------------------*/
602 LRESULT CALLBACK
NHCommandWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)603 NHCommandWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
604 {
605 PNHCmdWindow data;
606 int i;
607
608 switch (message) {
609 case WM_CREATE:
610 onCreate(hWnd, wParam, lParam);
611 break;
612
613 case WM_PAINT:
614 onPaint(hWnd);
615 break;
616
617 case WM_SIZE:
618 LayoutCmdWindow(hWnd);
619 break;
620
621 case WM_LBUTTONDOWN:
622 onMouseDown(hWnd, wParam, lParam);
623 return 0;
624
625 case WM_MOUSEMOVE:
626 /* proceed only if if have mouse focus (set in onMouseDown() -
627 left mouse button is pressed) */
628 if (GetCapture() == hWnd) {
629 onMouseMove(hWnd, wParam, lParam);
630 return 0;
631 } else {
632 return 1;
633 }
634 break;
635
636 case WM_LBUTTONUP:
637 /* proceed only if if have mouse focus (set in onMouseDown()) */
638 if (GetCapture() == hWnd) {
639 onMouseUp(hWnd, wParam, lParam);
640 return 0;
641 } else {
642 return 1;
643 }
644 break;
645
646 case WM_DESTROY:
647 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
648 for (i = 0; i <= NH_CMDPAD_FONT_MAX; i++)
649 if (data->font[i])
650 DeleteObject(data->font[i]);
651 free(data);
652 SetWindowLong(hWnd, GWL_USERDATA, (LONG) 0);
653 break;
654
655 default:
656 return DefWindowProc(hWnd, message, wParam, lParam);
657 }
658 return FALSE;
659 }
660 /*-------------------------------------------------------------------------*/
661 void
onPaint(HWND hWnd)662 onPaint(HWND hWnd)
663 {
664 PNHCmdWindow data;
665 PAINTSTRUCT ps;
666 HDC hDC;
667 int x, y;
668 TCHAR wbuf[BUFSZ];
669 HGDIOBJ saveFont;
670 BITMAP bm;
671 int cell_index;
672
673 /* get window data */
674 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
675
676 hDC = BeginPaint(hWnd, &ps);
677
678 if (!IsRectEmpty(&ps.rcPaint)) {
679 HGDIOBJ oldBr;
680 HBRUSH hbrPattern;
681 COLORREF OldBg, OldFg;
682 HPEN hPen;
683 HGDIOBJ hOldPen;
684
685 saveFont = SelectObject(hDC, data->font[NH_CMDPAD_FONT_NORMAL]);
686 OldBg = SetBkColor(hDC, mswin_get_color(NHW_KEYPAD, MSWIN_COLOR_BG));
687 OldFg =
688 SetTextColor(hDC, mswin_get_color(NHW_KEYPAD, MSWIN_COLOR_FG));
689
690 GetObject(data->images, sizeof(BITMAP), (LPVOID) &bm);
691
692 hbrPattern = CreatePatternBrush(data->images);
693 hPen = CreatePen(PS_SOLID, 1,
694 mswin_get_color(NHW_KEYPAD, MSWIN_COLOR_FG));
695
696 for (x = 0, cell_index = 0;
697 x < nhcmdlayout_rows(data->layout_current); x++)
698 for (y = 0; y < nhcmdlayout_columns(data->layout_current);
699 y++, cell_index++) {
700 RECT cell_rt;
701 POINT pt[5];
702 PNHCmdPadCell p_cell_data;
703
704 p_cell_data =
705 nhcmdlayout_cell_direct(data->layout_current, cell_index);
706
707 /* calculate the cell rectangle */
708 cell_rt.left = data->cells[cell_index].orig.x;
709 cell_rt.top = data->cells[cell_index].orig.y;
710 cell_rt.right = data->cells[cell_index].orig.x
711 + data->cell_size.cx * p_cell_data->mult;
712 cell_rt.bottom =
713 data->cells[cell_index].orig.y + data->cell_size.cy;
714
715 /* draw border */
716 hOldPen = SelectObject(hDC, hPen);
717 pt[0].x = cell_rt.left;
718 pt[0].y = cell_rt.top;
719 pt[1].x = cell_rt.right;
720 pt[1].y = cell_rt.top;
721 pt[2].x = cell_rt.right;
722 pt[2].y = cell_rt.bottom;
723 pt[3].x = cell_rt.left;
724 pt[3].y = cell_rt.bottom;
725 pt[4].x = cell_rt.left;
726 pt[4].y = cell_rt.top;
727 Polyline(hDC, pt, 5);
728 SelectObject(hDC, hOldPen);
729
730 /* calculate clipping rectangle for the text */
731 cell_rt.left++;
732 cell_rt.top++;
733 cell_rt.right--;
734 cell_rt.bottom--;
735
736 /* draw the cell text */
737 if (p_cell_data->image <= 0) {
738 SelectObject(hDC, data->font[-p_cell_data->image]);
739 DrawText(hDC, NH_A2W(p_cell_data->text, wbuf, BUFSZ),
740 strlen(p_cell_data->text), &cell_rt,
741 DT_CENTER | DT_VCENTER | DT_SINGLELINE
742 | DT_NOPREFIX);
743 } else {
744 /* draw bitmap */
745 int bmOffset;
746 RECT bitmap_rt;
747
748 bmOffset = (p_cell_data->image - 1) * bm.bmHeight;
749
750 bitmap_rt.left =
751 ((cell_rt.left + cell_rt.right)
752 - min(bm.bmHeight, (cell_rt.right - cell_rt.left)))
753 / 2;
754 bitmap_rt.top =
755 ((cell_rt.bottom + cell_rt.top)
756 - min(bm.bmHeight, (cell_rt.bottom - cell_rt.top)))
757 / 2;
758 bitmap_rt.right =
759 bitmap_rt.left
760 + min(bm.bmHeight, (cell_rt.right - cell_rt.left));
761 bitmap_rt.bottom =
762 bitmap_rt.top
763 + min(bm.bmHeight, (cell_rt.bottom - cell_rt.top));
764
765 SetBrushOrgEx(hDC, bitmap_rt.left - bmOffset,
766 bitmap_rt.top, NULL);
767 oldBr = SelectObject(hDC, hbrPattern);
768 PatBlt(hDC, bitmap_rt.left, bitmap_rt.top,
769 bitmap_rt.right - bitmap_rt.left,
770 bitmap_rt.bottom - bitmap_rt.top, PATCOPY);
771 SelectObject(hDC, oldBr);
772 }
773
774 /* invert the cell if it is selected */
775 if (data->cells[cell_index].state == NH_CST_CHECKED) {
776 IntersectRect(&cell_rt, &cell_rt, &ps.rcPaint);
777 PatBlt(hDC, cell_rt.left, cell_rt.top,
778 cell_rt.right - cell_rt.left,
779 cell_rt.bottom - cell_rt.top, DSTINVERT);
780 }
781 }
782
783 SetTextColor(hDC, OldFg);
784 SetBkColor(hDC, OldBg);
785 SelectObject(hDC, saveFont);
786 DeleteObject(hbrPattern);
787 DeleteObject(hPen);
788 }
789 EndPaint(hWnd, &ps);
790 }
791 /*-------------------------------------------------------------------------*/
792 void
onCreate(HWND hWnd,WPARAM wParam,LPARAM lParam)793 onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
794 {
795 PNHCmdWindow data;
796
797 /* set window data */
798 data = (PNHCmdWindow) malloc(sizeof(NHCmdWindow));
799 if (!data)
800 panic("out of memory");
801
802 ZeroMemory(data, sizeof(NHCmdWindow));
803 SetWindowLong(hWnd, GWL_USERDATA, (LONG) data);
804
805 data->active_cell = -1;
806
807 /* load images bitmap */
808 data->images = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_KEYPAD));
809 if (!data->images)
810 panic("cannot load keypad bitmap");
811
812 /* create default layouts */
813 data->layout_current = 0;
814 data->layout_save = 0;
815 data->cells = 0;
816
817 #if defined(WIN_CE_SMARTPHONE)
818 data->layout_selected = nhcmdset_get(nhcmdset_current, 0);
819 #endif
820
821 /* set default layout */
822 SetCmdWindowLayout(hWnd, nhcmdset_get(nhcmdset_current, 0));
823 }
824 /*-------------------------------------------------------------------------*/
825 void
LayoutCmdWindow(HWND hWnd)826 LayoutCmdWindow(HWND hWnd)
827 {
828 RECT clrt;
829 SIZE windowSize;
830 PNHCmdWindow data;
831 int i, j;
832 int x, y;
833 LOGFONT lgfnt;
834 int index;
835
836 GetClientRect(hWnd, &clrt);
837 if (IsRectEmpty(&clrt))
838 return;
839
840 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
841 if (!data->layout_current)
842 return;
843
844 /* calculate cell size */
845 windowSize.cx = clrt.right - clrt.left;
846 windowSize.cy = clrt.bottom - clrt.top;
847 CalculateCellSize(hWnd, &data->cell_size, &windowSize);
848
849 /* initialize display cells aray */
850 x = 0;
851 y = 0;
852 for (i = 0, index = 0; i < nhcmdlayout_rows(data->layout_current); i++) {
853 for (j = 0; j < nhcmdlayout_columns(data->layout_current);
854 j++, index++) {
855 data->cells[index].orig.x = x;
856 data->cells[index].orig.y = y;
857 data->cells[index].type =
858 nhcmdlayout_cell_direct(data->layout_current, index)->type;
859
860 switch (data->cells[index].type) {
861 case NH_CELL_CTRL:
862 data->cells[index].state = data->is_ctrl ? NH_CST_CHECKED : 0;
863 break;
864 case NH_CELL_CAP:
865 data->cells[index].state = data->is_caps ? NH_CST_CHECKED : 0;
866 break;
867 case NH_CELL_SHIFT:
868 data->cells[index].state =
869 data->is_shift ? NH_CST_CHECKED : 0;
870 break;
871 default:
872 data->cells[index].state = 0;
873 }
874
875 x += data->cell_size.cx
876 * nhcmdlayout_cell_direct(data->layout_current, index)->mult;
877 }
878 x = 0;
879 y += data->cell_size.cy;
880 }
881
882 /* create font for display cell text */
883 for (i = 0; i <= NH_CMDPAD_FONT_MAX; i++)
884 if (data->font[i])
885 DeleteObject(data->font[i]);
886
887 ZeroMemory(&lgfnt, sizeof(lgfnt));
888 lgfnt.lfHeight = data->cell_size.cy; // height of font
889 lgfnt.lfWidth = 0; // average character width
890 lgfnt.lfEscapement = 0; // angle of escapement
891 lgfnt.lfOrientation = 0; // base-line orientation angle
892 lgfnt.lfWeight = FW_NORMAL; // font weight
893 lgfnt.lfItalic = FALSE; // italic attribute option
894 lgfnt.lfUnderline = FALSE; // underline attribute option
895 lgfnt.lfStrikeOut = FALSE; // strikeout attribute option
896 lgfnt.lfCharSet = ANSI_CHARSET; // character set identifier
897 lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision
898 lgfnt.lfClipPrecision = CLIP_CHARACTER_PRECIS; // clipping precision
899 lgfnt.lfQuality = DEFAULT_QUALITY; // output quality
900 if (iflags.wc_font_message && *iflags.wc_font_message) {
901 lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family
902 NH_A2W(iflags.wc_font_message, lgfnt.lfFaceName, LF_FACESIZE);
903 } else {
904 lgfnt.lfPitchAndFamily = VARIABLE_PITCH; // pitch and family
905 }
906 data->font[NH_CMDPAD_FONT_NORMAL] = CreateFontIndirect(&lgfnt);
907
908 InvalidateRect(hWnd, NULL, TRUE);
909 }
910 /*-------------------------------------------------------------------------*/
911 void
SetCmdWindowLayout(HWND hWnd,PNHCmdLayout layout)912 SetCmdWindowLayout(HWND hWnd, PNHCmdLayout layout)
913 {
914 PNHCmdWindow data;
915 int size;
916
917 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
918 if (data->layout_current == layout)
919 return;
920
921 data->layout_current = layout;
922 size = sizeof(NHCmdPadLayoutCell) * nhcmdlayout_rows(layout)
923 * nhcmdlayout_columns(layout);
924 data->cells = (PNHCmdPadLayoutCell) realloc(data->cells, size);
925 ZeroMemory(data->cells, size);
926 LayoutCmdWindow(hWnd);
927 }
928 /*-------------------------------------------------------------------------*/
929 void
onMouseDown(HWND hWnd,WPARAM wParam,LPARAM lParam)930 onMouseDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
931 {
932 PNHCmdWindow data;
933 POINT mpt;
934
935 /* get mouse coordinates */
936 mpt.x = LOWORD(lParam);
937 mpt.y = HIWORD(lParam);
938
939 /* map mouse coordinates to the display cell */
940 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
941 data->active_cell = CellFromPoint(data, mpt);
942 if (data->active_cell == -1)
943 return;
944
945 /* set mouse focus to the current window */
946 SetCapture(hWnd);
947
948 /* invert the selection */
949 HighlightCell(hWnd, data->active_cell,
950 (data->cells[data->active_cell].state != NH_CST_CHECKED));
951 }
952 /*-------------------------------------------------------------------------*/
953 void
onMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)954 onMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
955 {
956 PNHCmdWindow data;
957 POINT mpt;
958 int newActiveCell;
959
960 /* get mouse coordinates */
961 mpt.x = LOWORD(lParam);
962 mpt.y = HIWORD(lParam);
963
964 /* map mouse coordinates to the display cell */
965 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
966 newActiveCell = CellFromPoint(data, mpt);
967 if (data->active_cell == -1)
968 return;
969
970 /* if mouse is within orginal display cell - select the cell otherwise
971 clear the selection */
972 switch (nhcmdlayout_cell_direct(data->layout_current, data->active_cell)
973 ->type) {
974 case NH_CELL_REG:
975 HighlightCell(hWnd, data->active_cell,
976 (newActiveCell == data->active_cell));
977 break;
978
979 case NH_CELL_CTRL:
980 HighlightCell(hWnd, data->active_cell,
981 ((newActiveCell == data->active_cell) ? !data->is_ctrl
982 : data->is_ctrl));
983 break;
984
985 case NH_CELL_CAP:
986 HighlightCell(hWnd, data->active_cell,
987 ((newActiveCell == data->active_cell) ? !data->is_caps
988 : data->is_caps));
989 break;
990 }
991 }
992 /*-------------------------------------------------------------------------*/
993 void
onMouseUp(HWND hWnd,WPARAM wParam,LPARAM lParam)994 onMouseUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
995 {
996 PNHCmdWindow data;
997
998 /* release mouse capture */
999 ReleaseCapture();
1000
1001 /* get active display cell */
1002 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
1003 if (data->active_cell == -1)
1004 return;
1005
1006 ActivateCell(hWnd, data->active_cell);
1007
1008 data->active_cell = -1;
1009 }
1010 /*-------------------------------------------------------------------------*/
1011 void
ActivateCell(HWND hWnd,int cell)1012 ActivateCell(HWND hWnd, int cell)
1013 {
1014 PNHCmdWindow data;
1015 PNHCmdPadCell p_cell_data;
1016 int i;
1017
1018 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
1019 if (!data)
1020 return;
1021 p_cell_data = nhcmdlayout_cell_direct(data->layout_current, cell);
1022
1023 /* act depending on the cell type:
1024 CAPS - change layout
1025 CTRL - modify CTRL status
1026 REG - place keyboard event on the nethack input queue
1027 */
1028 switch (p_cell_data->type) {
1029 case NH_CELL_REG:
1030 if (data->is_ctrl) {
1031 PushNethackCommand(p_cell_data->f_char, 1);
1032
1033 data->is_ctrl = 0;
1034 for (i = 0; i < nhcmdlayout_rows(data->layout_current)
1035 * nhcmdlayout_columns(data->layout_current);
1036 i++) {
1037 if (nhcmdlayout_cell_direct(data->layout_current, i)->type
1038 == NH_CELL_CTRL) {
1039 HighlightCell(hWnd, i, data->is_ctrl);
1040 }
1041 }
1042 } else {
1043 PushNethackCommand(p_cell_data->f_char, 0);
1044 }
1045 HighlightCell(hWnd, cell, FALSE);
1046
1047 // select a new layout if present
1048 i = (int) p_cell_data->data;
1049 if (i == -1) {
1050 if (data->layout_save)
1051 SetCmdWindowLayout(hWnd, data->layout_save);
1052 data->layout_save = NULL;
1053 } else {
1054 if (!data->layout_save)
1055 data->layout_save = data->layout_current;
1056 SetCmdWindowLayout(hWnd, nhcmdset_get(nhcmdset_current, i));
1057 }
1058
1059 if (!data->is_shift)
1060 break;
1061 // else fall through and reset the shift
1062
1063 case NH_CELL_SHIFT:
1064 data->is_shift = !data->is_shift;
1065 SetCmdWindowLayout(hWnd, (data->is_shift ^ data->is_caps)
1066 ? nhcmdset_get(nhcmdset_current, 1)
1067 : nhcmdset_get(nhcmdset_current, 0));
1068 data->cells[cell].state = data->is_shift ? NH_CST_CHECKED : 0;
1069 InvalidateRect(hWnd, NULL, TRUE);
1070 break;
1071
1072 case NH_CELL_CTRL:
1073 data->is_ctrl = !data->is_ctrl;
1074 HighlightCell(hWnd, cell, data->is_ctrl);
1075 break;
1076
1077 case NH_CELL_CAP:
1078 data->is_caps = !data->is_caps;
1079 SetCmdWindowLayout(hWnd, (data->is_shift ^ data->is_caps)
1080 ? nhcmdset_get(nhcmdset_current, 1)
1081 : nhcmdset_get(nhcmdset_current, 0));
1082 data->cells[cell].state = data->is_caps ? NH_CST_CHECKED : 0;
1083 InvalidateRect(hWnd, NULL, TRUE);
1084 break;
1085
1086 case NH_CELL_LAYOUT_NEW: {
1087 PNHCmdLayout pLayout;
1088
1089 HighlightCell(hWnd, cell, FALSE);
1090
1091 pLayout = (PNHCmdLayout) p_cell_data->data;
1092 if (pLayout) {
1093 SetCmdWindowLayout(hWnd, pLayout);
1094 }
1095 } break;
1096
1097 case NH_CELL_LAYOUT_MENU: {
1098 winid wid;
1099 int i;
1100 anything any;
1101 menu_item *selected = 0;
1102 PNHCmdSet pSet;
1103
1104 HighlightCell(hWnd, cell, FALSE);
1105
1106 pSet = (PNHCmdSet) p_cell_data->data;
1107 if (!pSet)
1108 pSet = nhcmdset_default;
1109
1110 wid = mswin_create_nhwindow(NHW_MENU);
1111 mswin_start_menu(wid, MENU_BEHAVE_STANDARD);
1112 for (i = 0; i < nhcmdset_count(pSet); i++) {
1113 any.a_void = nhcmdset_get(pSet, i);
1114 mswin_add_menu(wid, NO_GLYPH, &any, 'a' + i, 0, ATR_NONE,
1115 nhcmdset_get_name(pSet, i), FALSE);
1116 }
1117 mswin_end_menu(wid, "Select keypad layout");
1118 i = select_menu(wid, PICK_ONE, &selected);
1119 mswin_destroy_nhwindow(wid);
1120
1121 if (i == 1) {
1122 #if defined(WIN_CE_SMARTPHONE)
1123 data->layout_selected = (PNHCmdLayout) selected[0].item.a_void;
1124 #endif
1125 SetCmdWindowLayout(hWnd, (PNHCmdLayout) selected[0].item.a_void);
1126 }
1127 } break;
1128 }
1129 }
1130 /*-------------------------------------------------------------------------*/
1131 int
CellFromPoint(PNHCmdWindow data,POINT pt)1132 CellFromPoint(PNHCmdWindow data, POINT pt)
1133 {
1134 int i;
1135 for (i = 0; i < nhcmdlayout_rows(data->layout_current)
1136 * nhcmdlayout_columns(data->layout_current);
1137 i++) {
1138 RECT cell_rt;
1139 cell_rt.left = data->cells[i].orig.x;
1140 cell_rt.top = data->cells[i].orig.y;
1141 cell_rt.right =
1142 data->cells[i].orig.x
1143 + data->cell_size.cx
1144 * nhcmdlayout_cell_direct(data->layout_current, i)->mult;
1145 cell_rt.bottom = data->cells[i].orig.y + data->cell_size.cy;
1146 if (PtInRect(&cell_rt, pt))
1147 return i;
1148 }
1149 return -1;
1150 }
1151 /*-------------------------------------------------------------------------*/
1152 void
CalculateCellSize(HWND hWnd,LPSIZE pSize,LPSIZE pWindowSize)1153 CalculateCellSize(HWND hWnd, LPSIZE pSize, LPSIZE pWindowSize)
1154 {
1155 HDC hdc;
1156 PNHCmdWindow data;
1157 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
1158 if (!data)
1159 return;
1160
1161 hdc = GetDC(hWnd);
1162
1163 /* if windows size is specified - attempt ro stretch cells across
1164 the window size. If not - make default cell size based on
1165 10 points font. Make sure that cell cesize does not exceeds 20 points
1166 */
1167 if (pWindowSize->cx > 0)
1168 pSize->cx =
1169 pWindowSize->cx / nhcmdlayout_columns(data->layout_current);
1170 else
1171 pSize->cx = 10 * GetDeviceCaps(hdc, LOGPIXELSX) / 72;
1172 pSize->cx = min(pSize->cx, 20 * GetDeviceCaps(hdc, LOGPIXELSX) / 72);
1173
1174 if (pWindowSize->cy > 0)
1175 pSize->cy = pWindowSize->cy / nhcmdlayout_rows(data->layout_current);
1176 else
1177 pSize->cy = 10 * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
1178 pSize->cy = min(pSize->cy, 20 * GetDeviceCaps(hdc, LOGPIXELSY) / 72);
1179
1180 ReleaseDC(hWnd, hdc);
1181 }
1182 /*-------------------------------------------------------------------------*/
1183 void
HighlightCell(HWND hWnd,int cell,BOOL isSelected)1184 HighlightCell(HWND hWnd, int cell, BOOL isSelected)
1185 {
1186 HDC hDC;
1187 PNHCmdWindow data;
1188 int prevState;
1189
1190 data = (PNHCmdWindow) GetWindowLong(hWnd, GWL_USERDATA);
1191 prevState = data->cells[cell].state;
1192 data->cells[cell].state = (isSelected) ? NH_CST_CHECKED : 0;
1193
1194 if (prevState != data->cells[cell].state) {
1195 hDC = GetDC(hWnd);
1196 PatBlt(hDC, data->cells[cell].orig.x + 1,
1197 data->cells[cell].orig.y + 1,
1198 data->cell_size.cx
1199 * nhcmdlayout_cell_direct(data->layout_current, cell)
1200 ->mult
1201 - 2,
1202 data->cell_size.cy - 2, DSTINVERT);
1203 ReleaseDC(hWnd, hDC);
1204 }
1205 }
1206 /*-------------------------------------------------------------------------*/
1207 void
PushNethackCommand(const char * cmd_char_str,int is_ctrl)1208 PushNethackCommand(const char *cmd_char_str, int is_ctrl)
1209 {
1210 while (*cmd_char_str) {
1211 if (is_ctrl) {
1212 NHEVENT_KBD(C(*cmd_char_str));
1213 } else {
1214 NHEVENT_KBD(*cmd_char_str);
1215 }
1216 cmd_char_str++;
1217 }
1218 }
1219
1220 /*-------------------------------------------------------------------------*/
1221 /*------------------- keyboard keys layout functions ----------------------*/
1222 /*-------------------------------------------------------------------------*/
1223 PNHCmdLayout
nhcmdlayout_create(const char * name,int rows,int columns)1224 nhcmdlayout_create(const char *name, int rows, int columns)
1225 {
1226 PNHCmdLayout p;
1227 int i;
1228
1229 i = sizeof(NHCmdLayout) + rows * columns * sizeof(NHCmdPadCell);
1230 p = (PNHCmdLayout) malloc(i);
1231 ZeroMemory(p, i);
1232 p->rows = rows;
1233 p->columns = columns;
1234 strncpy(p->name, name, sizeof(p->name) - 1);
1235 for (i = 0; i < rows * columns; i++) {
1236 p->cells[i].cmd_code = -1;
1237 p->cells[i].image = -NH_CMDPAD_FONT_NORMAL;
1238 p->cells[i].type = 1;
1239 p->cells[i].mult = 1;
1240 }
1241 return p;
1242 }
1243 /*-------------------------------------------------------------------------*/
1244 void
nhcmdlayout_init(PNHCmdLayout p,PNHCmdPadCell cells)1245 nhcmdlayout_init(PNHCmdLayout p, PNHCmdPadCell cells)
1246 {
1247 memcpy(p->cells, cells, p->rows * p->columns * sizeof(NHCmdPadCell));
1248 }
1249
1250 void
nhcmdlayout_destroy(PNHCmdLayout p)1251 nhcmdlayout_destroy(PNHCmdLayout p)
1252 {
1253 free(p);
1254 }
1255
1256 /*-------------------------------------------------------------------------*/
1257 /*----------------- keyboard keys layout set functions --------------------*/
1258 /*-------------------------------------------------------------------------*/
1259 PNHCmdSet
nhcmdset_create()1260 nhcmdset_create()
1261 {
1262 PNHCmdSet p;
1263 p = (PNHCmdSet) malloc(sizeof(NHCmdSet));
1264 ZeroMemory(p, sizeof(NHCmdSet));
1265 return p;
1266 }
1267 /*-------------------------------------------------------------------------*/
1268 int
nhcmdset_count(PNHCmdSet p)1269 nhcmdset_count(PNHCmdSet p)
1270 {
1271 assert(p);
1272 return p->count;
1273 }
1274 /*-------------------------------------------------------------------------*/
1275 PNHCmdLayout
nhcmdset_get(PNHCmdSet p,int index)1276 nhcmdset_get(PNHCmdSet p, int index)
1277 {
1278 assert(p);
1279 assert(index >= 0 && index < p->count);
1280 return p->elements[index].layout;
1281 }
1282 /*-------------------------------------------------------------------------*/
1283 const char *
nhcmdset_get_name(PNHCmdSet p,int index)1284 nhcmdset_get_name(PNHCmdSet p, int index)
1285 {
1286 assert(p);
1287 assert(index >= 0 && index < p->count);
1288 return p->elements[index].layout->name;
1289 }
1290 /*-------------------------------------------------------------------------*/
1291 void
nhcmdset_add(PNHCmdSet p,PNHCmdLayout layout)1292 nhcmdset_add(PNHCmdSet p, PNHCmdLayout layout)
1293 {
1294 assert(p);
1295 assert(p->count < NH_CMDSET_MAXSIZE);
1296 p->elements[p->count].layout = layout;
1297 p->elements[p->count].free_on_destroy = 0;
1298 p->count++;
1299 }
1300 /*-------------------------------------------------------------------------*/
1301 void
nhcmdset_destroy(PNHCmdSet p)1302 nhcmdset_destroy(PNHCmdSet p)
1303 {
1304 int i = 0;
1305 assert(p);
1306 for (i = 0; i < p->count; i++) {
1307 if (p->elements[i].free_on_destroy) {
1308 nhcmdlayout_destroy(p->elements[i].layout);
1309 }
1310 }
1311 free(p);
1312 }
1313 /*-------------------------------------------------------------------------*/
1314
1315 #if defined(WIN_CE_SMARTPHONE)
1316 /* special keypad input handling for SmartPhone
1317 the phone keypad maps to VK_* as shown below.
1318 some keys might not be present, e.g. VK_TFLIP
1319 sofkey1 softkey2 VK_TSOFT1, VK_TSOFT2
1320 ^ VK_TUP
1321 < + > VK_TLEFT, VK_TACTION, VK_TRIGHT
1322 v VK_TDOWN
1323 home back VK_THOME, VK_TBACK
1324 talk end VK_TTALK, VK_TEND
1325 1 2 3 VK_T0..VK_T9
1326 4 5 6 ...
1327 7 8 9 ...
1328 * 0 # VK_TSTAR, VK_TPOUND
1329 other buttons include
1330 VK_TRECORD
1331 VK_TPOWER, VK_TVOLUMEUP, VK_TVOLUMEDOWN
1332 VK_TFLIP
1333 */
1334 BOOL
NHSPhoneTranslateKbdMessage(WPARAM wParam,LPARAM lParam,BOOL keyDown)1335 NHSPhoneTranslateKbdMessage(WPARAM wParam, LPARAM lParam, BOOL keyDown)
1336 {
1337 PNHCmdWindow data;
1338 int index = -1;
1339
1340 /* get window data */
1341 data = (PNHCmdWindow) GetWindowLong(GetNHApp()->hCmdWnd, GWL_USERDATA);
1342 if (!data)
1343 return FALSE;
1344
1345 switch (wParam) {
1346 case VK_T0:
1347 index = 10;
1348 break;
1349
1350 case VK_T1:
1351 index = 0;
1352 break;
1353
1354 case VK_T2:
1355 index = 1;
1356 break;
1357
1358 case VK_T3:
1359 index = 2;
1360 break;
1361
1362 case VK_T4:
1363 index = 3;
1364 break;
1365
1366 case VK_T5:
1367 index = 4;
1368 break;
1369
1370 case VK_T6:
1371 index = 5;
1372 break;
1373
1374 case VK_T7:
1375 index = 6;
1376 break;
1377
1378 case VK_T8:
1379 index = 7;
1380 break;
1381
1382 case VK_T9:
1383 index = 8;
1384 break;
1385
1386 case VK_TSTAR:
1387 index = 9;
1388 break;
1389
1390 case VK_TPOUND:
1391 index = 11;
1392 break;
1393 }
1394
1395 if (index >= 0) {
1396 HighlightCell(GetNHApp()->hCmdWnd, index, keyDown);
1397 if (keyDown)
1398 ActivateCell(GetNHApp()->hCmdWnd, index);
1399 return TRUE;
1400 } else {
1401 return FALSE;
1402 }
1403 }
1404 /*-------------------------------------------------------------------------*/
1405 void
NHSPhoneSetKeypadFromString(const char * str)1406 NHSPhoneSetKeypadFromString(const char *str)
1407 {
1408 PNHCmdWindow data;
1409 PNHCmdSet p = 0;
1410 PNHCmdLayout layout_prev = 0;
1411 PNHCmdLayout layout_cur = 0;
1412 char buf[2][BUFSZ];
1413 int i, lcount;
1414 char *s;
1415
1416 assert(NH_CMDPAD_ROWS == 4);
1417
1418 data = (PNHCmdWindow) GetWindowLong(GetNHApp()->hCmdWnd, GWL_USERDATA);
1419 if (!data)
1420 return;
1421
1422 p = nhcmdset_create();
1423
1424 ZeroMemory(buf, sizeof(buf));
1425 if (sscanf(str, "%s or %s", buf[1], buf[0]) != 2) {
1426 ZeroMemory(buf, sizeof(buf));
1427 strncpy(buf[0], str, sizeof(buf[0]) - 1);
1428 }
1429
1430 lcount = 10; /* create new layout on the first iteration */
1431 for (i = 0; i < 2; i++) {
1432 s = buf[i];
1433 while (*s) {
1434 char c_start, c_end, c_char;
1435
1436 /* parse character ranges */
1437 if (isalnum((c_start = s[0])) && s[1] == '-'
1438 && isalnum((c_end = s[2]))) {
1439 s += 2;
1440 } else {
1441 c_start = c_end = *s;
1442 }
1443
1444 for (c_char = c_start; c_char <= c_end; c_char++) {
1445 if (lcount >= 10) {
1446 /* create layout */
1447 lcount = 0;
1448 layout_prev = layout_cur;
1449 layout_cur = nhcmdlayout_create("noname", NH_CMDPAD_ROWS,
1450 NH_CMDPAD_COLS);
1451 nhcmdlayout_init(layout_cur, cells_layout_menu);
1452
1453 nhcmdlayout_cell(layout_cur, 3, 0)->data = layout_prev;
1454 nhcmdlayout_cell(layout_cur, 3, 2)->data = 0;
1455
1456 nhcmdset_add(p, layout_cur);
1457 p->elements[p->count - 1].free_on_destroy = 1;
1458
1459 if (layout_prev) {
1460 nhcmdlayout_cell(layout_prev, 3, 2)->data =
1461 layout_cur;
1462 }
1463 }
1464
1465 if (lcount == 9)
1466 lcount = 10; // skip '#'
1467 nhcmdlayout_cell_direct(layout_cur, lcount)->f_char[0] =
1468 c_char;
1469 if (c_char == '\033') {
1470 strcpy(nhcmdlayout_cell_direct(layout_cur, lcount)->text,
1471 "esc");
1472 nhcmdlayout_cell_direct(layout_cur, lcount)->image =
1473 14; /* 14 is a ESC symbol in IDB_KEYPAD */
1474 } else {
1475 nhcmdlayout_cell_direct(layout_cur, lcount)->text[0] =
1476 c_char;
1477 nhcmdlayout_cell_direct(layout_cur, lcount)->text[1] =
1478 '\x0';
1479 }
1480
1481 /* increment character count in the current layout */
1482 lcount++;
1483 }
1484
1485 /* prepareg next charcter from the source string */
1486 s++;
1487 }
1488 }
1489
1490 /* install the new set */
1491 if (nhcmdset_current != nhcmdset_default)
1492 nhcmdset_destroy(nhcmdset_current);
1493 nhcmdset_current = p;
1494 SetCmdWindowLayout(GetNHApp()->hCmdWnd,
1495 nhcmdset_get(nhcmdset_current, 0));
1496 }
1497 /*-------------------------------------------------------------------------*/
1498 void
NHSPhoneSetKeypadDirection()1499 NHSPhoneSetKeypadDirection()
1500 {
1501 PNHCmdWindow data;
1502
1503 data = (PNHCmdWindow) GetWindowLong(GetNHApp()->hCmdWnd, GWL_USERDATA);
1504 if (!data)
1505 return;
1506
1507 if (nhcmdset_current != nhcmdset_default)
1508 nhcmdset_destroy(nhcmdset_current);
1509 nhcmdset_current = nhcmdset_default;
1510 SetCmdWindowLayout(GetNHApp()->hCmdWnd,
1511 nhcmdset_get(nhcmdset_current, NH_LAYOUT_MOVEMENT));
1512 }
1513 /*-------------------------------------------------------------------------*/
1514 void
NHSPhoneSetKeypadDefault()1515 NHSPhoneSetKeypadDefault()
1516 {
1517 PNHCmdWindow data;
1518
1519 data = (PNHCmdWindow) GetWindowLong(GetNHApp()->hCmdWnd, GWL_USERDATA);
1520 if (!data)
1521 return;
1522
1523 if (nhcmdset_current != nhcmdset_default)
1524 nhcmdset_destroy(nhcmdset_current);
1525 nhcmdset_current = nhcmdset_default;
1526 SetCmdWindowLayout(GetNHApp()->hCmdWnd,
1527 data->layout_selected
1528 ? data->layout_selected
1529 : nhcmdset_get(nhcmdset_current, 0));
1530 }
1531
1532 #endif /* defined (WIN_CE_SMARTHPONE) */
1533