]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tty/tty_update.c
ncurses 5.0
[ncurses.git] / ncurses / tty / tty_update.c
similarity index 92%
rename from ncurses/lib_doupdate.c
rename to ncurses/tty/tty_update.c
index b0daf4fc144985b434426735c52a05e143894d82..a5a640f8663c7da328ff6f6286ab5be2e5d8c716 100644 (file)
  *
  *-----------------------------------------------------------------*/
 
+#ifdef __BEOS__
+#include <OS.h>
+#endif
+
 #include <curses.priv.h>
 
 #if defined(TRACE) && HAVE_SYS_TIMES_H && HAVE_TIMES
 #endif
 #endif
 
-#ifdef __BEOS__
-/* BeOS select() only works on sockets.  Use the tty hack instead */
-#include <socket.h>
-#define select check_select
-#endif
-
 #include <term.h>
 
-MODULE_ID("$Id: lib_doupdate.c,v 1.98 1998/02/11 12:14:00 tom Exp $")
+MODULE_ID("$Id: tty_update.c,v 1.117 1999/10/22 23:28:46 tom Exp $")
 
 /*
  * This define controls the line-breakout optimization.  Every once in a
@@ -97,10 +95,10 @@ MODULE_ID("$Id: lib_doupdate.c,v 1.98 1998/02/11 12:14:00 tom Exp $")
 
 static inline chtype ClrBlank ( WINDOW *win );
 static int ClrBottom(int total);
-static int InsStr( chtype *line, int count );
 static void ClearScreen( chtype blank );
-static void ClrUpdate( WINDOW *win );
+static void ClrUpdate( void );
 static void DelChar( int count );
+static void InsStr( chtype *line, int count );
 static void TransformLine( int const lineno );
 
 #ifdef POSITION_DEBUG
@@ -110,29 +108,40 @@ static void TransformLine( int const lineno );
  *
  ****************************************************************************/
 
-void position_check(int expected_y, int expected_x, char *legend)
+static void position_check(int expected_y, int expected_x, char *legend)
 /* check to see if the real cursor position matches the virtual */
 {
-    static char  buf[9];
+    char  buf[20];
     int y, x;
 
-    if (_nc_tracing)
+    if (!_nc_tracing || (expected_y < 0 && expected_x < 0))
        return;
 
     memset(buf, '\0', sizeof(buf));
-    (void) write(1, "\033[6n", 4);     /* only works on ANSI-compatibles */
-    (void) read(0, (void *)buf, 8);
+    putp("\033[6n");   /* only works on ANSI-compatibles */
+    _nc_flush();
+    (void) read(0, buf, sizeof(buf)-1);
     _tracef("probe returned %s", _nc_visbuf(buf));
 
     /* try to interpret as a position report */
-    if (sscanf(buf, "\033[%d;%dR", &y, &x) != 2)
+    if (sscanf(buf, "\033[%d;%dR", &y, &x) != 2) {
        _tracef("position probe failed in %s", legend);
-    else if (y - 1 != expected_y || x - 1 != expected_x)
-       _tracef("position seen (%d, %d) doesn't match expected one (%d, %d) in %s",
-               y-1, x-1, expected_y, expected_x, legend);
-    else
-       _tracef("position matches OK in %s", legend);
+    } else {
+       if (expected_x < 0)
+           expected_x = x - 1;
+       if (expected_y < 0)
+           expected_y = y - 1;
+       if (y - 1 != expected_y || x - 1 != expected_x) {
+           beep();
+           _tracef("position seen (%d, %d) doesn't match expected one (%d, %d) in %s",
+                   y-1, x-1, expected_y, expected_x, legend);
+       } else {
+           _tracef("position matches OK in %s", legend);
+       }
+    }
 }
+#else
+#define position_check(expected_y, expected_x, legend) /* nothing */
 #endif /* POSITION_DEBUG */
 
 /****************************************************************************
@@ -148,9 +157,7 @@ static inline void GoTo(int const row, int const col)
        TR(TRACE_MOVE, ("GoTo(%d, %d) from (%d, %d)",
                        row, col, SP->_cursrow, SP->_curscol));
 
-#ifdef POSITION_DEBUG
        position_check(SP->_cursrow, SP->_curscol, "GoTo");
-#endif /* POSITION_DEBUG */
 
        /*
         * Force restore even if msgr is on when we're in an alternate
@@ -168,6 +175,7 @@ static inline void GoTo(int const row, int const col)
        mvcur(SP->_cursrow, SP->_curscol, row, col);
        SP->_cursrow = row;
        SP->_curscol = col;
+       position_check(SP->_cursrow, SP->_curscol, "GoTo2");
 }
 
 static inline void PutAttrChar(chtype ch)
@@ -179,10 +187,14 @@ static inline void PutAttrChar(chtype ch)
                          _tracechtype(ch),
                           SP->_cursrow, SP->_curscol));
        UpdateAttrs(ch);
-       putc((int)TextOf(ch), SP->_ofp);
+       if (SP->_cleanup) {
+               _nc_outch((int)TextOf(ch));
+       } else {
+               putc((int)TextOf(ch), SP->_ofp); /* macro's fastest... */
 #ifdef TRACE
