addbytes.c revision 1.30 1 /* $NetBSD: addbytes.c,v 1.30 2006/01/15 11:43:54 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.30 2006/01/15 11:43:54 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("ADDBYTES('%c', %x) at (%d, %d)\n", c, attr, y, x);
123 #endif
124 switch (c) {
125 case '\t':
126 SYNCH_OUT;
127 if (waddbytes(win, blanks, 8 - (x % 8)) == ERR)
128 return (ERR);
129 SYNCH_IN;
130 break;
131
132 default:
133 #ifdef DEBUG
134 __CTRACE("ADDBYTES(%p, %d, %d)\n", win, y, x);
135 #endif
136
137 if (lp->flags & __ISPASTEOL) {
138 newline:
139 x = 0;
140 lp->flags &= ~__ISPASTEOL;
141 if (y == win->scr_b) {
142 #ifdef DEBUG
143 __CTRACE("ADDBYTES - on bottom "
144 "of scrolling region\n");
145 #endif
146 if (!(win->flags & __SCROLLOK))
147 return ERR;
148 SYNCH_OUT;
149 scroll(win);
150 SYNCH_IN;
151 } else {
152 y++;
153 }
154 lp = win->lines[y];
155 if (c == '\n')
156 break;
157 }
158
159 attributes = (win->wattr | attr) &
160 (__ATTRIBUTES & ~__COLOR);
161 if (attr & __COLOR)
162 attributes |= attr & __COLOR;
163 else if (win->wattr & __COLOR)
164 attributes |= win->wattr & __COLOR;
165 #ifdef DEBUG
166 __CTRACE("ADDBYTES: 1: y = %d, x = %d, firstch = %d, "
167 "lastch = %d\n",
168 y, x, *win->lines[y]->firstchp,
169 *win->lines[y]->lastchp);
170 #endif
171 /*
172 * Always update the change pointers. Otherwise,
173 * we could end up not displaying 'blank' characters
174 * when overlapping windows are displayed.
175 */
176 newx = x + win->ch_off;
177 lp->flags |= __ISDIRTY;
178 /*
179 * firstchp/lastchp are shared between
180 * parent window and sub-window.
181 */
182 if (newx < *lp->firstchp)
183 *lp->firstchp = newx;
184 if (newx > *lp->lastchp)
185 *lp->lastchp = newx;
186 #ifdef DEBUG
187 __CTRACE("ADDBYTES: change gives f/l: %d/%d [%d/%d]\n",
188 *lp->firstchp, *lp->lastchp,
189 *lp->firstchp - win->ch_off,
190 *lp->lastchp - win->ch_off);
191 #endif
192 if (win->bch != ' ' && c == ' ')
193 lp->line[x].ch = win->bch;
194 else
195 lp->line[x].ch = c;
196 if (attributes & __COLOR)
197 lp->line[x].attr =
198 attributes | (win->battr & ~__COLOR);
199 else
200 lp->line[x].attr = attributes | win->battr;
201 if (x == win->maxx - 1)
202 lp->flags |= __ISPASTEOL;
203 else
204 x++;
205 #ifdef DEBUG
206 __CTRACE("ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n",
207 y, x, *win->lines[y]->firstchp,
208 *win->lines[y]->lastchp);
209 #endif
210 break;
211 case '\n':
212 SYNCH_OUT;
213 wclrtoeol(win);
214 SYNCH_IN;
215 goto newline;
216 case '\r':
217 x = 0;
218 continue;
219 case '\b':
220 if (--x < 0)
221 x = 0;
222 break;
223 }
224 }
225 SYNCH_OUT;
226
227 #ifdef DEBUG
228 for (i = 0; i < win->maxy; i++) {
229 assert(win->lines[i]->sentinel == SENTINEL_VALUE);
230 }
231 #endif
232
233 return (OK);
234 }
235