1 /*
2 	langselwin.c - Shows a language selection window if no language specified in the ini file.
3 
4 	Each available language is displayed from languages/langsel.xml.  The user can click on
5 	their preferred language and then press save which will save the value in the ini file.
6 	Beside the save button a note can be displayed explaining a bit about languages in EL.
7 	If the language "en" is chosen the client will continue to open the login/new
8 	character/rules screen.   Otherwise, the client will be restarted.  All the text and
9 	colours are configurable in the langsel.xml file.
10 
11 	Most user will only see this window once, existing users probably never :(
12 
13 	23/09/07 bluap/pjbroad
14 */
15 
16 
17 #include <string.h>
18 #include <libxml/parser.h>
19 
20 #include "asc.h"
21 #include "elconfig.h"
22 #include "elwindows.h"
23 #include "errors.h"
24 #include "gamewin.h"
25 #include "gl_init.h"
26 #include "hud.h"
27 #include "interface.h"
28 #include "list.h"
29 #include "loginwin.h"
30 #include "main.h"
31 #include "misc.h"
32 #include "multiplayer.h"
33 #include "openingwin.h"
34 #include "rules.h"
35 #include "sound.h"
36 
37 typedef struct { char *code; unsigned char *text; char *save; char *note; } LANGSEL_LIST_NODE;
38 
39 int langsel_rootwin = -1;
40 int have_saved_langsel = 0;
41 static int langsel_win = -1;
42 static int langsel_scroll_id = -1;
43 static int langsel_first_lang_line = 0;
44 static int langsel_num_note_lines = 4;
45 static unsigned char *langsel_save_note_boxed = NULL;
46 static char *langsel_list_error = NULL;
47 static list_node_t *langsel_list = NULL;
48 static LANGSEL_LIST_NODE *langsel_default_node = NULL;
49 static LANGSEL_LIST_NODE *langsel_chosen_node = NULL;
50 static LANGSEL_LIST_NODE *langsel_selected_node = NULL;
51 static float langsel_winRGB[4][3] = {{0.0f,0.25f,1.0f},{0.2f,0.7f,1.2f},{0.2f,1.0f,1.2f},{1.0f, 1.0f, 1.0f}};
52 
53 
langsel_load_list(void)54 static int langsel_load_list(void)
55 {
56 	xmlDocPtr doc;
57 	xmlNodePtr cur;
58 	char *error_prefix = "Reading langsel.xml: ";
59 
60 	langsel_winRGB[3][0] = gui_color[0];
61 	langsel_winRGB[3][1] = gui_color[1];
62 	langsel_winRGB[3][2] = gui_color[2];
63 
64 	if ((doc = xmlReadFile("languages/langsel.xml", NULL, 0)) == NULL)
65 	{
66 		langsel_list_error = "Can't open file.";
67 		LOG_ERROR("%s%s\n", error_prefix, langsel_list_error );
68 		return 0;
69 	}
70 
71 	if ((cur = xmlDocGetRootElement (doc)) == NULL)
72 	{
73 		langsel_list_error = "Empty xml document.";
74 		LOG_ERROR("%s%s\n", error_prefix, langsel_list_error );
75 		xmlFreeDoc(doc);
76 		return 0;
77 	}
78 
79 	if (xmlStrcasecmp (cur->name, (const xmlChar *) "LANGUAGE_LIST"))
80 	{
81 		langsel_list_error = "Not language list.";
82 		LOG_ERROR("%s%s\n", error_prefix, langsel_list_error );
83 		xmlFreeDoc(doc);
84 		return 0;
85 	}
86 
87 	for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
88 	{
89 		if (!xmlStrcasecmp(cur->name, (const xmlChar *)"LANG"))
90 		{
91 			LANGSEL_LIST_NODE *new_lang_node = NULL;
92 			char *note = (char*)(cur->children ? cur->children->content : NULL);
93 			char *code = (char*)xmlGetProp(cur, (xmlChar *)"CODE");
94 			char *text = (char*)xmlGetProp(cur, (xmlChar *)"TEXT");
95 			char *save = (char*)xmlGetProp(cur, (xmlChar *)"SAVE");
96 			char *def = (char*)xmlGetProp(cur, (xmlChar *)"DEFAULT");
97 
98 			if ((code == NULL) || (text == NULL))
99 			{
100 				LOG_WARNING("%sInvalid language node\n", error_prefix );
101 				continue;
102 			}
103 
104 			new_lang_node = (LANGSEL_LIST_NODE *)malloc(sizeof(LANGSEL_LIST_NODE));
105 			new_lang_node->note = new_lang_node->code = new_lang_node->save = NULL;
106 			new_lang_node->text = NULL;
107 
108 			if (note)
109 				MY_XMLSTRCPY(&new_lang_node->note, note);
110 			if (code)
111 				MY_XMLSTRCPY(&new_lang_node->code, code);
112 			if (text)
113 				MY_XMLSTRCPY((char**)&new_lang_node->text, text);
114 			if (save)
115 				MY_XMLSTRCPY(&new_lang_node->save, save);
116 			if (def)
117 				langsel_default_node = new_lang_node;
118 
119 			xmlFree(code);
120 			xmlFree(text);
121 			xmlFree(save);
122 			xmlFree(def);
123 
124 			list_push(&langsel_list, new_lang_node);
125 		}
126 		else if (!xmlStrcasecmp(cur->name, (const xmlChar *)"SETTINGS"))
127 		{
128 			char *propstr[4] = {"TEXT", "HIGHLIGHT", "CHOSEN", "BUTTONS" };
129 			char *noteslines = (char*)xmlGetProp(cur, (xmlChar *)"NOTELINES");
130 			int i = atoi(noteslines);
131 			if (i >= 0)
132 				langsel_num_note_lines = i;
133 			for (i=0; i<4; i++)
134 			{
135 				char *text = (char*)xmlGetProp(cur, (xmlChar *)propstr[i]);
136 				float r = 0, g = 0, b = 0;
137 				if (sscanf(text, "%f %f %f", &r, &g, &b) == 3)
138 				{
139 					langsel_winRGB[i][0] = r;
140 					langsel_winRGB[i][1] = g;
141 					langsel_winRGB[i][2] = b;
142 				}
143 				else
144 					LOG_WARNING("%sColour error\n", error_prefix );
145 				xmlFree(text);
146 			}
147 		}
148 	}
149 	xmlFreeDoc(doc);
150 
151 	if (!langsel_default_node || (langsel_default_node->save == NULL))
152 	{
153 		langsel_list_error = "Invalid default language.";
154 		LOG_ERROR("%s%s\n", error_prefix, langsel_list_error );
155 		if (langsel_default_node)
156 			langsel_default_node = NULL;
157 		return 0;
158 	}
159 
160 	if (langsel_list == NULL)
161 	{
162 		langsel_list_error = "No languages found.";
163 		LOG_ERROR("%s%s\n", error_prefix, langsel_list_error );
164 		return 0;
165 	}
166 
167 	return 1;
168 }
169 
170 
langsel_free_list(void)171 static void langsel_free_list(void)
172 {
173 	while (langsel_list != NULL)
174 	{
175 		LANGSEL_LIST_NODE *new_lang_node = (LANGSEL_LIST_NODE *)list_pop(&langsel_list);
176 		if (new_lang_node->note)
177 			free(new_lang_node->note);
178 		if (new_lang_node->code)
179 			free(new_lang_node->code);
180 		if (new_lang_node->text)
181 			free(new_lang_node->text);
182 		if (new_lang_node->save)
183 			free(new_lang_node->save);
184 		free(new_lang_node);
185 	}
186 }
187 
188 
langsel_destroy_wins(void)189 static void langsel_destroy_wins(void)
190 {
191 	if (langsel_save_note_boxed)
192 		free(langsel_save_note_boxed);
193 
194 	destroy_window(langsel_win);
195 	destroy_window(langsel_rootwin);
196 	langsel_win = langsel_rootwin = -1;
197 }
198 
199 
langsel_save_handler(widget_list * widget,int mx,int my,Uint32 flags)200 static int langsel_save_handler(widget_list *widget, int mx, int my, Uint32 flags)
201 {
202 	char *selected_lang = lang;
203 
204 	/* don't use scroll wheel - leave for scroll bar */
205 	if ((flags & ELW_MOUSE_BUTTON) == 0)
206 		return 0;
207 
208 	langsel_destroy_wins();
209 
210 	if (langsel_chosen_node)
211 		selected_lang = langsel_chosen_node->code;
212 
213 	/* if the chosen language the that used during initialisation, no client restart is required */
214 	if (strcmp(selected_lang, lang) == 0)
215 	{
216 		/* go to the console->login screen */
217 		if (has_accepted)
218 		{
219 			show_window (opening_root_win);
220 			show_hud_windows();
221 			if (disconnected)
222 				connect_to_server();
223 		}
224 		/* unless we need to read the rules first */
225 		else
226 		{
227 			create_rules_root_window (window_width, window_height, opening_root_win, 15);
228 			show_window (rules_root_win);
229 		}
230 	}
231 	else
232 	{
233 		/* a different language has been chosen so restart the client */
234 		restart_required = 1;
235 		exit_now = 1;
236 	}
237 
238 	/* set the chosen language, it will be saved on exit, then complete the clean up */
239 	change_language(selected_lang);
240 	langsel_free_list();
241 	have_saved_langsel = 1;
242 
243   	return 1;
244 }
245 
246 
langsel_quit_handler(widget_list * widget,int mx,int my,Uint32 flags)247 static int langsel_quit_handler(widget_list *widget, int mx, int my, Uint32 flags)
248 {
249 	/* don't use scroll wheel - leave for scroll bar */
250 	if ((flags & ELW_MOUSE_BUTTON) == 0)
251 		return 0;
252 	langsel_destroy_wins();
253 	langsel_free_list();
254 	exit_now = 1;
255   	return 1;
256 }
257 
258 
langsel_scroll_click_handler(widget_list * widget,int mx,int my,Uint32 flags)259 static int langsel_scroll_click_handler(widget_list *widget, int mx, int my, Uint32 flags)
260 {
261 	langsel_first_lang_line = vscrollbar_get_pos(widget->window_id, widget->id);
262 	return 1;
263 }
264 
265 
langsel_scroll_drag_handler(widget_list * widget,int mx,int my,Uint32 flags,int dx,int dy)266 static int langsel_scroll_drag_handler(widget_list *widget, int mx, int my, Uint32 flags, int dx, int dy)
267 {
268 	return langsel_scroll_click_handler(widget, mx, my, flags);
269 }
270 
271 
click_langsel_handler(window_info * win,int mx,int my,Uint32 flags)272 static int click_langsel_handler(window_info *win, int mx, int my, Uint32 flags)
273 {
274 	if ((langsel_scroll_id > 0) && flags & ELW_WHEEL_UP)
275 		vscrollbar_scroll_up(langsel_win, langsel_scroll_id);
276 	else if ((langsel_scroll_id > 0) && flags & ELW_WHEEL_DOWN)
277 		vscrollbar_scroll_down(langsel_win, langsel_scroll_id);
278 	else if ((flags & ELW_MOUSE_BUTTON) && langsel_selected_node)
279 	{
280 		langsel_chosen_node = langsel_selected_node;
281 		do_click_sound();
282 	}
283 	if (langsel_scroll_id > 0)
284 		langsel_first_lang_line = vscrollbar_get_pos(langsel_win, langsel_scroll_id);
285 	return 1;
286 }
287 
288 
langsel_keypress_handler(window_info * win,int mx,int my,SDL_Keycode key_code,Uint32 key_unicode,Uint16 key_mod)289 static int langsel_keypress_handler(window_info *win, int mx, int my, SDL_Keycode key_code, Uint32 key_unicode, Uint16 key_mod)
290 {
291 	if (check_quit_or_fullscreen(key_code, key_mod))
292 	{
293 		return 1;
294 	}
295 	else if (KEY_DEF_CMP(K_OPAQUEWIN, key_code, key_mod))
296 	{
297 		win->opaque ^= 1;
298 	}
299 	else
300 		return 0;
301 	return 1;
302 }
303 
304 
305 /* display the loading/login image as a background */
langsel_display_root_handler(window_info * win)306 static int langsel_display_root_handler(window_info *win)
307 {
308 	if (login_text > 0)
309 		draw_console_pic(login_text);
310 	return 1;
311 }
312 
313 
314 /* displayed if the config file is missing or invalid */
langsel_display_error_handler(window_info * win)315 static int langsel_display_error_handler(window_info *win)
316 {
317 	static int first_time = 1;
318 	static int save_button = -1;
319 	static int quit_button = -1;
320 	static int sep = 0;
321 	static const unsigned char *message = (const unsigned char*)
322 		"The language selection file langsel.xml could\n"
323 		"not be read. Either click Save to accept the\n"
324 		"default language (English), or click Quit if\n"
325 		"you wish to manually correct this error.\n\n"
326 		"The error message was:\n\n";
327 
328 	const unsigned char* error
329 		= (const unsigned char *)(langsel_list_error ? langsel_list_error : "Unknown error");
330 
331 	if (first_time)
332 	{
333 		int width, height, button_width, button_height;
334 
335 		sep = (int)(0.5 + win->current_scale * 10);
336 
337 		save_button = button_add_extended(langsel_win, 100, NULL, 0, 0, 0, 0, 0, win->current_scale, "Save");
338 		widget_set_color(langsel_win, save_button, langsel_winRGB[3][0], langsel_winRGB[3][1],
339 			langsel_winRGB[3][2]);
340 		widget_set_OnClick(langsel_win, save_button, langsel_save_handler);
341 		button_width = widget_get_width(langsel_win, save_button);
342 		button_height = widget_get_height(langsel_win, save_button);
343 
344 		quit_button = button_add_extended(langsel_win, 101, NULL, 0, 0, 0, 0, 0, win->current_scale, "Quit");
345 		widget_set_color(langsel_win, quit_button, langsel_winRGB[3][0], langsel_winRGB[3][1],
346 			langsel_winRGB[3][2]);
347 		widget_set_OnClick(langsel_win, quit_button, langsel_quit_handler);
348 
349 		get_buf_dimensions(message, strlen((const char*)message), win->font_category,
350 			win->current_scale_small, &width, &height);
351 		width += 2 * sep;
352 		height += button_height + 3 * sep;
353 
354 		resize_window(langsel_win, width, height);
355 		widget_move(langsel_win, save_button, sep, win->len_y - button_height - sep);
356 		widget_move(langsel_win, quit_button, sep + button_width + sep,
357 			win->len_y - button_height - sep);
358 
359 		first_time = 0;
360 		return 1;
361 	}
362 
363 	draw_string_small_zoomed(sep, sep, (const unsigned char *)message, 6, win->current_scale);
364 	draw_string_small_zoomed(sep, sep + win->small_font_len_y * 6, error, 1, win->current_scale);
365 
366 	return 1;
367 }
368 
369 
370 /* the main business is done here */
display_langsel_handler(window_info * win)371 static int display_langsel_handler(window_info *win)
372 {
373 	static float font_zoom = 1.5;
374 	static float text_zoom = 1.0;
375 	static float line_step = 0;
376 	static int num_lang_lines = 0;
377 	static float max_str_width = 0;
378 	static list_node_t *first_node = NULL;
379 	static LANGSEL_LIST_NODE *last_langsel_chosen_node = NULL;
380 	static int save_button = -1;
381 	static int first_time = 1;
382 	static int second_time = 0;
383 	static int add_scroll_bar = 0;
384 	static int max_lang_lines = 0;
385 	static int winwidth = 0;
386 	static int winheight = 0;
387 	static char *langwin_save_note = NULL;
388 	static float note_height = 0;
389 	static int scroll_width = 0;
390 
391 	const float winsep = 15;
392 	list_node_t *local_head = NULL;
393 	int current_y = 0;
394 	int lang_line_num = 0;
395 
396 	/* first time through, create additional widgets and resize everything */
397 	if (first_time)
398 	{
399 		widget_list *save_widget = NULL;
400 		unsigned char *longest_string = NULL;
401 		int non_line_height = 0;
402 		float sizefrac = 0.80;
403 
404 		font_zoom *= win->current_scale;
405 
406 		/* count the number of language lines and find the widest line and the first line
407 		   - font_zoom unknow as yet */
408 		for (local_head = langsel_list; local_head; local_head = local_head->next)
409 		{
410 			LANGSEL_LIST_NODE *new_lang_node = (LANGSEL_LIST_NODE *)local_head->data;
411 			float str_width = get_string_width_zoom(new_lang_node->text, win->font_category,
412 				font_zoom);
413 			if (str_width > max_str_width)
414 			{
415 				max_str_width = str_width;
416 				longest_string = new_lang_node->text;
417 			}
418 			num_lang_lines++;
419 			first_node = local_head;
420 		}
421 
422 		/* if required, change the zoom based on a reasonable limit of using all the main window */
423 		if (max_str_width > (sizefrac * window_width))
424 		{
425 			font_zoom = sizefrac * window_width / max_str_width;
426 			max_str_width = get_string_width_zoom(longest_string, win->font_category, font_zoom);
427 		}
428 
429 		text_zoom = font_zoom / 1.5;
430 		note_height = get_line_height(win->font_category, text_zoom) * langsel_num_note_lines;
431 		scroll_width = ELW_BOX_SIZE * text_zoom;
432 
433 		/* number of pixels used per language line drawn */
434 		line_step = 3 + get_line_height(win->font_category, font_zoom);
435 
436 		/* set the window width now things about the width are known */
437 		winwidth = max_str_width + 2 * winsep;
438 
439 		/* to set the height, we need to know button sizes so create a temporary button */
440 		save_button = button_add_extended(langsel_win, 100, NULL, 0, 0, 0, 0, WIDGET_INVISIBLE, text_zoom, "Temp");
441 		save_widget = widget_find(langsel_win, save_button);
442 
443 		/* calculate the window height assuming we can display all languages without a scroll bar */
444 		max_lang_lines = num_lang_lines;
445 		non_line_height = 3 * winsep + max2i(save_widget->len_y, note_height);
446 		winheight = non_line_height + line_step * max_lang_lines;
447 
448 		/* if the height is too big, reduce it to something reasonable and add a scroll bar */
449 		if (winheight > (sizefrac * window_height))
450 		{
451 			add_scroll_bar = 1;
452 			max_lang_lines = ((sizefrac * window_height) - non_line_height) / line_step;
453 			winheight = non_line_height + line_step * max_lang_lines;
454 			winwidth += scroll_width;
455 		}
456 
457 		/* move the window to the centre of the screen and resize it as calculate */
458 		move_window(langsel_win, langsel_rootwin, 0, (window_width-winwidth)/2, (window_height-winheight)/2);
459 		resize_window(langsel_win, winwidth, winheight);
460 
461 		/* clean up then exit, leave the rest to next time so the buttons don't flash on the screen */
462 		widget_destroy(langsel_win, save_button);
463 		save_button = -1;
464 		first_time = 0;
465 		second_time = 1;
466 		return 1;
467 	}
468 
469 	/* if no button etc, or language choice has changed, redisplay the button and note */
470 	if (second_time || (langsel_chosen_node && (last_langsel_chosen_node != langsel_chosen_node)))
471 	{
472 		widget_list *save_widget = NULL;
473 		const char *save = "Save";
474 
475 		/* get the save button text, using the default if required */
476 		if (langsel_chosen_node->save)
477 			save = langsel_chosen_node->save;
478 		else if (langsel_default_node->save)
479 			save = langsel_default_node->save;
480 
481 		/* create the save button, resized and moved to keep things tidy */
482 		if (save_button > 0)
483 			widget_destroy(langsel_win, save_button);
484 		save_button = button_add_extended(langsel_win, 100, NULL, 0, 0, 0, 0, 0, text_zoom, save);
485 		widget_set_color(langsel_win, save_button, langsel_winRGB[3][0], langsel_winRGB[3][1],
486 			langsel_winRGB[3][2]);
487 		save_widget = widget_find(langsel_win, save_button);
488 		widget_move(langsel_win, save_button, winwidth - (winsep + save_widget->len_x), winheight - winsep - save_widget->len_y);
489 		widget_set_OnClick(langsel_win, save_button, langsel_save_handler);
490 
491 		/* get the note text, using the default if required */
492 		if (langsel_chosen_node->note)
493 			langwin_save_note = langsel_chosen_node->note;
494 		else if (langsel_default_node->note)
495 			langwin_save_note = langsel_default_node->note;
496 		else
497 			langwin_save_note = NULL;
498 
499 		/* wrap the text so that it fits into the window space available */
500 		if (langwin_save_note)
501 		{
502 			langsel_save_note_boxed = realloc(langsel_save_note_boxed,
503 				strlen(langwin_save_note)*2);
504 			put_small_text_in_box_zoomed((const Uint8 *)langwin_save_note,
505 				strlen(langwin_save_note), winwidth - (2 * winsep + save_widget->len_x),
506 				langsel_save_note_boxed, text_zoom);
507 		}
508 
509 		if (add_scroll_bar)
510 		{
511 			langsel_scroll_id = vscrollbar_add_extended(langsel_win, 102, NULL,  winwidth - scroll_width, winsep,
512 				scroll_width, line_step * max_lang_lines, 0, 1.0,
513 				0, 1, num_lang_lines - max_lang_lines);
514 			widget_set_color(langsel_win, langsel_scroll_id, langsel_winRGB[3][0], langsel_winRGB[3][1],
515 				langsel_winRGB[3][2]);
516 			widget_set_OnDrag(langsel_win, langsel_scroll_id, langsel_scroll_drag_handler);
517 			widget_set_OnClick(langsel_win, langsel_scroll_id, langsel_scroll_click_handler);
518 			add_scroll_bar = 0;
519 		}
520 
521 		last_langsel_chosen_node = langsel_chosen_node;
522 		second_time = 0;
523 	}
524 
525 	/* if we have note text, display it */
526 	if (langwin_save_note)
527 	{
528 		draw_string_small_zoomed(winsep, winheight - winsep - note_height,
529 			langsel_save_note_boxed, langsel_num_note_lines, text_zoom);
530 	}
531 
532 	/* draw a line under the language list */
533 	glColor3f(langsel_winRGB[3][0], langsel_winRGB[3][1], langsel_winRGB[3][2]);
534 	glDisable(GL_TEXTURE_2D);
535 	glBegin(GL_LINES);
536 	glVertex2i(winsep, winsep + line_step * max_lang_lines);
537 	glVertex2i(winsep + max_str_width, winsep + line_step * max_lang_lines);
538 	glEnd();
539 	glEnable(GL_TEXTURE_2D);
540 
541 	/* display the language list */
542 	current_y = winsep;
543 	langsel_selected_node = NULL;
544 	lang_line_num = 0;
545 	for (local_head = first_node; local_head; local_head = local_head->prev, lang_line_num++)
546 	{
547 		LANGSEL_LIST_NODE *new_lang_node = (LANGSEL_LIST_NODE *)local_head->data;
548 
549 		/* if off the top if the window, don't display */
550 		if (lang_line_num < langsel_first_lang_line)
551 			continue;
552 
553 		/* if off the bottom of the window, don't display this or any more lines */
554 		if ((lang_line_num - langsel_first_lang_line) >= max_lang_lines)
555 			break;
556 
557 		/* colour the list lines as required*/
558 		if (new_lang_node == langsel_chosen_node)
559 			glColor3f(langsel_winRGB[2][0],langsel_winRGB[2][1],langsel_winRGB[2][2]);
560 		/* if the mouse is over the current line.... */
561 		else if ((mouse_y > win->cur_y + current_y) &&
562 			(mouse_y < win->cur_y + current_y + line_step) &&
563 			(mouse_x >= win->cur_x + winsep) &&
564 			(mouse_x - winsep <= win->cur_x + max_str_width))
565 		{
566 			glColor3f(langsel_winRGB[1][0],langsel_winRGB[1][1],langsel_winRGB[1][2]);
567 			/* save the highlighted line in case it is clicked - and so chosen */
568 			langsel_selected_node = new_lang_node;
569 		}
570 		else
571 			glColor3f(langsel_winRGB[0][0],langsel_winRGB[0][1],langsel_winRGB[0][2]);
572 
573 		/* draw the line of text and step down for the next */
574 		draw_string_zoomed(winsep, current_y, new_lang_node->text, 1, font_zoom);
575 		current_y += line_step;
576 	}
577 
578 	return 1;
579 
580 } /* end display_langsel_handler() */
581 
langsel_rootwin_resize_handler(window_info * win,int width,int height)582 static int langsel_rootwin_resize_handler(window_info *win, int width, int height)
583 {
584 	if (langsel_win >=0 && langsel_win < windows_list.num_windows)
585 	{
586 		window_info *lwin = &windows_list.window[langsel_win];
587 		move_window(lwin->window_id, lwin->pos_id, lwin->pos_loc, (width-lwin->len_x)/2, (height-lwin->len_y)/2);
588 	}
589 	return 1;
590 }
591 
592 /* load the language list and create the windows */
display_langsel_win(void)593 int display_langsel_win(void)
594 {
595 	int loaded_lang_list = langsel_load_list();
596 	langsel_chosen_node = langsel_default_node;
597 
598 	/* create and show the root window */
599 	langsel_rootwin = create_window("", -1, -1, 0, 0, window_width, window_height, ELW_TITLE_NONE|ELW_SHOW_LAST);
600 	set_window_handler(langsel_rootwin, ELW_HANDLER_DISPLAY, &langsel_display_root_handler );
601 	set_window_handler(langsel_rootwin, ELW_HANDLER_RESIZE, &langsel_rootwin_resize_handler);
602 	show_window(langsel_rootwin);
603 
604 	/* create and show the language selection window */
605 	langsel_win = create_window("", langsel_rootwin, -1, (window_width-400)/2, (window_height-400/1.62)/2,
606 		400, 400/1.62, (ELW_USE_UISCALE|ELW_WIN_DEFAULT)^(ELW_CLOSE_BOX|ELW_TITLE_BAR));
607 	set_window_handler(langsel_win, ELW_HANDLER_CLICK, &click_langsel_handler );
608 	set_window_handler(langsel_win, ELW_HANDLER_KEYPRESS, (int (*)())&langsel_keypress_handler);
609 
610 	/* use the error window if the list could not be read */
611 	if (loaded_lang_list)
612 		set_window_handler(langsel_win, ELW_HANDLER_DISPLAY, &display_langsel_handler );
613 	else
614 		set_window_handler(langsel_win, ELW_HANDLER_DISPLAY, &langsel_display_error_handler );
615 
616 	show_window(langsel_win);
617 
618 	return 1;
619 }
620