-       _nc_outchars++;
+               _nc_outchars++;
 #endif /* TRACE */
+       }
        SP->_curscol++;
        if (char_padding) {
                TPUTS_TRACE("char_padding");
@@ -212,6 +224,21 @@ static bool check_pending(void)
                {
                        have_pending = TRUE;
                }
+#elif defined(__BEOS__)
+               /*
+                * BeOS's select() is declared in socket.h, so the configure script does
+                * not see it.  That's just as well, since that function works only for
+                * sockets.  This (using snooze and ioctl) was distilled from Be's patch
+                * for ncurses which uses a separate thread to simulate select().
+                *
+                * FIXME: the return values from the ioctl aren't very clear if we get
+                * interrupted.
+                */
+               int n = 0;
+               int howmany = ioctl(0, 'ichr', &n);
+               if (howmany >= 0 && n > 0) {
+                       have_pending = TRUE;
+               }
 #elif HAVE_SELECT
                fd_set fdset;
                struct timeval ktimeout;
@@ -221,7 +248,7 @@ static bool check_pending(void)
 
                FD_ZERO(&fdset);
                FD_SET(SP->_checkfd, &fdset);
-               if (select(SP->_checkfd+1, &fdset, NULL, NULL, &ktimeout) > 0)
+               if (select(SP->_checkfd+1, &fdset, NULL, NULL, &ktimeout) != 0)
                {
                        have_pending = TRUE;
                }
@@ -229,7 +256,7 @@ static bool check_pending(void)
        }
        if (have_pending) {
                SP->_fifohold = 5;
-               fflush(SP->_ofp);
+               _nc_flush();
        }
        return FALSE;
 }
@@ -261,6 +288,8 @@ static void PutCharLR(chtype const ch)
        putp(exit_am_mode);
 
        PutAttrChar(ch);
+       SP->_curscol--;
+       position_check(SP->_cursrow, SP->_curscol, "exit_am_mode");
 
        TPUTS_TRACE("enter_am_mode");
        putp(enter_am_mode);
@@ -307,6 +336,7 @@ static void wrap_cursor(void)
     {
        SP->_curscol--;
     }
+    position_check(SP->_cursrow, SP->_curscol, "wrap_cursor");
 }
 
 static inline void PutChar(chtype const ch)
@@ -320,9 +350,7 @@ static inline void PutChar(chtype const ch)
     if (SP->_curscol >= screen_columns)
        wrap_cursor();
 
-#ifdef POSITION_DEBUG
     position_check(SP->_cursrow, SP->_curscol, "PutChar");
-#endif /* POSITION_DEBUG */
 }
 
 /*
@@ -680,19 +708,11 @@ struct tms before, after;
 #endif /* USE_XMC_SUPPORT */
 
        nonempty = 0;
