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