1 /* $NetBSD: addbytes.c,v 1.31 2007/01/21 13:25:36 jdc 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94"; 36 #else 37 __RCSID("$NetBSD: addbytes.c,v 1.31 2007/01/21 13:25:36 jdc Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include "curses.h" 42 #include "curses_private.h" 43 #ifdef DEBUG 44 #include <assert.h> 45 #endif 46 47 #define SYNCH_IN {y = win->cury; x = win->curx;} 48 #define SYNCH_OUT {win->cury = y; win->curx = x;} 49 50 #ifndef _CURSES_USE_MACROS 51 52 /* 53 * addbytes -- 54 * Add the character to the current position in stdscr. 55 */ 56 int 57 addbytes(const char *bytes, int count) 58 { 59 return __waddbytes(stdscr, bytes, count, 0); 60 } 61 62 /* 63 * waddbytes -- 64 * Add the character to the current position in the given window. 65 */ 66 int 67 waddbytes(WINDOW *win, const char *bytes, int count) 68 { 69 return __waddbytes(win, bytes, count, 0); 70 } 71 72 /* 73 * mvaddbytes -- 74 * Add the characters to stdscr at the location given. 75 */ 76 int 77 mvaddbytes(int y, int x, const char *bytes, int count) 78 { 79 return mvwaddbytes(stdscr, y, x, bytes, count); 80 } 81 82 /* 83 * mvwaddbytes -- 84 * Add the characters to the given window at the location given. 85 */ 86 int 87 mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) 88 { 89 if (wmove(win, y, x) == ERR) 90 return ERR; 91 92 return __waddbytes(win, bytes, count, 0); 93 } 94 95 #endif 96 97 /* 98 * waddbytes -- 99 * Add the character to the current position in the given window. 100 */ 101 int 102 __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) 103 { 104 static char blanks[] = " "; 105 int c, newx, x, y; 106 attr_t attributes; 107 __LINE *lp; 108 #ifdef DEBUG 109 int i; 110 111 for (i = 0; i < win->maxy; i++) { 112 assert(win->lines[i]->sentinel == SENTINEL_VALUE); 113 } 114 #endif 115 116 SYNCH_IN; 117 lp = win->lines[y]; 118 119 while (count--) { 120 c = *bytes++; 121 #ifdef DEBUG 122 __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", 123 c, attr, y, x); 124 #endif 125 switch (c) { 126 case '\t': 127 SYNCH_OUT; 128 if (waddbytes(win, blanks, 8 - (x % 8)) == ERR) 129 return (ERR); 130 SYNCH_IN; 131 break; 132 133 default: 134 #ifdef DEBUG 135 __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", 136 win, y, x); 137 #endif 138 139 if (lp->flags & __ISPASTEOL) { 140 newline: 141 x = 0; 142 lp->flags &= ~__ISPASTEOL; 143 if (y == win->scr_b) { 144 #ifdef DEBUG 145 __CTRACE(__CTRACE_INPUT, 146 "ADDBYTES - on bottom " 147 "of scrolling region\n"); 148 #endif 149 if (!(win->flags & __SCROLLOK)) 150 return ERR; 151 SYNCH_OUT; 152 scroll(win); 153 SYNCH_IN; 154 } else { 155 y++; 156 } 157 lp = win->lines[y]; 158 if (c == '\n') 159 break; 160 } 161 162 attributes = (win->wattr | attr) & 163 (__ATTRIBUTES & ~__COLOR); 164 if (attr & __COLOR) 165 attributes |= attr & __COLOR; 166 else if (win->wattr & __COLOR) 167 attributes |= win->wattr & __COLOR; 168 #ifdef DEBUG 169 __CTRACE(__CTRACE_INPUT, 170 "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(__CTRACE_INPUT, 192 "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", 193 *lp->firstchp, *lp->lastchp, 194 *lp->firstchp - win->ch_off, 195 *lp->lastchp - win->ch_off); 196 #endif 197 if (win->bch != ' ' && c == ' ') 198 lp->line[x].ch = win->bch; 199 else 200 lp->line[x].ch = c; 201 if (attributes & __COLOR) 202 lp->line[x].attr = 203 attributes | (win->battr & ~__COLOR); 204 else 205 lp->line[x].attr = attributes | win->battr; 206 if (x == win->maxx - 1) 207 lp->flags |= __ISPASTEOL; 208 else 209 x++; 210 #ifdef DEBUG 211 __CTRACE(__CTRACE_INPUT, 212 "ADDBYTES: 2: y = %d, x = %d, firstch = %d, " 213 "lastch = %d\n", 214 y, x, *win->lines[y]->firstchp, 215 *win->lines[y]->lastchp); 216 #endif 217 break; 218 case '\n': 219 SYNCH_OUT; 220 wclrtoeol(win); 221 SYNCH_IN; 222 goto newline; 223 case '\r': 224 x = 0; 225 continue; 226 case '\b': 227 if (--x < 0) 228 x = 0; 229 break; 230 } 231 } 232 SYNCH_OUT; 233 234 #ifdef DEBUG 235 for (i = 0; i < win->maxy; i++) { 236 assert(win->lines[i]->sentinel == SENTINEL_VALUE); 237 } 238 #endif 239 240 return (OK); 241 } 242