1 |
james |
16 |
/* |
2 |
|
|
* main_riscos.c -- portable gui library, RISC OS |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "gui.h" |
6 |
|
|
|
7 |
|
|
wimp_t gui_wimp_task; /* wimp task handle */ |
8 |
|
|
os_error *gui_error; /* last error block pointer */ |
9 |
|
|
const char *gui_error_message; /* last error message */ |
10 |
|
|
int gui_error_line; /* last error line */ |
11 |
|
|
jmp_buf gui_error_jump; /* longjmp buffer for error handling */ |
12 |
|
|
bool quit = 0; |
13 |
|
|
|
14 |
|
|
char **gui_message; |
15 |
|
|
|
16 |
|
|
struct gui_window_data *gui_window_list; /* array of window details */ |
17 |
|
|
unsigned int gui_window_list_items; /* length of windows list */ |
18 |
|
|
signed int gui_window_origin_x, gui_window_origin_y; |
19 |
|
|
|
20 |
|
|
static void redraw_window_request(wimp_draw *redraw); |
21 |
|
|
static void open_window_request(wimp_open *open); |
22 |
|
|
static void close_window_request(wimp_close *close); |
23 |
|
|
static void mouse_click(wimp_pointer *pointer); |
24 |
|
|
static void key_pressed(wimp_key *key); |
25 |
|
|
static void menu_selection(wimp_selection *selection); |
26 |
|
|
static void user_message(wimp_message *message); |
27 |
|
|
static void help_request(wimp_message *message, help_message_request *request); |
28 |
|
|
|
29 |
|
|
|
30 |
|
|
/****************************************************************************************/ |
31 |
|
|
/* main() */ |
32 |
|
|
/****************************************************************************************/ |
33 |
|
|
|
34 |
|
|
int main(int argc, char *argv[]) |
35 |
|
|
{ |
36 |
|
|
gui_initialise(); |
37 |
|
|
task_initialise(); |
38 |
|
|
|
39 |
|
|
gui_event_loop(); |
40 |
|
|
|
41 |
|
|
task_finalise(); |
42 |
|
|
|
43 |
|
|
return 0; |
44 |
|
|
} |
45 |
|
|
|
46 |
|
|
|
47 |
|
|
/****************************************************************************************/ |
48 |
|
|
/* Initialisation */ |
49 |
|
|
/****************************************************************************************/ |
50 |
|
|
|
51 |
|
|
/* |
52 |
|
|
* gui_initialise -- initialise the program with the os or window manager |
53 |
|
|
* |
54 |
|
|
* => name -- program name to pass to the os if applicable |
55 |
|
|
* |
56 |
|
|
* <= nothing |
57 |
|
|
*/ |
58 |
|
|
|
59 |
|
|
void gui_initialise() |
60 |
|
|
{ |
61 |
|
|
char file_name[30]; |
62 |
|
|
wimp_MESSAGE_LIST(2) messages; |
63 |
|
|
|
64 |
|
|
gui_log("gui_initialise: task_name = '%s'\n", task_name); |
65 |
|
|
|
66 |
|
|
if (setjmp(gui_error_jump)) |
67 |
|
|
{ |
68 |
|
|
gui_log("gui_initialise: *** error %i: %s ***\n", gui_error_line, gui_error_message); |
69 |
|
|
|
70 |
|
|
printf("%s (%i)\n", gui_error_message, gui_error_line); |
71 |
|
|
fflush(stdout); |
72 |
|
|
exit(1); |
73 |
|
|
} |
74 |
|
|
|
75 |
|
|
messages.messages[0] = message_HELP_REQUEST; |
76 |
|
|
messages.messages[1] = message_QUIT; |
77 |
|
|
|
78 |
|
|
gui_error = xwimp_initialise(wimp_VERSION_RO3, task_name, |
79 |
|
|
(wimp_message_list const *) &messages, |
80 |
|
|
NULL, &gui_wimp_task); |
81 |
|
|
gui_check_error(); |
82 |
|
|
|
83 |
|
|
gui_window_list = NULL; |
84 |
|
|
gui_window_list_items = 0; |
85 |
|
|
|
86 |
|
|
sprintf(file_name, "<%s$Messages>", task_name); |
87 |
|
|
gui_message = gui_messages_read(file_name); |
88 |
|
|
|
89 |
|
|
gui_log("gui_initialise: gui_wimp_task = 0x%x\n", (unsigned int) gui_wimp_task); |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
|
93 |
|
|
/****************************************************************************************/ |
94 |
|
|
/* Event handling */ |
95 |
|
|
/****************************************************************************************/ |
96 |
|
|
|
97 |
|
|
/* |
98 |
|
|
* gui_event_loop -- receive and handle os or window manager events |
99 |
|
|
* |
100 |
|
|
* => nothing |
101 |
|
|
* |
102 |
|
|
* <= does not return directly, except on exit |
103 |
|
|
*/ |
104 |
|
|
|
105 |
|
|
#define MASK (wimp_MASK_NULL | wimp_MASK_LEAVING | wimp_MASK_ENTERING | wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_POLLWORD) |
106 |
|
|
|
107 |
|
|
static gui_window_id menu_window_id; |
108 |
|
|
|
109 |
|
|
void gui_event_loop(void) |
110 |
|
|
{ |
111 |
|
|
wimp_block block; |
112 |
|
|
wimp_event_no event; |
113 |
|
|
os_error err; |
114 |
|
|
|
115 |
|
|
if (setjmp(gui_error_jump)) |
116 |
|
|
{ |
117 |
|
|
gui_log("gui_event_loop: *** error %i: %s ***\n", gui_error_line, gui_error_message); |
118 |
|
|
|
119 |
|
|
err.errnum = 1; |
120 |
|
|
sprintf(err.errmess, "%s (%i)\n", gui_error_message, gui_error_line); |
121 |
|
|
xwimp_report_error(&err, wimp_ERROR_BOX_OK_ICON, task_name, NULL); |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
while (!quit) |
125 |
|
|
{ |
126 |
|
|
gui_error = xwimp_poll(MASK, &block, NULL, &event); |
127 |
|
|
gui_check_error(); |
128 |
|
|
|
129 |
|
|
gui_log("gui_event_loop: event = %i\n", event); |
130 |
|
|
switch (event) |
131 |
|
|
{ |
132 |
|
|
case wimp_REDRAW_WINDOW_REQUEST: redraw_window_request(&block.redraw); break; |
133 |
|
|
case wimp_OPEN_WINDOW_REQUEST: open_window_request(&block.open); break; |
134 |
|
|
case wimp_CLOSE_WINDOW_REQUEST: close_window_request(&block.close); break; |
135 |
|
|
case wimp_MOUSE_CLICK: mouse_click(&block.pointer); break; |
136 |
|
|
case wimp_KEY_PRESSED: key_pressed(&block.key); break; |
137 |
|
|
case wimp_MENU_SELECTION: menu_selection(&block.selection); break; |
138 |
|
|
case wimp_USER_MESSAGE: |
139 |
|
|
case wimp_USER_MESSAGE_RECORDED: user_message(&block.message); break; |
140 |
|
|
} |
141 |
|
|
} |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
|
145 |
|
|
/* |
146 |
|
|
* redraw window request |
147 |
|
|
*/ |
148 |
|
|
|
149 |
|
|
void redraw_window_request(wimp_draw *redraw) |
150 |
|
|
{ |
151 |
|
|
bool more; |
152 |
|
|
unsigned int invalid[4]; /* why was this signed ?? */ |
153 |
|
|
gui_window_id window_id = gui_handle_to_window_id(redraw->w); |
154 |
|
|
|
155 |
|
|
assert(window_id == gui_WINDOW_UNKNOWN || |
156 |
|
|
(window_id < gui_window_list_items && gui_window_list[window_id].used)); |
157 |
|
|
|
158 |
|
|
gui_error = xwimp_redraw_window(redraw, &more); |
159 |
|
|
gui_check_error(); |
160 |
|
|
|
161 |
|
|
gui_window_origin_x = redraw->box.x0 - redraw->xscroll; |
162 |
|
|
gui_window_origin_y = redraw->box.y1 - redraw->yscroll; |
163 |
|
|
|
164 |
|
|
gui_log("gui_event_loop: redraw origin %i %i\n", gui_window_origin_x, gui_window_origin_y); |
165 |
|
|
|
166 |
|
|
while (more) |
167 |
|
|
{ |
168 |
|
|
if (window_id != gui_WINDOW_UNKNOWN && gui_window_list[window_id].redraw_fn) |
169 |
|
|
{ |
170 |
|
|
invalid[0] = redraw->clip.x0 - gui_window_origin_x; |
171 |
|
|
invalid[1] = gui_window_origin_y - redraw->clip.y1; |
172 |
|
|
invalid[2] = redraw->clip.x1 - gui_window_origin_x; |
173 |
|
|
invalid[3] = gui_window_origin_y - redraw->clip.y0; |
174 |
|
|
|
175 |
|
|
gui_log("gui_event_loop: redraw invalid %i %i %i %i\n", |
176 |
|
|
invalid[0], invalid[1], invalid[2], invalid[3]); |
177 |
|
|
|
178 |
|
|
gui_window_list[window_id].redraw_fn(window_id, invalid); |
179 |
|
|
} |
180 |
|
|
gui_error = xwimp_get_rectangle(redraw, &more); |
181 |
|
|
gui_check_error(); |
182 |
|
|
} |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
|
186 |
|
|
/* |
187 |
|
|
* open window request |
188 |
|
|
*/ |
189 |
|
|
|
190 |
|
|
void open_window_request(wimp_open *open) |
191 |
|
|
{ |
192 |
|
|
gui_window_id window_id = gui_handle_to_window_id(open->w); |
193 |
|
|
|
194 |
|
|
gui_error = xwimp_open_window(open); |
195 |
|
|
gui_check_error(); |
196 |
|
|
|
197 |
|
|
if (window_id != gui_WINDOW_UNKNOWN) |
198 |
|
|
{ |
199 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
200 |
|
|
if ((unsigned int) (open->visible.x1 - open->visible.x0) != gui_window_list[window_id].width || |
201 |
|
|
(unsigned int) (open->visible.y1 - open->visible.y0) != gui_window_list[window_id].height) |
202 |
|
|
{ |
203 |
|
|
gui_window_list[window_id].width = open->visible.x1 - open->visible.x0; |
204 |
|
|
gui_window_list[window_id].height = open->visible.y1 - open->visible.y0; |
205 |
|
|
gui_log("open_window_request: resized to %i %i\n", |
206 |
|
|
gui_window_list[window_id].width, gui_window_list[window_id].height); |
207 |
|
|
if (gui_window_list[window_id].resize_fn) |
208 |
|
|
gui_window_list[window_id].resize_fn(window_id, |
209 |
|
|
gui_window_list[window_id].width, gui_window_list[window_id].height); |
210 |
|
|
} |
211 |
|
|
} |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
|
215 |
|
|
/* |
216 |
|
|
* close window request |
217 |
|
|
*/ |
218 |
|
|
|
219 |
|
|
void close_window_request(wimp_close *close) |
220 |
|
|
{ |
221 |
|
|
gui_window_id window_id = gui_handle_to_window_id(close->w); |
222 |
|
|
|
223 |
|
|
gui_log("gui_event_loop: window_id = 0x%x\n", window_id); |
224 |
|
|
|
225 |
|
|
if (window_id != gui_WINDOW_UNKNOWN) |
226 |
|
|
{ |
227 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
228 |
|
|
gui_window_list[window_id].close_fn(window_id); |
229 |
|
|
} |
230 |
|
|
} |
231 |
|
|
|
232 |
|
|
|
233 |
|
|
/* |
234 |
|
|
* mouse click |
235 |
|
|
*/ |
236 |
|
|
|
237 |
|
|
void mouse_click(wimp_pointer *pointer) |
238 |
|
|
{ |
239 |
|
|
gui_window_id window_id = gui_handle_to_window_id(pointer->w); |
240 |
|
|
|
241 |
|
|
gui_log("gui_event_loop: window_id = 0x%x\n", window_id); |
242 |
|
|
|
243 |
|
|
if (window_id != gui_WINDOW_UNKNOWN) |
244 |
|
|
{ |
245 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
246 |
|
|
if (gui_window_list[window_id].menu && (pointer->buttons & wimp_CLICK_MENU)) |
247 |
|
|
{ |
248 |
|
|
gui_error = xwimp_create_menu(gui_window_list[window_id].menu, |
249 |
|
|
pointer->pos.x - 64, pointer->pos.y); |
250 |
|
|
gui_check_error(); |
251 |
|
|
menu_window_id = window_id; |
252 |
|
|
} |
253 |
|
|
else if (gui_window_list[window_id].click_fn) |
254 |
|
|
{ |
255 |
|
|
unsigned int x, y, z; |
256 |
|
|
wimp_window_state state; |
257 |
|
|
|
258 |
|
|
state.w = pointer->w; |
259 |
|
|
gui_error = xwimp_get_window_state(&state); |
260 |
|
|
gui_check_error(); |
261 |
|
|
|
262 |
|
|
x = pointer->pos.x - (state.visible.x0 - state.xscroll); |
263 |
|
|
y = (state.visible.y1 - state.yscroll) - pointer->pos.y; |
264 |
|
|
z = (pointer->buttons & wimp_CLICK_SELECT ? gui_CLICK : |
265 |
|
|
(pointer->buttons & wimp_CLICK_ADJUST ? gui_CLICK_RIGHT : |
266 |
|
|
(pointer->buttons & wimp_DRAG_SELECT ? gui_DRAG : |
267 |
|
|
(pointer->buttons & wimp_DRAG_ADJUST ? gui_DRAG_RIGHT : 0)))); |
268 |
|
|
gui_window_list[window_id].click_fn(window_id, x, y, z); |
269 |
|
|
} |
270 |
|
|
} |
271 |
|
|
} |
272 |
|
|
|
273 |
|
|
|
274 |
|
|
/* |
275 |
|
|
* key pressed |
276 |
|
|
*/ |
277 |
|
|
|
278 |
|
|
void key_pressed(wimp_key *key) |
279 |
|
|
{ |
280 |
|
|
gui_window_id window_id = gui_handle_to_window_id(key->w); |
281 |
|
|
|
282 |
|
|
gui_log("gui_event_loop: window_id = 0x%x\n", window_id); |
283 |
|
|
|
284 |
|
|
if (window_id != gui_WINDOW_UNKNOWN) |
285 |
|
|
{ |
286 |
|
|
assert(window_id < gui_window_list_items && gui_window_list[window_id].used); |
287 |
|
|
|
288 |
|
|
if ((key->c & (1<<31)) || (key->c < 256)) |
289 |
|
|
{ |
290 |
|
|
if (gui_window_list[window_id].input_fn) |
291 |
|
|
gui_window_list[window_id].input_fn(window_id, (wchar_t) (key->c & 0xffff)); |
292 |
|
|
} |
293 |
|
|
else |
294 |
|
|
{ |
295 |
|
|
if (gui_window_list[window_id].key_fn) |
296 |
|
|
gui_window_list[window_id].key_fn(window_id, (unsigned int) key->c); |
297 |
|
|
} |
298 |
|
|
} |
299 |
|
|
} |
300 |
|
|
|
301 |
|
|
|
302 |
|
|
/* |
303 |
|
|
* menu selection |
304 |
|
|
*/ |
305 |
|
|
|
306 |
|
|
void menu_selection(wimp_selection *selection) |
307 |
|
|
{ |
308 |
|
|
wimp_pointer pointer; |
309 |
|
|
|
310 |
|
|
gui_error = xwimp_get_pointer_info(&pointer); |
311 |
|
|
gui_check_error(); |
312 |
|
|
|
313 |
|
|
gui_window_list[menu_window_id].menu_fn(menu_window_id, (unsigned int *) selection->items); |
314 |
|
|
|
315 |
|
|
if (pointer.buttons == wimp_CLICK_ADJUST) |
316 |
|
|
{ |
317 |
|
|
gui_error = xwimp_create_menu(gui_window_list[menu_window_id].menu, 0, 0); |
318 |
|
|
gui_check_error(); |
319 |
|
|
} |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
|
323 |
|
|
/* |
324 |
|
|
* user message, user message recorded |
325 |
|
|
*/ |
326 |
|
|
|
327 |
|
|
void user_message(wimp_message *message) |
328 |
|
|
{ |
329 |
|
|
gui_log("gui_event_loop: block.message.action = 0x%x\n", message->action); |
330 |
|
|
|
331 |
|
|
switch (message->action) |
332 |
|
|
{ |
333 |
|
|
case message_QUIT: |
334 |
|
|
quit = 1; |
335 |
|
|
break; |
336 |
|
|
case message_HELP_REQUEST: |
337 |
|
|
help_request(message, (help_message_request *) &message->data); |
338 |
|
|
break; |
339 |
|
|
} |
340 |
|
|
} |
341 |
|
|
|
342 |
|
|
/* |
343 |
|
|
* interactive help request |
344 |
|
|
*/ |
345 |
|
|
|
346 |
|
|
void help_request(wimp_message *message, help_message_request *request) |
347 |
|
|
{ |
348 |
|
|
const char *help; |
349 |
|
|
wimp_message reply; |
350 |
|
|
gui_window_id window_id = gui_handle_to_window_id(request->w); |
351 |
|
|
|
352 |
|
|
if (window_id != gui_WINDOW_UNKNOWN) |
353 |
|
|
{ |
354 |
|
|
if (gui_window_list[window_id].used == DIALOG && request->i >= 0) |
355 |
|
|
help = gui_window_list[window_id].icon[request->i].help; |
356 |
|
|
else |
357 |
|
|
help = gui_window_list[window_id].help; |
358 |
|
|
|
359 |
|
|
gui_log(help); |
360 |
|
|
reply.size = (20 + strlen(help) + 3) & ~3u; |
361 |
|
|
reply.your_ref = message->my_ref; |
362 |
|
|
reply.action = message_HELP_REPLY; |
363 |
|
|
strcpy((char *) &reply.data.reserved, help); |
364 |
|
|
gui_error = xwimp_send_message(wimp_USER_MESSAGE, &reply, message->sender); |
365 |
|
|
gui_check_error(); |
366 |
|
|
} |
367 |
|
|
} |