1 /* Bookmarks dialogs */
4 #define _GNU_SOURCE /* XXX: we _WANT_ strcasestr() ! */
15 #include "bfu/dialog.h"
16 #include "bfu/hierbox.h"
17 #include "bfu/listbox.h"
18 #include "bookmarks/bookmarks.h"
19 #include "bookmarks/dialogs.h"
20 #include "dialogs/edit.h"
21 #include "intl/gettext/libintl.h"
22 #include "main/object.h"
23 #include "protocol/uri.h"
24 #include "session/session.h"
25 #include "terminal/terminal.h"
26 #include "util/conv.h"
27 #include "util/error.h"
28 #include "util/memory.h"
29 #include "util/time.h"
32 /* Whether to save bookmarks after each modification of their list
33 * (add/modify/delete). */
34 #define BOOKMARKS_RESAVE 1
38 lock_bookmark(struct listbox_item
*item
)
40 object_lock((struct bookmark
*) item
->udata
);
44 unlock_bookmark(struct listbox_item
*item
)
46 object_unlock((struct bookmark
*) item
->udata
);
50 is_bookmark_used(struct listbox_item
*item
)
52 return is_object_used((struct bookmark
*) item
->udata
);
55 static unsigned char *
56 get_bookmark_text(struct listbox_item
*item
, struct terminal
*term
)
58 struct bookmark
*bookmark
= item
->udata
;
59 int utf8_cp
= get_cp_index("UTF-8");
60 int term_cp
= get_terminal_codepage(term
);
61 struct conv_table
*convert_table
;
63 convert_table
= get_translation_table(utf8_cp
, term_cp
);
64 if (!convert_table
) return NULL
;
66 return convert_string(convert_table
,
67 bookmark
->title
, strlen(bookmark
->title
),
68 term_cp
, CSM_NONE
, NULL
, NULL
, NULL
);
71 /** A callback for convert_string(). This ignores errors and can
72 * result in truncated strings if out of memory. Accordingly, the
73 * resulting string may be displayed in the UI but should not be saved
74 * to a file or given to another program. */
76 add_converted_bytes_to_string(void *data
, unsigned char *buf
, int buflen
)
78 struct string
*string
= data
;
80 add_bytes_to_string(string
, buf
, buflen
); /* ignore errors */
83 static unsigned char *
84 get_bookmark_info(struct listbox_item
*item
, struct terminal
*term
)
86 struct bookmark
*bookmark
= item
->udata
;
87 int utf8_cp
= get_cp_index("UTF-8");
88 int term_cp
= get_terminal_codepage(term
);
89 struct conv_table
*convert_table
;
92 if (item
->type
== BI_FOLDER
) return NULL
;
93 convert_table
= get_translation_table(utf8_cp
, term_cp
);
94 if (!convert_table
) return NULL
;
95 if (!init_string(&info
)) return NULL
;
97 add_format_to_string(&info
, "%s: ", _("Title", term
));
98 convert_string(convert_table
, bookmark
->title
, strlen(bookmark
->title
),
99 term_cp
, CSM_NONE
, NULL
,
100 add_converted_bytes_to_string
, &info
);
101 add_format_to_string(&info
, "\n%s: ", _("URL", term
));
102 convert_string(convert_table
, bookmark
->url
, strlen(bookmark
->url
),
103 term_cp
, CSM_NONE
, NULL
,
104 add_converted_bytes_to_string
, &info
);
110 get_bookmark_uri(struct listbox_item
*item
)
112 struct bookmark
*bookmark
= item
->udata
;
114 /** @todo Bug 1066: Tell the URI layer that bookmark->url is UTF-8. */
115 return bookmark
->url
&& *bookmark
->url
116 ? get_translated_uri(bookmark
->url
, NULL
) : NULL
;
119 static struct listbox_item
*
120 get_bookmark_root(struct listbox_item
*item
)
122 struct bookmark
*bookmark
= item
->udata
;
124 return bookmark
->root
? bookmark
->root
->box_item
: NULL
;
128 can_delete_bookmark(struct listbox_item
*item
)
134 delete_bookmark_item(struct listbox_item
*item
, int last
)
136 struct bookmark
*bookmark
= item
->udata
;
138 assert(!is_object_used(bookmark
));
140 delete_bookmark(bookmark
);
142 #ifdef BOOKMARKS_RESAVE
143 if (last
) write_bookmarks();
147 static struct listbox_ops_messages bookmarks_messages
= {
148 /* cant_delete_item */
149 N_("Sorry, but the bookmark \"%s\" cannot be deleted."),
150 /* cant_delete_used_item */
151 N_("Sorry, but the bookmark \"%s\" is being used by something else."),
152 /* cant_delete_folder */
153 N_("Sorry, but the folder \"%s\" cannot be deleted."),
154 /* cant_delete_used_folder */
155 N_("Sorry, but the folder \"%s\" is being used by something else."),
156 /* delete_marked_items_title */
157 N_("Delete marked bookmarks"),
158 /* delete_marked_items */
159 N_("Delete marked bookmarks?"),
160 /* delete_folder_title */
163 N_("Delete the folder \"%s\" and all bookmarks in it?"),
164 /* delete_item_title */
165 N_("Delete bookmark"),
166 /* delete_item; xgettext:c-format */
167 N_("Delete this bookmark?"),
168 /* clear_all_items_title */
169 N_("Clear all bookmarks"),
170 /* clear_all_items_title */
171 N_("Do you really want to remove all bookmarks?"),
174 static const struct listbox_ops bookmarks_listbox_ops
= {
184 delete_bookmark_item
,
189 /****************************************************************************
190 Bookmark manager stuff.
191 ****************************************************************************/
193 /* Callback for the "add" button in the bookmark manager */
194 static widget_handler_status_T
195 push_add_button(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
197 launch_bm_add_doc_dialog(dlg_data
->win
->term
, dlg_data
,
198 (struct session
*) dlg_data
->dlg
->udata
);
199 return EVENT_PROCESSED
;
204 void launch_bm_search_doc_dialog(struct terminal
*, struct dialog_data
*,
208 /* Callback for the "search" button in the bookmark manager */
209 static widget_handler_status_T
210 push_search_button(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
212 launch_bm_search_doc_dialog(dlg_data
->win
->term
, dlg_data
,
213 (struct session
*) dlg_data
->dlg
->udata
);
214 return EVENT_PROCESSED
;
219 move_bookmark_after_selected(struct bookmark
*bookmark
, struct bookmark
*selected
)
221 if (selected
== bookmark
->root
223 || !selected
->box_item
224 || !bookmark
->box_item
)
227 del_from_list(bookmark
->box_item
);
228 del_from_list(bookmark
);
230 add_at_pos(selected
, bookmark
);
231 add_at_pos(selected
->box_item
, bookmark
->box_item
);
234 /** Add a bookmark; if called from the bookmark manager, also move
235 * the bookmark to the right place and select it in the manager.
236 * And possibly save the bookmarks.
239 * The terminal whose user told ELinks to add the bookmark.
240 * Currently, @a term affects only the charset interpretation
241 * of @a title and @a url. In the future, this function could
242 * also display error messages in @a term.
245 * The bookmark manager dialog, or NULL if the bookmark is being
246 * added without involving the bookmark manager. If @a dlg_data
247 * is not NULL, dlg_data->win->term should be @a term.
250 * The title of the new bookmark, in the encoding of @a term.
251 * Must not be NULL. "-" means add a separator.
254 * The URL of the new bookmark, in the encoding of @a term. NULL
255 * or "" means add a bookmark folder, unless @a title is "-". */
257 do_add_bookmark(struct terminal
*term
, struct dialog_data
*dlg_data
,
258 unsigned char *title
, unsigned char *url
)
260 int term_cp
= get_terminal_codepage(term
);
261 struct bookmark
*bm
= NULL
;
262 struct bookmark
*selected
= NULL
;
263 struct listbox_data
*box
= NULL
;
266 box
= get_dlg_listbox_data(dlg_data
);
269 selected
= box
->sel
->udata
;
271 if (box
->sel
->type
== BI_FOLDER
&& box
->sel
->expanded
) {
279 bm
= add_bookmark_cp(bm
, 1, term_cp
, title
, url
);
282 move_bookmark_after_selected(bm
, selected
);
284 #ifdef BOOKMARKS_RESAVE
289 struct widget_data
*widget_data
= dlg_data
->widgets_data
;
291 /* We touch only the actual bookmark dialog, not all of them;
292 * that's right, right? ;-) --pasky */
293 listbox_sel(widget_data
, bm
->box_item
);
298 /**** ADD FOLDER *****************************************************/
300 /** Add a bookmark folder. This is called when the user pushes the OK
301 * button in the input dialog that asks for the folder name.
304 * The bookmark manager. Must not be NULL.
307 * The folder name that the user typed in the input dialog.
308 * This is in the charset of the terminal. */
310 do_add_folder(struct dialog_data
*dlg_data
, unsigned char *foldername
)
312 do_add_bookmark(dlg_data
->win
->term
, dlg_data
, foldername
, NULL
);
315 /** Prepare to add a bookmark folder. This is called when the user
316 * pushes the "Add folder" button in the bookmark manager.
319 * The bookmark manager. Must not be NULL.
322 * The "Add folder" button. */
323 static widget_handler_status_T
324 push_add_folder_button(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
326 input_dialog(dlg_data
->win
->term
, NULL
,
327 N_("Add folder"), N_("Folder name"),
329 MAX_STR_LEN
, NULL
, 0, 0, NULL
,
330 (void (*)(void *, unsigned char *)) do_add_folder
,
332 return EVENT_PROCESSED
;
336 /**** ADD SEPARATOR **************************************************/
338 /** Add a bookmark separator. This is called when the user pushes the
339 * "Add separator" button in the bookmark manager.
342 * The bookmark manager. Must not be NULL.
345 * The "Add separator" button. */
346 static widget_handler_status_T
347 push_add_separator_button(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
349 do_add_bookmark(dlg_data
->win
->term
, dlg_data
, "-", "");
350 redraw_dialog(dlg_data
, 1);
351 return EVENT_PROCESSED
;
355 /**** EDIT ***********************************************************/
357 /* Called when an edit is complete. */
359 bookmark_edit_done(void *data
) {
360 struct dialog
*dlg
= data
;
361 struct bookmark
*bm
= (struct bookmark
*) dlg
->udata2
;
362 struct dialog_data
*parent_dlg_data
= dlg
->udata
;
363 int term_cp
= get_terminal_codepage(parent_dlg_data
->win
->term
);
365 update_bookmark(bm
, term_cp
,
366 dlg
->widgets
[0].data
, dlg
->widgets
[1].data
);
369 #ifdef BOOKMARKS_RESAVE
375 bookmark_edit_cancel(struct dialog
*dlg
) {
376 struct bookmark
*bm
= (struct bookmark
*) dlg
->udata2
;
381 /* Called when the edit button is pushed */
382 static widget_handler_status_T
383 push_edit_button(struct dialog_data
*dlg_data
, struct widget_data
*edit_btn
)
385 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
387 /* Follow the bookmark */
389 struct bookmark
*bm
= (struct bookmark
*) box
->sel
->udata
;
390 int utf8_cp
= get_cp_index("UTF-8");
391 int term_cp
= get_terminal_codepage(dlg_data
->win
->term
);
392 struct conv_table
*convert_table
;
394 convert_table
= get_translation_table(utf8_cp
, term_cp
);
396 unsigned char *title
;
399 title
= convert_string(convert_table
,
400 bm
->title
, strlen(bm
->title
),
403 url
= convert_string(convert_table
,
404 bm
->url
, strlen(bm
->url
),
409 do_edit_dialog(dlg_data
->win
->term
, 1,
412 (struct session
*) dlg_data
->dlg
->udata
,
415 bookmark_edit_cancel
,
416 (void *) bm
, EDIT_DLG_ADD
);
423 return EVENT_PROCESSED
;
427 /**** MOVE ***********************************************************/
429 static struct bookmark
*move_cache_root_avoid
;
432 update_depths(struct listbox_item
*parent
)
434 struct listbox_item
*item
;
436 foreach (item
, parent
->child
) {
437 item
->depth
= parent
->depth
+ 1;
438 if (item
->type
== BI_FOLDER
)
443 enum move_bookmark_flags
{
444 MOVE_BOOKMARK_NONE
= 0x00,
445 MOVE_BOOKMARK_MOVED
= 0x01,
446 MOVE_BOOKMARK_CYCLE
= 0x02
449 /* Traverse all bookmarks and move all marked items
450 * _into_ dest or, if insert_as_child is 0, _after_ dest. */
451 static enum move_bookmark_flags
452 do_move_bookmark(struct bookmark
*dest
, int insert_as_child
,
453 LIST_OF(struct bookmark
) *src
, struct listbox_data
*box
)
455 static int move_bookmark_event_id
= EVENT_NONE
;
456 struct bookmark
*bm
, *next
;
457 enum move_bookmark_flags result
= MOVE_BOOKMARK_NONE
;
459 set_event_id(move_bookmark_event_id
, "bookmark-move");
461 foreachsafe (bm
, next
, *src
) {
462 if (!bm
->box_item
->marked
) {
463 /* Don't move this bookmark itself; but if
464 * it's a folder, then we'll look inside. */
465 } else if (bm
== dest
|| bm
== move_cache_root_avoid
) {
466 /* Prevent moving a folder into itself. */
467 result
|= MOVE_BOOKMARK_CYCLE
;
469 struct hierbox_dialog_list_item
*item
;
471 result
|= MOVE_BOOKMARK_MOVED
;
472 bm
->box_item
->marked
= 0;
474 trigger_event(move_bookmark_event_id
, bm
, dest
);
476 foreach (item
, bookmark_browser
.dialogs
) {
477 struct widget_data
*widget_data
;
478 struct listbox_data
*box2
;
480 widget_data
= item
->dlg_data
->widgets_data
;
481 box2
= get_listbox_widget_data(widget_data
);
483 if (box2
->top
== bm
->box_item
)
484 listbox_sel_move(widget_data
, 1);
487 del_from_list(bm
->box_item
);
489 if (insert_as_child
) {
490 add_to_list(dest
->child
, bm
);
491 add_to_list(dest
->box_item
->child
, bm
->box_item
);
495 add_at_pos(dest
, bm
);
496 add_at_pos(dest
->box_item
, bm
->box_item
);
497 bm
->root
= dest
->root
;
500 bm
->box_item
->depth
= bm
->root
501 ? bm
->root
->box_item
->depth
+ 1
504 if (bm
->box_item
->type
== BI_FOLDER
)
505 update_depths(bm
->box_item
);
509 /* We don't want to care about anything marked inside
510 * of the marked folder, let's move it as a whole
511 * directly. I believe that this is more intuitive.
516 if (bm
->box_item
->type
== BI_FOLDER
) {
517 result
|= do_move_bookmark(dest
, insert_as_child
,
525 static widget_handler_status_T
526 push_move_button(struct dialog_data
*dlg_data
,
527 struct widget_data
*blah
)
529 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
530 struct bookmark
*dest
= NULL
;
531 int insert_as_child
= 0;
532 enum move_bookmark_flags result
;
534 if (!box
->sel
) return EVENT_PROCESSED
; /* nowhere to move to */
536 dest
= box
->sel
->udata
;
537 if (box
->sel
->type
== BI_FOLDER
&& box
->sel
->expanded
) {
540 /* Avoid recursion headaches (prevents moving a folder into itself). */
541 move_cache_root_avoid
= NULL
;
543 struct bookmark
*bm
= dest
->root
;
546 if (bm
->box_item
->marked
)
547 move_cache_root_avoid
= bm
;
552 result
= do_move_bookmark(dest
, insert_as_child
, &bookmarks
, box
);
553 if (result
& MOVE_BOOKMARK_MOVED
) {
554 bookmarks_set_dirty();
556 #ifdef BOOKMARKS_RESAVE
559 update_hierbox_browser(&bookmark_browser
);
562 else if (result
& MOVE_BOOKMARK_CYCLE
) {
563 /* If the user also selected other bookmarks, then
564 * they have already been moved, and this box doesn't
566 info_box(dlg_data
->win
->term
, 0,
567 N_("Cannot move folder inside itself"), ALIGN_LEFT
,
568 N_("You are trying to move the marked folder inside "
569 "itself. To move the folder to a different "
570 "location select the new location before pressing "
571 "the Move button."));
573 info_box(dlg_data
->win
->term
, 0,
574 N_("Nothing to move"), ALIGN_LEFT
,
575 N_("To move bookmarks, first mark all the bookmarks "
576 "(or folders) you want to move. This can be done "
577 "with the Insert key if you're using the default "
578 "key-bindings. An asterisk will appear near all "
579 "marked bookmarks. Now move to where you want to "
580 "have the stuff moved to, and press the \"Move\" "
583 #endif /* ndef CONFIG_SMALL */
585 return EVENT_PROCESSED
;
589 /**** MANAGEMENT *****************************************************/
591 static const struct hierbox_browser_button bookmark_buttons
[] = {
592 /* [gettext_accelerator_context(.bookmark_buttons)] */
593 { N_("~Goto"), push_hierbox_goto_button
, 1 },
594 { N_("~Edit"), push_edit_button
, 0 },
595 { N_("~Delete"), push_hierbox_delete_button
, 0 },
596 { N_("~Add"), push_add_button
, 0 },
597 { N_("Add se~parator"), push_add_separator_button
, 0 },
598 { N_("Add ~folder"), push_add_folder_button
, 0 },
599 { N_("~Move"), push_move_button
, 0 },
600 { N_("~Search"), push_search_button
, 1 },
602 /* This one is too dangerous, so just let user delete
603 * the bookmarks file if needed. --Zas */
604 { N_("Clear"), push_hierbox_clear_button
, 0 },
606 /* TODO: Would this be useful? --jonas */
607 { N_("Save"), push_save_button
, 0 },
611 struct_hierbox_browser(
613 N_("Bookmark manager"),
615 &bookmarks_listbox_ops
618 /* Builds the "Bookmark manager" dialog */
620 bookmark_manager(struct session
*ses
)
622 free_last_searched_bookmark();
623 bookmark_browser
.expansion_callback
= bookmarks_set_dirty
;
624 hierbox_browser(&bookmark_browser
, ses
);
628 /****************************************************************************\
629 Bookmark search dialog.
630 \****************************************************************************/
633 /* Searchs a substring either in title or url fields (ignoring
634 * case). If search_title and search_url are not empty, it selects bookmarks
635 * matching the first OR the second.
637 * Perhaps another behavior could be to search bookmarks matching both
638 * (replacing OR by AND), but it would break a cool feature: when on a page,
639 * opening search dialog will have fields corresponding to that page, so
640 * pressing ok will find any bookmark with that title or url, permitting a
641 * rapid search of an already existing bookmark. --Zas */
643 struct bookmark_search_ctx
{
644 unsigned char *url
; /* UTF-8 */
645 unsigned char *title
; /* system charset */
652 #define NULL_BOOKMARK_SEARCH_CTX {NULL, NULL, 0, 0, -1, -1}
655 test_search(struct listbox_item
*item
, void *data_
, int *offset
)
657 struct bookmark_search_ctx
*ctx
= data_
;
660 ctx
->found
= 0; /* ignore possible match on first item */
662 struct bookmark
*bm
= item
->udata
;
664 assert(ctx
->title
&& ctx
->url
);
666 ctx
->found
= (*ctx
->url
&& c_strcasestr(bm
->url
, ctx
->url
));
667 if (!ctx
->found
&& *ctx
->title
) {
668 /* The comparison of bookmark titles should
669 * be case-insensitive and locale-sensitive
670 * (Turkish dotless i). ELinks doesn't have
671 * such a function for UTF-8. The best we
672 * have is strcasestr, which uses the system
673 * charset. So convert bm->title to that.
674 * (ctx->title has already been converted.) */
675 struct conv_table
*convert_table
;
676 unsigned char *title
= NULL
;
678 convert_table
= get_translation_table(ctx
->utf8_cp
,
681 title
= convert_string(convert_table
,
690 ctx
->found
= (strcasestr(title
, ctx
->title
)
694 /** @todo Tell the user that the string could
695 * not be converted. */
698 if (ctx
->found
) *offset
= 0;
705 /* Last searched values. Both are in UTF-8. (The title could be kept
706 * in the system charset, but that would be a bit risky, because
707 * setlocale calls from Lua scripts can change the system charset.) */
708 static unsigned char *bm_last_searched_title
= NULL
;
709 static unsigned char *bm_last_searched_url
= NULL
;
712 free_last_searched_bookmark(void)
714 mem_free_set(&bm_last_searched_title
, NULL
);
715 mem_free_set(&bm_last_searched_url
, NULL
);
719 memorize_last_searched_bookmark(const unsigned char *title
,
720 const unsigned char *url
)
722 /* Memorize last searched title */
723 mem_free_set(&bm_last_searched_title
, stracpy(title
));
724 if (!bm_last_searched_title
) return 0;
726 /* Memorize last searched url */
727 mem_free_set(&bm_last_searched_url
, stracpy(url
));
728 if (!bm_last_searched_url
) {
729 mem_free_set(&bm_last_searched_title
, NULL
);
736 /* Search bookmarks */
738 bookmark_search_do(void *data
)
740 struct dialog
*dlg
= data
;
741 struct bookmark_search_ctx ctx
= NULL_BOOKMARK_SEARCH_CTX
;
742 struct listbox_data
*box
;
743 struct dialog_data
*dlg_data
;
744 struct conv_table
*convert_table
;
746 unsigned char *url_term
;
747 unsigned char *title_term
;
748 unsigned char *title_utf8
= NULL
;
750 assertm(dlg
->udata
!= NULL
, "Bookmark search with NULL udata in dialog");
751 if_assert_failed
return;
753 dlg_data
= (struct dialog_data
*) dlg
->udata
;
754 term_cp
= get_terminal_codepage(dlg_data
->win
->term
);
755 ctx
.system_cp
= get_cp_index("System");
756 ctx
.utf8_cp
= get_cp_index("UTF-8");
758 title_term
= dlg
->widgets
[0].data
; /* need not be freed */
759 url_term
= dlg
->widgets
[1].data
; /* likewise */
761 convert_table
= get_translation_table(term_cp
, ctx
.system_cp
);
762 if (!convert_table
) goto free_all
;
763 ctx
.title
= convert_string(convert_table
,
764 title_term
, strlen(title_term
),
765 ctx
.system_cp
, CSM_NONE
, NULL
, NULL
, NULL
);
766 if (!ctx
.title
) goto free_all
;
768 convert_table
= get_translation_table(term_cp
, ctx
.utf8_cp
);
769 if (!convert_table
) goto free_all
;
770 ctx
.url
= convert_string(convert_table
,
771 url_term
, strlen(url_term
),
772 ctx
.utf8_cp
, CSM_NONE
, NULL
, NULL
, NULL
);
773 if (!ctx
.url
) goto free_all
;
774 title_utf8
= convert_string(convert_table
,
775 title_term
, strlen(title_term
),
776 ctx
.utf8_cp
, CSM_NONE
, NULL
, NULL
, NULL
);
777 if (!title_utf8
) goto free_all
;
779 if (!memorize_last_searched_bookmark(title_utf8
, ctx
.url
))
782 box
= get_dlg_listbox_data(dlg_data
);
784 traverse_listbox_items_list(box
->sel
, box
, 0, 0, test_search
, &ctx
);
785 if (!ctx
.found
) goto free_all
;
787 listbox_sel_move(dlg_data
->widgets_data
, ctx
.offset
- 1);
790 mem_free_if(ctx
.title
);
791 mem_free_if(ctx
.url
);
792 mem_free_if(title_utf8
);
796 launch_bm_search_doc_dialog(struct terminal
*term
,
797 struct dialog_data
*parent
,
800 unsigned char *title
= NULL
;
801 unsigned char *url
= NULL
;
803 if (bm_last_searched_title
&& bm_last_searched_url
) {
804 int utf8_cp
, term_cp
;
805 struct conv_table
*convert_table
;
807 utf8_cp
= get_cp_index("UTF-8");
808 term_cp
= get_terminal_codepage(term
);
810 convert_table
= get_translation_table(utf8_cp
, term_cp
);
812 title
= convert_string(convert_table
, bm_last_searched_title
,
813 strlen(bm_last_searched_title
), term_cp
,
814 CSM_NONE
, NULL
, NULL
, NULL
);
815 url
= convert_string(convert_table
, bm_last_searched_url
,
816 strlen(bm_last_searched_url
), term_cp
,
817 CSM_NONE
, NULL
, NULL
, NULL
);
819 if (!title
|| !url
) {
820 mem_free_set(&title
, NULL
);
821 mem_free_set(&url
, NULL
);
825 do_edit_dialog(term
, 1, N_("Search bookmarks"),
827 ses
, parent
, bookmark_search_do
, NULL
, NULL
,
836 /****************************************************************************\
838 \****************************************************************************/
840 /* Adds the bookmark */
842 bookmark_add_add(void *data
)
844 struct dialog
*dlg
= data
;
845 struct dialog_data
*dlg_data
= (struct dialog_data
*) dlg
->udata
;
846 struct terminal
*term
= dlg
->udata2
;
848 do_add_bookmark(term
, dlg_data
, dlg
->widgets
[0].data
, dlg
->widgets
[1].data
);
851 /** Open a dialog box for adding a bookmark.
854 * The terminal in which the dialog box should appear.
857 * The bookmark manager, or NULL if the user requested this action
858 * from somewhere else.
861 * If @a title or @a url is NULL, get defaults from the current
862 * document of @a ses.
865 * The initial title of the new bookmark, in the encoding of @a term.
866 * NULL means use @a ses.
869 * The initial URL of the new bookmark, in the encoding of @a term.
870 * NULL means use @a ses. */
872 launch_bm_add_dialog(struct terminal
*term
,
873 struct dialog_data
*parent
,
875 unsigned char *title
,
878 /* When the user eventually pushes the OK button, BFU calls
879 * bookmark_add_add() and gives it the struct dialog * as the
880 * void * parameter. However, bookmark_add_add() also needs
881 * to know the struct terminal *, and there is no way to get
882 * that from struct dialog. The other bookmark dialogs work
883 * around that by making dialog.udata point to the struct
884 * dialog_data of the bookmark manager, but the "Add bookmark"
885 * dialog can be triggered with ACT_MAIN_ADD_BOOKMARK, which
886 * does not involve the bookmark manager at all.
888 * The solution here is to save the struct terminal * in
889 * dialog.udata2, which the "Edit bookmark" dialog uses for
890 * struct bookmark *. When adding a new bookmark, we don't
891 * need a pointer to an existing one, of course. */
892 do_edit_dialog(term
, 1, N_("Add bookmark"), title
, url
, ses
,
893 parent
, bookmark_add_add
, NULL
, term
, EDIT_DLG_ADD
);
897 launch_bm_add_doc_dialog(struct terminal
*term
,
898 struct dialog_data
*parent
,
901 launch_bm_add_dialog(term
, parent
, ses
, NULL
, NULL
);
905 launch_bm_add_link_dialog(struct terminal
*term
,
906 struct dialog_data
*parent
,
909 unsigned char title
[MAX_STR_LEN
], url
[MAX_STR_LEN
];
911 launch_bm_add_dialog(term
, parent
, ses
,
912 get_current_link_name(ses
, title
, MAX_STR_LEN
),
913 get_current_link_url(ses
, url
, MAX_STR_LEN
));
917 /****************************************************************************\
918 Bookmark tabs dialog.
919 \****************************************************************************/
922 bookmark_terminal_tabs_ok(void *term_void
, unsigned char *foldername
)
924 struct terminal
*const term
= term_void
;
925 int from_cp
= get_terminal_codepage(term
);
926 int to_cp
= get_cp_index("UTF-8");
927 struct conv_table
*convert_table
;
928 unsigned char *converted
;
930 convert_table
= get_translation_table(from_cp
, to_cp
);
931 if (convert_table
== NULL
) return; /** @todo Report the error */
933 converted
= convert_string(convert_table
,
934 foldername
, strlen(foldername
),
937 if (converted
== NULL
) return; /** @todo Report the error */
939 bookmark_terminal_tabs(term_void
, converted
);
944 bookmark_terminal_tabs_dialog(struct terminal
*term
)
946 struct string string
;
948 if (!init_string(&string
)) return;
950 add_to_string(&string
, _("Saved session", term
));
953 add_to_string(&string
, " - ");
954 add_date_to_string(&string
, get_opt_str("ui.date_format", NULL
), NULL
);
957 input_dialog(term
, NULL
,
958 N_("Bookmark tabs"), N_("Enter folder name"),
960 MAX_STR_LEN
, string
.source
, 0, 0, NULL
,
961 bookmark_terminal_tabs_ok
, NULL
);
963 done_string(&string
);