Store URLs explicitly in URL database for faster access.

Iteration callbacks now passed url_data struct to remove need to look up

svn path=/trunk/netsurf/; revision=2522
This commit is contained in:
John Mark Bell 2006-04-11 02:39:55 +00:00
parent c3da525dbc
commit e0ba508992
5 changed files with 161 additions and 289 deletions

View File

@ -119,6 +119,7 @@ struct url_internal_data {
}; };
struct path_data { struct path_data {
char *url; /**< Full URL */
char *scheme; /**< URL scheme for data */ char *scheme; /**< URL scheme for data */
unsigned int port; /**< Port number for data */ unsigned int port; /**< Port number for data */
char *segment; /**< Path segment for this node */ char *segment; /**< Path segment for this node */
@ -126,7 +127,7 @@ struct path_data {
char **fragment; /**< Array of fragments */ char **fragment; /**< Array of fragments */
struct bitmap *thumb; /**< Thumbnail image of resource */ struct bitmap *thumb; /**< Thumbnail image of resource */
struct url_internal_data url; /**< URL data for resource */ struct url_internal_data urld; /**< URL data for resource */
struct auth_data auth; /**< Authentication data for resource */ struct auth_data auth; /**< Authentication data for resource */
struct cookie *cookies; /**< Cookies associated with resource */ struct cookie *cookies; /**< Cookies associated with resource */
@ -173,17 +174,17 @@ static void urldb_write_paths(const struct path_data *parent,
/* Iteration */ /* Iteration */
static bool urldb_iterate_partial_host(struct search_node *root, static bool urldb_iterate_partial_host(struct search_node *root,
const char *prefix, bool (*callback)(const char *url)); const char *prefix, bool (*callback)(const char *url,
const struct url_data *data));
static bool urldb_iterate_partial_path(const struct path_data *parent, static bool urldb_iterate_partial_path(const struct path_data *parent,
const char *host, const char *prefix, const char *prefix, bool (*callback)(const char *url,
char **path, int *path_alloc, int *path_used, const struct url_data *data));
bool (*callback)(const char *url));
static bool urldb_iterate_entries_host(struct search_node *parent, static bool urldb_iterate_entries_host(struct search_node *parent,
bool (*callback)(const char *url)); bool (*callback)(const char *url,
static bool urldb_iterate_entries_path(const char *host, char **path, const struct url_data *data));
int *path_alloc, int *path_used, static bool urldb_iterate_entries_path(const struct path_data *parent,
const struct path_data *parent, bool (*callback)(const char *url,
bool (*callback)(const char *url)); const struct url_data *data));
/* Insertion */ /* Insertion */
static struct host_part *urldb_add_host_node(const char *part, static struct host_part *urldb_add_host_node(const char *part,
@ -194,7 +195,8 @@ static struct path_data *urldb_add_path_node(const char *scheme,
struct path_data *parent); struct path_data *parent);
static struct path_data *urldb_add_path(const char *scheme, static struct path_data *urldb_add_path(const char *scheme,
unsigned int port, const struct host_part *host, unsigned int port, const struct host_part *host,
const char *path, const char *fragment); const char *path, const char *fragment,
const char *url_no_frag);
static int urldb_add_path_fragment_cmp(const void *a, const void *b); static int urldb_add_path_fragment_cmp(const void *a, const void *b);
static struct path_data *urldb_add_path_fragment(struct path_data *segment, static struct path_data *urldb_add_path_fragment(struct path_data *segment,
const char *fragment); const char *fragment);
@ -251,6 +253,7 @@ void urldb_load(const char *filename)
{ {
#define MAXIMUM_URL_LENGTH 4096 #define MAXIMUM_URL_LENGTH 4096
char s[MAXIMUM_URL_LENGTH]; char s[MAXIMUM_URL_LENGTH];
char host[256];
struct host_part *h; struct host_part *h;
int urls; int urls;
int i; int i;
@ -280,10 +283,10 @@ void urldb_load(const char *filename)
return; return;
} }
while (fgets(s, MAXIMUM_URL_LENGTH, fp)) { while (fgets(host, sizeof host, fp)) {
/* get the hostname */ /* get the hostname */
length = strlen(s) - 1; length = strlen(host) - 1;
s[length] = '\0'; host[length] = '\0';
/* skip data that has ended up with a host of '' */ /* skip data that has ended up with a host of '' */
if (length == 0) { if (length == 0) {
@ -297,7 +300,7 @@ void urldb_load(const char *filename)
continue; continue;
} }
h = urldb_add_host(s); h = urldb_add_host(host);
if (!h) if (!h)
die("Memory exhausted whilst loading URL file"); die("Memory exhausted whilst loading URL file");
@ -318,7 +321,8 @@ void urldb_load(const char *filename)
urldb_add_url(s); urldb_add_url(s);
p = urldb_find_url(s); p = urldb_find_url(s);
} else { } else {
char scheme[64]; char scheme[64], ports[6];
char url[64 + 3 + 256 + 6 + 4096 + 1];
unsigned int port; unsigned int port;
if (!fgets(scheme, sizeof scheme, fp)) if (!fgets(scheme, sizeof scheme, fp))
@ -326,32 +330,40 @@ void urldb_load(const char *filename)
length = strlen(scheme) - 1; length = strlen(scheme) - 1;
scheme[length] = '\0'; scheme[length] = '\0';
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(ports, sizeof ports, fp))
break; break;
port = atoi(s); length = strlen(ports) - 1;
ports[length] = '\0';
port = atoi(ports);
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
break; break;
length = strlen(s) - 1; length = strlen(s) - 1;
s[length] = '\0'; s[length] = '\0';
p = urldb_add_path(scheme, port, h, s, NULL); sprintf(url, "%s://%s%s%s%s", scheme, host,
(port ? ":" : ""),
(port ? ports : ""),
s);
p = urldb_add_path(scheme, port, h, s, NULL,
url);
} }
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
break; break;
if (p) if (p)
p->url.visits = (unsigned int)atoi(s); p->urld.visits = (unsigned int)atoi(s);
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
break; break;
if (p) if (p)
p->url.last_visit = (time_t)atoi(s); p->urld.last_visit = (time_t)atoi(s);
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
break; break;
if (p) if (p)
p->url.type = (content_type)atoi(s); p->urld.type = (content_type)atoi(s);
if (!fgets(s, MAXIMUM_URL_LENGTH, fp)) if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
break; break;
@ -371,9 +383,9 @@ void urldb_load(const char *filename)
length = strlen(s) - 1; length = strlen(s) - 1;
if (p && length > 0) { if (p && length > 0) {
s[length] = '\0'; s[length] = '\0';
p->url.title = malloc(length + 1); p->urld.title = malloc(length + 1);
if (p->url.title) if (p->urld.title)
memcpy(p->url.title, s, length + 1); memcpy(p->urld.title, s, length + 1);
} }
} }
} }
@ -476,8 +488,8 @@ void urldb_count_urls(const struct path_data *root, time_t expiry,
const struct path_data *p; const struct path_data *p;
if (!root->children) { if (!root->children) {
if ((root->url.last_visit > expiry) && if ((root->urld.last_visit > expiry) &&
(root->url.visits > 0)) (root->urld.visits > 0))
(*count)++; (*count)++;
} }
@ -506,8 +518,8 @@ void urldb_write_paths(const struct path_data *parent, const char *host,
if (!parent->children) { if (!parent->children) {
/* leaf node */ /* leaf node */
if (!((parent->url.last_visit > expiry) && if (!((parent->urld.last_visit > expiry) &&
(parent->url.visits > 0))) (parent->urld.visits > 0)))
/* expired */ /* expired */
return; return;
@ -522,9 +534,9 @@ void urldb_write_paths(const struct path_data *parent, const char *host,
/** \todo handle fragments? */ /** \todo handle fragments? */
fprintf(fp, "%i\n%i\n%i\n", parent->url.visits, fprintf(fp, "%i\n%i\n%i\n", parent->urld.visits,
(int)parent->url.last_visit, (int)parent->urld.last_visit,
(int)parent->url.type); (int)parent->urld.type);
#ifdef riscos #ifdef riscos
if (parent->thumb) if (parent->thumb)
@ -535,14 +547,14 @@ void urldb_write_paths(const struct path_data *parent, const char *host,
fprintf(fp, "\n"); fprintf(fp, "\n");
#endif #endif
if (parent->url.title) { if (parent->urld.title) {
char *s = parent->url.title; char *s = parent->urld.title;
for (i = 0; s[i] != '\0'; i++) for (i = 0; s[i] != '\0'; i++)
if (s[i] < 32) if (s[i] < 32)
s[i] = ' '; s[i] = ' ';
for (--i; ((i > 0) && (s[i] == ' ')); i--) for (--i; ((i > 0) && (s[i] == ' ')); i--)
s[i] = '\0'; s[i] = '\0';
fprintf(fp, "%s\n", parent->url.title); fprintf(fp, "%s\n", parent->urld.title);
} else } else
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
@ -586,30 +598,42 @@ bool urldb_add_url(const char *url)
{ {
struct host_part *h; struct host_part *h;
struct path_data *p; struct path_data *p;
char *fragment = NULL, *host, *plq, *scheme, *colon; char *fragment = NULL, *host, *plq, *scheme, *colon, *urlt;
unsigned short port; unsigned short port;
url_func_result ret; url_func_result ret;
assert(url); assert(url);
/** \todo consider file: URLs */ /** \todo consider file: URLs */
host = strchr(url, '#'); urlt = strdup(url);
if (host) { if (!urlt)
fragment = strdup(host+1);
if (!fragment)
return false; return false;
host = strchr(urlt, '#');
if (host) {
*host = '\0';
fragment = strdup(host+1);
if (!fragment) {
free(urlt);
return false;
}
} }
/* extract host */ /* extract host */
ret = url_host(url, &host); ret = url_host(url, &host);
if (ret != URL_FUNC_OK) if (ret != URL_FUNC_OK) {
free(fragment);
free(urlt);
return false; return false;
}
/* extract path, leafname, query */ /* extract path, leafname, query */
ret = url_plq(url, &plq); ret = url_plq(url, &plq);
if (ret != URL_FUNC_OK) { if (ret != URL_FUNC_OK) {
free(host); free(host);
free(fragment); free(fragment);
free(urlt);
return false; return false;
} }
@ -619,6 +643,7 @@ bool urldb_add_url(const char *url)
free(plq); free(plq);
free(host); free(host);
free(fragment); free(fragment);
free(urlt);
return false; return false;
} }
@ -637,18 +662,22 @@ bool urldb_add_url(const char *url)
free(plq); free(plq);
free(host); free(host);
free(fragment); free(fragment);
free(urlt);
return false; return false;
} }
/* Get path entry */ /* Get path entry */
p = urldb_add_path(scheme, port, h, plq, fragment); p = urldb_add_path(scheme, port, h, plq, fragment, urlt);
if (!p) { if (!p) {
return false;
}
free(scheme); free(scheme);
free(plq); free(plq);
free(host); free(host);
free(fragment); free(fragment);
return false; free(urlt);
}
return true; return true;
} }
@ -674,8 +703,8 @@ void urldb_set_url_title(const char *url, const char *title)
if (!temp) if (!temp)
return; return;
free(p->url.title); free(p->urld.title);
p->url.title = temp; p->urld.title = temp;
} }
/** /**
@ -694,7 +723,7 @@ void urldb_set_url_content_type(const char *url, content_type type)
if (!p) if (!p)
return; return;
p->url.type = type; p->urld.type = type;
} }
/** /**
@ -712,8 +741,8 @@ void urldb_update_url_visit_data(const char *url)
if (!p) if (!p)
return; return;
p->url.last_visit = time(NULL); p->urld.last_visit = time(NULL);
p->url.visits++; p->urld.visits++;
} }
/** /**
@ -731,8 +760,8 @@ void urldb_reset_url_visit_data(const char *url)
if (!p) if (!p)
return; return;
p->url.last_visit = (time_t)0; p->urld.last_visit = (time_t)0;
p->url.visits = 0; p->urld.visits = 0;
} }
@ -752,7 +781,7 @@ const struct url_data *urldb_get_url_data(const char *url)
if (!p) if (!p)
return NULL; return NULL;
return (struct url_data *)&p->url; return (struct url_data *)&p->urld;
} }
/** /**
@ -937,7 +966,8 @@ const struct bitmap *urldb_get_thumbnail(const char *url)
* \param callback Callback function * \param callback Callback function
*/ */
void urldb_iterate_partial(const char *prefix, void urldb_iterate_partial(const char *prefix,
bool (*callback)(const char *url)) bool (*callback)(const char *url,
const struct url_data *data))
{ {
char host[256]; char host[256];
char buf[260]; /* max domain + "www." */ char buf[260]; /* max domain + "www." */
@ -959,8 +989,7 @@ void urldb_iterate_partial(const char *prefix,
if (slash) { if (slash) {
/* if there's a slash in the input, then we can /* if there's a slash in the input, then we can
* assume that we're looking for a path */ * assume that we're looking for a path */
char *path, *domain = host; char *domain = host;
int path_alloc = 64, path_used = 2;
snprintf(host, sizeof host, "%.*s", slash - prefix, prefix); snprintf(host, sizeof host, "%.*s", slash - prefix, prefix);
@ -984,17 +1013,8 @@ void urldb_iterate_partial(const char *prefix,
return; return;
} }
path = malloc(path_alloc); urldb_iterate_partial_path(&h->paths, slash + 1, callback);
if (!path)
return;
path[0] = '/';
path[1] = '\0';
urldb_iterate_partial_path(&h->paths, domain, slash + 1,
&path, &path_alloc, &path_used, callback);
free(path);
} else { } else {
int len = strlen(prefix); int len = strlen(prefix);
@ -1026,13 +1046,10 @@ void urldb_iterate_partial(const char *prefix,
* \return true to continue, false otherwise * \return true to continue, false otherwise
*/ */
bool urldb_iterate_partial_host(struct search_node *root, const char *prefix, bool urldb_iterate_partial_host(struct search_node *root, const char *prefix,
bool (*callback)(const char *url)) bool (*callback)(const char *url,
const struct url_data *data))
{ {
int c; int c;
const struct host_part *h;
char domain[256], *p, *end;
char *path;
int path_alloc = 64, path_used = 2;
assert(root && prefix && callback); assert(root && prefix && callback);
@ -1055,34 +1072,12 @@ bool urldb_iterate_partial_host(struct search_node *root, const char *prefix,
callback)) callback))
return false; return false;
/* Generate host string */
for (h = root->data, p = domain,
end = domain + sizeof domain;
h && h != &db_root && p < end;
h = h->parent) {
int written = snprintf(p, end - p, "%s%s", h->part,
(h->parent && h->parent->parent) ? "." : "");
if (written < 0)
return false;
p += written;
}
path = malloc(path_alloc);
if (!path)
return false;
path[0] = '/';
path[1] = '\0';
/* and extract all paths attached to this host */ /* and extract all paths attached to this host */
if (!urldb_iterate_entries_path(domain, &path, &path_alloc, if (!urldb_iterate_entries_path(&root->data->paths,
&path_used, &root->data->paths, callback)) { callback)) {
free(path);
return false; return false;
} }
free(path);
if (!urldb_iterate_partial_host(root->right, prefix, if (!urldb_iterate_partial_host(root->right, prefix,
callback)) callback))
return false; return false;
@ -1095,22 +1090,16 @@ bool urldb_iterate_partial_host(struct search_node *root, const char *prefix,
* Partial path iterator (internal) * Partial path iterator (internal)
* *
* \param parent Root of (sub)tree to traverse * \param parent Root of (sub)tree to traverse
* \param host Host string
* \param prefix Prefix to match * \param prefix Prefix to match
* \param path The built path up to this point
* \param path_alloc Allocated size of path
* \param path_used Used size of path
* \param callback Callback function * \param callback Callback function
* \return true to continue, false otherwise * \return true to continue, false otherwise
*/ */
bool urldb_iterate_partial_path(const struct path_data *parent, bool urldb_iterate_partial_path(const struct path_data *parent,
const char *host, const char *prefix, const char *prefix, bool (*callback)(const char *url,
char **path, int *path_alloc, int *path_used, const struct url_data *data))
bool (*callback)(const char *url))
{ {
const struct path_data *p; const struct path_data *p;
const char *slash, *end = prefix + strlen(prefix); const char *slash, *end = prefix + strlen(prefix);
int pused = *path_used;
int c; int c;
slash = strchr(prefix, '/'); slash = strchr(prefix, '/');
@ -1130,41 +1119,17 @@ bool urldb_iterate_partial_path(const struct path_data *parent,
break; break;
/* prefix matches so far */ /* prefix matches so far */
int len = *path_used + strlen(p->segment) + 1;
if (*path_alloc < len) {
char *temp = realloc(*path,
(len > 64) ? len : *path_alloc + 64);
if (!temp)
return false;
*path = temp;
*path_alloc = (len > 64) ? len : *path_alloc + 64;
}
strcat(*path, p->segment);
if (p->children)
strcat(*path, "/");
else
len -= 1;
*path_used = len;
if (slash == end) { if (slash == end) {
/* we've run out of prefix, so all /* we've run out of prefix, so all
* paths below this one match */ * paths below this one match */
if (!urldb_iterate_entries_path(host, path, if (!urldb_iterate_entries_path(p, callback))
path_alloc, path_used, p, callback))
return false; return false;
} else { } else {
/* more prefix to go => recurse */ /* more prefix to go => recurse */
if (!urldb_iterate_partial_path(p, host, slash + 1, if (!urldb_iterate_partial_path(p, slash + 1,
path, path_alloc, path_used,
callback)) callback))
return false; return false;
} }
/* restore path to that from input for next child */
*path_used = pused;
(*path)[pused - 1] = '\0';
} }
return true; return true;
@ -1175,7 +1140,8 @@ bool urldb_iterate_partial_path(const struct path_data *parent,
* *
* \param callback Function to callback for each entry * \param callback Function to callback for each entry
*/ */
void urldb_iterate_entries(bool (*callback)(const char *url)) void urldb_iterate_entries(bool (*callback)(const char *url,
const struct url_data *data))
{ {
int i; int i;
@ -1196,43 +1162,19 @@ void urldb_iterate_entries(bool (*callback)(const char *url))
* \return true to continue, false otherwise * \return true to continue, false otherwise
*/ */
bool urldb_iterate_entries_host(struct search_node *parent, bool urldb_iterate_entries_host(struct search_node *parent,
bool (*callback)(const char *url)) bool (*callback)(const char *url,
const struct url_data *data))
{ {
char domain[256], *p, *end;
const struct host_part *h;
char *path;
int path_alloc = 64, path_used = 2;
if (parent == &empty) if (parent == &empty)
return true; return true;
if (!urldb_iterate_entries_host(parent->left, callback)) if (!urldb_iterate_entries_host(parent->left, callback))
return false; return false;
for (h = parent->data, p = domain, end = domain + sizeof domain; if (!urldb_iterate_entries_path(&parent->data->paths, callback)) {
h && h != &db_root && p < end; h = h->parent) {
int written = snprintf(p, end - p, "%s%s", h->part,
(h->parent && h->parent->parent) ? "." : "");
if (written < 0)
return false;
p += written;
}
path = malloc(path_alloc);
if (!path)
return false;
path[0] = '/';
path[1] = '\0';
if (!urldb_iterate_entries_path(domain, &path, &path_alloc,
&path_used, &parent->data->paths, callback)) {
free(path);
return false; return false;
} }
free(path);
if (!urldb_iterate_entries_host(parent->right, callback)) if (!urldb_iterate_entries_host(parent->right, callback))
return false; return false;
@ -1242,92 +1184,31 @@ bool urldb_iterate_entries_host(struct search_node *parent,
/** /**
* Path data iterator (internal) * Path data iterator (internal)
* *
* \param host Host component of output URI
* \param path The built path up to this point
* \param path_alloc Allocated size of path
* \param path_used Used size of path
* \param parent Root of subtree to iterate over * \param parent Root of subtree to iterate over
* \param callback Callback function to call * \param callback Callback function to call
* \return true to continue, false otherwise * \return true to continue, false otherwise
*/ */
bool urldb_iterate_entries_path(const char *host, char **path, bool urldb_iterate_entries_path(const struct path_data *parent,
int *path_alloc, int *path_used, bool (*callback)(const char *url,
const struct path_data *parent, const struct url_data *data))
bool (*callback)(const char *url))
{ {
const struct path_data *p; const struct path_data *p;
int pused = *path_used;
if (!parent->children) { if (!parent->children) {
/* leaf node */ /* leaf node */
int schemelen = strlen(parent->scheme);
int hostlen = strlen(host);
int prefixlen = schemelen + 3 /* :// */ +
hostlen + 6 /* :NNNNN */;
static char *url;
static int url_alloc;
int written;
if (url_alloc < *path_used + prefixlen + 2) { assert(parent->url);
char *temp = realloc(url, *path_used + prefixlen + 2);
if (!temp)
return false;
url = temp;
url_alloc = *path_used + prefixlen + 2;
}
written = sprintf(url, "%s://%s", parent->scheme, host);
if (written < 0) {
return false;
}
if (parent->port) {
written = sprintf(url + schemelen + 3 + hostlen,
":%d", parent->port);
if (written < 0) {
return false;
}
written += schemelen + 3 + hostlen;
}
written = sprintf(url + written, "%s", *path);
if (written < 0) {
return false;
}
/** \todo handle fragments? */ /** \todo handle fragments? */
if (!callback(url)) if (!callback(parent->url,
(const struct url_data *) &parent->urld))
return false; return false;
} }
for (p = parent->children; p; p = p->next) { for (p = parent->children; p; p = p->next) {
int len = *path_used + strlen(p->segment) + 1; if (!urldb_iterate_entries_path(p, callback))
if (*path_alloc < len) {
char *temp = realloc(*path,
(len > 64) ? len : *path_alloc + 64);
if (!temp)
return false; return false;
*path = temp;
*path_alloc = (len > 64) ? len : *path_alloc + 64;
}
strcat(*path, p->segment);
if (p->children) {
strcat(*path, "/");
} else {
len -= 1;
}
*path_used = len;
if (!urldb_iterate_entries_path(host, path, path_alloc,
path_used, p, callback))
return false;
/* restore path to its state on entry to this function */
*path_used = pused;
(*path)[pused - 1] = '\0';
} }
return true; return true;
@ -1540,17 +1421,18 @@ struct path_data *urldb_add_path_node(const char *scheme, unsigned int port,
* \param host Host tree node to attach to * \param host Host tree node to attach to
* \param path Absolute path to add * \param path Absolute path to add
* \param fragment URL fragment, or NULL * \param fragment URL fragment, or NULL
* \param url_no_frag URL, without fragment
* \return Pointer to leaf node, or NULL on memory exhaustion * \return Pointer to leaf node, or NULL on memory exhaustion
*/ */
struct path_data *urldb_add_path(const char *scheme, unsigned int port, struct path_data *urldb_add_path(const char *scheme, unsigned int port,
const struct host_part *host, const char *path, const struct host_part *host, const char *path,
const char *fragment) const char *fragment, const char *url_no_frag)
{ {
struct path_data *d, *e; struct path_data *d, *e;
char *buf; char *buf;
char *segment, *slash; char *segment, *slash;
assert(scheme && host && path); assert(scheme && host && path && url_no_frag);
d = (struct path_data *) &host->paths; d = (struct path_data *) &host->paths;
@ -1602,6 +1484,13 @@ struct path_data *urldb_add_path(const char *scheme, unsigned int port,
free(buf); free(buf);
if (d && !d->url) {
/* Insert URL */
d->url = strdup(url_no_frag);
if (!d->url)
return NULL;
}
return d; return d;
} }

View File

@ -54,10 +54,12 @@ const struct bitmap *urldb_get_thumbnail(const char *url);
/* URL completion */ /* URL completion */
void urldb_iterate_partial(const char *prefix, void urldb_iterate_partial(const char *prefix,
bool (*callback)(const char *url)); bool (*callback)(const char *url,
const struct url_data *data));
/* Iteration */ /* Iteration */
void urldb_iterate_entries(bool (*callback)(const char *url)); void urldb_iterate_entries(bool (*callback)(const char *url,
const struct url_data *data));
/* Debug */ /* Debug */
void urldb_dump(void); void urldb_dump(void);

View File

@ -894,7 +894,7 @@ void tree_delete_node(struct tree *tree, struct node *node, bool siblings) {
f = e->next; f = e->next;
if (e->text) { if (e->text) {
/* we don't free non-editable titles */ /* we don't free non-editable titles or URLs */
if (node->editable) if (node->editable)
free(e->text); free(e->text);
else { else {
@ -903,7 +903,8 @@ void tree_delete_node(struct tree *tree, struct node *node, bool siblings) {
urldb_reset_url_visit_data(e->text); urldb_reset_url_visit_data(e->text);
} }
if (e->data != TREE_ELEMENT_TITLE) if (e->data != TREE_ELEMENT_TITLE &&
e->data != TREE_ELEMENT_URL)
free(e->text); free(e->text);
} }
} }
@ -1033,7 +1034,7 @@ struct node *tree_create_URL_node(struct node *parent,
* edited and should never be freed. * edited and should never be freed.
* *
* \param parent the node to link to * \param parent the node to link to
* \param url the URL (copied) * \param url the URL
* \param data the URL data to use * \param data the URL data to use
* \return the node created, or NULL for failure * \return the node created, or NULL for failure
*/ */
@ -1043,16 +1044,12 @@ struct node *tree_create_URL_node_shared(struct node *parent,
struct node_element *element; struct node_element *element;
char *title; char *title;
assert(data); assert(url && data);
/* If title isn't set, set it to the URL */
if (!data->title)
urldb_set_url_title(url, url);
if (data->title) if (data->title)
title = data->title; title = data->title;
else else
return NULL; title = url;
node = tree_create_leaf_node(parent, title); node = tree_create_leaf_node(parent, title);
if (!node) if (!node)
return NULL; return NULL;
@ -1067,7 +1064,7 @@ struct node *tree_create_URL_node_shared(struct node *parent,
tree_create_node_element(node, TREE_ELEMENT_LAST_VISIT); tree_create_node_element(node, TREE_ELEMENT_LAST_VISIT);
element = tree_create_node_element(node, TREE_ELEMENT_URL); element = tree_create_node_element(node, TREE_ELEMENT_URL);
if (element) if (element)
element->text = strdup(url); element->text = url;
tree_update_URL_node(node, url, data); tree_update_URL_node(node, url, data);
tree_recalculate_node(node, false); tree_recalculate_node(node, false);

View File

@ -50,7 +50,8 @@ static void ro_gui_global_history_initialise_nodes(void);
static void ro_gui_global_history_initialise_node(const char *title, static void ro_gui_global_history_initialise_node(const char *title,
time_t base, int days_back); time_t base, int days_back);
static struct node *ro_gui_global_history_find(const char *url); static struct node *ro_gui_global_history_find(const char *url);
static bool global_history_iterate_callback(const char *url); static bool global_history_add_internal(const char *url,
const struct url_data *data);
/* The history window, toolbar and plot origins */ /* The history window, toolbar and plot origins */
static wimp_w global_history_window; static wimp_w global_history_window;
@ -119,23 +120,10 @@ void ro_gui_global_history_initialise(void)
} }
global_history_init = true; global_history_init = true;
urldb_iterate_entries(global_history_iterate_callback); urldb_iterate_entries(global_history_add_internal);
global_history_init = false; global_history_init = false;
} }
/**
* Callback for urldb_iterate_entries
*
* \param url The URL
* \return true to continue iteration, false otherwise
*/
bool global_history_iterate_callback(const char *url)
{
global_history_add(url);
return true;
}
/** /**
* Initialises the base nodes * Initialises the base nodes
*/ */
@ -267,19 +255,33 @@ int ro_gui_global_history_help(int x, int y)
*/ */
void global_history_add(const char *url) void global_history_add(const char *url)
{ {
int i, j;
const struct url_data *data; const struct url_data *data;
data = urldb_get_url_data(url);
if (!data)
return;
global_history_add_internal(url, data);
}
/**
* Internal routine to actually perform global history addition
*
* \param url The URL to add
* \param data URL data associated with URL
* \return true (for urldb_iterate_entries)
*/
bool global_history_add_internal(const char *url,
const struct url_data *data)
{
int i, j;
struct node *parent = NULL; struct node *parent = NULL;
struct node *link; struct node *link;
struct node *node; struct node *node;
bool before = false; bool before = false;
int visit_date; int visit_date;
assert(url); assert(url && data);
data = urldb_get_url_data(url);
if (!data)
return;
visit_date = data->last_visit; visit_date = data->last_visit;
@ -309,7 +311,7 @@ void global_history_add(const char *url)
/* the entry is too old to care about */ /* the entry is too old to care about */
if (!parent) if (!parent)
return; return true;
/* find any previous occurance */ /* find any previous occurance */
if (!global_history_init) { if (!global_history_init) {
@ -326,7 +328,7 @@ void global_history_add(const char *url)
node, false, true); node, false, true);
/* ro_gui_tree_scroll_visible(hotlist_tree, /* ro_gui_tree_scroll_visible(hotlist_tree,
&node->data); &node->data);
*/ return; */ return true;
} }
} }
@ -339,6 +341,8 @@ void global_history_add(const char *url)
tree_handle_node_changed(global_history_tree, node, tree_handle_node_changed(global_history_tree, node,
true, false); true, false);
} }
return true;
} }
/** /**
@ -359,7 +363,7 @@ struct node *ro_gui_global_history_find(const char *url)
node; node = node->next) { node; node = node->next) {
element = tree_find_element(node, element = tree_find_element(node,
TREE_ELEMENT_URL); TREE_ELEMENT_URL);
if ((element) && !strcmp(url, element->text)) if ((element) && (url == element->text))
return node; return node;
} }
} }

View File

@ -27,7 +27,7 @@
#define MAXIMUM_VISIBLE_LINES 7 #define MAXIMUM_VISIBLE_LINES 7
static char **url_complete_matches = NULL; static const char **url_complete_matches = NULL;
static int url_complete_matches_allocated = 0; static int url_complete_matches_allocated = 0;
static int url_complete_matches_available = 0; static int url_complete_matches_available = 0;
static char *url_complete_matched_string = NULL; static char *url_complete_matched_string = NULL;
@ -38,7 +38,7 @@ static bool url_complete_matches_reset = false;
static char *url_complete_original_url = NULL; static char *url_complete_original_url = NULL;
static bool url_complete_memory_exhausted = false; static bool url_complete_memory_exhausted = false;
static char *url_complete_redraw[MAXIMUM_VISIBLE_LINES]; static const char *url_complete_redraw[MAXIMUM_VISIBLE_LINES];
static char url_complete_icon_null[] = "\0"; static char url_complete_icon_null[] = "\0";
static char url_complete_icon_sprite[12]; static char url_complete_icon_sprite[12];
static wimp_icon url_complete_icon; static wimp_icon url_complete_icon;
@ -160,14 +160,7 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, int key)
free(url_complete_matched_string); free(url_complete_matched_string);
url_complete_matched_string = match_url; url_complete_matched_string = match_url;
url_complete_original_url = NULL; url_complete_original_url = NULL;
if (url_complete_matches) {
for (; url_complete_matches_available > 0;
url_complete_matches_available--)
free(url_complete_matches[
url_complete_matches_available - 1]);
} else {
url_complete_matches_available = 0; url_complete_matches_available = 0;
}
url_complete_matches_selection = -1; url_complete_matches_selection = -1;
url_complete_keypress_selection = -1; url_complete_keypress_selection = -1;
@ -338,17 +331,16 @@ bool ro_gui_url_complete_keypress(struct gui_window *g, int key)
*/ */
bool url_complete_callback(const char *url) bool url_complete_callback(const char *url)
{ {
char **array_extend; const char **array_extend;
char *temp;
url_complete_matches_available++; url_complete_matches_available++;
if (url_complete_matches_available > if (url_complete_matches_available >
url_complete_matches_allocated) { url_complete_matches_allocated) {
array_extend = (char **)realloc(url_complete_matches, array_extend = (const char **)realloc(url_complete_matches,
(url_complete_matches_allocated + 64) * (url_complete_matches_allocated + 64) *
sizeof(struct url_content *)); sizeof(char *));
if (!array_extend) { if (!array_extend) {
url_complete_memory_exhausted = true; url_complete_memory_exhausted = true;
return false; return false;
@ -357,13 +349,7 @@ bool url_complete_callback(const char *url)
url_complete_matches_allocated += 64; url_complete_matches_allocated += 64;
} }
temp = strdup(url); url_complete_matches[url_complete_matches_available - 1] = url;
if (!temp) {
url_complete_memory_exhausted = true;
return false;
}
url_complete_matches[url_complete_matches_available - 1] = temp;
return true; return true;
} }
@ -496,12 +482,6 @@ bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i)
currently_open = ((url_complete_parent) && currently_open = ((url_complete_parent) &&
(url_complete_matches_available > 0)); (url_complete_matches_available > 0));
if (url_complete_matches) {
for (; url_complete_matches_available > 0;
url_complete_matches_available--)
free(url_complete_matches[
url_complete_matches_available - 1]);
}
free(url_complete_matches); free(url_complete_matches);
free(url_complete_matched_string); free(url_complete_matched_string);
free(url_complete_original_url); free(url_complete_original_url);