"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/bookmark.c" (16 Nov 2011, 22981 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format (assuming markdown format). Alternatively you can here view or download the uninterpreted source code file. A member file download can also be achieved by clicking within a package contents listing on the according byte size field.

include “links.h”

/ The location of the box in the bookmark manager /

define BM_BOX_IND 5

/ The list of bookmarks / struct list_head bookmarks = {&bookmarks, &bookmarks};

/ The last used id of a bookmark / bookmark_id next_bookmark_id = 0;

/ Clears the bookmark list / void free_bookmarks() { struct bookmark *bm;

foreach(bm, bookmarks) {
    mem_free(bm->title);
    mem_free(bm->url);
}

free_list(bookmarks);

}

/ Does final cleanup and saving of bookmarks / void finalize_bookmarks() { write_bookmarks(); free_bookmarks(); }

/ Loads the bookmarks from file / void read_bookmarks() { unsigned char in_buffer[MAX_STR_LEN];
unsigned char file_name; unsigned char title, url; / Pointers to the start of each field (in buffer)/ FILE f;

file_name = stracpy(links_home);
if (!file_name) return;
add_to_strn(&file_name, "bookmarks");

f = fopen(file_name, "r");
mem_free(file_name);
if (f == NULL)
    return;

title = in_buffer;

while (fgets(in_buffer, MAX_STR_LEN, f)) {
    url = strchr(in_buffer, '|');
    if (url == NULL) 
        continue;
    *url = '\0';
    url++;
    if (strchr(url, '\n')) *( strchr(url, '\n') ) = '\0';
    add_bookmark(title, url);
}

fclose(f);

}

/ Saves the bookmarks to file / void write_bookmarks() { struct bookmark bm; FILE out; unsigned char tmp_file_name, file_name;

tmp_file_name = stracpy(links_home);
if (!tmp_file_name) return;
add_to_strn(&tmp_file_name, "bookmarks.tmp");

out = fopen(tmp_file_name, "w");
if (!out) {
    mem_free(tmp_file_name);
    return;
}

foreachback(bm, bookmarks) {
    unsigned char *p = stracpy(bm->title);
    int i;
    for (i = strlen(p) - 1; i >= 0; i--) if (p[i] < ' '|| p[i] == '|') p[i] = ' ';
    fputs(p,out);
    fputc('|', out);
    fputs(bm->url,out);
    fputc('\n',out);
    mem_free(p);
}

if (ferror(out)) {
    fclose(out);
    goto err;
}
if (fclose(out) == EOF) {
    err:
    remove(tmp_file_name);
    mem_free(tmp_file_name);
    return;
}

file_name = stracpy(links_home);
if (!file_name) {
    mem_free(tmp_file_name);
    return;
}
add_to_strn(&file_name, "bookmarks");

ifndef RENAME_OVER_EXISTING_FILES

unlink(file_name);      /* OS/2 needs this */

endif

rename(tmp_file_name, file_name);
mem_free(tmp_file_name);
mem_free(file_name);

}

/ Gets a bookmark by id / struct bookmark get_bookmark_by_id(bookmark_id id) { struct bookmark bm;

if (id == BAD_BOOKMARK_ID) 
    return NULL;

foreach(bm, bookmarks) {
    if (id == bm->id)
        return bm;
}

return NULL;

}

/ Adds a bookmark to the bookmark list. Don’t play with new_bm after you’re done. It would be impolite. / void add_bookmark(const unsigned char title, const unsigned char url) { struct bookmark bm; int title_size; / How much mem to allocate for the strings */ int url_size;

title_size = strlen(title) + 1;
url_size = strlen(url) + 1;

bm = mem_alloc(sizeof(struct bookmark));

bm->title = mem_alloc(title_size);
bm->url = mem_alloc(url_size);

strcpy(bm->title, title);
strcpy(bm->url, url);

bm->id = next_bookmark_id++;

/* Actually add it */
add_to_list(bookmarks, bm);

}

/ Updates an existing bookmark. * * If the requested bookmark does not exist, return 0. Otherwise, return 1. * * If any of the fields are NULL, the value is left unchanged. / int bookmark_update(bookmark_id id, unsigned char title, unsigned char url) { struct bookmark *bm = get_bookmark_by_id(id);

if (bm == NULL) {
    /* Does not exist. */
    return 0;
}

if (title) {
    mem_free(bm->title);
    bm->title = stracpy((unsigned char *)title);
}

if (url) {
    mem_free(bm->url);
    bm->url = stracpy((unsigned char *)url);
}

return 1;

}

/ Allocates and returns a bookmark / struct bookmark create_bookmark(const unsigned char title, const unsigned char url) { struct bookmark new_bm = NULL; size_t title_size; / How much mem to allocate for the strings / size_t url_size;

title_size = strlen(title) + 1;
url_size = strlen(url) + 1;
if (title_size > MAXINT) overalloc();
if (url_size > MAXINT) overalloc();

new_bm = mem_alloc(sizeof(struct bookmark));

new_bm->title = mem_alloc(title_size);
new_bm->url = mem_alloc(url_size);

strcpy(new_bm->title, title);
strcpy(new_bm->url, url);

return new_bm;

}

/ Deletes a bookmark, given the id. Returns 0 on failure (no such bm), 1 on success / int delete_bookmark_by_id(bookmark_id id) { struct bookmark *bm;

bm = get_bookmark_by_id(id);

if (bm == NULL)
    return 0;

del_from_list(bm);

/* Now wipe the bookmark */
mem_free(bm->title);
mem_free(bm->url);

mem_free(bm);

return 1;

}

/ * * Bookmark manager stuff. * /

void bookmark_edit_dialog( struct terminal , unsigned char , const unsigned char , const unsigned char , struct session , struct dialog_data , void when_done(struct dialog *), void * );

/ Gets the head of the bookmark list kept by the dialog (the one used for display purposes / / I really should use this somewhere… static inline list_head bookmark_dlg_list_get(struct dialog) { return dialog->items[BM_BOX_IND].data; } */

/ Clears the bookmark list from the bookmark_dialog / static inline void bookmark_dlg_list_clear(struct list_head bm_list) { free_list( bm_list ); }

/ Updates the bookmark list for a dialog. Returns the number of bookmarks. FIXME: Must be changed for hierarchical bookmarks. / int bookmark_dlg_list_update(struct list_head bm_list) { struct bookmark bm; / Iterator over bm list / struct box_item item; / New box item (one per displayed bookmark) / unsigned char text; int count = 0; bookmark_id id;

/* Empty the list */
bookmark_dlg_list_clear(bm_list);

/* Copy each bookmark into the display list */
foreach(bm, bookmarks) {
    /* Deleted in bookmark_dlg_clear_list() */
    item = mem_alloc( sizeof(struct box_item) + strlen(bm->title) + 1);
    item->text = text = ((unsigned char *)item + sizeof(struct box_item));
    item->data = (void *)(id = bm->id);

    /* Note that free_i is left at zero */

    strcpy(text, bm->title);

    add_to_list( *bm_list, item);
    count++;
}
return count;

}

/ Creates the box display (holds everything EXCEPT the actual rendering data) / struct dlg_data_item_data_box bookmark_dlg_box_build(struct dlg_data_item_data_box **box) { / Deleted in abort / box = mem_alloc( sizeof(struct dlg_data_item_data_box) ); memset(*box, 0, sizeof(struct dlg_data_item_data_box));

init_list((*box)->items);

(*box)->list_len = bookmark_dlg_list_update(&((*box)->items));
return *box;

}

/ Get the id of the currently selected bookmark / bookmark_id bookmark_dlg_box_id_get(struct dlg_data_item_data_box box) { struct box_item citem; int sel;

sel = box->sel;

if (sel == -1) 
    return BAD_BOOKMARK_ID;

/* Sel is an index into the list of bookmarks. Therefore, we spin thru
    until sel equals zero, and return the id at that point */
foreach(citem, box->items) {
    if (sel == 0) 
        return (bookmark_id)(citem->data);
    sel--;
}

return BAD_BOOKMARK_ID;

}

/ Cleans up after the bookmark dialog / void bookmark_dialog_abort_handler(struct dialog_data dlg) { struct dlg_data_item_data_box box;

box = (struct dlg_data_item_data_box *)(dlg->dlg->items[BM_BOX_IND].data);

/* Zap the display list */
bookmark_dlg_list_clear(&(box->items));

/* Delete the box structure */
mem_free(box);

}

/ Handles events for a bookmark dialog / int bookmark_dialog_event_handler(struct dialog_data dlg, struct event ev) {

switch ((int)ev->ev) {
    case EV_KBD:
        /* Catch change focus requests */
        if (ev->x == KBD_RIGHT || (ev->x == KBD_TAB && !ev->y)) {
            /* MP: dirty crap!!! this should be done in bfu.c */
            /* Move right */
            display_dlg_item(dlg, &dlg->items[dlg->selected], 0);
            if (++dlg->selected >= BM_BOX_IND) 
                dlg->selected = 0; 
            display_dlg_item(dlg, &dlg->items[dlg->selected], 1);

            return EVENT_PROCESSED;
        }

        if (ev->x == KBD_LEFT || (ev->x == KBD_TAB && ev->y)) {
            /* Move left */
            display_dlg_item(dlg, &dlg->items[dlg->selected], 0);
            if (--dlg->selected < 0) 
                dlg->selected = BM_BOX_IND - 1; 
            display_dlg_item(dlg, &dlg->items[dlg->selected], 1);

            return EVENT_PROCESSED;
        }

        /* Moving the box */
        if (ev->x == KBD_DOWN) {
            box_sel_move(&dlg->items[BM_BOX_IND], 1);
            show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);

            return EVENT_PROCESSED;
        }

        if (ev->x == KBD_UP) {
            box_sel_move(&dlg->items[BM_BOX_IND], -1);
            show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);

            return EVENT_PROCESSED;
        }

        if (ev->x == KBD_PAGE_DOWN) {
            box_sel_move(&dlg->items[BM_BOX_IND], dlg->items[BM_BOX_IND].item->gid / 2);
            show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);

            return EVENT_PROCESSED;
        }

        if (ev->x == KBD_PAGE_UP) {
            box_sel_move(&dlg->items[BM_BOX_IND], (-1) * dlg->items[BM_BOX_IND].item->gid / 2);
            show_dlg_item_box(dlg, &dlg->items[BM_BOX_IND]);

            return EVENT_PROCESSED;
        }

        /* Selecting a button */
    break;
    case EV_INIT:
    case EV_RESIZE:
    case EV_REDRAW:
    case EV_MOUSE:
    case EV_ABORT:
    break;
    default:
        internal("Unknown event received: %d", ev->ev);
}

