1 #include <stdlib.h>
2 #include <string.h>
3 #include "elconfig.h"
4 #include "chat.h"
5 #include "context_menu.h"
6 #include "hud.h"
7 #include "init.h"
8 #include "translate.h"
9 #include "elwindows.h"
10 #include "alphamap.h"
11 #include "asc.h"
12 #include "cursors.h"
13 #include "gamewin.h"
14 #include "gl_init.h"
15 #include "interface.h"
16 #ifdef JSON_FILES
17 #include "json_io.h"
18 #endif
19 #include "keys.h"
20 #include "misc.h"
21 #include "multiplayer.h"
22 #include "textures.h"
23 #include "widgets.h"
24 #include "sound.h"
25 
26 #define ELW_WIN_MAX 128
27 
28 const GLfloat gui_color[3] = { 0.77f, 0.57f, 0.39f };
29 const GLfloat gui_invert_color[3] = { 0.32f, 0.23f, 0.15f };
30 const GLfloat gui_bright_color[3] = { 0.95f, 0.76f, 0.52f };
31 const GLfloat gui_dull_color[3] = { 0.40f, 0.30f, 0.20f };
32 
33 // Managed Windows
34 // Provide common features for selected windows including id, position, name,
35 // scaling, activation keys and create/display/hide functions and information.
36 
37 // structure for indivual window information
38 typedef struct {
39 	int id;
40 	int pos_x;
41 	int pos_y;
42 	int keep_centred;
43 	int prop_pos;
44 	float pos_ratio_x;
45 	float pos_ratio_y;
46 	int on_top;
47 	const char * icon_name;
48 	int hideable;
49 	int was_open;
50 	float scale;
51 	el_key_def *key_def;
52 	void (*display)(void);
53 	void (*toggle)(void);
54 	int (*showable)(void);
55 } managed_window_list_def;
56 
57 // structure for the managed window array and any related vars
58 typedef struct {
59 	managed_window_list_def list[MW_MAX];
60 	int disable_mouse_or_keys_scaling;
61 } managed_window_def;
62 
63 static managed_window_def managed_windows =
64 {
65 	.list[MW_TRADE] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "trade", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = display_trade_menu, .toggle = NULL, .showable = NULL },
66 	.list[MW_ITEMS] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "invent", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_ITEMS, .display = display_items_menu, .toggle = NULL, .showable = NULL },
67 	.list[MW_BAGS] = { .id = -1, .pos_x = 400, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "bags", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
68 	.list[MW_SPELLS] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "spell", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_SIGILS, .display = display_sigils_menu, .toggle = NULL, .showable = NULL },
69 	.list[MW_STORAGE] = { .id = -1, .pos_x = 100, .pos_y = 100, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "storage", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = display_storage_menu, .toggle = NULL, .showable = NULL },
70 	.list[MW_MANU] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "manu", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_MANUFACTURE, .display = display_manufacture_menu, .toggle = NULL, .showable = NULL },
71 	.list[MW_EMOTE] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "emotewin", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_EMOTES, .display = display_emotes_menu, .toggle = NULL, .showable = NULL },
72 	.list[MW_QUESTLOG] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "quest", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_QUESTLOG, .display = display_questlog, .toggle = NULL, .showable = NULL },
73 	.list[MW_INFO] = { .id = -1, .pos_x = 150, .pos_y = 70, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "info", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = display_tab_info, .toggle = NULL, .showable = NULL },
74 	.list[MW_BUDDY] = { .id = -1, .pos_x = 150, .pos_y = 70, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "buddy", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_BUDDY, .display = display_buddy, .toggle = NULL, .showable = NULL },
75 	.list[MW_STATS] = { .id = -1, .pos_x = 150, .pos_y = 70, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "stats", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = display_tab_stats, .toggle = NULL, .showable = NULL },
76 	.list[MW_HELP] = { .id = -1, .pos_x = 150, .pos_y = 70, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "help", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = display_tab_help, .toggle = NULL, .showable = NULL },
77 	.list[MW_RANGING] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "range", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_RANGINGWIN, .display = display_range_win, .toggle = NULL, .showable = NULL },
78 	.list[MW_ACHIEVE] = { .id = -1, .pos_x = 0, .pos_y = 0, .keep_centred = 0, .prop_pos = 0, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "achievements", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
79 	.list[MW_DIALOGUE] = { .id = -1, .pos_x = 1, .pos_y = 1, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "dialogue", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
80 	.list[MW_QUICKBAR] = { .id = -1, .pos_x = 100, .pos_y = 100, .keep_centred = 0, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "quickbar", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
81 	.list[MW_QUICKSPELLS] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 0, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "quickspells", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
82 	.list[MW_CONFIG] = { .id = -1, .pos_x = 10, .pos_y = 10, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "opts", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_OPTIONS, .display = display_elconfig_win, .toggle = NULL, .showable = NULL },
83 	.list[MW_MINIMAP] = { .id = -1, .pos_x = 50, .pos_y = 50, .keep_centred = 0, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "minimap", .hideable = 1, .was_open = 0, .scale = 1.0f, .key_def = &K_MINIMAP, .display = display_minimap, .toggle = NULL, .showable = NULL },
84 	.list[MW_ASTRO] = { .id = -1, .pos_x = 10, .pos_y = 20, .keep_centred = 1, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 1, .icon_name = "astro", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
85 	.list[MW_TABMAP] = { .id = -1, .pos_x = 0, .pos_y = 0, .keep_centred = 0, .prop_pos = 0, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "map", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
86 	.list[MW_CONSOLE] = { .id = -1, .pos_x = 0, .pos_y = 0, .keep_centred = 0, .prop_pos = 0, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "console", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = NULL, .display = NULL, .toggle = NULL, .showable = NULL },
87 	.list[MW_CHAT] = { .id = -1, .pos_x = 0, .pos_y = 0, .keep_centred = 0, .prop_pos = 1, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "chat", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = &K_CHAT, .display = open_chat, .toggle = toggle_chat, .showable = is_chat_shown },
88 #ifdef ECDEBUGWIN
89 	.list[MW_ECDEBUG] = { .id = -1, .pos_x = 10, .pos_y = 10, .keep_centred = 1, .prop_pos = 0, .pos_ratio_x = 1.0f, .pos_ratio_y = 1.0f, .on_top = 0, .icon_name = "ecdebug", .hideable = 0, .was_open = 0, .scale = 1.0f, .key_def = &K_ECDEBUGWIN, .display = display_ecdebugwin, .toggle = NULL, .showable = NULL },
90 #endif
91 	.disable_mouse_or_keys_scaling = 0
92 };
93 
94 windows_info	windows_list;	// the master list of windows
95 
96 static window_info *cur_drag_window = NULL;
97 static widget_list *cur_drag_widget = NULL;
98 int top_SWITCHABLE_OPAQUE_window_drawn = -1;
99 int opaque_window_backgrounds = 0;
100 static int last_opaque_window_backgrounds = 0;
101 
102 int display_window(int win_id);
103 int	drag_in_window(int win_id, int x, int y, Uint32 flags, int dx, int dy);
104 int	mouseover_window(int win_id, int x, int y);	// do mouseover processing for a window
105 int	keypress_in_window(int win_id, int x, int y, SDL_Keycode key_code, Uint32 key_unicode, Uint16 key_mod);	// keypress in the window
106 
107 /*
108  * The intent of the windows system is to create the window once
109  * and then hide the window when you don't want to use it.
110  *
111  * Note: In the handlers, all cursor coordinates are relative to the window
112  *
113  */
114 
update_windows_custom_scale(float * changed_window_custom_scale)115 void update_windows_custom_scale(float *changed_window_custom_scale)
116 {
117 	size_t win_id;
118 	// to avoid getting out of step, scale all the variables first, then call the handers
119 	for (win_id=0; win_id < windows_list.num_windows; win_id++)
120 	{
121 		window_info *win = &windows_list.window[win_id];
122 		if ((win->custom_scale != NULL) && (win->custom_scale == changed_window_custom_scale))
123 			update_window_scale(win, get_global_scale());
124 	}
125 	for (win_id=0; win_id < windows_list.num_windows; win_id++)
126 	{
127 		window_info *win = &windows_list.window[win_id];
128 		if ((win->custom_scale != NULL) && (win->custom_scale == changed_window_custom_scale) && (win->ui_scale_handler != NULL))
129 			(*win->ui_scale_handler)(win);
130 	}
131 }
132 
set_window_custom_scale(int win_id,enum managed_window_enum managed_win)133 void set_window_custom_scale(int win_id, enum managed_window_enum managed_win)
134 {
135 	window_info *win = NULL;
136 	if (win_id < 0 || win_id >= windows_list.num_windows || managed_win >= MW_MAX)
137 		return;
138 	win = &windows_list.window[win_id];
139 	win->custom_scale = &managed_windows.list[managed_win].scale;
140 	update_window_scale(win, get_global_scale());
141 	if (win->ui_scale_handler)
142 		(*win->ui_scale_handler)(win);
143 }
144 
update_window_scale(window_info * win,float scale_factor)145 void update_window_scale(window_info *win, float scale_factor)
146 {
147 	if (win == NULL)
148 		return;
149 	if (win->flags & ELW_USE_UISCALE)
150 	{
151 		win->current_scale = scale_factor * ((win->custom_scale == NULL) ?1.0f : *win->custom_scale);
152 		win->current_scale_small = win->current_scale * DEFAULT_SMALL_RATIO;
153 		win->box_size = (int)(0.5 + win->current_scale * ELW_BOX_SIZE);
154 		win->small_font_max_len_x = get_max_char_width_zoom(win->font_category, win->current_scale_small);
155 		win->small_font_len_y = get_line_height(win->font_category, win->current_scale_small);
156 		win->default_font_max_len_x = get_max_char_width_zoom(win->font_category, win->current_scale);
157 		win->default_font_len_y = get_line_height(win->font_category, win->current_scale);
158 		win->title_height = max2i(win->small_font_len_y, win->current_scale*ELW_TITLE_HEIGHT);
159 	}
160 	else
161 	{
162 		win->current_scale = 1.0;
163 		win->current_scale_small = win->current_scale * DEFAULT_SMALL_RATIO;
164 		win->box_size = ELW_BOX_SIZE;
165 		win->small_font_max_len_x = get_max_char_width_zoom(win->font_category, DEFAULT_SMALL_RATIO);
166 		win->small_font_len_y = get_line_height(win->font_category, DEFAULT_SMALL_RATIO);
167 		win->default_font_max_len_x = get_max_char_width_zoom(win->font_category, 1.0);
168 		win->default_font_len_y = get_line_height(win->font_category, 1.0);
169 		win->title_height = max2i(win->small_font_len_y, ELW_TITLE_HEIGHT);
170 	}
171 }
172 
173 // Called when the ui_scale is changed to update scale settings for all windows
update_windows_scale(float scale_factor)174 void update_windows_scale(float scale_factor)
175 {
176 	int win_id;
177 	// to avoid getting out of step, scale all the variables first, then call the handers
178 	for (win_id=0; win_id < windows_list.num_windows; win_id++)
179 	{
180 		window_info *win = &windows_list.window[win_id];
181 		if(windows_list.window[win_id].window_id != win_id)
182 			continue;
183 		update_window_scale(win, scale_factor);
184 	}
185 	for (win_id=0; win_id < windows_list.num_windows; win_id++)
186 	{
187 		window_info *win = &windows_list.window[win_id];
188 		if(windows_list.window[win_id].window_id != win_id)
189 			continue;
190 		if (win->ui_scale_handler) (*win->ui_scale_handler)(win);
191 	}
192 }
193 
move_window_proportionally(int win_id,float pos_ratio_x,float pos_ratio_y)194 static void move_window_proportionally(int win_id, float pos_ratio_x, float pos_ratio_y)
195 {
196 	window_info *win = NULL;
197 	int new_x, new_y;
198 	if (win_id < 0 || win_id >= windows_list.num_windows)
199 		return;
200 	win = &windows_list.window[win_id];
201 	new_x = (int)(0.5 + pos_ratio_x * ((float)win->cur_x + (float)win->len_x / 2.0f) - (float)win->len_x / 2.0f);
202 	new_y = (int)(0.5 + pos_ratio_y * ((float)win->cur_y + (float)win->len_y / 2.0f) - (float)win->len_y / 2.0f);
203 	move_window(win->window_id, win->pos_id, win->pos_loc, new_x, new_y);
204 }
205 
move_windows_proportionally(float pos_ratio_x,float pos_ratio_y)206 void move_windows_proportionally(float pos_ratio_x, float pos_ratio_y)
207 {
208 	enum managed_window_enum i;
209 	for (i = 0; i < MW_MAX; i++)
210 	{
211 		if (!managed_windows.list[i].prop_pos)
212 			continue;
213 		if (managed_windows.list[i].id < 0)
214 		{
215 			managed_windows.list[i].pos_ratio_x *= pos_ratio_x;
216 			managed_windows.list[i].pos_ratio_y *= pos_ratio_y;
217 		}
218 		else
219 		{
220 			move_window_proportionally(managed_windows.list[i].id, pos_ratio_x, pos_ratio_y);
221 			managed_windows.list[i].pos_ratio_x = managed_windows.list[i].pos_ratio_y = 1.0f;
222 		}
223 	}
224 }
225 
get_MW_index(int window_id)226 static enum managed_window_enum get_MW_index(int window_id)
227 {
228 	if ((window_id >= 0) && (window_id < windows_list.num_windows))
229 	{
230 		enum managed_window_enum i;
231 		for (i = 0; i < MW_MAX; i++)
232 			if (managed_windows.list[i].id == window_id)
233 				return i;
234 	}
235 	return MW_MAX;
236 }
237 
centre_window_MW(enum managed_window_enum managed_win)238 static void centre_window_MW(enum managed_window_enum managed_win)
239 {
240 	if (managed_win >= MW_MAX)
241 		return;
242 	if ((managed_windows.list[managed_win].id >= 0) && (managed_windows.list[managed_win].id < windows_list.num_windows))
243 	{
244 		window_info *win = &windows_list.window[managed_windows.list[managed_win].id];
245 		int new_x = (window_width - win->len_x - HUD_MARGIN_X) / 2;
246 		int new_y = (window_height - win->len_y - HUD_MARGIN_Y) / 2;
247 		move_window(win->window_id, win->pos_id, win->pos_loc, new_x, new_y);
248 	}
249 }
250 
set_window_centered_MW(int window_id,int state)251 static void set_window_centered_MW(int window_id, int state)
252 {
253 	enum managed_window_enum managed_win = get_MW_index(window_id);
254 	if (managed_win < MW_MAX)
255 	{
256 		managed_windows.list[managed_win].keep_centred = state;
257 		if (state == 1)
258 			centre_window_MW(managed_win);
259 	}
260 }
261 
262 #ifdef JSON_FILES
get_json_window_state_MW(enum managed_window_enum managed_win)263 void get_json_window_state_MW(enum managed_window_enum managed_win)
264 {
265 	if (managed_win < MW_MAX)
266 	{
267 		char window_dict_name[50];
268 		int pos_x = 0, pos_y = 0;
269 		get_dict_name_WM(managed_win, window_dict_name, sizeof(window_dict_name));
270 		pos_x = json_cstate_get_int(window_dict_name, "pos_x",
271 			(managed_windows.list[managed_win].keep_centred) ? -1 : managed_windows.list[managed_win].pos_x);
272 		pos_y = json_cstate_get_int(window_dict_name, "pos_y",
273 			(managed_windows.list[managed_win].keep_centred) ? -1 : managed_windows.list[managed_win].pos_y);
274 		if ((pos_x >= 0) || (pos_y >= 0))
275 			set_pos_MW(managed_win, pos_x, pos_y);
276 	}
277 }
278 
set_json_window_state_MW(enum managed_window_enum managed_win)279 void set_json_window_state_MW(enum managed_window_enum managed_win)
280 {
281 	if ((managed_win < MW_MAX) && !managed_windows.list[managed_win].keep_centred)
282 	{
283 		char window_dict_name[50];
284 		int pos_x = 0, pos_y = 0;
285 		get_dict_name_WM(managed_win, window_dict_name, sizeof(window_dict_name));
286 		set_save_pos_MW(managed_win, &pos_x, &pos_y);
287 		json_cstate_set_int(window_dict_name, "pos_x", pos_x);
288 		json_cstate_set_int(window_dict_name, "pos_y", pos_y);
289 	}
290 }
291 #endif
292 
293 // Called just before saving data on exit.
294 // Window positions are proportionally adjusted ready for the next client run.
295 // Any window instantiated at exit will be positioned correctly.
296 // Any window that was not instantiated, will be positioned correctly only if
297 // the next start has the same sizes as was used starting this time.
298 // The case where the client will start with a different sizes than this time
299 // will cause the position of uninstantiated windows to be wrong.  This will be
300 // fixed when we save the managed window information as JSON.
restore_window_proportionally(void)301 void restore_window_proportionally(void)
302 {
303 	if (!full_screen)
304 	{
305 		int index = video_mode - 1;
306 		int new_width, new_height;
307 		if (index < 0 || index >= video_modes_count)
308 			index = 0;
309 		if (index == 0)
310 		{
311 			new_width = video_user_width;
312 			new_height = video_user_height;
313 		} else {
314 			new_width = video_modes[index].width;
315 			new_height = video_modes[index].height;
316 		}
317 		move_windows_proportionally((float)new_width / (float)window_width, (float)new_height / (float)window_height);
318 	}
319 }
320 
check_proportional_move(enum managed_window_enum managed_win)321 void check_proportional_move(enum managed_window_enum managed_win)
322 {
323 	if (managed_win >= MW_MAX)
324 		return;
325 	if (managed_windows.list[managed_win].keep_centred)
326 		centre_window_MW(managed_win);
327 	else if (managed_windows.list[managed_win].prop_pos && ((managed_windows.list[managed_win].pos_ratio_x != 1.0f) || (managed_windows.list[managed_win].pos_ratio_y != 1.0f)))
328 	{
329 		move_window_proportionally(managed_windows.list[managed_win].id, managed_windows.list[managed_win].pos_ratio_x, managed_windows.list[managed_win].pos_ratio_y);
330 		managed_windows.list[managed_win].pos_ratio_x = managed_windows.list[managed_win].pos_ratio_y = 1.0f;
331 	}
332 }
333 
get_by_name_MW(const char * name)334 enum managed_window_enum get_by_name_MW(const char *name)
335 {
336 	enum managed_window_enum i;
337 	if (name == NULL)
338 		return MW_MAX;
339 	for (i = 0; i < MW_MAX; i++)
340 		if (strcmp(managed_windows.list[i].icon_name, name) == 0)
341 			return i;
342 	return MW_MAX;
343 }
344 
get_dict_name_WM(enum managed_window_enum managed_win,char * buf,size_t buf_len)345 const char *get_dict_name_WM(enum managed_window_enum managed_win, char *buf, size_t buf_len)
346 {
347 	if (managed_win < MW_MAX)
348 		safe_snprintf(buf, buf_len, "%s_window", managed_windows.list[managed_win].icon_name);
349 	else
350 		safe_strncpy(buf, "unknown_window", buf_len);
351 	return buf;
352 }
353 
get_id_MW(enum managed_window_enum managed_win)354 int get_id_MW(enum managed_window_enum managed_win)
355 {
356 	if (managed_win < MW_MAX)
357 		return managed_windows.list[managed_win].id;
358 	else
359 		return -1;
360 }
361 
set_id_MW(enum managed_window_enum managed_win,int win_id)362 void set_id_MW(enum managed_window_enum managed_win, int win_id)
363 {
364 	if (managed_win < MW_MAX)
365 		managed_windows.list[managed_win].id = win_id;
366 }
367 
set_pos_MW(enum managed_window_enum managed_win,int pos_x,int pos_y)368 void set_pos_MW(enum managed_window_enum managed_win, int pos_x, int pos_y)
369 {
370 	if (managed_win < MW_MAX)
371 	{
372 		managed_windows.list[managed_win].pos_x = pos_x;
373 		managed_windows.list[managed_win].pos_y = pos_y;
374 		managed_windows.list[managed_win].keep_centred = 0;
375 	}
376 }
377 
get_pos_x_MW(enum managed_window_enum managed_win)378 int get_pos_x_MW(enum managed_window_enum managed_win)
379 {
380 	if (managed_win < MW_MAX)
381 		return managed_windows.list[managed_win].pos_x;
382 	else
383 		return 0;
384 }
385 
get_pos_y_MW(enum managed_window_enum managed_win)386 int get_pos_y_MW(enum managed_window_enum managed_win)
387 {
388 	if (managed_win < MW_MAX)
389 		return managed_windows.list[managed_win].pos_y;
390 	else
391 		return 0;
392 }
393 
on_top_responsive_MW(enum managed_window_enum managed_win)394 int on_top_responsive_MW(enum managed_window_enum managed_win)
395 {
396 	if (managed_win < MW_MAX)
397 		return managed_windows.list[managed_win].on_top;
398 	else
399 		return 0;
400 }
401 
not_on_top_now(enum managed_window_enum managed_win)402 int not_on_top_now(enum managed_window_enum managed_win)
403 {
404 	if ((managed_win < MW_MAX) && managed_windows.list[managed_win].on_top && !windows_on_top)
405 		return 1;
406 	else
407 		return 0;
408 }
409 
clear_was_open_MW(enum managed_window_enum managed_win)410 void clear_was_open_MW(enum managed_window_enum managed_win)
411 {
412 	if (managed_win < MW_MAX)
413 		managed_windows.list[managed_win].was_open = 0;
414 }
415 
set_was_open_MW(enum managed_window_enum managed_win)416 void set_was_open_MW(enum managed_window_enum managed_win)
417 {
418 	if (managed_win < MW_MAX)
419 		managed_windows.list[managed_win].was_open = 1;
420 }
421 
was_open_MW(enum managed_window_enum managed_win)422 int was_open_MW(enum managed_window_enum managed_win)
423 {
424 	if (managed_win < MW_MAX)
425 		return managed_windows.list[managed_win].was_open;
426 	else
427 		return 0;
428 }
429 
is_hideable_MW(enum managed_window_enum managed_win)430 int is_hideable_MW(enum managed_window_enum managed_win)
431 {
432 	if (managed_win < MW_MAX)
433 		return managed_windows.list[managed_win].hideable;
434 	else
435 		return 0;
436 }
437 
clear_hideable_MW(enum managed_window_enum managed_win)438 void clear_hideable_MW(enum managed_window_enum managed_win)
439 {
440 	if (managed_win < MW_MAX)
441 		managed_windows.list[managed_win].hideable = 0;
442 }
443 
set_hideable_MW(enum managed_window_enum managed_win)444 void set_hideable_MW(enum managed_window_enum managed_win)
445 {
446 	if (managed_win < MW_MAX)
447 		managed_windows.list[managed_win].hideable = 1;
448 }
449 
call_display_MW(enum managed_window_enum managed_win)450 void call_display_MW(enum managed_window_enum managed_win)
451 {
452 	if ((managed_win < MW_MAX) && (managed_windows.list[managed_win].display != NULL))
453 		managed_windows.list[managed_win].display();
454 }
455 
match_keydef_MW(enum managed_window_enum managed_win,SDL_Keycode key_code,Uint16 key_mod)456 int match_keydef_MW(enum managed_window_enum managed_win, SDL_Keycode key_code, Uint16 key_mod)
457 {
458 	if ((managed_win < MW_MAX) && (managed_windows.list[managed_win].key_def != NULL))
459 		return (KEY_DEF_CMP((*(managed_windows.list[managed_win].key_def)), key_code, key_mod));
460 	else
461 		return 0;
462 }
463 
get_scale_WM(enum managed_window_enum managed_win)464 float * get_scale_WM(enum managed_window_enum managed_win)
465 {
466 	if (managed_win < MW_MAX)
467 		return &managed_windows.list[managed_win].scale;
468 	else
469 		return NULL;
470 }
471 
get_scale_flag_MW(void)472 int * get_scale_flag_MW(void)
473 {
474 	return &managed_windows.disable_mouse_or_keys_scaling;
475 }
476 
set_save_pos_MW(enum managed_window_enum managed_win,int * pos_x,int * pos_y)477 void set_save_pos_MW(enum managed_window_enum managed_win, int *pos_x, int *pos_y)
478 {
479 	if (managed_win >= MW_MAX)
480 		return;
481 	if (managed_windows.list[managed_win].id >= 0)
482 	{
483 		*pos_x = windows_list.window[managed_windows.list[managed_win].id].cur_x;
484 		*pos_y = windows_list.window[managed_windows.list[managed_win].id].cur_y;
485 	}
486 	else
487 	{
488 		*pos_x = managed_windows.list[managed_win].pos_x;
489 		*pos_y = managed_windows.list[managed_win].pos_y;
490 	}
491 }
492 
toggle_window_MW(enum managed_window_enum managed_win)493 void toggle_window_MW(enum managed_window_enum managed_win)
494 {
495 	if (managed_win >= MW_MAX)
496 		return;
497 	if (managed_windows.list[managed_win].toggle != NULL)
498 		managed_windows.list[managed_win].toggle();
499 	else
500 		toggle_window(get_id_MW(managed_win));
501 }
502 
get_window_showable_MW(enum managed_window_enum managed_win)503 int get_window_showable_MW(enum managed_window_enum managed_win)
504 {
505 	if (managed_win >= MW_MAX)
506 		return 0;
507 	if (managed_windows.list[managed_win].showable != NULL)
508 		return managed_windows.list[managed_win].showable();
509 	else
510 		return get_window_showable(get_id_MW(managed_win));
511 }
512 
change_window_font(window_info * win,font_cat cat)513 static void change_window_font(window_info *win, font_cat cat)
514 {
515 	widget_list *W;
516 
517 	if (win->font_category == cat)
518 	{
519 		if (win->flags & ELW_USE_UISCALE)
520 		{
521 			win->small_font_max_len_x = get_max_char_width_zoom(win->font_category, win->current_scale_small);
522 			win->small_font_len_y = get_line_height(win->font_category, win->current_scale_small);
523 			win->default_font_max_len_x = get_max_char_width_zoom(win->font_category, win->current_scale);
524 			win->default_font_len_y = get_line_height(win->font_category, win->current_scale);
525 			win->title_height = max2i(win->small_font_len_y, win->current_scale*ELW_TITLE_HEIGHT);
526 		}
527 		else
528 		{
529 			win->small_font_max_len_x = get_max_char_width_zoom(win->font_category,
530 				DEFAULT_SMALL_RATIO);
531 			win->small_font_len_y = get_line_height(win->font_category, DEFAULT_SMALL_RATIO);
532 			win->default_font_max_len_x = get_max_char_width_zoom(win->font_category, 1.0);
533 			win->default_font_len_y = get_line_height(win->font_category, 1.0);
534 			win->title_height = max2i(win->small_font_len_y, ELW_TITLE_HEIGHT);
535 		}
536 	}
537 
538 	for (W = win->widgetlist; W; W = W->next)
539 		widget_handle_font_change(W, cat);
540 
541 	if (win->font_change_handler)
542 		(*win->font_change_handler)(win, cat);
543 }
544 
change_windows_font(font_cat cat)545 void change_windows_font(font_cat cat)
546 {
547 	int win_id;
548 	for (win_id = 0; win_id < windows_list.num_windows; ++win_id)
549 	{
550 		window_info *win = &windows_list.window[win_id];
551 		change_window_font(win, cat);
552 	}
553 }
554 
555 // general windows manager functions
display_windows(int level)556 void	display_windows(int level)
557 {
558 	int	id;
559 	int	next_id;
560 	int i;
561 
562 	windows_list.display_level= level;
563 	glColor3f(1.0f, 1.0f, 1.0f);
564 	// first draw everything that is last under everything
565 	id= -1;
566 	while (1)
567 	{
568 		next_id = -9999;
569 		for (i=0; i < windows_list.num_windows; i++)
570 		{
571 			// only look at displayed windows
572 			if (windows_list.window[i].displayed > 0)
573 			{
574 				// at this level?
575 				if (windows_list.window[i].order == id)
576 				{
577 					display_window(i);
578 				} else if (windows_list.window[i].order < id && windows_list.window[i].order > next_id)
579 				{
580 					// try to find the next level
581 					next_id = windows_list.window[i].order;
582 				}
583 			}
584 		}
585 
586 		if(next_id <= -9999)
587 		{
588 			break;
589 		}
590 		else
591 		{
592 			id= next_id;
593 		}
594 	}
595 
596 	top_SWITCHABLE_OPAQUE_window_drawn = -1;
597 	if(level > 0)
598 	{
599 		// now display each window in the proper order
600 		id = 0;
601 		while (1)
602 		{
603 			next_id = 9999;
604 			for (i = 0; i < windows_list.num_windows; i++)
605 			{
606 				// change the opaque option for all ELW_SWITCHABLE_OPAQUE if config has changed
607 				if ((windows_list.window[i].flags&ELW_SWITCHABLE_OPAQUE) &&
608 				    (last_opaque_window_backgrounds != opaque_window_backgrounds))
609 				{
610 					windows_list.window[i].opaque = opaque_window_backgrounds;
611 				}
612 				// only look at displayed windows
613 				if (windows_list.window[i].displayed > 0)
614 				{
615 					// at this level?
616 					if (windows_list.window[i].order == id)
617 					{
618 						display_window(i);
619 						// remember the top window that has ELW_SWITCHABLE_OPAQUE
620 						if (windows_list.window[i].flags&ELW_SWITCHABLE_OPAQUE)
621 							top_SWITCHABLE_OPAQUE_window_drawn = i;
622 					}
623 					else if (windows_list.window[i].order > id && windows_list.window[i].order < next_id)
624 					{
625 						// try to find the next level
626 						next_id = windows_list.window[i].order;
627 					}
628 				}
629 			}
630 			if (next_id >= 9999)
631 			{
632 				break;
633 			}
634 			else
635 			{
636 				id = next_id;
637 			}
638 		}
639 	}
640 	last_opaque_window_backgrounds = opaque_window_backgrounds;
641 }
642 
643 
click_in_windows(int mx,int my,Uint32 flags)644 int	click_in_windows(int mx, int my, Uint32 flags)
645 {
646 	int	done= 0;
647 	int	id;
648 	int	next_id;
649 	int	first_win= -1;
650 	int i;
651 
652 	/* only activate context menu on unmodified right click */
653 	int cm_try_activate = cm_pre_show_check(flags);
654 
655 	// check each window in the proper order
656 	if(windows_list.display_level > 0)
657 	{
658 		id= 9999;
659 		while(done <= 0)
660 		{
661 			next_id= 0;
662 			for (i=0; i<windows_list.num_windows; i++)
663 			{
664 				// only look at displayed windows
665 				if (windows_list.window[i].displayed > 0)
666 				{
667 					// at this level?
668 					if(windows_list.window[i].order == id)
669 					{
670 						if (cm_try_activate && cm_show_if_active(i))
671 							return 0;
672 						done= click_in_window(i, mx, my, flags);
673 						if(done > 0)
674 						{
675 							if(windows_list.window[i].displayed > 0)	select_window(i);	// select this window to the front
676 							cm_post_show_check(0);
677 							return i;
678 						}
679 						if(first_win < 0 && mouse_in_window(i, mx, my))	first_win= i;
680 					}
681 					else if(windows_list.window[i].order < id && windows_list.window[i].order > next_id)
682 					{
683 						// try to find the next level
684 						next_id= windows_list.window[i].order;
685 					}
686 				}
687 			}
688 			if(next_id <= 0)
689 				break;
690 			else
691 				id= next_id;
692 		}
693 	}
694 
695 	// now check the background windows in the proper order
696 	id= -9999;
697 	while(done <= 0)
698 	{
699 		next_id= 0;
700 		for(i=0; i<windows_list.num_windows; i++)
701 		{
702 			// only look at displayed windows
703 			if(windows_list.window[i].displayed > 0)
704 			{
705 				// at this level?
706 				if(windows_list.window[i].order == id)
707 				{
708 					if (cm_try_activate && cm_show_if_active(i))
709 						return 0;
710 					done= click_in_window(i, mx, my, flags);
711 					if(done > 0)
712 					{
713 						//select_window(i);	// these never get selected
714 						cm_post_show_check(0);
715 						return i;
716 					}
717 				}
718 				else if(windows_list.window[i].order > id && windows_list.window[i].order < next_id)
719 				{
720 					// try to find the next level
721 					next_id= windows_list.window[i].order;
722 				}
723 			}
724 		}
725 		if(next_id >= 0)
726 			break;
727 		else
728 			id= next_id;
729 	}
730 
731 	cm_post_show_check(0);
732 
733 	// nothing to click on, do a select instead
734 	if(first_win >= 0)
735 	{
736 		select_window(first_win);
737 		return first_win;
738 	}
739 
740 	return -1;	// no click in a window
741 }
742 
drag_in_windows(int mx,int my,Uint32 flags,int dx,int dy)743 int	drag_in_windows(int mx, int my, Uint32 flags, int dx, int dy)
744 {
745 	int	done = 0;
746 	int	id;
747 	int	next_id;
748 	int i;
749 	window_info *win;
750 
751 	// ignore a drag of 0, but say we processed
752 	if(dx == 0 && dy == 0)	return -1;
753 
754 	if (cur_drag_window)
755 	{
756 		// a drag was started from cur_drag_window, let that window
757 		// handle it, regardless of where the cursor is
758 
759 		done = drag_in_window (cur_drag_window->window_id, mx, my, flags, dx, dy);
760 		if (done > 0)
761 		{
762 			if (cur_drag_window->displayed)
763 				// select this window to the front
764 				select_window (cur_drag_window->window_id);
765 			return cur_drag_window->window_id;
766 		}
767 		else
768 		{
769 			// The original window didn't handle the drag, reset it
770 			// and continue
771 			cur_drag_window = NULL;
772 		}
773 	}
774 
775 	// check each window in the proper order
776 	if(windows_list.display_level > 0)
777 	{
778 		id= 9999;
779 		while (done <= 0)
780 		{
781 			next_id= 0;
782 			for(i=0; i < windows_list.num_windows; i++)
783 			{
784 				win = &(windows_list.window[i]);
785 				// only look at displayed windows
786 				if (win->displayed)
787 				{
788 					// at this level?
789 					if(win->order == id)
790 					{
791 						done = drag_in_window (i, mx, my, flags, dx, dy);
792 						if (done > 0)
793 						{
794 							if (win->displayed)
795 								select_window(i);	// select this window to the front
796 							cur_drag_window = win;
797 							return i;
798 						}
799 						else if (mouse_in_window (i, mx, my))
800 						{
801 							// drag started in this window
802 							return -1;
803 						}
804 					}
805 					else if (win->order < id && win->order > next_id)
806 					{
807 						// try to find the next level
808 						next_id= win->order;
809 					}
810 				}
811 			}
812 			if(next_id <= 0)
813 				break;
814 			else
815 				id= next_id;
816 		}
817 	}
818 
819 	// now check the background windows in the proper order
820 	id= -9999;
821 	while (done <= 0)
822 	{
823 		next_id= 0;
824 		for (i=0; i<windows_list.num_windows; i++)
825 		{
826 			win = &(windows_list.window[i]);
827 			// only look at displayed windows
828 			if(win->displayed)
829 			{
830 				// at this level?
831 				if(win->order == id)
832 				{
833 					done = drag_in_window (i, mx, my, flags, dx, dy);
834 					if(done > 0)
835 					{
836 						//select_window(i);	// these never get selected
837 						cur_drag_window = win;
838 						return i;
839 					}
840 					else if (mouse_in_window (i, mx, my))
841 					{
842 						// drag started in this window
843 						return -1;
844 					}
845 				}
846 				else if (win->order > id && win->order < next_id)
847 				{
848 					// try to find the next level
849 					next_id = win->order;
850 				}
851 			}
852 		}
853 		if(next_id >= 0)
854 			break;
855 		else
856 			id= next_id;
857 	}
858 
859 	return -1;	// no drag in a window
860 }
861 
862 
drag_windows(int mx,int my,int dx,int dy)863 int drag_windows (int mx, int my, int dx, int dy)
864 {
865 	int	next_id;
866 	int	id, i;
867 	int	drag_id = -1;
868 	int dragable, resizeable;
869 	int x, y;
870 	window_info *win;
871 
872 	if (cur_drag_window)
873 	{
874 		// We are currently dragging inside another window, don't
875 		// interrupt that by moving another window around
876 		return -1;
877 	}
878 
879 	// check each window in the proper order for which one might be getting dragged
880 	if(windows_list.display_level > 0)
881 	{
882 		id= 9999;
883 		while(drag_id < 0)
884 		{
885 			next_id= 0;
886 			for(i=0; i<windows_list.num_windows; i++)
887 			{
888 				win = &(windows_list.window[i]);
889 				dragable = win->flags & ELW_DRAGGABLE;
890 				resizeable = win->flags & ELW_RESIZEABLE;
891 				// only look at displayed windows
892 				if (win->displayed && (dragable || resizeable) )
893 				{
894 					// at this level?
895 					if(win->order == id)
896 					{
897 						// position relative to window
898 						x = mx - win->cur_x;
899 						y = my - win->cur_y;
900 
901 						// first check for being actively dragging or on the top bar
902 						if (win->dragged || (dragable && mouse_in_window(i, mx, my) && ((y < 0) || (win->owner_drawn_title_bar && y < win->title_height))) )
903 						{
904 							drag_id = i;
905 							win->dragged = 1;
906 							break;
907 						}
908 						// check if we are resizing this window
909 						else if (win->resized || (resizeable && mouse_in_window(i, mx, my) && x > win->len_x - win->box_size && y > win->len_y - win->box_size) )
910 						{
911 							drag_id = i;
912 							win->resized = 1;
913 							break;
914 						}
915 						// check if we're dragging inside a window
916 						else if(mouse_in_window(i, mx, my))
917 						{
918 							return -1;
919 						}
920 					}
921 					else if (win->order < id && win->order > next_id)
922 					{
923 						// try to find the next level
924 						next_id = win->order;
925 					}
926 				}
927 			}
928 			if(next_id <= 0)
929 				break;
930 			else
931 				id= next_id;
932 		}
933 	}
934 
935 	// this section probably won't be needed, included to be complete
936 	// now check the background windows in the proper order for which one might be getting dragged
937 	id = -9999;
938 	while (drag_id < 0)
939 	{
940 		next_id = 0;
941 		for (i=0; i<windows_list.num_windows; i++)
942 		{
943 			win = &(windows_list.window[i]);
944 			dragable = win->flags & ELW_DRAGGABLE;
945 			resizeable = win->flags & ELW_RESIZEABLE;
946 			// only look at displayed windows
947 			if (win->displayed && (dragable || resizeable) )
948 			{
949 				// at this level?
950 				if(win->order == id)
951 				{
952 					// position relative to window
953 					x = mx - win->cur_x;
954 					y = my - win->cur_y;
955 
956 					// check for being actively dragging or on the top bar
957 					if(win->dragged || (mouse_in_window(i, mx, my) && y < 0) )
958 					{
959 						drag_id = i;
960 						win->dragged = 1;
961 						break;
962 					}
963 					// check if we are resizing this window
964 					else if (resizeable && mouse_in_window(i, mx, my) && x > win->len_x - win->box_size && y > win->len_y - win->box_size)
965 					{
966 						drag_id = i;
967 						win->resized = 1;
968 						break;
969 					}
970 					// check if we're dragging inside a window
971 					else if (mouse_in_window(i, mx, my))
972 					{
973 						return -1;
974 					}
975 				}
976 				else if (win->order > id && win->order < next_id){
977 					// try to find the next level
978 					next_id = win->order;
979 				}
980 			}
981 		}
982 		if (next_id >= 0)
983 			break;
984 		else
985 			id= next_id;
986 	}
987 
988 	// are we dragging a window?
989 	if (drag_id < 0) return -1;
990 
991 	// dragged window is always on top
992 	select_window (drag_id);
993 
994 	if(left_click>1 && (dx != 0 || dy != 0))	// TODO: avoid globals?
995 	{
996 		win = &(windows_list.window[drag_id]);
997 		if (win->dragged)
998 		{
999 			// move to new location
1000 			move_window (drag_id, win->pos_id, win->pos_loc, win->pos_x+dx, win->pos_y+dy);
1001 			set_window_centered_MW(win->window_id, 0);
1002 		}
1003 		else
1004 			// resize this window
1005 			resize_window (drag_id, win->len_x + dx, win->len_y + dy);
1006 	}
1007 
1008 	return drag_id;
1009 }
1010 
keypress_in_windows(int x,int y,SDL_Keycode key_code,Uint32 key_unicode,Uint16 key_mod)1011 int	keypress_in_windows(int x, int y, SDL_Keycode key_code, Uint32 key_unicode, Uint16 key_mod)
1012 {
1013 	int	done= 0;
1014 	int	id;
1015 	int	next_id;
1016 	int i;
1017 
1018 	// check each window in the proper order
1019 	if(windows_list.display_level > 0)
1020 	{
1021 		id= 9999;
1022 		while(done <= 0)
1023 		{
1024 			next_id= 0;
1025 			for (i=0; i<windows_list.num_windows; i++)
1026 			{
1027 				// only look at displayed windows
1028 				if (windows_list.window[i].displayed > 0)
1029 				{
1030 					// at this level?
1031 					if(windows_list.window[i].order == id)
1032 					{
1033 						done = keypress_in_window (i, x, y, key_code, key_unicode, key_mod);
1034 						if(done > 0)
1035 						{
1036 							if (windows_list.window[i].displayed > 0)
1037 								select_window(i);	// select this window to the front
1038 							return i;
1039 						}
1040 					}
1041 					else if(windows_list.window[i].order < id && windows_list.window[i].order > next_id)
1042 					{
1043 						// try to find the next level
1044 						next_id = windows_list.window[i].order;
1045 					}
1046 				}
1047 			}
1048 			if(next_id <= 0)
1049 				break;
1050 			else
1051 				id= next_id;
1052 		}
1053 	}
1054 
1055 	// now check the background windows in the proper order
1056 	id= -9999;
1057 	while(done <= 0)
1058 	{
1059 		next_id= 0;
1060 		for(i=0; i<windows_list.num_windows; i++)
1061 		{
1062 			// only look at displayed windows
1063 			if(windows_list.window[i].displayed > 0)
1064 			{
1065 				// at this level?
1066 				if(windows_list.window[i].order == id)
1067 				{
1068 					done = keypress_in_window(i, x, y, key_code, key_unicode, key_mod);
1069 					if(done > 0)
1070 					{
1071 						//select_window(i);	// these never get selected
1072 						return i;
1073 					}
1074 				}
1075 				else if(windows_list.window[i].order > id && windows_list.window[i].order < next_id)
1076 				{
1077 					// try to find the next level
1078 					next_id= windows_list.window[i].order;
1079 				}
1080 			}
1081 		}
1082 		if(next_id >= 0)
1083 			break;
1084 		else
1085 			id= next_id;
1086 	}
1087 
1088 	return -1;	// no keypress in a window
1089 }
1090 
end_drag_windows()1091 void	end_drag_windows()
1092 {
1093 	int	i;
1094 
1095 	for (i=0; i<windows_list.num_windows; i++)
1096 	{
1097 		windows_list.window[i].dragged= 0;
1098 		windows_list.window[i].resized= 0;
1099 		windows_list.window[i].drag_in= 0;
1100 	}
1101 
1102 	// also reset the window we were dragging in, and the dragged widget
1103 	cur_drag_window = NULL;
1104 	cur_drag_widget = NULL;
1105 }
1106 
1107 
select_window_with(int win_id,int raise_parent,int raise_children)1108 int	select_window_with (int win_id, int raise_parent, int raise_children)
1109 {
1110 	int	i, old;
1111 
1112 	if (win_id < 0 || win_id >= windows_list.num_windows)	return -1;
1113 	if (windows_list.window[win_id].window_id != win_id)	return -1;
1114 	// never select background windows
1115 	if (windows_list.window[win_id].order < 0)		return 0;
1116 
1117 	// if this is a child window, raise the parent first
1118 	if (raise_parent && windows_list.window[win_id].pos_id >= 0)
1119 		select_window_with (windows_list.window[win_id].pos_id, 1, 0);
1120 
1121 	// shuffle the order of the windows
1122 	old = windows_list.window[win_id].order;
1123 	for (i=0; i<windows_list.num_windows; i++)
1124 	{
1125 		if(windows_list.window[i].order > old)
1126 			windows_list.window[i].order--;
1127 	}
1128 
1129 	// and put it on top
1130 	windows_list.window[win_id].order = windows_list.num_windows;
1131 
1132 	// now raise all children
1133 	if (raise_children)
1134 	{
1135 		for (i=0; i<windows_list.num_windows; i++)
1136 		{
1137 			if (windows_list.window[i].pos_id == win_id)
1138 				select_window_with (i, 0, 1);
1139 		}
1140 	}
1141 
1142 	return 1;
1143 }
1144 
select_window(int win_id)1145 int	select_window (int win_id)
1146 {
1147 	return select_window_with (win_id, 1, 1);
1148 }
1149 
1150 
cm_title_handler(window_info * win,int widget_id,int mx,int my,int option)1151 int cm_title_handler(window_info *win, int widget_id, int mx, int my, int option)
1152 {
1153 	extern void hide_all_windows();
1154 	switch (option)
1155 	{
1156 		case 0: hide_all_windows(); break;
1157 		case 1: break; // make sure the sound is sucess.
1158 		case 5: set_window_centered_MW(win->window_id, 1); break;
1159 	}
1160 	return 1;
1161 }
1162 
1163 
1164 // specific windows functions
create_window(const char * name,int pos_id,Uint32 pos_loc,int pos_x,int pos_y,int size_x,int size_y,Uint32 property_flags)1165 int	create_window(const char *name, int pos_id, Uint32 pos_loc, int pos_x, int pos_y, int size_x, int size_y, Uint32 property_flags)
1166 {
1167 	window_info *win;
1168 	int	win_id=-1;
1169 	int	i;
1170 	int isold = 1;
1171 
1172 	// verify that we are setup and space allocated
1173 	if (windows_list.window == NULL)
1174 	{
1175 		// allocate the space
1176 		windows_list.num_windows = 0;
1177 		windows_list.max_windows = ELW_WIN_MAX;
1178 		windows_list.window=(window_info *) calloc(ELW_WIN_MAX, sizeof(window_info));
1179 		//windows_list.window[0].window_id = -1;	// force a rebuild of this
1180 		//windows_list.num_windows = 1;
1181 	}
1182 
1183 	// find an empty slot
1184 	for (i=1; i<windows_list.num_windows; i++)
1185 	{
1186 		if (windows_list.window[i].window_id < 0)
1187 		{
1188 			win_id = i;
1189 			break;
1190 		}
1191 	}
1192 
1193 	// need a new_entry?
1194 	if (win_id < 0)
1195 	{
1196 		isold = 0;
1197 		if (windows_list.num_windows < windows_list.max_windows - 1)
1198 		{
1199 			win_id = windows_list.num_windows++;
1200 		}
1201 	}
1202 
1203 	// fill in the information
1204 	if (win_id >= 0)
1205 	{
1206 		win = &windows_list.window[win_id];
1207 		win->window_id = win_id;
1208 
1209 		win->flags = property_flags;
1210 		//win->collapsed = 0;
1211 		win->dragged = 0;
1212 		win->resized = 0;
1213 		win->drag_in = 0;
1214 		win->opaque = opaque_window_backgrounds;
1215 		win->owner_drawn_title_bar = 0;
1216 		if (win->flags&ELW_TITLE_BAR)
1217 		{
1218 			win->cm_id = cm_create(cm_title_menu_str, cm_title_handler);
1219 			if (win->flags&ELW_SWITCHABLE_OPAQUE)
1220 				cm_bool_line(win->cm_id, 1, &win->opaque, NULL);
1221 			else
1222 				cm_grey_line(win->cm_id, 1, 1);
1223 			cm_bool_line(win->cm_id, 2, &windows_on_top, "windows_on_top");
1224 			cm_bool_line(win->cm_id, 3, get_scale_flag_MW(), "disable_window_scaling_controls");
1225 		}
1226 		else
1227 			win->cm_id = CM_INIT_VALUE;
1228 		safe_strncpy(win->window_name, name, sizeof (win->window_name));
1229 
1230 		if (pos_id >= 0 && !windows_list.window[pos_id].displayed)
1231 		{
1232 			// parent is hidden
1233 			win->reinstate = (property_flags & ELW_SHOW) ? 1 : 0;
1234 			win->displayed = 0;
1235 		}
1236 		else
1237 		{
1238 			// no parent, or parent is shown
1239 			win->displayed = (property_flags & ELW_SHOW) ? 1 : 0;
1240 			win->reinstate = 0;
1241 		}
1242 
1243 		win->back_color[0] = 0.0f;
1244 		win->back_color[1] = 0.0f;
1245 		win->back_color[2] = 0.0f;
1246 		win->back_color[3] = 0.4f;
1247 		win->border_color[0] = gui_color[0];
1248 		win->border_color[1] = gui_color[1];
1249 		win->border_color[2] = gui_color[2];
1250 		win->border_color[3] = 0.0f;
1251 		win->line_color[0] = gui_color[0];
1252 		win->line_color[1] = gui_color[1];
1253 		win->line_color[2] = gui_color[2];
1254 		win->line_color[3] = 0.0f;
1255 
1256 		win->custom_scale = NULL;
1257 		// Imherit font category from parent, default to UI_FONT
1258 		if (pos_id >= 0 && pos_id < windows_list.num_windows)
1259 			win->font_category = windows_list.window[pos_id].font_category;
1260 		else
1261 			win->font_category = UI_FONT;
1262 		update_window_scale(win, get_global_scale());
1263 
1264 		win->init_handler = NULL;
1265 		win->display_handler = NULL;
1266 		win->pre_display_handler = NULL;
1267 		win->post_display_handler = NULL;
1268 		win->click_handler = NULL;
1269 		win->drag_handler = NULL;
1270 		win->mouseover_handler = NULL;
1271 		win->resize_handler = NULL;
1272 		win->keypress_handler = NULL;
1273 		win->close_handler = NULL;
1274 		win->destroy_handler = NULL;
1275 		win->show_handler = NULL;
1276 		win->after_show_handler = NULL;
1277 		win->hide_handler = NULL;
1278 		win->ui_scale_handler = NULL;
1279 		win->font_change_handler = NULL;
1280 
1281 		win->widgetlist = NULL;
1282 
1283 		// now call the routine to place it properly
1284 		init_window (win_id, pos_id, pos_loc, pos_x, pos_y, size_x, size_y);
1285 
1286 		win->order = (property_flags & ELW_SHOW_LAST) ? -win_id-1 : win_id+1;
1287 		// make sure the order is unique if this is not a background
1288 		// window
1289 		if (isold && win->order > 0)
1290 		{
1291 			// determine the highest unused order
1292 			int order = windows_list.num_windows;
1293 
1294 			while (1)
1295 			{
1296 				for (i = 0; i < windows_list.num_windows; i++)
1297 				{
1298 					if (windows_list.window[i].order == order)
1299 						break;
1300 				}
1301 				if (i < windows_list.num_windows)
1302 					order--;
1303 				else
1304 					break;
1305 			}
1306 
1307 			win->order = order;
1308 			// select the window to the foreground
1309 			select_window (win_id);
1310 		}
1311 	}
1312 
1313 	return	win_id;
1314 }
1315 
1316 
destroy_window(int win_id)1317 void	destroy_window(int win_id)
1318 {
1319 	window_info *win;
1320 
1321 	if(win_id < 0 || win_id >= windows_list.num_windows)	return;
1322 	if(windows_list.window[win_id].window_id != win_id)	return;
1323 	// mark the window as unused
1324 
1325 	win = &(windows_list.window[win_id]);
1326 
1327 	if (cm_valid(win->cm_id))
1328 	{
1329 		cm_destroy(win->cm_id);
1330 		win->cm_id = CM_INIT_VALUE;
1331 	}
1332 
1333 	// call destruction handler
1334 	if (win->destroy_handler != NULL)
1335 		win->destroy_handler (win);
1336 
1337 	// destroy our widgets
1338 	while (win->widgetlist != NULL)
1339 	{
1340 	    widget_destroy(win_id, win->widgetlist->id);
1341 	}
1342 	win->widgetlist = NULL;
1343 
1344 	win->window_id = -1;
1345 	win->order = -1;
1346 	win->displayed = 0;
1347 }
1348 
init_window(int win_id,int pos_id,Uint32 pos_loc,int pos_x,int pos_y,int size_x,int size_y)1349 int	init_window(int win_id, int pos_id, Uint32 pos_loc, int pos_x, int pos_y, int size_x, int size_y)
1350 {
1351 	int pwin_x, pwin_y;
1352 
1353 	if(win_id < 0 || win_id >= windows_list.num_windows)	return -1;
1354 	if(windows_list.window[win_id].window_id != win_id)	return -1;
1355 	if (pos_id >= 0)
1356 	{
1357 		if (pos_id >= windows_list.num_windows)			return -1;
1358 		if (windows_list.window[pos_id].window_id != pos_id)	return -1;
1359 	}
1360 
1361 	// parent window position. The new window is placed relative to these
1362 	// coordinates. If pos_id < 0, the values are taken to be absolute
1363 	// (i.e. relative to (0, 0) )
1364 	pwin_x = pos_id >= 0 ? windows_list.window[pos_id].cur_x : 0;
1365 	pwin_y = pos_id >= 0 ? windows_list.window[pos_id].cur_y : 0;
1366 
1367 	// memorize the size
1368 	windows_list.window[win_id].len_x= size_x;
1369 	windows_list.window[win_id].len_y= size_y;
1370 	// initialize min_len_x and min_len_y to zero.
1371 	windows_list.window[win_id].min_len_x= 0;
1372 	windows_list.window[win_id].min_len_y= 0;
1373 	// then place the window
1374 	move_window(win_id, pos_id, pos_loc, pos_x+pwin_x, pos_y+pwin_y);
1375 
1376 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE) {
1377 		/* Add the scroll widget */
1378 		Uint16 x = size_x-windows_list.window[win_id].box_size,
1379 				y = size_y,
1380 				width = windows_list.window[win_id].box_size,
1381 				height = size_y;
1382 
1383 		if(windows_list.window[win_id].flags&ELW_CLOSE_BOX) {
1384 			/* Don't put the scrollbar behind the close box. */
1385 			y += windows_list.window[win_id].box_size;
1386 			height -= windows_list.window[win_id].box_size;
1387 		}
1388 		if(windows_list.window[win_id].flags&ELW_RESIZEABLE) {
1389 			/* Don't put the scrollbar behind the resize box. */
1390 			height -= windows_list.window[win_id].box_size;
1391 		}
1392 		windows_list.window[win_id].scroll_id = vscrollbar_add(win_id, NULL, x, y, width, height);
1393 		windows_list.window[win_id].scroll_yoffset = 0;
1394 		widget_set_color(win_id, windows_list.window[win_id].scroll_id,
1395 						windows_list.window[win_id].border_color[0],
1396 						windows_list.window[win_id].border_color[1],
1397 						windows_list.window[win_id].border_color[2]);
1398 	}
1399 	// finally, call any init_handler that was defined
1400 	if(windows_list.window[win_id].init_handler)
1401 	{
1402 		return((*windows_list.window[win_id].init_handler)(&windows_list.window[win_id]));
1403 	}
1404 
1405 	return 1;
1406 }
1407 
move_window(int win_id,int pos_id,Uint32 pos_loc,int pos_x,int pos_y)1408 int	move_window(int win_id, int pos_id, Uint32 pos_loc, int pos_x, int pos_y)
1409 {
1410 	window_info *win;
1411 	int dx, dy, i;
1412 
1413 	if(win_id < 0 || win_id >= windows_list.num_windows)
1414 		return -1;
1415 	if(windows_list.window[win_id].window_id != win_id)
1416 		return -1;
1417 
1418 	win= &windows_list.window[win_id];
1419 
1420 	dx = -win->cur_x;
1421 	dy = -win->cur_y;
1422 
1423 	win->pos_id = pos_id;
1424 	win->pos_loc= pos_loc;	//NOT SUPPORTED YET
1425 	//TODO: calc win->cur_[xy] based on pos_id & pos_loc
1426 	if(win->len_x > 0 && win->len_y > 0 && (win->flags&ELW_TITLE_BAR || win->owner_drawn_title_bar)){
1427 		int xbound = (win->len_x < 50) ? win->len_x : 50;
1428 		int ybound = (win->len_y < 50) ? win->len_y : 50;
1429 		win->pos_x = win->cur_x = clampi(pos_x, xbound - win->len_x, window_width - xbound);
1430 		if(win->owner_drawn_title_bar)
1431 			win->pos_y = win->cur_y = clampi(pos_y, 0, window_height - ybound);
1432 		else
1433 			win->pos_y = win->cur_y = clampi(pos_y, win->title_height, window_height - ybound);
1434 	} else {
1435 		win->pos_x = win->cur_x = pos_x;
1436 		win->pos_y = win->cur_y = pos_y;
1437 	}
1438 
1439 	// don't check child windows for visibility
1440 	if (pos_id < 0 || windows_list.window[pos_id].order < 0) {
1441 		// check for the window actually being on the screen, if not, move it
1442 		if(win->cur_y < ((win->flags&ELW_TITLE_BAR)?win->title_height:0))
1443 			win->pos_y = win->cur_y = (win->flags&ELW_TITLE_BAR)?win->title_height:0;
1444 		if(win->cur_y >= window_height)
1445 			win->pos_y = win->cur_y = window_height;	// had -32, but do we want that?
1446 		if(win->len_x > 0 && (win->cur_x+win->len_x < win->box_size))
1447 			win->pos_x = win->cur_x = 0-win->len_x+win->box_size;
1448 		if(win->cur_x > window_width-win->box_size)
1449 			win->pos_x = win->cur_x = window_width-win->box_size;
1450 	}
1451 
1452 	// move child windows, if any
1453 	dx += win->cur_x;
1454 	dy += win->cur_y;
1455 	for (i = 0; i < windows_list.num_windows; i++) {
1456 		if (windows_list.window[i].pos_id == win_id) {
1457 			move_window (i, win_id, 0, windows_list.window[i].cur_x + dx, windows_list.window[i].cur_y + dy);
1458 		}
1459 	}
1460 
1461 	return 1;
1462 }
1463 
draw_window_title(window_info * win)1464 int	draw_window_title(window_info *win)
1465 {
1466 	float u_first_start = (float)31/255;
1467 	float u_first_end = 0.5f/255.0f;
1468 	float v_first_start = (float)160/255;
1469 	float v_first_end = (float)175/255;
1470 
1471 	float u_middle_start = (float)32/255;
1472 	float u_middle_end = (float)63/255;
1473 	float v_middle_start = (float)160/255;
1474 	float v_middle_end = (float)175/255;
1475 
1476 	float u_last_start = 0.5f/255.0f;
1477 	float u_last_end = (float)31/255;
1478 	float v_last_start = (float)160/255;
1479 	float v_last_end = (float)175/255;
1480 
1481 	int bar_end_x_width = (int)(0.5 + win->current_scale * 32);
1482 
1483 	if((win->flags&ELW_TITLE_BAR) == ELW_TITLE_NONE)	return 0;
1484 
1485 	/* draw the help text if the mouse is over the title bar */
1486 	if (show_help_text && cm_valid(win->cm_id) && (cm_window_shown() == CM_INIT_VALUE) &&
1487 		mouse_x > win->cur_x && mouse_x < win->cur_x+win->len_x &&
1488 		mouse_y > win->cur_y-win->title_height && mouse_y < win->cur_y)
1489 		show_help(cm_title_help_str, 0, win->len_y+10, win->current_scale);
1490 
1491 	glColor3f(1.0f,1.0f,1.0f);
1492 	//ok, now draw it...
1493 
1494 	bind_texture(icons_text);
1495 	glEnable(GL_ALPHA_TEST);
1496 	glAlphaFunc(GL_GREATER,0.03f);
1497 	glBegin(GL_QUADS);
1498 
1499 	if (win->len_x > 2 * bar_end_x_width)
1500 	{
1501 		glTexCoord2f(u_first_end, v_first_start);
1502 		glVertex3i(0, -win->title_height, 0);
1503 		glTexCoord2f(u_first_end, v_first_end);
1504 		glVertex3i(0, 0, 0);
1505 		glTexCoord2f(u_first_start, v_first_end);
1506 		glVertex3i(bar_end_x_width, 0, 0);
1507 		glTexCoord2f(u_first_start, v_first_start);
1508 		glVertex3i(bar_end_x_width, -win->title_height, 0);
1509 
1510 		// draw one streched out cell to the proper size
1511 		glTexCoord2f(u_middle_end, v_middle_start);
1512 		glVertex3i(bar_end_x_width, -win->title_height, 0);
1513 		glTexCoord2f(u_middle_end, v_middle_end);
1514 		glVertex3i(bar_end_x_width, 0, 0);
1515 		glTexCoord2f(u_middle_start, v_middle_end);
1516 		glVertex3i(win->len_x-bar_end_x_width, 0, 0);
1517 		glTexCoord2f(u_middle_start, v_middle_start);
1518 		glVertex3i(win->len_x-bar_end_x_width, -win->title_height, 0);
1519 
1520 		glTexCoord2f(u_last_end, v_last_start);
1521 		glVertex3i(win->len_x-bar_end_x_width, -win->title_height, 0);
1522 		glTexCoord2f(u_last_end, v_last_end);
1523 		glVertex3i(win->len_x-bar_end_x_width, 0, 0);
1524 		glTexCoord2f(u_last_start, v_last_end);
1525 		glVertex3i(win->len_x, 0, 0);
1526 		glTexCoord2f(u_last_start, v_last_start);
1527 		glVertex3i(win->len_x, -win->title_height, 0);
1528 	}
1529 	else
1530 	{
1531 		glTexCoord2f(u_first_end, v_first_start);
1532 		glVertex3i(0, -win->title_height, 0);
1533 		glTexCoord2f(u_first_end, v_first_end);
1534 		glVertex3i(0, 0, 0);
1535 		glTexCoord2f(u_first_start, v_first_end);
1536 		glVertex3i(win->len_x / 2, 0, 0);
1537 		glTexCoord2f(u_first_start, v_first_start);
1538 		glVertex3i(win->len_x / 2, -win->title_height, 0);
1539 
1540 		glTexCoord2f(u_middle_end, v_middle_start);
1541 		glVertex3i(win->len_x / 2, -win->title_height, 0);
1542 		glTexCoord2f(u_middle_end, v_middle_end);
1543 		glVertex3i(win->len_x / 2, 0, 0);
1544 		glTexCoord2f(u_middle_start, v_middle_end);
1545 		glVertex3i(win->len_x / 2 + 1, 0, 0);
1546 		glTexCoord2f(u_middle_start, v_middle_start);
1547 		glVertex3i(win->len_x / 2 + 1, -win->title_height, 0);
1548 
1549 		glTexCoord2f(u_last_end, v_last_start);
1550 		glVertex3i(win->len_x / 2 + 1, -win->title_height, 0);
1551 		glTexCoord2f(u_last_end, v_last_end);
1552 		glVertex3i(win->len_x / 2 + 1, 0, 0);
1553 		glTexCoord2f(u_last_start, v_last_end);
1554 		glVertex3i(win->len_x, 0, 0);
1555 		glTexCoord2f(u_last_start, v_last_start);
1556 		glVertex3i(win->len_x, -win->title_height, 0);
1557 	}
1558 
1559 	glEnd();
1560 	glDisable(GL_ALPHA_TEST);
1561 
1562 	// draw the name of the window
1563 	if(win->flags&ELW_TITLE_NAME)
1564 		{
1565 			int	len = get_string_width_zoom((unsigned char*)win->window_name,
1566 				UI_FONT, win->current_scale_small);
1567 			int	x_pos = (win->len_x-len)/2;
1568 			int y_txt = 1 - win->title_height + (win->title_height - win->small_font_len_y)/2;
1569 
1570 			glColor4f(0.0f,0.0f,0.0f,1.0f);
1571 			glBegin(GL_QUADS);
1572 				glVertex3i(x_pos, -win->title_height, 0);
1573 				glVertex3i(x_pos+len, -win->title_height, 0);
1574 				glVertex3i(x_pos+len, 0, 0);
1575 				glVertex3i(x_pos, 0, 0);
1576 			glEnd();
1577 			glBegin(GL_TRIANGLE_STRIP);
1578 				glVertex3i(x_pos, -win->title_height, 0);
1579 				glVertex3i(x_pos-10, -win->title_height/2, 0);
1580 				glVertex3i(x_pos, 0, 0);
1581 			glEnd();
1582 			glBegin(GL_TRIANGLE_STRIP);
1583 				glVertex3i(x_pos+len, -win->title_height, 0);
1584 				glVertex3i(x_pos+len+10, -win->title_height/2, 0);
1585 				glVertex3i(x_pos+len, 0, 0);
1586 			glEnd();
1587 			glEnable(GL_TEXTURE_2D);
1588 			glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]);
1589 			// center text
1590 			draw_string_small_zoomed(x_pos, y_txt, (const unsigned char*)win->window_name,
1591 				1, win->current_scale);
1592 		}
1593 #ifdef OPENGL_TRACE
1594 CHECK_GL_ERRORS();
1595 #endif //OPENGL_TRACE
1596 
1597 	return 1;
1598 }
1599 
draw_window_border(window_info * win)1600 int	draw_window_border(window_info *win)
1601 {
1602 	glDisable(GL_TEXTURE_2D);
1603 	if(win->flags&ELW_USE_BACKGROUND)
1604 	{
1605 		if (!(win->opaque && win->flags&ELW_SWITCHABLE_OPAQUE))
1606 		{
1607 			glEnable(GL_BLEND);
1608 			glBlendFunc(GL_ONE, GL_SRC_ALPHA);
1609 		}
1610 		glColor4f(win->back_color[0],win->back_color[1],win->back_color[2],win->back_color[3]);
1611 		glBegin(GL_QUADS);
1612 			glVertex3i(0, win->len_y, 0);
1613 			glVertex3i(0, 0, 0);
1614 			glVertex3i(win->len_x, 0, 0);
1615 			glVertex3i(win->len_x, win->len_y, 0);
1616 		glEnd();
1617 		if (!(win->opaque && win->flags&ELW_SWITCHABLE_OPAQUE))
1618 			glDisable(GL_BLEND);
1619 	}
1620 
1621 	if(win->flags&ELW_USE_BORDER)
1622 	{
1623 		if ( use_alpha_border && (win->flags & ELW_ALPHA_BORDER) )
1624 		{
1625 			draw_window_alphaborder (win);
1626 		}
1627 		else
1628 		{
1629 			glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]);
1630 			glBegin(GL_LINE_LOOP);
1631 				glVertex3i(0, 0, 0);
1632 				glVertex3i(win->len_x, 0, 0);
1633 				glVertex3i(win->len_x, win->len_y, 0);
1634 				glVertex3i(0, win->len_y, 0);
1635 			glEnd();
1636 		}
1637 	}
1638 
1639 	if (win->flags&ELW_RESIZEABLE)
1640 	{
1641 		// draw the diagonal drag stripes
1642 		glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]);
1643 		glBegin(GL_LINES);
1644 			glVertex3i(win->len_x-win->box_size/4, win->len_y, 0);
1645 			glVertex3i(win->len_x, win->len_y-win->box_size/4, 0);
1646 
1647 			glVertex3i(win->len_x-win->box_size/2, win->len_y, 0);
1648 			glVertex3i(win->len_x, win->len_y-win->box_size/2, 0);
1649 
1650 			glVertex3i(win->len_x-(3*win->box_size)/4, win->len_y, 0);
1651 			glVertex3i(win->len_x, win->len_y-(3*win->box_size)/4, 0);
1652 
1653 			glVertex3i(win->len_x-win->box_size, win->len_y, 0);
1654 			glVertex3i(win->len_x, win->len_y-win->box_size, 0);
1655 		glEnd();
1656 	}
1657 
1658 	if(win->flags&ELW_CLOSE_BOX)
1659 	{
1660 		//draw the corner, with the X in
1661 		glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]);
1662 		glBegin(GL_LINE_STRIP);
1663 			glVertex3i(win->len_x, win->box_size, 0);
1664 			glVertex3i(win->len_x-win->box_size, win->box_size, 0);
1665 			glVertex3i(win->len_x-win->box_size, 0, 0);
1666 		glEnd();
1667 		draw_cross(win->len_x - win->box_size / 2, win->box_size / 2, win->box_size / 2 - win->box_size / 6, 1);
1668 	}
1669 
1670 	glEnable(GL_TEXTURE_2D);
1671 #ifdef OPENGL_TRACE
1672 CHECK_GL_ERRORS();
1673 #endif //OPENGL_TRACE
1674 
1675 	return 1;
1676 }
1677 
draw_window(window_info * win)1678 int	draw_window(window_info *win)
1679 {
1680 	int	ret_val=0;
1681 	widget_list *W = NULL;
1682 
1683 #ifdef OPENGL_TRACE
1684 CHECK_GL_ERRORS();
1685 #endif //OPENGL_TRACE
1686 	if(win == NULL || win->window_id < 0)
1687 		return -1;
1688 
1689 	if(!win->displayed)
1690 		return 0;
1691 	// mouse over processing first
1692 	mouseover_window(win->window_id, mouse_x, mouse_y);
1693 	if(win->flags&ELW_TITLE_BAR) {
1694 		/* Only move windows with title bars, otherwise we'll get problems
1695 		 * with tab collections, etc. Windows without title bars
1696 		 * can't be moved anyways.
1697 		 */
1698 		 //if it's too far out of bounds, put it back. you do the bottom bounds first incase the window in question is larger than the game window
1699 		if(win->cur_x + 20 > window_width) {
1700 			move_window(win->window_id, win->pos_id, win->pos_loc, window_width-20, win->pos_y);
1701 		}
1702 		if(win->cur_y + 10 > window_height) {
1703 			move_window(win->window_id, win->pos_id, win->pos_loc, win->pos_x, window_height-10);
1704 		}
1705 		if(win->cur_x + win->len_x < 20) {
1706 			move_window(win->window_id, win->pos_id, win->pos_loc, 20 - win->len_x, win->pos_y);
1707 		}
1708 		if(win->cur_y < win->title_height) {
1709 			move_window(win->window_id, win->pos_id, win->pos_loc, win->pos_x, win->title_height);
1710 		}
1711 	}
1712 	// now normal display processing
1713 	glPushMatrix();
1714 #ifdef OPENGL_TRACE
1715 CHECK_GL_ERRORS();
1716 #endif //OPENGL_TRACE
1717 	glTranslatef((float)win->cur_x, (float)win->cur_y, 0.0f);
1718 	draw_window_title(win);
1719 	draw_window_border(win);
1720 	glColor3f(1.0f, 1.0f, 1.0f);
1721 	if(win->pre_display_handler)
1722 		(*win->pre_display_handler)(win);
1723 
1724 	if(win->flags&ELW_SCROLLABLE) {
1725 		int pos = vscrollbar_get_pos(win->window_id, win->scroll_id);
1726 		int offset = win->scroll_yoffset + ((win->flags&ELW_CLOSE_BOX) ? win->box_size : 0);
1727 
1728 		widget_move(win->window_id, win->scroll_id, win->len_x - widget_get_width(win->window_id, win->scroll_id), pos+offset);
1729 		/* Cut away what we've scrolled past, */
1730 		glEnable(GL_SCISSOR_TEST);
1731 		glScissor(win->cur_x, window_height - win->cur_y - win->len_y, win->len_x + 1, win->len_y + 1);
1732 		glTranslatef(0, -pos, 0);
1733 	}
1734 	if(win->display_handler)
1735 	{
1736 		ret_val=(*win->display_handler)(win);
1737 //the window's own display handler can cause OpenGL errors
1738 #ifdef OPENGL_TRACE
1739 CHECK_GL_ERRORS();
1740 #endif //OPENGL_TRACE
1741 	}
1742 	else
1743 	{
1744 		ret_val=1;
1745 	}
1746 	// assign here in case display_handler changed the widgets - like deletes the widgets
1747 	W = win->widgetlist;
1748 
1749 	// widget drawing
1750 	while(W != NULL)
1751 	{
1752 		if (!(W->Flags&WIDGET_INVISIBLE) && !(W->Flags&WIDGET_DISABLED)) {
1753 			// Draw defaults, then secondaries
1754 			if (W->type != NULL)
1755 				if (W->type->draw != NULL)
1756 					W->type->draw(W);
1757 			if (W->OnDraw != NULL)
1758 			{
1759 				if(W->spec != NULL)
1760 					W->OnDraw(W, W->spec);
1761 				else
1762 					W->OnDraw(W);
1763 			}
1764 		}
1765 		W = W->next;
1766 	}
1767 	if(win->flags&ELW_SCROLLABLE) {
1768 		glDisable(GL_SCISSOR_TEST);
1769 	}
1770 	if(win->post_display_handler)
1771 		(*win->post_display_handler)(win);
1772 	glPopMatrix();
1773 #ifdef OPENGL_TRACE
1774 CHECK_GL_ERRORS();
1775 #endif //OPENGL_TRACE
1776 
1777 	return(ret_val);
1778 }
1779 
show_window(int win_id)1780 void show_window(int win_id)
1781 {
1782 	int iwin;
1783 	int ipos;
1784 	window_info *win;
1785 
1786 	if(win_id < 0 || win_id >= windows_list.num_windows)	return;
1787 	if(windows_list.window[win_id].window_id != win_id)	return;
1788 
1789 	win = &windows_list.window[win_id];
1790 	if (win->show_handler) (*win->show_handler)(win);
1791 
1792 	// pull to the top if not currently displayed
1793 	if(!windows_list.window[win_id].displayed)
1794 		select_window(win_id);
1795 
1796 	ipos = windows_list.window[win_id].pos_id;
1797 	if (ipos >= 0 && !windows_list.window[ipos].displayed)
1798 	{
1799 		// parent is hidden, simply set the reinstated flag
1800 		windows_list.window[win_id].reinstate = 1;
1801 	}
1802 	else
1803 	{
1804 		// display it
1805 		windows_list.window[win_id].displayed = 1;
1806 	}
1807 
1808 	// see if child windows need to be reinstated
1809 	for (iwin = 0; iwin < windows_list.num_windows; iwin++)
1810 		if (windows_list.window[iwin].pos_id == win_id && windows_list.window[iwin].reinstate)
1811 			show_window (iwin);
1812 
1813 	if (win->after_show_handler) (*win->after_show_handler)(win);
1814 }
1815 
hide_window(int win_id)1816 void	hide_window(int win_id)
1817 {
1818 	int iwin;
1819 	window_info * win;
1820 
1821 	if(win_id < 0 || win_id >= windows_list.num_windows)	return;
1822 	if(windows_list.window[win_id].window_id != win_id)	return;
1823 
1824 	win = &windows_list.window[win_id];
1825 
1826 	win->displayed = 0;
1827 	win->reinstate = 0;
1828 
1829 	// hide child windows
1830 	for (iwin = 0; iwin < windows_list.num_windows; iwin++)
1831 		if (windows_list.window[iwin].pos_id == win_id && windows_list.window[iwin].displayed)
1832 		{
1833 			hide_window (iwin);
1834 			windows_list.window[iwin].reinstate = 1;
1835 		}
1836 
1837 	if (win->hide_handler) (*win->hide_handler)(win);
1838 }
1839 
toggle_window(int win_id)1840 void	toggle_window(int win_id)
1841 {
1842 	if(win_id < 0 || win_id >= windows_list.num_windows)	return;
1843 	if(windows_list.window[win_id].window_id != win_id)	return;
1844 
1845 	if(!windows_list.window[win_id].displayed)
1846 		select_window(win_id);
1847 	//windows_list.window[win_id].displayed=!windows_list.window[win_id].displayed;
1848 
1849 	// if we hide a window, we have to hide it's children too, so we cannot
1850 	// simply toggle the displayed flag.
1851 	if (windows_list.window[win_id].displayed || windows_list.window[win_id].reinstate)
1852 		hide_window (win_id);
1853 	else
1854 		show_window (win_id);
1855 }
1856 
resize_scrollbar(window_info * win)1857 static void resize_scrollbar(window_info *win)
1858 {
1859 	int sblen = win->len_y - win->scroll_yoffset;
1860 	int width = (win->flags&ELW_USE_UISCALE) ?win->box_size :widget_get_width(win->window_id, win->scroll_id);
1861 	if (win->flags&ELW_CLOSE_BOX)
1862 		sblen -= win->box_size;
1863 	if (win->flags&ELW_RESIZEABLE)
1864 		sblen -= win->box_size;
1865 	widget_resize(win->window_id, win->scroll_id, width, sblen);
1866 }
1867 
resize_window(int win_id,int new_width,int new_height)1868 void resize_window (int win_id, int new_width, int new_height)
1869 {
1870 	window_info *win;
1871 
1872 	if (win_id < 0 || win_id >= windows_list.num_windows)	return;
1873 	if (windows_list.window[win_id].window_id != win_id)	return;
1874 
1875 	win = &(windows_list.window[win_id]);
1876 
1877 	if (new_width < win->min_len_x) new_width = win->min_len_x;
1878 	if (new_height < win->min_len_y) new_height = win->min_len_y;
1879 
1880 	win->len_x = new_width;
1881 	win->len_y = new_height;
1882 
1883 	if (win->flags&ELW_SCROLLABLE)
1884 		resize_scrollbar(win);
1885 
1886 	if (win->resize_handler != NULL)
1887 	{
1888 		glPushMatrix ();
1889 		glTranslatef ((float)win->cur_x, (float)win->cur_y, 0.0f);
1890 		(*win->resize_handler) (win, new_width, new_height);
1891 		glPopMatrix  ();
1892 	}
1893 #ifdef OPENGL_TRACE
1894 CHECK_GL_ERRORS();
1895 #endif //OPENGL_TRACE
1896 }
1897 
get_show_window(int win_id)1898 int	get_show_window(int win_id)
1899 {
1900 	// unititialized windows always fail as if not shown, not an error
1901 	if(win_id < 0 || win_id >= windows_list.num_windows)	return 0;
1902 	if(windows_list.window[win_id].window_id != win_id)	return 0;
1903 
1904 	return windows_list.window[win_id].displayed;
1905 }
1906 
get_window_showable(int win_id)1907 int	get_window_showable(int win_id)
1908 {
1909 	// unititialized windows always fail as if not shown, not an error
1910 	if(win_id < 0 || win_id >= windows_list.num_windows)	return 0;
1911 	if(windows_list.window[win_id].window_id != win_id)	return 0;
1912 
1913 	return (windows_list.window[win_id].displayed || windows_list.window[win_id].reinstate);
1914 }
1915 
display_window(int win_id)1916 int	display_window(int win_id)
1917 {
1918 	if(win_id < 0 || win_id >= windows_list.num_windows)	return -1;
1919 	if(windows_list.window[win_id].window_id != win_id)	return -1;
1920 	// is it active/displayed?
1921 	if(windows_list.window[win_id].displayed)
1922 		{
1923 			return(draw_window(&windows_list.window[win_id]));
1924 		}
1925 	return 0;
1926 }
1927 
mouse_in_window(int win_id,int x,int y)1928 int	mouse_in_window(int win_id, int x, int y)
1929 {
1930 	// NOTE: these tests do not take depth into account, just location
1931 	// Returns -1 on error, 0 No, 1 yes
1932 	if(win_id < 0 || win_id >= windows_list.num_windows)	return -1;
1933 	if(windows_list.window[win_id].window_id != win_id)	return -1;
1934 
1935 	if(x<windows_list.window[win_id].cur_x || x>=windows_list.window[win_id].cur_x+windows_list.window[win_id].len_x)	return 0;
1936 	if(y<windows_list.window[win_id].cur_y-((windows_list.window[win_id].flags&ELW_TITLE_BAR)?windows_list.window[win_id].title_height:0) || y>=windows_list.window[win_id].cur_y+windows_list.window[win_id].len_y)	return 0;
1937 
1938 	return 1;
1939 }
1940 
click_in_window(int win_id,int x,int y,Uint32 flags)1941 int	click_in_window(int win_id, int x, int y, Uint32 flags)
1942 {
1943 	window_info *win;
1944 	int	mx, my;
1945    	widget_list *W;
1946 	int ret_val = 0;
1947 	int scroll_pos = 0;
1948 
1949 	if(win_id < 0 || win_id >= windows_list.num_windows)	return -1;
1950 	if(windows_list.window[win_id].window_id != win_id)	return -1;
1951 	win= &windows_list.window[win_id];
1952 	W = win->widgetlist;
1953 	if(mouse_in_window(win_id, x, y) > 0)
1954 	{
1955 		static int time=0;
1956 		if(time+60000<cur_time){
1957 			/*Server testing - required*/
1958 			Uint8 str[1];
1959 			str[0]=PING_REQUEST;
1960 			my_tcp_send(my_socket, str, 1);
1961 			time=cur_time;
1962 		}
1963 
1964 		mx = x - win->cur_x;
1965 		my = y - win->cur_y;
1966 		//check the X for close - but hide it
1967 		if(win->flags&ELW_CLOSE_BOX)
1968 		{
1969 			if(my>0 && my<=win->box_size && mx>(win->len_x-win->box_size) && mx<=win->len_x)
1970 			{
1971 				// the X was hit, hide this window
1972 				// but don't close storage if trade is open
1973 				if(win_id != managed_windows.list[MW_STORAGE].id || managed_windows.list[MW_TRADE].id < 0 || !windows_list.window[managed_windows.list[MW_TRADE].id].displayed)
1974 					hide_window(win_id);
1975 				if (win->close_handler != NULL)
1976 					win->close_handler (win);
1977 				do_window_close_sound();
1978 				return 1;
1979 			}
1980 		}
1981 		if(win->flags&ELW_RESIZEABLE && mx > win->len_x-win->box_size && my > win->len_y-win->box_size) {
1982 			/* Clicked on the resize-corner. */
1983 			return 1;
1984 		}
1985 		if ((win->custom_scale != NULL) && (!managed_windows.disable_mouse_or_keys_scaling) &&
1986 			(flags & KMOD_CTRL) && ((flags & ELW_WHEEL_DOWN) || (flags & ELW_WHEEL_UP)))
1987 		{
1988 			step_win_scale_factor((flags & ELW_WHEEL_UP) ? 1 : 0, win->custom_scale);
1989 			return 1;
1990 		}
1991 		if(win->flags&ELW_SCROLLABLE) {
1992 			/* Adjust mouse y coordinates according to the scrollbar position */
1993 			scroll_pos = vscrollbar_get_pos(win->window_id, win->scroll_id);
1994 			my += scroll_pos;
1995 		}
1996 		// check the widgets
1997 		glPushMatrix();
1998 		glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
1999 		while (W != NULL)
2000 		{
2001 			if (!(W->Flags&WIDGET_DISABLED) && !(W->Flags&WIDGET_CLICK_TRANSPARENT) &&  !(W->Flags&WIDGET_INVISIBLE) &&
2002 					mx > W->pos_x && mx <= W->pos_x + W->len_x && my > W->pos_y && my <= W->pos_y + W->len_y)
2003 			{
2004 				if ( widget_handle_click (W, mx - W->pos_x, my - W->pos_y, flags) )
2005 				{
2006 					// widget handled it
2007 					glPopMatrix ();
2008 					return 1;
2009 				}
2010 			}
2011 			W = W->next;
2012 		}
2013 		glPopMatrix();
2014 
2015 		// widgets don't deal with it, try the window handler
2016 		if (win->click_handler != NULL)
2017 		{
2018 			glPushMatrix();
2019 			glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2020 			ret_val = (*win->click_handler)(win, mx, my - scroll_pos, flags);
2021 			glPopMatrix();
2022 		}
2023 
2024 		if(!ret_val && win->flags&ELW_SCROLLABLE && flags &(ELW_WHEEL_UP|ELW_WHEEL_DOWN)) {
2025 			/* Scroll, pass to our scroll widget */
2026 			if(flags&ELW_WHEEL_UP) {
2027 				vscrollbar_scroll_up(win->window_id, win->scroll_id);
2028 			} else if(flags&ELW_WHEEL_DOWN) {
2029 				vscrollbar_scroll_down(win->window_id, win->scroll_id);
2030 			}
2031 		} else if ( !ret_val && (win->flags & ELW_CLICK_TRANSPARENT) && my >= 0 ) {
2032 			return 0;	// click is not handled, and the window is transparent
2033 		}
2034 		return	1;	// click is handled
2035 	}
2036 #ifdef OPENGL_TRACE
2037 CHECK_GL_ERRORS();
2038 #endif //OPENGL_TRACE
2039 
2040 	return 0;
2041 }
2042 
2043 
drag_in_window(int win_id,int x,int y,Uint32 flags,int dx,int dy)2044 int	drag_in_window(int win_id, int x, int y, Uint32 flags, int dx, int dy)
2045 {
2046 	window_info *win;
2047 	int	mx, my;
2048 	int scroll_pos = 0;
2049 	widget_list *W;
2050 
2051 	if(win_id < 0 || win_id >= windows_list.num_windows)
2052 		return -1;
2053 	if(windows_list.window[win_id].window_id != win_id)
2054 		return -1;
2055 
2056 	win= &windows_list.window[win_id];
2057 	W = win->widgetlist;
2058 
2059 	mx = x - win->cur_x;
2060 	my = y - win->cur_y;
2061 
2062 	if(win->flags&ELW_SCROLLABLE) {
2063 		/* Adjust mouse y coordinates according to the scrollbar position */
2064 		scroll_pos = vscrollbar_get_pos(win->window_id, win->scroll_id);
2065 		my += scroll_pos;
2066 	}
2067 	if (cur_drag_widget)
2068 	{
2069 		// Check if cur_drag_widget is indeed one of our widgets
2070 		while (W && W != cur_drag_widget)
2071 			W = W->next;
2072 
2073 		if (W && !(W->Flags & WIDGET_DISABLED))
2074 		{
2075 			int ret_val;
2076 
2077 			glPushMatrix ();
2078 			glTranslatef ((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2079 			ret_val = widget_handle_drag (W, mx - W->pos_x, my - W->pos_y, flags, dx, dy);
2080 			glPopMatrix ();
2081 			if (ret_val)
2082 				// widget handled it
2083 				return 1;
2084 		}
2085 
2086 		// If we got here, cur_drag_widget isn't in this window, or
2087 		// is unable to handle the drag request. Reset it and continue.
2088 		cur_drag_widget = NULL;
2089 	}
2090 
2091 	if(win->drag_in || mouse_in_window(win_id, x, y) > 0)
2092 	{
2093 		// widgets
2094 		glPushMatrix();
2095 		glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2096 		while (W != NULL)
2097 		{
2098 			if (mx > W->pos_x && mx <= W->pos_x + W->len_x && my> W ->pos_y && my <= W->pos_y+W->len_y)
2099 			{
2100 				if (!(W->Flags&WIDGET_DISABLED)) {
2101 					if ( widget_handle_drag (W, mx - W->pos_x, my - W->pos_y, flags, dx, dy) )
2102 					{
2103 						// widget handled it
2104 						glPopMatrix ();
2105 						cur_drag_widget = W;
2106 						return 1;
2107 					}
2108 				}
2109 			}
2110 			W = W->next;
2111 		}
2112 		glPopMatrix();
2113 
2114 		// widgets don't deal with it, try the window handler
2115 		if (win->drag_handler != NULL)
2116 		{
2117 			glPushMatrix();
2118 			glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2119 			glPopMatrix();
2120 		}
2121 		return	1;	// drag has been processed
2122 	}
2123 #ifdef OPENGL_TRACE
2124 CHECK_GL_ERRORS();
2125 #endif //OPENGL_TRACE
2126 
2127 	return 0;
2128 }
2129 
mouseover_window(int win_id,int x,int y)2130 int	mouseover_window (int win_id, int x, int y)
2131 {
2132 	window_info *win;
2133 	int	mx, my;
2134 	int	ret_val=0;
2135 	int scroll_pos = 0;
2136 	widget_list *W;
2137 
2138 	if(win_id < 0 || win_id >= windows_list.num_windows)	return -1;
2139 	if(windows_list.window[win_id].window_id != win_id)	return -1;
2140 	win = &windows_list.window[win_id];
2141 	W = win->widgetlist;
2142 
2143 	if (mouse_in_window (win_id, x, y) > 0)
2144 	{
2145 		mx = x - win->cur_x;
2146 		my = y - win->cur_y;
2147 
2148 		if(win->flags&ELW_SCROLLABLE) {
2149 			/* Adjust mouse y coordinates according to the scrollbar position */
2150 			scroll_pos = vscrollbar_get_pos(win->window_id, win->scroll_id);
2151 			my += scroll_pos;
2152 		} else {
2153 			scroll_pos = 0;
2154 		}
2155 		// widgets
2156 		glPushMatrix();
2157 		glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2158 		while (W != NULL)
2159 		{
2160 			if (mx > W->pos_x && mx <= W->pos_x + W->len_x && my > W->pos_y && my <= W->pos_y+W->len_y)
2161 			{
2162 				if (!(W->Flags&WIDGET_DISABLED)) {
2163 					// don't return on mouseover. hopefully it
2164 					// won't destroy our window...
2165 					widget_handle_mouseover (W, mx, my);
2166 				}
2167 			}
2168 			W = W->next;
2169 		}
2170 		glPopMatrix();
2171 
2172 		// use the handler if present
2173 		if(win->mouseover_handler)
2174 		{
2175 			glPushMatrix();
2176 			glTranslatef ((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2177 			ret_val = (*win->mouseover_handler)(win, mx, my);
2178 			glPopMatrix();
2179 
2180 		}
2181 #ifdef	ELC
2182 		if (!ret_val)
2183 			elwin_mouse = CURSOR_ARROW;
2184 #endif	//ELC
2185 #ifdef OPENGL_TRACE
2186 CHECK_GL_ERRORS();
2187 #endif //OPENGL_TRACE
2188 
2189 		return 1;
2190 	}
2191 
2192 	return 0;
2193 }
2194 
keypress_in_window(int win_id,int x,int y,SDL_Keycode key_code,Uint32 key_unicode,Uint16 key_mod)2195 int	keypress_in_window(int win_id, int x, int y, SDL_Keycode key_code, Uint32 key_unicode, Uint16 key_mod)
2196 {
2197 	window_info *win;
2198 	int	mx, my;
2199 	int scroll_pos = 0;
2200    	widget_list *W;
2201 
2202 	if(win_id < 0 || win_id >= windows_list.num_windows
2203 	|| windows_list.window[win_id].window_id != win_id) {
2204 		return -1;
2205 	}
2206 	win = &windows_list.window[win_id];
2207 	W = win->widgetlist;
2208 
2209 	if (mouse_in_window (win_id, x, y) > 0)
2210 	{
2211 		if ((win->custom_scale != NULL) && (!managed_windows.disable_mouse_or_keys_scaling))
2212 		{
2213 			int actioned = 1;
2214 			if (KEY_DEF_CMP(K_WINSCALEUP, key_code, key_mod))
2215 				step_win_scale_factor(1, win->custom_scale);
2216 			else if (KEY_DEF_CMP(K_WINSCALEDOWN, key_code, key_mod))
2217 				step_win_scale_factor(0, win->custom_scale);
2218 			else if (KEY_DEF_CMP(K_WINSCALEDEF, key_code, key_mod))
2219 				reset_win_scale_factor(1, win->custom_scale);
2220 			else if (KEY_DEF_CMP(K_WINSCALEINIT, key_code, key_mod))
2221 				reset_win_scale_factor(0, win->custom_scale);
2222 			else
2223 				actioned = 0;
2224 			if (actioned)
2225 				return 1;
2226 		}
2227 
2228 		mx = x - win->cur_x;
2229 		my = y - win->cur_y;
2230 
2231 		if(win->flags&ELW_SCROLLABLE) {
2232 			/* Adjust mouse y coordinates according to the scrollbar position */
2233 			scroll_pos = vscrollbar_get_pos(win->window_id, win->scroll_id);
2234 			my += scroll_pos;
2235 		} else {
2236 			scroll_pos = 0;
2237 		}
2238 		// widgets
2239 		glPushMatrix();
2240 		glTranslatef((float)win->cur_x, (float)win->cur_y-scroll_pos, 0.0f);
2241 		while(W != NULL)
2242 		{
2243 			if (mx > W->pos_x && mx <= W->pos_x + W->len_x && my > W->pos_y && my <= W->pos_y+W->len_y)
2244 			{
2245 				if (!(W->Flags&WIDGET_DISABLED)) {
2246 					if ( widget_handle_keypress (W, mx - W->pos_x, my - W->pos_y, key_code, key_unicode, key_mod) )
2247 					{
2248 						// widget handled it
2249 						glPopMatrix ();
2250 #ifdef OPENGL_TRACE
2251 CHECK_GL_ERRORS();
2252 #endif //OPENGL_TRACE
2253 						return 1;
2254 					}
2255 				}
2256 			}
2257 			W = W->next;
2258 		}
2259 		glPopMatrix();
2260 
2261 		// widgets don't deal with it, try the window handler
2262 		if(win->keypress_handler != NULL)
2263 		{
2264 			int ret_val;
2265 
2266 			glPushMatrix();
2267 			glTranslatef((float)win->cur_x, (float)win->cur_y, 0.0f);
2268 			ret_val = (*win->keypress_handler) (win, mx, my, key_code, key_unicode, key_mod);
2269 			glPopMatrix();
2270 #ifdef OPENGL_TRACE
2271 CHECK_GL_ERRORS();
2272 #endif //OPENGL_TRACE
2273 
2274 			return ret_val; // keypresses are fall-through
2275 		}
2276 	}
2277 #ifdef OPENGL_TRACE
2278 CHECK_GL_ERRORS();
2279 #endif //OPENGL_TRACE
2280 
2281 	return 0;
2282 }
2283 
set_window_handler(int win_id,int handler_id,int (* handler)())2284 void	*set_window_handler(int win_id, int handler_id, int (*handler)() )
2285 {
2286 	void	*old_handler;
2287 
2288 	if(win_id < 0 || win_id >= windows_list.num_windows)	return NULL;
2289 	if(windows_list.window[win_id].window_id != win_id)	return NULL;
2290 
2291 	// save the information
2292 	switch(handler_id){
2293 		case	ELW_HANDLER_INIT:
2294 			old_handler= (void *)windows_list.window[win_id].init_handler;
2295 			windows_list.window[win_id].init_handler=handler;
2296 			break;
2297 		case	ELW_HANDLER_DISPLAY:
2298 			old_handler= (void *)windows_list.window[win_id].display_handler;
2299 			windows_list.window[win_id].display_handler=handler;
2300 			break;
2301 		case	ELW_HANDLER_PRE_DISPLAY:
2302 			old_handler= (void *)windows_list.window[win_id].pre_display_handler;
2303 			windows_list.window[win_id].pre_display_handler=handler;
2304 			break;
2305 		case	ELW_HANDLER_POST_DISPLAY:
2306 			old_handler= (void *)windows_list.window[win_id].post_display_handler;
2307 			windows_list.window[win_id].post_display_handler=handler;
2308 			break;
2309 		case	ELW_HANDLER_CLICK:
2310 			old_handler= (void *)windows_list.window[win_id].click_handler;
2311 			windows_list.window[win_id].click_handler=handler;
2312 			break;
2313 		case	ELW_HANDLER_DRAG:
2314 			old_handler= (void *)windows_list.window[win_id].drag_handler;
2315 			windows_list.window[win_id].drag_handler=handler;
2316 			break;
2317 		case	ELW_HANDLER_MOUSEOVER:
2318 			old_handler= (void *)windows_list.window[win_id].mouseover_handler;
2319 			windows_list.window[win_id].mouseover_handler=handler;
2320 			break;
2321 		case	ELW_HANDLER_RESIZE:
2322 			old_handler= (void *)windows_list.window[win_id].resize_handler;
2323 			windows_list.window[win_id].resize_handler=handler;
2324 			break;
2325 		case	ELW_HANDLER_KEYPRESS:
2326 			old_handler= (void *)windows_list.window[win_id].keypress_handler;
2327 			windows_list.window[win_id].keypress_handler=handler;
2328 			break;
2329 		case	ELW_HANDLER_CLOSE:
2330 			old_handler= (void *)windows_list.window[win_id].close_handler;
2331 			windows_list.window[win_id].close_handler=handler;
2332 			break;
2333 		case	ELW_HANDLER_DESTROY:
2334 			old_handler= (void *)windows_list.window[win_id].destroy_handler;
2335 			windows_list.window[win_id].destroy_handler=handler;
2336 			break;
2337 		case	ELW_HANDLER_SHOW:
2338 			old_handler= (void *)windows_list.window[win_id].show_handler;
2339 			windows_list.window[win_id].show_handler=handler;
2340 			break;
2341 		case	ELW_HANDLER_AFTER_SHOW:
2342 			old_handler= (void *)windows_list.window[win_id].after_show_handler;
2343 			windows_list.window[win_id].after_show_handler=handler;
2344 			break;
2345 		case	ELW_HANDLER_HIDE:
2346 			old_handler= (void *)windows_list.window[win_id].hide_handler;
2347 			windows_list.window[win_id].hide_handler=handler;
2348 			break;
2349 		case	ELW_HANDLER_UI_SCALE:
2350 			old_handler= (void *)windows_list.window[win_id].ui_scale_handler;
2351 			windows_list.window[win_id].ui_scale_handler=handler;
2352 			break;
2353 		case	ELW_HANDLER_FONT_CHANGE:
2354 			old_handler= (void *)windows_list.window[win_id].font_change_handler;
2355 			windows_list.window[win_id].font_change_handler=handler;
2356 			break;
2357 		default:
2358 			old_handler=NULL;
2359 	}
2360 
2361 	return old_handler;
2362 }
2363 
set_window_color(int win_id,Uint32 color_id,float r,float g,float b,float a)2364 int	set_window_color(int win_id, Uint32 color_id, float r, float g, float b, float a)
2365 {
2366 	if(win_id < 0 || win_id >= windows_list.num_windows)	return 0;
2367 	if(windows_list.window[win_id].window_id != win_id)	return 0;
2368 
2369 	// save the information
2370 	switch(color_id){
2371 		case	ELW_COLOR_BACK:
2372 			windows_list.window[win_id].back_color[0]= r;
2373 			windows_list.window[win_id].back_color[1]= g;
2374 			windows_list.window[win_id].back_color[2]= b;
2375 			windows_list.window[win_id].back_color[3]= a;
2376 			return	1;
2377 
2378 		case	ELW_COLOR_BORDER:
2379 			windows_list.window[win_id].border_color[0]= r;
2380 			windows_list.window[win_id].border_color[1]= g;
2381 			windows_list.window[win_id].border_color[2]= b;
2382 			windows_list.window[win_id].border_color[3]= a;
2383 			if(windows_list.window[win_id].flags&ELW_SCROLLABLE) {
2384 				/* Update the color of the scroll widget too */
2385 				widget_set_color(win_id, windows_list.window[win_id].scroll_id, r, g, b);
2386 			}
2387 			return	1;
2388 
2389 		case	ELW_COLOR_LINE:
2390 			windows_list.window[win_id].line_color[0]= r;
2391 			windows_list.window[win_id].line_color[1]= g;
2392 			windows_list.window[win_id].line_color[2]= b;
2393 			windows_list.window[win_id].line_color[3]= a;
2394 			return	1;
2395 	}
2396 	return 0;
2397 }
2398 
use_window_color(int win_id,Uint32 color_id)2399 int	use_window_color(int win_id, Uint32 color_id)
2400 {
2401 	if(win_id < 0 || win_id >= windows_list.num_windows)	return 0;
2402 	if(windows_list.window[win_id].window_id != win_id)	return 0;
2403 
2404 	// save the information
2405 	switch(color_id){
2406 		case	ELW_COLOR_BACK:
2407 			glColor4f(windows_list.window[win_id].back_color[0], windows_list.window[win_id].back_color[1], windows_list.window[win_id].back_color[2], windows_list.window[win_id].back_color[3]);
2408 			return	1;
2409 
2410 		case	ELW_COLOR_BORDER:
2411 			glColor3f(windows_list.window[win_id].border_color[0], windows_list.window[win_id].border_color[1], windows_list.window[win_id].border_color[2]);
2412 			return	1;
2413 
2414 		case	ELW_COLOR_LINE:
2415 			glColor3f(windows_list.window[win_id].line_color[0], windows_list.window[win_id].line_color[1], windows_list.window[win_id].line_color[2]);
2416 			return	1;
2417 	}
2418 	return 0;
2419 }
2420 
set_window_min_size(int win_id,int width,int height)2421 int set_window_min_size (int win_id, int width, int height)
2422 {
2423 	if (win_id < 0 || win_id >= windows_list.num_windows)	return 0;
2424 	if (windows_list.window[win_id].window_id != win_id)	return 0;
2425 	if (width < 0 || height < 0)	return 0;
2426 
2427 	windows_list.window[win_id].min_len_x = width;
2428 	windows_list.window[win_id].min_len_y = height;
2429 
2430 	return 1;
2431 }
2432 
set_window_flag(int win_id,Uint32 flag)2433 int set_window_flag (int win_id, Uint32 flag)
2434 {
2435 	if (win_id < 0 || win_id >= windows_list.num_windows)	return 0;
2436 	if (windows_list.window[win_id].window_id != win_id)	return 0;
2437 
2438 	windows_list.window[win_id].flags |= flag;
2439 	return windows_list.window[win_id].flags;
2440 }
2441 
set_window_scroll_len(int win_id,int bar_len)2442 void set_window_scroll_len(int win_id, int bar_len)
2443 {
2444 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE) {
2445 		vscrollbar_set_bar_len (win_id, windows_list.window[win_id].scroll_id, bar_len);
2446 	}
2447 }
2448 
set_window_scroll_yoffset(int win_id,int yoffset)2449 void set_window_scroll_yoffset(int win_id, int yoffset)
2450 {
2451 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE)
2452 	{
2453 		windows_list.window[win_id].scroll_yoffset = yoffset;
2454 		resize_scrollbar(&windows_list.window[win_id]);
2455 	}
2456 }
2457 
set_window_scroll_inc(int win_id,int inc)2458 void set_window_scroll_inc(int win_id, int inc)
2459 {
2460 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE)
2461 		vscrollbar_set_pos_inc(win_id, windows_list.window[win_id].scroll_id, inc);
2462 }
2463 
set_window_scroll_pos(int win_id,int pos)2464 void set_window_scroll_pos(int win_id, int pos)
2465 {
2466 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE)
2467 		vscrollbar_set_pos(win_id, windows_list.window[win_id].scroll_id, pos);
2468 }
2469 
get_window_scroll_pos(int win_id)2470 int get_window_scroll_pos(int win_id)
2471 {
2472 	if(windows_list.window[win_id].flags&ELW_SCROLLABLE)
2473 		return vscrollbar_get_pos(win_id, windows_list.window[win_id].scroll_id);
2474 	else
2475 		return 0;
2476 }
2477 
set_window_font_category(int win_id,font_cat cat)2478 int set_window_font_category(int win_id, font_cat cat)
2479 {
2480 	if (win_id < 0 || win_id >= windows_list.num_windows) return 0;
2481 	if (windows_list.window[win_id].window_id != win_id) return 0;
2482 
2483 	windows_list.window[win_id].font_category = cat;
2484 	change_window_font(&windows_list.window[win_id], cat);
2485 	return 1;
2486 }
2487 
get_window_content_width(int window_id)2488 int get_window_content_width(int window_id)
2489 {
2490 	const window_info *win;
2491 
2492 	if (window_id < 0 || window_id >= windows_list.num_windows) return 0;
2493 	win = &windows_list.window[window_id];
2494 	if (win->window_id != window_id) return 0;
2495 
2496 	if (win->scroll_id < 0)
2497 		return win->len_x;
2498 	else
2499 		return win->len_x - widget_get_width(window_id, win->scroll_id);
2500 }
2501