/* * window_riscos.c -- window handling, RISC OS */ #include "gui.h" /* * gui_create_window -- create and display a window * * => flags -- window details * title -- window title * width -- width of window * height -- height of window * close_fn -- function called when an attempt is made to close the window, * NULL for default of closing and destroying window * redraw_fn -- function called when the window needs redrawing * click_fn -- function called when the mouse is clicked in the window or equivalent, * NULL for default of no action * * <= window id */ gui_window_id gui_create_window(const unsigned int flags, char *title, const unsigned int width, const unsigned int height, void (*close_fn)(gui_window_id window_id), void (*redraw_fn)(gui_window_id window_id, unsigned int invalid[]), void (*click_fn)(gui_window_id window_id, unsigned int x, unsigned int y, unsigned int z), void (*resize_fn)(gui_window_id window_id, unsigned int width, unsigned int height), bool (*key_fn)(gui_window_id window_id, unsigned int key), void (*input_fn)(gui_window_id window_id, wchar_t key), void (*menu_fn)(gui_window_id window_id, unsigned int items[]), wimp_menu *menu, const char *bbar, const char *help) { wimp_WINDOW(1) window; wimp_w handle; wimp_window_state open; gui_window_id id; #ifdef DEBUG printf("gui_create_window: title = '%s'\n", title); fflush(stdout); #endif assert(redraw_fn != NULL); id = gui_get_free_window_id(); window.visible.x0 = 100; window.visible.y0 = 100; window.visible.x1 = window.visible.x0 + width; window.visible.y1 = window.visible.y0 + height; window.xscroll = window.yscroll = 0; window.next = wimp_TOP; window.flags = wimp_WINDOW_MOVEABLE | wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | (flags & gui_H_SCROLL_BAR ? wimp_WINDOW_HSCROLL | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_SIZE_ICON : 0) | (flags & gui_V_SCROLL_BAR ? wimp_WINDOW_VSCROLL | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_SIZE_ICON : 0); window.title_fg = wimp_COLOUR_BLACK; window.title_bg = wimp_COLOUR_LIGHT_GREY; window.work_fg = wimp_COLOUR_BLACK; // window.work_bg = wimp_COLOUR_WHITE; window.work_bg = wimp_COLOUR_TRANSPARENT; window.highlight_bg = wimp_COLOUR_CREAM; window.extent.x0 = window.extent.y1 = 0; window.extent.y0 = -height; window.extent.x1 = width; window.title_flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED; window.work_flags = wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT; window.sprite_area = (osspriteop_area *) 1; window.xmin = window.ymin = 1; window.title_data.indirected_text.text = title; window.title_data.indirected_text.validation = 0; window.icon_count = 0; gui_error = xwimp_create_window((wimp_window const *) &window, &handle); gui_check_error(); open.w = handle; gui_error = xwimp_get_window_state(&open); gui_check_error(); gui_error = xwimp_open_window((wimp_open *) &open); gui_check_error(); gui_window_list[id].used = 1; gui_window_list[id].handle = handle; gui_window_list[id].close_fn = (close_fn == NULL ? gui_remove_window : close_fn); gui_window_list[id].redraw_fn = redraw_fn; gui_window_list[id].click_fn = click_fn; gui_window_list[id].resize_fn = resize_fn; gui_window_list[id].key_fn = key_fn; gui_window_list[id].input_fn = input_fn; gui_window_list[id].menu_fn = menu_fn; gui_window_list[id].width = width; gui_window_list[id].height = height; gui_window_list[id].menu = menu; gui_window_list[id].help = help; #ifdef DEBUG printf("gui_create_window: id = 0x%x, handle = 0x%x\n", id, (unsigned int) handle); fflush(stdout); #endif return id; } /* * gui_get_free_window_id -- allocate space and return a window id * * => nothing * * <= window id (gui_window_list index) */ gui_window_id gui_get_free_window_id() { static struct gui_window_data *new_gui_window_list; unsigned int i; #ifdef DEBUG printf("gui_get_free_window_id: gui_window_list_items = %i\n", gui_window_list_items); fflush(stdout); #endif for (i = 0; i < gui_window_list_items; i++) if (!gui_window_list[i].used) return i; new_gui_window_list = realloc(gui_window_list, sizeof(struct gui_window_data) * (gui_window_list_items + WINDOW_LIST_CHUNK)); if (!new_gui_window_list) gui_raise_error("memory"); gui_window_list = new_gui_window_list; for (i = gui_window_list_items; i < gui_window_list_items + WINDOW_LIST_CHUNK; i++) gui_window_list[i].used = 0; i = gui_window_list_items; gui_window_list_items += WINDOW_LIST_CHUNK; #ifdef DEBUG printf("gui_get_free_window_id: increased gui_window_list_items = %i\n", gui_window_list_items); fflush(stdout); #endif assert(i < gui_window_list_items); return i; } /* * gui_handle_to_window_id -- convert a window handle to a window id * * => handle -- wimp window handle * * <= window id */ gui_window_id gui_handle_to_window_id(wimp_w handle) { unsigned int i; for (i = 0; i < gui_window_list_items; i++) { if ((gui_window_list[i].used) && (gui_window_list[i].handle == handle)) { #ifdef DEBUG printf("gui_handle_to_window_id: handle = 0x%x, id = 0x%x\n", (unsigned int) handle, i); fflush(stdout); #endif return i; } } return gui_WINDOW_UNKNOWN; } /* * gui_remove_window -- close and destroy a window * * => window_id -- window id from gui_create_window * * <= nothing */ void gui_remove_window(const gui_window_id window_id) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); #ifdef DEBUG printf("gui_remove_window: window_id = 0x%x\n", window_id); fflush(stdout); #endif gui_error = xwimp_delete_window(gui_window_list[window_id].handle); gui_check_error(); gui_window_list[window_id].used = 0; } /* * gui_refresh_window -- update a window's contents * * => window_id -- window id from gui_create_window * * <= nothing */ void gui_refresh_window(const gui_window_id window_id) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); #ifdef DEBUG printf("gui_refresh_window: window_id = 0x%x\n", window_id); fflush(stdout); #endif gui_refresh_box(window_id, 0, 0, 0x10000000, 0x10000000); } /* * gui_refresh_box -- update part of a window's contents * * => window_id -- window id from gui_create_window * x0, y0, x1, y1 -- area to update * * <= nothing */ void gui_refresh_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) { unsigned int invalid[4]; bool more; wimp_window_state state; wimp_draw update; assert(window_id < gui_window_list_items && gui_window_list[window_id].used); #ifdef DEBUG printf("gui_refresh_box: window_id = 0x%x, box %i %i %i %i\n", window_id, x0, y0, x1, y1); fflush(stdout); #endif state.w = gui_window_list[window_id].handle; gui_error = xwimp_get_window_state(&state); gui_check_error(); gui_window_origin_x = state.visible.x0 - state.xscroll; gui_window_origin_y = state.visible.y1 - state.yscroll; #ifdef DEBUG printf("gui_refresh_box: redraw origin %i %i\n", gui_window_origin_x, gui_window_origin_y); fflush(stdout); #endif update.w = state.w; update.box.x0 = x0; update.box.y0 = -y1; update.box.x1 = x1; update.box.y1 = -y0; gui_error = xwimp_update_window(&update, &more); gui_check_error(); while (more) { invalid[0] = update.clip.x0 - gui_window_origin_x; invalid[1] = gui_window_origin_y - update.clip.y1; invalid[2] = update.clip.x1 - gui_window_origin_x; invalid[3] = gui_window_origin_y - update.clip.y0; #ifdef DEBUG printf("gui_refresh_box: redraw invalid %i %i %i %i\n", invalid[0], invalid[1], invalid[2], invalid[3]); fflush(stdout); #endif gui_window_list[window_id].redraw_fn(window_id, invalid); gui_error = xwimp_get_rectangle(&update, &more); gui_check_error(); } } /* * gui_window_extent -- set window size * * => window_id -- window id from gui_create_window * width, height -- new dimensions of window * * <= nothing */ void gui_window_extent(const gui_window_id window_id, unsigned int width, unsigned int height) { os_box box = {0, 0, 0, 0}; box.y0 = (height == 0 ? 0x80000000 : -height); box.x1 = (width == 0 ? 0x7fffffff : width); assert(window_id < gui_window_list_items && gui_window_list[window_id].used); #ifdef DEBUG printf("gui_window_extent: window_id = 0x%x, extent = %i x %i\n", window_id, width, height); fflush(stdout); #endif gui_error = xwimp_set_extent(gui_window_list[window_id].handle, &box); gui_check_error(); gui_window_list[window_id].width = width; gui_window_list[window_id].height = height; } /* * gui_fill -- fill a rectangular area during window redraw * * => colour -- 0xbbggrr format colour * x0, y0, x1, y1 -- coordinates of rectangle */ void gui_fill(unsigned int colour, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) { gui_error = xcolourtrans_set_gcol((os_colour) colour << 8, 0, os_ACTION_OVERWRITE, NULL, NULL); gui_check_error(); gui_error = xos_plot(os_MOVE_TO, (signed int) (gui_window_origin_x + x0), (signed int) (gui_window_origin_y - y0)); gui_check_error(); gui_error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO, (signed int) (gui_window_origin_x + x1), (signed int) (gui_window_origin_y - y1)); gui_check_error(); } /* * gui_move_box -- copy a rectangular area within a window * * => window_id -- window id from gui_create_window * x0, y0, x1, y1 -- source area * x2, y2 -- destination */ void gui_move_box(const gui_window_id window_id, unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) { assert(window_id < gui_window_list_items && gui_window_list[window_id].used); #ifdef DEBUG printf("gui_move_box: window_id = 0x%x, box = %i %i %i %i, dest = %i %i\n", window_id, x0, y0, x1, y1, x2, y2); fflush(stdout); #endif gui_error = xwimp_block_copy(gui_window_list[window_id].handle, (signed int) x0, (signed int) -y1, (signed int) x1, (signed int) -y0, (signed int) x2, (signed int) -(y1 + (y2 - y0))); gui_check_error(); }