2005-09-15 09:58:31 -04:00
|
|
|
/* Bookmarks dialogs */
|
|
|
|
|
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE /* XXX: we _WANT_ strcasestr() ! */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "elinks.h"
|
|
|
|
|
|
|
|
#include "bfu/dialog.h"
|
2006-06-14 03:11:51 -04:00
|
|
|
#include "bfu/hierbox.h"
|
|
|
|
#include "bfu/listbox.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "bookmarks/bookmarks.h"
|
|
|
|
#include "bookmarks/dialogs.h"
|
|
|
|
#include "dialogs/edit.h"
|
|
|
|
#include "intl/gettext/libintl.h"
|
|
|
|
#include "main/object.h"
|
|
|
|
#include "protocol/uri.h"
|
|
|
|
#include "session/session.h"
|
|
|
|
#include "terminal/terminal.h"
|
|
|
|
#include "util/conv.h"
|
|
|
|
#include "util/error.h"
|
|
|
|
#include "util/memory.h"
|
|
|
|
#include "util/time.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Whether to save bookmarks after each modification of their list
|
|
|
|
* (add/modify/delete). */
|
|
|
|
#define BOOKMARKS_RESAVE 1
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
lock_bookmark(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
object_lock((struct bookmark *) item->udata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
unlock_bookmark(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
object_unlock((struct bookmark *) item->udata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
is_bookmark_used(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
return is_object_used((struct bookmark *) item->udata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char *
|
|
|
|
get_bookmark_text(struct listbox_item *item, struct terminal *term)
|
|
|
|
{
|
|
|
|
struct bookmark *bookmark = item->udata;
|
2008-11-17 02:19:12 -05:00
|
|
|
int utf8_cp = get_cp_index("UTF-8");
|
|
|
|
int term_cp = get_terminal_codepage(term);
|
|
|
|
struct conv_table *convert_table;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2008-11-17 02:19:12 -05:00
|
|
|
convert_table = get_translation_table(utf8_cp, term_cp);
|
|
|
|
if (!convert_table) return NULL;
|
|
|
|
|
|
|
|
return convert_string(convert_table,
|
|
|
|
bookmark->title, strlen(bookmark->title),
|
|
|
|
term_cp, CSM_NONE, NULL, NULL, NULL);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2008-11-17 02:19:12 -05:00
|
|
|
/** A callback for convert_string(). This ignores errors and can
|
|
|
|
* result in truncated strings if out of memory. Accordingly, the
|
|
|
|
* resulting string may be displayed in the UI but should not be saved
|
|
|
|
* to a file or given to another program. */
|
|
|
|
static void
|
|
|
|
add_converted_bytes_to_string(void *data, unsigned char *buf, int buflen)
|
|
|
|
{
|
|
|
|
struct string *string = data;
|
|
|
|
|
|
|
|
add_bytes_to_string(string, buf, buflen); /* ignore errors */
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char *
|
|
|
|
get_bookmark_info(struct listbox_item *item, struct terminal *term)
|
|
|
|
{
|
|
|
|
struct bookmark *bookmark = item->udata;
|
2008-11-17 02:19:12 -05:00
|
|
|
int utf8_cp = get_cp_index("UTF-8");
|
|
|
|
int term_cp = get_terminal_codepage(term);
|
|
|
|
struct conv_table *convert_table;
|
2005-09-15 09:58:31 -04:00
|
|
|
struct string info;
|
|
|
|
|
|
|
|
if (item->type == BI_FOLDER) return NULL;
|
2008-11-17 02:19:12 -05:00
|
|
|
convert_table = get_translation_table(utf8_cp, term_cp);
|
|
|
|
if (!convert_table) return NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
if (!init_string(&info)) return NULL;
|
|
|
|
|
2008-11-17 02:19:12 -05:00
|
|
|
add_format_to_string(&info, "%s: ", _("Title", term));
|
|
|
|
convert_string(convert_table, bookmark->title, strlen(bookmark->title),
|
|
|
|
term_cp, CSM_NONE, NULL,
|
|
|
|
add_converted_bytes_to_string, &info);
|
|
|
|
add_format_to_string(&info, "\n%s: ", _("URL", term));
|
|
|
|
convert_string(convert_table, bookmark->url, strlen(bookmark->url),
|
|
|
|
term_cp, CSM_NONE, NULL,
|
|
|
|
add_converted_bytes_to_string, &info);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
return info.source;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct uri *
|
|
|
|
get_bookmark_uri(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
struct bookmark *bookmark = item->udata;
|
|
|
|
|
2008-10-19 18:06:36 -04:00
|
|
|
/** @todo Bug 1066: Tell the URI layer that bookmark->url is UTF-8. */
|
2005-09-15 09:58:31 -04:00
|
|
|
return bookmark->url && *bookmark->url
|
2005-11-24 09:38:47 -05:00
|
|
|
? get_translated_uri(bookmark->url, NULL) : NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct listbox_item *
|
|
|
|
get_bookmark_root(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
struct bookmark *bookmark = item->udata;
|
|
|
|
|
|
|
|
return bookmark->root ? bookmark->root->box_item : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
can_delete_bookmark(struct listbox_item *item)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
delete_bookmark_item(struct listbox_item *item, int last)
|
|
|
|
{
|
|
|
|
struct bookmark *bookmark = item->udata;
|
|
|
|
|
|
|
|
assert(!is_object_used(bookmark));
|
|
|
|
|
|
|
|
delete_bookmark(bookmark);
|
|
|
|
|
|
|
|
#ifdef BOOKMARKS_RESAVE
|
|
|
|
if (last) write_bookmarks();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct listbox_ops_messages bookmarks_messages = {
|
|
|
|
/* cant_delete_item */
|
|
|
|
N_("Sorry, but the bookmark \"%s\" cannot be deleted."),
|
|
|
|
/* cant_delete_used_item */
|
|
|
|
N_("Sorry, but the bookmark \"%s\" is being used by something else."),
|
|
|
|
/* cant_delete_folder */
|
|
|
|
N_("Sorry, but the folder \"%s\" cannot be deleted."),
|
|
|
|
/* cant_delete_used_folder */
|
|
|
|
N_("Sorry, but the folder \"%s\" is being used by something else."),
|
|
|
|
/* delete_marked_items_title */
|
|
|
|
N_("Delete marked bookmarks"),
|
|
|
|
/* delete_marked_items */
|
|
|
|
N_("Delete marked bookmarks?"),
|
|
|
|
/* delete_folder_title */
|
|
|
|
N_("Delete folder"),
|
|
|
|
/* delete_folder */
|
|
|
|
N_("Delete the folder \"%s\" and all bookmarks in it?"),
|
|
|
|
/* delete_item_title */
|
|
|
|
N_("Delete bookmark"),
|
2006-05-27 01:51:24 -04:00
|
|
|
/* delete_item; xgettext:c-format */
|
2005-09-15 09:58:31 -04:00
|
|
|
N_("Delete this bookmark?"),
|
|
|
|
/* clear_all_items_title */
|
|
|
|
N_("Clear all bookmarks"),
|
|
|
|
/* clear_all_items_title */
|
|
|
|
N_("Do you really want to remove all bookmarks?"),
|
|
|
|
};
|
|
|
|
|
2007-02-04 08:17:49 -05:00
|
|
|
static const struct listbox_ops bookmarks_listbox_ops = {
|
2005-09-15 09:58:31 -04:00
|
|
|
lock_bookmark,
|
|
|
|
unlock_bookmark,
|
|
|
|
is_bookmark_used,
|
|
|
|
get_bookmark_text,
|
|
|
|
get_bookmark_info,
|
|
|
|
get_bookmark_uri,
|
|
|
|
get_bookmark_root,
|
|
|
|
NULL,
|
|
|
|
can_delete_bookmark,
|
|
|
|
delete_bookmark_item,
|
|
|
|
NULL,
|
|
|
|
&bookmarks_messages,
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Bookmark manager stuff.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/* Callback for the "add" button in the bookmark manager */
|
|
|
|
static widget_handler_status_T
|
|
|
|
push_add_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
|
|
|
{
|
|
|
|
launch_bm_add_doc_dialog(dlg_data->win->term, dlg_data,
|
|
|
|
(struct session *) dlg_data->dlg->udata);
|
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
void launch_bm_search_doc_dialog(struct terminal *, struct dialog_data *,
|
|
|
|
struct session *);
|
|
|
|
|
|
|
|
|
|
|
|
/* Callback for the "search" button in the bookmark manager */
|
|
|
|
static widget_handler_status_T
|
|
|
|
push_search_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
|
|
|
{
|
|
|
|
launch_bm_search_doc_dialog(dlg_data->win->term, dlg_data,
|
|
|
|
(struct session *) dlg_data->dlg->udata);
|
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
move_bookmark_after_selected(struct bookmark *bookmark, struct bookmark *selected)
|
|
|
|
{
|
|
|
|
if (selected == bookmark->root
|
|
|
|
|| !selected
|
|
|
|
|| !selected->box_item
|
|
|
|
|| !bookmark->box_item)
|
|
|
|
return;
|
|
|
|
|
|
|
|
del_from_list(bookmark->box_item);
|
|
|
|
del_from_list(bookmark);
|
|
|
|
|
|
|
|
add_at_pos(selected, bookmark);
|
|
|
|
add_at_pos(selected->box_item, bookmark->box_item);
|
|
|
|
}
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
/** Add a bookmark; if called from the bookmark manager, also move
|
|
|
|
* the bookmark to the right place and select it in the manager.
|
|
|
|
* And possibly save the bookmarks.
|
|
|
|
*
|
|
|
|
* @param term
|
|
|
|
* The terminal whose user told ELinks to add the bookmark.
|
|
|
|
* Currently, @a term affects only the charset interpretation
|
|
|
|
* of @a title and @a url. In the future, this function could
|
|
|
|
* also display error messages in @a term.
|
|
|
|
*
|
|
|
|
* @param dlg_data
|
|
|
|
* The bookmark manager dialog, or NULL if the bookmark is being
|
|
|
|
* added without involving the bookmark manager. If @a dlg_data
|
|
|
|
* is not NULL, dlg_data->win->term should be @a term.
|
|
|
|
*
|
|
|
|
* @param title
|
|
|
|
* The title of the new bookmark, in the encoding of @a term.
|
|
|
|
* Must not be NULL. "-" means add a separator.
|
|
|
|
*
|
|
|
|
* @param url
|
|
|
|
* The URL of the new bookmark, in the encoding of @a term. NULL
|
|
|
|
* or "" means add a bookmark folder, unless @a title is "-". */
|
2005-09-15 09:58:31 -04:00
|
|
|
static void
|
2008-11-16 15:32:32 -05:00
|
|
|
do_add_bookmark(struct terminal *term, struct dialog_data *dlg_data,
|
|
|
|
unsigned char *title, unsigned char *url)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
2008-11-16 15:32:32 -05:00
|
|
|
int term_cp = get_terminal_codepage(term);
|
2005-09-15 09:58:31 -04:00
|
|
|
struct bookmark *bm = NULL;
|
|
|
|
struct bookmark *selected = NULL;
|
|
|
|
struct listbox_data *box = NULL;
|
|
|
|
|
|
|
|
if (dlg_data) {
|
|
|
|
box = get_dlg_listbox_data(dlg_data);
|
|
|
|
|
|
|
|
if (box->sel) {
|
2006-06-06 00:28:32 -04:00
|
|
|
selected = box->sel->udata;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
if (box->sel->type == BI_FOLDER && box->sel->expanded) {
|
|
|
|
bm = selected;
|
|
|
|
} else {
|
|
|
|
bm = selected->root;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
bm = add_bookmark_cp(bm, 1, term_cp, title, url);
|
2005-09-15 09:58:31 -04:00
|
|
|
if (!bm) return;
|
|
|
|
|
|
|
|
move_bookmark_after_selected(bm, selected);
|
|
|
|
|
|
|
|
#ifdef BOOKMARKS_RESAVE
|
|
|
|
write_bookmarks();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (dlg_data) {
|
|
|
|
struct widget_data *widget_data = dlg_data->widgets_data;
|
|
|
|
|
|
|
|
/* We touch only the actual bookmark dialog, not all of them;
|
|
|
|
* that's right, right? ;-) --pasky */
|
2006-05-27 20:12:08 -04:00
|
|
|
listbox_sel(widget_data, bm->box_item);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** ADD FOLDER *****************************************************/
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
/** Add a bookmark folder. This is called when the user pushes the OK
|
|
|
|
* button in the input dialog that asks for the folder name.
|
|
|
|
*
|
|
|
|
* @param dlg_data
|
|
|
|
* The bookmark manager. Must not be NULL.
|
|
|
|
*
|
|
|
|
* @param foldername
|
|
|
|
* The folder name that the user typed in the input dialog.
|
|
|
|
* This is in the charset of the terminal. */
|
2005-09-15 09:58:31 -04:00
|
|
|
static void
|
|
|
|
do_add_folder(struct dialog_data *dlg_data, unsigned char *foldername)
|
|
|
|
{
|
2008-11-16 15:32:32 -05:00
|
|
|
do_add_bookmark(dlg_data->win->term, dlg_data, foldername, NULL);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
/** Prepare to add a bookmark folder. This is called when the user
|
|
|
|
* pushes the "Add folder" button in the bookmark manager.
|
|
|
|
*
|
|
|
|
* @param dlg_data
|
|
|
|
* The bookmark manager. Must not be NULL.
|
|
|
|
*
|
|
|
|
* @param widget_data
|
|
|
|
* The "Add folder" button. */
|
2005-09-15 09:58:31 -04:00
|
|
|
static widget_handler_status_T
|
|
|
|
push_add_folder_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
|
|
|
{
|
|
|
|
input_dialog(dlg_data->win->term, NULL,
|
|
|
|
N_("Add folder"), N_("Folder name"),
|
|
|
|
dlg_data, NULL,
|
|
|
|
MAX_STR_LEN, NULL, 0, 0, NULL,
|
|
|
|
(void (*)(void *, unsigned char *)) do_add_folder,
|
|
|
|
NULL);
|
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** ADD SEPARATOR **************************************************/
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
/** Add a bookmark separator. This is called when the user pushes the
|
|
|
|
* "Add separator" button in the bookmark manager.
|
|
|
|
*
|
|
|
|
* @param dlg_data
|
|
|
|
* The bookmark manager. Must not be NULL.
|
|
|
|
*
|
|
|
|
* @param widget_data
|
|
|
|
* The "Add separator" button. */
|
2005-09-15 09:58:31 -04:00
|
|
|
static widget_handler_status_T
|
|
|
|
push_add_separator_button(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
|
|
|
{
|
2008-11-16 15:32:32 -05:00
|
|
|
do_add_bookmark(dlg_data->win->term, dlg_data, "-", "");
|
2005-09-15 09:58:31 -04:00
|
|
|
redraw_dialog(dlg_data, 1);
|
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** EDIT ***********************************************************/
|
|
|
|
|
|
|
|
/* Called when an edit is complete. */
|
|
|
|
static void
|
|
|
|
bookmark_edit_done(void *data) {
|
|
|
|
struct dialog *dlg = data;
|
|
|
|
struct bookmark *bm = (struct bookmark *) dlg->udata2;
|
2008-11-16 17:56:18 -05:00
|
|
|
struct dialog_data *parent_dlg_data = dlg->udata;
|
|
|
|
int term_cp = get_terminal_codepage(parent_dlg_data->win->term);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2008-11-16 17:56:18 -05:00
|
|
|
update_bookmark(bm, term_cp,
|
|
|
|
dlg->widgets[0].data, dlg->widgets[1].data);
|
2005-09-15 09:58:31 -04:00
|
|
|
object_unlock(bm);
|
|
|
|
|
|
|
|
#ifdef BOOKMARKS_RESAVE
|
|
|
|
write_bookmarks();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bookmark_edit_cancel(struct dialog *dlg) {
|
|
|
|
struct bookmark *bm = (struct bookmark *) dlg->udata2;
|
|
|
|
|
|
|
|
object_unlock(bm);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Called when the edit button is pushed */
|
|
|
|
static widget_handler_status_T
|
|
|
|
push_edit_button(struct dialog_data *dlg_data, struct widget_data *edit_btn)
|
|
|
|
{
|
|
|
|
struct listbox_data *box = get_dlg_listbox_data(dlg_data);
|
|
|
|
|
|
|
|
/* Follow the bookmark */
|
|
|
|
if (box->sel) {
|
|
|
|
struct bookmark *bm = (struct bookmark *) box->sel->udata;
|
2008-11-17 02:19:12 -05:00
|
|
|
int utf8_cp = get_cp_index("UTF-8");
|
|
|
|
int term_cp = get_terminal_codepage(dlg_data->win->term);
|
|
|
|
struct conv_table *convert_table;
|
|
|
|
|
|
|
|
convert_table = get_translation_table(utf8_cp, term_cp);
|
|
|
|
if (convert_table) {
|
|
|
|
unsigned char *title;
|
|
|
|
unsigned char *url;
|
|
|
|
|
|
|
|
title = convert_string(convert_table,
|
|
|
|
bm->title, strlen(bm->title),
|
|
|
|
term_cp, CSM_NONE,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
url = convert_string(convert_table,
|
|
|
|
bm->url, strlen(bm->url),
|
|
|
|
term_cp, CSM_NONE,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
if (title && url) {
|
|
|
|
object_lock(bm);
|
|
|
|
do_edit_dialog(dlg_data->win->term, 1,
|
|
|
|
N_("Edit bookmark"),
|
|
|
|
title, url,
|
|
|
|
(struct session *) dlg_data->dlg->udata,
|
|
|
|
dlg_data,
|
|
|
|
bookmark_edit_done,
|
|
|
|
bookmark_edit_cancel,
|
|
|
|
(void *) bm, EDIT_DLG_ADD);
|
|
|
|
}
|
|
|
|
mem_free_if(title);
|
|
|
|
mem_free_if(url);
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** MOVE ***********************************************************/
|
|
|
|
|
|
|
|
static struct bookmark *move_cache_root_avoid;
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_depths(struct listbox_item *parent)
|
|
|
|
{
|
|
|
|
struct listbox_item *item;
|
|
|
|
|
|
|
|
foreach (item, parent->child) {
|
|
|
|
item->depth = parent->depth + 1;
|
|
|
|
if (item->type == BI_FOLDER)
|
|
|
|
update_depths(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-21 09:46:23 -04:00
|
|
|
enum move_bookmark_flags {
|
|
|
|
MOVE_BOOKMARK_NONE = 0x00,
|
|
|
|
MOVE_BOOKMARK_MOVED = 0x01,
|
|
|
|
MOVE_BOOKMARK_CYCLE = 0x02
|
|
|
|
};
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
/* Traverse all bookmarks and move all marked items
|
2007-04-01 07:59:28 -04:00
|
|
|
* _into_ dest or, if insert_as_child is 0, _after_ dest. */
|
2006-05-21 09:46:23 -04:00
|
|
|
static enum move_bookmark_flags
|
2006-06-15 16:53:38 -04:00
|
|
|
do_move_bookmark(struct bookmark *dest, int insert_as_child,
|
2007-07-26 15:39:08 -04:00
|
|
|
LIST_OF(struct bookmark) *src, struct listbox_data *box)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
|
|
|
static int move_bookmark_event_id = EVENT_NONE;
|
|
|
|
struct bookmark *bm, *next;
|
2006-05-21 09:46:23 -04:00
|
|
|
enum move_bookmark_flags result = MOVE_BOOKMARK_NONE;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
set_event_id(move_bookmark_event_id, "bookmark-move");
|
|
|
|
|
|
|
|
foreachsafe (bm, next, *src) {
|
2006-05-21 09:46:23 -04:00
|
|
|
if (!bm->box_item->marked) {
|
|
|
|
/* Don't move this bookmark itself; but if
|
|
|
|
* it's a folder, then we'll look inside. */
|
|
|
|
} else if (bm == dest || bm == move_cache_root_avoid) {
|
|
|
|
/* Prevent moving a folder into itself. */
|
|
|
|
result |= MOVE_BOOKMARK_CYCLE;
|
|
|
|
} else {
|
2006-06-15 17:14:51 -04:00
|
|
|
struct hierbox_dialog_list_item *item;
|
|
|
|
|
2006-05-21 09:46:23 -04:00
|
|
|
result |= MOVE_BOOKMARK_MOVED;
|
2005-09-15 09:58:31 -04:00
|
|
|
bm->box_item->marked = 0;
|
|
|
|
|
2006-06-15 16:53:38 -04:00
|
|
|
trigger_event(move_bookmark_event_id, bm, dest);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2006-06-15 17:14:51 -04:00
|
|
|
foreach (item, bookmark_browser.dialogs) {
|
|
|
|
struct widget_data *widget_data;
|
|
|
|
struct listbox_data *box2;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2006-06-15 17:14:51 -04:00
|
|
|
widget_data = item->dlg_data->widgets_data;
|
|
|
|
box2 = get_listbox_widget_data(widget_data);
|
|
|
|
|
|
|
|
if (box2->top == bm->box_item)
|
|
|
|
listbox_sel_move(widget_data, 1);
|
|
|
|
}
|
2006-07-27 03:51:10 -04:00
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
del_from_list(bm->box_item);
|
|
|
|
del_from_list(bm);
|
2006-06-15 16:53:38 -04:00
|
|
|
if (insert_as_child) {
|
|
|
|
add_to_list(dest->child, bm);
|
|
|
|
add_to_list(dest->box_item->child, bm->box_item);
|
|
|
|
bm->root = dest;
|
|
|
|
insert_as_child = 0;
|
|
|
|
} else {
|
|
|
|
add_at_pos(dest, bm);
|
|
|
|
add_at_pos(dest->box_item, bm->box_item);
|
|
|
|
bm->root = dest->root;
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
bm->box_item->depth = bm->root
|
|
|
|
? bm->root->box_item->depth + 1
|
|
|
|
: 0;
|
|
|
|
|
|
|
|
if (bm->box_item->type == BI_FOLDER)
|
|
|
|
update_depths(bm->box_item);
|
|
|
|
|
|
|
|
dest = bm;
|
|
|
|
|
|
|
|
/* We don't want to care about anything marked inside
|
|
|
|
* of the marked folder, let's move it as a whole
|
|
|
|
* directly. I believe that this is more intuitive.
|
|
|
|
* --pasky */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bm->box_item->type == BI_FOLDER) {
|
2006-06-15 16:53:38 -04:00
|
|
|
result |= do_move_bookmark(dest, insert_as_child,
|
2006-05-21 09:46:23 -04:00
|
|
|
&bm->child, box);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
}
|
2006-05-21 09:46:23 -04:00
|
|
|
|
|
|
|
return result;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static widget_handler_status_T
|
|
|
|
push_move_button(struct dialog_data *dlg_data,
|
|
|
|
struct widget_data *blah)
|
|
|
|
{
|
|
|
|
struct listbox_data *box = get_dlg_listbox_data(dlg_data);
|
|
|
|
struct bookmark *dest = NULL;
|
2006-06-15 16:53:38 -04:00
|
|
|
int insert_as_child = 0;
|
2006-05-21 09:46:23 -04:00
|
|
|
enum move_bookmark_flags result;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
if (!box->sel) return EVENT_PROCESSED; /* nowhere to move to */
|
|
|
|
|
|
|
|
dest = box->sel->udata;
|
|
|
|
if (box->sel->type == BI_FOLDER && box->sel->expanded) {
|
2006-06-15 16:53:38 -04:00
|
|
|
insert_as_child = 1;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
/* Avoid recursion headaches (prevents moving a folder into itself). */
|
|
|
|
move_cache_root_avoid = NULL;
|
|
|
|
{
|
|
|
|
struct bookmark *bm = dest->root;
|
|
|
|
|
|
|
|
while (bm) {
|
|
|
|
if (bm->box_item->marked)
|
|
|
|
move_cache_root_avoid = bm;
|
|
|
|
bm = bm->root;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-15 16:53:38 -04:00
|
|
|
result = do_move_bookmark(dest, insert_as_child, &bookmarks, box);
|
2006-05-21 09:46:23 -04:00
|
|
|
if (result & MOVE_BOOKMARK_MOVED) {
|
|
|
|
bookmarks_set_dirty();
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
#ifdef BOOKMARKS_RESAVE
|
2006-05-21 09:46:23 -04:00
|
|
|
write_bookmarks();
|
2005-09-15 09:58:31 -04:00
|
|
|
#endif
|
2006-06-15 17:14:51 -04:00
|
|
|
update_hierbox_browser(&bookmark_browser);
|
2006-06-01 14:23:31 -04:00
|
|
|
}
|
|
|
|
#ifndef CONFIG_SMALL
|
|
|
|
else if (result & MOVE_BOOKMARK_CYCLE) {
|
2006-05-21 09:46:23 -04:00
|
|
|
/* If the user also selected other bookmarks, then
|
|
|
|
* they have already been moved, and this box doesn't
|
|
|
|
* appear. */
|
|
|
|
info_box(dlg_data->win->term, 0,
|
|
|
|
N_("Cannot move folder inside itself"), ALIGN_LEFT,
|
|
|
|
N_("You are trying to move the marked folder inside "
|
|
|
|
"itself. To move the folder to a different "
|
|
|
|
"location select the new location before pressing "
|
|
|
|
"the Move button."));
|
|
|
|
} else {
|
|
|
|
info_box(dlg_data->win->term, 0,
|
|
|
|
N_("Nothing to move"), ALIGN_LEFT,
|
|
|
|
N_("To move bookmarks, first mark all the bookmarks "
|
|
|
|
"(or folders) you want to move. This can be done "
|
|
|
|
"with the Insert key if you're using the default "
|
|
|
|
"key-bindings. An asterisk will appear near all "
|
|
|
|
"marked bookmarks. Now move to where you want to "
|
|
|
|
"have the stuff moved to, and press the \"Move\" "
|
|
|
|
"button."));
|
|
|
|
}
|
2006-06-01 14:23:31 -04:00
|
|
|
#endif /* ndef CONFIG_SMALL */
|
2006-05-21 09:46:23 -04:00
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
return EVENT_PROCESSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**** MANAGEMENT *****************************************************/
|
|
|
|
|
2007-02-04 06:54:07 -05:00
|
|
|
static const struct hierbox_browser_button bookmark_buttons[] = {
|
Here is a framework that detects cases where a PO file assigns
the same accelerator key to multiple buttons in a dialog box or
to multiple items in a menu. ELinks already has some support for
this but it requires the translator to run ELinks and manually
scan through all menus and dialogs. The attached changes make it
possible to quickly detect and list any conflicts, including ones
that can only occur on operating systems or configurations that
the translator is not currently using.
The changes have no immediate effect on the elinks executable or
the MO files. PO files become larger, however.
The scheme works like this:
- Like before, accelerator keys in translatable strings are
tagged with the tilde (~) character.
- Whenever a C source file defines an accelerator key, it must
assign one or more named "contexts" to it. The translations in
the PO files inherit these contexts. If multiple strings use
the same accelerator (case insensitive) in the same context,
that's a conflict and can be detected automatically.
- The contexts are defined with "gettext_accelerator_context"
comments in source files. These comments delimit regions where
all translatable strings containing tildes are given the same
contexts. There must be one special comment at the top of the
region; it lists the contexts assigned to that region. The
region automatically ends at the end of the function (found
with regexp /^\}/), but it can also be closed explicitly with
another special comment. The comments are formatted like this:
/* [gettext_accelerator_context(foo, bar, baz)]
begins a region that uses the contexts "foo", "bar", and "baz".
The comma is the delimiter; whitespace is optional.
[gettext_accelerator_context()]
ends the region. */
The scripts don't currently check whether this syntax occurs
inside or outside comments.
- The names of contexts consist of C identifiers delimited with
periods. I typically used the name of a function that sets
up a dialog, or the name of an array where the items of a
menu are listed. There is a special feature for static
functions: if the name begins with a period, then the period
will be replaced with the name of the source file and a colon.
- If a menu is programmatically generated from multiple parts,
of which some are never used together, so that it is safe to
use the same accelerators in them, then it is necessary to
define multiple contexts for the same menu. link_menu() in
src/viewer/text/link.c is the most complex example of this.
- During make update-po:
- A Perl script (po/gather-accelerator-contexts.pl) reads
po/elinks.pot, scans the source files listed in it for
"gettext_accelerator_context" comments, and rewrites
po/elinks.pot with "accelerator_context" comments that
indicate the contexts of each msgid: the union of all
contexts of all of its uses in the source files. It also
removes any "gettext_accelerator_context" comments that
xgettext --add-comments has copied to elinks.pot.
- If po/gather-accelerator-contexts.pl does not find any
contexts for some use of an msgid that seems to contain an
accelerator (because it contains a tilde), it warns. If the
tilde refers to e.g. "~/.elinks" and does not actually mark
an accelerator, the warning can be silenced by specifying the
special context "IGNORE", which the script otherwise ignores.
- msgmerge copies the "accelerator_context" comments from
po/elinks.pot to po/*.po. Translators do not edit those
comments.
- During make check-po:
- Another Perl script (po/check-accelerator-contexts.pl) reads
po/*.po and keeps track of which accelerators have been bound
in each context. It warns about any conflicts it finds.
This script does not access the C source files; thus it does
not matter if the line numbers in "#:" lines are out of date.
This implementation is not perfect and I am not proposing to
add it to the main source tree at this time. Specifically:
- It introduces compile-time dependencies on Perl and Locale::PO.
There should be a configure-time or compile-time check so that
the new features are skipped if the prerequisites are missing.
- When the scripts include msgstr strings in warnings, they
should transcode them from the charset of the PO file to the
one specified by the user's locale.
- It is not adequately documented (well, except perhaps here).
- po/check-accelerator-contexts.pl reports the same conflict
multiple times if it occurs in multiple contexts.
- The warning messages should include line numbers, so that users
of Emacs could conveniently edit the conflicting part of the PO
file. This is not feasible with the current version of
Locale::PO.
- Locale::PO does not understand #~ lines and spews warnings
about them. There is an ugly hack to hide these warnings.
- Jonas Fonseca suggested the script could propose accelerators
that are still available. This has not been implemented.
There are three files attached:
- po/gather-accelerator-contexts.pl: Augments elinks.pot with
context information.
- po/check-accelerator-contexts.pl: Checks conflicts.
- accelerator-contexts.diff: Makes po/Makefile run the scripts,
and adds special comments to source files.
2005-12-04 18:38:29 -05:00
|
|
|
/* [gettext_accelerator_context(.bookmark_buttons)] */
|
2005-09-15 09:58:31 -04:00
|
|
|
{ N_("~Goto"), push_hierbox_goto_button, 1 },
|
|
|
|
{ N_("~Edit"), push_edit_button, 0 },
|
|
|
|
{ N_("~Delete"), push_hierbox_delete_button, 0 },
|
|
|
|
{ N_("~Add"), push_add_button, 0 },
|
|
|
|
{ N_("Add se~parator"), push_add_separator_button, 0 },
|
|
|
|
{ N_("Add ~folder"), push_add_folder_button, 0 },
|
|
|
|
{ N_("~Move"), push_move_button, 0 },
|
|
|
|
{ N_("~Search"), push_search_button, 1 },
|
|
|
|
#if 0
|
|
|
|
/* This one is too dangerous, so just let user delete
|
|
|
|
* the bookmarks file if needed. --Zas */
|
|
|
|
{ N_("Clear"), push_hierbox_clear_button, 0 },
|
|
|
|
|
|
|
|
/* TODO: Would this be useful? --jonas */
|
2007-02-04 06:54:07 -05:00
|
|
|
{ N_("Save"), push_save_button, 0 },
|
2005-09-15 09:58:31 -04:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
struct_hierbox_browser(
|
|
|
|
bookmark_browser,
|
|
|
|
N_("Bookmark manager"),
|
|
|
|
bookmark_buttons,
|
|
|
|
&bookmarks_listbox_ops
|
|
|
|
);
|
|
|
|
|
|
|
|
/* Builds the "Bookmark manager" dialog */
|
|
|
|
void
|
|
|
|
bookmark_manager(struct session *ses)
|
|
|
|
{
|
|
|
|
free_last_searched_bookmark();
|
|
|
|
bookmark_browser.expansion_callback = bookmarks_set_dirty;
|
|
|
|
hierbox_browser(&bookmark_browser, ses);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
Bookmark search dialog.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* Searchs a substring either in title or url fields (ignoring
|
|
|
|
* case). If search_title and search_url are not empty, it selects bookmarks
|
|
|
|
* matching the first OR the second.
|
|
|
|
*
|
|
|
|
* Perhaps another behavior could be to search bookmarks matching both
|
|
|
|
* (replacing OR by AND), but it would break a cool feature: when on a page,
|
|
|
|
* opening search dialog will have fields corresponding to that page, so
|
|
|
|
* pressing ok will find any bookmark with that title or url, permitting a
|
|
|
|
* rapid search of an already existing bookmark. --Zas */
|
|
|
|
|
|
|
|
struct bookmark_search_ctx {
|
2008-11-19 03:57:10 -05:00
|
|
|
unsigned char *url; /* UTF-8 */
|
|
|
|
unsigned char *title; /* system charset */
|
2005-09-15 09:58:31 -04:00
|
|
|
int found;
|
|
|
|
int offset;
|
2008-11-19 03:57:10 -05:00
|
|
|
int utf8_cp;
|
|
|
|
int system_cp;
|
2005-09-15 09:58:31 -04:00
|
|
|
};
|
|
|
|
|
2008-11-19 03:57:10 -05:00
|
|
|
#define NULL_BOOKMARK_SEARCH_CTX {NULL, NULL, 0, 0, -1, -1}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
static int
|
|
|
|
test_search(struct listbox_item *item, void *data_, int *offset)
|
|
|
|
{
|
|
|
|
struct bookmark_search_ctx *ctx = data_;
|
|
|
|
|
|
|
|
if (!ctx->offset) {
|
|
|
|
ctx->found = 0; /* ignore possible match on first item */
|
|
|
|
} else {
|
|
|
|
struct bookmark *bm = item->udata;
|
|
|
|
|
|
|
|
assert(ctx->title && ctx->url);
|
|
|
|
|
2016-04-20 14:11:08 -04:00
|
|
|
ctx->found = (*ctx->url && c_strcasestr((const char *)bm->url, (const char *)ctx->url));
|
2008-11-19 03:57:10 -05:00
|
|
|
if (!ctx->found && *ctx->title) {
|
|
|
|
/* The comparison of bookmark titles should
|
|
|
|
* be case-insensitive and locale-sensitive
|
|
|
|
* (Turkish dotless i). ELinks doesn't have
|
|
|
|
* such a function for UTF-8. The best we
|
|
|
|
* have is strcasestr, which uses the system
|
|
|
|
* charset. So convert bm->title to that.
|
|
|
|
* (ctx->title has already been converted.) */
|
|
|
|
struct conv_table *convert_table;
|
|
|
|
unsigned char *title = NULL;
|
|
|
|
|
|
|
|
convert_table = get_translation_table(ctx->utf8_cp,
|
|
|
|
ctx->system_cp);
|
|
|
|
if (convert_table) {
|
|
|
|
title = convert_string(convert_table,
|
|
|
|
bm->title,
|
|
|
|
strlen(bm->title),
|
|
|
|
ctx->system_cp,
|
|
|
|
CSM_NONE, NULL,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (title) {
|
2016-04-20 14:11:08 -04:00
|
|
|
ctx->found = (strcasestr((const char *)title, (const char *)ctx->title)
|
2009-03-01 02:21:29 -05:00
|
|
|
!= NULL);
|
2008-11-19 03:57:10 -05:00
|
|
|
mem_free(title);
|
|
|
|
}
|
|
|
|
/** @todo Tell the user that the string could
|
|
|
|
* not be converted. */
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
if (ctx->found) *offset = 0;
|
|
|
|
}
|
|
|
|
ctx->offset++;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-19 03:57:10 -05:00
|
|
|
/* Last searched values. Both are in UTF-8. (The title could be kept
|
|
|
|
* in the system charset, but that would be a bit risky, because
|
|
|
|
* setlocale calls from Lua scripts can change the system charset.) */
|
2005-09-15 09:58:31 -04:00
|
|
|
static unsigned char *bm_last_searched_title = NULL;
|
|
|
|
static unsigned char *bm_last_searched_url = NULL;
|
|
|
|
|
|
|
|
void
|
|
|
|
free_last_searched_bookmark(void)
|
|
|
|
{
|
|
|
|
mem_free_set(&bm_last_searched_title, NULL);
|
|
|
|
mem_free_set(&bm_last_searched_url, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2008-11-19 03:57:10 -05:00
|
|
|
memorize_last_searched_bookmark(const unsigned char *title,
|
|
|
|
const unsigned char *url)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
|
|
|
/* Memorize last searched title */
|
2008-11-19 03:57:10 -05:00
|
|
|
mem_free_set(&bm_last_searched_title, stracpy(title));
|
2005-09-15 09:58:31 -04:00
|
|
|
if (!bm_last_searched_title) return 0;
|
|
|
|
|
|
|
|
/* Memorize last searched url */
|
2008-11-19 03:57:10 -05:00
|
|
|
mem_free_set(&bm_last_searched_url, stracpy(url));
|
2005-09-15 09:58:31 -04:00
|
|
|
if (!bm_last_searched_url) {
|
2006-06-06 01:08:01 -04:00
|
|
|
mem_free_set(&bm_last_searched_title, NULL);
|
2005-09-15 09:58:31 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search bookmarks */
|
|
|
|
static void
|
|
|
|
bookmark_search_do(void *data)
|
|
|
|
{
|
|
|
|
struct dialog *dlg = data;
|
|
|
|
struct bookmark_search_ctx ctx = NULL_BOOKMARK_SEARCH_CTX;
|
|
|
|
struct listbox_data *box;
|
|
|
|
struct dialog_data *dlg_data;
|
2008-11-19 03:57:10 -05:00
|
|
|
struct conv_table *convert_table;
|
|
|
|
int term_cp;
|
|
|
|
unsigned char *url_term;
|
|
|
|
unsigned char *title_term;
|
|
|
|
unsigned char *title_utf8 = NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2007-03-11 06:22:02 -04:00
|
|
|
assertm(dlg->udata != NULL, "Bookmark search with NULL udata in dialog");
|
2005-09-15 09:58:31 -04:00
|
|
|
if_assert_failed return;
|
|
|
|
|
|
|
|
dlg_data = (struct dialog_data *) dlg->udata;
|
2008-11-19 03:57:10 -05:00
|
|
|
term_cp = get_terminal_codepage(dlg_data->win->term);
|
|
|
|
ctx.system_cp = get_cp_index("System");
|
|
|
|
ctx.utf8_cp = get_cp_index("UTF-8");
|
|
|
|
|
|
|
|
title_term = dlg->widgets[0].data; /* need not be freed */
|
|
|
|
url_term = dlg->widgets[1].data; /* likewise */
|
|
|
|
|
|
|
|
convert_table = get_translation_table(term_cp, ctx.system_cp);
|
|
|
|
if (!convert_table) goto free_all;
|
|
|
|
ctx.title = convert_string(convert_table,
|
|
|
|
title_term, strlen(title_term),
|
|
|
|
ctx.system_cp, CSM_NONE, NULL, NULL, NULL);
|
|
|
|
if (!ctx.title) goto free_all;
|
|
|
|
|
|
|
|
convert_table = get_translation_table(term_cp, ctx.utf8_cp);
|
|
|
|
if (!convert_table) goto free_all;
|
|
|
|
ctx.url = convert_string(convert_table,
|
|
|
|
url_term, strlen(url_term),
|
|
|
|
ctx.utf8_cp, CSM_NONE, NULL, NULL, NULL);
|
|
|
|
if (!ctx.url) goto free_all;
|
|
|
|
title_utf8 = convert_string(convert_table,
|
|
|
|
title_term, strlen(title_term),
|
|
|
|
ctx.utf8_cp, CSM_NONE, NULL, NULL, NULL);
|
|
|
|
if (!title_utf8) goto free_all;
|
|
|
|
|
|
|
|
if (!memorize_last_searched_bookmark(title_utf8, ctx.url))
|
|
|
|
goto free_all;
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
box = get_dlg_listbox_data(dlg_data);
|
|
|
|
|
|
|
|
traverse_listbox_items_list(box->sel, box, 0, 0, test_search, &ctx);
|
2008-11-19 03:57:10 -05:00
|
|
|
if (!ctx.found) goto free_all;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
listbox_sel_move(dlg_data->widgets_data, ctx.offset - 1);
|
|
|
|
|
2008-11-19 03:57:10 -05:00
|
|
|
free_all:
|
|
|
|
mem_free_if(ctx.title);
|
|
|
|
mem_free_if(ctx.url);
|
|
|
|
mem_free_if(title_utf8);
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
static void
|
|
|
|
launch_bm_search_doc_dialog(struct terminal *term,
|
|
|
|
struct dialog_data *parent,
|
|
|
|
struct session *ses)
|
|
|
|
{
|
2008-11-19 03:57:10 -05:00
|
|
|
unsigned char *title = NULL;
|
|
|
|
unsigned char *url = NULL;
|
|
|
|
|
|
|
|
if (bm_last_searched_title && bm_last_searched_url) {
|
|
|
|
int utf8_cp, term_cp;
|
|
|
|
struct conv_table *convert_table;
|
|
|
|
|
|
|
|
utf8_cp = get_cp_index("UTF-8");
|
|
|
|
term_cp = get_terminal_codepage(term);
|
|
|
|
|
|
|
|
convert_table = get_translation_table(utf8_cp, term_cp);
|
|
|
|
if (convert_table) {
|
|
|
|
title = convert_string(convert_table, bm_last_searched_title,
|
|
|
|
strlen(bm_last_searched_title), term_cp,
|
|
|
|
CSM_NONE, NULL, NULL, NULL);
|
|
|
|
url = convert_string(convert_table, bm_last_searched_url,
|
|
|
|
strlen(bm_last_searched_url), term_cp,
|
|
|
|
CSM_NONE, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
if (!title || !url) {
|
|
|
|
mem_free_set(&title, NULL);
|
|
|
|
mem_free_set(&url, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
do_edit_dialog(term, 1, N_("Search bookmarks"),
|
2008-11-19 03:57:10 -05:00
|
|
|
title, url,
|
2005-09-15 09:58:31 -04:00
|
|
|
ses, parent, bookmark_search_do, NULL, NULL,
|
|
|
|
EDIT_DLG_SEARCH);
|
2008-11-19 03:57:10 -05:00
|
|
|
|
|
|
|
mem_free_if(title);
|
|
|
|
mem_free_if(url);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
Bookmark add dialog.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
|
|
/* Adds the bookmark */
|
|
|
|
static void
|
|
|
|
bookmark_add_add(void *data)
|
|
|
|
{
|
|
|
|
struct dialog *dlg = data;
|
|
|
|
struct dialog_data *dlg_data = (struct dialog_data *) dlg->udata;
|
2008-11-16 15:32:32 -05:00
|
|
|
struct terminal *term = dlg->udata2;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
do_add_bookmark(term, dlg_data, dlg->widgets[0].data, dlg->widgets[1].data);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
/** Open a dialog box for adding a bookmark.
|
|
|
|
*
|
|
|
|
* @param term
|
|
|
|
* The terminal in which the dialog box should appear.
|
|
|
|
*
|
|
|
|
* @param parent
|
|
|
|
* The bookmark manager, or NULL if the user requested this action
|
|
|
|
* from somewhere else.
|
|
|
|
*
|
|
|
|
* @param ses
|
|
|
|
* If @a title or @a url is NULL, get defaults from the current
|
|
|
|
* document of @a ses.
|
|
|
|
*
|
|
|
|
* @param title
|
|
|
|
* The initial title of the new bookmark, in the encoding of @a term.
|
|
|
|
* NULL means use @a ses.
|
|
|
|
*
|
|
|
|
* @param url
|
|
|
|
* The initial URL of the new bookmark, in the encoding of @a term.
|
|
|
|
* NULL means use @a ses. */
|
2005-09-15 09:58:31 -04:00
|
|
|
void
|
|
|
|
launch_bm_add_dialog(struct terminal *term,
|
|
|
|
struct dialog_data *parent,
|
|
|
|
struct session *ses,
|
|
|
|
unsigned char *title,
|
|
|
|
unsigned char *url)
|
|
|
|
{
|
2008-11-16 15:32:32 -05:00
|
|
|
/* When the user eventually pushes the OK button, BFU calls
|
|
|
|
* bookmark_add_add() and gives it the struct dialog * as the
|
|
|
|
* void * parameter. However, bookmark_add_add() also needs
|
|
|
|
* to know the struct terminal *, and there is no way to get
|
|
|
|
* that from struct dialog. The other bookmark dialogs work
|
|
|
|
* around that by making dialog.udata point to the struct
|
|
|
|
* dialog_data of the bookmark manager, but the "Add bookmark"
|
|
|
|
* dialog can be triggered with ACT_MAIN_ADD_BOOKMARK, which
|
|
|
|
* does not involve the bookmark manager at all.
|
|
|
|
*
|
|
|
|
* The solution here is to save the struct terminal * in
|
|
|
|
* dialog.udata2, which the "Edit bookmark" dialog uses for
|
|
|
|
* struct bookmark *. When adding a new bookmark, we don't
|
|
|
|
* need a pointer to an existing one, of course. */
|
2005-09-15 09:58:31 -04:00
|
|
|
do_edit_dialog(term, 1, N_("Add bookmark"), title, url, ses,
|
2008-11-16 15:32:32 -05:00
|
|
|
parent, bookmark_add_add, NULL, term, EDIT_DLG_ADD);
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
launch_bm_add_doc_dialog(struct terminal *term,
|
|
|
|
struct dialog_data *parent,
|
|
|
|
struct session *ses)
|
|
|
|
{
|
|
|
|
launch_bm_add_dialog(term, parent, ses, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
launch_bm_add_link_dialog(struct terminal *term,
|
|
|
|
struct dialog_data *parent,
|
|
|
|
struct session *ses)
|
|
|
|
{
|
|
|
|
unsigned char title[MAX_STR_LEN], url[MAX_STR_LEN];
|
|
|
|
|
|
|
|
launch_bm_add_dialog(term, parent, ses,
|
|
|
|
get_current_link_name(ses, title, MAX_STR_LEN),
|
|
|
|
get_current_link_url(ses, url, MAX_STR_LEN));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************\
|
|
|
|
Bookmark tabs dialog.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
2008-11-16 15:32:32 -05:00
|
|
|
static void
|
|
|
|
bookmark_terminal_tabs_ok(void *term_void, unsigned char *foldername)
|
|
|
|
{
|
|
|
|
struct terminal *const term = term_void;
|
|
|
|
int from_cp = get_terminal_codepage(term);
|
|
|
|
int to_cp = get_cp_index("UTF-8");
|
|
|
|
struct conv_table *convert_table;
|
|
|
|
unsigned char *converted;
|
|
|
|
|
|
|
|
convert_table = get_translation_table(from_cp, to_cp);
|
|
|
|
if (convert_table == NULL) return; /** @todo Report the error */
|
|
|
|
|
|
|
|
converted = convert_string(convert_table,
|
|
|
|
foldername, strlen(foldername),
|
|
|
|
to_cp, CSM_NONE,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
if (converted == NULL) return; /** @todo Report the error */
|
|
|
|
|
|
|
|
bookmark_terminal_tabs(term_void, converted);
|
|
|
|
mem_free(converted);
|
|
|
|
}
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
void
|
|
|
|
bookmark_terminal_tabs_dialog(struct terminal *term)
|
|
|
|
{
|
|
|
|
struct string string;
|
|
|
|
|
|
|
|
if (!init_string(&string)) return;
|
|
|
|
|
|
|
|
add_to_string(&string, _("Saved session", term));
|
|
|
|
|
|
|
|
#ifdef HAVE_STRFTIME
|
|
|
|
add_to_string(&string, " - ");
|
2007-08-28 12:41:18 -04:00
|
|
|
add_date_to_string(&string, get_opt_str("ui.date_format", NULL), NULL);
|
2005-09-15 09:58:31 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
input_dialog(term, NULL,
|
|
|
|
N_("Bookmark tabs"), N_("Enter folder name"),
|
|
|
|
term, NULL,
|
|
|
|
MAX_STR_LEN, string.source, 0, 0, NULL,
|
2008-11-16 15:32:32 -05:00
|
|
|
bookmark_terminal_tabs_ok, NULL);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
done_string(&string);
|
|
|
|
}
|