"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libedit/refresh.c" between
tnftp-20151004.tar.gz and tnftp-20200705.tar.gz

About: tnftp is an enhanced ftp client (prior name "lukemftp").

refresh.c  (tnftp-20151004):refresh.c  (tnftp-20200705)
/* $NetBSD: refresh.c,v 1.5 2005/06/09 16:48:58 lukem Exp $ */ /* $NetBSD: refresh.c,v 1.8 2020/07/04 13:43:21 lukem Exp $ */
/* from NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp */ /* from NetBSD: refresh.c,v 1.57 2020/03/30 06:54:37 ryo Exp */
/*- /*-
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University. * Christos Zoulas of Cornell University.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
skipping to change at line 36 skipping to change at line 36
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include "tnftp.h" #include "config.h"
#include "sys.h"
#if 0 /* tnftp */
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID(" NetBSD: refresh.c,v 1.57 2020/03/30 06:54:37 ryo Exp ");
#endif
#endif /* not lint && not SCCSID */
#endif /* tnftp */
/* /*
* refresh.c: Lower level screen refreshing functions * refresh.c: Lower level screen refreshing functions
*/ */
#if 0 /* tnftp */
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#endif /* tnftp */
#include "el.h" #include "el.h"
private void re_addc(EditLine *, int); static void re_nextline(EditLine *);
private void re_update_line(EditLine *, char *, char *, int); static void re_addc(EditLine *, wint_t);
private void re_insert (EditLine *, char *, int, int, char *, int); static void re_update_line(EditLine *, wchar_t *, wchar_t *, int);
private void re_delete(EditLine *, char *, int, int, int); static void re_insert (EditLine *, wchar_t *, int, int, wchar_t *, int);
private void re_fastputc(EditLine *, int); static void re_delete(EditLine *, wchar_t *, int, int, int);
private void re__strncopy(char *, char *, size_t); static void re_fastputc(EditLine *, wint_t);
private void re__copy_and_pad(char *, const char *, size_t); static void re_clear_eol(EditLine *, int, int, int);
static void re__strncopy(wchar_t *, wchar_t *, size_t);
static void re__copy_and_pad(wchar_t *, const wchar_t *, size_t);
#ifdef DEBUG_REFRESH #ifdef DEBUG_REFRESH
private void re_printstr(EditLine *, const char *, char *, char *); static void re_printstr(EditLine *, const char *, wchar_t *, wchar_t *);
#define __F el->el_errfile #define __F el->el_errfile
#define ELRE_ASSERT(a, b, c) do \ #define ELRE_ASSERT(a, b, c) do \
if (/*CONSTCOND*/ a) { \ if (/*CONSTCOND*/ a) { \
(void) fprintf b; \ (void) fprintf b; \
c; \ c; \
} \ } \
while (/*CONSTCOND*/0) while (/*CONSTCOND*/0)
#define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;) #define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;)
/* re_printstr(): /* re_printstr():
* Print a string on the debugging pty * Print a string on the debugging pty
*/ */
private void static void
re_printstr(EditLine *el, const char *str, char *f, char *t) re_printstr(EditLine *el, const char *str, wchar_t *f, wchar_t *t)
{ {
ELRE_DEBUG(1, (__F, "%s:\"", str)); ELRE_DEBUG(1, (__F, "%s:\"", str));
while (f < t) while (f < t)
ELRE_DEBUG(1, (__F, "%c", *f++ & 0177)); ELRE_DEBUG(1, (__F, "%c", *f++ & 0177));
ELRE_DEBUG(1, (__F, "\"\r\n")); ELRE_DEBUG(1, (__F, "\"\r\n"));
} }
#else #else
#define ELRE_ASSERT(a, b, c) #define ELRE_ASSERT(a, b, c)
#define ELRE_DEBUG(a, b) #define ELRE_DEBUG(a, b)
#endif #endif
/* re_nextline():
* Move to the next line or scroll
*/
static void
re_nextline(EditLine *el)
{
el->el_refresh.r_cursor.h = 0; /* reset it. */
/*
* If we would overflow (input is longer than terminal size),
* emulate scroll by dropping first line and shuffling the rest.
* We do this via pointer shuffling - it's safe in this case
* and we avoid memcpy().
*/
if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) {
int i, lins = el->el_terminal.t_size.v;
wchar_t *firstline = el->el_vdisplay[0];
for(i = 1; i < lins; i++)
el->el_vdisplay[i - 1] = el->el_vdisplay[i];
firstline[0] = '\0'; /* empty the string */
el->el_vdisplay[i - 1] = firstline;
} else
el->el_refresh.r_cursor.v++;
ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v,
(__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
el->el_refresh.r_cursor.v, el->el_terminal.t_size.v),
abort());
}
/* re_addc(): /* re_addc():
* Draw c, expanding tabs, control chars etc. * Draw c, expanding tabs, control chars etc.
*/ */
private void static void
re_addc(EditLine *el, int c) re_addc(EditLine *el, wint_t c)
{ {
switch (ct_chr_class(c)) {
if (isprint(c)) { case CHTYPE_TAB: /* expand the tab */
re_putc(el, c, 1);
return;
}
if (c == '\n') { /* expand the newline */
int oldv = el->el_refresh.r_cursor.v;
re_putc(el, '\0', 0); /* assure end of line */
if (oldv == el->el_refresh.r_cursor.v) { /* XXX */
el->el_refresh.r_cursor.h = 0; /* reset cursor pos */
el->el_refresh.r_cursor.v++;
}
return;
}
if (c == '\t') { /* expand the tab */
for (;;) { for (;;) {
re_putc(el, ' ', 1); re_putc(el, ' ', 1);
if ((el->el_refresh.r_cursor.h & 07) == 0) if ((el->el_refresh.r_cursor.h & 07) == 0)
break; /* go until tab stop */ break; /* go until tab stop */
} }
} else if (iscntrl(c)) { break;
re_putc(el, '^', 1); case CHTYPE_NL: {
if (c == '\177') int oldv = el->el_refresh.r_cursor.v;
re_putc(el, '?', 1); re_putc(el, '\0', 0); /* assure end of line */
else if (oldv == el->el_refresh.r_cursor.v) /* XXX */
/* uncontrolify it; works only for iso8859-1 like sets */ re_nextline(el);
re_putc(el, (c | 0100), 1); break;
} else { }
re_putc(el, '\\', 1); case CHTYPE_PRINT:
re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1); re_putc(el, c, 1);
re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1); break;
re_putc(el, (c & 07) + '0', 1); default: {
wchar_t visbuf[VISUAL_WIDTH_MAX];
ssize_t i, n =
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
for (i = 0; n-- > 0; ++i)
re_putc(el, visbuf[i], 1);
break;
}
}
}
/* re_putliteral():
* Place the literal string given
*/
libedit_private void
re_putliteral(EditLine *el, const wchar_t *begin, const wchar_t *end)
{
coord_t *cur = &el->el_refresh.r_cursor;
wint_t c;
int sizeh = el->el_terminal.t_size.h;
int i, w;
c = literal_add(el, begin, end, &w);
if (c == 0 || w <= 0)
return;
el->el_vdisplay[cur->v][cur->h] = c;
i = w;
if (i > sizeh - cur->h) /* avoid overflow */
i = sizeh - cur->h;
while (--i > 0)
el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
cur->h += w;
if (cur->h >= sizeh) {
/* assure end of line */
el->el_vdisplay[cur->v][sizeh] = '\0';
re_nextline(el);
} }
} }
/* re_putc(): /* re_putc():
* Draw the character given * Draw the character given
*/ */
protected void libedit_private void
re_putc(EditLine *el, int c, int shift) re_putc(EditLine *el, wint_t c, int shift)
{ {
coord_t *cur = &el->el_refresh.r_cursor;
int i, w = wcwidth(c);
int sizeh = el->el_terminal.t_size.h;
ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c));
if (w == -1)
w = 0;
while (shift && (cur->h + w > sizeh))
re_putc(el, ' ', 1);
el->el_vdisplay[cur->v][cur->h] = c;
/* assumes !shift is only used for single-column chars */
i = w;
while (--i > 0)
el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c));
el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c
;
if (!shift) if (!shift)
return; return;
el->el_refresh.r_cursor.h++; /* advance to next place */ cur->h += w; /* advance to next place */
if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) { if (cur->h >= sizeh) {
el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h]
= '\0';
/* assure end of line */ /* assure end of line */
el->el_refresh.r_cursor.h = 0; /* reset it. */ el->el_vdisplay[cur->v][sizeh] = '\0';
re_nextline(el);
/*
* If we would overflow (input is longer than terminal size),
* emulate scroll by dropping first line and shuffling the rest.
* We do this via pointer shuffling - it's safe in this case
* and we avoid memcpy().
*/
if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) {
int i, lins = el->el_term.t_size.v;
char *firstline = el->el_vdisplay[0];
for(i=1; i < lins; i++)
el->el_vdisplay[i-1] = el->el_vdisplay[i];
firstline[0] = '\0'; /* empty the string */
el->el_vdisplay[i-1] = firstline;
} else
el->el_refresh.r_cursor.v++;
ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
(__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
el->el_refresh.r_cursor.v, el->el_term.t_size.v),
abort());
} }
} }
/* re_refresh(): /* re_refresh():
* draws the new virtual screen image from the current input * draws the new virtual screen image from the current input
* line, then goes line-by-line changing the real image to the new * line, then goes line-by-line changing the real image to the new
* virtual image. The routine to re-draw a line can be replaced * virtual image. The routine to re-draw a line can be replaced
* easily in hopes of a smarter one being placed there. * easily in hopes of a smarter one being placed there.
*/ */
protected void libedit_private void
re_refresh(EditLine *el) re_refresh(EditLine *el)
{ {
int i, rhdiff; int i, rhdiff;
char *cp, *st; wchar_t *cp, *st;
coord_t cur; coord_t cur;
#ifdef notyet #ifdef notyet
size_t termsz; size_t termsz;
#endif #endif
ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%s:\r\n", ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%ls:\r\n",
el->el_line.buffer)); el->el_line.buffer));
literal_clear(el);
/* reset the Drawing cursor */ /* reset the Drawing cursor */
el->el_refresh.r_cursor.h = 0; el->el_refresh.r_cursor.h = 0;
el->el_refresh.r_cursor.v = 0; el->el_refresh.r_cursor.v = 0;
terminal_move_to_char(el, 0);
/* temporarily draw rprompt to calculate its size */ /* temporarily draw rprompt to calculate its size */
prompt_print(el, EL_RPROMPT); prompt_print(el, EL_RPROMPT);
/* reset the Drawing cursor */ /* reset the Drawing cursor */
el->el_refresh.r_cursor.h = 0; el->el_refresh.r_cursor.h = 0;
el->el_refresh.r_cursor.v = 0; el->el_refresh.r_cursor.v = 0;
if (el->el_line.cursor >= el->el_line.lastchar) { if (el->el_line.cursor >= el->el_line.lastchar) {
if (el->el_map.current == el->el_map.alt if (el->el_map.current == el->el_map.alt
&& el->el_line.lastchar != el->el_line.buffer) && el->el_line.lastchar != el->el_line.buffer)
skipping to change at line 215 skipping to change at line 277
el->el_line.cursor = el->el_line.lastchar; el->el_line.cursor = el->el_line.lastchar;
} }
cur.h = -1; /* set flag in case I'm not set */ cur.h = -1; /* set flag in case I'm not set */
cur.v = 0; cur.v = 0;
prompt_print(el, EL_PROMPT); prompt_print(el, EL_PROMPT);
/* draw the current input buffer */ /* draw the current input buffer */
#if notyet #if notyet
termsz = el->el_term.t_size.h * el->el_term.t_size.v; termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v;
if (el->el_line.lastchar - el->el_line.buffer > termsz) { if (el->el_line.lastchar - el->el_line.buffer > termsz) {
/* /*
* If line is longer than terminal, process only part * If line is longer than terminal, process only part
* of line which would influence display. * of line which would influence display.
*/ */
size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz; size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
st = el->el_line.lastchar - rem st = el->el_line.lastchar - rem
- (termsz - (((rem / el->el_term.t_size.v) - 1) - (termsz - (((rem / el->el_terminal.t_size.v) - 1)
* el->el_term.t_size.v)); * el->el_terminal.t_size.v));
} else } else
#endif #endif
st = el->el_line.buffer; st = el->el_line.buffer;
for (cp = st; cp < el->el_line.lastchar; cp++) { for (cp = st; cp < el->el_line.lastchar; cp++) {
if (cp == el->el_line.cursor) { if (cp == el->el_line.cursor) {
int w = wcwidth(*cp);
/* save for later */ /* save for later */
cur.h = el->el_refresh.r_cursor.h; cur.h = el->el_refresh.r_cursor.h;
cur.v = el->el_refresh.r_cursor.v; cur.v = el->el_refresh.r_cursor.v;
/* handle being at a linebroken doublewidth char */
if (w > 1 && el->el_refresh.r_cursor.h + w >
el->el_terminal.t_size.h) {
cur.h = 0;
cur.v++;
}
} }
re_addc(el, (unsigned char) *cp); re_addc(el, *cp);
} }
if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */
cur.h = el->el_refresh.r_cursor.h; cur.h = el->el_refresh.r_cursor.h;
cur.v = el->el_refresh.r_cursor.v; cur.v = el->el_refresh.r_cursor.v;
} }
rhdiff = el->el_term.t_size.h - el->el_refresh.r_cursor.h - rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h -
el->el_rprompt.p_pos.h; el->el_rprompt.p_pos.h;
if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v && if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
!el->el_refresh.r_cursor.v && rhdiff > 1) { !el->el_refresh.r_cursor.v && rhdiff > 1) {
/* /*
* have a right-hand side prompt that will fit * have a right-hand side prompt that will fit
* on the end of the first line with at least * on the end of the first line with at least
* one character gap to the input buffer. * one character gap to the input buffer.
*/ */
while (--rhdiff > 0) /* pad out with spaces */ while (--rhdiff > 0) /* pad out with spaces */
re_putc(el, ' ', 1); re_putc(el, ' ', 1);
skipping to change at line 266 skipping to change at line 335
el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */ el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */
el->el_rprompt.p_pos.v = 0; el->el_rprompt.p_pos.v = 0;
} }
re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */ re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */
el->el_refresh.r_newcv = el->el_refresh.r_cursor.v; el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
el->el_term.t_size.h, el->el_refresh.r_cursor.h, el->el_terminal.t_size.h, el->el_refresh.r_cursor.h,
el->el_refresh.r_cursor.v, el->el_vdisplay[0])); el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0],
&el->el_scratch)));
ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
for (i = 0; i <= el->el_refresh.r_newcv; i++) { for (i = 0; i <= el->el_refresh.r_newcv; i++) {
/* NOTE THAT re_update_line MAY CHANGE el_display[i] */ /* NOTE THAT re_update_line MAY CHANGE el_display[i] */
re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
/* /*
* Copy the new line to be the current one, and pad out with * Copy the new line to be the current one, and pad out with
* spaces to the full width of the terminal so that if we try * spaces to the full width of the terminal so that if we try
* moving the cursor by writing the character that is at the * moving the cursor by writing the character that is at the
* end of the screen line, it won't be a NUL or some old * end of the screen line, it won't be a NUL or some old
* leftover stuff. * leftover stuff.
*/ */
re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
(size_t) el->el_term.t_size.h); (size_t) el->el_terminal.t_size.h);
} }
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n", "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i)); el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv) if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
for (; i <= el->el_refresh.r_oldcv; i++) { for (; i <= el->el_refresh.r_oldcv; i++) {
term_move_to_line(el, i); terminal_move_to_line(el, i);
term_move_to_char(el, 0); terminal_move_to_char(el, 0);
term_clear_EOL(el, (int) strlen(el->el_display[i])); /* This wcslen should be safe even with MB_FILL_CHARs */
terminal_clear_EOL(el, (int) wcslen(el->el_display[i]));
#ifdef DEBUG_REFRESH #ifdef DEBUG_REFRESH
term_overwrite(el, "C\b", 2); terminal_overwrite(el, L"C\b", 2);
#endif /* DEBUG_REFRESH */ #endif /* DEBUG_REFRESH */
el->el_display[i][0] = '\0'; el->el_display[i][0] = '\0';
} }
el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */ el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n", "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v, el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
cur.h, cur.v)); cur.h, cur.v));
term_move_to_line(el, cur.v); /* go to where the cursor is */ terminal_move_to_line(el, cur.v); /* go to where the cursor is */
term_move_to_char(el, cur.h); terminal_move_to_char(el, cur.h);
} }
/* re_goto_bottom(): /* re_goto_bottom():
* used to go to last used screen line * used to go to last used screen line
*/ */
protected void libedit_private void
re_goto_bottom(EditLine *el) re_goto_bottom(EditLine *el)
{ {
term_move_to_line(el, el->el_refresh.r_oldcv); terminal_move_to_line(el, el->el_refresh.r_oldcv);
term__putc('\n'); terminal__putc(el, '\n');
re_clear_display(el); re_clear_display(el);
term__flush(); terminal__flush(el);
} }
/* re_insert(): /* re_insert():
* insert num characters of s into d (in front of the character) * insert num characters of s into d (in front of the character)
* at dat, maximum length of d is dlen * at dat, maximum length of d is dlen
*/ */
private void static void
/*ARGSUSED*/ /*ARGSUSED*/
re_insert(EditLine *el __attribute__((__unused__)), re_insert(EditLine *el __attribute__((__unused__)),
char *d, int dat, int dlen, char *s, int num) wchar_t *d, int dat, int dlen, wchar_t *s, int num)
{ {
char *a, *b; wchar_t *a, *b;
if (num <= 0) if (num <= 0)
return; return;
if (num > dlen - dat) if (num > dlen - dat)
num = dlen - dat; num = dlen - dat;
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d)); num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s,
&el->el_scratch)));
/* open up the space for num chars */ /* open up the space for num chars */
if (num > 0) { if (num > 0) {
b = d + dlen - 1; b = d + dlen - 1;
a = b - num; a = b - num;
while (a >= &d[dat]) while (a >= &d[dat])
*b-- = *a--; *b-- = *a--;
d[dlen] = '\0'; /* just in case */ d[dlen] = '\0'; /* just in case */
} }
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"re_insert() after insert: %d at %d max %d, d == \"%s\"\n", "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d)); num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s,
&el->el_scratch)));
/* copy the characters */ /* copy the characters */
for (a = d + dat; (a < d + dlen) && (num > 0); num--) for (a = d + dat; (a < d + dlen) && (num > 0); num--)
*a++ = *s++; *a++ = *s++;
#ifdef notyet
/* ct_encode_string() uses a static buffer, so we can't conveniently
* encode both d & s here */
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
num, dat, dlen, d, s)); num, dat, dlen, d, s));
ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s));
#endif
} }
/* re_delete(): /* re_delete():
* delete num characters d at dat, maximum length of d is dlen * delete num characters d at dat, maximum length of d is dlen
*/ */
private void static void
/*ARGSUSED*/ /*ARGSUSED*/
re_delete(EditLine *el __attribute__((__unused__)), re_delete(EditLine *el __attribute__((__unused__)),
char *d, int dat, int dlen, int num) wchar_t *d, int dat, int dlen, int num)
{ {
char *a, *b; wchar_t *a, *b;
if (num <= 0) if (num <= 0)
return; return;
if (dat + num >= dlen) { if (dat + num >= dlen) {
d[dat] = '\0'; d[dat] = '\0';
return; return;
} }
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d)); num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
/* open up the space for num chars */ /* open up the space for num chars */
if (num > 0) { if (num > 0) {
b = d + dat; b = d + dat;
a = b + num; a = b + num;
while (a < &d[dlen]) while (a < &d[dlen])
*b++ = *a++; *b++ = *a++;
d[dlen] = '\0'; /* just in case */ d[dlen] = '\0'; /* just in case */
} }
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d)); num, dat, dlen, ct_encode_string(d, &el->el_scratch)));
} }
/* re__strncopy(): /* re__strncopy():
* Like strncpy without padding. * Like strncpy without padding.
*/ */
private void static void
re__strncopy(char *a, char *b, size_t n) re__strncopy(wchar_t *a, wchar_t *b, size_t n)
{ {
while (n-- && *b) while (n-- && *b)
*a++ = *b++; *a++ = *b++;
} }
/* re_clear_eol():
* Find the number of characters we need to clear till the end of line
* in order to make sure that we have cleared the previous contents of
* the line. fx and sx is the number of characters inserted or deleted
* in the first or second diff, diff is the difference between the
* number of characters between the new and old line.
*/
static void
re_clear_eol(EditLine *el, int fx, int sx, int diff)
{
ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n",
sx, fx, diff));
if (fx < 0)
fx = -fx;
if (sx < 0)
sx = -sx;
if (fx > diff)
diff = fx;
if (sx > diff)
diff = sx;
ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff));
terminal_clear_EOL(el, diff);
}
/***************************************************************** /*****************************************************************
re_update_line() is based on finding the middle difference of each line re_update_line() is based on finding the middle difference of each line
on the screen; vis: on the screen; vis:
/old first difference /old first difference
/beginning of line | /old last same /old EOL /beginning of line | /old last same /old EOL
v v v v v v v v
old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
new: eddie> Oh, my little buggy says to me, as lurgid as new: eddie> Oh, my little buggy says to me, as lurgid as
^ ^ ^ ^ ^ ^ ^ ^
skipping to change at line 433 skipping to change at line 538
no differences, as well as for end of line additions must be handled. no differences, as well as for end of line additions must be handled.
**************************************************************** */ **************************************************************** */
/* Minimum at which doing an insert it "worth it". This should be about /* Minimum at which doing an insert it "worth it". This should be about
* half the "cost" of going into insert mode, inserting a character, and * half the "cost" of going into insert mode, inserting a character, and
* going back out. This should really be calculated from the termcap * going back out. This should really be calculated from the termcap
* data... For the moment, a good number for ANSI terminals. * data... For the moment, a good number for ANSI terminals.
*/ */
#define MIN_END_KEEP 4 #define MIN_END_KEEP 4
private void static void
re_update_line(EditLine *el, char *old, char *new, int i) re_update_line(EditLine *el, wchar_t *old, wchar_t *new, int i)
{ {
char *o, *n, *p, c; wchar_t *o, *n, *p, c;
char *ofd, *ols, *oe, *nfd, *nls, *ne; wchar_t *ofd, *ols, *oe, *nfd, *nls, *ne;
char *osb, *ose, *nsb, *nse; wchar_t *osb, *ose, *nsb, *nse;
int fx, sx; int fx, sx;
size_t len;
/* /*
* find first diff * find first diff
*/ */
for (o = old, n = new; *o && (*o == *n); o++, n++) for (o = old, n = new; *o && (*o == *n); o++, n++)
continue; continue;
ofd = o; ofd = o;
nfd = n; nfd = n;
/* /*
skipping to change at line 494 skipping to change at line 600
} }
/* /*
* find last same pointer * find last same pointer
*/ */
while ((o > ofd) && (n > nfd) && (*--o == *--n)) while ((o > ofd) && (n > nfd) && (*--o == *--n))
continue; continue;
ols = ++o; ols = ++o;
nls = ++n; nls = ++n;
/* /*
* find same begining and same end * find same beginning and same end
*/ */
osb = ols; osb = ols;
nsb = nls; nsb = nls;
ose = ols; ose = ols;
nse = nls; nse = nls;
/* /*
* case 1: insert: scan from nfd to nls looking for *ofd * case 1: insert: scan from nfd to nls looking for *ofd
*/ */
if (*ofd) { if (*ofd) {
skipping to change at line 566 skipping to change at line 672
} }
/* /*
* Pragmatics II: if the terminal isn't smart enough, make the data * Pragmatics II: if the terminal isn't smart enough, make the data
* dumber so the smart update doesn't try anything fancy * dumber so the smart update doesn't try anything fancy
*/ */
/* /*
* fx is the number of characters we need to insert/delete: in the * fx is the number of characters we need to insert/delete: in the
* beginning to bring the two same begins together * beginning to bring the two same begins together
*/ */
fx = (nsb - nfd) - (osb - ofd); fx = (int)((nsb - nfd) - (osb - ofd));
/* /*
* sx is the number of characters we need to insert/delete: in the * sx is the number of characters we need to insert/delete: in the
* end to bring the two same last parts together * end to bring the two same last parts together
*/ */
sx = (nls - nse) - (ols - ose); sx = (int)((nls - nse) - (ols - ose));
if (!EL_CAN_INSERT) { if (!EL_CAN_INSERT) {
if (fx > 0) { if (fx > 0) {
osb = ols; osb = ols;
ose = ols; ose = ols;
nsb = nls; nsb = nls;
nse = nls; nse = nls;
} }
if (sx > 0) { if (sx > 0) {
ols = oe; ols = oe;
skipping to change at line 620 skipping to change at line 726
/* was: if (osb == ose) */ /* was: if (osb == ose) */
if ((ose - osb) < MIN_END_KEEP) { if ((ose - osb) < MIN_END_KEEP) {
osb = ols; osb = ols;
ose = ols; ose = ols;
nsb = nls; nsb = nls;
nse = nls; nse = nls;
} }
/* /*
* Now that we are done with pragmatics we recompute fx, sx * Now that we are done with pragmatics we recompute fx, sx
*/ */
fx = (nsb - nfd) - (osb - ofd); fx = (int)((nsb - nfd) - (osb - ofd));
sx = (nls - nse) - (ols - ose); sx = (int)((nls - nse) - (ols - ose));
ELRE_DEBUG(1, (__F, "\n")); ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx));
ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", ELRE_DEBUG(1, (__F, "ofd %td, osb %td, ose %td, ols %td, oe %td\n",
ofd - old, osb - old, ose - old, ols - old, oe - old)); ofd - old, osb - old, ose - old, ols - old, oe - old));
ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", ELRE_DEBUG(1, (__F, "nfd %td, nsb %td, nse %td, nls %td, ne %td\n",
nfd - new, nsb - new, nse - new, nls - new, ne - new)); nfd - new, nsb - new, nse - new, nls - new, ne - new));
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n")); "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n")); "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
#ifdef DEBUG_REFRESH #ifdef DEBUG_REFRESH
re_printstr(el, "old- oe", old, oe); re_printstr(el, "old- oe", old, oe);
re_printstr(el, "new- ne", new, ne); re_printstr(el, "new- ne", new, ne);
re_printstr(el, "old-ofd", old, ofd); re_printstr(el, "old-ofd", old, ofd);
re_printstr(el, "new-nfd", new, nfd); re_printstr(el, "new-nfd", new, nfd);
skipping to change at line 652 skipping to change at line 758
re_printstr(el, "nse-nls", nse, nls); re_printstr(el, "nse-nls", nse, nls);
re_printstr(el, "ols- oe", ols, oe); re_printstr(el, "ols- oe", ols, oe);
re_printstr(el, "nls- ne", nls, ne); re_printstr(el, "nls- ne", nls, ne);
#endif /* DEBUG_REFRESH */ #endif /* DEBUG_REFRESH */
/* /*
* el_cursor.v to this line i MUST be in this routine so that if we * el_cursor.v to this line i MUST be in this routine so that if we
* don't have to change the line, we don't move to it. el_cursor.h to * don't have to change the line, we don't move to it. el_cursor.h to
* first diff char * first diff char
*/ */
term_move_to_line(el, i); terminal_move_to_line(el, i);
/* /*
* at this point we have something like this: * at this point we have something like this:
* *
* /old /ofd /osb /ose /ols /oe * /old /ofd /osb /ose /ols /oe
* v.....................v v..................v v........v * v.....................v v..................v v........v
* eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
* eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
* ^.....................^ ^..................^ ^........^ * ^.....................^ ^..................^ ^........^
* \new \nfd \nsb \nse \nls \ne * \new \nfd \nsb \nse \nls \ne
skipping to change at line 676 skipping to change at line 782
* characters to delete if < 0 (new is shorter than old, as above), * characters to delete if < 0 (new is shorter than old, as above),
* or insert (new is longer than short). * or insert (new is longer than short).
* *
* sx is the same for the second differences. * sx is the same for the second differences.
*/ */
/* /*
* if we have a net insert on the first difference, AND inserting the * if we have a net insert on the first difference, AND inserting the
* net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful
* character (which is ne if nls != ne, otherwise is nse) off the edge * character (which is ne if nls != ne, otherwise is nse) off the edge
* of the screen (el->el_term.t_size.h) else we do the deletes first * of the screen (el->el_terminal.t_size.h) else we do the deletes first
* so that we keep everything we need to. * so that we keep everything we need to.
*/ */
/* /*
* if the last same is the same like the end, there is no last same * if the last same is the same like the end, there is no last same
* part, otherwise we want to keep the last same part set p to the * part, otherwise we want to keep the last same part set p to the
* last useful old character * last useful old character
*/ */
p = (ols != oe) ? oe : ose; p = (ols != oe) ? oe : ose;
skipping to change at line 698 skipping to change at line 804
* if (There is a diffence in the beginning) && (we need to insert * if (There is a diffence in the beginning) && (we need to insert
* characters) && (the number of characters to insert is less than * characters) && (the number of characters to insert is less than
* the term width) * the term width)
* We need to do an insert! * We need to do an insert!
* else if (we need to delete characters) * else if (we need to delete characters)
* We need to delete characters! * We need to delete characters!
* else * else
* No insert or delete * No insert or delete
*/ */
if ((nsb != nfd) && fx > 0 && if ((nsb != nfd) && fx > 0 &&
((p - old) + fx <= el->el_term.t_size.h)) { ((p - old) + fx <= el->el_terminal.t_size.h)) {
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "first diff insert at %d...\r\n", nfd - new)); (__F, "first diff insert at %td...\r\n", nfd - new));
/* /*
* Move to the first char to insert, where the first diff is. * Move to the first char to insert, where the first diff is.
*/ */
term_move_to_char(el, nfd - new); terminal_move_to_char(el, (int)(nfd - new));
/* /*
* Check if we have stuff to keep at end * Check if we have stuff to keep at end
*/ */
if (nsb != ne) { if (nsb != ne) {
ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
/* /*
* insert fx chars of new starting at nfd * insert fx chars of new starting at nfd
*/ */
if (fx > 0) { if (fx > 0) {
ELRE_DEBUG(!EL_CAN_INSERT, (__F, ELRE_DEBUG(!EL_CAN_INSERT, (__F,
"ERROR: cannot insert in early first diff\n")); "ERROR: cannot insert in early first diff\n"));
term_insertwrite(el, nfd, fx); terminal_insertwrite(el, nfd, fx);
re_insert(el, old, ofd - old, re_insert(el, old, (int)(ofd - old),
el->el_term.t_size.h, nfd, fx); el->el_terminal.t_size.h, nfd, fx);
} }
/* /*
* write (nsb-nfd) - fx chars of new starting at * write (nsb-nfd) - fx chars of new starting at
* (nfd + fx) * (nfd + fx)
*/ */
term_overwrite(el, nfd + fx, (nsb - nfd) - fx); len = (size_t) ((nsb - nfd) - fx);
re__strncopy(ofd + fx, nfd + fx, terminal_overwrite(el, (nfd + fx), len);
(size_t) ((nsb - nfd) - fx)); re__strncopy(ofd + fx, nfd + fx, len);
} else { } else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n")); ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
term_overwrite(el, nfd, (nsb - nfd)); len = (size_t)(nsb - nfd);
re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); terminal_overwrite(el, nfd, len);
re__strncopy(ofd, nfd, len);
/* /*
* Done * Done
*/ */
return; return;
} }
} else if (fx < 0) { } else if (fx < 0) {
ELRE_DEBUG(1, ELRE_DEBUG(1,
(__F, "first diff delete at %d...\r\n", ofd - old)); (__F, "first diff delete at %td...\r\n", ofd - old));
/* /*
* move to the first char to delete where the first diff is * move to the first char to delete where the first diff is
*/ */
term_move_to_char(el, ofd - old); terminal_move_to_char(el, (int)(ofd - old));
/* /*
* Check if we have stuff to save * Check if we have stuff to save
*/ */
if (osb != oe) { if (osb != oe) {
ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
/* /*
* fx is less than zero *always* here but we check * fx is less than zero *always* here but we check
* for code symmetry * for code symmetry
*/ */
if (fx < 0) { if (fx < 0) {
ELRE_DEBUG(!EL_CAN_DELETE, (__F, ELRE_DEBUG(!EL_CAN_DELETE, (__F,
"ERROR: cannot delete in first diff\n")); "ERROR: cannot delete in first diff\n"));
term_deletechars(el, -fx); terminal_deletechars(el, -fx);
re_delete(el, old, ofd - old, re_delete(el, old, (int)(ofd - old),
el->el_term.t_size.h, -fx); el->el_terminal.t_size.h, -fx);
} }
/* /*
* write (nsb-nfd) chars of new starting at nfd * write (nsb-nfd) chars of new starting at nfd
*/ */
term_overwrite(el, nfd, (nsb - nfd)); len = (size_t) (nsb - nfd);
re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); terminal_overwrite(el, nfd, len);
re__strncopy(ofd, nfd, len);
} else { } else {
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"but with nothing left to save\r\n")); "but with nothing left to save\r\n"));
/* /*
* write (nsb-nfd) chars of new starting at nfd * write (nsb-nfd) chars of new starting at nfd
*/ */
term_overwrite(el, nfd, (nsb - nfd)); terminal_overwrite(el, nfd, (size_t)(nsb - nfd));
ELRE_DEBUG(1, (__F, re_clear_eol(el, fx, sx,
"cleareol %d\n", (oe - old) - (ne - new))); (int)((oe - old) - (ne - new)));
term_clear_EOL(el, (oe - old) - (ne - new));
/* /*
* Done * Done
*/ */
return; return;
} }
} else } else
fx = 0; fx = 0;
if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) { if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) {
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"second diff delete at %d...\r\n", (ose - old) + fx)); "second diff delete at %td...\r\n", (ose - old) + fx));
/* /*
* Check if we have stuff to delete * Check if we have stuff to delete
*/ */
/* /*
* fx is the number of characters inserted (+) or deleted (-) * fx is the number of characters inserted (+) or deleted (-)
*/ */
term_move_to_char(el, (ose - old) + fx); terminal_move_to_char(el, (int)((ose - old) + fx));
/* /*
* Check if we have stuff to save * Check if we have stuff to save
*/ */
if (ols != oe) { if (ols != oe) {
ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n")); ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
/* /*
* Again a duplicate test. * Again a duplicate test.
*/ */
if (sx < 0) { if (sx < 0) {
ELRE_DEBUG(!EL_CAN_DELETE, (__F, ELRE_DEBUG(!EL_CAN_DELETE, (__F,
"ERROR: cannot delete in second diff\n")); "ERROR: cannot delete in second diff\n"));
term_deletechars(el, -sx); terminal_deletechars(el, -sx);
} }
/* /*
* write (nls-nse) chars of new starting at nse * write (nls-nse) chars of new starting at nse
*/ */
term_overwrite(el, nse, (nls - nse)); terminal_overwrite(el, nse, (size_t)(nls - nse));
} else { } else {
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"but with nothing left to save\r\n")); "but with nothing left to save\r\n"));
term_overwrite(el, nse, (nls - nse)); terminal_overwrite(el, nse, (size_t)(nls - nse));
ELRE_DEBUG(1, (__F, re_clear_eol(el, fx, sx,
"cleareol %d\n", (oe - old) - (ne - new))); (int)((oe - old) - (ne - new)));
if ((oe - old) - (ne - new) != 0)
term_clear_EOL(el, (oe - old) - (ne - new));
} }
} }
/* /*
* if we have a first insert AND WE HAVEN'T ALREADY DONE IT... * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
*/ */
if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n", ELRE_DEBUG(1, (__F, "late first diff insert at %td...\r\n",
nfd - new)); nfd - new));
term_move_to_char(el, nfd - new); terminal_move_to_char(el, (int)(nfd - new));
/* /*
* Check if we have stuff to keep at the end * Check if we have stuff to keep at the end
*/ */
if (nsb != ne) { if (nsb != ne) {
ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
/* /*
* We have to recalculate fx here because we set it * We have to recalculate fx here because we set it
* to zero above as a flag saying that we hadn't done * to zero above as a flag saying that we hadn't done
* an early first insert. * an early first insert.
*/ */
fx = (nsb - nfd) - (osb - ofd); fx = (int)((nsb - nfd) - (osb - ofd));
if (fx > 0) { if (fx > 0) {
/* /*
* insert fx chars of new starting at nfd * insert fx chars of new starting at nfd
*/ */
ELRE_DEBUG(!EL_CAN_INSERT, (__F, ELRE_DEBUG(!EL_CAN_INSERT, (__F,
"ERROR: cannot insert in late first diff\n")); "ERROR: cannot insert in late first diff\n"));
term_insertwrite(el, nfd, fx); terminal_insertwrite(el, nfd, fx);
re_insert(el, old, ofd - old, re_insert(el, old, (int)(ofd - old),
el->el_term.t_size.h, nfd, fx); el->el_terminal.t_size.h, nfd, fx);
} }
/* /*
* write (nsb-nfd) - fx chars of new starting at * write (nsb-nfd) - fx chars of new starting at
* (nfd + fx) * (nfd + fx)
*/ */
term_overwrite(el, nfd + fx, (nsb - nfd) - fx); len = (size_t) ((nsb - nfd) - fx);
re__strncopy(ofd + fx, nfd + fx, terminal_overwrite(el, (nfd + fx), len);
(size_t) ((nsb - nfd) - fx)); re__strncopy(ofd + fx, nfd + fx, len);
} else { } else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n")); ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
term_overwrite(el, nfd, (nsb - nfd)); len = (size_t) (nsb - nfd);
re__strncopy(ofd, nfd, (size_t) (nsb - nfd)); terminal_overwrite(el, nfd, len);
re__strncopy(ofd, nfd, len);
} }
} }
/* /*
* line is now NEW up to nse * line is now NEW up to nse
*/ */
if (sx >= 0) { if (sx >= 0) {
ELRE_DEBUG(1, (__F, ELRE_DEBUG(1, (__F,
"second diff insert at %d...\r\n", nse - new)); "second diff insert at %d...\r\n", (int)(nse - new)));
term_move_to_char(el, nse - new); terminal_move_to_char(el, (int)(nse - new));
if (ols != oe) { if (ols != oe) {
ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
if (sx > 0) { if (sx > 0) {
/* insert sx chars of new starting at nse */ /* insert sx chars of new starting at nse */
ELRE_DEBUG(!EL_CAN_INSERT, (__F, ELRE_DEBUG(!EL_CAN_INSERT, (__F,
"ERROR: cannot insert in second diff\n")); "ERROR: cannot insert in second diff\n"));
term_insertwrite(el, nse, sx); terminal_insertwrite(el, nse, sx);
} }
/* /*
* write (nls-nse) - sx chars of new starting at * write (nls-nse) - sx chars of new starting at
* (nse + sx) * (nse + sx)
*/ */
term_overwrite(el, nse + sx, (nls - nse) - sx); terminal_overwrite(el, (nse + sx),
(size_t)((nls - nse) - sx));
} else { } else {
ELRE_DEBUG(1, (__F, "without anything to save\r\n")); ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
term_overwrite(el, nse, (nls - nse)); terminal_overwrite(el, nse, (size_t)(nls - nse));
/* /*
* No need to do a clear-to-end here because we were * No need to do a clear-to-end here because we were
* doing a second insert, so we will have over * doing a second insert, so we will have over
* written all of the old string. * written all of the old string.
*/ */
} }
} }
ELRE_DEBUG(1, (__F, "done.\r\n")); ELRE_DEBUG(1, (__F, "done.\r\n"));
} }
/* re__copy_and_pad(): /* re__copy_and_pad():
* Copy string and pad with spaces * Copy string and pad with spaces
*/ */
private void static void
re__copy_and_pad(char *dst, const char *src, size_t width) re__copy_and_pad(wchar_t *dst, const wchar_t *src, size_t width)
{ {
size_t i; size_t i;
for (i = 0; i < width; i++) { for (i = 0; i < width; i++) {
if (*src == '\0') if (*src == '\0')
break; break;
*dst++ = *src++; *dst++ = *src++;
} }
for (; i < width; i++) for (; i < width; i++)
*dst++ = ' '; *dst++ = ' ';
*dst = '\0'; *dst = '\0';
} }
/* re_refresh_cursor(): /* re_refresh_cursor():
* Move to the new cursor position * Move to the new cursor position
*/ */
protected void libedit_private void
re_refresh_cursor(EditLine *el) re_refresh_cursor(EditLine *el)
{ {
char *cp, c; wchar_t *cp;
int h, v, th; int h, v, th, w;
if (el->el_line.cursor >= el->el_line.lastchar) { if (el->el_line.cursor >= el->el_line.lastchar) {
if (el->el_map.current == el->el_map.alt if (el->el_map.current == el->el_map.alt
&& el->el_line.lastchar != el->el_line.buffer) && el->el_line.lastchar != el->el_line.buffer)
el->el_line.cursor = el->el_line.lastchar - 1; el->el_line.cursor = el->el_line.lastchar - 1;
else else
el->el_line.cursor = el->el_line.lastchar; el->el_line.cursor = el->el_line.lastchar;
} }
/* first we must find where the cursor is... */ /* first we must find where the cursor is... */
h = el->el_prompt.p_pos.h; h = el->el_prompt.p_pos.h;
v = el->el_prompt.p_pos.v; v = el->el_prompt.p_pos.v;
th = el->el_term.t_size.h; /* optimize for speed */ th = el->el_terminal.t_size.h; /* optimize for speed */
/* do input buffer to el->el_line.cursor */ /* do input buffer to el->el_line.cursor */
for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
c = *cp; switch (ct_chr_class(*cp)) {
h++; /* all chars at least this long */ case CHTYPE_NL: /* handle newline in data part too */
if (c == '\n') {/* handle newline in data part too */
h = 0; h = 0;
v++; v++;
} else { break;
if (c == '\t') { /* if a tab, to next tab stop */ case CHTYPE_TAB: /* if a tab, to next tab stop */
while (h & 07) { while (++h & 07)
h++; continue;
} break;
} else if (iscntrl((unsigned char) c)) { default:
/* if control char */ w = wcwidth(*cp);
h++; if (w > 1 && h + w > th) { /* won't fit on line */
if (h > th) { /* if overflow, compensate */ h = 0;
h = 1; v++;
v++;
}
} else if (!isprint((unsigned char) c)) {
h += 3;
if (h > th) { /* if overflow, compensate */
h = h - th;
v++;
}
} }
} h += ct_visual_width(*cp);
break;
}
if (h >= th) { /* check, extra long tabs picked up here also */ if (h >= th) { /* check, extra long tabs picked up here also */
h = 0; h -= th;
v++; v++;
} }
} }
/* if we have a next character, and it's a doublewidth one, we need to
* check whether we need to linebreak for it to fit */
if (cp < el->el_line.lastchar && (w = wcwidth(*cp)) > 1)
if (h + w > th) {
h = 0;
v++;
}
/* now go there */ /* now go there */
term_move_to_line(el, v); terminal_move_to_line(el, v);
term_move_to_char(el, h); terminal_move_to_char(el, h);
term__flush(); terminal__flush(el);
} }
/* re_fastputc(): /* re_fastputc():
* Add a character fast. * Add a character fast.
*/ */
private void static void
re_fastputc(EditLine *el, int c) re_fastputc(EditLine *el, wint_t c)
{ {
wchar_t *lastline;
int w;
w = wcwidth(c);
while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h)
re_fastputc(el, ' ');
term__putc(c); terminal__putc(el, c);
el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
if (el->el_cursor.h >= el->el_term.t_size.h) { while (--w > 0)
el->el_display[el->el_cursor.v][el->el_cursor.h++]
= MB_FILL_CHAR;
if (el->el_cursor.h >= el->el_terminal.t_size.h) {
/* if we must overflow */ /* if we must overflow */
el->el_cursor.h = 0; el->el_cursor.h = 0;
/* /*
* If we would overflow (input is longer than terminal size), * If we would overflow (input is longer than terminal size),
* emulate scroll by dropping first line and shuffling the rest. * emulate scroll by dropping first line and shuffling the rest.
* We do this via pointer shuffling - it's safe in this case * We do this via pointer shuffling - it's safe in this case
* and we avoid memcpy(). * and we avoid memcpy().
*/ */
if (el->el_cursor.v + 1 >= el->el_term.t_size.v) { if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {
int i, lins = el->el_term.t_size.v; int i, lins = el->el_terminal.t_size.v;
char *firstline = el->el_display[0];
for(i=1; i < lins; i++) lastline = el->el_display[0];
el->el_display[i-1] = el->el_display[i]; for(i = 1; i < lins; i++)
el->el_display[i - 1] = el->el_display[i];
re__copy_and_pad(firstline, "", 0); el->el_display[i - 1] = lastline;
el->el_display[i-1] = firstline;
} else { } else {
el->el_cursor.v++; el->el_cursor.v++;
el->el_refresh.r_oldcv++; lastline = el->el_display[++el->el_refresh.r_oldcv];
} }
re__copy_and_pad(lastline, L"", (size_t)el->el_terminal.t_size.h)
;
if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_AUTO_MARGINS) {
if (EL_HAS_MAGIC_MARGINS) { if (EL_HAS_MAGIC_MARGINS) {
term__putc(' '); terminal__putc(el, ' ');
term__putc('\b'); terminal__putc(el, '\b');
} }
} else { } else {
term__putc('\r'); terminal__putc(el, '\r');
term__putc('\n'); terminal__putc(el, '\n');
} }
} }
} }
/* re_fastaddc(): /* re_fastaddc():
* we added just one char, handle it fast. * we added just one char, handle it fast.
* Assumes that screen cursor == real cursor * Assumes that screen cursor == real cursor
*/ */
protected void libedit_private void
re_fastaddc(EditLine *el) re_fastaddc(EditLine *el)
{ {
char c; wchar_t c;
int rhdiff; int rhdiff;
c = el->el_line.cursor[-1]; c = el->el_line.cursor[-1];
if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
re_refresh(el); /* too hard to handle */ re_refresh(el); /* too hard to handle */
return; return;
} }
rhdiff = el->el_term.t_size.h - el->el_cursor.h - rhdiff = el->el_terminal.t_size.h - el->el_cursor.h -
el->el_rprompt.p_pos.h; el->el_rprompt.p_pos.h;
if (el->el_rprompt.p_pos.h && rhdiff < 3) { if (el->el_rprompt.p_pos.h && rhdiff < 3) {
re_refresh(el); /* clear out rprompt if less than 1 char gap */ re_refresh(el); /* clear out rprompt if less than 1 char gap */
return; return;
} /* else (only do at end of line, no TAB) */ } /* else (only do at end of line, no TAB) */
if (iscntrl((unsigned char) c)) { /* if control char, do caret */ switch (ct_chr_class(c)) {
char mc = (c == '\177') ? '?' : (c | 0100); case CHTYPE_TAB: /* already handled, should never happen here */
re_fastputc(el, '^'); break;
re_fastputc(el, mc); case CHTYPE_NL:
} else if (isprint((unsigned char) c)) { /* normal char */ case CHTYPE_PRINT:
re_fastputc(el, c); re_fastputc(el, c);
} else { break;
re_fastputc(el, '\\'); case CHTYPE_ASCIICTL:
re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0')); case CHTYPE_NONPRINT: {
re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0')); wchar_t visbuf[VISUAL_WIDTH_MAX];
re_fastputc(el, (c & 7) + '0'); ssize_t i, n =
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
for (i = 0; n-- > 0; ++i)
re_fastputc(el, visbuf[i]);
break;
}
} }
term__flush(); terminal__flush(el);
} }
/* re_clear_display(): /* re_clear_display():
* clear the screen buffers so that new new prompt starts fresh. * clear the screen buffers so that new new prompt starts fresh.
*/ */
protected void libedit_private void
re_clear_display(EditLine *el) re_clear_display(EditLine *el)
{ {
int i; int i;
el->el_cursor.v = 0; el->el_cursor.v = 0;
el->el_cursor.h = 0; el->el_cursor.h = 0;
for (i = 0; i < el->el_term.t_size.v; i++) for (i = 0; i < el->el_terminal.t_size.v; i++)
el->el_display[i][0] = '\0'; el->el_display[i][0] = '\0';
el->el_refresh.r_oldcv = 0; el->el_refresh.r_oldcv = 0;
} }
/* re_clear_lines(): /* re_clear_lines():
* Make sure all lines are *really* blank * Make sure all lines are *really* blank
*/ */
protected void libedit_private void
re_clear_lines(EditLine *el) re_clear_lines(EditLine *el)
{ {
if (EL_CAN_CEOL) { if (EL_CAN_CEOL) {
int i; int i;
term_move_to_char(el, 0); for (i = el->el_refresh.r_oldcv; i >= 0; i--) {
for (i = 0; i <= el->el_refresh.r_oldcv; i++) {
/* for each line on the screen */ /* for each line on the screen */
term_move_to_line(el, i); terminal_move_to_line(el, i);
term_clear_EOL(el, el->el_term.t_size.h); terminal_move_to_char(el, 0);
terminal_clear_EOL(el, el->el_terminal.t_size.h);
} }
term_move_to_line(el, 0);
} else { } else {
term_move_to_line(el, el->el_refresh.r_oldcv); terminal_move_to_line(el, el->el_refresh.r_oldcv);
/* go to last line */ /* go to last line */
term__putc('\r'); /* go to BOL */ terminal__putc(el, '\r'); /* go to BOL */
term__putc('\n'); /* go to new line */ terminal__putc(el, '\n'); /* go to new line */
} }
} }
 End of changes. 126 change blocks. 
254 lines changed or deleted 374 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)