1 /* $NetBSD: addbytes.c,v 1.27 2003/07/31 10:36:00 dsl Exp $ */ 2 3 /* 4 * Copyright (c) 1987, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94"; 40 #else 41 __RCSID("$NetBSD: addbytes.c,v 1.27 2003/07/31 10:36:00 dsl Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include "curses.h" 46 #include "curses_private.h" 47 #ifdef DEBUG 48 #include <assert.h> 49 #endif 50 51 #define SYNCH_IN {y = win->cury; x = win->curx;} 52 #define SYNCH_OUT {win->cury = y; win->curx = x;} 53 54 #ifndef _CURSES_USE_MACROS 55 56 /* 57 * addbytes -- 58 * Add the character to the current position in stdscr. 59 */ 60 int 61 addbytes(const char *bytes, int count) 62 { 63 return __waddbytes(stdscr, bytes, count, 0); 64 } 65 66 /* 67 * waddbytes -- 68 * Add the character to the current position in the given window. 69 */ 70 int 71 waddbytes(WINDOW *win, const char *bytes, int count) 72 { 73 return __waddbytes(win, bytes, count, 0); 74 } 75 76 /* 77 * mvaddbytes -- 78 * Add the characters to stdscr at the location given. 79 */ 80 int 81 mvaddbytes(int y, int x, const char *bytes, int count) 82 { 83 return mvwaddbytes(stdscr, y, x, bytes, count); 84 } 85 86 /* 87 * mvwaddbytes -- 88 * Add the characters to the given window at the location given. 89 */ 90 int 91 mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) 92 { 93 if (wmove(win, y, x) == ERR) 94 return ERR; 95 96 return __waddbytes(win, bytes, count, 0); 97 } 98 99 #endif 100 101 /* 102 * waddbytes -- 103 * Add the character to the current position in the given window. 104 */ 105 int 106 __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) 107 { 108 static char blanks[] = " "; 109 int c, newx, x, y; 110 attr_t attributes; 111 __LINE *lp; 112 #ifdef DEBUG 113 int i; 114 115 for (i = 0; i < win->maxy; i++) { 116 assert(win->lines[i]->sentinel == SENTINEL_VALUE); 117 } 118 #endif 119 120 SYNCH_IN; 121 lp = win->lines[y]; 122 123 while (count--) { 124 c = *bytes++; 125 #ifdef DEBUG 126 __CTRACE("ADDBYTES('%c', %x) at (%d, %d)\n", c, attr, y, x); 127 #endif 128 switch (c) { 129 case '\t': 130 SYNCH_OUT; 131 if (waddbytes(win, blanks, 8 - (x % 8)) == ERR) 132 return (ERR); 133 SYNCH_IN; 134 break; 135 136 default: 137 #ifdef DEBUG 138 __CTRACE("ADDBYTES(%p, %d, %d)\n", win, y, x); 139 #endif 140 141 if (lp->flags & __ISPASTEOL) { 142 x = 0; 143 newline: 144 lp->flags &= ~(__ISPASTEOL | __ISAFTERCR); 145 if (y == win->scr_b) { 146 #ifdef DEBUG 147 __CTRACE("ADDBYTES - on bottom " 148 "of scrolling region\n"); 149 #endif 150 if (!(win->flags & __SCROLLOK)) 151 return ERR; 152 SYNCH_OUT; 153 scroll(win); 154 SYNCH_IN; 155 } else { 156 y++; 157 } 158 lp = win->lines[y]; 159 if (c == '\n') 160 break; 161 } 162 163 attributes = (win->wattr | attr) & 164 (__ATTRIBUTES & ~__COLOR); 165 if (attr & __COLOR) 166 attributes |= attr & __COLOR; 167 else if (win->wattr & __COLOR) 168 attributes |= win->wattr & __COLOR; 169 #ifdef DEBUG 170 __CTRACE("ADDBYTES: 1: y = %d, x = %d, firstch = %d, " 171 "lastch = %d\n", 172 y, x, *win->lines[y]->firstchp, 173 *win->lines[y]->lastchp); 174 #endif 175 /* 176 * Always update the change pointers. Otherwise, 177 * we could end up not displaying 'blank' characters 178 * when overlapping windows are displayed. 179 */ 180 newx = x + win->ch_off; 181 lp->flags |= __ISDIRTY; 182 /* 183 * firstchp/lastchp are shared between 184 * parent window and sub-window. 185 */ 186 if (newx < *lp->firstchp) 187 *lp->firstchp = newx; 188 if (newx > *lp->lastchp) 189 *lp->lastchp = newx; 190 #ifdef DEBUG 191 __CTRACE("ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", 192 *lp->firstchp, *lp->lastchp, 193 *lp->firstchp - win->ch_off, 194 *lp->lastchp - win->ch_off); 195 #endif 196 lp->line[x].ch = c; 197 lp->line[x].bch = win->bch; 198 lp->line[x].attr = attributes; 199 lp->line[x].battr = win->battr; 200 if (x == win->maxx - 1) 201 lp->flags |= __ISPASTEOL; 202 else 203 x++; 204 #ifdef DEBUG 205 __CTRACE("ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n", 206 y, x, *win->lines[y]->firstchp, 207 *win->lines[y]->lastchp); 208 #endif 209 break; 210 case '\n': 211 if (!(lp->flags & (__ISPASTEOL | __ISAFTERCR))) { 212 SYNCH_OUT; 213 wclrtoeol(win); 214 SYNCH_IN; 215 } 216 if (!__NONL) 217 x = 0; 218 goto newline; 219 case '\r': 220 if (!(lp->flags & __ISAFTERCR)) { 221 SYNCH_OUT; 222 wclrtoeol(win); 223 SYNCH_IN; 224 } 225 x = 0; 226 lp->flags |= __ISAFTERCR; 227 continue; 228 case '\b': 229 if (--x < 0) 230 x = 0; 231 break; 232 } 233 lp->flags &= ~__ISAFTERCR; 234 } 235 SYNCH_OUT; 236 237 #ifdef DEBUG 238 for (i = 0; i < win->maxy; i++) { 239 assert(win->lines[i]->sentinel == SENTINEL_VALUE); 240 } 241 #endif 242 243 return (OK); 244 } 245