Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/external/bsd/nvi/dist/vi - Fix cursor position when a multiw...
details: https://anonhg.NetBSD.org/src/rev/a7f26d1fe958
branches: trunk
changeset: 357430:a7f26d1fe958
user: rin <rin%NetBSD.org@localhost>
date: Fri Nov 10 14:44:13 2017 +0000
description:
- Fix cursor position when a multiwidth char does not fit within a line.
- Put cursor on the leftmost column of a multiwidth char, instead of
the rightmost one. Otherwise, some terminal emulators do not focus on
the entire of the char.
Logic taken from nvi-m17n by itojun.
diffstat:
external/bsd/nvi/dist/vi/vs_line.c | 108 ++++++++++++++++++++-------
external/bsd/nvi/dist/vi/vs_refresh.c | 126 ++++++++++++++++++++++-----------
external/bsd/nvi/dist/vi/vs_relative.c | 121 ++++++++++++++++++++++++++++--
3 files changed, 274 insertions(+), 81 deletions(-)
diffs (truncated from 540 to 300 lines):
diff -r 708b99613c4a -r a7f26d1fe958 external/bsd/nvi/dist/vi/vs_line.c
--- a/external/bsd/nvi/dist/vi/vs_line.c Fri Nov 10 14:35:25 2017 +0000
+++ b/external/bsd/nvi/dist/vi/vs_line.c Fri Nov 10 14:44:13 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vs_line.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
+/* $NetBSD: vs_line.c,v 1.4 2017/11/10 14:44:13 rin Exp $ */
/*-
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -16,7 +16,7 @@
static const char sccsid[] = "Id: vs_line.c,v 10.38 2002/01/19 21:59:07 skimo Exp (Berkeley) Date: 2002/01/19 21:59:07 ";
#endif /* not lint */
#else
-__RCSID("$NetBSD: vs_line.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
+__RCSID("$NetBSD: vs_line.c,v 1.4 2017/11/10 14:44:13 rin Exp $");
#endif
#include <sys/types.h>
@@ -271,38 +271,64 @@
/* Do it the hard way, for leftright scrolling screens. */
if (O_ISSET(sp, O_LEFTRIGHT)) {
- for (; offset_in_line < len; ++offset_in_line) {
- chlen = (ch = (UCHAR_T)*p++) == L('\t') && !list_tab ?
+ while (offset_in_line < len) {
+ ch = (UCHAR_T)*p;
+ chlen = (ch == '\t' && !list_tab) ?
TAB_OFF(scno) : KEY_COL(sp, ch);
- if ((scno += chlen) >= skip_cols)
- break;
+
+ /* easy cases first. */
+ if (scno + chlen < skip_cols) {
+ scno += chlen;
+ p++;
+ offset_in_line++;
+ continue;
+ }
+
+ if (scno + chlen == skip_cols) {
+ scno += chlen;
+ p++;
+ offset_in_line++;
+ }
+
+ break;
}
/* Set cols_per_screen to 2nd and later line length. */
cols_per_screen = sp->cols;
/* Put starting info for this line in the cache. */
- if (offset_in_line >= len) {
- smp->c_sboff = offset_in_line;
- smp->c_scoff = 255;
- } else if (scno != skip_cols) {
- smp->c_sboff = offset_in_line;
- smp->c_scoff =
- offset_in_char = chlen - (scno - skip_cols);
- --p;
- } else {
- smp->c_sboff = ++offset_in_line;
- smp->c_scoff = 0;
- }
+ smp->c_sboff = offset_in_line;
+ smp->c_scoff = offset_in_char = scno + chlen - skip_cols;
}
/* Do it the hard way, for historic line-folding screens. */
else {
- for (; offset_in_line < len; ++offset_in_line) {
- chlen = (ch = (UCHAR_T)*p++) == L('\t') && !list_tab ?
+ while (offset_in_line < len) {
+ ch = (UCHAR_T)*p;
+ chlen = (ch == '\t' && !list_tab) ?
TAB_OFF(scno) : KEY_COL(sp, ch);
- if ((scno += chlen) < cols_per_screen)
+
+ /* Easy case first. */
+ if (scno + chlen < cols_per_screen) {
+ scno += chlen;
+ p++;
+ offset_in_line++;
continue;
+ }
+
+ /*
+ * Since we can't generally cross the rightmost column
+ * by displaying multi-width char, we must check it.
+ * In that case, we fake the scno so that you'll see
+ * that the line was already filled up completely.
+ */
+ if (!INTISWIDE(ch) || scno + chlen == cols_per_screen) {
+ scno += chlen;
+ p++;
+ offset_in_line++;
+ } else
+ scno = cols_per_screen;
+
scno -= cols_per_screen;
/* Set cols_per_screen to 2nd and later line length. */
@@ -320,9 +346,10 @@
if (scno != 0) {
smp->c_sboff = offset_in_line;
smp->c_scoff = offset_in_char = chlen - scno;
- --p;
+ offset_in_line--;
+ p--;
} else {
- smp->c_sboff = ++offset_in_line;
+ smp->c_sboff = offset_in_line;
smp->c_scoff = 0;
}
}
@@ -334,10 +361,16 @@
* called repeatedly with a valid pointer to a cursor position.
* Don't fill anything in unless it's the right line and the right
* character, and the right part of the character...
+ *
+ * It is not true that every wide chars occupy at least single column.
+ * - It is safe to compare sp->cno and offset_in_line since they are
+ * both offset in unit of CHAR_T.
+ * - We can't simply compare offset_in_line + cols_per_screen against
+ * sp->cno, since cols_per_screen is screen column, not offset in
+ * CHAR_T. Do it slowly.
*/
if (yp == NULL ||
- smp->lno != sp->lno || sp->cno < offset_in_line ||
- offset_in_line + cols_per_screen < sp->cno) {
+ smp->lno != sp->lno || sp->cno < offset_in_line) {
cno_cnt = 0;
/* If the line is on the screen, quit. */
if (is_cached || no_draw)
@@ -358,6 +391,23 @@
}
/*
+ * Since we can't generally cross the rightmost column
+ * by displaying multi-width char, we must check it.
+ * In that case, we fake the scno so that you'll see
+ * that the line was already filled up completely.
+ */
+ if (INTISWIDE(ch) && scno > cols_per_screen) {
+ smp->c_ecsize = chlen;
+ smp->c_eclen = 0;
+
+ is_partial = 1;
+
+ smp->c_eboff = offset_in_line;
+
+ /* Terminate the loop. */
+ offset_in_line = len;
+ } else
+ /*
* Only display up to the right-hand column. Set a flag if
* the entire character wasn't displayed for use in setting
* the cursor. If reached the end of the line, set the cache
@@ -400,6 +450,8 @@
*xp = scno - smp->c_ecsize;
else
*xp = scno - chlen;
+ else if (INTISWIDE(ch))
+ *xp = scno - chlen;
else
*xp = scno - 1;
if (O_ISSET(sp, O_NUMBER) &&
@@ -437,8 +489,8 @@
if (cbp + chlen >= ecbp)
FLUSH;
- /* don't display half a wide character */
- if (is_partial && CHAR_WIDTH(sp, ch) > 1) {
+ /* Don't display half a multi-width character */
+ if (is_partial && INTISWIDE(ch)) {
*cbp++ = ' ';
break;
}
@@ -458,7 +510,7 @@
if (scno < cols_per_screen) {
/* If didn't paint the whole line, update the cache. */
- smp->c_ecsize = smp->c_eclen = KEY_LEN(sp, ch);
+ smp->c_ecsize = smp->c_eclen = KEY_COL(sp, ch);
smp->c_eboff = len - 1;
/*
diff -r 708b99613c4a -r a7f26d1fe958 external/bsd/nvi/dist/vi/vs_refresh.c
--- a/external/bsd/nvi/dist/vi/vs_refresh.c Fri Nov 10 14:35:25 2017 +0000
+++ b/external/bsd/nvi/dist/vi/vs_refresh.c Fri Nov 10 14:44:13 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vs_refresh.c,v 1.6 2014/01/26 21:43:45 christos Exp $ */
+/* $NetBSD: vs_refresh.c,v 1.7 2017/11/10 14:44:13 rin Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -16,7 +16,7 @@
static const char sccsid[] = "Id: vs_refresh.c,v 10.50 2001/06/25 15:19:37 skimo Exp (Berkeley) Date: 2001/06/25 15:19:37 ";
#endif /* not lint */
#else
-__RCSID("$NetBSD: vs_refresh.c,v 1.6 2014/01/26 21:43:45 christos Exp $");
+__RCSID("$NetBSD: vs_refresh.c,v 1.7 2017/11/10 14:44:13 rin Exp $");
#endif
#include <sys/types.h>
@@ -148,7 +148,7 @@
SMAP *smp, tmp;
VI_PRIVATE *vip;
db_recno_t lastline, lcnt;
- size_t cwtotal, cnt, len, notused, off, y;
+ size_t cwtotal, cnt, len, notused, off, y, chlen;
int ch = 0, didpaint, isempty, leftright_warp;
CHAR_T *p;
@@ -467,15 +467,31 @@
/*
* 7a: Cursor moved left.
*
- * Point to the old character. The old cursor position can
- * be past EOL if, for example, we just deleted the rest of
- * the line. In this case, since we don't know the width of
- * the characters we traversed, we have to do it slowly.
+ * The old cursor position can be past EOL if, for example,
+ * we just deleted the rest of the line. In this case, since
+ * we don't know the width of the characters we traversed, we
+ * have to do it slowly.
+ */
+ if (OCNO >= len)
+ goto slow;
+
+ /*
+ * cwtotal acts as new value for SCNO. Set cwtotal to the
+ * first char for content on CNO byte, for ease handling of
+ * wide characters.
+ *
+ * If the character we're stepping on lies across a screen
+ * boundary, we have no hope to speed it up. Do it slowly.
*/
p += OCNO;
- cnt = (OCNO - CNO) + 1;
- if (OCNO >= len)
- goto slow;
+ if (INTISWIDE(ch = (UCHAR_T)*p))
+ cwtotal = SCNO;
+ else {
+ if (ch == '\t' || (chlen = KEY_LEN(sp, ch)) > SCNO + 1)
+ goto slow;
+ cwtotal = SCNO + 1 - chlen;
+ }
+ cnt = OCNO - CNO;
/*
* Quick sanity check -- it's hard to figure out exactly when
@@ -488,63 +504,87 @@
/*
* Count up the widths of the characters. If it's a tab
- * character, go do it the the slow way.
+ * character, go do it the slow way.
*/
- for (cwtotal = 0; cnt--; cwtotal += KEY_COL(sp, ch))
- if ((ch = *(UCHAR_T *)p--) == '\t')
+ while (cnt--) {
+ if ((ch = (UCHAR_T)*--p) == '\t'
+ || (chlen = KEY_COL(sp, ch)) > cwtotal)
goto slow;
-
- /*
- * Decrement the screen cursor by the total width of the
- * characters minus 1.
- */
- cwtotal -= 1;
+ cwtotal -= chlen;
+ }
/*
- * If we're moving left, and there's a wide character in the
+ * If we're moving left, and there's a multi-width char in the
* current position, go to the end of the character.
*/
- if (KEY_COL(sp, ch) > 1)
- cwtotal -= KEY_COL(sp, ch) - 1;
+ if (!INTISWIDE(ch) && (chlen = KEY_LEN(sp, ch)) > 1)
+ cwtotal += chlen - 1;
/*
- * If the new column moved us off of the current logical line,
- * calculate a new one. If doing leftright scrolling, we've
- * moved off of the current screen, as well.
+ * At last, update the screen cursor.
*/
- if (SCNO < cwtotal)
- goto slow;
- SCNO -= cwtotal;
+ SCNO = cwtotal;
} else {
/*
* 7b: Cursor moved right.
- *
- * Point to the first character to the right.
Home |
Main Index |
Thread Index |
Old Index