OSDN Git Service

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