#include "links.h" static struct list *block_new_item(void *ignore); static void block_delete_item(struct list *data); static void block_copy_item(struct list *in, struct list *out); static unsigned char *block_type_item(struct terminal *term, struct list *data, int x); static void block_edit_item(struct dialog_data *dlg, struct list *data, void (*ok_fn)(struct dialog_data *, struct list *, struct list *, struct list_description *), struct list *ok_arg, unsigned char dlg_title); static struct list *block_find_item(struct list *start, unsigned char *str, int direction); static struct history block_search_histroy = { 0, {&block_search_histroy.items, &block_search_histroy.items} }; struct list blocks = { init_list_1st(&blocks.list_entry) 0, -1, NULL, init_list_last(&blocks.list_entry) }; static struct list_description blocks_ld = { 0, /* flat */ &blocks, /* list head */ block_new_item, block_edit_item, NULL, block_delete_item, block_copy_item, block_type_item, block_find_item, &block_search_histroy, 0, /* this is set in init_assoc function */ 15, /* # of items in main window */ T_BLOCKED_IMAGE, /* item title */ T_BLOCK_LIST_IN_USE, /* Already open message */ T_BLOCK_LIST_MANAGER, /* Window title */ T_BLOCK_DELETE, 0, /* no button */ NULL, /* no button */ NULL, /* no save */ NULL, NULL, 0, 0, /* internal vars */ 0, /* modified */ NULL, NULL, 0, }; static struct list *block_new_item(void *ignore) { /*Default constructor*/ struct block *neww; neww = mem_alloc(sizeof(struct block)); neww->url = stracpy(cast_uchar ""); return &neww->head; } static void block_delete_item(struct list *data) { /*Destructor */ struct block *del = get_struct(data, struct block, head); if (del->head.list_entry.next) del_from_list(&del->head); mem_free(del->url); mem_free(del); } static void block_copy_item(struct list *in, struct list *out) { /*Copy construction */ struct block *item_in = get_struct(in, struct block, head); struct block *item_out = get_struct(out, struct block, head); mem_free(item_out->url); item_out->url = stracpy(item_in->url); } /*This is used to display the items in the menu*/ static unsigned char *block_type_item(struct terminal *term, struct list *data, int x) { unsigned char *txt, *txt1; struct block *item; if (data == &blocks) return stracpy(get_text_translation(TEXT_(T_BLOCK_LIST), term)); item = get_struct(data, struct block, head); txt = stracpy(item->url); /*I have no idea what this does, but it os copied from working code in types.c*/ txt1 = convert(blocks_ld.codepage, term_charset(term), txt, NULL); mem_free(txt); return txt1; } struct assoc_ok_struct { void (*fn)(struct dialog_data *, struct list *, struct list *, struct list_description *); struct list *data; struct dialog_data *dlg; }; /* destroys an item, this function is called when edit window is aborted */ static void block_edit_abort(struct dialog_data *data) { struct block *item = (struct block *)data->dlg->udata; struct dialog *dlg = data->dlg; mem_free(dlg->udata2); if (item) block_delete_item(&item->head); } /* Puts url into the block list */ static void block_edit_done(void *data) { /*Copied from types.c*/ struct dialog *d = (struct dialog *)data; struct block *item = (struct block *)d->udata; struct assoc_ok_struct *s = (struct assoc_ok_struct *)d->udata2; unsigned char *txt; unsigned char *url; /*See block_edit_item*/ url = (unsigned char *)&d->items[4]; txt = convert(term_charset(s->dlg->win->term), blocks_ld.codepage, url, NULL); mem_free(item->url); item->url = txt; s->fn(s->dlg, s->data, &item->head, &blocks_ld); d->udata = NULL; /* for abort function */ } static void block_edit_item_fn(struct dialog_data *dlg) { /*Copied from input_field. I don't know how most of it works.*/ #define LL gf_val(1, G_BFU_FONT_SIZE) struct terminal *term = dlg->win->term; int max = 0, min = 0; int w, rw; int y = gf_val(-1, -G_BFU_FONT_SIZE); unsigned char *text = TEXT_(T_ENTER_URL); if (dlg->win->term->spec->braille) y += gf_val(1, G_BFU_FONT_SIZE); max_text_width(term, text, &max, AL_LEFT); min_text_width(term, text, &min, AL_LEFT); max_buttons_width(term, dlg->items + 1, 2, &max); min_buttons_width(term, dlg->items + 1, 2, &min); if (max < dlg->dlg->items->dlen) max = dlg->dlg->items->dlen; w = term->x * 9 / 10 - 2 * DIALOG_LB; if (w > max) w = max; if (w < min) w = min; rw = w; dlg_format_text_and_field(dlg, NULL, text, dlg->items, 0, &y, w, &rw, COLOR_DIALOG_TEXT, AL_LEFT); y += LL; dlg_format_buttons(dlg, NULL, dlg->items + 1, 2, 0, &y, w, &rw, AL_CENTER); w = rw; dlg->xw = rw + 2 * DIALOG_LB; dlg->yw = y + 2 * DIALOG_TB; center_dlg(dlg); draw_dlg(dlg); y = dlg->y + DIALOG_TB; if (dlg->win->term->spec->braille) y += gf_val(1, G_BFU_FONT_SIZE); dlg_format_text_and_field(dlg, term, text, dlg->items, dlg->x + DIALOG_LB, &y, w, NULL, COLOR_DIALOG_TEXT, AL_LEFT); y += LL; dlg_format_buttons(dlg, term, dlg->items + 1, 2, dlg->x + DIALOG_LB, &y, w, NULL, AL_CENTER); } static void block_edit_item(struct dialog_data *dlg, struct list *data, void (*ok_fn)(struct dialog_data *, struct list *, struct list *, struct list_description *), struct list *ok_arg, unsigned char dlg_title) { /*Copied from types.c */ /*Data is a new item generated by the "default" function*/ struct block *neww = get_struct(data, struct block, head); struct terminal *term = dlg->win->term; struct dialog *d; struct assoc_ok_struct *s; unsigned char *url, *txt; /*Allocate space for dialog, 4 items followed by 1 string*/ d = mem_alloc(sizeof(struct dialog) + 4 * sizeof(struct dialog_item) + 1 * MAX_STR_LEN); memset(d, 0, sizeof(struct dialog) + 4 * sizeof(struct dialog_item) + 1 * MAX_STR_LEN); /*Set up this string */ url = (unsigned char *)&d->items[4]; txt = convert(blocks_ld.codepage, term_charset(dlg->win->term), neww->url, NULL); safe_strncpy(url, txt, MAX_STR_LEN); mem_free(txt); /* Create the dialog */ s = mem_alloc(sizeof(struct assoc_ok_struct)); s->fn = ok_fn; s->data = ok_arg; s->dlg = dlg; switch (dlg_title) { case TITLE_EDIT: d->title = TEXT_(T_BLOCK_EDIT); break; case TITLE_ADD: d->title = TEXT_(T_BLOCK_ADD); break; default: internal_error("Unsupported dialog title.\n"); } d->udata = neww; d->udata2 = s; d->fn = block_edit_item_fn; d->abort = block_edit_abort; d->refresh = block_edit_done; d->refresh_data = d; d->items[0].type = D_FIELD; d->items[0].dlen = MAX_STR_LEN; d->items[0].data = url; d->items[0].fn = check_nonempty; d->items[1].type = D_BUTTON; d->items[1].gid = B_ENTER; d->items[1].fn = ok_dialog; d->items[1].text = TEXT_(T_OK); d->items[2].type = D_BUTTON; d->items[2].gid = B_ESC; d->items[2].text = TEXT_(T_CANCEL); d->items[2].fn = cancel_dialog; d->items[3].type = D_END; do_dialog(term, d, getml(d, NULL)); } static int test_entry(struct list *e, unsigned char *str) { return casestrstr(get_struct(e, struct block, head)->url, str); } static struct list *block_find_item(struct list *s, unsigned char *str, int direction) { struct list *e; if (direction >= 0) { for (e = list_next(s); e != s; e = list_next(e)) { if (e->depth >= 0 && test_entry(e, str)) return e; } } else { for (e = list_prev(s); e != s; e = list_prev(e)) { if (e->depth >= 0 && test_entry(e, str)) return e; } } if (e->depth >= 0 && test_entry(e, str)) return e; return NULL; } void block_manager(struct terminal *term, void *fcp, void *ses_) { struct session *ses = (struct session *)ses_; create_list_window(&blocks_ld, &blocks, term, ses); } void *block_url_add(void *ses_, unsigned char *url) { struct session *ses = (struct session *)ses_; /*Callback from the dialog box created from the link menu*/ struct list *new_list; struct block *new_b; struct terminal *term = ses ? ses->term : NULL; if (test_list_window_in_use(&blocks_ld, term)) return NULL; new_list = block_new_item(0); new_b = get_struct(new_list, struct block, head); mem_free(new_b->url); new_b->url = stracpy(url); new_b->head.type = 0; add_to_list(blocks.list_entry, &new_b->head); return NULL; } void block_url_query(struct session *ses, unsigned char *u) { if (test_list_window_in_use(&blocks_ld, ses->term)) return; input_field(ses->term, NULL, TEXT_(T_BLOCK_URL), TEXT_(T_BLOCK_ADD), ses, 0, MAX_INPUT_URL_LEN, u, 0, 0, NULL, 2, TEXT_(T_OK), block_url_add, TEXT_(T_CANCEL), input_field_null); } static unsigned char *find_first_match(unsigned char *s, unsigned char *p, unsigned *ii) { unsigned i; retry: for (i = 0; s[i] && p[i] && p[i] != '*'; i++) { if (s[i] != p[i] && p[i] != '?') { s++; goto retry; } } *ii = i; if (!p[i] || p[i] == '*') return s; return NULL; } static int simple_glob_match(unsigned char *s, unsigned char *p) { unsigned i; if (find_first_match(s, p, &i) != s) return 0; if (!p[i]) return !s[i]; while (1) { s += i; p += i + 1; if (!(s = find_first_match(s, p, &i))) return 0; if (!p[i]) { s += strlen(cast_const_char s) - i; return !!find_first_match(s, p, &i); } } } int is_url_blocked(unsigned char *url) { struct list *b; struct list_head *lb; foreach(struct list, b, lb, blocks.list_entry) { if (simple_glob_match(url, get_struct(b, struct block, head)->url)) return 1; } return 0; } void init_blocks(void) { blocks_ld.codepage = utf8_table; } void free_blocks(void) { /*List destructor */ struct list *b; struct list_head *lb; foreach(struct list, b, lb, blocks.list_entry) { struct block *bm = get_struct(b, struct block, head); mem_free(bm->url); lb = lb->prev; del_from_list(b); mem_free(bm); } free_history(block_search_histroy); }