void ro_treeview_pointer_entering(wimp_entering *entering) { ro_treeview *tv; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(entering->w); if (tv == NULL) return; ro_mouse_track_start(NULL, ro_treeview_mouse_at, NULL); }
/** * Handle acceptance of query dialog */ bool ro_gui_query_apply(wimp_w w) { struct gui_query_window *qw; const query_callback *cb; qw = (struct gui_query_window *)ro_gui_wimp_event_get_user_data(w); cb = qw->cb; cb->confirm(qw->id, QUERY_YES, qw->pw); return true; }
void ro_gui_cert_reject(wimp_pointer *pointer) { struct ro_sslcert *s; s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w); if (s != NULL) { sslcert_reject(s->data); ro_gui_dialog_close(s->window); ro_gui_cert_release_window(s); } }
/** * Handle clicks in query dialog */ bool ro_gui_query_click(wimp_pointer *pointer) { struct gui_query_window *qw; const query_callback *cb; qw = (struct gui_query_window *)ro_gui_wimp_event_get_user_data(pointer->w); cb = qw->cb; switch (pointer->i) { case ICON_QUERY_NO: cb->cancel(qw->id, QUERY_NO, qw->pw); break; default: return false; } return false; }
bool ro_gui_download_click(wimp_pointer *pointer) { struct gui_download_window *dw; dw = (struct gui_download_window *)ro_gui_wimp_event_get_user_data(pointer->w); if ((pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) && pointer->i == ICON_DOWNLOAD_ICON && !dw->error && !dw->saved) { const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i); int x = pointer->pos.x, y = pointer->pos.y; wimp_window_state wstate; wimp_icon_state istate; /* start the drag from the icon's exact location, rather than the pointer */ istate.w = wstate.w = pointer->w; istate.i = pointer->i; if (!xwimp_get_window_state(&wstate) && !xwimp_get_icon_state(&istate)) { x = (istate.icon.extent.x1 + istate.icon.extent.x0)/2 + wstate.visible.x0 - wstate.xscroll; y = (istate.icon.extent.y1 + istate.icon.extent.y0)/2 + wstate.visible.y1 - wstate.yscroll; } ro_mouse_drag_start(ro_gui_download_drag_end, NULL, NULL, NULL); download_window_current = dw; ro_gui_drag_icon(x, y, sprite); } else if (pointer->i == ICON_DOWNLOAD_DESTINATION) { char command[256] = "Filer_OpenDir "; char *dot; strncpy(command + 14, dw->path, 242); command[255] = 0; dot = strrchr(command, '.'); if (dot) { os_error *error; *dot = 0; error = xos_cli(command); if (error) { LOG("xos_cli: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("MiscError", error->errmess); } } } return true; }
static bool ro_treeview_mouse_click(wimp_pointer *pointer) { os_error *error; ro_treeview *tv; wimp_window_state state; int xpos, ypos; browser_mouse_state mouse; bool handled = false; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(pointer->w); if (tv == NULL) { LOG(("NULL treeview block for window: 0x%x", (unsigned int) pointer->w)); return false; } state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return false; } /* Convert the returned mouse coordinates into NetSurf's internal * units. */ xpos = ((pointer->pos.x - state.visible.x0) + state.xscroll - tv->origin.x) / 2; ypos = ((state.visible.y1 - pointer->pos.y) - state.yscroll + tv->origin.y) / 2; /* Start to process the mouse click. * * Select and Adjust are processed normally. To get filer-like operation * with selections, Menu clicks are passed to the treeview first as * Select if there are no selected nodes in the tree. */ mouse = 0; if (pointer->buttons == wimp_CLICK_MENU) { if (!tree_node_has_selection(tree_get_root(tv->tree))) mouse |= BROWSER_MOUSE_CLICK_1; } else { mouse = ro_gui_mouse_click_state(pointer->buttons, wimp_BUTTON_DOUBLE_CLICK_DRAG); /* Give the window input focus on Select-clicks. This wouldn't * be necessary if the core used the RISC OS caret. */ if (mouse & BROWSER_MOUSE_CLICK_1) xwimp_set_caret_position(tv->w, -1, -100, -100, 32, -1); } if (mouse != 0) { handled = tree_mouse_action(tv->tree, mouse, xpos, ypos); tv->drag = tree_drag_status(tv->tree); if (tv->drag != TREE_NO_DRAG) { tv->drag_start.x = xpos; tv->drag_start.y = ypos; } /* If it's a visible drag, start the RO side of the visible * effects. */ if (tv->drag == TREE_SELECT_DRAG || tv->drag == TREE_MOVE_DRAG) ro_treeview_drag_start(tv, pointer, &state); if (tv->callbacks != NULL && tv->callbacks->toolbar_button_update != NULL) tv->callbacks->toolbar_button_update(); } /* Special actions for some mouse buttons. Adjust closes the dialog; * Menu opens a menu. For the latter, we assume that the owning module * will have attached a window menu to our parent window with the auto * flag unset (so that we can fudge the selection above). If it hasn't, * the call will quietly fail. * * \TODO -- Adjust-click close isn't a perfect copy of what the RO * version did: adjust clicks anywhere close the tree, and * selections persist. */ switch(pointer->buttons) { case wimp_CLICK_ADJUST: if (handled) ro_gui_dialog_close(tv->w); break; case wimp_CLICK_MENU: ro_gui_wimp_event_process_window_menu_click(pointer); break; } return true; }
void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv, osbool more) { os_error *error; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &ro_plotters }; while (more) { ro_plot_origin_x = redraw->box.x0 - redraw->xscroll; ro_plot_origin_y = redraw->box.y1 - redraw->yscroll; if (tv != NULL && tv->tree != NULL) { struct rect clip; tree_draw(tv->tree, tv->origin.x/2, -(tv->origin.y/2), (redraw->clip.x0 -(ro_plot_origin_x+tv->origin.x))/2, ((ro_plot_origin_y+tv->origin.y) -redraw->clip.y1)/2, (redraw->clip.x1 - redraw->clip.x0)/2, (redraw->clip.y1 - redraw->clip.y0)/2, &ctx); /* Put the graphcis window back how the Wimp set it. */ clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2; clip.y0 = (ro_plot_origin_y - redraw->clip.y1) / 2; clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2; clip.y1 = (ro_plot_origin_y - redraw->clip.y0) / 2; ro_plotters.clip(&clip); } error = xwimp_get_rectangle(redraw, &more); if (error) { LOG(("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } } } /** * Callback to notify us of a new overall tree size. * * \param tree The tree being resized. * \param width The new width of the window. * \param height The new height of the window. * \param *pw The treeview object to be resized. */ void ro_treeview_resized(struct tree *tree, int width, int height, void *pw) { if (pw != NULL) { ro_treeview *tv = (ro_treeview *) pw; /* Store the width and height in terms of RISC OS work area. */ tv->size.x = width * 2; tv->size.y = -(height * 2); /* Resize the window. */ ro_treeview_set_window_extent(tv, tv->size.x, tv->size.y); } } /** * Callback to request that a section of the tree is scrolled into view. * * \param y The Y coordinate of top of the area in NS units. * \param height The height of the area in NS units. * \param *pw The treeview object affected. */ void ro_treeview_scroll_visible(int y, int height, void *pw) { if (pw != NULL) { ro_treeview *tv = (ro_treeview *) pw; os_error *error; wimp_window_state state; int visible_t, visible_b; int request_t, request_b; state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* Work out top and bottom of both the currently visible and * the required areas, in terms of the RO work area. */ visible_t = state.yscroll; visible_b = state.yscroll - (state.visible.y1 - state.visible.y0); request_t = -(2 * y);// - tv->origin.y; request_b = -(2 * (y + height));// - tv->origin.y; /* If the area is outside the visible window, then scroll it * in to view. */ if (request_t > visible_t || request_b < visible_b) { if (request_t > visible_t) { state.yscroll = request_t; } else if (request_b < visible_b) { state.yscroll = request_b + tv->origin.y + (state.visible.y1 - state.visible.y0); /* If the required area is bigger than the * visible extent, then align to the top and * let the bottom disappear out of view. */ if (state.yscroll < request_t) state.yscroll = request_t; } error = xwimp_open_window((wimp_open *) &state); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } } } } /** * Callback to return the tree window dimensions to the treeview system. * * \param *width Return the window width. * \param *height Return the window height. * \param *pw The treeview object to use. */ void ro_treeview_get_window_dimensions(int *width, int *height, void *pw) { if (pw != NULL && (width != NULL || height != NULL)) { ro_treeview *tv = (ro_treeview *) pw; os_error *error; wimp_window_state state; state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } if (width != NULL) *width = (state.visible.x1 - state.visible.x0) / 2; if (height != NULL) *height = (state.visible.y1 - state.visible.y0) / 2; } } /** * Resize the RISC OS window extent of a treeview. * * \param *tv The RISC OS treeview object to resize. * \param width The new width of the work area, in RO units. * \param height The new height of the work area, in RO units. */ void ro_treeview_set_window_extent(ro_treeview *tv, int width, int height) { if (tv != NULL) { os_error *error; os_box extent; wimp_window_state state; int new_x, new_y; int visible_x, visible_y; int new_x_scroll, new_y_scroll; /* Calculate the new window extents, in RISC OS units. */ new_x = width + tv->origin.x; new_y = height + tv->origin.y; /* Get details of the existing window, and start to sanity * check the new extents. */ state.w = tv->w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* If the extent is smaller than the current visible area, * then extend it so that it matches the visible area. */ if (new_x < (state.visible.x1 - state.visible.x0)) new_x = state.visible.x1 - state.visible.x0; if (new_y > (state.visible.y0 - state.visible.y1)) new_y = state.visible.y0 - state.visible.y1; /* Calculate the maximum visible coordinates of the existing * window. */ visible_x = state.xscroll + (state.visible.x1 - state.visible.x0); visible_y = state.yscroll + (state.visible.y0 - state.visible.y1); /* If the window is currently open, and the exising visible * area is bigger than the new extent, then we need to reopen * the window in an appropriare position before setting the * new extent. */ if ((state.flags & wimp_WINDOW_OPEN) && (visible_x > new_x || visible_y < new_y)) { new_x_scroll = state.xscroll; new_y_scroll = state.yscroll; if (visible_x > new_x) new_x_scroll = new_x - (state.visible.x1 - state.visible.x0); if (visible_y < new_y) new_y_scroll = new_y - (state.visible.y0 - state.visible.y1); if (new_x_scroll < 0) { state.visible.x1 -= new_x_scroll; state.xscroll = 0; } else { state.xscroll = new_x_scroll; } if (new_y_scroll > 0) { state.visible.y0 += new_y_scroll; state.yscroll = 0; } else { state.yscroll = new_y_scroll; } error = xwimp_open_window((wimp_open *) &state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* \todo -- Not sure if we need to reattach the * toolbar here: the nested wimp seems to take care * of it for us? */ } /* Now that the new extent fits into the visible window, we * can resize the work area. If we succeed, the values are * recorded to save having to ask the Wimp for them * each time. */ extent.x0 = 0; extent.y0 = new_y; extent.x1 = new_x; extent.y1 = 0; error = xwimp_set_extent(tv->w, &extent); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } tv->extent.x = new_x; tv->extent.y = new_y; } } /** * Handle RISC OS Window Open events for a treeview window. * * \param *open Pointer to the Window Open Event block. */ static void ro_treeview_open(wimp_open *open) { ro_treeview *tv; os_error *error; os_box extent; int width, height; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(open->w); if (tv == NULL) { LOG(("NULL treeview block for window: ox%x", (unsigned int) open->w)); return; } /* Calculate the window work area. It must be at least the same as * the current visible area of the window, and needs to contain the * tree as defined by size.x + offset.x and size.y + offset.y (note * that the offset.y should be set to cover any toolbar, so we can * ignore the size of that). */ width = open->visible.x1 - open->visible.x0; height = open->visible.y0 - open->visible.y1; if (tv->size.x != 0 && width < (tv->origin.x + tv->size.x)) width = (tv->origin.x + tv->size.x); if (tv->size.y != 0 && height > (tv->size.y + tv->origin.y)) height = (tv->size.y + tv->origin.y); if (width != tv->extent.x || height != tv->extent.y) { extent.x0 = 0; extent.y0 = height; extent.x1 = width; extent.y1 = 0; error = xwimp_set_extent(tv->w, &extent); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } tv->extent.x = width; tv->extent.y = height; } /* \todo -- Might need to add vertical scrollbar hiding back in here? */ error = xwimp_open_window(open); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); } if (tv->tb) ro_toolbar_process(tv->tb, -1, false); }
static bool ro_treeview_keypress(wimp_key *key) { ro_treeview *tv; uint32_t c; tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(key->w); if (tv == NULL) { LOG(("NULL treeview block for window: 0x%x", (unsigned int) key->w)); return false; } c = (uint32_t) key->c; if ((unsigned)c < 0x20 || (0x7f <= c && c <= 0x9f) || (c & IS_WIMP_KEY)) { /* Munge control keys into unused control chars */ /* We can't map onto 1->26 (reserved for ctrl+<qwerty> That leaves 27->31 and 128->159 */ switch (c & ~IS_WIMP_KEY) { case wimp_KEY_TAB: c = 9; break; case wimp_KEY_SHIFT | wimp_KEY_TAB: c = 11; break; /* cursor movement keys */ case wimp_KEY_HOME: case wimp_KEY_CONTROL | wimp_KEY_LEFT: c = KEY_LINE_START; break; case wimp_KEY_END: if (os_version >= RISCOS5) c = KEY_LINE_END; else c = KEY_DELETE_RIGHT; break; case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = KEY_LINE_END; break; case wimp_KEY_CONTROL | wimp_KEY_UP: c = KEY_TEXT_START; break; case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = KEY_TEXT_END; break; case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = KEY_WORD_LEFT ; break; case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = KEY_WORD_RIGHT; break; case wimp_KEY_SHIFT | wimp_KEY_UP: c = KEY_PAGE_UP; break; case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = KEY_PAGE_DOWN; break; case wimp_KEY_LEFT: c = KEY_LEFT; break; case wimp_KEY_RIGHT: c = KEY_RIGHT; break; case wimp_KEY_UP: c = KEY_UP; break; case wimp_KEY_DOWN: c = KEY_DOWN; break; /* editing */ case wimp_KEY_CONTROL | wimp_KEY_END: c = KEY_DELETE_LINE_END; break; case wimp_KEY_DELETE: if (ro_gui_ctrl_pressed()) c = KEY_DELETE_LINE_START; else if (os_version < RISCOS5) c = KEY_DELETE_LEFT; break; default: break; } } if (!(c & IS_WIMP_KEY)) { if (tree_keypress(tv->tree, c)) { if (tv->callbacks && tv->callbacks->toolbar_button_update != NULL) tv->callbacks->toolbar_button_update(); return true; } } return false; }
/** * Handle key presses in a text area * * \param key Key pressed state block * \param true if press handled, false otherwise */ bool ro_textarea_key_press(wimp_key *key) { uint32_t c = (uint32_t) key->c; wimp_key keypress; struct text_area *ta; char utf8[7]; size_t utf8_len; bool redraw = false; unsigned int c_pos; os_error *error; ta = (struct text_area *)ro_gui_wimp_event_get_user_data(key->w); if (ta->flags & TEXTAREA_READONLY) return true; if (!(c & IS_WIMP_KEY || (c <= 0x001f || (0x007f <= c && c <= 0x009f)))) { /* normal character - insert */ utf8_len = utf8_from_ucs4(c, utf8); utf8[utf8_len] = '\0'; c_pos = ro_textarea_get_caret((uintptr_t)ta); ro_textarea_insert_text((uintptr_t)ta, c_pos, utf8); ro_textarea_set_caret((uintptr_t)ta, ++c_pos); redraw = true; } else { /** \todo handle command keys */ switch (c & ~IS_WIMP_KEY) { case 8: /* Backspace */ c_pos = ro_textarea_get_caret((uintptr_t)ta); if (c_pos > 0) { ro_textarea_replace_text((uintptr_t)ta, c_pos - 1, c_pos, ""); ro_textarea_set_caret((uintptr_t)ta, c_pos - 1); redraw = true; } break; case 21: /* Ctrl + U */ ro_textarea_set_text((uintptr_t)ta, ""); ro_textarea_set_caret((uintptr_t)ta, 0); redraw = true; break; case wimp_KEY_DELETE: c_pos = ro_textarea_get_caret((uintptr_t)ta); if (os_version < RISCOS5 && c_pos > 0) { ro_textarea_replace_text((uintptr_t)ta, c_pos - 1, c_pos, ""); ro_textarea_set_caret((uintptr_t)ta, c_pos - 1); } else { ro_textarea_replace_text((uintptr_t)ta, c_pos, c_pos + 1, ""); } redraw = true; break; case wimp_KEY_LEFT: c_pos = ro_textarea_get_caret((uintptr_t)ta); if (c_pos > 0) ro_textarea_set_caret((uintptr_t)ta, c_pos - 1); break; case wimp_KEY_RIGHT: c_pos = ro_textarea_get_caret((uintptr_t)ta); ro_textarea_set_caret((uintptr_t)ta, c_pos + 1); break; case wimp_KEY_UP: /** \todo Move caret up a line */ break; case wimp_KEY_DOWN: /** \todo Move caret down a line */ break; case wimp_KEY_HOME: case wimp_KEY_CONTROL | wimp_KEY_LEFT: /** \todo line start */ break; case wimp_KEY_CONTROL | wimp_KEY_RIGHT: /** \todo line end */ break; case wimp_KEY_CONTROL | wimp_KEY_UP: ro_textarea_set_caret((uintptr_t)ta, 0); break; case wimp_KEY_CONTROL | wimp_KEY_DOWN: ro_textarea_set_caret((uintptr_t)ta, utf8_length(ta->text)); break; case wimp_KEY_COPY: if (os_version < RISCOS5) { c_pos = ro_textarea_get_caret((uintptr_t)ta); ro_textarea_replace_text((uintptr_t)ta, c_pos, c_pos + 1, ""); } else { /** \todo line end */ } break; /** pass on RETURN and ESCAPE to the parent icon */ case wimp_KEY_RETURN: if (ta->flags & TEXTAREA_MULTILINE) { /* Insert newline */ c_pos = ro_textarea_get_caret((uintptr_t)ta); ro_textarea_insert_text((uintptr_t)ta, c_pos, "\n"); ro_textarea_set_caret((uintptr_t)ta, ++c_pos); redraw = true; break; } /* fall through */ case wimp_KEY_ESCAPE: keypress = *key; keypress.w = ta->parent; keypress.i = ta->icon; keypress.index = 0; /* undefined if not in an icon */ error = xwimp_send_message_to_window(wimp_KEY_PRESSED, (wimp_message*)&keypress, ta->parent, ta->icon, 0); if (error) { LOG(("xwimp_send_message: 0x%x:%s", error->errnum, error->errmess)); } break; } } if (redraw) { wimp_draw update; update.w = ta->window; update.box.x0 = 0; update.box.y1 = 0; update.box.x1 = ta->vis_width; update.box.y0 = -ta->line_height * (ta->line_count + 1); ro_textarea_redraw_internal(&update, true); } return true; }
/** * Internal textarea redraw routine * * \param redraw Redraw/update request block * \param update True if update, false if full redraw */ void ro_textarea_redraw_internal(wimp_draw *redraw, bool update) { struct text_area *ta; int clip_x0, clip_y0, clip_x1, clip_y1; int line0, line1, line; osbool more; rufl_code code; os_error *error; ta = (struct text_area *)ro_gui_wimp_event_get_user_data(redraw->w); if (update) error = xwimp_update_window(redraw, &more); else error = xwimp_redraw_window(redraw, &more); if (error) { LOG(("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess)); return; } while (more) { clip_x0 = redraw->clip.x0 - (redraw->box.x0-redraw->xscroll); clip_y0 = (redraw->box.y1-redraw->yscroll) - redraw->clip.y1; clip_x1 = redraw->clip.x1 - (redraw->box.x0-redraw->xscroll); clip_y1 = (redraw->box.y1-redraw->yscroll) - redraw->clip.y0; error = xcolourtrans_set_gcol( (ta->flags & TEXTAREA_READONLY) ? 0xD9D9D900 : 0xFFFFFF00, colourtrans_SET_BG_GCOL | colourtrans_USE_ECFS_GCOL, os_ACTION_OVERWRITE, 0, 0); if (error) { LOG(("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess)); return; } error = xos_clg(); if (error) { LOG(("xos_clg: 0x%x: %s", error->errnum, error->errmess)); return; } if (!ta->lines) /* Nothing to redraw */ return; line0 = clip_y0 / ta->line_height - 1; line1 = clip_y1 / ta->line_height + 1; if (line0 < 0) line0 = 0; if (line1 < 0) line1 = 0; if (ta->line_count - 1 < (unsigned)line0) line0 = ta->line_count - 1; if (ta->line_count - 1 < (unsigned)line1) line1 = ta->line_count - 1; if (line1 < line0) line1 = line0; for (line = line0; line <= line1; line++) { if (ta->lines[line].b_length == 0) continue; error = xcolourtrans_set_font_colours(font_CURRENT, (ta->flags & TEXTAREA_READONLY) ? 0xD9D9D900 : 0xFFFFFF00, 0x00000000, 14, 0, 0, 0); if (error) { LOG(("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess)); return; } code = rufl_paint(ta->font_family, ta->font_style, ta->font_size, ta->text + ta->lines[line].b_start, ta->lines[line].b_length, redraw->box.x0 - redraw->xscroll + MARGIN_LEFT, redraw->box.y1 - redraw->yscroll - ((line + 1) * ta->line_height - ta->line_spacing), rufl_BLEND_FONT); if (code != rufl_OK) { if (code == rufl_FONT_MANAGER_ERROR) LOG(("rufl_paint: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess)); else LOG(("rufl_paint: 0x%x", code)); } } error = xwimp_get_rectangle(redraw, &more); if (error) { LOG(("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess)); return; } } }