return EVENT_NOT_PROCESSED;

}

/ The titles to appear in the bookmark add dialog / unsigned char *bookmark_add_msg[] = { TEXT(T_BOOKMARK_TITLE), TEXT(T_URL), };

/ The titles to appear in the bookmark manager / unsigned char *bookmark_dialog_msg[] = { TEXT_(T_BOOKMARKS), };

/ Loads the selected bookmark / void menu_goto_bookmark(struct terminal term, void url, struct session ses) { goto_url(ses, (unsigned char)url); }

/ Gets the url of the requested bookmark. * * This returns a pointer to the url’s data. Be gentle with it. * * Returns a NULL if the bookmark has no url, AND if the passed bookmark id is * invalid. / const unsigned char bookmark_get_url(bookmark_id id) { struct bookmark bm = get_bookmark_by_id(id);

if (bm == NULL) {
    return NULL;
}

return bm->url;

}

/ Gets the name of the requested bookmark. * * See bookmark_get_url() for further comments. / const unsigned char bookmark_get_name(bookmark_id id) { struct bookmark bm = get_bookmark_by_id(id);

if (bm == NULL) {
    return NULL;
}

return bm->title;

}

/ Goes to the called bookmark / void bookmark_goto(bookmark_id id, struct session ses) { struct bookmark bm; bm = get_bookmark_by_id(id);

if (bm) 
    goto_url(ses, bm->url);

}

