1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
/*
* Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* URL Suggestion Menu (implementation).
*/
#include <assert.h>
#include "oslib/wimp.h"
#include "content/content_type.h"
#include "content/urldb.h"
#include "riscos/menus.h"
#include "riscos/url_suggest.h"
#include "utils/messages.h"
struct url_suggest_item {
const char *url; /*< The URL being stored. */
unsigned int weight; /*< A weight assigned to the URL. */
struct url_suggest_item *next; /*< The next URL in the list. */
};
static bool ro_gui_url_suggest_callback(const char *url,
const struct url_data *data);
static int suggest_entries;
static time_t suggest_time;
static struct url_suggest_item *suggest_list;
static wimp_MENU(URL_SUGGEST_MAX_URLS) url_suggest_menu_block;
wimp_menu *ro_gui_url_suggest_menu = (wimp_menu *) &url_suggest_menu_block;
/**
* Initialise the URL suggestion menu. This MUST be called before anything
* tries to use the URL menu.
*
* /return true if initialisation was OK; else false.
*/
bool ro_gui_url_suggest_init(void)
{
ro_gui_url_suggest_menu->title_data.indirected_text.text =
(char *) messages_get("URLSuggest");
ro_gui_menu_init_structure((wimp_menu *) ro_gui_url_suggest_menu,
URL_SUGGEST_MAX_URLS);
suggest_entries = 0;
return true;
}
/**
* Check if there is a URL suggestion menu available for use.
*
* \TODO -- Ideally this should be able to decide if there's a menu
* available without actually having to build it all.
*
* /return true if the menu has entries; else false.
*/
bool ro_gui_url_suggest_get_menu_available(void)
{
return ro_gui_url_suggest_prepare_menu();
}
/**
* Builds the URL suggestion menu. This is called by ro_gui_menu_create() when
* it is asked to display the url_suggest_menu.
*
* /return true if the menu has entries; else false.
*/
bool ro_gui_url_suggest_prepare_menu(void)
{
int i;
struct url_suggest_item *list, *next;
/* Fetch the URLs we want to include from URLdb. */
suggest_entries = 0;
suggest_list = NULL;
suggest_time = time(NULL);
urldb_iterate_entries(ro_gui_url_suggest_callback);
/* If any menu entries were found, put them into the menu. The list
* is in reverse order, last to first, so the menu is filled backwards.
* Entries from the list are freed as we go.
*/
assert(suggest_entries <= URL_SUGGEST_MAX_URLS);
if (suggest_entries > 0) {
i = suggest_entries;
list = suggest_list;
suggest_list = NULL;
while (list != NULL && i > 0) {
i--;
ro_gui_url_suggest_menu->entries[i].menu_flags = 0;
ro_gui_url_suggest_menu->
entries[i].data.indirected_text.text =
(char *) list->url;
ro_gui_url_suggest_menu->
entries[i].data.indirected_text.size =
strlen(list->url) + 1;
next = list->next;
free(list);
list = next;
}
assert(i == 0);
ro_gui_url_suggest_menu->entries[0].menu_flags |=
wimp_MENU_TITLE_INDIRECTED;
ro_gui_url_suggest_menu->
entries[suggest_entries - 1].menu_flags |=
wimp_MENU_LAST;
return true;
}
return false;
}
/**
* Callback function for urldb_iterate_entries
*
* \param url URL which matches
* \param data Data associated with URL
* \return true to continue iteration, false otherwise
*/
bool ro_gui_url_suggest_callback(const char *url, const struct url_data *data)
{
int count;
unsigned int weight;
struct url_suggest_item **list, *new, *old;
/* Ignore unvisited URLs, and those that don't apply to HTML or Text. */
if (data->visits <= 0 || (data->type != CONTENT_HTML &&
data->type != CONTENT_TEXTPLAIN))
return true;
/* Calculate a weight for the URL. */
weight = (suggest_time - data->last_visit) / data->visits;
/* Hunt through those URLs already found to see if we want to add
* this one. Smaller weights carry higher priority.
*
* The list is sorted into reverse order, so that lowest weight
* items are nearest the head. Therefore, items are dropped from
* the head, making things simpler.
*/
list = &suggest_list;
count = 0;
while (*list != NULL && weight < (*list)->weight) {
list = &((*list)->next);
count++;
}
if (count > 0 || suggest_entries < URL_SUGGEST_MAX_URLS) {
new = (struct url_suggest_item *)
malloc(sizeof(struct url_suggest_item));
if (new != NULL) {
suggest_entries++;
new->url = url;
new->weight = weight;
new->next = *list;
*list = new;
}
}
/* If adding the URL gave us too many menu items, drop the lowest
* priority ones until the list is the right length again.
*/
while (suggest_list != NULL && suggest_entries > URL_SUGGEST_MAX_URLS) {
old = suggest_list;
suggest_list = suggest_list->next;
free(old);
suggest_entries--;
}
return true;
}
/**
* Process a selection from the URL Suggest menu.
*
* \param *selection The menu selection.
* \return Pointer to the URL that was selected, or NULL for none.
*/
const char *ro_gui_url_suggest_get_selection(wimp_selection *selection)
{
const char *url = NULL;
if (selection->items[0] >= 0)
url = ro_gui_url_suggest_menu->entries[selection->items[0]].
data.indirected_text.text;
return url;
}
|