about summary refs log tree commit diff stats
path: root/src/GridText.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/GridText.c')
-rw-r--r--src/GridText.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/GridText.c b/src/GridText.c
index e7221bfa..c1d21bd0 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -1,5 +1,5 @@
 /*
- * $LynxId: GridText.c,v 1.313 2018/05/15 20:43:41 tom Exp $
+ * $LynxId: GridText.c,v 1.318 2018/12/28 22:36:22 tom Exp $
  *
  *		Character grid hypertext object
  *		===============================
@@ -50,7 +50,17 @@
 #include <AttrList.h>
 #include <LYHash.h>
 #include <LYStyle.h>
+#endif
 
+#ifdef EXP_WCWIDTH_SUPPORT
+#  ifdef HAVE_WCWIDTH
+#    ifdef HAVE_WCHAR_H
+#      include <wchar.h>
+#    endif
+#  else
+#    include <wcwidth.h>
+#    define wcwidth(n) mk_wcwidth(n)
+#  endif
 #endif
 
 #include <LYJustify.h>
@@ -74,6 +84,9 @@
 
 static void HText_trimHightext(HText *text, int final, int stop_before);
 
+#define IS_UTF_FIRST(ch) (text->T.output_utf8 && \
+			  (UCH((ch))&0xc0) == 0xc0)
+
 #define IS_UTF_EXTRA(ch) (text->T.output_utf8 && \
 			  (UCH((ch))&0xc0) == 0x80)
 
@@ -589,8 +602,16 @@ static int ctrl_chars_on_this_line = 0;		/* num of ctrl chars in current line */
 static int utfxtra_on_this_line = 0;	/* num of UTF-8 extra bytes in line,
 
 					   they *also* count as ctrl chars. */
+#ifdef EXP_WCWIDTH_SUPPORT
+static int utfxtracells_on_this_line = 0;	/* num of UTF-8 extra cells in line */
+static int utfextracells(const char *s);
+#endif
 #ifdef WIDEC_CURSES
+# ifdef EXP_WCWIDTH_SUPPORT	/* TODO: support for !WIDEC_CURSES */
+#define UTFXTRA_ON_THIS_LINE utfxtracells_on_this_line
+# else
 #define UTFXTRA_ON_THIS_LINE 0
+# endif
 #else
 #define UTFXTRA_ON_THIS_LINE utfxtra_on_this_line
 #endif
@@ -2690,6 +2711,10 @@ static HTLine *insert_blanks_in_line(HTLine *line, int line_number,
 		    break;
 		ioldc++;
 		pre = s + 1;
+#ifdef EXP_WCWIDTH_SUPPORT
+		if (text && text->T.output_utf8 && IS_UTF_FIRST(*s))
+		    ioldc += utfextracells(s);
+#endif
 	    }
 	    s++;
 	}
@@ -2832,6 +2857,9 @@ static void split_line(HText *text, unsigned split)
 
     ctrl_chars_on_this_line = 0;	/*reset since we are going to a new line */
     utfxtra_on_this_line = 0;	/*reset too, we'll count them */
+#ifdef EXP_WCWIDTH_SUPPORT
+    utfxtracells_on_this_line = 0;
+#endif
     text->LastChar = ' ';
 
 #ifdef DEBUG_APPCH
@@ -2959,6 +2987,10 @@ static void split_line(HText *text, unsigned split)
 		    ctrl_chars_on_this_line++;
 		} else if (IS_UTF_EXTRA(p[i])) {
 		    utfxtra_on_this_line++;
+#ifdef EXP_WCWIDTH_SUPPORT
+		} else if (IS_UTF_FIRST(p[i])) {
+		    utfxtracells_on_this_line += utfextracells(&p[i]);
+#endif
 		}
 		if (p[i] == LY_SOFT_HYPHEN &&
 		    (int) text->permissible_split < i)
@@ -4112,6 +4144,21 @@ void HText_appendCharacter(HText *text, int ch)
 	    line->data[line->size] = '\0';
 	    utfxtra_on_this_line++;
 	    ctrl_chars_on_this_line++;
+#ifdef EXP_WCWIDTH_SUPPORT
+	    /* update utfxtracells_on_this_line on last byte of UTF-8 sequence */
+	    {
+		/* find start position of UTF-8 sequence */
+		int utff = line->size - 2;
+		int utf_xlen;
+
+		while (utff > 0 && IS_UTF_EXTRA(line->data[utff]))
+		    utff--;
+		utf_xlen = UTF_XLEN(line->data[utff]);
+
+		if (line->size - utff == utf_xlen + 1)	/* have last byte */
+		    utfxtracells_on_this_line += utfextracells(&(line->data[utff]));
+	    }
+#endif
 	    return;
 	} else if (ch & 0x80) {	/* a first char of UTF-8 sequence - kw */
 	    if ((line->size > (MAX_LINE - 7))) {
@@ -4331,6 +4378,9 @@ void HText_appendCharacter(HText *text, int ch)
 	    (actual
 	     + (int) style->rightIndent
 	     + ((IS_CJK_TTY && text->kanji_buf) ? 1 : 0)
+#ifdef EXP_WCWIDTH_SUPPORT
+	     + utfxtracells_on_this_line
+#endif
 	    ) >= WRAP_COLS(text))
 	|| (text->T.output_utf8
 	    && ((actual
@@ -9176,6 +9226,12 @@ static int HText_TrueLineSize(HTLine *line, HText *text, int IgnoreSpaces)
 		UCH(line->data[i]) != HT_NON_BREAK_SPACE &&
 		UCH(line->data[i]) != HT_EN_SPACE) {
 		true_size++;
+#ifdef EXP_WCWIDTH_SUPPORT
+		if (text && text->T.output_utf8 &&
+		    IS_UTF_FIRST(line->data[i])) {
+		    true_size += utfextracells(&(line->data[i]));
+		}
+#endif
 	    }
 	}
     } else {
@@ -9183,6 +9239,12 @@ static int HText_TrueLineSize(HTLine *line, HText *text, int IgnoreSpaces)
 	    if (!IsSpecialAttrChar(line->data[i]) &&
 		IS_UTF8_EXTRA(line->data[i])) {
 		true_size++;
+#ifdef EXP_WCWIDTH_SUPPORT
+		if (text && text->T.output_utf8 &&
+		    IS_UTF_FIRST(line->data[i])) {
+		    true_size += utfextracells(&(line->data[i]));
+		}
+#endif
 	    }
 	}
     }
@@ -14869,3 +14931,19 @@ GLOBALDEF HTProtocol LYLynxCache =
 {"LYNXCACHE", LYHandleCache, 0};
 #endif /* GLOBALDEF_IS_MACRO */
 #endif /* USE_CACHEJAR */
+
+#ifdef EXP_WCWIDTH_SUPPORT
+static int utfextracells(const char *s)
+{
+    UCode_t ucs = UCGetUniFromUtf8String(&s);
+    int result = 0;
+
+    if (ucs > 0) {
+	int cells = wcwidth((wchar_t) ucs);
+
+	if (cells > 1)
+	    result = (cells - 1);
+    }
+    return result;
+}
+#endif