OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / sys / wince / mhdlg.c
1 /* NetHack 3.6  mhdlg.c $NHDT-Date: 1432512802 2015/05/25 00:13:22 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
2 /* Copyright (C) 2001 by Alex Kompel     */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* various dialog boxes are defined here */
6
7 #include "winMS.h"
8 #include "hack.h"
9 #include "func_tab.h"
10 #include "mhdlg.h"
11 #include "mhmain.h"
12
13 #define CheckDlgButton(dlg, btn_id, st) \
14     SendDlgItemMessage((dlg), (btn_id), BM_SETCHECK, (WPARAM)(st), 0)
15
16 /*---------------------------------------------------------------*/
17 /* data for getlin dialog */
18 struct getlin_data {
19     const char *question;
20     char *result;
21     size_t result_size;
22 };
23
24 LRESULT CALLBACK GetlinDlgProc(HWND, UINT, WPARAM, LPARAM);
25
26 int
27 mswin_getlin_window(const char *question, char *result, size_t result_size)
28 {
29     int ret;
30     struct getlin_data data;
31
32     /* initilize dialog data */
33     ZeroMemory(&data, sizeof(data));
34     data.question = question;
35     data.result = result;
36     data.result_size = result_size;
37
38     /* create modal dialog window */
39     ret = DialogBoxParam(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_GETLIN),
40                          GetNHApp()->hMainWnd, GetlinDlgProc, (LPARAM) &data);
41     if (ret == -1)
42         panic("Cannot create getlin window");
43
44     return ret;
45 }
46
47 LRESULT CALLBACK
48 GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
49 {
50     struct getlin_data *data;
51     RECT main_rt, text_rt, dlg_rt, edit_rt;
52     SIZE dlg_sz;
53     TCHAR wbuf[BUFSZ];
54     HDC hdc;
55     HWND control;
56     HWND hwndMap;
57
58 #if defined(WIN_CE_POCKETPC)
59     SHInputDialog(hWnd, message, wParam);
60 #endif
61
62     switch (message) {
63     case WM_INITDIALOG:
64         data = (struct getlin_data *) lParam;
65         SetWindowText(hWnd, NH_A2W(data->question, wbuf, sizeof(wbuf)));
66         SetWindowLong(hWnd, GWL_USERDATA, lParam);
67
68         /* get title text width */
69         SetRect(&text_rt, 0, 0, 100, 50);
70         hdc = GetWindowDC(hWnd);
71         DrawText(hdc, wbuf, _tcslen(wbuf), &text_rt,
72                  DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX | DT_LEFT
73                      | DT_VCENTER);
74         ReleaseDC(hWnd, hdc);
75
76         /* center dialog in the main window */
77         GetWindowRect(hWnd, &dlg_rt);
78         hwndMap = mswin_hwnd_from_winid(WIN_MAP);
79         GetWindowRect(IsWindow(hwndMap) ? hwndMap : GetNHApp()->hMainWnd,
80                       &main_rt);
81         dlg_sz.cx = max(
82             dlg_rt.right - dlg_rt.left,
83             min(text_rt.right - text_rt.left + GetSystemMetrics(SM_CXICON),
84                 main_rt.right - main_rt.left));
85         dlg_sz.cy =
86             min(dlg_rt.bottom - dlg_rt.top, main_rt.bottom - main_rt.top);
87         dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
88         dlg_rt.right = dlg_rt.left + dlg_sz.cx;
89         dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
90         dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
91         MoveWindow(hWnd, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
92                    (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
93                    dlg_sz.cy, TRUE);
94
95         /* change layout of controls */
96         GetClientRect(hWnd, &dlg_rt);
97
98         control = GetDlgItem(hWnd, IDC_GETLIN_EDIT);
99         GetWindowRect(control, &edit_rt);
100         MoveWindow(control, 0, 0, dlg_rt.right - dlg_rt.left,
101                    edit_rt.bottom - edit_rt.top, TRUE);
102
103         control = GetDlgItem(hWnd, IDOK);
104         GetWindowRect(control, &text_rt);
105         MoveWindow(control, 0, edit_rt.bottom - edit_rt.top,
106                    (dlg_rt.right - dlg_rt.left) / 2,
107                    text_rt.bottom - text_rt.top, TRUE);
108
109         control = GetDlgItem(hWnd, IDCANCEL);
110         GetWindowRect(control, &text_rt);
111         MoveWindow(control, (dlg_rt.right - dlg_rt.left) / 2,
112                    edit_rt.bottom - edit_rt.top,
113                    (dlg_rt.right - dlg_rt.left) / 2,
114                    text_rt.bottom - text_rt.top, TRUE);
115
116 #if defined(WIN_CE_SMARTPHONE)
117         NHSPhoneDialogSetup(hWnd, IDC_SPHONE_DIALOGBAR, TRUE, FALSE);
118 #endif
119
120         /* set focus to the edit control */
121         SetFocus(GetDlgItem(hWnd, IDC_GETLIN_EDIT));
122
123         /* tell windows that we've set the focus */
124         return FALSE;
125         break;
126
127     case WM_COMMAND: {
128         TCHAR wbuf[BUFSZ];
129
130         switch (LOWORD(wParam)) {
131         /* OK button was pressed */
132         case IDOK:
133             data = (struct getlin_data *) GetWindowLong(hWnd, GWL_USERDATA);
134             SendDlgItemMessage(hWnd, IDC_GETLIN_EDIT, WM_GETTEXT,
135                                (WPARAM) sizeof(wbuf), (LPARAM) wbuf);
136             NH_W2A(wbuf, data->result, data->result_size);
137
138         /* Fall through. */
139
140         /* cancel button was pressed */
141         case IDCANCEL:
142             EndDialog(hWnd, wParam);
143             return TRUE;
144         }
145     } break;
146
147 #if defined(WIN_CE_SMARTPHONE)
148     case WM_HOTKEY:
149         if (VK_TBACK == HIWORD(lParam)) {
150             SHSendBackToFocusWindow(message, wParam, lParam);
151         }
152         break;
153 #endif
154
155     } /* end switch (message) */
156     return FALSE;
157 }
158
159 /*---------------------------------------------------------------*/
160 /* dialog data for the list of extended commands */
161 struct extcmd_data {
162     int *selection;
163 };
164
165 LRESULT CALLBACK ExtCmdDlgProc(HWND, UINT, WPARAM, LPARAM);
166
167 int
168 mswin_ext_cmd_window(int *selection)
169 {
170     int ret;
171     struct extcmd_data data;
172
173     /* init dialog data */
174     ZeroMemory(&data, sizeof(data));
175     *selection = -1;
176     data.selection = selection;
177
178     /* create modal dialog window */
179     ret = DialogBoxParam(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_EXTCMD),
180                          GetNHApp()->hMainWnd, ExtCmdDlgProc, (LPARAM) &data);
181     if (ret == -1)
182         panic("Cannot create extcmd window");
183     return ret;
184 }
185
186 LRESULT CALLBACK
187 ExtCmdDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
188 {
189     struct extcmd_data *data;
190     RECT main_rt, dlg_rt;
191     SIZE dlg_sz;
192     int i;
193     const char *ptr;
194     TCHAR wbuf[255];
195
196     switch (message) {
197     case WM_INITDIALOG:
198         data = (struct extcmd_data *) lParam;
199         SetWindowLong(hWnd, GWL_USERDATA, lParam);
200
201         /* center dialog in the main window */
202         GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
203         GetWindowRect(hWnd, &dlg_rt);
204         dlg_sz.cx = dlg_rt.right - dlg_rt.left;
205         dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
206
207         dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
208         dlg_rt.right = dlg_rt.left + dlg_sz.cx;
209         dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
210         dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
211         MoveWindow(hWnd, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
212                    (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
213                    dlg_sz.cy, TRUE);
214
215         /* fill combobox with extended commands */
216         for (i = 0; (ptr = extcmdlist[i].ef_txt); i++) {
217             SendDlgItemMessage(hWnd, IDC_EXTCMD_LIST, LB_ADDSTRING,
218                                (WPARAM) 0,
219                                (LPARAM) NH_A2W(ptr, wbuf, sizeof(wbuf)));
220         }
221
222 #if defined(WIN_CE_SMARTPHONE)
223         NHSPhoneDialogSetup(hWnd, IDC_SPHONE_DIALOGBAR, FALSE, FALSE);
224
225         GetClientRect(hWnd, &dlg_rt);
226         MoveWindow(GetDlgItem(hWnd, IDC_EXTCMD_LIST), dlg_rt.left, dlg_rt.top,
227                    dlg_rt.right - dlg_rt.left, dlg_rt.bottom - dlg_rt.top,
228                    TRUE);
229 #endif
230
231         /* set focus to the list control */
232         SetFocus(GetDlgItem(hWnd, IDC_EXTCMD_LIST));
233
234         /* tell windows we set the focus */
235         return FALSE;
236         break;
237
238     case WM_COMMAND:
239         data = (struct extcmd_data *) GetWindowLong(hWnd, GWL_USERDATA);
240         switch (LOWORD(wParam)) {
241         /* OK button ws clicked */
242         case IDOK:
243             *data->selection = SendDlgItemMessage(
244                 hWnd, IDC_EXTCMD_LIST, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
245             if (*data->selection == LB_ERR)
246                 *data->selection = -1;
247         /* Fall through. */
248
249         /* CANCEL button ws clicked */
250         case IDCANCEL:
251             EndDialog(hWnd, wParam);
252             return TRUE;
253
254         /* list control events */
255         case IDC_EXTCMD_LIST:
256             switch (HIWORD(wParam)) {
257             case LBN_DBLCLK:
258                 /* double click within the list
259                        wParam
260                          The low-order word is the list box identifier.
261                          The high-order word is the notification message.
262                        lParam
263                          Handle to the list box
264                       */
265                 *data->selection = SendMessage((HWND) lParam, LB_GETCURSEL,
266                                                (WPARAM) 0, (LPARAM) 0);
267                 if (*data->selection == LB_ERR)
268                     *data->selection = -1;
269                 EndDialog(hWnd, IDOK);
270                 return TRUE;
271             }
272             break;
273         }
274     }
275     return FALSE;
276 }
277
278 /*---------------------------------------------------------------*/
279 /* player selector dialog data */
280 struct plsel_data {
281     int *selection;
282 };
283
284 BOOL CALLBACK PlayerSelectorDlgProc(HWND, UINT, WPARAM, LPARAM);
285 static void plselInitDialog(HWND hWnd);
286 static void plselAdjustLists(HWND hWnd, int changed_opt);
287 static int plselFinalSelection(HWND hWnd, int *selection);
288
289 int
290 mswin_player_selection_window(int *selection)
291 {
292     int ret;
293     struct plsel_data data;
294
295     /* init dialog data */
296     ZeroMemory(&data, sizeof(data));
297     data.selection = selection;
298
299     /* create modal dialog */
300     ret = DialogBoxParam(
301         GetNHApp()->hApp, MAKEINTRESOURCE(IDD_PLAYER_SELECTOR),
302         GetNHApp()->hMainWnd, PlayerSelectorDlgProc, (LPARAM) &data);
303     if (ret == -1)
304         panic("Cannot create getlin window");
305
306     return ret;
307 }
308
309 BOOL CALLBACK
310 PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
311 {
312     struct plsel_data *data;
313     RECT main_rt, dlg_rt;
314     SIZE dlg_sz;
315
316     switch (message) {
317     case WM_INITDIALOG:
318         data = (struct plsel_data *) lParam;
319         SetWindowLong(hWnd, GWL_USERDATA, lParam);
320
321         /* center dialog in the main window */
322         GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
323         GetWindowRect(hWnd, &dlg_rt);
324         dlg_sz.cx = dlg_rt.right - dlg_rt.left;
325         dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
326
327         dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
328         dlg_rt.right = dlg_rt.left + dlg_sz.cx;
329         dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
330         dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
331         MoveWindow(hWnd, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
332                    (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
333                    dlg_sz.cy, TRUE);
334
335         /* init dialog */
336         plselInitDialog(hWnd);
337
338 #if defined(WIN_CE_SMARTPHONE)
339         NHSPhoneDialogSetup(hWnd, IDC_SPHONE_DIALOGBAR, FALSE, FALSE);
340 #endif
341         /* set focus on the role checkbox (random) field */
342         SetFocus(GetDlgItem(hWnd, IDC_PLSEL_ROLE_RANDOM));
343
344         /* tell windows we set the focus */
345         return FALSE;
346         break;
347
348     case WM_COMMAND:
349         data = (struct plsel_data *) GetWindowLong(hWnd, GWL_USERDATA);
350         switch (LOWORD(wParam)) {
351         /* OK button was clicked */
352         case IDOK:
353             if (plselFinalSelection(hWnd, data->selection)) {
354                 EndDialog(hWnd, wParam);
355             } else {
356                 MessageBox(
357                     hWnd, TEXT("Cannot match this role. Try something else."),
358                     TEXT("STOP"), MB_OK);
359             }
360             return TRUE;
361
362         /* CANCEL button was clicked */
363         case IDCANCEL:
364             *data->selection = -1;
365             EndDialog(hWnd, wParam);
366             return TRUE;
367
368         /* following are events from dialog controls:
369            "random" checkboxes send BN_CLICKED messages;
370            role/race/... combo-boxes send CBN_SELENDOK
371            if something was selected;
372         */
373         case IDC_PLSEL_ROLE_RANDOM:
374             if (HIWORD(wParam) == BN_CLICKED) {
375                 /* enable corresponding list window if "random"
376                    checkbox was "unchecked" */
377                 EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST),
378                              SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
379                                  == BST_UNCHECKED);
380             }
381             break;
382
383         case IDC_PLSEL_RACE_RANDOM:
384             if (HIWORD(wParam) == BN_CLICKED) {
385                 EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST),
386                              SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
387                                  == BST_UNCHECKED);
388             }
389             break;
390
391         case IDC_PLSEL_GENDER_RANDOM:
392             if (HIWORD(wParam) == BN_CLICKED) {
393                 EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST),
394                              SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
395                                  == BST_UNCHECKED);
396             }
397             break;
398
399         case IDC_PLSEL_ALIGN_RANDOM:
400             if (HIWORD(wParam) == BN_CLICKED) {
401                 EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST),
402                              SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
403                                  == BST_UNCHECKED);
404             }
405             break;
406
407         case IDC_PLSEL_ROLE_LIST:
408             if (HIWORD(wParam) == CBN_SELENDOK) {
409                 /* filter out invalid options if
410                    the selection was made */
411                 plselAdjustLists(hWnd, LOWORD(wParam));
412             }
413             break;
414
415         case IDC_PLSEL_RACE_LIST:
416             if (HIWORD(wParam) == CBN_SELENDOK) {
417                 plselAdjustLists(hWnd, LOWORD(wParam));
418             }
419             break;
420
421         case IDC_PLSEL_GENDER_LIST:
422             if (HIWORD(wParam) == CBN_SELENDOK) {
423                 plselAdjustLists(hWnd, LOWORD(wParam));
424             }
425             break;
426
427         case IDC_PLSEL_ALIGN_LIST:
428             if (HIWORD(wParam) == CBN_SELENDOK) {
429                 plselAdjustLists(hWnd, LOWORD(wParam));
430             }
431             break;
432         }
433         break;
434     }
435     return FALSE;
436 }
437
438 void
439 setComboBoxValue(HWND hWnd, int combo_box, int value)
440 {
441     int index_max = SendDlgItemMessage(hWnd, combo_box, CB_GETCOUNT, 0, 0);
442     int index;
443     int value_to_set = LB_ERR;
444     for (index = 0; index < index_max; index++) {
445         if (SendDlgItemMessage(hWnd, combo_box, CB_GETITEMDATA,
446                                (WPARAM) index, 0) == value) {
447             value_to_set = index;
448             break;
449         }
450     }
451     SendDlgItemMessage(hWnd, combo_box, CB_SETCURSEL, (WPARAM) value_to_set,
452                        0);
453 }
454
455 /* initialize player selector dialog */
456 void
457 plselInitDialog(HWND hWnd)
458 {
459     TCHAR wbuf[BUFSZ];
460
461     /* set player name */
462     SetDlgItemText(hWnd, IDC_PLSEL_NAME, NH_A2W(plname, wbuf, sizeof(wbuf)));
463
464     /* check flags for consistency */
465     if (flags.initrole >= 0) {
466         if (flags.initrace >= 0
467             && !validrace(flags.initrole, flags.initrace)) {
468             flags.initrace = ROLE_NONE;
469         }
470
471         if (flags.initgend >= 0
472             && !validgend(flags.initrole, flags.initrace, flags.initgend)) {
473             flags.initgend = ROLE_NONE;
474         }
475
476         if (flags.initalign >= 0
477             && !validalign(flags.initrole, flags.initrace, flags.initalign)) {
478             flags.initalign = ROLE_NONE;
479         }
480     }
481
482     /* populate select boxes */
483     plselAdjustLists(hWnd, -1);
484
485     /* intialize roles list */
486     if (flags.initrole < 0
487         || !ok_role(flags.initrole, ROLE_NONE, ROLE_NONE, ROLE_NONE)) {
488         CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_CHECKED);
489         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), FALSE);
490     } else {
491         CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_UNCHECKED);
492         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), TRUE);
493         setComboBoxValue(hWnd, IDC_PLSEL_ROLE_LIST, flags.initrole);
494     }
495
496     /* intialize races list */
497     if (flags.initrace < 0
498         || !ok_race(flags.initrole, flags.initrace, ROLE_NONE, ROLE_NONE)) {
499         CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_CHECKED);
500         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), FALSE);
501     } else {
502         CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_UNCHECKED);
503         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), TRUE);
504         setComboBoxValue(hWnd, IDC_PLSEL_RACE_LIST, flags.initrace);
505     }
506
507     /* intialize genders list */
508     if (flags.initgend < 0
509         || !ok_gend(flags.initrole, flags.initrace, flags.initgend,
510                     ROLE_NONE)) {
511         CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_CHECKED);
512         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), FALSE);
513     } else {
514         CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_UNCHECKED);
515         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), TRUE);
516         setComboBoxValue(hWnd, IDC_PLSEL_GENDER_LIST, flags.initgend);
517     }
518
519     /* intialize alignments list */
520     if (flags.initalign < 0
521         || !ok_align(flags.initrole, flags.initrace, flags.initgend,
522                      flags.initalign)) {
523         CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_CHECKED);
524         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), FALSE);
525     } else {
526         CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_UNCHECKED);
527         EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), TRUE);
528         setComboBoxValue(hWnd, IDC_PLSEL_ALIGN_LIST, flags.initalign);
529     }
530 }
531
532 /* adjust role/race/alignment/gender list - filter out
533    invalid combinations
534    changed_sel points to the list where selection occurred
535    (-1 if unknown)
536 */
537 void
538 plselAdjustLists(HWND hWnd, int changed_sel)
539 {
540     HWND control_role, control_race, control_gender, control_align;
541     int initrole, initrace, initgend, initalign;
542     int i;
543     int ind;
544     int valid_opt;
545     TCHAR wbuf[255];
546
547     /* get control handles */
548     control_role = GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST);
549     control_race = GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST);
550     control_gender = GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST);
551     control_align = GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST);
552
553     /* get current selections */
554     ind = SendMessage(control_role, CB_GETCURSEL, 0, 0);
555     initrole = (ind == LB_ERR)
556                    ? flags.initrole
557                    : SendMessage(control_role, CB_GETITEMDATA, ind, 0);
558
559     ind = SendMessage(control_race, CB_GETCURSEL, 0, 0);
560     initrace = (ind == LB_ERR)
561                    ? flags.initrace
562                    : SendMessage(control_race, CB_GETITEMDATA, ind, 0);
563
564     ind = SendMessage(control_gender, CB_GETCURSEL, 0, 0);
565     initgend = (ind == LB_ERR)
566                    ? flags.initgend
567                    : SendMessage(control_gender, CB_GETITEMDATA, ind, 0);
568
569     ind = SendMessage(control_align, CB_GETCURSEL, 0, 0);
570     initalign = (ind == LB_ERR)
571                     ? flags.initalign
572                     : SendMessage(control_align, CB_GETITEMDATA, ind, 0);
573
574     /* intialize roles list */
575     if (changed_sel == -1) {
576         valid_opt = 0;
577
578         /* reset content and populate the list */
579         SendMessage(control_role, CB_RESETCONTENT, 0, 0);
580         for (i = 0; roles[i].name.m; i++) {
581             if (ok_role(i, initrace, initgend, initalign)) {
582                 if (initgend >= 0 && flags.female && roles[i].name.f)
583                     ind = SendMessage(
584                         control_role, CB_ADDSTRING, (WPARAM) 0,
585                         (LPARAM) NH_A2W(roles[i].name.f, wbuf, sizeof(wbuf)));
586                 else
587                     ind = SendMessage(
588                         control_role, CB_ADDSTRING, (WPARAM) 0,
589                         (LPARAM) NH_A2W(roles[i].name.m, wbuf, sizeof(wbuf)));
590
591                 SendMessage(control_role, CB_SETITEMDATA, (WPARAM) ind,
592                             (LPARAM) i);
593                 if (i == initrole) {
594                     SendMessage(control_role, CB_SETCURSEL, (WPARAM) ind,
595                                 (LPARAM) 0);
596                     valid_opt = 1;
597                 }
598             }
599         }
600
601         /* set selection to the previously selected role
602            if it is still valid */
603         if (!valid_opt) {
604             initrole = ROLE_NONE;
605             initrace = ROLE_NONE;
606             initgend = ROLE_NONE;
607             initalign = ROLE_NONE;
608             SendMessage(control_role, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
609         }
610
611         /* trigger change of the races list */
612         changed_sel = IDC_PLSEL_ROLE_LIST;
613     }
614
615     /* intialize races list */
616     if (changed_sel == IDC_PLSEL_ROLE_LIST) {
617         valid_opt = 0;
618
619         /* reset content and populate the list */
620         SendMessage(control_race, CB_RESETCONTENT, 0, 0);
621         for (i = 0; races[i].noun; i++)
622             if (ok_race(initrole, i, ROLE_NONE, ROLE_NONE)) {
623                 ind = SendMessage(
624                     control_race, CB_ADDSTRING, (WPARAM) 0,
625                     (LPARAM) NH_A2W(races[i].noun, wbuf, sizeof(wbuf)));
626                 SendMessage(control_race, CB_SETITEMDATA, (WPARAM) ind,
627                             (LPARAM) i);
628                 if (i == initrace) {
629                     SendMessage(control_race, CB_SETCURSEL, (WPARAM) ind,
630                                 (LPARAM) 0);
631                     valid_opt = 1;
632                 }
633             }
634
635         /* set selection to the previously selected race
636            if it is still valid */
637         if (!valid_opt) {
638             initrace = ROLE_NONE;
639             initgend = ROLE_NONE;
640             initalign = ROLE_NONE;
641             SendMessage(control_race, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
642         }
643
644         /* trigger change of the genders list */
645         changed_sel = IDC_PLSEL_RACE_LIST;
646     }
647
648     /* intialize genders list */
649     if (changed_sel == IDC_PLSEL_RACE_LIST) {
650         valid_opt = 0;
651
652         /* reset content and populate the list */
653         SendMessage(control_gender, CB_RESETCONTENT, 0, 0);
654         for (i = 0; i < ROLE_GENDERS; i++)
655             if (ok_gend(initrole, initrace, i, ROLE_NONE)) {
656                 ind = SendMessage(
657                     control_gender, CB_ADDSTRING, (WPARAM) 0,
658                     (LPARAM) NH_A2W(genders[i].adj, wbuf, sizeof(wbuf)));
659                 SendMessage(control_gender, CB_SETITEMDATA, (WPARAM) ind,
660                             (LPARAM) i);
661                 if (i == initgend) {
662                     SendMessage(control_gender, CB_SETCURSEL, (WPARAM) ind,
663                                 (LPARAM) 0);
664                     valid_opt = 1;
665                 }
666             }
667
668         /* set selection to the previously selected gender
669            if it is still valid */
670         if (!valid_opt) {
671             initgend = ROLE_NONE;
672             initalign = ROLE_NONE;
673             SendMessage(control_gender, CB_SETCURSEL, (WPARAM) -1,
674                         (LPARAM) 0);
675         }
676
677         /* trigger change of the alignments list */
678         changed_sel = IDC_PLSEL_GENDER_LIST;
679     }
680
681     /* intialize alignments list */
682     if (changed_sel == IDC_PLSEL_GENDER_LIST) {
683         valid_opt = 0;
684
685         /* reset content and populate the list */
686         SendMessage(control_align, CB_RESETCONTENT, 0, 0);
687         for (i = 0; i < ROLE_ALIGNS; i++)
688             if (ok_align(initrole, initrace, initgend, i)) {
689                 ind = SendMessage(
690                     control_align, CB_ADDSTRING, (WPARAM) 0,
691                     (LPARAM) NH_A2W(aligns[i].adj, wbuf, sizeof(wbuf)));
692                 SendMessage(control_align, CB_SETITEMDATA, (WPARAM) ind,
693                             (LPARAM) i);
694                 if (i == initalign) {
695                     SendMessage(control_align, CB_SETCURSEL, (WPARAM) ind,
696                                 (LPARAM) 0);
697                     valid_opt = 1;
698                 }
699             }
700
701         /* set selection to the previously selected alignment
702            if it is still valid */
703         if (!valid_opt) {
704             initalign = ROLE_NONE;
705             SendMessage(control_align, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
706         }
707     }
708 }
709
710 /* player made up his mind - get final selection here */
711 int
712 plselFinalSelection(HWND hWnd, int *selection)
713 {
714     int ind;
715
716     /* get current selections */
717     if (SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_RANDOM, BM_GETCHECK, 0, 0)
718         == BST_CHECKED) {
719         flags.initrole = ROLE_RANDOM;
720     } else {
721         ind =
722             SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_GETCURSEL, 0, 0);
723         flags.initrole = (ind == LB_ERR)
724                              ? ROLE_RANDOM
725                              : SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST,
726                                                   CB_GETITEMDATA, ind, 0);
727     }
728
729     if (SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_RANDOM, BM_GETCHECK, 0, 0)
730         == BST_CHECKED) {
731         flags.initrace = ROLE_RANDOM;
732     } else {
733         ind =
734             SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_GETCURSEL, 0, 0);
735         flags.initrace = (ind == LB_ERR)
736                              ? ROLE_RANDOM
737                              : SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST,
738                                                   CB_GETITEMDATA, ind, 0);
739     }
740
741     if (SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_RANDOM, BM_GETCHECK, 0, 0)
742         == BST_CHECKED) {
743         flags.initgend = ROLE_RANDOM;
744     } else {
745         ind = SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_GETCURSEL, 0,
746                                  0);
747         flags.initgend = (ind == LB_ERR)
748                              ? ROLE_RANDOM
749                              : SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST,
750                                                   CB_GETITEMDATA, ind, 0);
751     }
752
753     if (SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_RANDOM, BM_GETCHECK, 0, 0)
754         == BST_CHECKED) {
755         flags.initalign = ROLE_RANDOM;
756     } else {
757         ind = SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_GETCURSEL, 0,
758                                  0);
759         flags.initalign = (ind == LB_ERR)
760                               ? ROLE_RANDOM
761                               : SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST,
762                                                    CB_GETITEMDATA, ind, 0);
763     }
764
765     /* check the role */
766     if (flags.initrole == ROLE_RANDOM) {
767         flags.initrole = pick_role(flags.initrace, flags.initgend,
768                                    flags.initalign, PICK_RANDOM);
769         if (flags.initrole < 0) {
770             MessageBox(hWnd, TEXT("Incompatible role!"), TEXT("STOP"), MB_OK);
771             return FALSE;
772         }
773     }
774
775     /* Select a race, if necessary */
776     /* force compatibility with role */
777     if (flags.initrace == ROLE_RANDOM
778         || !validrace(flags.initrole, flags.initrace)) {
779         /* pre-selected race not valid */
780         if (flags.initrace == ROLE_RANDOM) {
781             flags.initrace = pick_race(flags.initrole, flags.initgend,
782                                        flags.initalign, PICK_RANDOM);
783         }
784
785         if (flags.initrace < 0) {
786             MessageBox(hWnd, TEXT("Incompatible race!"), TEXT("STOP"), MB_OK);
787             return FALSE;
788         }
789     }
790
791     /* Select a gender, if necessary */
792     /* force compatibility with role/race, try for compatibility with
793      * pre-selected alignment */
794     if (flags.initgend < 0
795         || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
796         /* pre-selected gender not valid */
797         if (flags.initgend == ROLE_RANDOM) {
798             flags.initgend = pick_gend(flags.initrole, flags.initrace,
799                                        flags.initalign, PICK_RANDOM);
800         }
801
802         if (flags.initgend < 0) {
803             MessageBox(hWnd, TEXT("Incompatible gender!"), TEXT("STOP"),
804                        MB_OK);
805             return FALSE;
806         }
807     }
808
809     /* Select an alignment, if necessary */
810     /* force compatibility with role/race/gender */
811     if (flags.initalign < 0
812         || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
813         /* pre-selected alignment not valid */
814         if (flags.initalign == ROLE_RANDOM) {
815             flags.initalign = pick_align(flags.initrole, flags.initrace,
816                                          flags.initgend, PICK_RANDOM);
817         } else {
818             MessageBox(hWnd, TEXT("Incompatible alignment!"), TEXT("STOP"),
819                        MB_OK);
820             return FALSE;
821         }
822     }
823
824     return TRUE;
825 }