curses scrolling
Mark Davoren
mark at munnari.OZ
Wed Jun 6 08:28:31 AEST 1984
[]
I didn't get the original question, only the replies.
I hope this is of interest to those who are trying to
beat curses into some sense of sanity.
I have recently finished developing a screen based version of
the CAI program "learn". It consists of two windows.
A set of instructions is displayed in the top window
then the user is put into the shell, editor, etc.
operating in the bottom window (like a ~12 line screen)
To do this properly the bottom window must scroll.
The following are some fixes I had to make to get everything
working.
All the programs displayed characters by using waddch
or derivatives like waddstr etc. This is then followed by a wrefresh.
I let waddch decide when to scroll the screen.
1) The following are two fixes to refresh.c version 1.8
This will fix the bug which stopped windows of width less than
the screen scrolling properly.
diff refresh.c $S/refresh.c
198c198
< /* scroll(win); */ /* mark */
---
> scroll(win);
201,202c201,202
< ly = win->_begy+win->_maxy-1; /* mark */
< lx = win->_begx+win->_maxx; /* mark */
---
> ly = win->_begy+win->_cury;
> lx = win->_begx+win->_curx;
2) Here is my copy of scroll.c (easier to give the source than a diff)
This version fixes the scrolling of curscr
and includes a quicky to see whether the delete line and insert line
facilities of the terminal can be used (if they exist).
Without this addition, scrolling windows is amazingly slow
since the whole window is redrawn. Refresh does not have enough
information to know when it can simply scroll a window. In addition
things would get very confused if refresh had to scroll and make
changes as well.
================================================================================
# include "curses.ext"
/*
* This routine scrolls the window up a line.
*
* 6/1/83 (Berkeley) @(#)scroll.c 1.3
*
* with bug fixes 20/5/84 Mark Davoren (Uni of Melbourne, Australia)
* with quicky using add line and delete line 1/6/84 "
*/
scroll(win)
reg WINDOW *win;
{
reg char *sp;
reg int i;
reg char *temp;
reg int tx;
if (!win->_scroll)
return ERR;
temp = win->_y[0];
for (i = 1; i < win->_maxy; i++)
win->_y[i - 1] = win->_y[i];
for (sp = temp; sp < &temp[win->_maxx]; )
*sp++ = ' ';
win->_y[win->_maxy - 1] = temp;
if (win == curscr) {
/* BUG FIX so that scrolling curscr works */
mvcur(win->_cury, win->_curx, win->_maxy-1, win->_curx);
/*
* Doing a newline whilst in the middle of the screen
* is not going to scroll the screen very much!
*/
putchar('\n'); /*
* Should make use of scroll forwards functions
* but only some terminals support it
* and I need it to work on all our terminals
*/
tx = win->_curx;
if (!NONL)
tx = 0;
/*
* If we were at the top of the screen
* don't go into hyperspace.
*/
if (win->_cury > 0)
win->_cury--;
mvcur(win->_maxy-1, tx, win->_cury, win->_curx);
# ifdef DEBUG
fprintf(outf, "SCROLL: win == curscr\n");
# endif
} else {
#ifdef DEBUG
fprintf(outf, "SCROLL: win [0%o] != curscr [0%o]\n",win,curscr);
#endif
if (AL && DL && win->_maxx == curscr->_maxx) {
# ifdef DEBUG
fprintf(outf, "SCROLL: shifting %d - %d (%d)\n"
, win->_begy
, win->_begy + win->_maxy
, curscr->_maxy
);
# endif
temp = curscr->_y[win->_begy];
for (i = win->_begy; i < win->_begy + win->_maxy; i++)
curscr->_y[i - 1] = curscr->_y[i];
for (sp = temp; sp < &temp[curscr->_maxx]; )
*sp++ = ' ';
curscr->_y[win->_begy + win->_maxy - 1] = temp;
mvcur(curscr->_cury, curscr->_curx, win->_begy, 0);
tputs(DL, 1, _putchar);
if (curscr->_cury > win->_begy
&& curscr->_cury < win->_begy + win->_maxy)
curscr->_cury--;
if (win->_begy + win->_maxy != curscr->_maxy) {
mvcur(win->_begy, 0, win->_begy+win->_maxy - 1, 0);
tputs(AL, 1, _putchar);
mvcur(win->_begy+win->_maxy - 1, 0, curscr->_cury, curscr->_curx);
} else
mvcur(win->_begy, 0, curscr->_cury, curscr->_curx);
}
}
touchwin(win);
return OK;
}
================================================================================
3) The following is a fix to addch.c (1.5) The call to refresh and
scroll are swapped. This is to avoid the situation where a character
has been placed in the bottom right hand corner of a window
which corresponds to the bottom right hand corner of the screen.
If refresh is called first then the char would be printed
and the terminal will automatically scroll (all the terminals we
use do) this of course upsets everything else on the screen, such
as the top window. By calling scroll first, no chars are ever written
into the bottom right hand corner and thus the terminal doesn't
do anything dumb.
diff addch.c $S/addch.c
48d47
< scroll(win);
49a49
> scroll(win);
4) Curses seems to have an identity crisis with cbreak mode
crmode() exists as separate to raw(), yet it still sets _rawmode.
This mucks up the innards of cr_put.c which use _rawmode
to decide whether it can do a newline without the ensuing carriage
return taking the cursor to column one.
This is a problem since whilst in cbreak mode, one can still
have newline mapping turned on, but not so in raw mode.
(This will only occur if it is quicker to do a newline than
do a cursor movement command)
So here are fixes to allow a proper crmode.
curses.c (1.2) curses.h (1.14) curses.ext (1.3)
diff curses.c $S/curses.c
10d9
< _crmode = FALSE,/* set if stty indicates CRMODE mode */
diff curses.h $S/curses.h
60,66c60
< extern bool My_term, _echoit, _crmode, _rawmode, _endwin;
< /*
< * CRMOD is not the same as RAW, therefore needs a different variable
< * to hold state info
< * In particular nl mapping is off in raw mode, but not necessarily
< * so in crmode mark.
< */
---
> extern bool My_term, _echoit, _rawmode, _endwin;
139,140c133,134
< #define crmode() (_tty.sg_flags |= CBREAK, _crmode = TRUE, stty(_tty_ch,&_tty))
< #define nocrmode() (_tty.sg_flags &= ~CBREAK,_crmode=FALSE,stty(_tty_ch,&_tty))
---
> #define crmode() (_tty.sg_flags |= CBREAK, _rawmode = TRUE, stty(_tty_ch,&_tty))
> #define nocrmode() (_tty.sg_flags &= ~CBREAK,_rawmode=FALSE,stty(_tty_ch,&_tty))
diff curses.ext $S/curses.ext
11c11
< extern bool _echoit, _rawmode, My_term, _endwin, _crmode;
---
> extern bool _echoit, _rawmode, My_term, _endwin;
I hope this has been of some use to all you out there in curses land
Mark Davoren
decvax!mulga!mark
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list