1 /* $OpenBSD: lib_scroll.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ 2 3 /**************************************************************************** 4 * Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * 5 * * 6 * Permission is hereby granted, free of charge, to any person obtaining a * 7 * copy of this software and associated documentation files (the * 8 * "Software"), to deal in the Software without restriction, including * 9 * without limitation the rights to use, copy, modify, merge, publish, * 10 * distribute, distribute with modifications, sublicense, and/or sell * 11 * copies of the Software, and to permit persons to whom the Software is * 12 * furnished to do so, subject to the following conditions: * 13 * * 14 * The above copyright notice and this permission notice shall be included * 15 * in all copies or substantial portions of the Software. * 16 * * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 24 * * 25 * Except as contained in this notice, the name(s) of the above copyright * 26 * holders shall not be used in advertising or otherwise to promote the * 27 * sale, use or other dealings in this Software without prior written * 28 * authorization. * 29 ****************************************************************************/ 30 31 /**************************************************************************** 32 * Author: Thomas E. Dickey 1996-2003 * 33 * and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 34 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 35 ****************************************************************************/ 36 37 /* 38 ** lib_scroll.c 39 ** 40 ** The routine wscrl(win, n). 41 ** positive n scroll the window up (ie. move lines down) 42 ** negative n scroll the window down (ie. move lines up) 43 ** 44 */ 45 46 #include <curses.priv.h> 47 48 MODULE_ID("$Id: lib_scroll.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") 49 50 NCURSES_EXPORT(void) 51 _nc_scroll_window(WINDOW *win, 52 int const n, 53 NCURSES_SIZE_T const top, 54 NCURSES_SIZE_T const bottom, 55 NCURSES_CH_T blank) 56 { 57 int limit; 58 int line; 59 int j; 60 size_t to_copy = (size_t) (sizeof(NCURSES_CH_T) * (win->_maxx + 1)); 61 62 TR(TRACE_MOVE, ("_nc_scroll_window(%p, %d, %ld, %ld)", 63 win, n, (long) top, (long) bottom)); 64 65 if (top < 0 66 || bottom < top 67 || bottom > win->_maxy) { 68 TR(TRACE_MOVE, ("nothing to scroll")); 69 return; 70 } 71 72 /* 73 * This used to do a line-text pointer-shuffle instead of text copies. 74 * That (a) doesn't work when the window is derived and doesn't have 75 * its own storage, (b) doesn't save you a lot on modern machines 76 * anyway. Your typical memcpy implementations are coded in 77 * assembler using a tight BLT loop; for the size of copies we're 78 * talking here, the total execution time is dominated by the one-time 79 * setup cost. So there is no point in trying to be excessively 80 * clever -- esr. 81 */ 82 83 /* shift n lines downwards */ 84 if (n < 0) { 85 limit = top - n; 86 for (line = bottom; line >= limit && line >= 0; line--) { 87 TR(TRACE_MOVE, ("...copying %d to %d", line + n, line)); 88 memcpy(win->_line[line].text, 89 win->_line[line + n].text, 90 to_copy); 91 if_USE_SCROLL_HINTS(win->_line[line].oldindex = 92 win->_line[line + n].oldindex); 93 } 94 for (line = top; line < limit && line <= win->_maxy; line++) { 95 TR(TRACE_MOVE, ("...filling %d", line)); 96 for (j = 0; j <= win->_maxx; j++) 97 win->_line[line].text[j] = blank; 98 if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX); 99 } 100 } 101 102 /* shift n lines upwards */ 103 if (n > 0) { 104 limit = bottom - n; 105 for (line = top; line <= limit && line <= win->_maxy; line++) { 106 memcpy(win->_line[line].text, 107 win->_line[line + n].text, 108 to_copy); 109 if_USE_SCROLL_HINTS(win->_line[line].oldindex = 110 win->_line[line + n].oldindex); 111 } 112 for (line = bottom; line > limit && line >= 0; line--) { 113 for (j = 0; j <= win->_maxx; j++) 114 win->_line[line].text[j] = blank; 115 if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX); 116 } 117 } 118 touchline(win, top, bottom - top + 1); 119 120 if_WIDEC({ 121 if (WINDOW_EXT(win, addch_used) != 0) { 122 int next = WINDOW_EXT(win, addch_y) + n; 123 if (next < 0 || next > win->_maxy) { 124 TR(TRACE_VIRTPUT, 125 ("Alert discarded multibyte on scroll")); 126 WINDOW_EXT(win, addch_y) = 0; 127 } else { 128 TR(TRACE_VIRTPUT, ("scrolled working position to %d,%d", 129 WINDOW_EXT(win, addch_y), 130 WINDOW_EXT(win, addch_x))); 131 WINDOW_EXT(win, addch_y) = next; 132 } 133 } 134 }) 135 } 136 137 NCURSES_EXPORT(int) 138 wscrl(WINDOW *win, int n) 139 { 140 T((T_CALLED("wscrl(%p,%d)"), win, n)); 141 142 if (!win || !win->_scroll) { 143 TR(TRACE_MOVE, ("...scrollok is false")); 144 returnCode(ERR); 145 } 146 147 if (n != 0) { 148 _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd); 149 _nc_synchook(win); 150 } 151 returnCode(OK); 152 } 153