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 */