1 /****************************************************************************
2 * Copyright (c) 1998 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
31 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
32 ****************************************************************************/
37 ** The routine waddch().
41 #include <curses.priv.h>
44 MODULE_ID("$Id: lib_addch.c,v 1.39 1998/02/11 12:13:57 tom Exp $")
47 * Ugly microtweaking alert. Everything from here to end of module is
48 * likely to be speed-critical -- profiling data sure says it is!
49 * Most of the important screen-painting functions are shells around
50 * waddch(). So we make every effort to reduce function-call overhead
51 * by inlining stuff, even at the cost of making wrapped copies for
52 * export. Also we supply some internal versions that don't call the
53 * window sync hook, for use by string-put functions.
56 /* Return bit mask for clearing color pair number if given ch has color */
57 #define COLOR_MASK(ch) (~(chtype)((ch)&A_COLOR?A_COLOR:0))
59 static inline chtype render_char(WINDOW *win, chtype ch)
60 /* compute a rendition of the given char correct for the current context */
62 chtype a = win->_attrs;
66 /* color in attrs has precedence over bkgd */
67 ch = a | (win->_bkgd & COLOR_MASK(a));
71 /* color in attrs has precedence over bkgd */
72 a |= (win->_bkgd & A_ATTRIBUTES) & COLOR_MASK(a);
73 /* color in ch has precedence */
74 ch |= (a & COLOR_MASK(ch));
77 TR(TRACE_VIRTPUT, ("bkg = %lx, attrs = %lx -> ch = %lx", win->_bkgd,
83 chtype _nc_background(WINDOW *win)
84 /* make render_char() visible while still allowing us to inline it below */
89 chtype _nc_render(WINDOW *win, chtype ch)
90 /* make render_char() visible while still allowing us to inline it below */
92 return render_char(win, ch);
95 /* check if position is legal; if not, return error */
96 #ifndef NDEBUG /* treat this like an assertion */
97 #define CHECK_POSITION(win, x, y) \
102 TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \
103 "(_maxx = %d, _maxy = %d)", win, x, y, \
104 win->_maxx, win->_maxy)); \
108 #define CHECK_POSITION(win, x, y) /* nothing */
112 int waddch_literal(WINDOW *win, chtype ch)
119 CHECK_POSITION(win, x, win->_cury);
122 * If we're trying to add a character at the lower-right corner more
123 * than once, fail. (Moving the cursor will clear the flag).
125 if (win->_flags & _WRAPPED) {
128 win->_flags &= ~_WRAPPED;
131 ch = render_char(win, ch);
132 TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs)));
134 line = win->_line+win->_cury;
136 if (line->firstchar == _NOCHANGE)
137 line->firstchar = line->lastchar = x;
138 else if (x < line->firstchar)
140 else if (x > line->lastchar)
143 line->text[x++] = ch;
145 TR(TRACE_VIRTPUT, ("(%d, %d) = %s", win->_cury, x, _tracechtype(ch)));
146 if (x > win->_maxx) {
148 * The _WRAPPED flag is useful only for telling an application
149 * that we've just wrapped the cursor. We don't do anything
150 * with this flag except set it when wrapping, and clear it
151 * whenever we move the cursor. If we try to wrap at the
152 * lower-right corner of a window, we cannot move the cursor
153 * (since that wouldn't be legal). So we return an error
154 * (which is what SVr4 does). Unlike SVr4, we can successfully
155 * add a character to the lower-right corner.
157 win->_flags |= _WRAPPED;
158 if (++win->_cury > win->_regbottom) {
159 win->_cury = win->_regbottom;
160 win->_curx = win->_maxx;
173 int waddch_nosync(WINDOW *win, const chtype ch)
174 /* the workhorse function -- add a character to the given window */
180 if ((ch & A_ALTCHARSET)
181 || ((t = TextOf(ch)) > 127)
182 || ((s = unctrl(t))[1] == 0))
183 return waddch_literal(win, ch);
190 x += (TABSIZE-(x%TABSIZE));
193 * Space-fill the tab on the bottom line so that we'll get the
194 * "correct" cursor position.
196 if ((! win->_scroll && (y == win->_regbottom))
197 || (x <= win->_maxx)) {
198 chtype blank = (' ' | AttrOf(ch));
199 while (win->_curx < x) {
200 if (waddch_literal(win, blank) == ERR)
206 win->_flags |= _WRAPPED;
207 if (++y > win->_regbottom) {
221 if (++y > win->_regbottom) {
231 win->_flags &= ~_WRAPPED;
237 win->_flags &= ~_WRAPPED;
241 if (waddch_literal(win, (*s++)|AttrOf(ch)) == ERR)
252 int _nc_waddch_nosync(WINDOW *win, const chtype c)
253 /* export copy of waddch_nosync() so the string-put functions can use it */
255 return(waddch_nosync(win, c));
259 * The versions below call _nc_synhook(). We wanted to avoid this in the
260 * version exported for string puts; they'll call _nc_synchook once at end
264 /* These are actual entry points */
266 int waddch(WINDOW *win, const chtype ch)
270 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win, _tracechtype(ch)));
272 if (win && (waddch_nosync(win, ch) != ERR))
278 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_RETURN("%d"), code));
282 int wechochar(WINDOW *win, const chtype ch)
286 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win, _tracechtype(ch)));
288 if (win && (waddch_nosync(win, ch) != ERR))
290 bool save_immed = win->_immed;
293 win->_immed = save_immed;
296 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_RETURN("%d"), code));