NetSurf
global_history.c
Go to the documentation of this file.
1/*
2 * Copyright 2012 - 2013 Michael Drake <tlsa@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20#include <stdlib.h>
21#include <string.h>
22#include <time.h>
23
24#include "utils/messages.h"
25#include "utils/utils.h"
26#include "utils/utf8.h"
27#include "utils/libdom.h"
28#include "utils/log.h"
29#include "utils/nsurl.h"
30#include "content/urldb.h"
31
33#include "desktop/treeview.h"
35
36#define N_DAYS 28
37#define N_SEC_PER_DAY (60 * 60 * 24)
38
51};
52
60};
61
65};
66
71 time_t today;
73 bool built;
74};
76
79
80 int slot;
82 time_t t;
86
88};
90
91
92/**
93 * Find an entry in the global history
94 *
95 * \param url The URL to find
96 * \return Pointer to history entry, or NULL if not found
97 */
99{
100 int i;
101 struct global_history_entry *e;
102
103 for (i = 0; i < N_DAYS; i++) {
104 e = gh_list[i];
105
106 while (e != NULL) {
107 if (nsurl_compare(e->url, url,
108 NSURL_COMPLETE) == true) {
109 /* Got a match */
110 return e;
111 }
112 e = e->next;
113 }
114
115 }
116
117 /* No match found */
118 return NULL;
119}
120
121
122/**
123 * Initialise the treeview directories
124 *
125 * \param f Ident for folder to create
126 * \return NSERROR_OK on success, appropriate error otherwise
127 */
129{
130 nserror err;
131 treeview_node *relation = NULL;
133 const char *label;
134 int i;
135
136 switch (f) {
137 case GH_TODAY:
138 label = "DateToday";
139 break;
140
141 case GH_YESTERDAY:
142 label = "DateYesterday";
143 break;
144
145 case GH_2_DAYS_AGO:
146 label = "Date2Days";
147 break;
148
149 case GH_3_DAYS_AGO:
150 label = "Date3Days";
151 break;
152
153 case GH_4_DAYS_AGO:
154 label = "Date4Days";
155 break;
156
157 case GH_5_DAYS_AGO:
158 label = "Date5Days";
159 break;
160
161 case GH_6_DAYS_AGO:
162 label = "Date6Days";
163 break;
164
165 case GH_LAST_WEEK:
166 label = "Date1Week";
167 break;
168
169 case GH_2_WEEKS_AGO:
170 label = "Date2Week";
171 break;
172
173 case GH_3_WEEKS_AGO:
174 label = "Date3Week";
175 break;
176
177 default:
179 }
180
181 label = messages_get(label);
182
183 for (i = f - 1; i >= 0; i--) {
184 if (gh_ctx.folders[i].folder != NULL) {
185 relation = gh_ctx.folders[i].folder;
187 break;
188 }
189 }
190
192 gh_ctx.folders[f].data.value = label;
193 gh_ctx.folders[f].data.value_len = strlen(label);
196 relation, rel,
197 &gh_ctx.folders[f].data,
198 &gh_ctx.folders[f],
202
203 return err;
204}
205
206
207/**
208 * Get the treeview folder for history entires in a particular slot
209 *
210 * \param parent Updated to parent folder.
211 * \param slot Global history slot of entry we want folder node for
212 * \return NSERROR_OK on success, appropriate error otherwise
213 */
216{
217 int folder_index;
218 struct global_history_folder *f;
219 nserror err;
220
221 if (slot < 7) {
222 folder_index = slot;
223
224 } else if (slot < 14) {
225 folder_index = GH_LAST_WEEK;
226
227 } else if (slot < 21) {
228 folder_index = GH_2_WEEKS_AGO;
229
230 } else if (slot < N_DAYS) {
231 folder_index = GH_3_WEEKS_AGO;
232
233 } else {
234 /* Slot value is invalid */
236 }
237
238 /* Get the folder */
239 f = &(gh_ctx.folders[folder_index]);
240
241 if (f->folder == NULL) {
242 err = global_history_create_dir(folder_index);
243 if (err != NSERROR_OK) {
244 *parent = NULL;
245 return err;
246 }
247 }
248
249 /* Return the parent treeview folder */
250 *parent = f->folder;
251 return NSERROR_OK;
252}
253
254
255/**
256 * Set a global history entry's data from the url_data.
257 *
258 * \param e Global history entry to set up
259 * \param data Data associated with entry's URL
260 * \return NSERROR_OK on success, appropriate error otherwise
261 */
263 struct global_history_entry *e,
264 const struct url_data *data)
265{
266 const char *title = (data->title != NULL) ?
267 data->title : messages_get("NoTitle");
268 char buffer[16];
269 struct tm *lvtime;
270 char *last_visited = NULL;
271 size_t len = 0;
272
274 e->data[GH_TITLE].value = strdup(title);
275 e->data[GH_TITLE].value_len = (e->data[GH_TITLE].value != NULL) ?
276 strlen(title) : 0;
277
279 e->data[GH_URL].value = nsurl_access(e->url);
281
282 if ((lvtime = localtime(&data->last_visit)) != NULL) {
283 const size_t lvsize = 256;
284 last_visited = malloc(lvsize);
285 if (last_visited != NULL) {
286 len = strftime(last_visited, lvsize,
287 "%a %b %e %H:%M:%S %Y", lvtime);
288 }
289 }
290
292 e->data[GH_LAST_VISIT].value = last_visited;
293 e->data[GH_LAST_VISIT].value_len = len;
294
295 len = snprintf(buffer, 16, "%u", data->visits);
296 if (len == 16) {
297 len--;
298 buffer[len] = '\0';
299 }
300
302 e->data[GH_VISITS].value = strdup(buffer);
303 e->data[GH_VISITS].value_len = len;
304
305 return NSERROR_OK;
306}
307
308/**
309 * Add a global history entry to the treeview
310 *
311 * \param e entry to add to treeview
312 * \param slot global history slot containing entry
313 * \return NSERROR_OK on success, or appropriate error otherwise
314 *
315 * It is assumed that the entry is unique (for its URL) in the global
316 * history table
317 */
319 int slot)
320{
321 nserror err;
322
325 if (err != NSERROR_OK) {
326 return err;
327 }
328
334 if (err != NSERROR_OK) {
335 return err;
336 }
337
338 return NSERROR_OK;
339}
340
341
342/**
343 * Add an entry to the global history (creates the entry).
344 *
345 * If the treeview has already been created, the entry will be added to the
346 * treeview. Otherwise, the entry will have to be added to the treeview later.
347 *
348 * When we first create the global history we create it without the treeview, to
349 * simplfy sorting the entries.
350 *
351 * \param url URL for entry to add to history
352 * \param slot Global history slot to contain history entry
353 * \param data URL data for the entry
354 * \param got_treeview Whether the treeview has been created already
355 * \return NSERROR_OK on success, or appropriate error otherwise
356 */
358 const struct url_data *data, bool got_treeview)
359{
360 nserror err;
361 struct global_history_entry *e;
362
363 /* Create new local history entry */
364 e = malloc(sizeof(struct global_history_entry));
365 if (e == NULL) {
366 return NSERROR_NOMEM;
367 }
368
369 e->user_delete = false;
370 e->slot = slot;
371 e->url = nsurl_ref(url);
372 e->t = data->last_visit;
373 e->entry = NULL;
374 e->next = NULL;
375 e->prev = NULL;
376
378 if (err != NSERROR_OK) {
379 return err;
380 }
381
382 if (gh_list[slot] == NULL) {
383 /* list empty */
384 gh_list[slot] = e;
385
386 } else if (gh_list[slot]->t < e->t) {
387 /* Insert at list head */
388 e->next = gh_list[slot];
389 gh_list[slot]->prev = e;
390 gh_list[slot] = e;
391 } else {
393 struct global_history_entry *curr = prev->next;
394 while (curr != NULL) {
395 if (curr->t < e->t) {
396 break;
397 }
398 prev = curr;
399 curr = curr->next;
400 }
401
402 /* insert after prev */
403 e->next = curr;
404 e->prev = prev;
405 prev->next = e;
406
407 if (curr != NULL)
408 curr->prev = e;
409 }
410
411 if (got_treeview) {
413 if (err != NSERROR_OK) {
414 return err;
415 }
416 }
417
418 return NSERROR_OK;
419}
420
421
422/**
423 * Delete a global history entry
424 *
425 * This does not delete the treeview node, rather it should only be called from
426 * the treeview node delete event message.
427 *
428 * \param e Entry to delete
429 */
431 struct global_history_entry *e)
432{
433 assert(e != NULL);
434 assert(e->entry == NULL);
435
436 /* Unlink */
437 if (gh_list[e->slot] == e) {
438 /* e is first entry */
439 gh_list[e->slot] = e->next;
440
441 if (e->next != NULL)
442 e->next->prev = NULL;
443
444 } else if (e->next == NULL) {
445 /* e is last entry */
446 e->prev->next = NULL;
447
448 } else {
449 /* e has an entry before and after */
450 e->prev->next = e->next;
451 e->next->prev = e->prev;
452 }
453
454 if (e->user_delete) {
455 /* User requested delete, so delete from urldb too. */
457 }
458
459 /* Destroy fields */
460 free((void *)e->data[GH_TITLE].value); /* Eww */
461 free((void *)e->data[GH_LAST_VISIT].value); /* Eww */
462 free((void *)e->data[GH_VISITS].value); /* Eww */
463 nsurl_unref(e->url);
464
465 /* Destroy entry */
466 free(e);
467}
468
469/**
470 * Internal routine to actually perform global history addition
471 *
472 * \param url The URL to add
473 * \param data URL data associated with URL
474 * \return true (for urldb_iterate_entries)
475 */
477 const struct url_data *data)
478{
479 int slot;
480 time_t visit_date;
481 time_t earliest_date = gh_ctx.today - (N_DAYS - 1) * N_SEC_PER_DAY;
482 bool got_treeview = gh_ctx.tree != NULL;
483
484 assert((url != NULL) && (data != NULL));
485
486 visit_date = data->last_visit;
487
488 /* Find day array slot for entry */
489 if (visit_date >= gh_ctx.today) {
490 slot = 0;
491 } else if (visit_date >= earliest_date) {
492 slot = (gh_ctx.today - visit_date) / N_SEC_PER_DAY + 1;
493 } else {
494 /* too old */
495 return true;
496 }
497
498 if (got_treeview == true) {
499 /* The treeview for global history already exists */
500 struct global_history_entry *e;
501
502 /* Delete any existing entry for this URL */
504 if (e != NULL) {
508 }
509 }
510
512 got_treeview) != NSERROR_OK) {
513 return false;
514 }
515
516 return true;
517}
518
519/**
520 * Initialise the treeview entry feilds
521 *
522 * \return NSERROR_OK on success, or appropriate error otherwise
523 */
525{
526 int i;
527 const char *label;
528
529 for (i = 0; i < N_FIELDS; i++)
530 gh_ctx.fields[i].field = NULL;
531
533 label = "TreeviewLabelTitle";
534 label = messages_get(label);
535 if (lwc_intern_string(label, strlen(label),
537 lwc_error_ok) {
538 goto error;
539 }
540
544 label = "TreeviewLabelURL";
545 label = messages_get(label);
546 if (lwc_intern_string(label, strlen(label),
548 lwc_error_ok) {
549 goto error;
550 }
551
553 label = "TreeviewLabelLastVisit";
554 label = messages_get(label);
555 if (lwc_intern_string(label, strlen(label),
557 lwc_error_ok) {
558 goto error;
559 }
560
562 label = "TreeviewLabelVisits";
563 label = messages_get(label);
564 if (lwc_intern_string(label, strlen(label),
566 lwc_error_ok) {
567 goto error;
568 }
569
571 label = "TreeviewLabelPeriod";
572 label = messages_get(label);
573 if (lwc_intern_string(label, strlen(label),
575 lwc_error_ok) {
576 return false;
577 }
578
579 return NSERROR_OK;
580
581error:
582 for (i = 0; i < N_FIELDS; i++)
583 if (gh_ctx.fields[i].field != NULL)
584 lwc_string_unref(gh_ctx.fields[i].field);
585
586 return NSERROR_UNKNOWN;
587}
588
589
590/**
591 * Initialise the time
592 *
593 * \return NSERROR_OK on success, or appropriate error otherwise
594 */
596{
597 struct tm *full_time;
598 time_t t;
599
600 /* get the current time */
601 t = time(NULL);
602 if (t == -1) {
603 NSLOG(netsurf, INFO, "time info unaviable");
604 return NSERROR_UNKNOWN;
605 }
606
607 /* get the time at the start of today */
608 full_time = localtime(&t);
609 full_time->tm_sec = 0;
610 full_time->tm_min = 0;
611 full_time->tm_hour = 0;
612 t = mktime(full_time);
613 if (t == -1) {
614 NSLOG(netsurf, INFO, "mktime failed");
615 return NSERROR_UNKNOWN;
616 }
617
618 gh_ctx.today = t;
619 gh_ctx.weekday = full_time->tm_wday;
620
621 return NSERROR_OK;
622}
623
624
625/**
626 * Initialise the treeview entries
627 *
628 * \return NSERROR_OK on success, or appropriate error otherwise
629 */
631{
632 int i;
633 nserror err;
634
635 /* Itterate over all global history data, inserting it into treeview */
636 for (i = 0; i < N_DAYS; i++) {
637 struct global_history_entry *l = NULL;
638 struct global_history_entry *e = gh_list[i];
639
640 /* Insert in reverse order; find last */
641 while (e != NULL) {
642 l = e;
643 e = e->next;
644 }
645
646 /* Insert the entries into the treeview */
647 while (l != NULL) {
648 err = global_history_entry_insert(l, i);
649 if (err != NSERROR_OK) {
650 return err;
651 }
652 l = l->prev;
653 }
654 }
655
656 return NSERROR_OK;
657}
658
659
661 struct treeview_node_msg msg, void *data)
662{
663 struct global_history_folder *f = data;
664
665 switch (msg.msg) {
667 f->folder = NULL;
668 break;
669
671 break;
672
674 break;
675 }
676
677 return NSERROR_OK;
678}
679
680static nserror
682{
683 struct global_history_entry *e = data;
684 nserror ret = NSERROR_OK;
685
686 switch (msg.msg) {
688 e->entry = NULL;
689 e->user_delete = msg.data.delete.user;
691 break;
692
694 break;
695
697 {
698 struct browser_window *existing = NULL;
700
701 /* TODO: Set existing to window that new tab appears in */
702
703 if (msg.data.node_launch.mouse &
705 existing == NULL) {
706 /* Shift or Ctrl launch, open in new window rather
707 * than tab. */
708 /* TODO: flags ^= BW_CREATE_TAB; */
709 }
710
711 ret = browser_window_create(flags, e->url, NULL,
712 existing, NULL);
713 }
714 break;
715 }
716 return ret;
717}
718
722};
723
724
725/* Exported interface, documented in global_history.h */
726nserror global_history_init(void *core_window_handle)
727{
728 nserror err;
729
730 err = treeview_init();
731 if (err != NSERROR_OK) {
732 return err;
733 }
734
735 NSLOG(netsurf, INFO, "Loading global history");
736
737 /* Init. global history treeview time */
739 if (err != NSERROR_OK) {
740 gh_ctx.tree = NULL;
741 return err;
742 }
743
744 /* Init. global history treeview entry fields */
746 if (err != NSERROR_OK) {
747 gh_ctx.tree = NULL;
748 return err;
749 }
750
751 /* Load the entries */
753
754 /* Create the global history treeview */
757 core_window_handle,
760 if (err != NSERROR_OK) {
761 gh_ctx.tree = NULL;
762 return err;
763 }
764
765 /* Ensure there is a folder for today */
767 if (err != NSERROR_OK) {
768 return err;
769 }
770
771 /* Add the history to the treeview */
773 if (err != NSERROR_OK) {
774 return err;
775 }
776
777 /* Expand the "Today" folder node */
780 if (err != NSERROR_OK) {
781 return err;
782 }
783
784 /* History tree is built
785 * We suppress the treeview height callback on entry insertion before
786 * the treeview is built. */
787 gh_ctx.built = true;
788
789 /* Inform client of window height */
791
792 NSLOG(netsurf, INFO, "Loaded global history");
793
794 return NSERROR_OK;
795}
796
797
798/* Exported interface, documented in global_history.h */
800{
801 int i;
802 nserror err;
803
804 NSLOG(netsurf, INFO, "Finalising global history");
805
806 gh_ctx.built = false;
807
808 /* Destroy the global history treeview */
810 gh_ctx.tree = NULL;
811
812 /* Free global history treeview entry fields */
813 for (i = 0; i < N_FIELDS; i++)
814 if (gh_ctx.fields[i].field != NULL)
815 lwc_string_unref(gh_ctx.fields[i].field);
816
817 err = treeview_fini();
818 if (err != NSERROR_OK) {
819 return err;
820 }
821
822 NSLOG(netsurf, INFO, "Finalised global history");
823
824 return err;
825}
826
827
828/* Exported interface, documented in global_history.h */
830{
831 const struct url_data *data;
832
833 /* If we don't have a global history at the moment, just return OK */
834 if (gh_ctx.tree == NULL)
835 return NSERROR_OK;
836
837 data = urldb_get_url_data(url);
838 if (data == NULL) {
839 NSLOG(netsurf, INFO,
840 "Can't add URL to history that's not present in urldb.");
842 }
843
844 global_history_add_entry(url, data);
845
846 return NSERROR_OK;
847}
848
849
851 FILE *fp;
852};
853/** Callback for treeview_walk node entering */
854static nserror global_history_export_enter_cb(void *ctx, void *node_data,
855 enum treeview_node_type type, bool *abort)
856{
857 struct treeview_export_walk_ctx *tw = ctx;
858 nserror ret;
859
860 if (type == TREE_NODE_ENTRY) {
861 struct global_history_entry *e = node_data;
862 char *t_text;
863 char *u_text;
864
865 ret = utf8_to_html(e->data[GH_TITLE].value, "iso-8859-1",
866 e->data[GH_TITLE].value_len, &t_text);
867 if (ret != NSERROR_OK)
868 return NSERROR_SAVE_FAILED;
869
870 ret = utf8_to_html(e->data[GH_URL].value, "iso-8859-1",
871 e->data[GH_URL].value_len, &u_text);
872 if (ret != NSERROR_OK) {
873 free(t_text);
874 return NSERROR_SAVE_FAILED;
875 }
876
877 fprintf(tw->fp, "<li><a href=\"%s\">%s</a></li>\n",
878 u_text, t_text);
879
880 free(t_text);
881 free(u_text);
882
883 } else if (type == TREE_NODE_FOLDER) {
884 struct global_history_folder *f = node_data;
885 char *f_text;
886
887 ret = utf8_to_html(f->data.value, "iso-8859-1",
888 f->data.value_len, &f_text);
889 if (ret != NSERROR_OK)
890 return NSERROR_SAVE_FAILED;
891
892 fprintf(tw->fp, "<li><h4>%s</h4>\n<ul>\n", f_text);
893
894 free(f_text);
895 }
896
897 return NSERROR_OK;
898}
899/** Callback for treeview_walk node leaving */
900static nserror global_history_export_leave_cb(void *ctx, void *node_data,
901 enum treeview_node_type type, bool *abort)
902{
903 struct treeview_export_walk_ctx *tw = ctx;
904
905 if (type == TREE_NODE_FOLDER) {
906 fputs("</ul></li>\n", tw->fp);
907 }
908
909 return NSERROR_OK;
910}
911/* Exported interface, documented in global_history.h */
912nserror global_history_export(const char *path, const char *title)
913{
914 struct treeview_export_walk_ctx tw;
915 nserror err;
916 FILE *fp;
917
918 fp = fopen(path, "w");
919 if (fp == NULL)
920 return NSERROR_SAVE_FAILED;
921
922 if (title == NULL)
923 title = "NetSurf Browsing History";
924
925 fputs("<!DOCTYPE html "
926 "PUBLIC \"//W3C/DTD HTML 4.01//EN\" "
927 "\"http://www.w3.org/TR/html4/strict.dtd\">\n", fp);
928 fputs("<html>\n<head>\n", fp);
929 fputs("<meta http-equiv=\"Content-Type\" "
930 "content=\"text/html; charset=iso-8859-1\">\n", fp);
931 fprintf(fp, "<title>%s</title>\n", title);
932 fputs("</head>\n<body>\n<ul>\n", fp);
933
934 tw.fp = fp;
935 err = treeview_walk(gh_ctx.tree, NULL,
939 if (err != NSERROR_OK)
940 return err;
941
942 fputs("</ul>\n</body>\n</html>\n", fp);
943
944 fclose(fp);
945
946 return NSERROR_OK;
947}
948
949
950/* Exported interface, documented in global_history.h */
951void global_history_redraw(int x, int y, struct rect *clip,
952 const struct redraw_context *ctx)
953{
954 treeview_redraw(gh_ctx.tree, x, y, clip, ctx);
955}
956
957
958/* Exported interface, documented in global_history.h */
960{
961 treeview_mouse_action(gh_ctx.tree, mouse, x, y);
962}
963
964
965/* Exported interface, documented in global_history.h */
966bool global_history_keypress(uint32_t key)
967{
968 return treeview_keypress(gh_ctx.tree, key);
969}
970
971
972/* Exported interface, documented in global_history.h */
974{
976}
977
978
979/* Exported interface, documented in global_history.h */
980bool global_history_get_selection(nsurl **url, const char **title)
981{
982 struct global_history_entry *e;
984 void *v;
985
987 if (type != TREE_NODE_ENTRY || v == NULL) {
988 *url = NULL;
989 *title = NULL;
990 return false;
991 }
992
993 e = (struct global_history_entry *)v;
994
995 *url = e->url;
996 *title = e->data[GH_TITLE].value;
997 return true;
998}
999
1000
1001/* Exported interface, documented in global_history.h */
1003{
1004 return treeview_expand(gh_ctx.tree, only_folders);
1005}
1006
1007
1008/* Exported interface, documented in global_history.h */
1010{
1011 return treeview_contract(gh_ctx.tree, all);
1012}
1013
Browser window creation and manipulation interface.
nserror browser_window_create(enum browser_window_create_flags flags, struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw)
Create and open a new root browser window with the given page.
browser_window_create_flags
flags to browser_window_create
@ BW_CREATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
global_history_fields
@ GH_URL
@ GH_LAST_VISIT
@ GH_TITLE
@ GH_VISITS
@ N_FIELDS
@ GH_PERIOD
nserror global_history_init(void *core_window_handle)
Initialise the global history.
static nserror global_history_create_treeview_field_data(struct global_history_entry *e, const struct url_data *data)
Set a global history entry's data from the url_data.
static nserror global_history_initialise_time(void)
Initialise the time.
static nserror global_history_get_parent_treeview_node(treeview_node **parent, int slot)
Get the treeview folder for history entires in a particular slot.
nserror global_history_expand(bool only_folders)
Expand the treeview's nodes.
static nserror global_history_init_entries(void)
Initialise the treeview entries.
static struct global_history_entry * global_history_find(nsurl *url)
Find an entry in the global history.
nserror global_history_fini(void)
Finalise the global history.
void global_history_redraw(int x, int y, struct rect *clip, const struct redraw_context *ctx)
Redraw the global history.
struct global_history_ctx gh_ctx
global_history_folders
@ GH_2_DAYS_AGO
@ GH_6_DAYS_AGO
@ GH_5_DAYS_AGO
@ GH_4_DAYS_AGO
@ GH_3_DAYS_AGO
@ GH_3_WEEKS_AGO
@ GH_LAST_WEEK
@ GH_TODAY
@ GH_2_WEEKS_AGO
@ GH_N_FOLDERS
@ GH_YESTERDAY
nserror global_history_add(nsurl *url)
Add an entry to the global history.
bool global_history_has_selection(void)
Determine whether there is a selection.
static nserror global_history_export_enter_cb(void *ctx, void *node_data, enum treeview_node_type type, bool *abort)
Callback for treeview_walk node entering.
static bool global_history_add_entry(nsurl *url, const struct url_data *data)
Internal routine to actually perform global history addition.
static nserror global_history_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
static void global_history_delete_entry_internal(struct global_history_entry *e)
Delete a global history entry.
static nserror global_history_create_dir(enum global_history_folders f)
Initialise the treeview directories.
#define N_SEC_PER_DAY
bool global_history_get_selection(nsurl **url, const char **title)
Get the first selected node.
static nserror global_history_add_entry_internal(nsurl *url, int slot, const struct url_data *data, bool got_treeview)
Add an entry to the global history (creates the entry).
nserror global_history_export(const char *path, const char *title)
Save global history to file (html)
nserror global_history_contract(bool all)
Contract the treeview's nodes.
static nserror global_history_entry_insert(struct global_history_entry *e, int slot)
Add a global history entry to the treeview.
struct global_history_entry * gh_list[N_DAYS]
static nserror global_history_initialise_entry_fields(void)
Initialise the treeview entry feilds.
static nserror global_history_export_leave_cb(void *ctx, void *node_data, enum treeview_node_type type, bool *abort)
Callback for treeview_walk node leaving.
bool global_history_keypress(uint32_t key)
Key press handling.
#define N_DAYS
void global_history_mouse_action(browser_mouse_state mouse, int x, int y)
Handles all kinds of mouse action.
struct treeview_callback_table gh_tree_cb_t
static nserror global_history_tree_node_folder_cb(struct treeview_node_msg msg, void *data)
nserror treeview_create(treeview **treeout, const struct treeview_callback_table *callbacks, int n_fields, struct treeview_field_desc fields[], struct core_window *cw, treeview_flags flags)
Create a treeview.
Definition: treeview.c:2022
void treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
Handles all kinds of mouse action.
Definition: treeview.c:4723
nserror treeview_contract(treeview *tree, bool all)
Contract a treeview's nodes.
Definition: treeview.c:2434
nserror treeview_delete_node(treeview *tree, treeview_node *n, treeview_node_options_flags flags)
Delete a treeview node.
Definition: treeview.c:1924
enum treeview_node_type treeview_get_selection(treeview *tree, void **node_data)
Get the first selected node.
Definition: treeview.c:3363
nserror treeview_fini(void)
Finalise the treeview module (all treeviews must have been destroyed first)
Definition: treeview.c:5384
bool treeview_has_selection(treeview *tree)
Determine whether treeview has a selection.
Definition: treeview.c:3326
bool treeview_keypress(treeview *tree, uint32_t key)
Key press handling for treeviews.
Definition: treeview.c:4006
nserror treeview_create_node_folder(treeview *tree, treeview_node **folder, treeview_node *relation, enum treeview_relationship rel, const struct treeview_field_data *field, void *data, treeview_node_options_flags flags)
Create a folder node in given treeview.
Definition: treeview.c:1198
nserror treeview_destroy(treeview *tree)
Destroy a treeview object.
Definition: treeview.c:2158
nserror treeview_walk(treeview *tree, treeview_node *root, treeview_walk_cb enter_cb, treeview_walk_cb leave_cb, void *ctx, enum treeview_node_type type)
Walk (depth first) a treeview subtree, calling a callback at each node of required type.
Definition: treeview.c:1534
int treeview_get_height(treeview *tree)
Find current height of a treeview.
Definition: treeview.c:4908
void treeview_redraw(treeview *tree, const int x, const int y, struct rect *clip, const struct redraw_context *ctx)
Redraw a treeview object.
Definition: treeview.c:2997
nserror treeview_node_expand(treeview *tree, treeview_node *node)
Expand a treeview node.
Definition: treeview.c:2291
nserror treeview_init(void)
Prepare treeview module for treeview usage.
Definition: treeview.c:5335
nserror treeview_create_node_entry(treeview *tree, treeview_node **entry, treeview_node *relation, enum treeview_relationship rel, const struct treeview_field_data fields[], void *data, treeview_node_options_flags flags)
Create an entry node in given treeview.
Definition: treeview.c:1388
nserror treeview_expand(treeview *tree, bool only_folders)
Expand a treeview's nodes.
Definition: treeview.c:2525
Treeview handling interface.
@ TREE_MSG_NODE_EDIT
Node to be edited.
Definition: treeview.h:87
@ TREE_MSG_NODE_LAUNCH
Node to be launched.
Definition: treeview.h:88
@ TREE_MSG_NODE_DELETE
Node to be deleted.
Definition: treeview.h:86
treeview_node_type
treeview node type
Definition: treeview.h:43
@ TREE_NODE_ENTRY
Node is an entry.
Definition: treeview.h:47
@ TREE_NODE_FOLDER
Node is folder.
Definition: treeview.h:46
@ TREE_OPTION_NONE
Definition: treeview.h:64
@ TREE_OPTION_SUPPRESS_RESIZE
Definition: treeview.h:66
@ TREE_OPTION_SUPPRESS_REDRAW
Definition: treeview.h:67
@ TREE_FLAG_SEARCHABLE
Whether field is searchable.
Definition: treeview.h:121
@ TREE_FLAG_SHOW_NAME
Whether field name shown.
Definition: treeview.h:119
@ TREE_FLAG_COPY_TEXT
Whether to copy to clipb.
Definition: treeview.h:120
@ TREE_FLAG_DEFAULT
Whether field is default.
Definition: treeview.h:118
treeview_relationship
Relationship between nodes.
Definition: treeview.h:54
@ TREE_REL_FIRST_CHILD
Definition: treeview.h:55
@ TREE_REL_NEXT_SIBLING
Definition: treeview.h:56
@ TREEVIEW_DEL_EMPTY_DIRS
Delete dirs on empty.
Definition: treeview.h:78
@ TREEVIEW_SEARCHABLE
Treeview has search bar.
Definition: treeview.h:79
@ TREEVIEW_NO_MOVES
No node drags.
Definition: treeview.h:75
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_SAVE_FAILED
Failed to save data.
Definition: errors.h:36
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_UNKNOWN
Unknown error - DO NOT USE.
Definition: errors.h:31
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * type
Definition: filetype.cpp:44
browser_mouse_state
Mouse state: 1 is primary mouse button.
Definition: mouse.h:52
@ BROWSER_MOUSE_MOD_2
2nd modifier key pressed (eg.
Definition: mouse.h:101
@ BROWSER_MOUSE_MOD_1
1st modifier key pressed (eg.
Definition: mouse.h:99
libdom utilities (implementation).
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
NetSurf URL handling (interface).
bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts)
Compare two URLs.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
size_t nsurl_length(const nsurl *url)
Find the length of a NetSurf URL object's URL, as returned by nsurl_access.
nsurl * nsurl_ref(nsurl *url)
Increment the reference count to a NetSurf URL object.
@ NSURL_COMPLETE
Definition: nsurl.h:54
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
Interface to utility string handling.
Browser window data.
struct global_history_folder folders[GH_N_FOLDERS]
struct treeview_field_desc fields[N_FIELDS]
treeview_node * entry
nsurl * url
bool user_delete
time_t t
struct global_history_entry * prev
int slot
struct treeview_field_data data[N_FIELDS - 1]
struct global_history_entry * next
treeview_node * folder
struct treeview_field_data data
Rectangle coordinates.
Definition: types.h:40
Redraw context.
Definition: plotters.h:51
Client callbacks for events concerning nodes.
Definition: treeview.h:147
nserror(* folder)(struct treeview_node_msg msg, void *data)
Definition: treeview.h:148
Treeview field data.
Definition: treeview.h:137
const char * value
Field value.
Definition: treeview.h:139
lwc_string * field
Field name.
Definition: treeview.h:138
size_t value_len
Field value length (bytes)
Definition: treeview.h:140
Treeview field description.
Definition: treeview.h:128
lwc_string * field
A treeview field name.
Definition: treeview.h:129
enum treeview_field_flags flags
Flags for field.
Definition: treeview.h:130
treeview message
Definition: treeview.h:95
bool user
True iff delete by user interaction.
Definition: treeview.h:99
union treeview_node_msg::@94 data
The message data.
struct treeview_node_msg::@94::@95 delete
browser_mouse_state mouse
Definition: treeview.h:106
struct treeview_node_msg::@94::@97 node_launch
enum treeview_msg msg
The message type.
Definition: treeview.h:96
Treeview node.
Definition: treeview.c:133
The treeview context.
Definition: treeview.c:232
unsigned int visits
Visit count.
Definition: url_db.h:38
time_t last_visit
Last visit time.
Definition: url_db.h:39
Interface to time operations.
void urldb_iterate_entries(bool(*callback)(struct nsurl *url, const struct url_data *data))
Iterate over all entries in database.
const struct url_data * urldb_get_url_data(struct nsurl *url)
Find data for an URL.
Definition: urldb.c:3309
void urldb_reset_url_visit_data(nsurl *url)
Reset an URL's visit statistics.
Definition: urldb.c:3293
Unified URL information database internal interface.
nserror utf8_to_html(const char *string, const char *encname, size_t len, char **result_out)
Convert a UTF-8 encoded string into a string of the given encoding, applying HTML escape sequences wh...
Definition: utf8.c:369
UTF-8 manipulation functions (interface).
Interface to a number of general purpose functionality.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357