void ro_gui_history_open(struct browser_window *bw, struct history *history, bool at_pointer) { int width, height; os_box box = {0, 0, 0, 0}; wimp_window_state state; os_error *error; assert(history); history_current = history; history_bw = bw; history_size(history, &width, &height); width *= 2; height *= 2; /* set extent */ box.x1 = width; box.y0 = -height; error = xwimp_set_extent(history_window, &box); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* open full size */ state.w = history_window; 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; } state.visible.x0 = 0; state.visible.y0 = 0; state.visible.x1 = width; state.visible.y1 = height; state.next = wimp_HIDDEN; error = xwimp_open_window(PTR_WIMP_OPEN(&state)); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } ro_gui_dialog_open_persistent(bw->window->window, history_window, at_pointer); }
bool ro_gui_options_theme_initialise(wimp_w w) { wimp_window_state state; wimp_icon_state icon_state; os_error *error; struct theme_descriptor *theme_choice; struct toolbar_display *toolbar; /* only allow one instance for now*/ if (theme_pane) return false; error = xwimp_create_window(&theme_pane_definition, &theme_pane); if (error) { LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); return false; } state.w = w; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return false; } icon_state.w = w; icon_state.i = THEME_PANE_AREA; error = xwimp_get_icon_state(&icon_state); if (error) { LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); return false; } state.w = theme_pane; state.visible.x1 = state.visible.x0 + icon_state.icon.extent.x1 - 16 - ro_get_vscroll_width(theme_pane); state.visible.x0 += icon_state.icon.extent.x0 + 16; state.visible.y0 = state.visible.y1 + icon_state.icon.extent.y0 + 16; state.visible.y1 += icon_state.icon.extent.y1 - 28; LOG(("Y0 = %i, y1 = %i", icon_state.icon.extent.y0, icon_state.icon.extent.y1)); error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), w, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_YORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_LS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_BS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_RS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_TS_EDGE_SHIFT); if (error) { LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); return false; } /* load themes */ ro_gui_options_theme_load(); /* set the current selection */ theme_choice = ro_gui_theme_find(option_theme); if (!theme_choice) theme_choice = ro_gui_theme_find("Aletheia"); for (toolbar = toolbars; toolbar; toolbar = toolbar->next) ro_gui_set_icon_selected_state(theme_pane, toolbar->icon_number, (toolbar->descriptor == theme_choice)); ro_gui_wimp_event_memorise(theme_pane); ro_gui_wimp_event_set_help_prefix(theme_pane, "HelpThemePConfig"); ro_gui_wimp_event_register_mouse_click(w, ro_gui_options_theme_click); ro_gui_wimp_event_register_cancel(w, THEME_CANCEL_BUTTON); ro_gui_wimp_event_register_ok(w, THEME_OK_BUTTON, ro_gui_options_theme_ok); ro_gui_wimp_event_set_help_prefix(w, "HelpThemeConfig"); ro_gui_wimp_event_memorise(w); return true; }
void ro_gui_options_theme_load(void) { os_error *error; os_box extent = { 0, 0, 0, 0 }; struct theme_descriptor *descriptor; struct toolbar_display *link; struct toolbar_display *toolbar_display; struct toolbar *toolbar; wimp_icon_create new_icon; wimp_window_state state; int parent_width, nested_y, min_extent, base_extent; int item_height; int *radio_icons, *radio_set; int theme_count; /* delete our old list and get/open a new one */ ro_gui_options_theme_free(); theme_list = ro_gui_theme_get_available(); ro_gui_theme_open(theme_list, true); /* create toolbars for each theme */ theme_count = 0; descriptor = theme_list; while (descriptor) { /* try to create a toolbar */ toolbar = ro_gui_theme_create_toolbar(descriptor, THEME_BROWSER_TOOLBAR); if (toolbar) { toolbar_display = calloc(sizeof(struct toolbar_display), 1); if (!toolbar_display) { LOG(("No memory for calloc()")); warn_user("NoMemory", 0); return; } toolbar_display->toolbar = toolbar; toolbar_display->descriptor = descriptor; if (!toolbars) { toolbars = toolbar_display; } else { link = toolbars; while (link->next) link = link->next; link->next = toolbar_display; } theme_count++; } descriptor = descriptor->next; } /* nest the toolbars */ state.w = theme_pane; 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; } parent_width = state.visible.x1 - state.visible.x0; min_extent = state.visible.y0 - state.visible.y1; nested_y = 0; base_extent = state.visible.y1 - state.yscroll; extent.x1 = parent_width; link = toolbars; new_icon.w = theme_pane; new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); while (link) { /* update the toolbar */ item_height = 44 + 44 + 16; if (link->next) item_height += 16; ro_gui_theme_process_toolbar(link->toolbar, parent_width); extent.y0 = nested_y - link->toolbar->height - item_height; if (link->next) extent.y0 -= 16; if (extent.y0 > min_extent) extent.y0 = min_extent; xwimp_set_extent(theme_pane, &extent); ro_gui_set_icon_button_type(link->toolbar->toolbar_handle, ICON_TOOLBAR_URL, wimp_BUTTON_NEVER); /* create the descriptor icons and separator line */ new_icon.icon.extent.x0 = 8; new_icon.icon.extent.x1 = parent_width - 8; new_icon.icon.flags &= ~wimp_ICON_BORDER; new_icon.icon.flags |= wimp_ICON_SPRITE; new_icon.icon.extent.y1 = nested_y - link->toolbar->height - 8; new_icon.icon.extent.y0 = nested_y - link->toolbar->height - 52; new_icon.icon.data.indirected_text_and_sprite.text = (char *)&link->descriptor->name; new_icon.icon.data.indirected_text_and_sprite.size = strlen(link->descriptor->name) + 1; new_icon.icon.data.indirected_text_and_sprite.validation = theme_radio_validation; new_icon.icon.flags |= (wimp_BUTTON_RADIO << wimp_ICON_BUTTON_TYPE_SHIFT); xwimp_create_icon(&new_icon, &link->icon_number); new_icon.icon.flags &= ~wimp_ICON_SPRITE; new_icon.icon.extent.x0 = 52; new_icon.icon.extent.y1 -= 44; new_icon.icon.extent.y0 -= 44; new_icon.icon.data.indirected_text.text = (char *)&link->descriptor->author; new_icon.icon.data.indirected_text.size = strlen(link->descriptor->filename) + 1; new_icon.icon.data.indirected_text.validation = theme_null_validation; new_icon.icon.flags &= ~(wimp_BUTTON_RADIO << wimp_ICON_BUTTON_TYPE_SHIFT); xwimp_create_icon(&new_icon, 0); if (link->next) { new_icon.icon.flags |= wimp_ICON_BORDER; new_icon.icon.extent.x0 = -8; new_icon.icon.extent.x1 = parent_width + 8; new_icon.icon.extent.y1 -= 52; new_icon.icon.extent.y0 = new_icon.icon.extent.y1 - 8; new_icon.icon.data.indirected_text.text = theme_null_validation; new_icon.icon.data.indirected_text.validation = theme_line_validation; new_icon.icon.data.indirected_text.size = 1; xwimp_create_icon(&new_icon, 0); } /* nest the toolbar window */ state.w = link->toolbar->toolbar_handle; state.yscroll = 0; state.visible.y1 = nested_y + base_extent; state.visible.y0 = state.visible.y1 - link->toolbar->height + 2; xwimp_open_window_nested(PTR_WIMP_OPEN(&state), theme_pane, wimp_CHILD_LINKS_PARENT_WORK_AREA << wimp_CHILD_BS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_WORK_AREA << wimp_CHILD_TS_EDGE_SHIFT); /* continue processing */ nested_y -= link->toolbar->height + item_height; link = link->next; } /* set the icons as radios */ radio_icons = (int *)calloc(theme_count + 1, sizeof(int)); radio_set = radio_icons; for (link = toolbars; link; link = link->next) *radio_set++ = link->icon_number; *radio_set = -1; ro_gui_wimp_event_register_radio(theme_pane, radio_icons); /* update our display */ xwimp_force_redraw(theme_pane, 0, -16384, 16384, 16384); }
bool ro_gui_url_complete_keypress(struct toolbar *toolbar, uint32_t key) { wimp_w parent; wimp_window_state state; char *match_url; const char *url; int old_selection; int height; os_error *error; bool currently_open; assert(toolbar != NULL); parent = ro_toolbar_get_parent_window(toolbar); /* we must have a toolbar/url bar */ if (!ro_toolbar_get_display_url(toolbar) || (!nsoption_bool(url_suggestion))) { ro_gui_url_complete_close(); return false; } /* if we are currently active elsewhere, remove the previous window */ currently_open = ((parent == url_complete_parent) && (url_complete_matches_available > 0)); if (parent != url_complete_parent) ro_gui_url_complete_close(); /* forcibly open on down keys */ if ((!currently_open) && (url_complete_matched_string)) { switch (key) { case IS_WIMP_KEY | wimp_KEY_DOWN: case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN: case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN: free(url_complete_matched_string); url_complete_matched_string = NULL; } } /* get the text to match */ url_complete_parent = parent; url = ro_toolbar_get_url(toolbar); match_url = (url != NULL) ? strdup(url) : NULL; if (match_url == NULL) { ro_gui_url_complete_close(); return false; } /* if the text to match has changed then update it */ if ((!url_complete_matched_string) || (strcmp(match_url, url_complete_matched_string))) { /* memorize the current matches */ int i; int lines = MAXIMUM_VISIBLE_LINES; if (lines > url_complete_matches_available) lines = url_complete_matches_available; if (url_complete_matches) { for (i = 0; i < MAXIMUM_VISIBLE_LINES; i++) { if (i < lines) { url_complete_redraw[i] = url_complete_matches[i]; } else { url_complete_redraw[i] = NULL; } } } /* our selection gets wiped */ error = xwimp_force_redraw(dialog_url_complete, 0, -(url_complete_matches_selection + 1) * 44, 65536, -url_complete_matches_selection * 44); if (error) { LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } /* clear our state */ free(url_complete_original_url); free(url_complete_matched_string); url_complete_matched_string = match_url; url_complete_original_url = NULL; url_complete_matches_available = 0; url_complete_matches_selection = -1; url_complete_keypress_selection = -1; /* get some initial memory */ if (!url_complete_matches) { url_complete_matches = malloc(64 * sizeof(char *)); if (!url_complete_matches) { ro_gui_url_complete_close(); return false; } url_complete_matches_allocated = 64; } /* find matches */ url_complete_memory_exhausted = false; if (strlen(match_url) == 0) urldb_iterate_entries(url_complete_callback); else urldb_iterate_partial(match_url, url_complete_callback); if ((url_complete_memory_exhausted) || (url_complete_matches_available == 0)) { ro_gui_url_complete_close(); return false; } /* update the window */ state.w = parent; error = xwimp_get_window_state(&state); if (error) { LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); return false; } url_complete_matches_reset = true; ro_gui_url_complete_resize(toolbar, PTR_WIMP_OPEN(&state)); url_complete_matches_reset = false; /* redraw the relevant bits of the window */ lines = MAXIMUM_VISIBLE_LINES; if (lines > url_complete_matches_available) lines = url_complete_matches_available; for (i = 0; i < lines; i++) { if (url_complete_redraw[i] != url_complete_matches[i]) { error = xwimp_force_redraw(dialog_url_complete, 0, -(i + 1) * 44, 65536, -i * 44); if (error) { LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } } } } else { free(match_url); } /* handle keypresses */ if (!currently_open) return false; old_selection = url_complete_matches_selection; switch (key) { case IS_WIMP_KEY | wimp_KEY_UP: url_complete_matches_selection--; break; case IS_WIMP_KEY | wimp_KEY_DOWN: url_complete_matches_selection++; break; case IS_WIMP_KEY | wimp_KEY_PAGE_UP: url_complete_matches_selection -= MAXIMUM_VISIBLE_LINES; break; case IS_WIMP_KEY | wimp_KEY_PAGE_DOWN: url_complete_matches_selection += MAXIMUM_VISIBLE_LINES; break; case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_UP: url_complete_matches_selection = 0; break; case IS_WIMP_KEY | wimp_KEY_CONTROL | wimp_KEY_DOWN: url_complete_matches_selection = 65536; break; } if (url_complete_matches_selection > url_complete_matches_available - 1) url_complete_matches_selection = url_complete_matches_available - 1; else if (url_complete_matches_selection < -1) url_complete_matches_selection = -1; if (old_selection == url_complete_matches_selection) return false; error = xwimp_force_redraw(dialog_url_complete, 0, -(old_selection + 1) * 44, 65536, -old_selection * 44); if (error) { LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } error = xwimp_force_redraw(dialog_url_complete, 0, -(url_complete_matches_selection + 1) * 44, 65536, -url_complete_matches_selection * 44); if (error) { LOG("xwimp_force_redraw: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } if (old_selection == -1) { free(url_complete_original_url); url_complete_original_url = malloc(strlen(url) + 1); if (!url_complete_original_url) return false; strcpy(url_complete_original_url, url); } if (url_complete_matches_selection == -1) { ro_toolbar_set_url(toolbar, url_complete_original_url, true, false); } else { ro_toolbar_set_url(toolbar, nsurl_access(url_complete_matches[ url_complete_matches_selection]), true, false); free(url_complete_matched_string); url_complete_matched_string = strdup(nsurl_access( url_complete_matches[ url_complete_matches_selection])); } url_complete_keypress_selection = url_complete_matches_selection; /* auto-scroll */ state.w = dialog_url_complete; error = xwimp_get_window_state(&state); if (error) { LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); return true; } if (state.yscroll < -(url_complete_matches_selection * 44)) state.yscroll = -(url_complete_matches_selection * 44); height = state.visible.y1 - state.visible.y0; if (state.yscroll - height > -((url_complete_matches_selection + 1) * 44)) state.yscroll = -((url_complete_matches_selection + 1) * 44) + height; error = xwimp_open_window(PTR_WIMP_OPEN(&state)); if (error) { LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); return true; } return true; }
void gui_cert_verify(const char *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw) { struct ro_sslcert *sslcert_window; wimp_window_state state; wimp_icon_state istate; wimp_window_info info; os_error *error; bool set_extent; assert(certs); sslcert_window = malloc(sizeof(struct ro_sslcert)); if (sslcert_window == NULL) { LOG(("Failed to allocate memory for SSL Cert Dialog")); return; } /* Create the SSL window and its pane. */ error = xwimp_create_window(ro_gui_cert_dialog_template, &(sslcert_window->window)); if (error) { LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); free(sslcert_window); return; } error = xwimp_create_window(ro_gui_cert_tree_template, &(sslcert_window->pane)); if (error) { LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); free(sslcert_window); return; } /* Create the SSL data and build a tree from it. */ sslcert_window->tv = ro_treeview_create(sslcert_window->pane, NULL, NULL, sslcert_get_tree_flags()); if (sslcert_window->tv == NULL) { LOG(("Failed to allocate treeview")); free(sslcert_window); return; } sslcert_window->data = sslcert_create_session_data(num, url, cb, cbpw); sslcert_load_tree(ro_treeview_get_tree(sslcert_window->tv), certs, sslcert_window->data); tree_set_redraw(ro_treeview_get_tree(sslcert_window->tv), true); /* Set up the certificate window event handling. * * (The action buttons are registered as button events, not OK and * Cancel, as both need to carry out actions.) */ ro_gui_wimp_event_set_user_data(sslcert_window->window, sslcert_window); ro_gui_wimp_event_register_close_window(sslcert_window->window, ro_gui_cert_close_window); ro_gui_wimp_event_register_button(sslcert_window->window, ICON_SSL_REJECT, ro_gui_cert_reject); ro_gui_wimp_event_register_button(sslcert_window->window, ICON_SSL_ACCEPT, ro_gui_cert_accept); ro_gui_dialog_open_persistent(NULL, sslcert_window->window, false); /* Nest the tree window inside the pane window. To do this, we: * - Get the current pane extent, * - Get the parent window position and the location of the pane- * locating icon inside it, * - Set the visible area of the pane to suit, * - Check that the pane extents are OK for this visible area, and * increase them if necessary, * - Before finally opening the pane as a nested part of the parent. */ info.w = sslcert_window->pane; error = xwimp_get_window_info_header_only(&info); if (error) { ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_window_info: 0x%x: %s", error->errnum, error->errmess)); return; } state.w = sslcert_window->window; error = xwimp_get_window_state(&state); if (error) { ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return; } istate.w = sslcert_window->window; istate.i = ICON_SSL_PANE; error = xwimp_get_icon_state(&istate); if (error) { ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); return; } state.w = sslcert_window->pane; state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 - 20 - ro_get_vscroll_width(sslcert_window->pane); state.visible.x0 += istate.icon.extent.x0 + 20; state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 + 20 + ro_get_hscroll_height(sslcert_window->pane); state.visible.y1 += istate.icon.extent.y1 - 32; set_extent = false; if ((info.extent.x1 - info.extent.x0) < (state.visible.x1 - state.visible.x0)) { info.extent.x0 = 0; info.extent.x1 = state.visible.x1 - state.visible.x0; set_extent = true; } if ((info.extent.y1 - info.extent.y0) < (state.visible.y1 - state.visible.y0)) { info.extent.y1 = 0; info.extent.x1 = state.visible.y0 - state.visible.y1; set_extent = true; } if (set_extent) { error = xwimp_set_extent(sslcert_window->pane, &(info.extent)); if (error) { ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); return; } } error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), sslcert_window->window, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_YORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_LS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_RS_EDGE_SHIFT); if (error) { ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); ro_gui_cert_release_window(sslcert_window); return; } ro_treeview_set_origin(sslcert_window->tv, 0, 0); }
/** * Reflow a text area from the given line onwards * * \param ta Text area to reflow * \param line Line number to begin reflow on */ void ro_textarea_reflow(struct text_area *ta, unsigned int line) { rufl_code code; char *text; unsigned int len; size_t b_off; int x; char *space; unsigned int line_count = 0; os_box extent; os_error *error; /** \todo pay attention to line parameter */ /** \todo create horizontal scrollbar if needed */ ta->line_count = 0; if (!ta->lines) { ta->lines = malloc(LINE_CHUNK_SIZE * sizeof(struct line_info)); if (!ta->lines) { LOG(("malloc failed")); return; } } if (!(ta->flags & TEXTAREA_MULTILINE)) { /* Single line */ ta->lines[line_count].b_start = 0; ta->lines[line_count++].b_length = ta->text_len - 1; ta->line_count = line_count; return; } for (len = ta->text_len - 1, text = ta->text; len > 0; len -= b_off, text += b_off) { code = rufl_split(ta->font_family, ta->font_style, ta->font_size, text, len, ta->vis_width - MARGIN_LEFT - MARGIN_RIGHT, &b_off, &x); if (code != rufl_OK) { if (code == rufl_FONT_MANAGER_ERROR) LOG(("rufl_x_to_offset: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess)); else LOG(("rufl_x_to_offset: 0x%x", code)); return; } if (line_count > 0 && line_count % LINE_CHUNK_SIZE == 0) { struct line_info *temp = realloc(ta->lines, (line_count + LINE_CHUNK_SIZE) * sizeof(struct line_info)); if (!temp) { LOG(("realloc failed")); return; } ta->lines = temp; } /* handle CR/LF */ for (space = text; space < text + b_off; space++) { if (*space == '\r' || *space == '\n') break; } if (space != text + b_off) { /* Found newline; use it */ ta->lines[line_count].b_start = text - ta->text; ta->lines[line_count++].b_length = space - text; /* CRLF / LFCR pair */ if (*space == '\r' && *(space + 1) == '\n') space++; else if (*space == '\n' && *(space + 1) == '\r') space++; b_off = space + 1 - text; if (len - b_off == 0) { /* reached end of input => add last line */ ta->lines[line_count].b_start = text + b_off - ta->text; ta->lines[line_count++].b_length = 0; } continue; } if (len - b_off > 0) { /* find last space (if any) */ for (space = text + b_off; space > text; space--) if (*space == ' ') break; if (space != text) b_off = space + 1 - text; } ta->lines[line_count].b_start = text - ta->text; ta->lines[line_count++].b_length = b_off; } ta->line_count = line_count; /* and now update extent */ extent.x0 = 0; extent.y1 = 0; extent.x1 = ta->vis_width; extent.y0 = -ta->line_height * line_count - ta->line_spacing; if (extent.y0 > (int)-ta->vis_height) /* haven't filled window yet */ return; error = xwimp_set_extent(ta->window, &extent); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); return; } /* Create vertical scrollbar if we don't already have one */ if (!ro_gui_wimp_check_window_furniture(ta->window, wimp_WINDOW_VSCROLL)) { wimp_window_state state; wimp_w parent; bits linkage; unsigned int vscroll_width; /* Save window parent & linkage flags */ state.w = ta->window; error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage); if (error) { LOG(("xwimp_get_window_state_and_nesting: 0x%x: %s", error->errnum, error->errmess)); return; } /* Now, attempt to create vertical scrollbar */ ro_gui_wimp_update_window_furniture(ta->window, wimp_WINDOW_VSCROLL, wimp_WINDOW_VSCROLL); /* Get new window state */ state.w = ta->window; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return; } /* Get scroll width */ vscroll_width = ro_get_vscroll_width(NULL); /* Shrink width by difference */ state.visible.x1 -= vscroll_width; /* and reopen window */ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), parent, linkage); if (error) { LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); return; } /* finally, update visible width */ ta->vis_width -= vscroll_width; /* Now we've done that, we have to reflow the text area */ ro_textarea_reflow(ta, 0); } }
/** * Update the a text area following a change in the parent icon * * \param self Text area to update */ bool ro_textarea_update(uintptr_t self) { struct text_area *ta; wimp_window_state state; wimp_icon_state istate; os_box extent; os_error *error; ta = (struct text_area *)self; if (!ta || ta->magic != MAGIC) return false; state.w = ta->parent; error = xwimp_get_window_state(&state); if (error) { LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return false; } istate.w = ta->parent; istate.i = ta->icon; error = xwimp_get_icon_state(&istate); if (error) { LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); return false; } state.w = ta->window; state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 - ro_get_vscroll_width(ta->window) - state.xscroll; state.visible.x0 += istate.icon.extent.x0 + 2 - state.xscroll; state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 + ro_get_hscroll_height(ta->window) - state.yscroll; state.visible.y1 += istate.icon.extent.y1 - 2 - state.yscroll; if (ta->flags & TEXTAREA_READONLY) { state.visible.x0 += 2; state.visible.x1 -= 4; state.visible.y0 += 2; state.visible.y1 -= 4; } /* set our width/height */ ta->vis_width = state.visible.x1 - state.visible.x0; ta->vis_height = state.visible.y1 - state.visible.y0; /* Set window extent to visible area */ extent.x0 = 0; extent.y0 = -ta->vis_height; extent.x1 = ta->vis_width; extent.y1 = 0; error = xwimp_set_extent(ta->window, &extent); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); return false; } /* and open the window */ error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), ta->parent, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_YORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_LS_EDGE_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_RS_EDGE_SHIFT); if (error) { LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); return false; } /* reflow the text */ ro_textarea_reflow(ta, 0); return true; }
void ro_gui_history_redraw(wimp_draw *redraw) { osbool more; os_error *error; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &ro_plotters }; error = xwimp_redraw_window(redraw, &more); if (error) { LOG(("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } while (more) { ro_plot_origin_x = redraw->box.x0 - redraw->xscroll; ro_plot_origin_y = redraw->box.y1 - redraw->yscroll; history_redraw(history_current, &ctx); error = xwimp_get_rectangle(redraw, &more); if (error) { LOG(("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } } } /** * Handle mouse movements over the history window. */ void ro_gui_history_mouse_at(wimp_pointer *pointer) { int x, y; int width; const char *url; wimp_window_state state; wimp_icon_state ic; os_box box = {0, 0, 0, 0}; os_error *error; /* If the mouse hasn't moved, or if we don't want tooltips, exit */ if ((mouse_x == pointer->pos.x && mouse_y == pointer->pos.y) || !nsoption_bool(history_tooltip)) return; /* Update mouse position */ mouse_x = pointer->pos.x; mouse_y = pointer->pos.y; /* Find history tree entry under mouse */ state.w = history_window; 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; } x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2; y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2; url = history_position_url(history_current, x, y); if (!url) { /* not over a tree entry => close tooltip window. */ error = xwimp_close_window(dialog_tooltip); if (error) { LOG(("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } return; } /* get width of string */ error = xwimptextop_string_width(url, strlen(url) > 256 ? 256 : strlen(url), &width); if (error) { LOG(("xwimptextop_string_width: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } ro_gui_set_icon_string(dialog_tooltip, 0, url, true); /* resize icon appropriately */ ic.w = dialog_tooltip; ic.i = 0; error = xwimp_get_icon_state(&ic); if (error) { LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } error = xwimp_resize_icon(dialog_tooltip, 0, ic.icon.extent.x0, ic.icon.extent.y0, width + 16, ic.icon.extent.y1); if (error) { LOG(("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } state.w = dialog_tooltip; 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; } /* update window extent */ box.x1 = width + 16; box.y0 = -36; error = xwimp_set_extent(dialog_tooltip, &box); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* set visible area */ state.visible.x0 = pointer->pos.x + 24; state.visible.y0 = pointer->pos.y - 22 - 36; state.visible.x1 = pointer->pos.x + 24 + width + 16; state.visible.y1 = pointer->pos.y - 22; state.next = wimp_TOP; /* open window */ error = xwimp_open_window(PTR_WIMP_OPEN(&state)); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } }
void ro_gui_history_mouse_at(wimp_pointer *pointer, void *data) { int x, y; int width; const char *url; wimp_window_state state; wimp_icon_state ic; os_box box = {0, 0, 0, 0}; os_error *error; LOG(("Mouse at...")); /* If the mouse hasn't moved, or if we don't want tooltips, exit */ if ((mouse_x == pointer->pos.x && mouse_y == pointer->pos.y) || !nsoption_bool(history_tooltip)) return; /* Update mouse position */ mouse_x = pointer->pos.x; mouse_y = pointer->pos.y; /* Find history tree entry under mouse */ state.w = history_window; 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; } x = (pointer->pos.x - (state.visible.x0 - state.xscroll)) / 2; y = -(pointer->pos.y - (state.visible.y1 - state.yscroll)) / 2; url = history_position_url(history_current, x, y); if (!url) { /* not over a tree entry => close tooltip window. */ error = xwimp_close_window(dialog_tooltip); if (error) { LOG(("xwimp_close_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } return; } /* get width of string */ error = xwimptextop_string_width(url, strlen(url) > 256 ? 256 : strlen(url), &width); if (error) { LOG(("xwimptextop_string_width: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } ro_gui_set_icon_string(dialog_tooltip, 0, url, true); /* resize icon appropriately */ ic.w = dialog_tooltip; ic.i = 0; error = xwimp_get_icon_state(&ic); if (error) { LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } error = xwimp_resize_icon(dialog_tooltip, 0, ic.icon.extent.x0, ic.icon.extent.y0, width + 16, ic.icon.extent.y1); if (error) { LOG(("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } state.w = dialog_tooltip; 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; } /* update window extent */ box.x1 = width + 16; box.y0 = -36; error = xwimp_set_extent(dialog_tooltip, &box); if (error) { LOG(("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } /* set visible area */ state.visible.x0 = pointer->pos.x + 24; state.visible.y0 = pointer->pos.y - 22 - 36; state.visible.x1 = pointer->pos.x + 24 + width + 16; state.visible.y1 = pointer->pos.y - 22; state.next = wimp_TOP; /* open window */ error = xwimp_open_window(PTR_WIMP_OPEN(&state)); if (error) { LOG(("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); return; } }