/* _tty_upd.c ********** Copyright 1985-1996 by Vermont Creative Software ********** _tty_upd() Updates the video display Call #include void _tty_upd(rb, cb, re, ce) int rb; Beginning row to update int cb; Beginning column to update int re; Ending row to update int ce; Ending column to update Returns None Description _tty_upd() positions the cursor to the point on the screen where the update is to begin. The character information from the virtual video buffer is copied to the screen. Video attributes are changed when necessary. The function terminates when the designated end point is reached. The screen updating algorithm makes use of a second buffer (_scr_buf). _scr_buf is a copy of what actually is displayed on the screen. The virtual video buffer is compared against _scr_buf and only the differences are sent to the screen. The advantage is that the minimum characters necessary to update the screen are sent to the terminal. The disadvantage is that we keep a second copy of the virtual video buffer (approx 4000 bytes) and use a little more processing time. HP support is provided by conditional code. When _tshp is 1 _tty_upd will not look at _scr_buf for attributes. This is due to hp block mode terminals keeping track of turn on and turn off locations. */ #include #include #include #include #define PUTCHAR(x) _vv_putchar(x) #if OLD_STYLE void FASTCALL _tty_upd(rb, cb, re, ce) int rb; int cb; int re; int ce; #else void FASTCALL _tty_upd(int rb, int cb, int re, int ce) #endif { UCHAR ch; UCHAR att; UCHAR pratt; UCHAR hold; UCHAR hold1; UCHAR * sc_ptr; UCHAR FAR * back_ptr; UCHAR * scrw_ptr; UCHAR FAR * row_ptr; UCHAR FAR * ch_ptr; int bytes_row; int offset; int last_row; int last_col; int tvid_echo; int tr; int tc; int csr_dif; int wrotesome = 0; register int j; register int k; register int i; tr = _csr_row; /*save current cursor position */ tc = _csr_col; tvid_echo = VID_ECHO; /*save current value */ VID_ECHO = ON; /*lower level func need VID_ECHO ON */ last_row = vs_rowq() - 1; /*initialize */ last_col = vs_colq() - 1; if (_tshp) ce = last_col; /*for hp only; ce is set to max col */ bytes_row = vs_colq() * 2; /*number of bytes per row */ offset = (rb * vs_colq() + cb) * 2; scrw_ptr = _scr_buf + offset; row_ptr = _vid_scr.vbufp + offset; /*determine cursor difference from the*/ /*starting position. If on different */ /*row, then csr_dif = -9999 */ csr_dif = (rb == _csr_row) ? (cb - _csr_col) : -9999; for (i = rb; i <= re; i++) /*for all rows */ { ch_ptr = row_ptr; /*initialize working pointers */ sc_ptr = scrw_ptr; /*if the terminal scrolls then we */ /*cannot write to the last column */ /*on the screen, therefore, we make */ /*the last row one character shorter */ if (ce == last_col && i == last_row && _tscrl ) --ce; for (j = cb; j <= ce; j++) /*loop for all columns on this row */ { ch = *ch_ptr; att = *(ch_ptr + 1); if (_tshp) hold = _cur_att; else hold = *(sc_ptr + 1); if (_tshp) hold1 = (*sc_ptr == ' ' && ch == ' ' && att != *(sc_ptr + 1)); else hold1 = 0; if (*sc_ptr != ch || hold != att || hold1 || _force) /*is char in v_vrb different */ { /*from screen */ if (!wrotesome && _keyloopfp) fcntl(0, F_SETFL, _kb_flags & ~O_NDELAY); wrotesome = 1; if (csr_dif) /*if csr in improper position*/ { if (csr_dif > 0 && csr_dif < _min_cm) /* a few columns off */ { if (_tshp) back_ptr = ch_ptr - 2 * csr_dif; else back_ptr = sc_ptr - 2 * csr_dif ; /*print all chars to current pos */ /******************************************************************************/ /*the hp terms do not use the stream of data as other terms do. The hp is */ /*position dependent. Thus each time we move our focus within the screen we */ /*have to find what the current attribue is and set _cur_att */ /******************************************************************************/ if (_tshp) _cur_att = ((j - csr_dif) == 0) ? NORMAL : *(back_ptr - 1); for (k = csr_dif; k; k--, back_ptr += 2) { if ((pratt = *(back_ptr + 1)) != _cur_att) /*if different att */ _vsatt_set(pratt); /*set new video att */ if (pratt == INVISIBLE) PUTCHAR(' '); else PUTCHAR(*back_ptr); } _csr_col += csr_dif; } else _csr_mv(i, j); /*use "slow" move */ /******************************************************************************/ /* hp term specific code */ /******************************************************************************/ if (_tshp) { _cur_att = (j == 0) ? NORMAL : *(_vid_scr.vbufp + (i * vs_colq() + j) * 2 - 1); _puts_pad(_scr_cmd[LNE_CLEAR], 1); for (k = (i * vs_colq() + j) * 2; k < (i + 1) * vs_colq() * 2; k += 2) { *(_scr_buf + k) = ' '; *(_scr_buf + k + 1) = NORMAL; } } } *sc_ptr = ch; /* update the screen buffer */ *(sc_ptr + 1) = att; if (att != _cur_att) /*if different att */ _vsatt_set(att); /*set new video att */ if (att == INVISIBLE) PUTCHAR(' '); else PUTCHAR(ch); _csr_col++; csr_dif = 0; } else csr_dif++; ch_ptr += 2; sc_ptr += 2; } row_ptr += bytes_row; /*move row_ptr to next row */ scrw_ptr += bytes_row; csr_dif = -9999; } if (_frz_csr == FALSE) _csr_mv(tr, tc); /*restore cursor to original position */ VID_ECHO = tvid_echo; /*restore value */ _vv_flush(); /*Flush output */ if (wrotesome && _keyloopfp) fcntl(0, F_SETFL, _kb_flags); return; }