1 #include "links.h"
2
3 /* The location of the box in the bookmark manager */
4 #define BM_BOX_IND 5
5
6
7 /* The list of bookmarks */
8 struct list_head bookmarks = {&bookmarks, &bookmarks};
9
10 /* The last used id of a bookmark */
11 bookmark_id next_bookmark_id = 0;
12
13 /* Clears the bookmark list */
free_bookmarks()14 void free_bookmarks() {
15 struct bookmark *bm;
16
17 foreach(bm, bookmarks) {
18 mem_free(bm->title);
19 mem_free(bm->url);
20 }
21
22 free_list(bookmarks);
23 }
24
25 /* Does final cleanup and saving of bookmarks */
finalize_bookmarks()26 void finalize_bookmarks() {
27 write_bookmarks();
28 free_bookmarks();
29 }
30
31
32 /* Loads the bookmarks from file */
read_bookmarks()33 void read_bookmarks() {
34 unsigned char *file_name;
35 unsigned char *url; /* Pointer to the start of url field */
36 unsigned char *str, *ptr, *nl;
37
38 if (!links_home) return;
39 file_name = stracpy(links_home);
40 add_to_strn(&file_name, "bookmarks");
41
42 str = read_config_file(file_name);
43 mem_free(file_name);
44 if (!str) return;
45
46 for (ptr = str; *ptr; ptr = nl) {
47 nl = strchr(ptr, '\n');
48 if (nl) *nl++ = 0;
49 else nl = strchr(ptr, 0);
50
51 url = strchr(ptr, '|');
52 if (!url) continue;
53 *url++ = 0;
54 add_bookmark(ptr, url);
55 }
56
57 mem_free(str);
58 }
59
60 /* Saves the bookmarks to file */
write_bookmarks()61 void write_bookmarks() {
62 struct bookmark *bm;
63 unsigned char *file_name;
64 unsigned char *s;
65 int l;
66
67 if (!links_home) return;
68 file_name = stracpy(links_home);
69 add_to_strn(&file_name, "bookmarks");
70
71 s = init_str();
72 l = 0;
73
74 foreachback(bm, bookmarks) {
75 int i;
76 unsigned char *p = stracpy(bm->title);
77 for (i = strlen(p) - 1; i >= 0; i--) if (p[i] < ' '|| p[i] == '|') p[i] = ' ';
78 add_to_str(&s, &l, p);
79 mem_free(p);
80 add_chr_to_str(&s, &l, '|');
81 p = stracpy(bm->url);
82 for (i = strlen(p) - 1; i >= 0; i--) if (p[i] < ' ') p[i] = ' ';
83 add_to_str(&s, &l, p);
84 mem_free(p);
85 add_chr_to_str(&s, &l, '\n');
86 }
87
88 write_to_config_file(file_name, s);
89
90 mem_free(s);
91 mem_free(file_name);
92
93 }
94
95 /* Gets a bookmark by id */
get_bookmark_by_id(bookmark_id id)96 struct bookmark *get_bookmark_by_id(bookmark_id id) {
97 struct bookmark *bm;
98
99 if (id == BAD_BOOKMARK_ID)
100 return NULL;
101
102 foreach(bm, bookmarks) {
103 if (id == bm->id)
104 return bm;
105 }
106
107 return NULL;
108 }
109
110
111 /* Adds a bookmark to the bookmark list. Don't play with new_bm after you're
112 done. It would be impolite. */
add_bookmark(const unsigned char * title,const unsigned char * url)113 void add_bookmark(const unsigned char *title, const unsigned char *url) {
114 struct bookmark *bm;
115 int title_size; /* How much mem to allocate for the strings */
116 int url_size;
117
118 title_size = strlen(title) + 1;
119 url_size = strlen(url) + 1;
120
121 bm = mem_alloc(sizeof(struct bookmark));
122
123 bm->title = mem_alloc(title_size);
124 bm->url = mem_alloc(url_size);
125
126 strcpy(bm->title, title);
127 strcpy(bm->url, url);
128
129 bm->id = next_bookmark_id++;
130
131 /* Actually add it */
132 add_to_list(bookmarks, bm);
133 }
134
135
136 /* Updates an existing bookmark.
137 *
138 * If the requested bookmark does not exist, return 0. Otherwise, return 1.
139 *
140 * If any of the fields are NULL, the value is left unchanged.
141 */
bookmark_update(bookmark_id id,unsigned char * title,unsigned char * url)142 int bookmark_update(bookmark_id id, unsigned char *title, unsigned char *url) {
143 struct bookmark *bm = get_bookmark_by_id(id);
144
145 if (bm == NULL) {
146 /* Does not exist. */
147 return 0;
148 }
149
150 if (title) {
151 mem_free(bm->title);
152 bm->title = stracpy((unsigned char *)title);
153 }
154
155 if (url) {
156 mem_free(bm->url);
157 bm->url = stracpy((unsigned char *)url);
158 }
159
160 return 1;
161 }
162
163 /* Allocates and returns a bookmark */
create_bookmark(const unsigned char * title,const unsigned char * url)164 struct bookmark *create_bookmark(const unsigned char *title, const unsigned char *url) {
165 struct bookmark *new_bm = NULL;
166 size_t title_size; /* How much mem to allocate for the strings */
167 size_t url_size;
168
169 title_size = strlen(title) + 1;
170 url_size = strlen(url) + 1;
171 if (title_size > MAXINT) overalloc();
172 if (url_size > MAXINT) overalloc();
173
174 new_bm = mem_alloc(sizeof(struct bookmark));
175
176 new_bm->title = mem_alloc(title_size);
177 new_bm->url = mem_alloc(url_size);
178
179 strcpy(new_bm->title, title);
180 strcpy(new_bm->url, url);
181
182 return new_bm;
183 }
184
185
186 /* Deletes a bookmark, given the id. Returns 0 on failure (no such bm), 1 on
187 success */
delete_bookmark_by_id(bookmark_id id)188 int delete_bookmark_by_id(bookmark_id id) {
189 struct bookmark *bm;
190
191 bm = get_bookmark_by_id(id);
192
193 if (bm == NULL)
194 return 0;
195
196 del_from_list(bm);
197
198 /* Now wipe the bookmark */
199 mem_free(bm->title);
200 mem_free(bm->url);
201
202 mem_free(bm);
203
204 return 1;
205 }
206
207 /****************************************************************************
208 *
209 * Bookmark manager stuff.
210 *
211 ****************************************************************************/
212
213 void bookmark_edit_dialog(
214 struct terminal *,
215 unsigned char *,
216 const unsigned char *,
217 const unsigned char *,
218 struct session *,
219 struct dialog_data *,
220 void when_done(struct dialog *),
221 void *
222 );
223
224 /* Gets the head of the bookmark list kept by the dialog (the one used for
225 display purposes */
226 /* I really should use this somewhere...
227 static inline *list_head bookmark_dlg_list_get(struct dialog) {
228 return dialog->items[BM_BOX_IND].data;
229 }
230 */
231
232 /* Clears the bookmark list from the bookmark_dialog */
bookmark_dlg_list_clear(struct list_head * bm_list)233 static inline void bookmark_dlg_list_clear(struct list_head *bm_list) {
234 free_list( *bm_list );
235 }
236
237 /* Updates the bookmark list for a dialog. Returns the number of bookmarks.
238 FIXME: Must be changed for hierarchical bookmarks.
239 */
bookmark_dlg_list_update(struct list_head * bm_list)240 int bookmark_dlg_list_update(struct list_head *bm_list) {
241 struct bookmark *bm; /* Iterator over bm list */
242 struct box_item *item; /* New box item (one per displayed bookmark) */
243 unsigned char *text;
244 int count = 0;
245 bookmark_id id;
246
247 /* Empty the list */
248 bookmark_dlg_list_clear(bm_list);
249
250 /* Copy each bookmark into the display list */
251 foreach(bm, bookmarks) {
252 /* Deleted in bookmark_dlg_clear_list() */
253 item = mem_alloc( sizeof(struct box_item) + strlen(bm->title) + 1);
254 item->text = text = ((unsigned char *)item + sizeof(struct box_item));
255 item->data = (void *)(my_uintptr_t)(id = bm->id);
256
257 /* Note that free_i is left at zero */
258
259 strcpy(text, bm->title);
260
261 add_to_list( *bm_list, item);
262 count++;
263 }
264 return count;
265 }
266
267
268 /* Creates the box display (holds everything EXCEPT the actual rendering data) */
bookmark_dlg_box_build(struct dlg_data_item_data_box ** box)269 struct dlg_data_item_data_box *bookmark_dlg_box_build(struct dlg_data_item_data_box **box) {
270 /* Deleted in abort */
271 *box = mem_alloc( sizeof(struct dlg_data_item_data_box) );
272 memset(*box, 0, sizeof(struct dlg_data_item_data_box));
273
274 init_list((*box)->items);
275
276 (*box)->list_len = bookmark_dlg_list_update(&((*box)->items));
277 return *box;
278 }
279
280 /* Get the id of the currently selected bookmark */
bookmark_dlg_box_id_get(struct dlg_data_item_data_box * box)281 bookmark_id bookmark_dlg_box_id_get(struct dlg_data_item_data_box *box) {
282 struct box_item *citem;
283 int sel;
284
285 sel = box->sel;
286
287 if (sel == -1)
288 return BAD_BOOKMARK_ID;
289
290 /* Sel is an index into the list of bookmarks. Therefore, we spin thru
291 until sel equals zero, and return the id at that point */
292 foreach(citem, box->items) {
293 if (sel == 0)
294 return (bookmark_id)(my_uintptr_t)(citem->data);
295 sel--;
296 }
297
298 return BAD_BOOKMARK_ID;
299 }
300
301
302
303 /* Cleans up after the bookmark dialog */
bookmark_dialog_abort_handler(struct dialog_data * dlg)304 void bookmark_dialog_abort_handler(struct dialog_data *dlg) {
305 struct dlg_data_item_data_box *box;
306
307 box = (struct dlg_data_item_data_box *)(dlg->dlg->items[BM_BOX_IND].data);
308
309 /* Zap the display list */
310 bookmark_dlg_list_clear(&(box->items));
311
312 /* Delete the box structure */
313 mem_free(box);
314 }
315
316 /* Handles events for a bookmark dialog */
bookmark_dialog_event_handler(struct dialog_data * dlg,struct event * ev)317 int bookmark_dialog_event_handler(struct dialog_data *dlg, struct event *ev) {
318
319 switch ((int)ev->ev) {
320 case EV_KBD:
321 /* Catch change focus requests */
322 if (ev->x == KBD_RIGHT || (ev->x == KBD_TAB && !ev->y)) {
323 /* MP: dirty crap!!! this should be done in bfu.c */
324 /* Move right */
325 display_dlg_item(dlg, &dlg->items[dlg->selected], 0);
326 if (++dlg->selected >= BM_BOX_IND)
327 dlg->selected = 0;
328 display_dlg_item(dlg, &dlg->items[dlg->selected], 1);
329
330 return EVENT_PROCESSED;
331 }
332
333 if (ev->x == KBD_LEFT || (ev->x == KBD_TAB && ev->y)) {
334 /* Move left */
335 display_dlg_item(dlg, &dlg->items[dlg->selected], 0);
336 if (--dlg->selected < 0)
337 dlg->selected = BM_BOX_IND - 1;
338 display_dlg_item(dlg, &dlg->items[dlg->selected], 1);
339
340 return EVENT_PROCESSED;
341 }
342
343 /* Moving the box */
344 if (ev->x == KBD_DOWN) {
345 box_sel_move(&dlg->items[BM_BOX_IND], 1);
346 show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);
347
348 return EVENT_PROCESSED;
349 }
350
351 if (ev->x == KBD_UP) {
352 box_sel_move(&dlg->items[BM_BOX_IND], -1);
353 show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);
354
355 return EVENT_PROCESSED;
356 }
357
358 if (ev->x == KBD_PAGE_DOWN) {
359 box_sel_move(&dlg->items[BM_BOX_IND], dlg->items[BM_BOX_IND].item->gid / 2);
360 show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);
361
362 return EVENT_PROCESSED;
363 }
364
365 if (ev->x == KBD_PAGE_UP) {
366 box_sel_move(&dlg->items[BM_BOX_IND], (-1) * dlg->items[BM_BOX_IND].item->gid / 2);
367 show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);
368
369 return EVENT_PROCESSED;
370 }
371
372 /* Selecting a button */
373 break;
374 case EV_INIT:
375 case EV_RESIZE:
376 case EV_REDRAW:
377 case EV_MOUSE:
378 case EV_ABORT:
379 break;
380 default:
381 internal("Unknown event received: %d", (int)ev->ev);
382 }
383
384 return EVENT_NOT_PROCESSED;
385 }
386
387
388 /* The titles to appear in the bookmark add dialog */
389 unsigned char *bookmark_add_msg[] = {
390 TEXT_(T_BOOKMARK_TITLE),
391 TEXT_(T_URL),
392 };
393
394
395 /* The titles to appear in the bookmark manager */
396 unsigned char *bookmark_dialog_msg[] = {
397 TEXT_(T_BOOKMARKS),
398 };
399
400
401 /* Loads the selected bookmark */
menu_goto_bookmark(struct terminal * term,void * url,struct session * ses)402 void menu_goto_bookmark(struct terminal *term, void *url, struct session *ses) {
403 goto_url(ses, (unsigned char*)url);
404 }
405
406
407 /* Gets the url of the requested bookmark.
408 *
409 * This returns a pointer to the url's data. Be gentle with it.
410 *
411 * Returns a NULL if the bookmark has no url, AND if the passed bookmark id is
412 * invalid.
413 */
bookmark_get_url(bookmark_id id)414 const unsigned char *bookmark_get_url(bookmark_id id) {
415 struct bookmark *bm = get_bookmark_by_id(id);
416
417 if (bm == NULL) {
418 return NULL;
419 }
420
421 return bm->url;
422 }
423
424 /* Gets the name of the requested bookmark.
425 *
426 * See bookmark_get_url() for further comments.
427 */
bookmark_get_name(bookmark_id id)428 const unsigned char *bookmark_get_name(bookmark_id id) {
429 struct bookmark *bm = get_bookmark_by_id(id);
430
431 if (bm == NULL) {
432 return NULL;
433 }
434
435 return bm->title;
436 }
437
438
439
440 /* Goes to the called bookmark */
bookmark_goto(bookmark_id id,struct session * ses)441 void bookmark_goto(bookmark_id id, struct session *ses) {
442 struct bookmark *bm;
443 bm = get_bookmark_by_id(id);
444
445 if (bm)
446 goto_url(ses, bm->url);
447
448 }
449
450 /* Shows the bookmark list */
bookmark_menu(struct terminal * term,void * ddd,struct session * ses)451 void bookmark_menu(struct terminal *term, void *ddd, struct session *ses)
452 {
453 struct bookmark *bm;
454 struct menu_item *mi;
455
456 if (!(mi = new_menu(3)))
457 return;
458
459 foreach(bm, bookmarks) {
460 add_to_menu(&mi, stracpy(bm->title), "", 0, MENU_FUNC menu_goto_bookmark, (void *)bm->url, 0);
461 }
462
463 do_menu(term, mi, ses);
464 }
465
466
467 /* Called to setup the bookmark dialog */
layout_bookmark_manager(struct dialog_data * dlg)468 void layout_bookmark_manager(struct dialog_data *dlg)
469 {
470 int max = 0, min = 0;
471 int w, rw;
472 int y = -1;
473 struct terminal *term;
474
475 term = dlg->win->term;
476
477 /* Find dimensions of dialog */
478 max_text_width(term, bookmark_dialog_msg[0], &max);
479 min_text_width(term, bookmark_dialog_msg[0], &min);
480 max_buttons_width(term, dlg->items + 2, 2, &max);
481 min_buttons_width(term, dlg->items + 2, 2, &min);
482
483 w = term->x * 9 / 10 - 2 * DIALOG_LB;
484 if (w > max) w = max;
485 if (w < min) w = min;
486
487 if (w > term->x - 2 * DIALOG_LB)
488 w = term->x - 2 * DIALOG_LB;
489
490 if (w < 1)
491 w = 1;
492
493 w = rw = 50 ;
494
495 y += 1; /* Blankline between top and top of box */
496 dlg_format_box(NULL, term, &dlg->items[BM_BOX_IND], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
497 y += 1; /* Blankline between box and menu */
498 dlg_format_buttons(NULL, term, dlg->items, 5, 0, &y, w, &rw, AL_CENTER);
499 w = rw;
500 dlg->xw = w + 2 * DIALOG_LB;
501 dlg->yw = y + 2 * DIALOG_TB;
502 center_dlg(dlg);
503 draw_dlg(dlg);
504 y = dlg->y + DIALOG_TB;
505
506 y++;
507 dlg_format_box(term, term, &dlg->items[BM_BOX_IND], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
508 y++;
509 dlg_format_buttons(term, term, &dlg->items[0], 5, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);
510 }
511
512
513 void launch_bm_add_doc_dialog(struct terminal *,struct dialog_data *, struct session *);
514 /* Callback for the "add" button in the bookmark manager */
push_add_button(struct dialog_data * dlg,struct dialog_item_data * di)515 int push_add_button(struct dialog_data *dlg, struct dialog_item_data *di) {
516 launch_bm_add_doc_dialog(dlg->win->term, dlg, (struct session *)dlg->dlg->udata);
517 return 0;
518 }
519
520
521 /* Called when the goto button is pushed */
push_goto_button(struct dialog_data * dlg,struct dialog_item_data * goto_btn)522 int push_goto_button(struct dialog_data *dlg, struct dialog_item_data *goto_btn) {
523 bookmark_id id;
524 struct dlg_data_item_data_box *box;
525
526 box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);
527
528 /* Follow the bookmark */
529 id = bookmark_dlg_box_id_get(box);
530 if (id != BAD_BOOKMARK_ID)
531 bookmark_goto(id, (struct session*)goto_btn->item->udata);
532 /* FIXME There really should be some feedback to the user here */
533
534 /* Close the bookmark dialog */
535 delete_window(dlg->win);
536 return 0;
537 }
538
539 /* Called when an edit is complete. */
bookmark_edit_done(struct dialog * d)540 void bookmark_edit_done(struct dialog *d) {
541 bookmark_id id = (bookmark_id)(my_uintptr_t)d->udata2;
542 struct dialog_data *parent;
543
544 bookmark_update(id, d->items[0].data, d->items[1].data);
545
546 parent = d->udata;
547
548 /* Tell the bookmark dialog to redraw */
549 if (parent)
550 bookmark_dlg_list_update(&(((struct dlg_data_item_data_box*)parent->dlg->items[BM_BOX_IND].data)->items));
551 }
552
553 /* Called when the edit button is pushed */
push_edit_button(struct dialog_data * dlg,struct dialog_item_data * edit_btn)554 int push_edit_button(struct dialog_data *dlg, struct dialog_item_data *edit_btn) {
555 bookmark_id id;
556 struct dlg_data_item_data_box *box;
557
558 box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);
559
560 /* Follow the bookmark */
561 id = bookmark_dlg_box_id_get(box);
562 if (id != BAD_BOOKMARK_ID) {
563 const unsigned char *name = bookmark_get_name(id);
564 const unsigned char *url = bookmark_get_url(id);
565
566 bookmark_edit_dialog(dlg->win->term, TEXT_(T_EDIT_BOOKMARK), name, url, (struct session*)edit_btn->item->udata, dlg, bookmark_edit_done, (void *)(my_uintptr_t)id);
567 }
568 /* FIXME There really should be some feedback to the user here */
569 return 0;
570 }
571
572
573 /* Used to carry extra info between the push_delete_button() and the really_del_bookmark_ */
574 struct push_del_button_hop_struct {
575 struct dialog *dlg;
576 struct dlg_data_item_data_box *box;
577 bookmark_id id;
578 };
579
580
581 /* Called to _really_ delete a bookmark (a confirm in the delete dialog) */
really_del_bookmark(void * vhop)582 void really_del_bookmark(void *vhop) {
583 struct push_del_button_hop_struct *hop;
584 int last;
585
586 hop = (struct push_del_button_hop_struct *)vhop;
587
588 if (!delete_bookmark_by_id(hop->id))
589 return;
590
591 last = bookmark_dlg_list_update(&(hop->box->items));
592 /* In case we deleted the last bookmark */
593 if (hop->box->sel >= (last - 1))
594 hop->box->sel = last - 1;
595
596 /* Made in push_delete_button() */
597 /*mem_free(vhop);*/
598 }
599
600
601 /* Callback for the "delete" button in the bookmark manager */
push_delete_button(struct dialog_data * dlg,struct dialog_item_data * some_useless_delete_button)602 int push_delete_button(struct dialog_data *dlg, struct dialog_item_data *some_useless_delete_button) {
603 struct bookmark *bm;
604 struct push_del_button_hop_struct *hop;
605 struct terminal *term;
606 struct dlg_data_item_data_box *box;
607
608 /* FIXME There's probably a nicer way to do this */
609 term = dlg->win->term;
610
611 box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);
612
613 bm = get_bookmark_by_id(bookmark_dlg_box_id_get(box));
614
615 if (bm == NULL)
616 return 0;
617
618
619 /* Deleted in really_del_bookmark() */
620 hop = mem_alloc(sizeof(struct push_del_button_hop_struct));
621
622 hop->id = bm->id;
623 hop->dlg = dlg->dlg;
624 hop->box = box;
625
626 msg_box(term, getml(hop, NULL), TEXT_(T_DELETE_BOOKMARK), AL_CENTER | AL_EXTD_TEXT, TEXT_(T_DELETE_BOOKMARK), " \"", bm->title, "\" (", TEXT_(T_url), ": \"", bm->url, "\")?", NULL, hop, 2, TEXT_(T_YES), really_del_bookmark, B_ENTER, TEXT_(T_NO), NULL, B_ESC);
627 return 0;
628 }
629
630 /* Builds the "Bookmark manager" dialog */
menu_bookmark_manager(struct terminal * term,void * fcp,struct session * ses)631 void menu_bookmark_manager(struct terminal *term, void *fcp, struct session *ses)
632 {
633 struct dialog *d;
634
635 /* Create the dialog */
636 d = mem_alloc(sizeof(struct dialog) + 7 * sizeof(struct dialog_item) + sizeof(struct bookmark) + 2 * MAX_STR_LEN);
637
638 memset(d, 0, sizeof(struct dialog) + 7 * sizeof(struct dialog_item) + sizeof(struct bookmark) + 2 * MAX_STR_LEN);
639
640 d->title = TEXT_(T_BOOKMARK_MANAGER);
641 d->fn = layout_bookmark_manager;
642 d->handle_event = bookmark_dialog_event_handler;
643 d->abort = bookmark_dialog_abort_handler;
644 /* bookmark_build_dlg_list(d);*/ /* Where the currently displayed list goes */
645 d->udata = ses;
646
647 d->items[0].type = D_BUTTON;
648 d->items[0].gid = B_ENTER;
649 d->items[0].fn = push_goto_button;
650 d->items[0].udata = ses;
651 d->items[0].text = TEXT_(T_GOTO);
652
653 d->items[1].type = D_BUTTON;
654 d->items[1].gid = B_ENTER;
655 d->items[1].fn = push_edit_button;
656 d->items[1].udata = ses;
657 d->items[1].text = TEXT_(T_EDIT);
658
659 d->items[2].type = D_BUTTON;
660 d->items[2].gid = B_ENTER;
661 d->items[2].fn = push_delete_button;
662 d->items[2].text = TEXT_(T_DELETE);
663
664 d->items[3].type = D_BUTTON;
665 d->items[3].gid = B_ENTER;
666 d->items[3].fn = push_add_button;
667 d->items[3].text = TEXT_(T_ADD);
668
669 d->items[4].type = D_BUTTON;
670 d->items[4].gid = B_ESC;
671 d->items[4].fn = cancel_dialog;
672 d->items[4].text = TEXT_(T_CLOSE);
673
674 d->items[5].type = D_BOX; /* MP: D_BOX is nonsence. I tried to remove it, but didn't succeed */
675 d->items[5].gid = 12;
676 /*d->items[5].data = (void *)bookmark_dlg_box_build();*/ /* Where the currently displayed list goes */
677 bookmark_dlg_box_build((struct dlg_data_item_data_box**)(void *)&(d->items[5].data)); /* Where the currently displayed list goes */
678
679 d->items[6].type = D_END;
680 do_dialog(term, d, getml(d, NULL));
681 }
682
683 /****************************************************************************
684 *
685 * Bookmark add dialog
686 *
687 ****************************************************************************/
688
689 /* Adds the bookmark */
bookmark_add_add(struct dialog * d)690 void bookmark_add_add(struct dialog *d)
691 {
692 struct dialog_data *parent;
693
694 add_bookmark(d->items[0].data, d->items[1].data);
695
696 parent = d->udata;
697
698 /* Tell the bookmark dialog to redraw */
699 if (parent)
700 bookmark_dlg_list_update(&(((struct dlg_data_item_data_box*)parent->dlg->items[BM_BOX_IND].data)->items));
701 }
702
703
launch_bm_add_doc_dialog(struct terminal * term,struct dialog_data * parent,struct session * ses)704 void launch_bm_add_doc_dialog(struct terminal *term,struct dialog_data *parent,struct session *ses) {
705
706 bookmark_edit_dialog(term, TEXT_(T_ADD_BOOKMARK), NULL, NULL, ses, parent, bookmark_add_add, NULL);
707 }
708
709 /* Called to launch an add dialog on the current link */
launch_bm_add_link_dialog(struct terminal * term,struct dialog_data * parent,struct session * ses)710 void launch_bm_add_link_dialog(struct terminal *term,struct dialog_data *parent,struct session *ses) {
711 unsigned char url[MAX_STR_LEN];
712
713 /* FIXME: Logic error -- if there is no current link,
714 * get_current_link_url() will return NULL, which will cause
715 * bookmark_add_dialog() to try and use the current document's url.
716 * Instead, it should use "".
717 */
718 bookmark_edit_dialog(term, TEXT_(T_ADD_BOOKMARK), NULL, get_current_link_url(ses, url, MAX_STR_LEN), ses, parent, bookmark_add_add, NULL);
719 }
720
721
722
723 unsigned char *bm_add_msg[] = {
724 TEXT_(T_NNAME),
725 TEXT_(T_URL),
726 };
727
728 /* Called to setup the add bookmark dialog */
layout_add_dialog(struct dialog_data * dlg)729 void layout_add_dialog(struct dialog_data *dlg)
730 {
731 int max = 0, min = 0;
732 int w, rw;
733 int y = -1;
734 struct terminal *term;
735
736 term = dlg->win->term;
737
738 max_text_width(term, bm_add_msg[0], &max);
739 min_text_width(term, bm_add_msg[0], &min);
740 max_text_width(term, bm_add_msg[1], &max);
741 min_text_width(term, bm_add_msg[1], &min);
742 max_buttons_width(term, dlg->items + 2, 2, &max);
743 min_buttons_width(term, dlg->items + 2, 2, &min);
744 w = term->x * 9 / 10 - 2 * DIALOG_LB;
745
746 if (w > max) w = max;
747 if (w < min) w = min;
748 if (w > term->x - 2 * DIALOG_LB) w = term->x - 2 * DIALOG_LB;
749 if (w < 1) w = 1;
750
751 w = rw = 50;
752
753 dlg_format_text(NULL, term, bm_add_msg[0], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);
754 y += 2;
755 dlg_format_text(NULL, term, bm_add_msg[1], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);
756 y += 2;
757 dlg_format_buttons(NULL, term, dlg->items + 2, 2, 0, &y, w, &rw, AL_CENTER);
758 w = rw;
759 dlg->xw = w + 2 * DIALOG_LB;
760 dlg->yw = y + 2 * DIALOG_TB;
761 center_dlg(dlg);
762 draw_dlg(dlg);
763 y = dlg->y + DIALOG_TB;
764 dlg_format_text(term, term, bm_add_msg[0], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);
765 dlg_format_field(NULL, term, &dlg->items[0], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
766 y++;
767 dlg_format_text(term, term, bm_add_msg[1], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);
768 dlg_format_field(term, term, &dlg->items[1], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
769 y++;
770 dlg_format_buttons(term, term, &dlg->items[2], 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);
771
772 }
773
774 /* Edits a bookmark's fields.
775 * If parent is defined, then that points to a dialog that should be sent
776 * an update when the add is done.
777 *
778 * If either of src_name or src_url are NULL, try to obtain the name and url
779 * of the current document. If you want to create two null fields, pass in a
780 * pointer to a zero length string ("").
781 */
bookmark_edit_dialog(struct terminal * term,unsigned char * title,const unsigned char * src_name,const unsigned char * src_url,struct session * ses,struct dialog_data * parent,void when_done (struct dialog *),void * done_data)782 void bookmark_edit_dialog(
783 struct terminal *term /* Terminal to write on. */,
784 unsigned char *title /* Title of the dialog. */,
785 const unsigned char *src_name /* Pointer to name to use. (can be null)*/,
786 const unsigned char *src_url /* Url to use. (can be null) */,
787 struct session *ses,
788 struct dialog_data *parent /* The parent window launching this one. */,
789 void when_done(struct dialog *) /* Function to execute on 'ok'. */,
790 void *done_data /* Spare data to pass to when_done. Stored in udata2 */
791 ) {
792 unsigned char *name, *url;
793
794 struct dialog *d;
795
796 /* Create the dialog */
797 d = mem_alloc(sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN);
798 memset(d, 0, sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN);
799
800 name = (unsigned char *)&d->items[5];
801 url = name + MAX_STR_LEN;
802
803 /* Get the name */
804 if (src_name == NULL) {
805 /* Unknown name. */
806 get_current_title(ses, name, MAX_STR_LEN);
807 } else {
808 /* Known name. */
809 safe_strncpy(name, src_name, MAX_STR_LEN);
810 }
811
812 /* Get the url */
813 if (src_url == NULL) {
814 /* Unknown . */
815 get_current_url(ses, url, MAX_STR_LEN);
816 } else {
817 /* Known url. */
818 safe_strncpy(url, src_url, MAX_STR_LEN);
819 }
820
821 d->title = title;
822 d->fn = layout_add_dialog;
823 d->refresh = (void (*)(void *))when_done;
824 d->refresh_data = d;
825 d->udata = parent;
826 d->udata2 = done_data;
827
828 d->items[0].type = D_FIELD;
829 d->items[0].dlen = MAX_STR_LEN;
830 d->items[0].data = name;
831 d->items[0].fn = check_nonempty;
832
833 d->items[1].type = D_FIELD;
834 d->items[1].dlen = MAX_STR_LEN;
835 d->items[1].data = url;
836 d->items[1].fn = check_nonempty;
837
838 d->items[2].type = D_BUTTON;
839 d->items[2].gid = B_ENTER;
840 d->items[2].fn = ok_dialog;
841 d->items[2].text = TEXT_(T_OK);
842
843 d->items[3].type = D_BUTTON;
844 d->items[3].gid = B_ESC;
845 d->items[3].text = TEXT_(T_CANCEL);
846 d->items[3].fn = cancel_dialog;
847
848 d->items[4].type = D_END;
849
850 do_dialog(term, d, getml(d, NULL));
851 }
852