Ejemplo n.º 1
0
static void ti_hwcursor( void )
/*****************************/
{
    // Set cursor to correct visibility
    switch( UIData->cursor_type ) {
    case C_OFF:
        TI_CURSOR_OFF();
        break;
    case C_NORMAL:
        TI_CURSOR_NORMAL();
        break;
    case C_INSERT:
        TI_CURSOR_BOLD();
        break;
    }

    if( UIData->cursor_type == C_OFF ) {
        // Since some terminals can't hide the cursor we'll also
        // move the cursor into an inconspicuous(sp?) location
        TI_CURSOR_MOVE( 0, UIData->height - 1 );
    } else {
        TI_CURSOR_MOVE( UIData->cursor_col, UIData->cursor_row );
    }

    __flush();
}
Ejemplo n.º 2
0
static bool td_initconsole( void )
/********************************/
{
    if( !ostream_init( UIConHandle ) )
        return( false );

    // Initialize the term as documented in "Terminal Control Under QNX"
    TI_EXEC_PROG( init_prog );

    TI_INIT1_STRING();
    TI_INIT2_STRING();
    TI_CLEAR_MARGINS();
    TI_PUT_FILE( init_file );
    TI_INIT3_STRING();

    // Now we're initialized, so set term to usable mode:
    TI_CA_ENABLE();
    TI_ENABLE_ACS();

    // disable auto-right-margin
    TI_NOWRAP();
    // if we can't then we just won't use the bottom right corner
    TI_ignore_bottom_right = !TCAP_NOSCROLL;
    QNXDebugPrintf1( "IgnoreLowerRight=%d", TI_ignore_bottom_right );

    TI_NOBOLD();
    TI_NOBLINK();

    __flush();

    return( true );
}
Ejemplo n.º 3
0
static bool intern td_initconsole( void )
/***************************************/
{
    if( !ostream_init(UIConHandle) ) return( FALSE );
    QNX_NOWRAP();
    QNX_NOBOLD();
    QNX_NOBLINK();
    __flush();
    return( TRUE );
}
Ejemplo n.º 4
0
static bool td_initconsole( void )
/********************************/
{
    if( !ostream_init( UIConHandle ) )
        return( false );
    QNX_NOWRAP();
    QNX_NOBOLD();
    QNX_NOBLINK();
    __flush();
    return( true );
}
Ejemplo n.º 5
0
static struct OPerIR* _inst( const iONode ini ,const iOTrace trc ) {
  iOPerIR __PerIR = allocMem( sizeof( struct OPerIR ) );
  iOPerIRData data = allocMem( sizeof( struct OPerIRData ) );
  MemOp.basecpy( __PerIR, &PerIROp, 0, sizeof( struct OPerIR ), data );

  /* Initialize data->xxx members... */
  TraceOp.set( trc );
  SystemOp.inst();

  /* Initialize data->xxx members... */
  data->device   = StrOp.dup( wDigInt.getdevice( ini ) );
  data->iid      = StrOp.dup( wDigInt.getiid( ini ) );
  data->fboffset = wDigInt.getfboffset( ini );

