X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Fwin32con%2Fwin_driver.c;h=9b7a752ecc411a5f3d1eafd50dacdcde19775e30;hp=02cd378c9e2e4079d7ac2b29200bbfa0a3b7ea5c;hb=4b1ec76cb0a0fa5055909f534b3f928dafc7f7f1;hpb=cabcc699fe87c3982b795dabea1ba6970b4faa90 diff --git a/ncurses/win32con/win_driver.c b/ncurses/win32con/win_driver.c index 02cd378c..9b7a752e 100644 --- a/ncurses/win32con/win_driver.c +++ b/ncurses/win32con/win_driver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * 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 * @@ -38,10 +38,12 @@ #include #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 @@ -143,9 +145,10 @@ MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, attr_t ch) * 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; @@ -159,34 +162,37 @@ con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int n) 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); @@ -238,6 +244,81 @@ con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n) #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 @@ -287,6 +368,32 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB) 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) { @@ -306,6 +413,7 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB) MARK_NOCHANGE(CurScreen(sp), y); } } +#endif } }