term: batch simple input events into a single %txt

By accumulating %txt events until we reach a more complex event or reach
the end of the input buffer, we can significantly reduce the "overhead"
of pasting text into the terminal. Instead of an event for each
character, we now inject up to a buffer's worth of characters
(currently, 123 bytes) at a time. This makes pasting process much
faster.

Incidentally, the behavior for pasting text with syntax errors into the
dojo may be a little bit surprising: after every buffer boundary, the
dojo will complain about the syntax error, moving the cursor to its
location, and causing the remainder of the text to be inserted in that
position. This may result in garbled-looking input in some cases.
This ux problem should be resolved on dojo's end, perhaps by
highlighting syntax errors with color, instead of the cursor.

Alleviates most of the need for #5687.
This commit is contained in:
fang 2022-04-01 22:15:34 +02:00
parent 531fd61ace
commit c5b07f5203
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972
2 changed files with 39 additions and 17 deletions

View File

@ -158,10 +158,11 @@
c3_y col_y; // column coordinate
} esc;
struct {
c3_y syb_y[5]; // utf8 code buffer
c3_w len_w; // present length
c3_w wid_w; // total width
struct { // input buffering
c3_y syb_y[5]; // utf8 code buffer
c3_w len_w; // present length
c3_w wid_w; // total width
u3_noun imp; // %txt input buffer
} fut;
struct {

View File

@ -147,6 +147,7 @@ u3_term_log_init(void)
uty_u->tat_u.fut.len_w = 0;
uty_u->tat_u.fut.wid_w = 0;
uty_u->tat_u.fut.imp = u3_nul;
}
// default size
@ -636,9 +637,28 @@ _term_io_belt(u3_utty* uty_u, u3_noun blb)
}
}
/* _term_io_suck_char(): process a single character.
/* _term_io_spit(): input the buffer (if any), then input the belt (if any)
*/
static void
_term_io_spit(u3_utty* uty_u, u3_noun bet) {
u3_utat* tat_u = &uty_u->tat_u;
if (u3_nul != tat_u->fut.imp) {
_term_io_belt(uty_u, u3nc(c3__txt, u3kb_flop(tat_u->fut.imp)));
tat_u->fut.imp = u3_nul;
}
if (u3_none != bet) {
_term_io_belt(uty_u, bet);
}
}
/* _term_io_suck_char(): process a single character.
*
* Note that this accumulates simple inputs in a buffer, and is not
* guaranteed to flush it fully. After a call (or sequence of calls)
* to this function, please call _term_io_spit(uty_u, u3_none) to
* flush any remainder.
*/
static void
_term_io_suck_char(u3_utty* uty_u, c3_y cay_y)
{
u3_utat* tat_u = &uty_u->tat_u;
@ -652,10 +672,10 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y)
_term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u);
break;
}
case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break;
case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break;
case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break;
case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break;
case 'A': _term_io_spit(uty_u, u3nc(c3__aro, 'u')); break;
case 'B': _term_io_spit(uty_u, u3nc(c3__aro, 'd')); break;
case 'C': _term_io_spit(uty_u, u3nc(c3__aro, 'r')); break;
case 'D': _term_io_spit(uty_u, u3nc(c3__aro, 'l')); break;
//
case 'M': tat_u->esc.mou = c3y; break;
}
@ -667,13 +687,13 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y)
// XX for backwards compatibility, check kelvin version
// and fallback to [%met @c]
//
_term_io_belt(uty_u, u3nt(c3__mod, c3__met, cay_y));
_term_io_spit(uty_u, u3nt(c3__mod, c3__met, cay_y));
}
else if ( 8 == cay_y || 127 == cay_y ) {
tat_u->esc.ape = c3n;
// XX backwards compatibility [%met @c]
//
_term_io_belt(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul));
_term_io_spit(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul));
}
else if ( ('[' == cay_y) || ('O' == cay_y) ) {
tat_u->esc.bra = c3y;
@ -698,7 +718,7 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y)
c3_y row_y = cay_y - 32;
// only acknowledge button 1 presses within our window
if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) {
_term_io_belt(uty_u, u3nt(c3__hit,
_term_io_spit(uty_u, u3nt(c3__hit,
tat_u->esc.col_y - 1,
tat_u->siz.row_l - row_y));
}
@ -720,28 +740,28 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y)
wug = u3do("taft", huv);
tat_u->fut.len_w = tat_u->fut.wid_w = 0;
_term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul));
tat_u->fut.imp = u3nc(wug, tat_u->fut.imp);
}
}
// individual characters
//
else {
if ( (cay_y >= 32) && (cay_y < 127) ) { // visual ascii
_term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul));
tat_u->fut.imp = u3nc(cay_y, tat_u->fut.imp);
}
else if ( 0 == cay_y ) { // null
_term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u);
}
else if ( 8 == cay_y || 127 == cay_y ) { // backspace & delete
_term_io_belt(uty_u, u3nc(c3__bac, u3_nul));
_term_io_spit(uty_u, u3nc(c3__bac, u3_nul));
}
else if ( 10 == cay_y || 13 == cay_y ) { // newline & carriage return
_term_io_belt(uty_u, u3nc(c3__ret, u3_nul));
_term_io_spit(uty_u, u3nc(c3__ret, u3_nul));
}
else if ( cay_y <= 26 ) {
// XX backwards compatibility [%ctl @c]
//
_term_io_belt(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1))));
_term_io_spit(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1))));
}
else if ( 27 == cay_y ) {
tat_u->esc.ape = c3y;
@ -799,6 +819,7 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i)
for ( i=0; i < siz_i; i++ ) {
_term_io_suck_char(uty_u, buf[i]);
}
_term_io_spit(uty_u, u3_none);
}
}
}