  MemOp.set( data->readerTick, 0, sizeof(data->readerTick) );


  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "----------------------------------------" );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "PerIR %d.%d.%d", vmajor, vminor, patch );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "----------------------------------------" );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "iid       = %s", data->iid );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "device    = %s", data->device );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "baudrate  = %d", 9600 );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "handshake = %s", wDigInt.getflow(ini) );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "fboffset  = %d", data->fboffset );
  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "----------------------------------------" );

  data->serial = SerialOp.inst( data->device );
  SerialOp.setFlow( data->serial, StrOp.equals( wDigInt.cts, wDigInt.getflow( data->ini ) ) ? cts:0 );
  SerialOp.setLine( data->serial, 9600, 8, 2, none, wDigInt.isrtsdisabled( ini ) );
  data->serialOK = SerialOp.open( data->serial );

  if( data->serialOK ) {
    char* thname = NULL;
    data->run = True;
    /* empty UART receive buffer */
    __flush(data);

    thname = StrOp.fmt("perirread%X", __PerIR);
    data->reader = ThreadOp.inst( thname, &__PerIRReader, __PerIR );
    StrOp.free(thname),
    ThreadOp.start( data->reader );

    thname = StrOp.fmt("perirtick%X", __PerIR);
    data->ticker = ThreadOp.inst( thname, &__irTicker, __PerIR );
    StrOp.free(thname),
    ThreadOp.start( data->ticker );
  }
  else
    TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "Could not init PerIR port!" );

  instCnt++;
  return __PerIR;
}
Ejemplo n.º 6
0
static int td_fini( void )
/************************/
{
    QNX_RESTORE_ATTR();
    QNX_HOME();
    QNX_CLS();
    QNX_CURSOR_NORMAL();
    __flush();
    finikeyboard();
    uifinicursor();
    return( 0 );
}
Ejemplo n.º 7
0
static void
iptree_destroy(struct ip_set *set)
{
	struct ip_set_iptree *map = set->data;

	/* gc might be running */
	while (!del_timer(&map->gc))
		msleep(IPTREE_DESTROY_SLEEP);
	__flush(map);
	kfree(map);
	set->data = NULL;
}
Ejemplo n.º 8
0
_WCRTLINK int __F_NAME(fputs,fputws)( const CHAR_TYPE *s, FILE *fp )
{
    const CHAR_TYPE     *start;
    int                 c;
    int                 not_buffered;
    int                 rc;

    _ValidFile( fp, __F_NAME(EOF,WEOF) );
    _AccessFile( fp );

    if( _FP_BASE(fp) == NULL ) {
        __ioalloc( fp );                /* allocate buffer */
    }
    not_buffered = 0;
    if( fp->_flag & _IONBF ) {
        not_buffered = 1;
        fp->_flag &= ~_IONBF;
        fp->_flag |= _IOLBF;
    }
    rc = 0;
    start = s;
    while( c = *s ) {
        s++;
#ifndef __WIDECHAR__
        if( (fputc)( c, fp ) == EOF ) {         /* 23-oct-91 */
            rc = EOF;
            break;
        }
#else
        if( (fputwc)( c, fp ) == WEOF ) {       /* 23-oct-91 */
            rc = -1;
            break;
        }
#endif
    }
    if( not_buffered ) {
        fp->_flag &= ~_IOLBF;
        fp->_flag |= _IONBF;
        if( rc == 0 ) {
            rc = __flush( fp );                 /* 23-oct-91 */
        }
    }
    if( rc == 0 ) {
        /* return the number of items written */
        /* this is ok by ANSI which says that success is */
        /* indicated by a non-negative return value */
        rc = s - start;
    }
    _ReleaseFile( fp );
    return( rc );
}
Ejemplo n.º 9
0
static void
iptree_flush(struct ip_set *set)
{
	struct ip_set_iptree *map = set->data;
	unsigned int timeout = map->timeout;
	
	/* gc might be running */
	while (!del_timer(&map->gc))
		msleep(IPTREE_DESTROY_SLEEP);
	__flush(map);
	memset(map, 0, sizeof(*map));
	map->timeout = timeout;

	init_gc_timer(set);
}
Ejemplo n.º 10
0
static void td_hwcursor( void )
/*****************************/
{
    switch( UIData->cursor_type ) {
    case C_OFF:
        QNX_CURSOR_OFF();
        break;
    case C_NORMAL:
        QNX_CURSOR_NORMAL();
        break;
    case C_INSERT:
        QNX_CURSOR_BOLD();
        break;
    }
    QNX_CURSOR_MOVE( UIData->cursor_col, UIData->cursor_row );
    __flush();
}
Ejemplo n.º 11
0
int __doclose( FILE *fp, int close_handle )
{
    int         ret;

    if( (fp->_flag & (_READ | _WRITE)) == 0 ) {
        return( -1 );                       /* file already closed */
    }
    ret = 0;
    if( fp->_flag & _DIRTY ) {
        if( __flush( fp ) ) {
            ret = -1;
        }
    }
    _AccessFile( fp );
/*
 *      02-nov-92 G.Turcotte  Syncronize buffer pointer with the file pointer
 *                        IEEE Std 1003.1-1988 B.8.2.3.2
 *      03-nov-03 B.Oldeman Inlined ftell; we already know the buffer isn't
 *                dirty (because of the flush), so only a "get" applies
 */
    if( fp->_cnt != 0 ) {                   /* if something in buffer */
        __lseek( fileno( fp ), -fp->_cnt, SEEK_CUR );
    }

    if( close_handle ) {
#if defined( __UNIX__ ) || defined( __NETWARE__ ) || defined( __RDOS__ ) || defined( __RDOSDEV__ )
        // we don't get to implement the close function on these systems
        ret |= close( fileno( fp ) );
#else
        ret |= __close( fileno( fp ) );
#endif
    }
    if( fp->_flag & _BIGBUF ) {     /* if we allocated the buffer */
        lib_free( _FP_BASE( fp ) );
        _FP_BASE( fp ) = NULL;
    }
#ifndef __UNIX__
    /* this never happens under UNIX */
    if( fp->_flag & _TMPFIL ) {     /* if this is a temporary file */
        __RmTmpFileFn( fp );
    }
#endif
    fp->_flag &= _DYNAMIC;
    _ReleaseFile( fp );
    return( ret );
}
Ejemplo n.º 12
0
//
// write -- write bytes to the serial port. Ignore fd, since
//          stdout and stderr are the same. Since we have no filesystem,
//          open will only return an error.
//
static int
sys_write(int fd, char *buf, int nbytes)
{
#define WBUFSIZE  256
    int  tosend;

    tosend = nbytes;

    while (tosend > 0) {
        if (*buf == '\n')
            __putc('\r');
        __putc(*buf++);
        tosend--;
    }
    __flush();

    return (nbytes);
}
Ejemplo n.º 13
0
static int td_fini( void )
/************************/
{
    TI_RESTORE_ATTR();
    TI_HOME();
    TI_CLS();
    TI_CURSOR_NORMAL();
    TI_RESTORE_COLOUR();

    TI_RESET1_STRING();
    TI_RESET2_STRING();
    TI_PUT_FILE( reset_file );
    TI_RESET3_STRING();
    __flush();

    finikeyboard();
    uifinicursor();
    return( 0 );
}
Ejemplo n.º 14
0
int __flushall( int mask )
{
    __stream_link   *link;
    FILE            *fp;
    int             number_of_open_files;

    _AccessIOB();
    number_of_open_files = 0;
    for( link = _RWD_ostream; link != NULL; link = link->next ) {
        fp = link->stream;
        if( fp->_flag & mask ) {      /* if file is a candidate */
            ++number_of_open_files;
            if( fp->_flag & _DIRTY ) {
                __flush( fp );
            }
        }
    }
    _ReleaseIOB();
    return( number_of_open_files );
}
Ejemplo n.º 15
0
static void update_shadow( void )
/*******************************/
{
    LP_PIXEL    bufp, sbufp;    // buffer and shadow buffer
    int         incr = UIData->screen.increment;

    // make sure cursor is back where it belongs
    ti_hwcursor();
    __flush();

    // copy buffer to shadow buffer
    bufp = UIData->screen.origin;
    sbufp = shadow;
    for( ; dirty_area.row0 < dirty_area.row1; dirty_area.row0++ ) {
        _fmemcpy( sbufp + incr * dirty_area.row0 + dirty_area.col0,
                bufp + incr * dirty_area.row0 + dirty_area.col0,
                ( dirty_area.col1 - dirty_area.col0 ) * sizeof( PIXEL ) );
    }

    // set dirty_area rectangle to be empty
    dirty_area.row0 = dirty_area.row1 = dirty_area.col0 = dirty_area.col1 = 0;
}
Ejemplo n.º 16
0
int __doclose( FILE *fp, int close_handle )
{
    int                 ret;

    if( fp->_flag == 0 ) {
        return( -1 );                       /* file already closed */
    }
    ret = 0;
    if( fp->_flag & _DIRTY ) {
        ret = __flush( fp );
    }
    _AccessFile( fp );
    if( fp->_cnt != 0 ) {                   /* if something in buffer */
        __lseek( fileno( fp ), -fp->_cnt, SEEK_CUR );
    }

    if( close_handle ) {
        #if defined(__UNIX__) || defined(__NETWARE__)
            // we don't get to implement the close function on these systems
            ret |= close( fileno( fp ) );
        #else
            ret |= __close( fileno( fp ) );
        #endif
    }
    if( fp->_flag & _BIGBUF ) {     /* if we allocated the buffer */
        lib_free( _FP_BASE(fp) );
        _FP_BASE(fp) = NULL;
    }
#ifndef __UNIX__
    /* this never happens under UNIX */
    if( fp->_flag & _TMPFIL ) {     /* if this is a temporary file */
        __RmTmpFileFn( fp );
    }
#endif
    _ReleaseFile( fp );
    return( ret );
}
Ejemplo n.º 17
0
static int __oflush( int c )
{
    __flush();
    //assert( _con_out.curp < _con_out.ebuf );
    return( __putchar( c ) );
}
Ejemplo n.º 18
0
static int td_refresh( int must )
/*******************************/
{
    int             i;
    int             incr;
    LP_PIXEL        bufp, sbufp;

    must |= UserForcedTermRefresh;
    UserForcedTermRefresh = false;

    if( dirty_area.row0 == dirty_area.row1 && dirty_area.col0 == dirty_area.col1 ) {
        td_hwcursor();
        __flush();
        return( 0 );
    }

QNXDebugPrintf4("td_refresh (%d,%d)->(%d,%d)", dirty_area.row0, dirty_area.col0, dirty_area.row1, dirty_area.col1);

    if( UIData->cursor_type != C_OFF )
        QNX_CURSOR_OFF();

    bufp = UIData->screen.origin;
    incr = UIData->screen.increment;
    sbufp = shadow;
    bufp += dirty_area.row0 * incr;
    sbufp += dirty_area.row0 * incr;

/*-
* minimize updates
*/
    for( i = dirty_area.row0; i < dirty_area.row1; i++ ) {
        int     j;
        int     lastattr = -1;      // invalid to start
        bool    ca_valid = false;   // is cursor address valid?

        for( j = dirty_area.col0; j < dirty_area.col1; j++ ) {
            if( !must && PIXELEQUAL( bufp[j], sbufp[j] ) ) {
                ca_valid = false;
                lastattr = -1;
                continue;
            }

            if( !ca_valid ) {
QNXDebugPrintf2("cursor address %d,%d\n",j,i);
                QNX_CURSOR_MOVE( j, i );
                ca_valid = true;
            }
            if( bufp[j].attr != lastattr ) {
                lastattr = new_attr( bufp[j].attr, lastattr );
            }
            if( bufp[j].ch < 0x20 )
                __putchar( 033 );
            __putchar( bufp[j].ch );
            sbufp[j] = bufp[j];
        }
        bufp += incr;
        sbufp += incr;
    }
    dirty_area.row0 = dirty_area.row1 = 0;
    dirty_area.col0 = dirty_area.col1 = 0;

    td_hwcursor();
    __flush();

    return( 0 );
}
Ejemplo n.º 19
0
_WCRTLINK int fseek( FILE *fp, long offset, int origin )
#endif
{
    _ValidFile( fp, -1 );
    _AccessFile( fp );
    /*
      if the file is open for any sort of writing we must ensure that
      the buffer is flushed when dirty so that the integrity of the
      data is preserved.
      if there is an ungotten character in the buffer then the data must
      be discarded to ensure the integrity of the data
    */
    if( fp->_flag & (_WRITE | _UNGET) ) {
        if( fp->_flag & _DIRTY ) {
            /*
              the __flush routine aligns the DOS file pointer with the
              start of the resulting cleared buffer, as such, the SEEK_CUR
              code used for the non-_DIRTY buffer case is not required
            */
            if( __flush( fp ) ) {
                // assume __flush set the errno value
                // if erroneous input, override errno value
                if( origin == SEEK_SET && offset < 0 ) {
                    _RWD_errno = EINVAL;
                }
                _ReleaseFile( fp );
                return( -1 );
            }
        } else {
            if( origin == SEEK_CUR ) {
                offset -= fp->_cnt;
            }
            fp->_ptr = _FP_BASE( fp );
            fp->_cnt = 0;
        }
        fp->_flag &= ~(_EOF|_UNGET);
#ifdef __INT64__
        if( _lseeki64( fileno( fp ), offset, origin ) == -1 ) {
#else
        if( lseek( fileno( fp ), offset, origin ) == -1 ) {
#endif
            _ReleaseFile( fp );
            return( -1 );
        }
    } else {
        // file is open for read only,
        // no characters have been ungotten
        // the OS file pointer is at fp->_ptr + fp->_cnt relative to the
        // FILE* buffer
        switch( origin ) {
        case SEEK_CUR:
        {
            long    ptr_delta = fp->_cnt;

            if( __update_buffer( offset, fp ) ) {
                offset -= ptr_delta;
#ifdef __INT64__
                if( _lseeki64( fileno( fp ), offset, origin ) == -1 ) {
#else
                if( lseek( fileno( fp ), offset, origin ) == -1 ) {
#endif
                    _ReleaseFile( fp );
                    return( -1 );
                }
                __reset_buffer(fp);
            }
        }   break;
        case SEEK_SET:
        {
#ifdef __INT64__
            long long   file_ptr = _telli64( fileno( fp ) );
#else
            long        file_ptr = tell( fileno( fp ) );
#endif

            file_ptr -= fp->_cnt;
            if( __update_buffer( offset - file_ptr, fp ) ) {
#ifdef __INT64__
                if( _lseeki64( fileno( fp ), offset, origin ) == -1 ) {
#else
                if( lseek( fileno( fp ), offset, origin ) == -1 ) {
#endif
                    _ReleaseFile( fp );
                    return( -1 );
                }
                __reset_buffer(fp);
            }
        }   break;
        case SEEK_END:
            __reset_buffer(fp);
#ifdef __INT64__
            if( _lseeki64( fileno( fp ), offset, origin ) == -1 ) {
#else
            if( lseek( fileno( fp ), offset, origin ) == -1 ) {
#endif
                _ReleaseFile( fp );
                return( -1 );
            }
            break;
        default:
            _RWD_errno = EINVAL;
            _ReleaseFile( fp );
            return( -1 );
        }
    }
    _ReleaseFile( fp );
    return( 0 );            /* indicate success */
}
Ejemplo n.º 20
0
static int ti_refresh( int must )
/*******************************/
{
    int         i;
    int         incr;               // chars per line
    LP_PIXEL    bufp, sbufp;        // buffer and shadow buffer
    LP_PIXEL    pos;                // the address of the current char
    LP_PIXEL    blankStart;         // start of spaces to eos and then complete
                                    // draw
    int         lastattr = -1;
    int         bufSize;
    LP_PIXEL    bufEnd;
    bool        cls = dirty_area.row1;   // line on which we should clr_eos
                                    // and then continue to draw
    bool        done = false;

    // Need these for startup and the refresh key
    if( UserForcedTermRefresh ) {
        // in the case where a user has forced a refresh we must assume
        // the screen is trashed, and so our cursor position is unknown
        OldCol = -1;
        OldRow = -1;
    }
    must |= UserForcedTermRefresh;
    UserForcedTermRefresh = false;

    // Move the cursor & return if dirty box contains no chars
    if( dirty_area.row0 == dirty_area.row1 && dirty_area.col0 == dirty_area.col1 ) {
        ti_hwcursor();
        __flush();
        return( 0 );
    }

    QNXDebugPrintf4( "ti_refresh( %d, %d )->( %d, %d )", dirty_area.row0,
                                    dirty_area.col0, dirty_area.row1, dirty_area.col1 );

    // Disable cursor during draw if we can
    if( UIData->cursor_type != C_OFF ) {
        TI_CURSOR_OFF();
    }

    // Get our new and old buffers
    bufp = UIData->screen.origin;
    sbufp = shadow;

    // Get some screen statistics
    bufSize = UIData->height * UIData->width;
    bufEnd = &UIData->screen.origin[bufSize - 1];
    incr = UIData->screen.increment;

    // Find a place where we could use clear to end of screen
    if( OptimizeTerminfo ) {
        blankStart = NonBlankEnd( bufEnd, bufSize, *bufEnd ) + 1;
    } else {
        blankStart = bufEnd;
    }

    if( blankStart <= UIData->screen.origin && TCAP_CLS ) {
        // if we could do it at the top then we might as well
        // not bother doing anything else
        lastattr = new_attr( UIData->screen.origin->attr, -1 );
        done = true;
    } else {
        lastattr = -1;

        if( !must ) {
            int         r,c;
            int         pos;
            bool        diff = false;

            while( dirty_area.col0 < dirty_area.col1 ) {
                for( r = dirty_area.row0; r < dirty_area.row1; r++ ) {
                    pos = r * incr + dirty_area.col0;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.col0++;
            }

            diff = false;
            while( dirty_area.col0 < dirty_area.col1 ) {
                for( r = dirty_area.row0; r < dirty_area.row1; r++ ) {
                    pos = r * incr + dirty_area.col1 - 1;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.col1--;
            }

            diff = false;
            while( dirty_area.row0 < dirty_area.row1 ) {
                for( c = dirty_area.col0; c < dirty_area.col1; c++ ) {
                    pos = dirty_area.row0 * incr + c;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.row0++;
            }

            diff = false;
            while( dirty_area.row0 < dirty_area.row1 ) {
                for( c = dirty_area.col0; c < dirty_area.col1; c++ ) {
                    pos = ( dirty_area.row1 - 1 ) * incr + c;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.row1--; 
            }
        }

        if( OptimizeTerminfo ) {
            // Set cls if drawing box is bottom part (or whole) of screen
            if( dirty_area.col0 == 0 &&
                dirty_area.row1 == UIData->height &&
                dirty_area.col1 == UIData->width &&
                TCAP_CLS ) {

                if( clr_eos[0] != '\0' ) {
                    cls = dirty_area.row0;
                } else if( dirty_area.row0 == 0 ) {
                    cls = 0;
                }
            }

            if( !must ) {
                // Adjust cls so refresh looks pretty
                for( ; cls < dirty_area.row1; cls++ ) {
                    int         pos;
                    int         pos2;

                    pos = cls * incr;
                    pos2 = pos + UIData->width - 1;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] )
                      && ( bufp[pos].ch != sbufp[pos2].ch
                      || bufp[pos].attr == sbufp[pos2].attr) ) {
                        break;
                    }
                }
            }

            /*
            if( cls < dirty_area.row1 ) {
                // If cls is set to by this point we've decided to clear the area
                blankStart = bufEnd;
            }
            */
        }
    }

    if( cls == 0 || ( TI_FillColourSet && blankStart < bufp && TCAP_CLS ) ) {
        // Clear the screen if cls is set to 0 or if the screen
        // is supposed to be blank
        if( cls == 0 ) {
            TI_RESTORE_COLOUR();
        }
        TI_CLS();
    } else {
        // we still have work to do if it turned out we couldn't use the
        // blank start after all
        done = false;
    }

    if( !done ) {
        // If the screen isn't completely blank we have to do some work
        int             j;
        bool            ca_valid;       // is cursor address valid?

        int             rcount;         // repeat count
        char            rchar;          // repeated character
        bool            ralt;           // if repeated character is in acs
        int             rcol;           // starting column of repeated chars

        bufp += dirty_area.row0 * incr;
        sbufp += dirty_area.row0 * incr;

        for( i = dirty_area.row0; i < dirty_area.row1; i++ ) {
            ca_valid = false;
            rcount = 0;

            if( i == cls ) {
                TI_RESTORE_COLOUR();
                TI_CURSOR_MOVE( 0, i );
                putp( clr_eos );
                ca_valid = true;
                //assert( dirty_area.col0==0 && dirty_area.col1==UIData->width );
            }

            for( j = dirty_area.col0; j < dirty_area.col1; j++ ) {
                pos = &bufp[j];
                if( !must && (
                    ( cls <= i )
                    ? ( bufp[j].ch == ' ' && ( (bufp[j].attr & 0x70) == 0 ) )
                    : ( PIXELEQUAL( bufp[j], sbufp[j] ) && pos <= blankStart ) ) ) {
                    ca_valid = false;
                    continue;
                }

                if( !ca_valid ) {
                    QNXDebugPrintf2( "cursor address %d, %d\n", j, i );

                    // gotta dump chars before we move
                    TI_DUMPCHARS();
                    TI_CURSOR_MOVE( j, i );
                    ca_valid = true;
                }

                if( bufp[j].attr != lastattr ) {
                    // dump before changing attrs too...
                    TI_DUMPCHARS();
                    lastattr = new_attr( bufp[j].attr, lastattr );
                }

                // Clear to end of screen if we can
                if( pos > blankStart ) {
                    if( TI_FillColourSet ) {
                        // Dump before blank to end of screen...
                        TI_DUMPCHARS();
                        putp( clr_eos );
                        update_shadow();
                        return( 0 );
                    } else {
                        pos = bufEnd;
                    }
                }

                if( !TI_ignore_bottom_right || (j != UIData->width - 1) || (i != UIData->height - 1) ) {
                    // slurp up the char
                    TI_SLURPCHAR( bufp[j].ch );
                    OldCol++;

                    // if we walk off the edge our position is undefined
                    if( OldCol >= UIData->width ) {
                        OldCol = -1;
                        OldRow = -1;
                    }
                }
            }
            // Make sure we dump any stragglers
            TI_DUMPCHARS();

            bufp += incr;
            sbufp += incr;
        }
    }

    update_shadow();
    return( 0 );
}