/ Shows the bookmark list / void bookmark_menu(struct terminal term, void ddd, struct session ses) { struct bookmark bm; struct menu_item *mi;

if (!(mi = new_menu(3)))
    return;

foreach(bm, bookmarks) {
    add_to_menu(&mi, stracpy(bm->title), "", 0, MENU_FUNC menu_goto_bookmark, (void *)bm->url, 0);
}

do_menu(term, mi, ses);

}

/ Called to setup the bookmark dialog / void layout_bookmark_manager(struct dialog_data dlg) { int max = 0, min = 0; int w, rw; int y = -1; struct terminal term;

term = dlg->win->term;

/* Find dimensions of dialog */
max_text_width(term, bookmark_dialog_msg[0], &max);
min_text_width(term, bookmark_dialog_msg[0], &min);
max_buttons_width(term, dlg->items + 2, 2, &max);
min_buttons_width(term, dlg->items + 2, 2, &min);

w = term->x * 9 / 10 - 2 * DIALOG_LB;
if (w > max) w = max;
if (w < min) w = min;

if (w > term->x - 2 * DIALOG_LB) 
    w = term->x - 2 * DIALOG_LB;

if (w < 1) 
    w = 1;

w = rw = 50 ;

y += 1; /* Blankline between top and top of box */
dlg_format_box(NULL, term, &dlg->items[BM_BOX_IND], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
y += 1; /* Blankline between box and menu */
dlg_format_buttons(NULL, term, dlg->items, 5, 0, &y, w, &rw, AL_CENTER);
w = rw;
dlg->xw = w + 2 * DIALOG_LB;
dlg->yw = y + 2 * DIALOG_TB;
center_dlg(dlg);
draw_dlg(dlg);
y = dlg->y + DIALOG_TB;

y++;
dlg_format_box(term, term, &dlg->items[BM_BOX_IND], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
y++;
dlg_format_buttons(term, term, &dlg->items[0], 5, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);

}

void launch_bm_add_doc_dialog(struct terminal ,struct dialog_data , struct session ); / Callback for the “add” button in the bookmark manager / int push_add_button(struct dialog_data dlg, struct dialog_item_data di) { launch_bm_add_doc_dialog(dlg->win->term, dlg, (struct session )dlg->dlg->udata); return 0; }

/ Called when the goto button is pushed / int push_goto_button(struct dialog_data dlg, struct dialog_item_data goto_btn) { bookmark_id id; struct dlg_data_item_data_box *box;

box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);

/* Follow the bookmark */
id = bookmark_dlg_box_id_get(box);
if (id != BAD_BOOKMARK_ID) 
    bookmark_goto(id, (struct session*)goto_btn->item->udata);
/* FIXME There really should be some feedback to the user here */

/* Close the bookmark dialog */
delete_window(dlg->win);
return 0;

}

/ Called when an edit is complete. / void bookmark_edit_done(struct dialog d) { bookmark_id id = (bookmark_id)d->udata2; struct dialog_data parent;

bookmark_update(id, d->items[0].data, d->items[1].data);

parent = d->udata;

/* Tell the bookmark dialog to redraw */
if (parent) 
    bookmark_dlg_list_update(&(((struct dlg_data_item_data_box*)parent->dlg->items[BM_BOX_IND].data)->items));

}

/ Called when the edit button is pushed / int push_edit_button(struct dialog_data dlg, struct dialog_item_data edit_btn) { bookmark_id id; struct dlg_data_item_data_box *box;

box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);

/* Follow the bookmark */
id = bookmark_dlg_box_id_get(box);
if (id != BAD_BOOKMARK_ID) {
    const unsigned char *name = bookmark_get_name(id);
    const unsigned char *url = bookmark_get_url(id);

    bookmark_edit_dialog(dlg->win->term, TEXT_(T_EDIT_BOOKMARK), name, url, (struct session*)edit_btn->item->udata, dlg, bookmark_edit_done, (void *)id);
}
/* FIXME There really should be some feedback to the user here */
return 0;

}

