]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/win32con/win_driver.c
ncurses 5.9 - patch 20130105
[ncurses.git] / ncurses / win32con / win_driver.c
index afc1a16815b7ccb83a4bbb8f4ba3bd0650271ba4..9b7a752ecc411a5f3d1eafd50dacdcde19775e30 100644 (file)
@@ -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            *
 #include <curses.priv.h>
 #define CUR my_term.type.
 
-MODULE_ID("$Id: win_driver.c,v 1.13 2012/09/03 16:20:24 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
        }
     }
 
@@ -340,7 +448,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
     assert(tname != 0);
 
     TCB->magic = WINMAGIC;
-    if (*tname == 0 || *tname == 0) {
+    if (*tname == 0 || *tname == 0 || *tname == '#') {
        code = TRUE;
     } else {
        TERMINAL my_term;