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