mark@munnari.OZ (Mark Davoren) (06/06/84)
[] 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