/ Used to carry extra info between the push_delete_button() and the really_del_bookmark_ / struct push_del_button_hop_struct { struct dialog dlg; struct dlg_data_item_data_box box; bookmark_id id; };

/ Called to really delete a bookmark (a confirm in the delete dialog) / void really_del_bookmark(void vhop) { struct push_del_button_hop_struct hop; int last;

hop = (struct push_del_button_hop_struct *)vhop;

if (!delete_bookmark_by_id(hop->id)) 
    return;

last = bookmark_dlg_list_update(&(hop->box->items));
/* In case we deleted the last bookmark */
if (hop->box->sel >= (last - 1))
    hop->box->sel = last - 1;

/* Made in push_delete_button() */
/*mem_free(vhop);*/

}

/ Callback for the “delete” button in the bookmark manager / int push_delete_button(struct dialog_data dlg, struct dialog_item_data some_useless_delete_button) { struct bookmark bm; struct push_del_button_hop_struct hop; struct terminal term; struct dlg_data_item_data_box box;

/* FIXME There's probably a nicer way to do this */
term = dlg->win->term;

box = (struct dlg_data_item_data_box*)(dlg->dlg->items[BM_BOX_IND].data);

bm = get_bookmark_by_id(bookmark_dlg_box_id_get(box));

if (bm == NULL) 
    return 0;


/* Deleted in really_del_bookmark() */
hop = mem_alloc(sizeof(struct push_del_button_hop_struct));

hop->id = bm->id;
hop->dlg = dlg->dlg;
hop->box = box;

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);
return 0;

}

