/* * main_riscos.c -- portable gui library, RISC OS */ #include "gui.h" wimp_t gui_wimp_task; /* wimp task handle */ os_error *gui_error; /* last error block pointer */ const char *gui_error_message; /* last error message */ int gui_error_line; /* last error line */ jmp_buf gui_error_jump; /* longjmp buffer for error handling */ bool quit = 0; char **gui_message; struct gui_window_data *gui_window_list; /* array of window details */ unsigned int gui_window_list_items; /* length of windows list */ signed int gui_window_origin_x, gui_window_origin_y; static void redraw_window_request(wimp_draw *redraw); static void open_window_request(wimp_open *open); static void close_window_request(wimp_close *close); static void mouse_click(wimp_pointer *pointer); static void key_pressed(wimp_key *key); static void menu_selection(wimp_selection *selection); static void user_message(wimp_message *message); static void help_request(wimp_message *message, help_message_request *request); /****************************************************************************************/ /* main() */ /****************************************************************************************/ int main(int argc, char *argv[]) { gui_initialise(); task_initialise(); gui_event_loop(); task_finalise(); return 0; } /****************************************************************************************/ /* Initialisation */ /****************************************************************************************/ /* * gui_initialise -- initialise the program with the os or window manager * * => name -- program name to pass to the os if applicable * * <= nothing */ void gui_initialise() { char file_name[30]; wimp_MESSAGE_LIST(2) messages; gui_log("gui_initialise: task_name = '%s'\n", task_name); if (setjmp(gui_error_jump)) { gui_log("gui_initialise: *** error %i: %s ***\n", gui_error_line, gui_error_message); printf("%s (%i)\n", gui_error_message, gui_error_line); fflush(stdout); exit(1); } messages.messages[0] = message_HELP_REQUEST; messages.messages[1] = message_QUIT; gui_error = xwimp_initialise(wimp_VERSION_RO3, task_name, (wimp_message_list const *) &messages, NULL, &gui_wimp_task); gui_check_error(); gui_window_list = NULL; gui_window_list_items = 0; sprintf(file_name, "<%s$Messages>", task_name); gui_message = gui_messages_read(file_name); gui_log("gui_initialise: gui_wimp_task = 0x%x\n", (unsigned int) gui_wimp_task); } /****************************************************************************************/ /* Event handling */ /****************************************************************************************/ /* * gui_event_loop -- receive and handle os or window manager events * * => nothing * * <= does not return directly, except on exit */ #define MASK (wimp_MASK_NULL | wimp_MASK_LEAVING | wimp_MASK_ENTERING | wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_POLLWORD) static gui_window_id menu_window_id; void gui_event_loop(void) { wimp_block block; wimp_event_no event; os_error err; if (setjmp(gui_error_jump)) { gui_log("gui_event_loop: *** error %i: %s ***\n", gui_error_line, gui_error_message); err.errnum = 1; sprintf(err.errmess, "%s (%i)\n", gui_error_message, gui_error_line); xwimp_report_error(&err, wimp_ERROR_BOX_OK_ICON, task_name, NULL); } while (!quit) { gui_error = xwimp_poll(MASK, &block, NULL, &event); gui_check_error(); gui_log("gui_event_loop: event = %i\n", event); switch (event) { case wimp_REDRAW_WINDOW_REQUEST: redraw_window_request(&block.redraw); break; case wimp_OPEN_WINDOW_REQUEST: open_window_request(&block.open); break; case wimp_CLOSE_WINDOW_REQUEST: close_window_request(&block.close); break; case wimp_MOUSE_CLICK: mouse_click(&block.pointer); break; case wimp_KEY_PRESSED: key_pressed(&block.key); break; case wimp_MENU_SELECTION: menu_selection(&block.selection); break; case wimp_USER_MESSAGE: case wimp_USER_MESSAGE_RECORDED: user_message(&block.message); break; } } } /* * redraw window request */ void redraw_window_request(wimp_draw *redraw) { bool more; unsigned int invalid[4]; /* why was this signed ?? */ gui_window_id window_id = gui_handle_to_window_id(redraw->w); assert(window_id == gui_WINDOW_UNKNOWN || (window_id < gui_window_list_items && gui_window_list[window_id].used)); gui_error = xwimp_redraw_window(redraw, &more); gui_check_error(); gui_window_origin_x = redraw->box.x0 - redraw->xscroll; gui_window_origin_y = redraw->box.y1 - redraw->yscroll; gui_log("gui_event_loop: redraw origin %i %i\n", gui_window_origin_x, gui_window_origin_y); while (more) { if (window_id != gui_WINDOW_UNKNOWN && gui_window_list[window_id].redraw_fn) { invalid[0] = redraw->clip.x0 - gui_window_origin_x; invalid[1] = gui_window_origin_y - redraw->clip.y1; invalid[2] = redraw->clip.x1 - gui_window_origin_x; invalid[3] = gui_window_origin_y - redraw->clip.y0; gui_log("gui_event_loop: redraw invalid %i %i %i %i\n", invalid[0], invalid[1], invalid[2], invalid[3]); gui_window_list[window_id].redraw_fn(window_id, invalid); } gui_error = xwimp_get_rectangle(redraw, &more); gui_check_error(); } } /* * open window request */ void open_window_request(wimp_open *open) { gui_window_id window_id = gui_handle_to_window_id(open->w); gui_error = xwimp_open_window(open); gui_check_error(); if (window_id != gui_WINDOW_UNKNOWN) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); if ((unsigned int) (open->visible.x1 - open->visible.x0) != gui_window_list[window_id].width || (unsigned int) (open->visible.y1 - open->visible.y0) != gui_window_list[window_id].height) { gui_window_list[window_id].width = open->visible.x1 - open->visible.x0; gui_window_list[window_id].height = open->visible.y1 - open->visible.y0; gui_log("open_window_request: resized to %i %i\n", gui_window_list[window_id].width, gui_window_list[window_id].height); if (gui_window_list[window_id].resize_fn) gui_window_list[window_id].resize_fn(window_id, gui_window_list[window_id].width, gui_window_list[window_id].height); } } } /* * close window request */ void close_window_request(wimp_close *close) { gui_window_id window_id = gui_handle_to_window_id(close->w); gui_log("gui_event_loop: window_id = 0x%x\n", window_id); if (window_id != gui_WINDOW_UNKNOWN) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); gui_window_list[window_id].close_fn(window_id); } } /* * mouse click */ void mouse_click(wimp_pointer *pointer) { gui_window_id window_id = gui_handle_to_window_id(pointer->w); gui_log("gui_event_loop: window_id = 0x%x\n", window_id); if (window_id != gui_WINDOW_UNKNOWN) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); if (gui_window_list[window_id].menu && (pointer->buttons & wimp_CLICK_MENU)) { gui_error = xwimp_create_menu(gui_window_list[window_id].menu, pointer->pos.x - 64, pointer->pos.y); gui_check_error(); menu_window_id = window_id; } else if (gui_window_list[window_id].click_fn) { unsigned int x, y, z; wimp_window_state state; state.w = pointer->w; gui_error = xwimp_get_window_state(&state); gui_check_error(); x = pointer->pos.x - (state.visible.x0 - state.xscroll); y = (state.visible.y1 - state.yscroll) - pointer->pos.y; z = (pointer->buttons & wimp_CLICK_SELECT ? gui_CLICK : (pointer->buttons & wimp_CLICK_ADJUST ? gui_CLICK_RIGHT : (pointer->buttons & wimp_DRAG_SELECT ? gui_DRAG : (pointer->buttons & wimp_DRAG_ADJUST ? gui_DRAG_RIGHT : 0)))); gui_window_list[window_id].click_fn(window_id, x, y, z); } } } /* * key pressed */ void key_pressed(wimp_key *key) { gui_window_id window_id = gui_handle_to_window_id(key->w); gui_log("gui_event_loop: window_id = 0x%x\n", window_id); if (window_id != gui_WINDOW_UNKNOWN) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); if ((key->c & (1<<31)) || (key->c < 256)) { if (gui_window_list[window_id].input_fn) gui_window_list[window_id].input_fn(window_id, (wchar_t) (key->c & 0xffff)); } else { if (gui_window_list[window_id].key_fn) gui_window_list[window_id].key_fn(window_id, (unsigned int) key->c); } } } /* * menu selection */ void menu_selection(wimp_selection *selection) { wimp_pointer pointer; gui_error = xwimp_get_pointer_info(&pointer); gui_check_error(); gui_window_list[menu_window_id].menu_fn(menu_window_id, (unsigned int *) selection->items); if (pointer.buttons == wimp_CLICK_ADJUST) { gui_error = xwimp_create_menu(gui_window_list[menu_window_id].menu, 0, 0); gui_check_error(); } } /* * user message, user message recorded */ void user_message(wimp_message *message) { gui_log("gui_event_loop: block.message.action = 0x%x\n", message->action); switch (message->action) { case message_QUIT: quit = 1; break; case message_HELP_REQUEST: help_request(message, (help_message_request *) &message->data); break; } } /* * interactive help request */ void help_request(wimp_message *message, help_message_request *request) { const char *help; wimp_message reply; gui_window_id window_id = gui_handle_to_window_id(request->w); if (window_id != gui_WINDOW_UNKNOWN) { if (gui_window_list[window_id].used == DIALOG && request->i >= 0) help = gui_window_list[window_id].icon[request->i].help; else help = gui_window_list[window_id].help; gui_log(help); reply.size = (20 + strlen(help) + 3) & ~3u; reply.your_ref = message->my_ref; reply.action = message_HELP_REPLY; strcpy((char *) &reply.data.reserved, help); gui_error = xwimp_send_message(wimp_USER_MESSAGE, &reply, message->sender); gui_check_error(); } }