links/block.c
2021-08-28 18:37:32 +03:00

357 lines
9.5 KiB
C

#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);
}