OSDN Git Service

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