From 1000f8874813b77f9691ea2df94c0625cfc43472 Mon Sep 17 00:00:00 2001 From: Miciah Dashiel Butler Masters Date: Sat, 1 Sep 2007 03:08:47 +0000 Subject: [PATCH] bug 181: Allow edit textareas using an external editor on slave terminals. Added EVENT_TEXTAREA used to notify the master terminal about end of execution of an external program on a slave terminal. The format of data sent to the master terminal by exec_on_slave_terminal has changed. Now after 0, fg the value of term is sent. Therfore this release of ELinks is incompatible with previous releases. Patch by Witold Filipczyk, taken from his witekfl branch. Conflicts: src/viewer/text/textarea.c --- src/bfu/dialog.c | 2 + src/bfu/hierbox.c | 1 + src/bfu/listbox.c | 1 + src/bfu/menu.c | 3 + src/session/session.c | 2 + src/terminal/event.c | 6 ++ src/terminal/event.h | 4 ++ src/terminal/kbd.c | 12 ++++ src/terminal/terminal.c | 9 +-- src/terminal/window.c | 1 + src/viewer/text/textarea.c | 114 ++++++++++++++++++++----------------- 11 files changed, 100 insertions(+), 55 deletions(-) diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c index f99e7814..865415a9 100644 --- a/src/bfu/dialog.c +++ b/src/bfu/dialog.c @@ -460,6 +460,8 @@ dialog_func(struct window *win, struct term_event *ev) case EVENT_ABORT: dialog_ev_abort(dlg_data); break; + case EVENT_TEXTAREA: + break; } } diff --git a/src/bfu/hierbox.c b/src/bfu/hierbox.c index 5d49e64e..6cbaaa61 100644 --- a/src/bfu/hierbox.c +++ b/src/bfu/hierbox.c @@ -281,6 +281,7 @@ hierbox_dialog_event_handler(struct dialog_data *dlg_data) case EVENT_RESIZE: case EVENT_REDRAW: case EVENT_MOUSE: + case EVENT_TEXTAREA: return EVENT_NOT_PROCESSED; case EVENT_ABORT: diff --git a/src/bfu/listbox.c b/src/bfu/listbox.c index 2e27abae..8d54858c 100644 --- a/src/bfu/listbox.c +++ b/src/bfu/listbox.c @@ -729,6 +729,7 @@ kbd_listbox(struct dialog_data *dlg_data, struct widget_data *widget_data) case EVENT_REDRAW: case EVENT_MOUSE: case EVENT_ABORT: + case EVENT_TEXTAREA: break; } diff --git a/src/bfu/menu.c b/src/bfu/menu.c index f4501017..d45854cf 100644 --- a/src/bfu/menu.c +++ b/src/bfu/menu.c @@ -1006,6 +1006,8 @@ menu_handler(struct window *win, struct term_event *ev) case EVENT_ABORT: free_menu_items(menu->items); break; + case EVENT_TEXTAREA: + break; } } @@ -1343,6 +1345,7 @@ mainmenu_handler(struct window *win, struct term_event *ev) break; case EVENT_ABORT: + case EVENT_TEXTAREA: break; } } diff --git a/src/session/session.c b/src/session/session.c index cdb44aa1..149cdca2 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -1283,6 +1283,8 @@ tabwin_func(struct window *tab, struct term_event *ev) assert(ses->tab == get_current_tab(ses->tab->term)); send_event(ses, ev); break; + case EVENT_TEXTAREA: + break; } } diff --git a/src/terminal/event.c b/src/terminal/event.c index 1cea4589..4628fc77 100644 --- a/src/terminal/event.c +++ b/src/terminal/event.c @@ -31,6 +31,7 @@ #include "util/memory.h" #include "util/snprintf.h" #include "util/string.h" +#include "viewer/text/textarea.h" #include "viewer/timer.h" @@ -118,6 +119,7 @@ term_send_event(struct terminal *term, struct term_event *ev) case EVENT_MOUSE: case EVENT_KBD: case EVENT_ABORT: + case EVENT_TEXTAREA: assert(!list_empty(term->windows)); if_assert_failed break; @@ -443,6 +445,10 @@ invalid_utf8_start_byte: case EVENT_ABORT: destroy_terminal(term); return 0; + case EVENT_TEXTAREA: + if (textarea_editor) + textarea_edit(1, ilev->info.textarea, NULL, NULL, NULL); + break; default: ERROR(gettext("Bad event %d"), ilev->ev); diff --git a/src/terminal/event.h b/src/terminal/event.h index 9de3ce1e..b0f197a7 100644 --- a/src/terminal/event.h +++ b/src/terminal/event.h @@ -20,6 +20,7 @@ enum term_event_type { EVENT_REDRAW, EVENT_RESIZE, EVENT_ABORT, + EVENT_TEXTAREA, }; /** An event received from a terminal. This type can be changed @@ -58,6 +59,9 @@ struct interlink_event { /* ::EVENT_INIT, ::EVENT_RESIZE, ::EVENT_REDRAW */ #define interlink_event_size term_event_size struct interlink_event_size size; + + /* EVENT_TEXTAREA */ + struct terminal *textarea; } info; }; diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c index e7e2e169..21761dd9 100644 --- a/src/terminal/kbd.c +++ b/src/terminal/kbd.c @@ -42,6 +42,8 @@ #include "util/time.h" struct itrm *ditrm = NULL; +static struct terminal *slave_term; +static unsigned char *term_addr = (unsigned char *)&slave_term; static void free_itrm(struct itrm *); static void in_kbd(struct itrm *); @@ -352,10 +354,17 @@ handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, static void unblock_itrm_x(void *h) { + struct interlink_event ev; + close_handle(h); if (!ditrm) return; unblock_itrm(); resize_terminal(); + + memset(&ev, 0, sizeof(ev)); + ev.ev = EVENT_TEXTAREA; + ev.info.textarea = slave_term; + itrm_queue_event(ditrm, (char *) &ev, sizeof(ev)); } @@ -549,6 +558,9 @@ has_nul_byte: } RD(fg); + for (i = 0; i < sizeof(slave_term); i++) { + RD(term_addr[i]); + } if (!init_string(&path)) goto free_and_return; diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 75e8994c..c1d940b6 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -203,7 +203,7 @@ unblock_terminal(struct terminal *term) unblock_itrm(); redraw_terminal_cls(term); if (textarea_editor) /* XXX */ - textarea_edit(1, NULL, NULL, NULL, NULL); + textarea_edit(1, term, NULL, NULL, NULL); } @@ -256,15 +256,16 @@ exec_on_slave_terminal( struct terminal *term, unsigned char *delete, int dlen, enum term_exec fg) { - int data_size = plen + dlen + 1 /* 0 */ + 1 /* fg */ + 2 /* 2 null char */; + int data_size = sizeof(term) + plen + dlen + 1 /* 0 */ + 1 /* fg */ + 2 /* 2 null char */; unsigned char *data = fmem_alloc(data_size); if (!data) return; data[0] = 0; data[1] = fg; - memcpy(data + 2, path, plen + 1); - memcpy(data + 2 + plen + 1, delete, dlen + 1); + memcpy(data + 2, &term, sizeof(term)); + memcpy(data + 2 + sizeof(term), path, plen + 1); + memcpy(data + 2 + sizeof(term) + plen + 1, delete, dlen + 1); hard_write(term->fdout, data, data_size); fmem_free(data); } diff --git a/src/terminal/window.c b/src/terminal/window.c index d4cd6c1b..4e96f2d0 100644 --- a/src/terminal/window.c +++ b/src/terminal/window.c @@ -152,6 +152,7 @@ empty_window_handler(struct window *win, struct term_event *ev) return; case EVENT_KBD: case EVENT_MOUSE: + case EVENT_TEXTAREA: /* Silence compiler warnings */ break; } diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index b7a2cba4..369917fd 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -29,6 +29,7 @@ #include "terminal/window.h" #include "util/error.h" #include "util/file.h" +#include "util/lists.h" #include "util/memory.h" #include "util/string.h" #include "viewer/action.h" @@ -47,6 +48,18 @@ struct line_info { #endif /* CONFIG_UTF8 */ }; +struct textarea_data { + LIST_HEAD(struct textarea_data); + size_t fc_maxlength; + struct form_state *fs; + struct terminal *term; + struct document_view *doc_view; + struct link *link; + unsigned char *fn; +}; + +static INIT_LIST_HEAD(textarea_list); /* struct textarea_data */ + /** We add two extra entries to the table so the ending info can be added * without reallocating. */ #define realloc_line_info(info, size) \ @@ -577,16 +590,9 @@ void textarea_edit(int op, struct terminal *term_, struct form_state *fs_, struct document_view *doc_view_, struct link *link_) { - static size_t fc_maxlength; - static struct form_state *fs; - static struct terminal *term; - static struct document_view *doc_view; - static struct link *link; - static unsigned char *fn; + struct textarea_data *td; - assert (op == 0 || op == 1); - if_assert_failed return; - assert (op == 1 || term_); + assert ((op == 0 || op == 1) && term_); if_assert_failed return; if (op == 0 && get_cmd_opt_bool("anonymous")) { @@ -596,20 +602,20 @@ textarea_edit(int op, struct terminal *term_, struct form_state *fs_, return; } - if (op == 0 && !term_->master) { - info_box(term_, 0, N_("Error"), ALIGN_CENTER, - N_("You can do this only on the master terminal")); - return; - } - - if (op == 0 && !textarea_editor) { + if (op == 0) { unsigned char *ed; unsigned char *ex; assert(fs_ && doc_view_ && link_ && term_); - fn = save_textarea_file(fs_->value); - if (!fn) return; + td = mem_calloc(1, sizeof(*td)); + if (!td) return; + + td->fn = save_textarea_file(fs_->value); + if (!td->fn) { + mem_free(td); + return; + } ed = get_opt_str("document.browse.forms.editor", doc_view_->session); @@ -618,41 +624,50 @@ textarea_edit(int op, struct terminal *term_, struct form_state *fs_, if (!ed || !*ed) ed = "vi"; } - ex = straconcat(ed, " ", fn, (unsigned char *) NULL); + ex = straconcat(ed, " ", td->fn, (unsigned char *) NULL); if (!ex) { - unlink(fn); + unlink(td->fn); goto free_and_return; } - fs = fs_; - doc_view = doc_view_; - link = link_; - fc_maxlength = get_link_form_control(link_)->maxlength; - term = term_; + td->fs = fs_; + td->doc_view = doc_view_; + td->link = link_; + td->fc_maxlength = get_link_form_control(link_)->maxlength; + td->term = term_; + add_to_list(textarea_list, td); - exec_on_terminal(term, ex, "", TERM_EXEC_FG); + exec_on_terminal(td->term, ex, "", TERM_EXEC_FG); mem_free(ex); - textarea_editor = 1; + textarea_editor++; + return; - } else if (op == 1 && fs) { + } else if (op == 1) { + int found = 0; struct string file; - if (!init_string(&file) - || !add_file_to_string(&file, fn)) { - textarea_editor = 0; - goto free_and_return; + foreach (td, textarea_list) { + if (td->term == term_) { + found = 1; + break; + } } + if (!found) return; - if (file.length > fc_maxlength) { - file.source[fc_maxlength] = '\0'; + if (!td->fs || !init_string(&file) + || !add_file_to_string(&file, td->fn)) + goto end; + + if (file.length > td->fc_maxlength) { + file.source[td->fc_maxlength] = '\0'; /* Casting size_t fc_maxlength to unsigned int * and formatting it with "%u" is safe, * because fc_maxlength is smaller than * file.length, which is an int. */ - info_box(term, MSGBOX_FREE_TEXT, N_("Warning"), + info_box(td->term, MSGBOX_FREE_TEXT, N_("Warning"), ALIGN_CENTER, - msg_text(term, + msg_text(td->term, N_("You have exceeded the textarea's" " size limit: your input is %d" " bytes, but the maximum is %u" @@ -661,27 +676,24 @@ textarea_edit(int op, struct terminal *term_, struct form_state *fs_, " but you can still recover the" " text that you entered from" " this file: %s"), file.length, - (unsigned int) fc_maxlength, fn)); + (unsigned int) td->fc_maxlength, td->fn)); } else { - unlink(fn); + unlink(td->fn); } - mem_free(fs->value); - fs->value = file.source; - fs->state = file.length; + mem_free(td->fs->value); + td->fs->value = file.source; + td->fs->state = file.length; - if (doc_view && link) - draw_form_entry(term, doc_view, link); - - textarea_editor = 0; - goto free_and_return; + if (td->doc_view && td->link) + draw_form_entry(td->term, td->doc_view, td->link); } - - return; - +end: + del_from_list(td); + textarea_editor--; free_and_return: - mem_free_set(&fn, NULL); - fs = NULL; + mem_free(td->fn); + mem_free(td); } /* menu_func_T */