/ Builds the “Bookmark manager” dialog / void menu_bookmark_manager(struct terminal term, void fcp, struct session ses) { struct dialog d;

/* Create the dialog */
d = mem_alloc(sizeof(struct dialog) + 7 * sizeof(struct dialog_item) + sizeof(struct bookmark) + 2 * MAX_STR_LEN);

memset(d, 0, sizeof(struct dialog) + 7 * sizeof(struct dialog_item) + sizeof(struct bookmark) + 2 * MAX_STR_LEN);

d->title = TEXT_(T_BOOKMARK_MANAGER);
d->fn = layout_bookmark_manager;
d->handle_event = bookmark_dialog_event_handler;
d->abort = bookmark_dialog_abort_handler;

/ bookmark_build_dlg_list(d);/ / Where the currently displayed list goes / d->udata = ses;

d->items[0].type = D_BUTTON;
d->items[0].gid = B_ENTER;
d->items[0].fn = push_goto_button;
d->items[0].udata = ses;
d->items[0].text = TEXT_(T_GOTO);

d->items[1].type = D_BUTTON;
d->items[1].gid = B_ENTER;
d->items[1].fn = push_edit_button;
d->items[1].udata = ses;
d->items[1].text = TEXT_(T_EDIT);

d->items[2].type = D_BUTTON;
d->items[2].gid = B_ENTER;
d->items[2].fn = push_delete_button;
d->items[2].text = TEXT_(T_DELETE);

d->items[3].type = D_BUTTON;
d->items[3].gid = B_ENTER;
d->items[3].fn = push_add_button;
d->items[3].text = TEXT_(T_ADD);

d->items[4].type = D_BUTTON;
d->items[4].gid = B_ESC;
d->items[4].fn = cancel_dialog;
d->items[4].text = TEXT_(T_CLOSE);

d->items[5].type = D_BOX;   /* MP: D_BOX is nonsence. I tried to remove it, but didn't succeed */
d->items[5].gid = 12;
/*d->items[5].data = (void *)bookmark_dlg_box_build();*/    /* Where the currently displayed list goes */
bookmark_dlg_box_build((struct dlg_data_item_data_box**)(void *)&(d->items[5].data));   /* Where the currently displayed list goes */

d->items[6].type = D_END;
do_dialog(term, d, getml(d, NULL));

}

/ * * Bookmark add dialog * /

/ Adds the bookmark / void bookmark_add_add(struct dialog d) { struct dialog_data parent;

add_bookmark(d->items[0].data, d->items[1].data);

parent = d->udata;

/* Tell the bookmark dialog to redraw */
if (parent) 
    bookmark_dlg_list_update(&(((struct dlg_data_item_data_box*)parent->dlg->items[BM_BOX_IND].data)->items));

}

void launch_bm_add_doc_dialog(struct terminal term,struct dialog_data parent,struct session *ses) {

bookmark_edit_dialog(term, TEXT_(T_ADD_BOOKMARK), NULL, NULL, ses, parent, bookmark_add_add, NULL);

}

/ Called to launch an add dialog on the current link / void launch_bm_add_link_dialog(struct terminal term,struct dialog_data parent,struct session *ses) { unsigned char url[MAX_STR_LEN];

/* FIXME: Logic error -- if there is no current link, 
 * get_current_link_url() will return NULL, which will cause 
 * bookmark_add_dialog() to try and use the current document's url. 
 * Instead, it should use "". 
 */ 
bookmark_edit_dialog(term, TEXT_(T_ADD_BOOKMARK), NULL, get_current_link_url(ses, url, MAX_STR_LEN), ses, parent, bookmark_add_add, NULL);

}

unsigned char *bm_add_msg[] = { TEXT(T_NNAME), TEXT(T_URL), };

