150276Speter/**************************************************************************** 2174993Srafan * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * lib_refresh.c 3750276Speter * 3850276Speter * The routines wrefresh() and wnoutrefresh(). 3950276Speter * 4050276Speter */ 4150276Speter 4250276Speter#include <curses.priv.h> 4350276Speter 44174993SrafanMODULE_ID("$Id: lib_refresh.c,v 1.41 2007/09/29 20:39:34 tom Exp $") 4550276Speter 4676726SpeterNCURSES_EXPORT(int) 4762449Speterwrefresh(WINDOW *win) 4850276Speter{ 4962449Speter int code; 5050276Speter 5162449Speter T((T_CALLED("wrefresh(%p)"), win)); 5250276Speter 53166124Srafan if (win == 0) { 54166124Srafan code = ERR; 55166124Srafan } else if (win == curscr) { 5662449Speter curscr->_clear = TRUE; 5762449Speter code = doupdate(); 5862449Speter } else if ((code = wnoutrefresh(win)) == OK) { 5962449Speter if (win->_clear) 6062449Speter newscr->_clear = TRUE; 6162449Speter code = doupdate(); 6262449Speter /* 6362449Speter * Reset the clearok() flag in case it was set for the special 6462449Speter * case in hardscroll.c (if we don't reset it here, we'll get 2 6562449Speter * refreshes because the flag is copied from stdscr to newscr). 6662449Speter * Resetting the flag shouldn't do any harm, anyway. 6762449Speter */ 6862449Speter win->_clear = FALSE; 6962449Speter } 7062449Speter returnCode(code); 7150276Speter} 7250276Speter 7376726SpeterNCURSES_EXPORT(int) 7462449Speterwnoutrefresh(WINDOW *win) 7550276Speter{ 7662449Speter NCURSES_SIZE_T limit_x; 77174993Srafan NCURSES_SIZE_T src_row, src_col; 7862449Speter NCURSES_SIZE_T begx; 7962449Speter NCURSES_SIZE_T begy; 80174993Srafan NCURSES_SIZE_T dst_row, dst_col; 8176726Speter#if USE_SCROLL_HINTS 8262449Speter bool wide; 8376726Speter#endif 8450276Speter 8562449Speter T((T_CALLED("wnoutrefresh(%p)"), win)); 8650276Speter#ifdef TRACE 87174993Srafan if (USE_TRACEF(TRACE_UPDATE)) { 8862449Speter _tracedump("...win", win); 89174993Srafan _nc_unlock_global(tracef); 90174993Srafan } 9150276Speter#endif /* TRACE */ 9250276Speter 9362449Speter /* 9462449Speter * This function will break badly if we try to refresh a pad. 9562449Speter */ 9662449Speter if ((win == 0) 9762449Speter || (win->_flags & _ISPAD)) 9862449Speter returnCode(ERR); 9950276Speter 10062449Speter /* put them here so "win == 0" won't break our code */ 10162449Speter begx = win->_begx; 10262449Speter begy = win->_begy; 10350276Speter 10497049Speter newscr->_nc_bkgd = win->_nc_bkgd; 105166124Srafan WINDOW_ATTRS(newscr) = WINDOW_ATTRS(win); 10650276Speter 10762449Speter /* merge in change information from all subwindows of this window */ 10862449Speter wsyncdown(win); 10950276Speter 11076726Speter#if USE_SCROLL_HINTS 11162449Speter /* 11262449Speter * For pure efficiency, we'd want to transfer scrolling information 11362449Speter * from the window to newscr whenever the window is wide enough that 11462449Speter * its update will dominate the cost of the update for the horizontal 11562449Speter * band of newscr that it occupies. Unfortunately, this threshold 11662449Speter * tends to be complex to estimate, and in any case scrolling the 11762449Speter * whole band and rewriting the parts outside win's image would look 11862449Speter * really ugly. So. What we do is consider the window "wide" if it 11962449Speter * either (a) occupies the whole width of newscr, or (b) occupies 12062449Speter * all but at most one column on either vertical edge of the screen 12162449Speter * (this caters to fussy people who put boxes around full-screen 12262449Speter * windows). Note that changing this formula will not break any code, 12362449Speter * merely change the costs of various update cases. 12462449Speter */ 12562449Speter wide = (begx <= 1 && win->_maxx >= (newscr->_maxx - 1)); 12676726Speter#endif 12750276Speter 12862449Speter win->_flags &= ~_HASMOVED; 12950276Speter 13062449Speter /* 13162449Speter * Microtweaking alert! This double loop is one of the genuine 13262449Speter * hot spots in the code. Even gcc doesn't seem to do enough 13362449Speter * common-subexpression chunking to make it really tense, 13462449Speter * so we'll force the issue. 13562449Speter */ 13650276Speter 137174993Srafan /* limit(dst_col) */ 13862449Speter limit_x = win->_maxx; 139174993Srafan /* limit(src_col) */ 140166124Srafan if (limit_x > newscr->_maxx - begx) 141166124Srafan limit_x = newscr->_maxx - begx; 14250276Speter 143174993Srafan for (src_row = 0, dst_row = begy + win->_yoffset; 144174993Srafan src_row <= win->_maxy && dst_row <= newscr->_maxy; 145174993Srafan src_row++, dst_row++) { 146174993Srafan register struct ldat *nline = &newscr->_line[dst_row]; 147174993Srafan register struct ldat *oline = &win->_line[src_row]; 14850276Speter 14962449Speter if (oline->firstchar != _NOCHANGE) { 150174993Srafan int last_src = oline->lastchar; 15150276Speter 152174993Srafan if (last_src > limit_x) 153174993Srafan last_src = limit_x; 15450276Speter 155174993Srafan src_col = oline->firstchar; 156174993Srafan dst_col = src_col + begx; 157174993Srafan 158174993Srafan if_WIDEC({ 159174993Srafan register int j; 160174993Srafan 161174993Srafan /* 162174993Srafan * Ensure that we will copy complete multi-column characters 163174993Srafan * on the left-boundary. 164174993Srafan */ 165174993Srafan if (isWidecExt(oline->text[src_col])) { 166174993Srafan j = 1 + dst_col - WidecExt(oline->text[src_col]); 167174993Srafan if (j < 0) 168174993Srafan j = 0; 169174993Srafan if (dst_col > j) { 170174993Srafan src_col -= (dst_col - j); 171174993Srafan dst_col = j; 172174993Srafan } 17350276Speter } 174174993Srafan 175174993Srafan /* 176174993Srafan * Ensure that we will copy complete multi-column characters 177174993Srafan * on the right-boundary. 178174993Srafan */ 179174993Srafan j = last_src; 180174993Srafan if (WidecExt(oline->text[j])) { 181174993Srafan ++j; 182174993Srafan while (j <= limit_x) { 183174993Srafan if (isWidecBase(oline->text[j])) { 184174993Srafan break; 185174993Srafan } else { 186174993Srafan last_src = j; 187174993Srafan } 188174993Srafan ++j; 189174993Srafan } 190174993Srafan } 191174993Srafan }); 192174993Srafan 193174993Srafan if_WIDEC({ 194174993Srafan static cchar_t blank = BLANK; 195174993Srafan int last_dst = begx + ((last_src < win->_maxx) 196174993Srafan ? last_src 197174993Srafan : win->_maxx); 198174993Srafan int fix_left = dst_col; 199174993Srafan int fix_right = last_dst; 200174993Srafan register int j; 201174993Srafan 202174993Srafan /* 203174993Srafan * Check for boundary cases where we may overwrite part of a 204174993Srafan * multi-column character. For those, wipe the remainder of 205174993Srafan * the character to blanks. 206174993Srafan */ 207174993Srafan j = dst_col; 208174993Srafan if (isWidecExt(nline->text[j])) { 209174993Srafan /* 210174993Srafan * On the left, we only care about multi-column characters 211174993Srafan * that extend into the changed region. 212174993Srafan */ 213174993Srafan fix_left = 1 + j - WidecExt(nline->text[j]); 214174993Srafan if (fix_left < 0) 215174993Srafan fix_left = 0; /* only if cell is corrupt */ 216174993Srafan } 217174993Srafan 218174993Srafan j = last_dst; 219174993Srafan if (WidecExt(nline->text[j]) != 0) { 220174993Srafan /* 221174993Srafan * On the right, any multi-column character is a problem, 222174993Srafan * unless it happens to be contained in the change, and 223174993Srafan * ending at the right boundary of the change. The 224174993Srafan * computation for 'fix_left' accounts for the left-side of 225174993Srafan * this character. Find the end of the character. 226174993Srafan */ 227174993Srafan ++j; 228174993Srafan while (j <= newscr->_maxx && isWidecExt(nline->text[j])) { 229174993Srafan fix_right = j++; 230174993Srafan } 231174993Srafan } 232174993Srafan 233174993Srafan /* 234174993Srafan * The analysis is simpler if we do the clearing afterwards. 235174993Srafan * Do that now. 236174993Srafan */ 237174993Srafan if (fix_left < dst_col || fix_right > last_dst) { 238174993Srafan for (j = fix_left; j <= fix_right; ++j) { 239174993Srafan nline->text[j] = blank; 240174993Srafan CHANGED_CELL(nline, j); 241174993Srafan } 242174993Srafan } 243174993Srafan }); 244174993Srafan 245174993Srafan /* 246174993Srafan * Copy the changed text. 247174993Srafan */ 248174993Srafan for (; src_col <= last_src; src_col++, dst_col++) { 249174993Srafan if (!CharEq(oline->text[src_col], nline->text[dst_col])) { 250174993Srafan nline->text[dst_col] = oline->text[src_col]; 251174993Srafan CHANGED_CELL(nline, dst_col); 252174993Srafan } 25362449Speter } 25450276Speter 25562449Speter } 25650276Speter#if USE_SCROLL_HINTS 25762449Speter if (wide) { 25862449Speter int oind = oline->oldindex; 25950276Speter 260174993Srafan nline->oldindex = ((oind == _NEWINDEX) 261174993Srafan ? _NEWINDEX 262174993Srafan : (begy + oind + win->_yoffset)); 26362449Speter } 26450276Speter#endif /* USE_SCROLL_HINTS */ 26550276Speter 26662449Speter oline->firstchar = oline->lastchar = _NOCHANGE; 267174993Srafan if_USE_SCROLL_HINTS(oline->oldindex = src_row); 26862449Speter } 26950276Speter 27062449Speter if (win->_clear) { 27162449Speter win->_clear = FALSE; 27262449Speter newscr->_clear = TRUE; 27362449Speter } 27450276Speter 27562449Speter if (!win->_leaveok) { 27662449Speter newscr->_cury = win->_cury + win->_begy + win->_yoffset; 27762449Speter newscr->_curx = win->_curx + win->_begx; 27862449Speter } 27962449Speter newscr->_leaveok = win->_leaveok; 28062449Speter 28150276Speter#ifdef TRACE 282174993Srafan if (USE_TRACEF(TRACE_UPDATE)) { 28362449Speter _tracedump("newscr", newscr); 284174993Srafan _nc_unlock_global(tracef); 285174993Srafan } 28650276Speter#endif /* TRACE */ 28762449Speter returnCode(OK); 28850276Speter} 289