void tree_update_URL_node(struct node *node, const char *url, const struct url_data *data) { struct node_element *element; char buffer[256]; assert(node); element = tree_find_element(node, TREE_ELEMENT_URL); if (!element) return; if (data) { /* node is linked, update */ assert(!node->editable); if (!data->title) urldb_set_url_title(url, url); if (!data->title) return; node->data.text = data->title; } else { /* node is not linked, find data */ assert(node->editable); data = urldb_get_url_data(element->text); if (!data) return; } /* not implemented yet if (element) { sprintf(buffer, "small_%.3x", ro_content_filetype_from_type(data->type)); if (ro_gui_wimp_sprite_exists(buffer)) tree_set_node_sprite(node, buffer, buffer); else tree_set_node_sprite(node, "small_xxx", "small_xxx"); } */ element = tree_find_element(node, TREE_ELEMENT_LAST_VISIT); if (element) { snprintf(buffer, 256, (char *)messages_get("TreeLast"), (data->last_visit > 0) ? ctime((time_t *)&data->last_visit) : (char *)messages_get("TreeUnknown")); if (data->last_visit > 0) buffer[strlen(buffer) - 1] = '\0'; free((void *)element->text); element->text = (char *)strdup(buffer); } element = tree_find_element(node, TREE_ELEMENT_VISITS); if (element) { snprintf(buffer, 256, (char *)messages_get("TreeVisits"), data->visits); free((void *)element->text); element->text = (char *)strdup(buffer); } }
/** * Callback to determine if a node is a linking element whose target has been * visited. * * \param pw HTML document * \param node DOM node * \param match Pointer to location to receive result * \return CSS_OK. * * \post \a match will contain true if the node matches and false otherwise. */ css_error node_is_visited(void *pw, void *node, bool *match) { nscss_select_ctx *ctx = pw; nsurl *url; nserror error; const struct url_data *data; dom_exception exc; dom_node *n = node; dom_string *s = NULL; *match = false; exc = dom_node_get_node_name(n, &s); if ((exc != DOM_NO_ERR) || (s == NULL)) { return CSS_NOMEM; } if (!dom_string_caseless_lwc_isequal(s, corestring_lwc_a)) { /* Can't be visited; not ancher element */ dom_string_unref(s); return CSS_OK; } /* Finished with node name string */ dom_string_unref(s); s = NULL; exc = dom_element_get_attribute(n, corestring_dom_href, &s); if ((exc != DOM_NO_ERR) || (s == NULL)) { /* Can't be visited; not got a URL */ return CSS_OK; } /* Make href absolute */ /* TODO: this duplicates what we do for box->href * should we put the absolute URL on the dom node? */ error = nsurl_join(ctx->base_url, dom_string_data(s), &url); /* Finished with href string */ dom_string_unref(s); if (error != NSERROR_OK) { /* Couldn't make nsurl object */ return CSS_NOMEM; } data = urldb_get_url_data(url); /* Visited if in the db and has * non-zero visit count */ if (data != NULL && data->visits > 0) *match = true; nsurl_unref(url); return CSS_OK; }
/** * Adds to the global history * * \param url The URL to add */ void global_history_add(const char *url) { const struct url_data *data; data = urldb_get_url_data(url); if (!data) return; global_history_add_internal(url, data); }
/** * Adds the currently viewed page to the hotlist at the given co-ordinates * \param url url of the page * \param x X cooridinate with respect to tree origin * \param y Y cooridinate with respect to tree origin */ void hotlist_add_page_xy(const char *url, int x, int y) { const struct url_data *data; struct node *link, *node; bool before; data = urldb_get_url_data(url); if (data == NULL) { urldb_add_url(url); urldb_set_url_persistence(url, true); data = urldb_get_url_data(url); } if (data != NULL) { link = tree_get_link_details(hotlist_tree, x, y, &before); node = tree_create_URL_node(NULL, NULL, url, NULL, hotlist_node_callback, NULL); tree_link_node(hotlist_tree, link, node, before); } }
void ami_new_bookmark(struct treeview_window *twin) { const struct url_data *data; struct Node *lbnode; struct node *treenode; char *url,*title; GetAttr(LISTBROWSER_SelectedNode,twin->gadgets[GID_TREEBROWSER],(ULONG *)&lbnode); if(lbnode) { GetListBrowserNodeAttrs(lbnode, LBNA_UserData,(ULONG *)&treenode, TAG_DONE); } else { treenode = twin->tree->root; } url = (char *)strdup("http://www.netsurf-browser.org"); data = urldb_get_url_data(url); if (!data) { urldb_add_url(url); urldb_set_url_persistence(url,true); data = urldb_get_url_data(url); } if (data) { title = data->title; tree_create_URL_node(treenode,url,data,title); ami_recreate_listbrowser(twin); } }
/** * Adds the currently viewed page to the hotlist */ void hotlist_add_page(const char *url) { const struct url_data *data; struct node *node, *parent; if (url == NULL) return; data = urldb_get_url_data(url); if (data == NULL) return; parent = tree_get_default_folder_node(hotlist_tree); node = tree_create_URL_node(hotlist_tree, parent, url, NULL, hotlist_node_callback, NULL); tree_update_URL_node(hotlist_tree, node, url, data); }
/* Exported interface, documented in global_history.h */ nserror global_history_add(nsurl *url) { const struct url_data *data; /* If we don't have a global history at the moment, just return OK */ if (gh_ctx.tree == NULL) return NSERROR_OK; data = urldb_get_url_data(url); if (data == NULL) { LOG("Can't add URL to history that's not present in urldb."); return NSERROR_BAD_PARAMETER; } global_history_add_entry(url, data); return NSERROR_OK; }
/** * Parse an entry represented as a li. * * \param li xmlNode for parsed li * \param directory directory to add this entry to */ static void tree_url_load_entry(xmlNode *li, struct tree *tree, struct node *directory, tree_node_user_callback callback, void *callback_data) { char *url1 = NULL; char *title = NULL; struct node *entry; xmlNode *xmlnode; const struct url_data *data; nsurl *url; nserror error; for (xmlnode = li->children; xmlnode; xmlnode = xmlnode->next) { /* The li must contain an "a" element */ if (xmlnode->type == XML_ELEMENT_NODE && strcmp((const char *)xmlnode->name, "a") == 0) { url1 = (char *)xmlGetProp(xmlnode, (const xmlChar *) "href"); title = (char *)xmlNodeGetContent(xmlnode); } } if ((url1 == NULL) || (title == NULL)) { warn_user("TreeLoadError", "(Missing <a> in <li> or " "memory exhausted.)"); return; } /* We're loading external input. * This may be garbage, so attempt to normalise via nsurl */ error = nsurl_create(url1, &url); if (error != NSERROR_OK) { LOG(("Failed normalising '%s'", url1)); warn_user("NoMemory", NULL); xmlFree(url1); xmlFree(title); return; } /* No longer need this */ xmlFree(url1); data = urldb_get_url_data(nsurl_access(url)); if (data == NULL) { /* No entry in database, so add one */ urldb_add_url(nsurl_access(url)); /* now attempt to get url data */ data = urldb_get_url_data(nsurl_access(url)); } if (data == NULL) { xmlFree(title); nsurl_unref(url); return; } /* Make this URL persistent */ urldb_set_url_persistence(nsurl_access(url), true); /* Force the title in the hotlist */ urldb_set_url_title(nsurl_access(url), title); entry = tree_create_URL_node(tree, directory, nsurl_access(url), title, callback, callback_data); if (entry == NULL) { /** \todo why isn't this fatal? */ warn_user("NoMemory", 0); } else { tree_update_URL_node(tree, entry, nsurl_access(url), data); } xmlFree(title); nsurl_unref(url); }
node_callback_resp tree_url_node_callback(void *user_data, struct node_msg_data *msg_data) { struct tree *tree; struct node_element *element; nsurl *nsurl; nserror error; const char *text; char *norm_text; const struct url_data *data; /** @todo memory leaks on non-shared folder deletion. */ switch (msg_data->msg) { case NODE_DELETE_ELEMENT_TXT: switch (msg_data->flag) { /* only history is using non-editable url * elements so only history deletion will run * this code */ case TREE_ELEMENT_URL: /* reset URL characteristics */ urldb_reset_url_visit_data( msg_data->data.text); return NODE_CALLBACK_HANDLED; case TREE_ELEMENT_TITLE: return NODE_CALLBACK_HANDLED; } break; case NODE_DELETE_ELEMENT_IMG: if (msg_data->flag == TREE_ELEMENT_THUMBNAIL || msg_data->flag == TREE_ELEMENT_TITLE) return NODE_CALLBACK_HANDLED; break; case NODE_LAUNCH: element = tree_node_find_element(msg_data->node, TREE_ELEMENT_URL, NULL); if (element != NULL) { text = tree_node_element_get_text(element); if (msg_data->flag == TREE_ELEMENT_LAUNCH_IN_TABS) { msg_data->data.bw = browser_window_create(text, msg_data->data.bw, 0, true, true); } else { browser_window_create(text, NULL, 0, true, false); } return NODE_CALLBACK_HANDLED; } break; case NODE_ELEMENT_EDIT_FINISHING: text = msg_data->data.text; if (msg_data->flag == TREE_ELEMENT_URL) { size_t len; error = nsurl_create(text, &nsurl); if (error != NSERROR_OK) { warn_user("NoMemory", 0); return NODE_CALLBACK_REJECT; } error = nsurl_get(nsurl, NSURL_WITH_FRAGMENT, &norm_text, &len); nsurl_unref(nsurl); if (error != NSERROR_OK) { warn_user("NoMemory", 0); return NODE_CALLBACK_REJECT; } msg_data->data.text = norm_text; data = urldb_get_url_data(norm_text); if (data == NULL) { urldb_add_url(norm_text); urldb_set_url_persistence(norm_text, true); data = urldb_get_url_data(norm_text); if (data == NULL) return NODE_CALLBACK_REJECT; } tree = user_data; tree_update_URL_node(tree, msg_data->node, norm_text, NULL); } else if (msg_data->flag == TREE_ELEMENT_TITLE) { while (isspace(*text)) text++; norm_text = strdup(text); if (norm_text == NULL) { LOG(("malloc failed")); warn_user("NoMemory", 0); return NODE_CALLBACK_REJECT; } /* don't allow zero length entry text, return false */ if (norm_text[0] == '\0') { warn_user("NoNameError", 0); msg_data->data.text = NULL; return NODE_CALLBACK_CONTINUE; } msg_data->data.text = norm_text; } return NODE_CALLBACK_HANDLED; default: break; } return NODE_CALLBACK_NOT_HANDLED; }
/** * Updates the node details for a URL node. * * \param node the node to update */ void tree_update_URL_node(struct tree *tree, struct node *node, const char *url, const struct url_data *data) { struct node_element *element; struct bitmap *bitmap = NULL; struct icon_entry *entry; char *text_cp; assert(node != NULL); element = tree_node_find_element(node, TREE_ELEMENT_URL, NULL); if (element == NULL) return; if (data != NULL) { if (data->title == NULL) urldb_set_url_title(url, url); if (data->title == NULL) return; element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL); text_cp = strdup(data->title); if (text_cp == NULL) { LOG(("malloc failed")); warn_user("NoMemory", 0); return; } tree_update_node_element(tree, element, text_cp, NULL); } else { data = urldb_get_url_data(url); if (data == NULL) return; } entry = icon_table; do { if (entry->type == data->type) { if (entry->icon != NULL) tree_set_node_icon(tree, node, entry->icon); break; } ++entry; } while (entry->type != CONTENT_HTML); /* update last visit text */ element = tree_node_find_element(node, TREE_ELEMENT_LAST_VISIT, element); tree_update_element_text(tree, element, messages_get_buff("TreeLast", (data->last_visit > 0) ? ctime((time_t *)&data->last_visit) : messages_get("TreeUnknown"))); /* update number of visits text */ element = tree_node_find_element(node, TREE_ELEMENT_VISITS, element); tree_update_element_text(tree, element, messages_get_buff("TreeVisits", data->visits)); /* update thumbnail */ element = tree_node_find_element(node, TREE_ELEMENT_THUMBNAIL, element); if (element != NULL) { bitmap = urldb_get_thumbnail(url); if (bitmap != NULL) { tree_update_node_element(tree, element, NULL, bitmap); } } }
void ro_gui_url_complete_redraw(wimp_draw *redraw) { osbool more; os_error *error; int line; const struct url_data *data; int type; /* initialise our icon */ url_complete_icon.flags = wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED | wimp_ICON_TEXT | wimp_ICON_FILLED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); url_complete_icon.extent.x0 = 50; url_complete_icon.extent.x1 = 16384; url_complete_icon.data.indirected_text.validation = url_complete_icon_null; url_complete_sprite.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_INDIRECTED | wimp_ICON_FILLED | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED; url_complete_sprite.extent.x0 = 0; url_complete_sprite.extent.x1 = 50; url_complete_sprite.data.indirected_text.text = url_complete_icon_null; url_complete_sprite.data.indirected_text.validation = url_complete_icon_sprite; url_complete_sprite.data.indirected_text.size = 1; /* no matches? no redraw */ if (!url_complete_matches) { LOG("Attempt to redraw with no matches made"); /* Fill is never used, so make it something obvious */ ro_gui_user_redraw(redraw, false, os_COLOUR_BLACK); return; } /* redraw */ more = wimp_redraw_window(redraw); while (more) { int first_line, last_line; int origin_y = redraw->box.y1 - redraw->yscroll; int clip_y0 = redraw->clip.y0 - origin_y; int clip_y1 = redraw->clip.y1 - origin_y; first_line = (-clip_y1) / 44; last_line = (-clip_y0 + 43) / 44; for (line = first_line; line < last_line; line++) { if (line == url_complete_matches_selection) url_complete_icon.flags |= wimp_ICON_SELECTED; else url_complete_icon.flags &= ~wimp_ICON_SELECTED; url_complete_icon.extent.y1 = -line * 44; url_complete_icon.extent.y0 = -(line + 1) * 44; url_complete_icon.data.indirected_text.text = (char *)nsurl_access( url_complete_matches[line]); url_complete_icon.data.indirected_text.size = nsurl_length( url_complete_matches[line]); error = xwimp_plot_icon(&url_complete_icon); if (error) { LOG("xwimp_plot_icon: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } data = urldb_get_url_data(url_complete_matches[line]); if (data) type = ro_content_filetype_from_type( data->type); else type = 0; sprintf(url_complete_icon_sprite, "Ssmall_%.3x", type); if (!ro_gui_wimp_sprite_exists( url_complete_icon_sprite + 1)) sprintf(url_complete_icon_sprite, "Ssmall_xxx"); url_complete_sprite.extent.y1 = -line * 44; url_complete_sprite.extent.y0 = -(line + 1) * 44; error = xwimp_plot_icon(&url_complete_sprite); if (error) { LOG("xwimp_plot_icon: 0x%x: %s", error->errnum, error->errmess); ro_warn_user("WimpError", error->errmess); } } more = wimp_get_rectangle(redraw); } }
/* exported interface documented in hotlist.h */ bool hotlist_initialise(struct tree *tree, const char *hotlist_path, const char* folder_icon_name) { struct node *node; const struct url_data *url_data; char *name; int hlst_loop; /* Either load or create a hotlist */ creating_node = false; folder_icon = tree_load_icon(folder_icon_name); tree_url_node_init(folder_icon_name); if (tree == NULL) return false; hotlist_tree = tree; hotlist_tree_root = tree_get_root(hotlist_tree); if (tree_urlfile_load(hotlist_path, hotlist_tree, hotlist_node_callback, NULL)) { return true; } /* failed to load hotlist file, use default list */ name = strdup("NetSurf"); if (name == NULL) { LOG(("malloc failed")); warn_user("NoMemory", 0); return false; } node = tree_create_folder_node(hotlist_tree, hotlist_tree_root, name, true, false, false); if (node == NULL) { free(name); return false; } tree_set_node_user_callback(node, hotlist_node_callback, NULL); tree_set_node_icon(hotlist_tree, node, folder_icon); for (hlst_loop = 0; hlst_loop != HOTLIST_ENTRIES_COUNT; hlst_loop++) { url_data = urldb_get_url_data(hotlist_default_entries[hlst_loop].url); if (url_data == NULL) { urldb_add_url(hotlist_default_entries[hlst_loop].url); urldb_set_url_persistence( hotlist_default_entries[hlst_loop].url, true); url_data = urldb_get_url_data( hotlist_default_entries[hlst_loop].url); } if (url_data != NULL) { tree_create_URL_node(hotlist_tree, node, hotlist_default_entries[hlst_loop].url, messages_get(hotlist_default_entries[hlst_loop].msg_key), hotlist_node_callback, NULL); tree_update_URL_node(hotlist_tree, node, hotlist_default_entries[hlst_loop].url, url_data); } } return true; }