/ Called to setup the add bookmark dialog / void layout_add_dialog(struct dialog_data dlg) { int max = 0, min = 0; int w, rw; int y = -1; struct terminal term;

term = dlg->win->term;

max_text_width(term, bm_add_msg[0], &max);
min_text_width(term, bm_add_msg[0], &min);
max_text_width(term, bm_add_msg[1], &max);
min_text_width(term, bm_add_msg[1], &min);
max_buttons_width(term, dlg->items + 2, 2, &max);
min_buttons_width(term, dlg->items + 2, 2, &min);
w = term->x * 9 / 10 - 2 * DIALOG_LB;

if (w > max) w = max;
if (w < min) w = min;
if (w > term->x - 2 * DIALOG_LB) w = term->x - 2 * DIALOG_LB;
if (w < 1) w = 1;

w = rw = 50;

dlg_format_text(NULL, term, bm_add_msg[0], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);
y += 2;
dlg_format_text(NULL, term, bm_add_msg[1], 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT);
y += 2;
dlg_format_buttons(NULL, term, dlg->items + 2, 2, 0, &y, w, &rw, AL_CENTER);
w = rw;
dlg->xw = w + 2 * DIALOG_LB;
dlg->yw = y + 2 * DIALOG_TB;
center_dlg(dlg);
draw_dlg(dlg);
y = dlg->y + DIALOG_TB;
dlg_format_text(term, term, bm_add_msg[0], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);
dlg_format_field(NULL, term, &dlg->items[0], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
y++;
dlg_format_text(term, term, bm_add_msg[1], dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT);
dlg_format_field(term, term, &dlg->items[1], dlg->x + DIALOG_LB, &y, w, NULL, AL_LEFT);
y++;
dlg_format_buttons(term, term, &dlg->items[2], 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER);

}

/ Edits a bookmark’s fields. * If parent is defined, then that points to a dialog that should be sent * an update when the add is done. * * If either of src_name or src_url are NULL, try to obtain the name and url * of the current document. If you want to create two null fields, pass in a * pointer to a zero length string (“”). / void bookmark_edit_dialog( struct terminal term / Terminal to write on. /, unsigned char title / Title of the dialog. /, const unsigned char src_name / Pointer to name to use. (can be null)/, const unsigned char src_url / Url to use. (can be null) /, struct session ses, struct dialog_data parent / The parent window launching this one. /, void when_done(struct dialog ) / Function to execute on ‘ok’. /, void done_data / Spare data to pass to when_done. Stored in udata2 / ) { unsigned char name, url;

struct dialog *d;

/* Create the dialog */
d = mem_alloc(sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN);
memset(d, 0, sizeof(struct dialog) + 5 * sizeof(struct dialog_item) + sizeof(struct extension) + 2 * MAX_STR_LEN);

name = (unsigned char *)&d->items[5];
url = name + MAX_STR_LEN;

/* Get the name */
if (src_name == NULL) {
    /* Unknown name. */
    get_current_title(ses, name, MAX_STR_LEN);
} else {
    /* Known name. */
    safe_strncpy(name, src_name, MAX_STR_LEN);
}

/* Get the url */
if (src_url == NULL) {
    /* Unknown . */
    get_current_url(ses, url, MAX_STR_LEN);
} else {
    /* Known url. */
    safe_strncpy(url, src_url, MAX_STR_LEN);
}

d->title = title;
d->fn = layout_add_dialog;
d->refresh = (void (*)(void *))when_done;
d->refresh_data = d;
d->udata = parent;
d->udata2 = done_data;

d->items[0].type = D_FIELD;
d->items[0].dlen = MAX_STR_LEN;
d->items[0].data = name;
d->items[0].fn = check_nonempty;

d->items[1].type = D_FIELD;
d->items[1].dlen = MAX_STR_LEN;
d->items[1].data = url;
d->items[1].fn = check_nonempty;

d->items[2].type = D_BUTTON;
d->items[2].gid = B_ENTER;
d->items[2].fn = ok_dialog;
d->items[2].text = TEXT_(T_OK);

d->items[3].type = D_BUTTON;
d->items[3].gid = B_ESC;
d->items[3].text = TEXT_(T_CANCEL);
d->items[3].fn = cancel_dialog;

d->items[4].type = D_END;

do_dialog(term, d, getml(d, NULL));

}