/****************************************************************************
- * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
#include <curses.priv.h>
#define CUR my_term.type.
-MODULE_ID("$Id: win_driver.c,v 1.14 2012/09/22 19:15:14 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.16 2013/01/05 23:16:54 tom Exp $")
#define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
+#define EXP_OPTIMIZE 0
+
#define AssertTCB() assert(TCB!=0 && TCB->magic==WINMAGIC)
#define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp
* TODO: _nc_wacs should be part of sp.
*/
static BOOL
-con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int n)
+con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
{
- CHAR_INFO ci[n];
+ int actual = 0;
+ CHAR_INFO ci[limit];
COORD loc, siz;
SMALL_RECT rec;
int i;
SetSP();
- for (i = 0; i < n; i++) {
+ for (i = actual = 0; i < limit; i++) {
ch = str[i];
- ci[i].Char.UnicodeChar = CharOf(ch);
- ci[i].Attributes = MapAttr(TCB,
- PropOf(TCB)->SBI.wAttributes,
- AttrOf(ch));
+ if (isWidecExt(ch))
+ continue;
+ ci[actual].Char.UnicodeChar = CharOf(ch);
+ ci[actual].Attributes = MapAttr(TCB,
+ PropOf(TCB)->SBI.wAttributes,
+ AttrOf(ch));
if (AttrOf(ch) & A_ALTCHARSET) {
if (_nc_wacs) {
int which = CharOf(ch);
if (which > 0
&& which < ACS_LEN
&& CharOf(_nc_wacs[which]) != 0) {
- ci[i].Char.UnicodeChar = CharOf(_nc_wacs[which]);
+ ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]);
} else {
- ci[i].Char.UnicodeChar = ' ';
+ ci[actual].Char.UnicodeChar = ' ';
}
}
}
+ ++actual;
}
loc.X = (short) 0;
loc.Y = (short) 0;
- siz.X = (short) n;
+ siz.X = (short) actual;
siz.Y = 1;
rec.Left = (short) x;
rec.Top = (short) y;
- rec.Right = (short) (x + n - 1);
+ rec.Right = (short) (x + limit - 1);
rec.Bottom = rec.Top;
return WriteConsoleOutputW(TCB->hdl, ci, siz, loc, &rec);
#define con_write(tcb, y, x, str, n) con_write8(tcb, y, x, str, n)
#endif
+#if EXP_OPTIMIZE
+/*
+ * Comparing new/current screens, determine the last column-index for a change
+ * beginning on the given row,col position. Unlike a serial terminal, there is
+ * no cost for "moving" the "cursor" on the line as we update it.
+ */
+static int
+find_end_of_change(SCREEN *sp, int row, int col)
+{
+ int result = col;
+ struct ldat *curdat = CurScreen(sp)->_line + row;
+ struct ldat *newdat = NewScreen(sp)->_line + row;
+
+ while (col <= newdat->lastchar) {
+#if USE_WIDEC_SUPPORT
+ if (isWidecExt(curdat->text[col]) || isWidecExt(newdat->text[col])) {
+ result = col;
+ } else if (memcmp(&curdat->text[col],
+ &newdat->text[col],
+ sizeof(curdat->text[0]))) {
+ result = col;
+ } else {
+ break;
+ }
+#else
+ if (curdat->text[col] != newdat->text[col]) {
+ result = col;
+ } else {
+ break;
+ }
+#endif
+ ++col;
+ }
+ return result;
+}
+
+/*
+ * Given a row,col position at the end of a change-chunk, look for the
+ * beginning of the next change-chunk.
+ */
+static int
+find_next_change(SCREEN *sp, int row, int col)
+{
+ struct ldat *curdat = CurScreen(sp)->_line + row;
+ struct ldat *newdat = NewScreen(sp)->_line + row;
+ int result = newdat->lastchar + 1;
+
+ while (++col <= newdat->lastchar) {
+#if USE_WIDEC_SUPPORT
+ if (isWidecExt(curdat->text[col]) != isWidecExt(newdat->text[col])) {
+ result = col;
+ break;
+ } else if (memcmp(&curdat->text[col],
+ &newdat->text[col],
+ sizeof(curdat->text[0]))) {
+ result = col;
+ break;
+ }
+#else
+ if (curdat->text[col] != newdat->text[col]) {
+ result = col;
+ break;
+ }
+#endif
+ }
+ return result;
+}
+
+#define EndChange(first) \
+ find_end_of_change(sp, y, first)
+#define NextChange(last) \
+ find_next_change(sp, y, last)
+
+#endif /* EXP_OPTIMIZE */
+
#define MARK_NOCHANGE(win,row) \
win->_line[row].firstchar = _NOCHANGE; \
win->_line[row].lastchar = _NOCHANGE
for (y = 0; y < nonempty; y++) {
x0 = NewScreen(sp)->_line[y].firstchar;
if (x0 != _NOCHANGE) {
+#if EXP_OPTIMIZE
+ int x2;
+ int limit = NewScreen(sp)->_line[y].lastchar;
+ while ((x1 = EndChange(x0)) <= limit) {
+ while ((x2 = NextChange(x1)) <= limit && x2 <= (x1 + 2)) {
+ x1 = x2;
+ }
+ n = x1 - x0 + 1;
+ memcpy(&CurScreen(sp)->_line[y].text[x0],
+ &NewScreen(sp)->_line[y].text[x0],
+ n * sizeof(CurScreen(sp)->_line[y].text[x0]));
+ con_write(TCB,
+ y,
+ x0,
+ &CurScreen(sp)->_line[y].text[x0], n);
+ x0 = NextChange(x1);
+ }
+
+ /* mark line changed successfully */
+ if (y <= NewScreen(sp)->_maxy) {
+ MARK_NOCHANGE(NewScreen(sp), y);
+ }
+ if (y <= CurScreen(sp)->_maxy) {
+ MARK_NOCHANGE(CurScreen(sp), y);
+ }
+#else
x1 = NewScreen(sp)->_line[y].lastchar;
n = x1 - x0 + 1;
if (n > 0) {
MARK_NOCHANGE(CurScreen(sp), y);
}
}
+#endif
}
}