1 |
james |
16 |
/* |
2 |
|
|
* window_riscos.c -- window handling, RISC OS |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "gui.h" |
6 |
|
|
|
7 |
|
|
|
8 |
|
|
/* |
9 |
|
|
* gui_create_window -- create and display a window |
10 |
|
|
* |
11 |
|
|
* => flags -- window details |
12 |
|
|
* title -- window title |
13 |
|
|
* width -- width of window |
14 |
|
|
* height -- height of window |
15 |
|
|
* close_fn -- function called when an attempt is made to close the window, |
16 |
|
|
* NULL for default of closing and destroying window |
17 |
|
|
* redraw_fn -- function called when the window needs redrawing |
18 |
|
|
* click_fn -- function called when the mouse is clicked in the window or equivalent, |
19 |
|
|
* NULL for default of no action |
20 |
|
|
* |
21 |
|
|
* <= window id |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
gui_window_id gui_create_window(const unsigned int flags, |
25 |
|
|
char *title, |
26 |
|
|
const unsigned int width, const unsigned int height, |
27 |
|
|
void (*close_fn)(gui_window_id window_id), |
28 |
|
|
void (*redraw_fn)(gui_window_id window_id, unsigned int invalid[]), |
29 |
|
|
void (*click_fn)(gui_window_id window_id, unsigned int x, unsigned int y, |
30 |
|
|
unsigned int z), |
31 |
|
|
void (*resize_fn)(gui_window_id window_id, unsigned int width, unsigned int height), |
32 |
|
|
bool (*key_fn)(gui_window_id window_id, unsigned int key), |
33 |
|
|
void (*input_fn)(gui_window_id window_id, wchar_t key), |
34 |
|
|
void (*menu_fn)(gui_window_id window_id, unsigned int items[]), |
35 |
|
|
wimp_menu *menu, |
36 |
|
|
const char *bbar, |
37 |
|
|
const char *help) |
38 |
|
|
{ |
39 |
|
|
wimp_WINDOW(1) window; |
40 |
|
|
wimp_w handle; |
41 |
|
|
wimp_window_state open; |
42 |
|
|
gui_window_id id; |
43 |
|
|
|
44 |
|
|
#ifdef DEBUG |
45 |
|
|
printf("gui_create_window: title = '%s'\n", title); |
46 |
|
|
fflush(stdout); |
47 |
|
|
#endif |
48 |
|
|
|
49 |
|
|
assert(redraw_fn != NULL); |
50 |
|
|
|
51 |
|
|
id = gui_get_free_window_id(); |
52 |
|
|
|
53 |
|
|
window.visible.x0 = 100; |
54 |
|
|
window.visible.y0 = 100; |
55 |
|
|
window.visible.x1 = window.visible.x0 + width; |
56 |
|
|
window.visible.y1 = window.visible.y0 + height; |
57 |
|
|
window.xscroll = window.yscroll = 0; |
58 |
|
|
window.next = wimp_TOP; |
59 |
|
|
window.flags = wimp_WINDOW_MOVEABLE | wimp_WINDOW_NEW_FORMAT | |
60 |
|
|
wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | |
61 |
|
|
(flags & gui_H_SCROLL_BAR ? wimp_WINDOW_HSCROLL | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_SIZE_ICON : 0) | |
62 |
|
|
(flags & gui_V_SCROLL_BAR ? wimp_WINDOW_VSCROLL | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_SIZE_ICON : 0); |
63 |
|
|
window.title_fg = wimp_COLOUR_BLACK; |
64 |
|
|
window.title_bg = wimp_COLOUR_LIGHT_GREY; |
65 |
|
|
window.work_fg = wimp_COLOUR_BLACK; |
66 |
|
|
// window.work_bg = wimp_COLOUR_WHITE; |
67 |
|
|
window.work_bg = wimp_COLOUR_TRANSPARENT; |
68 |
|
|
window.highlight_bg = wimp_COLOUR_CREAM; |
69 |
|
|
window.extent.x0 = window.extent.y1 = 0; |
70 |
|
|
window.extent.y0 = -height; |
71 |
|
|
window.extent.x1 = width; |
72 |
|
|
window.title_flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED; |
73 |
|
|
window.work_flags = wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT; |
74 |
|
|
window.sprite_area = (osspriteop_area *) 1; |
75 |
|
|
window.xmin = window.ymin = 1; |
76 |
|
|
window.title_data.indirected_text.text = title; |
77 |
|
|
window.title_data.indirected_text.validation = 0; |
78 |
|
|
window.icon_count = 0; |
79 |
|
|
|
80 |
|
|
gui_error = xwimp_create_window((wimp_window const *) &window, &handle); |
81 |
|
|
gui_check_error(); |
82 |
|
|
|
83 |
|
|
open.w = handle; |
84 |
|
|
gui_error = xwimp_get_window_state(&open); |
85 |
|
|
gui_check_error(); |
86 |
|
|
|
87 |
|
|
gui_error = xwimp_open_window((wimp_open *) &open); |
88 |
|
|
gui_check_error(); |
89 |
|
|
|
90 |
|
|
gui_window_list[id].used = 1; |
91 |
|
|
gui_window_list[id].handle = handle; |
92 |
|
|
gui_window_list[id].close_fn = (close_fn == NULL ? gui_remove_window : close_fn); |
93 |
|
|
gui_window_list[id].redraw_fn = redraw_fn; |
94 |
|
|
gui_window_list[id].click_fn = click_fn; |
95 |
|
|
gui_window_list[id].resize_fn = resize_fn; |
96 |
|
|
gui_window_list[id].key_fn = key_fn; |
97 |
|
|
gui_window_list[id].input_fn = input_fn; |
98 |
|
|
gui_window_list[id].menu_fn = menu_fn; |
99 |
|
|
gui_window_list[id].width = width; |
100 |
|
|
gui_window_list[id].height = height; |
101 |
|
|
gui_window_list[id].menu = menu; |
102 |
|
|
gui_window_list[id].help = help; |
103 |
|
|
|
104 |
|
|
#ifdef DEBUG |
105 |
|
|
printf("gui_create_window: id = 0x%x, handle = 0x%x\n", id, (unsigned int) handle); |
106 |
|
|
fflush(stdout); |
107 |
|
|
#endif |
108 |
|
|
|
109 |
|
|
return id; |
110 |
|
|
} |
111 |
|
|
|
112 |
|
|
|
113 |
|
|
/* |
114 |
|
|
* gui_get_free_window_id -- allocate space and return a window id |
115 |
|
|
* |
116 |
|
|
* => nothing |
117 |
|
|
* |
118 |
|
|
* <= window id (gui_window_list index) |
119 |
|
|
*/ |
120 |
|
|
|
121 |
|
|
gui_window_id gui_get_free_window_id() |
122 |
|
|
{ |
123 |
|
|
static struct gui_window_data *new_gui_window_list; |
124 |
|
|
unsigned int i; |
125 |
|
|
|
126 |
|
|
#ifdef DEBUG |
127 |
|
|
printf("gui_get_free_window_id: gui_window_list_items = %i\n", gui_window_list_items); |
128 |
|
|
fflush(stdout); |
129 |
|
|
#endif |
130 |
|
|
|
131 |
|
|
for (i = 0; i < gui_window_list_items; i++) |
132 |
|
|
if (!gui_window_list[i].used) |
133 |
|
|
return i; |
134 |
|
|
|
135 |
|
|
new_gui_window_list = realloc(gui_window_list, |
136 |
|
|
sizeof(struct gui_window_data) * (gui_window_list_items + WINDOW_LIST_CHUNK)); |
137 |
|
|
if (!new_gui_window_list) gui_raise_error("memory"); |
138 |
|
|
|
139 |
|
|
gui_window_list = new_gui_window_list; |
140 |
|
|
for (i = gui_window_list_items; i < gui_window_list_items + WINDOW_LIST_CHUNK; i++) |
141 |
|
|
gui_window_list[i].used = 0; |
142 |
|
|
|
143 |
|
|
i = gui_window_list_items; |
144 |
|
|
gui_window_list_items += WINDOW_LIST_CHUNK; |
145 |
|
|
|
146 |
|
|
#ifdef DEBUG |
147 |
|
|
printf("gui_get_free_window_id: increased gui_window_list_items = %i\n", gui_window_list_items); |
148 |
|
|
fflush(stdout); |
149 |
|
|
#endif |
150 |
|
|
|
151 |
|
|
assert(i < gui_window_list_items); |
152 |
|
|
return i; |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
|
156 |
|
|
/* |
157 |
|
|
* gui_handle_to_window_id -- convert a window handle to a window id |
158 |
|
|
* |
159 |
|
|
* => handle -- wimp window handle |
160 |
|
|
* |
161 |
|
|
* <= window id |
162 |
|
|
*/ |
163 |
|
|
|
164 |
|
|
gui_window_id gui_handle_to_window_id(wimp_w handle) |
165 |
|
|
{ |
166 |
|
|
unsigned int i; |
167 |
|
|
|
168 |
|
|
for (i = 0; i < gui_window_list_items; i++) |
169 |
|
|
{ |
170 |
|
|
if ((gui_window_list[i].used) && (gui_window_list[i].handle == handle)) |
171 |
|
|
{ |
172 |
|
|
|
173 |
|
|
#ifdef DEBUG |
174 |
|
|
printf("gui_handle_to_window_id: handle = 0x%x, id = 0x%x\n", (unsigned int) handle, i); |
175 |
|
|
fflush(stdout); |
176 |
|
|
#endif |
177 |
|
|
return i; |
178 |
|
|
} |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
return gui_WINDOW_UNKNOWN; |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
|
185 |
|
|
/* |
186 |
|
|
* gui_remove_window -- close and destroy a window |
187 |
|
|
* |
188 |
|
|
* => window_id -- window id from gui_create_window |
189 |
|
|
* |
190 |
|
|
* <= nothing |
191 |
|
|
*/ |
192 |
|
|
|
193 |
|
|
void gui_remove_window(const gui_window_id window_id) |
194 |
|
|
{ |
195 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
196 |
|
|
|
197 |
|
|
#ifdef DEBUG |
198 |
|
|
printf("gui_remove_window: window_id = 0x%x\n", window_id); |
199 |
|
|
fflush(stdout); |
200 |
|
|
#endif |
201 |
|
|
|
202 |
|
|
gui_error = xwimp_delete_window(gui_window_list[window_id].handle); |
203 |
|
|
gui_check_error(); |
204 |
|
|
gui_window_list[window_id].used = 0; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
|
208 |
|
|
/* |
209 |
|
|
* gui_refresh_window -- update a window's contents |
210 |
|
|
* |
211 |
|
|
* => window_id -- window id from gui_create_window |
212 |
|
|
* |
213 |
|
|
* <= nothing |
214 |
|
|
*/ |
215 |
|
|
|
216 |
|
|
void gui_refresh_window(const gui_window_id window_id) |
217 |
|
|
{ |
218 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
219 |
|
|
|
220 |
|
|
#ifdef DEBUG |
221 |
|
|
printf("gui_refresh_window: window_id = 0x%x\n", window_id); |
222 |
|
|
fflush(stdout); |
223 |
|
|
#endif |
224 |
|
|
|
225 |
|
|
gui_refresh_box(window_id, 0, 0, 0x10000000, 0x10000000); |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
|
229 |
|
|
/* |
230 |
|
|
* gui_refresh_box -- update part of a window's contents |
231 |
|
|
* |
232 |
|
|
* => window_id -- window id from gui_create_window |
233 |
|
|
* x0, y0, x1, y1 -- area to update |
234 |
|
|
* |
235 |
|
|
* <= nothing |
236 |
|
|
*/ |
237 |
|
|
|
238 |
|
|
void gui_refresh_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, |
239 |
|
|
unsigned int x1, unsigned int y1) |
240 |
|
|
{ |
241 |
|
|
unsigned int invalid[4]; |
242 |
|
|
bool more; |
243 |
|
|
wimp_window_state state; |
244 |
|
|
wimp_draw update; |
245 |
|
|
|
246 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
247 |
|
|
|
248 |
|
|
#ifdef DEBUG |
249 |
|
|
printf("gui_refresh_box: window_id = 0x%x, box %i %i %i %i\n", window_id, x0, y0, x1, y1); |
250 |
|
|
fflush(stdout); |
251 |
|
|
#endif |
252 |
|
|
|
253 |
|
|
state.w = gui_window_list[window_id].handle; |
254 |
|
|
|
255 |
|
|
gui_error = xwimp_get_window_state(&state); |
256 |
|
|
gui_check_error(); |
257 |
|
|
|
258 |
|
|
gui_window_origin_x = state.visible.x0 - state.xscroll; |
259 |
|
|
gui_window_origin_y = state.visible.y1 - state.yscroll; |
260 |
|
|
|
261 |
|
|
#ifdef DEBUG |
262 |
|
|
printf("gui_refresh_box: redraw origin %i %i\n", gui_window_origin_x, gui_window_origin_y); |
263 |
|
|
fflush(stdout); |
264 |
|
|
#endif |
265 |
|
|
|
266 |
|
|
update.w = state.w; |
267 |
|
|
update.box.x0 = x0; |
268 |
|
|
update.box.y0 = -y1; |
269 |
|
|
update.box.x1 = x1; |
270 |
|
|
update.box.y1 = -y0; |
271 |
|
|
gui_error = xwimp_update_window(&update, &more); |
272 |
|
|
gui_check_error(); |
273 |
|
|
|
274 |
|
|
while (more) |
275 |
|
|
{ |
276 |
|
|
invalid[0] = update.clip.x0 - gui_window_origin_x; |
277 |
|
|
invalid[1] = gui_window_origin_y - update.clip.y1; |
278 |
|
|
invalid[2] = update.clip.x1 - gui_window_origin_x; |
279 |
|
|
invalid[3] = gui_window_origin_y - update.clip.y0; |
280 |
|
|
|
281 |
|
|
#ifdef DEBUG |
282 |
|
|
printf("gui_refresh_box: redraw invalid %i %i %i %i\n", |
283 |
|
|
invalid[0], invalid[1], invalid[2], invalid[3]); |
284 |
|
|
fflush(stdout); |
285 |
|
|
#endif |
286 |
|
|
|
287 |
|
|
gui_window_list[window_id].redraw_fn(window_id, invalid); |
288 |
|
|
|
289 |
|
|
gui_error = xwimp_get_rectangle(&update, &more); |
290 |
|
|
gui_check_error(); |
291 |
|
|
} |
292 |
|
|
} |
293 |
|
|
|
294 |
|
|
|
295 |
|
|
/* |
296 |
|
|
* gui_window_extent -- set window size |
297 |
|
|
* |
298 |
|
|
* => window_id -- window id from gui_create_window |
299 |
|
|
* width, height -- new dimensions of window |
300 |
|
|
* |
301 |
|
|
* <= nothing |
302 |
|
|
*/ |
303 |
|
|
|
304 |
|
|
void gui_window_extent(const gui_window_id window_id, unsigned int width, unsigned int height) |
305 |
|
|
{ |
306 |
|
|
os_box box = {0, 0, 0, 0}; |
307 |
|
|
box.y0 = (height == 0 ? 0x80000000 : -height); |
308 |
|
|
box.x1 = (width == 0 ? 0x7fffffff : width); |
309 |
|
|
|
310 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
311 |
|
|
|
312 |
|
|
#ifdef DEBUG |
313 |
|
|
printf("gui_window_extent: window_id = 0x%x, extent = %i x %i\n", window_id, width, height); |
314 |
|
|
fflush(stdout); |
315 |
|
|
#endif |
316 |
|
|
|
317 |
|
|
gui_error = xwimp_set_extent(gui_window_list[window_id].handle, &box); |
318 |
|
|
gui_check_error(); |
319 |
|
|
|
320 |
|
|
gui_window_list[window_id].width = width; |
321 |
|
|
gui_window_list[window_id].height = height; |
322 |
|
|
} |
323 |
|
|
|
324 |
|
|
|
325 |
|
|
/* |
326 |
|
|
* gui_fill -- fill a rectangular area during window redraw |
327 |
|
|
* |
328 |
|
|
* => colour -- 0xbbggrr format colour |
329 |
|
|
* x0, y0, x1, y1 -- coordinates of rectangle |
330 |
|
|
*/ |
331 |
|
|
|
332 |
|
|
void gui_fill(unsigned int colour, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) |
333 |
|
|
{ |
334 |
|
|
gui_error = xcolourtrans_set_gcol((os_colour) colour << 8, 0, os_ACTION_OVERWRITE, NULL, NULL); |
335 |
|
|
gui_check_error(); |
336 |
|
|
|
337 |
|
|
gui_error = xos_plot(os_MOVE_TO, (signed int) (gui_window_origin_x + x0), (signed int) (gui_window_origin_y - y0)); |
338 |
|
|
gui_check_error(); |
339 |
|
|
|
340 |
|
|
gui_error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO, |
341 |
|
|
(signed int) (gui_window_origin_x + x1), (signed int) (gui_window_origin_y - y1)); |
342 |
|
|
gui_check_error(); |
343 |
|
|
} |
344 |
|
|
|
345 |
|
|
|
346 |
|
|
/* |
347 |
|
|
* gui_move_box -- copy a rectangular area within a window |
348 |
|
|
* |
349 |
|
|
* => window_id -- window id from gui_create_window |
350 |
|
|
* x0, y0, x1, y1 -- source area |
351 |
|
|
* x2, y2 -- destination |
352 |
|
|
*/ |
353 |
|
|
|
354 |
|
|
void gui_move_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, |
355 |
|
|
unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) |
356 |
|
|
{ |
357 |
|
|
|
358 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
359 |
|
|
|
360 |
|
|
#ifdef DEBUG |
361 |
|
|
printf("gui_move_box: window_id = 0x%x, box = %i %i %i %i, dest = %i %i\n", |
362 |
|
|
window_id, x0, y0, x1, y1, x2, y2); |
363 |
|
|
fflush(stdout); |
364 |
|
|
#endif |
365 |
|
|
|
366 |
|
|
gui_error = xwimp_block_copy(gui_window_list[window_id].handle, (signed int) x0, (signed int) -y1, |
367 |
|
|
(signed int) x1, (signed int) -y0, (signed int) x2, (signed int) -(y1 + (y2 - y0))); |
368 |
|
|
gui_check_error(); |
369 |
|
|
} |