-       if (curscr->_clear) {           /* force refresh ? */
-               /* yes, clear all & update */
-               T(("clearing and updating curscr"));
-               if (is_wintouched(newscr))
-                       ClrUpdate(newscr);
-               else
-                       ClrUpdate(curscr);
+       if (curscr->_clear || newscr->_clear) {         /* force refresh ? */
+               T(("clearing and updating from scratch"));
+               ClrUpdate();
                curscr->_clear = FALSE; /* reset flag */
                newscr->_clear = FALSE; /* reset flag */
-       } else if (newscr->_clear) {
-               T(("clearing and updating newscr"));
-               ClrUpdate(newscr);
-               newscr->_clear = FALSE;
        } else {
                int changedlines = CHECK_INTERVAL;
 
@@ -702,22 +722,7 @@ struct tms before, after;
                nonempty = min(screen_lines, newscr->_maxy+1);
 
                if (SP->_scrolling) {
-#if USE_HASHMAP
-#if defined(TRACE) || defined(NCURSES_TEST)
-               if (_nc_optimize_enable & OPTIMIZE_HASHMAP)
-#endif /*TRACE */
-                       _nc_hash_map();
-#elif !USE_SCROLL_HINTS
-               _nc_setup_scroll();
-#endif
-#if defined(TRACE) || defined(NCURSES_TEST)
-               if (_nc_optimize_enable & OPTIMIZE_SCROLL)
-#endif /*TRACE */
-#if USE_SCROLL_HINTS || USE_HASHMAP
                        _nc_scroll_optimize();
-#else
-                       _nc_perform_scroll();
-#endif
                }
 
                nonempty = ClrBottom(nonempty);
@@ -761,10 +766,13 @@ struct tms before, after;
        for (i = nonempty; i <= curscr->_maxy; i++)
                MARK_NOCHANGE(curscr,i)
 
-       curscr->_curx = newscr->_curx;
-       curscr->_cury = newscr->_cury;
+       if (!newscr->_leaveok)
+       {
+               curscr->_curx = newscr->_curx;
+               curscr->_cury = newscr->_cury;
 
-       GoTo(curscr->_cury, curscr->_curx);
+               GoTo(curscr->_cury, curscr->_curx);
+       }
 
     cleanup:
        /*
@@ -773,7 +781,7 @@ struct tms before, after;
         */
        UpdateAttrs(A_NORMAL);
 
-       fflush(SP->_ofp);
+       _nc_flush();
        curscr->_attrs = newscr->_attrs;
 /*     curscr->_bkgd  = newscr->_bkgd; */
 
@@ -812,29 +820,20 @@ chtype    blank = BLANK;
 }
 
 /*
-**     ClrUpdate(win)
+**     ClrUpdate()
 **
 **     Update by clearing and redrawing the entire screen.
 **
 */
 
-static void ClrUpdate(WINDOW *win)
+static void ClrUpdate(void)
 {
        int i;
-       chtype blank = ClrBlank(win);
+       chtype blank = ClrBlank(stdscr);
        int nonempty = min(screen_lines, newscr->_maxy+1);
 
        T(("ClrUpdate() called"));
 
-       if (win == curscr) {
-               /* discard updates */
-               for (i = 0; i < screen_lines ; i++) {
-                       memcpy( newscr->_line[i].text,
-                               curscr->_line[i].text,
-                               screen_columns * sizeof(chtype));
-               }
-       }
-
        ClearScreen(blank);
 
        T(("updating screen from scratch"));
@@ -928,16 +927,16 @@ chtype    blank  = newscr->_line[total-1].text[last-1]; /* lower right char */
        if(!clr_eos || !can_clear_with(blank))
                return total;
 
-       if (tstLine == 0)
-               tstLine = (chtype *)malloc(length);
-       else if (length > lenLine)
-               tstLine = (chtype *)realloc(tstLine, length);
+       if ((tstLine == 0) || (last > (int)lenLine)) {
+               tstLine = typeRealloc(chtype, last, tstLine);
+               if (tstLine != 0) {
+                       lenLine = last;
+                       for (col = 0; col < last; col++)
+                               tstLine[col] = blank;
+               }
+       }
 
        if (tstLine != 0) {
-               lenLine = length;
-               for (col = 0; col < last; col++)
-                       tstLine[col] = blank;
-
                for (row = total-1; row >= 0; row--) {
                        if (memcmp(tstLine, newscr->_line[row].text, length))
                                break;
@@ -950,10 +949,16 @@ chtype    blank  = newscr->_line[total-1].text[last-1]; /* lower right char */
                        GoTo(top,0);
                        ClrToEOS(blank);
                        total = top;
+                       if (SP->oldhash && SP->newhash)
+                       {
+                               for (row = top; row < screen_lines; row++)
+                                       SP->oldhash[row] = SP->newhash[row];
+                       }
                }
        }
 #if NO_LEAKS
-       FreeAndNull(tstLine);
+       if (tstLine != 0)
+               FreeAndNull(tstLine);
 #endif
        return total;
 }
@@ -987,6 +992,10 @@ bool       attrchanged = FALSE;
 
        T(("TransformLine(%d) called", lineno));
 
+       /* copy new hash value to old one */
+       if (SP->oldhash && SP->newhash)
+               SP->oldhash[lineno] = SP->newhash[lineno];
+
        if(ceol_standout_glitch && clr_eol) {
                firstChar = 0;
                while(firstChar < screen_columns) {
@@ -1141,8 +1150,9 @@ bool      attrchanged = FALSE;
                        if(newLine[firstChar] != blank )
                                PutChar(newLine[firstChar]);
                        ClrToEOL(blank);
-               } else if( newLine[nLastChar] != oldLine[oLastChar]
-                               || !(_nc_idcok && has_ic()) ) {
+               } else if( (nLastChar != oLastChar)
+                       && (newLine[nLastChar] != oldLine[oLastChar]
+                               || !(_nc_idcok && has_ic())) ) {
                        GoTo(lineno, firstChar);
                        if ((oLastChar - nLastChar) > SP->_el_cost) {
                                if(PutRange(oldLine, newLine, lineno, firstChar, nLastChar))
@@ -1172,10 +1182,10 @@ bool    attrchanged = FALSE;
                                GoTo(lineno, firstChar);
                                PutRange(oldLine, newLine, lineno, firstChar, n);
                        }
-                       GoTo(lineno, n+1);
 
                        if (oLastChar < nLastChar) {
                                int m = max(nLastNonblank, oLastNonblank);
+                               GoTo(lineno, n+1);
                                if (InsCharCost(nLastChar - oLastChar)
                                 > (m - n)) {
                                        PutRange(oldLine, newLine, lineno, n+1, m);
@@ -1183,6 +1193,7 @@ bool      attrchanged = FALSE;
                                        InsStr(&newLine[n+1], nLastChar - oLastChar);
                                }
                        } else if (oLastChar > nLastChar ) {
+                               GoTo(lineno, n+1);
                                if (DelCharCost(oLastChar - nLastChar)
                                    > SP->_el_cost + nLastNonblank - (n+1)) {
                                        if(PutRange(oldLine, newLine, lineno,
@@ -1230,9 +1241,7 @@ static void ClearScreen(chtype blank)
                TPUTS_TRACE("clear_screen");
                putp(clear_screen);
                SP->_cursrow = SP->_curscol = 0;
-#ifdef POSITION_DEBUG
                position_check(SP->_cursrow, SP->_curscol, "ClearScreen");
-#endif /* POSITION_DEBUG */
        } else if (clr_eos) {
                SP->_cursrow = SP->_curscol = -1;
                GoTo(0,0);
@@ -1270,30 +1279,36 @@ static void ClearScreen(chtype blank)
 **
 */
 
-static int InsStr(chtype *line, int count)
+static void InsStr(chtype *line, int count)
 {
        T(("InsStr(%p,%d) called", line, count));
 
-       if (enter_insert_mode  &&  exit_insert_mode) {
-               TPUTS_TRACE("enter_insert_mode");
-               putp(enter_insert_mode);
+       /* Prefer parm_ich as it has the smallest cost - no need to shift
+        * the whole line on each character. */
+       /* The order must match that of InsCharCost. */
+       if (parm_ich) {
+               TPUTS_TRACE("parm_ich");
+               tputs(tparm(parm_ich, count), count, _nc_outch);
                while (count) {
                        PutAttrChar(*line);
                        line++;
                        count--;
                }
-               TPUTS_TRACE("exit_insert_mode");
-               putp(exit_insert_mode);
-               return(OK);
-       } else if (parm_ich) {
-               TPUTS_TRACE("parm_ich");
-               tputs(tparm(parm_ich, count), count, _nc_outch);
+       } else if (enter_insert_mode  &&  exit_insert_mode) {
+               TPUTS_TRACE("enter_insert_mode");
+               putp(enter_insert_mode);
                while (count) {
                        PutAttrChar(*line);
+                       if (insert_padding)
+                       {
+                               TPUTS_TRACE("insert_padding");
+                               putp(insert_padding);
+                       }
                        line++;
                        count--;
                }
-               return(OK);
+               TPUTS_TRACE("exit_insert_mode");
+               putp(exit_insert_mode);
        } else {
                while (count) {
                        TPUTS_TRACE("insert_character");
@@ -1307,8 +1322,8 @@ static int InsStr(chtype *line, int count)
                        line++;
                        count--;
                }
-               return(OK);
        }
+       position_check(SP->_cursrow, SP->_curscol, "InsStr");
 }
 
 /*
@@ -1342,14 +1357,8 @@ static void DelChar(int count)
 
 void _nc_outstr(const char *str)
 {
-    FILE *ofp = SP ? SP->_ofp : stdout;
-
-    (void) fputs(str, ofp);
-    (void) fflush(ofp);
-
-#ifdef TRACE
-    _nc_outchars += strlen(str);
-#endif /* TRACE */
+    (void) putp(str);
+    _nc_flush();
 }
 
 /*
@@ -1652,17 +1661,17 @@ int _nc_scrolln(int n, int top, int bot, int maxy)
        if (res == ERR && change_scroll_region)
        {
            if (top != 0 && (SP->_cursrow == top || SP->_cursrow == top-1)
-               && save_cursor && restore_cursor)
+               && save_cursor && restore_cursor)
            {
                cursor_saved=TRUE;
-               TPUTS_TRACE("save_cursor");
+               TPUTS_TRACE("save_cursor");
                tputs(save_cursor, 0, _nc_outch);
            }
            TPUTS_TRACE("change_scroll_region");
            tputs(tparm(change_scroll_region, top, bot), 0, _nc_outch);
            if (cursor_saved)
            {
-               TPUTS_TRACE("restore_cursor");
+               TPUTS_TRACE("restore_cursor");
                tputs(restore_cursor, 0, _nc_outch);
            }
            else
@@ -1686,6 +1695,9 @@ int _nc_scrolln(int n, int top, int bot, int maxy)
 
     _nc_scroll_window(curscr, n, top, bot, blank);
 
+    /* shift hash values too - they can be reused */
+    _nc_scroll_oldhash(n, top, bot);
+
     return(OK);
 }