bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tty_update.c


From: Philippe Blain
Subject: tty_update.c
Date: Tue, 19 Nov 2002 07:34:18 +0100

>From Philippe Blain, Bordeaux, France.
My old computer: P133 - 8,4 Go - 32 Mo Red Hat Linux 7.0

To maintainers of 'ncurses'.(and to Mr Dickey)
Subject: Corrections for ncurses-5.3-20021116+

Here are some problems I found :

----------------------------------------------------------------------------
File : ncurses/base/tty_update.c
Function : ClearScreen ()

Think the sense of that function has been altered after code modification.
ClearScreen() must be seen as bounded to ClrUpdate().
In fact, it should be named '_nc_hard_clearscreen()'.

In 4.2, end of ClearScreen() was :
    } else {
        T(("cannot clear screen"));
        return;
    }

In 5.1, it was changed in:
    } else {
        UpdateAttrs(blank);
        for (i = 0; i < screen_lines; i++) {
            GoTo(i, 0);
            for (j = 0; j < screen_columns; j++)
                PutChar(blank);
        }
        GoTo(0, 0);
    }

Think the original purpose was to hard-clear the screen in black
with the capabilities clear_screen, clr_eos, or clr_eol.
If all these 3 capabilities were absent, do nothing, hard clear not done.
Nevermind because the function is considered as the first step of
ClrUpdate() where the screen is repainted from scratch.
After that step, lines are always color cleared by ClrBottom() and
displayed from 0 to nonempty by TransformLine().
It's just a visual effect before redrawn.

In 5.3, for the worse case, 24*80=1920 blanks are sended to clear the
physical screen, before the 1920 characters of newscr.
It's faster in that case to send the 1920 chars of newscr by doupdate()
directly and the screen has been redrawn entirely too without the visual
effect.

The 5.1 modif has introduced the lower right corner bug.
Before 4.2 included, what the function was doing was ok relative to
ClrUpdate(), probably its name do confusion after that.

Propose that :

static void ClearScreen (NCURSES_CH_T blank)
{
    int i, j;
    bool fast_clear = (clear_screen || clr_eos || clr_eol);

    TR (TRACE_UPDATE, ("ClearScreen() called"));

    /* Try to hard-clear the physical screen */
    if (fast_clear && can_clear_with(blank)) {
==>     UpdateAttrs (AttrOf (blank));
        if (clear_screen) {
            TPUTS_TRACE ("clear_screen");
            putp (clear_screen);
            SP->_cursrow = SP->_curscol = 0;
            position_check (SP->_cursrow, SP->_curscol, "ClearScreen");
        }
        else if (clr_eos) {
            SP->_cursrow = SP->_curscol = -1;
            GoTo (0, 0);

            TPUTS_TRACE ("clr_eos");
==>         tputs (clr_eos, screen_lines, _nc_outch); /* proportional
padding */
        }
        else if (clr_eol) {
            SP->_cursrow = SP->_curscol = -1;

==>         TPUTS_TRACE ("clr_eol");
            for (i = 0; i < screen_lines; i++) {
                GoTo (i, 0);
                putp (clr_eol);
            }
            GoTo (0, 0);
        }

        for (i = 0; i < screen_lines; i++) {
            for (j = 0; j < screen_columns; j++)
                curscr->_line[i].text[j] = blank;
        }
    }
==> else {
==>     T(("hard clearing of physical screen impossible"));
    }
    TR (TRACE_UPDATE, ("screen cleared"));
}

----------------------------------------------------------------------------
File : ncurses/base/tty_update.c
Function : ClrBottom ()

In ClrBottom(), why cheking if characters of CURSCR are 'blank' ?
==> What really matters is if chars of NEWSCR are 'blank'. That's all.
And ClrToEOS() blanks the bottom of curscr.

/* It's a hard-clear to EOL, too */
static void ClrToEOS (NCURSES_CH_T blank)
{
    int i, row, col;

    row = SP->_cursrow;
    col = SP->_curscol;

    UpdateAttrs (AttrOf (blank));
    if (clr_eos) {
==>     TPUTS_TRACE("clr_eos");
==>     tputs (clr_eos, screen_lines - row, _nc_outch);
==> } else if (clr_eol) {
==>     TPUTS_TRACE("clr_eol");
==>     putp(clr_eol);
==>     for (i = row + 1; i < screen_lines; i++) {
==>         GoTo(i, 0);
==>         putp(clr_eol);
==>     }
==>     GoTo(row, col);
    }

    while (col < screen_columns)
        curscr->_line[row].text[col++] = blank;

    for (row++; row < screen_lines; row++) {
        for (col = 0; col < screen_columns; col++)
            curscr->_line[row].text[col] = blank;
    }
}

static int ClrBottom (int total)
{
    int row;
    int col;
    int top = total;
    int last = min (screen_columns, newscr->_maxx + 1);
    NCURSES_CH_T blank = ClrBlank (stdscr);
    bool ok;

==> if ((clr_eos || clr_eol) && can_clear_with (CHREF (blank))) {

        for (row = total - 1; row >= 0; row--) {
            for (col = 0, ok = TRUE; ok && col < last; col++) {
                ok = (CharEq (newscr->_line[row].text[col], blank));
            }
            if (!ok) break;
==>         top = row;
        }

==>     if (top < total) {
            GoTo (top, 0);
            ClrToEOS (blank);
            if (SP->oldhash && SP->newhash) {
                for (row = top; row < screen_lines; row++)
                    SP->oldhash[row] = SP->newhash[row];
            }
        }
    }
==> return (top);
}

----------------------------------------------------------------------------
File : ncurses/base/tty_update.c
Function : ClrBlank ()

The function returns a space with background attribs or not.
If the terminal has NOT bce (9/10e of terminfo entries), returns the
nude space character.

static inline NCURSES_CH_T ClrBlank(WINDOW *win)
{
    NCURSES_CH_T blank = NewChar(BLANK_TEXT);
    if (back_color_erase)
        AddAttr(blank, (AttrOf(BCE_BKGD(win)) & BCE_ATTRS));
    return blank;
}

This is not logical.
How can I clear a window with background with such a character on a
non-bce terminal ?  All background attributes are lost for a non-bce.

Should return the space with background color in all cases.
We then compare lines with that character to see if they are blank
or not. When we 'can_clear_with(that_char)', terminfo sequences
are safe to emit.

It's in 'can_clear_with()' that the test bce/non-bce must be.

----------------------------------------------------------------------------
File : ncurses/base/tty_update.c
Function : check_pending ()

SUGGESTION:
It's possible to use '_nc_timed_wait()' in 'check_pending()' by just
adding another case (mode = 8) to _nc_timed_wait() checking if
input on SP->_checkfd.
This simplify the source and provide a better support by having all wait
code in lib_twait.c

static bool check_pending (void)     /* check for pending input */
{
    bool have_pending = FALSE;
    int tleft;

    /*
     * Only carry out this check when the flag is zero, otherwise we'll
     * have the refreshing slow down drastically (or stop) if there's an
     * unread character available.
     */
    if (SP->_fifohold != 0) return FALSE;

    if (SP->_checkfd >= 0) {
==>     if (_nc_timed_wait (8, 0, &tleft EVENTLIST_2nd(0)) > 0)
            have_pending = TRUE;
    }
    if (have_pending) {
        SP->_fifohold = 5;
        _nc_flush ();
    }
    return FALSE;
}


----------------------------------------------------------------------------
- Philippe






reply via email to

[Prev in Thread] Current Thread [Next in Thread]