OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / wince / mhcmd.c
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
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
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
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
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
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
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
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
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
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
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
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
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);
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
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
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
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
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
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
1245 nhcmdlayout_init(PNHCmdLayout p, PNHCmdPadCell cells)
1246 {
1247     memcpy(p->cells, cells, p->rows * p->columns * sizeof(NHCmdPadCell));
1248 }
1249
1250 void
1251 nhcmdlayout_destroy(PNHCmdLayout p)
1252 {
1253     free(p);
1254 }
1255
1256 /*-------------------------------------------------------------------------*/
1257 /*----------------- keyboard keys layout set functions --------------------*/
1258 /*-------------------------------------------------------------------------*/
1259 PNHCmdSet
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
1269 nhcmdset_count(PNHCmdSet p)
1270 {
1271     assert(p);
1272     return p->count;
1273 }
1274 /*-------------------------------------------------------------------------*/
1275 PNHCmdLayout
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 *
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
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
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
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
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
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
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) */