mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
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.
This commit is contained in:
parent
4cca8f1a2c
commit
6bc992250b
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1290,6 +1290,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "util/memory.h"
|
||||
#include "util/snprintf.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/textarea.h"
|
||||
#include "viewer/timer.h"
|
||||
|
||||
|
||||
@ -116,6 +117,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;
|
||||
|
||||
@ -439,6 +441,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);
|
||||
|
@ -19,6 +19,7 @@ enum term_event_type {
|
||||
EVENT_REDRAW,
|
||||
EVENT_RESIZE,
|
||||
EVENT_ABORT,
|
||||
EVENT_TEXTAREA,
|
||||
};
|
||||
|
||||
struct term_event {
|
||||
@ -51,6 +52,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;
|
||||
};
|
||||
|
||||
|
@ -40,6 +40,8 @@
|
||||
/* TODO: move stuff from here to itrm.{c,h} and mouse.{c,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 *);
|
||||
@ -348,10 +350,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));
|
||||
}
|
||||
|
||||
|
||||
@ -545,6 +554,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;
|
||||
|
||||
|
@ -202,7 +202,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);
|
||||
}
|
||||
|
||||
|
||||
@ -255,15 +255,16 @@ exec_on_slave_terminal( struct terminal *term,
|
||||
unsigned char *delete, int dlen,
|
||||
int 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);
|
||||
}
|
||||
|
@ -151,6 +151,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;
|
||||
}
|
||||
|
@ -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) \
|
||||
@ -574,16 +587,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")) {
|
||||
@ -593,61 +599,70 @@ 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 = get_opt_str("document.browse.forms.editor");
|
||||
unsigned char *ex;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!ed || !*ed) {
|
||||
ed = getenv("EDITOR");
|
||||
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;
|
||||
}
|
||||
|
||||
if (fs_) fs = fs_;
|
||||
if (doc_view_) doc_view = doc_view_;
|
||||
if (fs_) td->fs = fs_;
|
||||
if (doc_view_) td->doc_view = doc_view_;
|
||||
if (link_) {
|
||||
link = link_;
|
||||
fc_maxlength = get_link_form_control(link_)->maxlength;
|
||||
td->link = link_;
|
||||
td->fc_maxlength = get_link_form_control(link_)->maxlength;
|
||||
}
|
||||
if (term_) term = term_;
|
||||
if (term_) td->term = term_;
|
||||
add_to_list(textarea_list, td);
|
||||
|
||||
exec_on_terminal(term, ex, "", 1);
|
||||
exec_on_terminal(td->term, ex, "", 1);
|
||||
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"
|
||||
@ -656,27 +671,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user