Back to index

tetex-bin  3.0
lib_pad.c
Go to the documentation of this file.
00001 /****************************************************************************
00002  * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc.                   *
00003  *                                                                          *
00004  * Permission is hereby granted, free of charge, to any person obtaining a  *
00005  * copy of this software and associated documentation files (the            *
00006  * "Software"), to deal in the Software without restriction, including      *
00007  * without limitation the rights to use, copy, modify, merge, publish,      *
00008  * distribute, distribute with modifications, sublicense, and/or sell       *
00009  * copies of the Software, and to permit persons to whom the Software is    *
00010  * furnished to do so, subject to the following conditions:                 *
00011  *                                                                          *
00012  * The above copyright notice and this permission notice shall be included  *
00013  * in all copies or substantial portions of the Software.                   *
00014  *                                                                          *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00018  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00021  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00022  *                                                                          *
00023  * Except as contained in this notice, the name(s) of the above copyright   *
00024  * holders shall not be used in advertising or otherwise to promote the     *
00025  * sale, use or other dealings in this Software without prior written       *
00026  * authorization.                                                           *
00027  ****************************************************************************/
00028 
00029 /****************************************************************************
00030  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
00031  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
00032  ****************************************************************************/
00033 
00034 /*
00035  * lib_pad.c
00036  * newpad     -- create a new pad
00037  * pnoutrefresh -- refresh a pad, no update
00038  * pechochar  -- add a char to a pad and refresh
00039  */
00040 
00041 #include <curses.priv.h>
00042 
00043 MODULE_ID("$Id: lib_pad.c,v 1.38 2002/08/03 23:29:26 Philippe.Blain Exp $")
00044 
00045 NCURSES_EXPORT(WINDOW *)
00046 newpad(int l, int c)
00047 {
00048     WINDOW *win;
00049     NCURSES_CH_T *ptr;
00050     int i;
00051 
00052     T((T_CALLED("newpad(%d, %d)"), l, c));
00053 
00054     if (l <= 0 || c <= 0)
00055        returnWin(0);
00056 
00057     if ((win = _nc_makenew(l, c, 0, 0, _ISPAD)) == NULL)
00058        returnWin(0);
00059 
00060     for (i = 0; i < l; i++) {
00061        if_USE_SCROLL_HINTS(win->_line[i].oldindex = _NEWINDEX);
00062        if ((win->_line[i].text = typeCalloc(NCURSES_CH_T, ((size_t) c))) == 0) {
00063            (void) _nc_freewin(win);
00064            returnWin(0);
00065        }
00066        for (ptr = win->_line[i].text; ptr < win->_line[i].text + c; ptr++)
00067            SetChar(*ptr, BLANK_TEXT, BLANK_ATTR);
00068     }
00069 
00070     returnWin(win);
00071 }
00072 
00073 NCURSES_EXPORT(WINDOW *)
00074 subpad
00075 (WINDOW *orig, int l, int c, int begy, int begx)
00076 {
00077     WINDOW *win = (WINDOW *) 0;
00078 
00079     T((T_CALLED("subpad(%d, %d)"), l, c));
00080 
00081     if (orig) {
00082        if (!(orig->_flags & _ISPAD)
00083            || ((win = derwin(orig, l, c, begy, begx)) == NULL))
00084            returnWin(0);
00085     }
00086     returnWin(win);
00087 }
00088 
00089 NCURSES_EXPORT(int)
00090 prefresh
00091 (WINDOW *win, int pminrow, int pmincol,
00092  int sminrow, int smincol, int smaxrow, int smaxcol)
00093 {
00094     T((T_CALLED("prefresh()")));
00095     if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow,
00096                    smaxcol) != ERR
00097        && doupdate() != ERR) {
00098        returnCode(OK);
00099     }
00100     returnCode(ERR);
00101 }
00102 
00103 NCURSES_EXPORT(int)
00104 pnoutrefresh
00105 (WINDOW *win, int pminrow, int pmincol,
00106  int sminrow, int smincol, int smaxrow, int smaxcol)
00107 {
00108     NCURSES_SIZE_T i, j;
00109     NCURSES_SIZE_T m, n;
00110     NCURSES_SIZE_T pmaxrow;
00111     NCURSES_SIZE_T pmaxcol;
00112 
00113 #if USE_SCROLL_HINTS
00114     const int my_len = 2;   /* parameterize the threshold for hardscroll */
00115     NCURSES_SIZE_T displaced;
00116     bool wide;
00117 #endif
00118 
00119     T((T_CALLED("pnoutrefresh(%p, %d, %d, %d, %d, %d, %d)"),
00120        win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol));
00121 
00122     if (win == 0)
00123        returnCode(ERR);
00124 
00125     if (!(win->_flags & _ISPAD))
00126        returnCode(ERR);
00127 
00128     /* negative values are interpreted as zero */
00129     if (pminrow < 0)
00130        pminrow = 0;
00131     if (pmincol < 0)
00132        pmincol = 0;
00133     if (sminrow < 0)
00134        sminrow = 0;
00135     if (smincol < 0)
00136        smincol = 0;
00137 
00138     pmaxrow = pminrow + smaxrow - sminrow;
00139     pmaxcol = pmincol + smaxcol - smincol;
00140 
00141     T((" pminrow + smaxrow - sminrow %d, win->_maxy %d", pmaxrow, win->_maxy));
00142     T((" pmincol + smaxcol - smincol %d, win->_maxx %d", pmaxcol, win->_maxx));
00143 
00144     /*
00145      * Trim the caller's screen size back to the actual limits.
00146      */
00147     if (pmaxrow > win->_maxy) {
00148        smaxrow -= (pmaxrow - win->_maxy);
00149        pmaxrow = pminrow + smaxrow - sminrow;
00150     }
00151     if (pmaxcol > win->_maxx) {
00152        smaxcol -= (pmaxcol - win->_maxx);
00153        pmaxcol = pmincol + smaxcol - smincol;
00154     }
00155 
00156     if (smaxrow >= screen_lines
00157        || smaxcol >= screen_columns
00158        || sminrow > smaxrow
00159        || smincol > smaxcol)
00160        returnCode(ERR);
00161 
00162     T(("pad being refreshed"));
00163 
00164 #if USE_SCROLL_HINTS
00165     if (win->_pad._pad_y >= 0) {
00166        displaced = pminrow - win->_pad._pad_y
00167            - (sminrow - win->_pad._pad_top);
00168        T(("pad being shifted by %d line(s)", displaced));
00169     } else
00170        displaced = 0;
00171 #endif
00172 
00173     /*
00174      * For pure efficiency, we'd want to transfer scrolling information
00175      * from the pad to newscr whenever the window is wide enough that
00176      * its update will dominate the cost of the update for the horizontal
00177      * band of newscr that it occupies.  Unfortunately, this threshold
00178      * tends to be complex to estimate, and in any case scrolling the
00179      * whole band and rewriting the parts outside win's image would look
00180      * really ugly.  So.  What we do is consider the pad "wide" if it
00181      * either (a) occupies the whole width of newscr, or (b) occupies
00182      * all but at most one column on either vertical edge of the screen
00183      * (this caters to fussy people who put boxes around full-screen
00184      * windows).  Note that changing this formula will not break any code,
00185      * merely change the costs of various update cases.
00186      */
00187 #if USE_SCROLL_HINTS
00188     wide = (smincol < my_len && smaxcol > (newscr->_maxx - my_len));
00189 #endif
00190 
00191     for (i = pminrow, m = sminrow + win->_yoffset;
00192         i <= pmaxrow && m <= newscr->_maxy;
00193         i++, m++) {
00194        register struct ldat *nline = &newscr->_line[m];
00195        register struct ldat *oline = &win->_line[i];
00196        for (j = pmincol, n = smincol; j <= pmaxcol; j++, n++) {
00197            NCURSES_CH_T ch = oline->text[j];
00198 #if USE_WIDEC_SUPPORT
00199            /*
00200             * Special case for leftmost character of the displayed area.
00201             * Only half of a double-width character may be visible.
00202             */
00203            if (j == pmincol
00204               && j > 0
00205               && isnac(ch)) {
00206               SetChar(ch, L(' '), AttrOf(oline->text[j - 1]));
00207            }
00208 #endif
00209            if (!CharEq(ch, nline->text[n])) {
00210               nline->text[n] = ch;
00211               CHANGED_CELL(nline, n);
00212            }
00213        }
00214 
00215 #if USE_SCROLL_HINTS
00216        if (wide) {
00217            int nind = m + displaced;
00218            if (oline->oldindex < 0
00219               || nind < sminrow
00220               || nind > smaxrow) {
00221               nind = _NEWINDEX;
00222            } else if (displaced) {
00223               register struct ldat *pline = &curscr->_line[nind];
00224               for (j = 0; j <= my_len; j++) {
00225                   int k = newscr->_maxx - j;
00226                   if (pline->text[j] != nline->text[j]
00227                      || pline->text[k] != nline->text[k]) {
00228                      nind = _NEWINDEX;
00229                      break;
00230                   }
00231               }
00232            }
00233 
00234            nline->oldindex = nind;
00235        }
00236 #endif /* USE_SCROLL_HINTS */
00237        oline->firstchar = oline->lastchar = _NOCHANGE;
00238        if_USE_SCROLL_HINTS(oline->oldindex = i);
00239     }
00240 
00241     /*
00242      * Clean up debris from scrolling or resizing the pad, so we do not
00243      * accidentally pick up the index value during the next call to this
00244      * procedure.  The only rows that should have an index value are those
00245      * that are displayed during this cycle.
00246      */
00247 #if USE_SCROLL_HINTS
00248     for (i = pminrow - 1; (i >= 0) && (win->_line[i].oldindex >= 0); i--)
00249        win->_line[i].oldindex = _NEWINDEX;
00250     for (i = pmaxrow + 1; (i <= win->_maxy)
00251         && (win->_line[i].oldindex >= 0); i++)
00252        win->_line[i].oldindex = _NEWINDEX;
00253 #endif
00254 
00255     win->_begx = smincol;
00256     win->_begy = sminrow;
00257 
00258     if (win->_clear) {
00259        win->_clear = FALSE;
00260        newscr->_clear = TRUE;
00261     }
00262 
00263     /*
00264      * Use the pad's current position, if it will be visible.
00265      * If not, don't do anything; it's not an error.
00266      */
00267     if (win->_leaveok == FALSE
00268        && win->_cury >= pminrow
00269        && win->_curx >= pmincol
00270        && win->_cury <= pmaxrow
00271        && win->_curx <= pmaxcol) {
00272        newscr->_cury = win->_cury - pminrow + win->_begy + win->_yoffset;
00273        newscr->_curx = win->_curx - pmincol + win->_begx;
00274     }
00275     newscr->_leaveok = win->_leaveok;
00276     win->_flags &= ~_HASMOVED;
00277 
00278     /*
00279      * Update our cache of the line-numbers that we displayed from the pad.
00280      * We will use this on subsequent calls to this function to derive
00281      * values to stuff into 'oldindex[]' -- for scrolling optimization.
00282      */
00283     win->_pad._pad_y = pminrow;
00284     win->_pad._pad_x = pmincol;
00285     win->_pad._pad_top = sminrow;
00286     win->_pad._pad_left = smincol;
00287     win->_pad._pad_bottom = smaxrow;
00288     win->_pad._pad_right = smaxcol;
00289 
00290     returnCode(OK);
00291 }
00292 
00293 NCURSES_EXPORT(int)
00294 pechochar(WINDOW *pad, const chtype ch)
00295 {
00296     T((T_CALLED("pechochar(%p, %s)"), pad, _tracechtype(ch)));
00297 
00298     if (pad == 0)
00299        returnCode(ERR);
00300 
00301     if (!(pad->_flags & _ISPAD))
00302        returnCode(wechochar(pad, ch));
00303 
00304     waddch(pad, ch);
00305     prefresh(pad, pad->_pad._pad_y,
00306             pad->_pad._pad_x,
00307             pad->_pad._pad_top,
00308             pad->_pad._pad_left,
00309             pad->_pad._pad_bottom,
00310             pad->_pad._pad_right);
00311 
00312     returnCode(OK);
00313 }