mirror of
https://github.com/rkd77/elinks.git
synced 2024-10-09 05:20:36 -04:00
773 lines
18 KiB
C
773 lines
18 KiB
C
/* Internal bookmarks support */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "elinks.h"
|
|
|
|
#include "bfu/dialog.h"
|
|
#include "bfu/hierbox.h"
|
|
#include "bfu/listbox.h"
|
|
#include "bookmarks/backend/common.h"
|
|
#include "bookmarks/bookmarks.h"
|
|
#include "bookmarks/dialogs.h"
|
|
#include "config/home.h"
|
|
#include "config/options.h"
|
|
#include "intl/libintl.h"
|
|
#include "main/module.h"
|
|
#include "main/object.h"
|
|
#include "protocol/uri.h"
|
|
#include "session/task.h"
|
|
#include "terminal/tab.h"
|
|
#include "util/conv.h"
|
|
#include "util/hash.h"
|
|
#include "util/lists.h"
|
|
#include "util/memory.h"
|
|
#include "util/secsave.h"
|
|
#include "util/string.h"
|
|
|
|
/* The list of bookmarks */
|
|
INIT_LIST_OF(struct bookmark, bookmarks);
|
|
|
|
/* Set to 1, if bookmarks have changed. */
|
|
static int bookmarks_dirty = 0;
|
|
|
|
static struct hash *bookmark_cache = NULL;
|
|
|
|
static struct bookmark *bm_snapshot_last_folder;
|
|
|
|
|
|
/* Life functions */
|
|
|
|
static union option_info bookmark_options_info[] = {
|
|
INIT_OPT_TREE("", N_("Bookmarks"),
|
|
"bookmarks", OPT_ZERO,
|
|
N_("Bookmark options.")),
|
|
|
|
#ifdef CONFIG_XBEL_BOOKMARKS
|
|
INIT_OPT_INT("bookmarks", N_("File format"),
|
|
"file_format", OPT_ZERO, 0, 1, 0,
|
|
N_("File format for bookmarks (affects both reading and "
|
|
"saving):\n"
|
|
"0 is the default native ELinks format\n"
|
|
"1 is XBEL universal XML bookmarks format")),
|
|
#else
|
|
INIT_OPT_INT("bookmarks", N_("File format"),
|
|
"file_format", OPT_ZERO, 0, 1, 0,
|
|
N_("File format for bookmarks (affects both reading and "
|
|
"saving):\n"
|
|
"0 is the default native ELinks format\n"
|
|
"1 is XBEL universal XML bookmarks format (DISABLED)")),
|
|
#endif
|
|
|
|
INIT_OPT_BOOL("bookmarks", N_("Save folder state"),
|
|
"folder_state", OPT_ZERO, 1,
|
|
N_("When saving bookmarks also store whether folders are "
|
|
"expanded or not, so the look of the bookmark dialog is "
|
|
"kept across ELinks sessions. If disabled all folders will "
|
|
"appear unexpanded next time ELinks is run.")),
|
|
|
|
INIT_OPT_BOOL("ui.sessions", N_("Periodic snapshotting"),
|
|
"snapshot", OPT_ZERO, 0,
|
|
N_("Automatically save a snapshot of all tabs periodically. "
|
|
"This will periodically bookmark the tabs of each terminal "
|
|
"in a separate folder for recovery after a crash.\n"
|
|
"\n"
|
|
"This feature requires bookmark support.")),
|
|
|
|
NULL_OPTION_INFO
|
|
};
|
|
|
|
static enum evhook_status bookmark_change_hook(va_list ap, void *data);
|
|
static enum evhook_status bookmark_write_hook(va_list ap, void *data);
|
|
|
|
struct event_hook_info bookmark_hooks[] = {
|
|
{ "bookmark-delete", 0, bookmark_change_hook, {NULL} },
|
|
{ "bookmark-move", 0, bookmark_change_hook, {NULL} },
|
|
{ "bookmark-update", 0, bookmark_change_hook, {NULL} },
|
|
{ "periodic-saving", 0, bookmark_write_hook, {NULL} },
|
|
|
|
NULL_EVENT_HOOK_INFO,
|
|
};
|
|
|
|
static enum evhook_status
|
|
bookmark_change_hook(va_list ap, void *data)
|
|
{
|
|
struct bookmark *bookmark = va_arg(ap, struct bookmark *);
|
|
|
|
if (bookmark == bm_snapshot_last_folder)
|
|
bm_snapshot_last_folder = NULL;
|
|
|
|
return EVENT_HOOK_STATUS_NEXT;
|
|
}
|
|
|
|
static void bookmark_snapshot();
|
|
|
|
static enum evhook_status
|
|
bookmark_write_hook(va_list ap, void *data)
|
|
{
|
|
if (get_opt_bool("ui.sessions.snapshot", NULL)
|
|
&& !get_cmd_opt_bool("anonymous"))
|
|
bookmark_snapshot();
|
|
|
|
write_bookmarks();
|
|
|
|
return EVENT_HOOK_STATUS_NEXT;
|
|
}
|
|
|
|
|
|
static int
|
|
change_hook_folder_state(struct session *ses, struct option *current,
|
|
struct option *changed)
|
|
{
|
|
if (!changed->value.number) {
|
|
/* We are to collapse all folders on exit; mark bookmarks dirty
|
|
* to ensure that this will happen. */
|
|
bookmarks_set_dirty();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
init_bookmarks(struct module *module)
|
|
{
|
|
static const struct change_hook_info bookmarks_change_hooks[] = {
|
|
{ "bookmarks.folder_state", change_hook_folder_state },
|
|
{ NULL, NULL },
|
|
};
|
|
|
|
register_change_hooks(bookmarks_change_hooks);
|
|
|
|
read_bookmarks();
|
|
}
|
|
|
|
/* Clears the bookmark list */
|
|
static void
|
|
free_bookmarks(LIST_OF(struct bookmark) *bookmarks_list,
|
|
LIST_OF(struct listbox_item) *box_items)
|
|
{
|
|
struct bookmark *bm;
|
|
|
|
foreach (bm, *bookmarks_list) {
|
|
if (!list_empty(bm->child))
|
|
free_bookmarks(&bm->child, &bm->box_item->child);
|
|
mem_free(bm->title);
|
|
mem_free(bm->url);
|
|
}
|
|
|
|
free_list(*box_items);
|
|
free_list(*bookmarks_list);
|
|
if (bookmark_cache) free_hash(&bookmark_cache);
|
|
}
|
|
|
|
/* Does final cleanup and saving of bookmarks */
|
|
static void
|
|
done_bookmarks(struct module *module)
|
|
{
|
|
/* This is a clean shutdown, so delete the last snapshot. */
|
|
if (bm_snapshot_last_folder) delete_bookmark(bm_snapshot_last_folder);
|
|
bm_snapshot_last_folder = NULL;
|
|
|
|
write_bookmarks();
|
|
free_bookmarks(&bookmarks, &bookmark_browser.root.child);
|
|
free_last_searched_bookmark();
|
|
}
|
|
|
|
struct module bookmarks_module = struct_module(
|
|
/* name: */ N_("Bookmarks"),
|
|
/* options: */ bookmark_options_info,
|
|
/* hooks: */ bookmark_hooks,
|
|
/* submodules: */ NULL,
|
|
/* data: */ NULL,
|
|
/* init: */ init_bookmarks,
|
|
/* done: */ done_bookmarks
|
|
);
|
|
|
|
|
|
|
|
/* Read/write wrappers */
|
|
|
|
/* Loads the bookmarks from file */
|
|
void
|
|
read_bookmarks(void)
|
|
{
|
|
bookmarks_read();
|
|
}
|
|
|
|
void
|
|
write_bookmarks(void)
|
|
{
|
|
if (get_cmd_opt_bool("anonymous")) {
|
|
bookmarks_unset_dirty();
|
|
return;
|
|
}
|
|
bookmarks_write(&bookmarks);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Bookmarks manipulation */
|
|
|
|
void
|
|
bookmarks_set_dirty(void)
|
|
{
|
|
bookmarks_dirty = 1;
|
|
}
|
|
|
|
void
|
|
bookmarks_unset_dirty(void)
|
|
{
|
|
bookmarks_dirty = 0;
|
|
}
|
|
|
|
int
|
|
bookmarks_are_dirty(void)
|
|
{
|
|
return (bookmarks_dirty == 1);
|
|
}
|
|
|
|
#define check_bookmark_cache(url) (bookmark_cache && (url) && *(url))
|
|
|
|
static void
|
|
done_bookmark(struct bookmark *bm)
|
|
{
|
|
done_listbox_item(&bookmark_browser, bm->box_item);
|
|
|
|
mem_free(bm->title);
|
|
mem_free(bm->url);
|
|
mem_free(bm);
|
|
}
|
|
|
|
void
|
|
delete_bookmark(struct bookmark *bm)
|
|
{
|
|
static int delete_bookmark_event_id = EVENT_NONE;
|
|
|
|
while (!list_empty(bm->child)) {
|
|
delete_bookmark((struct bookmark *)bm->child.next);
|
|
}
|
|
|
|
if (check_bookmark_cache(bm->url)) {
|
|
struct hash_item *item;
|
|
|
|
item = get_hash_item(bookmark_cache, bm->url, strlen(bm->url));
|
|
if (item) del_hash_item(bookmark_cache, item);
|
|
}
|
|
|
|
set_event_id(delete_bookmark_event_id, "bookmark-delete");
|
|
trigger_event(delete_bookmark_event_id, bm);
|
|
|
|
del_from_list(bm);
|
|
bookmarks_set_dirty();
|
|
|
|
done_bookmark(bm);
|
|
}
|
|
|
|
/** Deletes any bookmarks with no URLs (i.e., folders) and of which
|
|
* the title matches the given argument.
|
|
*
|
|
* @param foldername
|
|
* The title of the folder, in UTF-8. */
|
|
static void
|
|
delete_folder_by_name(const char *foldername)
|
|
{
|
|
struct bookmark *bookmark, *next;
|
|
|
|
foreachsafe (bookmark, next, bookmarks) {
|
|
if ((bookmark->url && *bookmark->url)
|
|
|| strcmp(bookmark->title, foldername))
|
|
continue;
|
|
|
|
delete_bookmark(bookmark);
|
|
}
|
|
}
|
|
|
|
/** Allocate and initialize a bookmark in the given folder. This
|
|
* however does not set bookmark.box_item; use add_bookmark() for
|
|
* that.
|
|
*
|
|
* @param root
|
|
* The folder in which to add the bookmark, or NULL to add it at
|
|
* top level.
|
|
* @param title
|
|
* Title of the bookmark. Must be in UTF-8 and not NULL.
|
|
* "-" means add a separator.
|
|
* @param url
|
|
* URL to which the bookmark will point. Must be in UTF-8.
|
|
* NULL or "" means add a bookmark folder.
|
|
*
|
|
* @return the new bookmark, or NULL on error. */
|
|
static struct bookmark *
|
|
init_bookmark(struct bookmark *root, const char *title, const char *url)
|
|
{
|
|
struct bookmark *bm;
|
|
|
|
bm = (struct bookmark *)mem_calloc(1, sizeof(*bm));
|
|
if (!bm) return NULL;
|
|
|
|
bm->title = stracpy(title);
|
|
if (!bm->title) {
|
|
mem_free(bm);
|
|
return NULL;
|
|
}
|
|
sanitize_title(bm->title);
|
|
|
|
bm->url = stracpy(empty_string_or_(url));
|
|
if (!bm->url) {
|
|
mem_free(bm->title);
|
|
mem_free(bm);
|
|
return NULL;
|
|
}
|
|
sanitize_url(bm->url);
|
|
|
|
bm->root = root;
|
|
init_list(bm->child);
|
|
|
|
object_nolock(bm, "bookmark");
|
|
|
|
return bm;
|
|
}
|
|
|
|
static void
|
|
add_bookmark_item_to_bookmarks(struct bookmark *bm, struct bookmark *root, int place)
|
|
{
|
|
/* Actually add it */
|
|
if (place) {
|
|
if (root)
|
|
add_to_list_end(root->child, bm);
|
|
else
|
|
add_to_list_end(bookmarks, bm);
|
|
} else {
|
|
if (root)
|
|
add_to_list(root->child, bm);
|
|
else
|
|
add_to_list(bookmarks, bm);
|
|
}
|
|
bookmarks_set_dirty();
|
|
|
|
/* Hash creation if needed. */
|
|
if (!bookmark_cache)
|
|
bookmark_cache = init_hash8();
|
|
|
|
/* Create a new entry. */
|
|
if (check_bookmark_cache(bm->url))
|
|
add_hash_item(bookmark_cache, bm->url, strlen(bm->url), bm);
|
|
}
|
|
|
|
/** Add a bookmark to the bookmark list.
|
|
*
|
|
* @param root
|
|
* The folder in which to add the bookmark, or NULL to add it at
|
|
* top level.
|
|
* @param place
|
|
* 0 means add to the top. 1 means add to the bottom.
|
|
* @param title
|
|
* Title of the bookmark. Must be in UTF-8 and not NULL.
|
|
* "-" means add a separator.
|
|
* @param url
|
|
* URL to which the bookmark will point. Must be in UTF-8.
|
|
* NULL or "" means add a bookmark folder.
|
|
*
|
|
* @return the new bookmark, or NULL on error.
|
|
*
|
|
* @see add_bookmark_cp() */
|
|
struct bookmark *
|
|
add_bookmark(struct bookmark *root, int place, const char *title,
|
|
const char *url)
|
|
{
|
|
enum listbox_item_type type;
|
|
struct bookmark *bm;
|
|
|
|
bm = init_bookmark(root, title, url);
|
|
if (!bm) return NULL;
|
|
|
|
if (url && *url) {
|
|
type = BI_LEAF;
|
|
} else if (title && title[0] == '-' && title[1] == '\0') {
|
|
type = BI_SEPARATOR;
|
|
} else {
|
|
type = BI_FOLDER;
|
|
}
|
|
|
|
bm->box_item = add_listbox_item(&bookmark_browser,
|
|
root ? root->box_item : NULL,
|
|
type,
|
|
(void *) bm,
|
|
place ? -1 : 1);
|
|
|
|
if (!bm->box_item) {
|
|
mem_free(bm->url);
|
|
mem_free(bm->title);
|
|
mem_free(bm);
|
|
return NULL;
|
|
}
|
|
|
|
add_bookmark_item_to_bookmarks(bm, root, place);
|
|
|
|
return bm;
|
|
}
|
|
|
|
/** Add a bookmark to the bookmark list.
|
|
*
|
|
* @param root
|
|
* The folder in which to add the bookmark, or NULL to add it at
|
|
* top level.
|
|
* @param place
|
|
* 0 means add to the top. 1 means add to the bottom.
|
|
* @param codepage
|
|
* Codepage of @a title and @a url.
|
|
* @param title
|
|
* Title of the bookmark. Must not be NULL.
|
|
* "-" means add a separator.
|
|
* @param url
|
|
* URL to which the bookmark will point.
|
|
* NULL or "" means add a bookmark folder.
|
|
*
|
|
* @return the new bookmark.
|
|
*
|
|
* @see add_bookmark() */
|
|
struct bookmark *
|
|
add_bookmark_cp(struct bookmark *root, int place, int codepage,
|
|
const char *title, const char *url)
|
|
{
|
|
const int utf8_cp = get_cp_index("UTF-8");
|
|
struct conv_table *table;
|
|
char *utf8_title = NULL;
|
|
char *utf8_url = NULL;
|
|
struct bookmark *bookmark = NULL;
|
|
|
|
if (!url)
|
|
url = "";
|
|
|
|
table = get_translation_table(codepage, utf8_cp);
|
|
if (!table)
|
|
return NULL;
|
|
|
|
utf8_title = convert_string(table, title, strlen(title),
|
|
utf8_cp, CSM_NONE,
|
|
NULL, NULL, NULL);
|
|
utf8_url = convert_string(table, url, strlen(url),
|
|
utf8_cp, CSM_NONE,
|
|
NULL, NULL, NULL);
|
|
if (utf8_title && utf8_url)
|
|
bookmark = add_bookmark(root, place,
|
|
utf8_title, utf8_url);
|
|
mem_free_if(utf8_title);
|
|
mem_free_if(utf8_url);
|
|
return bookmark;
|
|
}
|
|
|
|
/* Updates an existing bookmark.
|
|
*
|
|
* If there's any problem, return 0. Otherwise, return 1.
|
|
*
|
|
* If any of the fields are NULL, the value is left unchanged. */
|
|
int
|
|
update_bookmark(struct bookmark *bm, int codepage,
|
|
char *title, char *url)
|
|
{
|
|
static int update_bookmark_event_id = EVENT_NONE;
|
|
const int utf8_cp = get_cp_index("UTF-8");
|
|
struct conv_table *table;
|
|
char *title2 = NULL;
|
|
char *url2 = NULL;
|
|
|
|
table = get_translation_table(codepage, utf8_cp);
|
|
if (!table)
|
|
return 0;
|
|
|
|
if (url) {
|
|
url2 = convert_string(table, url, strlen(url),
|
|
utf8_cp, CSM_NONE,
|
|
NULL, NULL, NULL);
|
|
if (!url2) return 0;
|
|
sanitize_url(url2);
|
|
}
|
|
|
|
if (title) {
|
|
title2 = convert_string(table, title, strlen(title),
|
|
utf8_cp, CSM_NONE,
|
|
NULL, NULL, NULL);
|
|
if (!title2) {
|
|
mem_free_if(url2);
|
|
return 0;
|
|
}
|
|
sanitize_title(title2);
|
|
}
|
|
|
|
set_event_id(update_bookmark_event_id, "bookmark-update");
|
|
trigger_event(update_bookmark_event_id, bm, title2, url2);
|
|
|
|
if (title2) {
|
|
mem_free_set(&bm->title, title2);
|
|
}
|
|
|
|
if (url2) {
|
|
if (check_bookmark_cache(bm->url)) {
|
|
struct hash_item *item;
|
|
int len = strlen(bm->url);
|
|
|
|
item = get_hash_item(bookmark_cache, bm->url, len);
|
|
if (item) del_hash_item(bookmark_cache, item);
|
|
}
|
|
|
|
if (check_bookmark_cache(url2)) {
|
|
add_hash_item(bookmark_cache, url2, strlen(url2), bm);
|
|
}
|
|
|
|
mem_free_set(&bm->url, url2);
|
|
}
|
|
|
|
bookmarks_set_dirty();
|
|
|
|
return 1;
|
|
}
|
|
|
|
/** Search for a bookmark with the given title. The search does not
|
|
* recurse into subfolders.
|
|
*
|
|
* @param folder
|
|
* Search in this folder. NULL means search in the root.
|
|
*
|
|
* @param title
|
|
* Search for this title. Must be in UTF-8 and not NULL.
|
|
*
|
|
* @return The bookmark, or NULL if not found. */
|
|
struct bookmark *
|
|
get_bookmark_by_name(struct bookmark *folder, char *title)
|
|
{
|
|
struct bookmark *bookmark;
|
|
LIST_OF(struct bookmark) *lh;
|
|
|
|
lh = folder ? &folder->child : &bookmarks;
|
|
|
|
foreach (bookmark, *lh)
|
|
if (!strcmp(bookmark->title, title)) return bookmark;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Search bookmark cache for item matching url. */
|
|
struct bookmark *
|
|
get_bookmark(char *url)
|
|
{
|
|
struct hash_item *item;
|
|
|
|
/** @todo Bug 1066: URLs in bookmark_cache should be UTF-8 */
|
|
if (!check_bookmark_cache(url))
|
|
return NULL;
|
|
|
|
/* Search for cached entry. */
|
|
|
|
item = get_hash_item(bookmark_cache, url, strlen(url));
|
|
|
|
return (struct bookmark *)(item ? item->value : NULL);
|
|
}
|
|
|
|
static void
|
|
bookmark_terminal(struct terminal *term, struct bookmark *folder)
|
|
{
|
|
char title[MAX_STR_LEN], url[MAX_STR_LEN];
|
|
struct window *tab;
|
|
int term_cp = get_terminal_codepage(term);
|
|
|
|
foreachback_tab (tab, term->windows) {
|
|
struct session *ses = (struct session *)tab->data;
|
|
|
|
if (!get_current_url(ses, url, MAX_STR_LEN))
|
|
continue;
|
|
|
|
if (!get_current_title(ses, title, MAX_STR_LEN))
|
|
continue;
|
|
|
|
add_bookmark_cp(folder, 1, term_cp, title, url);
|
|
}
|
|
}
|
|
|
|
/** Create a bookmark for each document on the specified terminal,
|
|
* and a folder to contain those bookmarks.
|
|
*
|
|
* @param term
|
|
* The terminal whose open documents should be bookmarked.
|
|
*
|
|
* @param foldername
|
|
* The name of the new bookmark folder, in UTF-8. */
|
|
void
|
|
bookmark_terminal_tabs(struct terminal *term, char *foldername)
|
|
{
|
|
struct bookmark *folder = add_bookmark(NULL, 1, foldername, NULL);
|
|
|
|
if (!folder) return;
|
|
|
|
bookmark_terminal(term, folder);
|
|
}
|
|
|
|
static void
|
|
bookmark_all_terminals(struct bookmark *folder)
|
|
{
|
|
unsigned int n = 0;
|
|
struct terminal *term;
|
|
|
|
if (get_cmd_opt_bool("anonymous"))
|
|
return;
|
|
|
|
if (list_is_singleton(terminals)) {
|
|
bookmark_terminal((struct terminal *)terminals.next, folder);
|
|
return;
|
|
}
|
|
|
|
foreach (term, terminals) {
|
|
char subfoldername[5];
|
|
struct bookmark *subfolder;
|
|
|
|
if (ulongcat(subfoldername, NULL, n, sizeof(subfoldername)-1, 0)
|
|
>= sizeof(subfoldername)-1)
|
|
return;
|
|
|
|
++n;
|
|
|
|
/* Because subfoldername[] contains only digits,
|
|
* it is OK as UTF-8. */
|
|
subfolder = add_bookmark(folder, 1, subfoldername, NULL);
|
|
if (!subfolder) return;
|
|
|
|
bookmark_terminal(term, subfolder);
|
|
}
|
|
}
|
|
|
|
|
|
char *
|
|
get_auto_save_bookmark_foldername_utf8(void)
|
|
{
|
|
char *foldername;
|
|
int from_cp, to_cp;
|
|
struct conv_table *convert_table;
|
|
|
|
foldername = get_opt_str("ui.sessions.auto_save_foldername", NULL);
|
|
if (!*foldername) return NULL;
|
|
|
|
/* The charset of the string returned by get_opt_str()
|
|
* seems to be documented nowhere. Let's assume it is
|
|
* the system charset. */
|
|
from_cp = get_cp_index("System");
|
|
to_cp = get_cp_index("UTF-8");
|
|
convert_table = get_translation_table(from_cp, to_cp);
|
|
if (!convert_table) return NULL;
|
|
|
|
return convert_string(convert_table,
|
|
foldername, strlen(foldername),
|
|
to_cp, CSM_NONE,
|
|
NULL, NULL, NULL);
|
|
}
|
|
|
|
void
|
|
bookmark_auto_save_tabs(struct terminal *term)
|
|
{
|
|
char *foldername; /* UTF-8 */
|
|
|
|
if (get_cmd_opt_bool("anonymous")
|
|
|| !get_opt_bool("ui.sessions.auto_save", NULL))
|
|
return;
|
|
|
|
foldername = get_auto_save_bookmark_foldername_utf8();
|
|
if (!foldername) return;
|
|
|
|
/* Ensure uniqueness of the auto save folder, so it is possible to
|
|
* restore the (correct) session when starting up. */
|
|
delete_folder_by_name(foldername);
|
|
|
|
bookmark_terminal_tabs(term, foldername);
|
|
mem_free(foldername);
|
|
}
|
|
|
|
static void
|
|
bookmark_snapshot(void)
|
|
{
|
|
struct string folderstring;
|
|
struct bookmark *folder;
|
|
|
|
if (!init_string(&folderstring)) return;
|
|
|
|
add_to_string(&folderstring, "Session snapshot");
|
|
|
|
#ifdef HAVE_STRFTIME
|
|
add_to_string(&folderstring, " - ");
|
|
add_date_to_string(&folderstring, get_opt_str("ui.date_format", NULL),
|
|
NULL);
|
|
#endif
|
|
|
|
/* folderstring must be in the system codepage because
|
|
* add_date_to_string() uses strftime(). */
|
|
folder = add_bookmark_cp(NULL, 1, get_cp_index("System"),
|
|
folderstring.source, NULL);
|
|
done_string(&folderstring);
|
|
if (!folder) return;
|
|
|
|
bookmark_all_terminals(folder);
|
|
|
|
if (bm_snapshot_last_folder) delete_bookmark(bm_snapshot_last_folder);
|
|
bm_snapshot_last_folder = folder;
|
|
}
|
|
|
|
|
|
/** Open all bookmarks from the named folder.
|
|
*
|
|
* @param ses
|
|
* The session in which to open the first bookmark. The other
|
|
* bookmarks of the folder open in new tabs on the same terminal.
|
|
*
|
|
* @param foldername
|
|
* The name of the bookmark folder, in UTF-8. */
|
|
void
|
|
open_bookmark_folder(struct session *ses, char *foldername)
|
|
{
|
|
struct bookmark *bookmark;
|
|
struct bookmark *folder = NULL;
|
|
struct bookmark *current = NULL;
|
|
|
|
assert(foldername && ses);
|
|
if_assert_failed return;
|
|
|
|
foreach (bookmark, bookmarks) {
|
|
if (bookmark->box_item->type != BI_FOLDER)
|
|
continue;
|
|
if (strcmp(bookmark->title, foldername))
|
|
continue;
|
|
folder = bookmark;
|
|
break;
|
|
}
|
|
|
|
if (!folder) return;
|
|
|
|
foreach (bookmark, folder->child) {
|
|
struct uri *uri;
|
|
|
|
if (bookmark->box_item->type == BI_FOLDER
|
|
|| bookmark->box_item->type == BI_SEPARATOR
|
|
|| !*bookmark->url)
|
|
continue;
|
|
|
|
/** @todo Bug 1066: Tell the URI layer that
|
|
* bookmark->url is UTF-8. */
|
|
uri = get_translated_uri(bookmark->url, NULL);
|
|
if (!uri) continue;
|
|
|
|
/* Save the first bookmark for the current tab */
|
|
if (!current) {
|
|
current = bookmark;
|
|
goto_uri(ses, uri);
|
|
} else {
|
|
open_uri_in_new_tab(ses, uri, 1, 0);
|
|
}
|
|
|
|
done_uri(uri);
|
|
}
|
|
}
|