1 /****************************************************************************
2 * Copyright (c) 1998,1999,2000 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.44 2000/05/20 21:13:11 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))
60 render_char(WINDOW *win, chtype ch)
61 /* compute a rendition of the given char correct for the current context */
63 chtype a = win->_attrs;
66 /* color in attrs has precedence over bkgd */
67 ch = a | (win->_bkgd & COLOR_MASK(a));
69 /* color in attrs has precedence over bkgd */
70 a |= (win->_bkgd & A_ATTRIBUTES) & COLOR_MASK(a);
71 /* color in ch has precedence */
72 ch |= (a & COLOR_MASK(ch));
75 TR(TRACE_VIRTPUT, ("bkg = %lx, attrs = %lx -> ch = %lx", win->_bkgd,
82 _nc_background(WINDOW *win)
83 /* make render_char() visible while still allowing us to inline it below */
89 _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 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 0 /* Solaris 2.6 allows updating the corner more than once */
126 if (win->_flags & _WRAPPED) {
129 win->_flags &= ~_WRAPPED;
133 ch = render_char(win, ch);
134 TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs)));
136 line = win->_line + win->_cury;
138 CHANGED_CELL(line, x);
140 line->text[x++] = ch;
142 TR(TRACE_VIRTPUT, ("(%d, %d) = %s", win->_cury, x, _tracechtype(ch)));
143 if (x > win->_maxx) {
145 * The _WRAPPED flag is useful only for telling an application that
146 * we've just wrapped the cursor. We don't do anything with this flag
147 * except set it when wrapping, and clear it whenever we move the
148 * cursor. If we try to wrap at the lower-right corner of a window, we
149 * cannot move the cursor (since that wouldn't be legal). So we return
150 * an error (which is what SVr4 does). Unlike SVr4, we can
151 * successfully add a character to the lower-right corner (Solaris 2.6
152 * does this also, however).
154 win->_flags |= _WRAPPED;
155 if (++win->_cury > win->_regbottom) {
156 win->_cury = win->_regbottom;
157 win->_curx = win->_maxx;
170 waddch_nosync(WINDOW *win, const chtype ch)
171 /* the workhorse function -- add a character to the given window */
177 if ((ch & A_ALTCHARSET)
178 || ((t = TextOf(ch)) > 127)
179 || ((s = unctrl(t))[1] == 0))
180 return waddch_literal(win, ch);
187 x += (TABSIZE - (x % TABSIZE));
190 * Space-fill the tab on the bottom line so that we'll get the
191 * "correct" cursor position.
193 if ((!win->_scroll && (y == win->_regbottom))
194 || (x <= win->_maxx)) {
195 chtype blank = (' ' | AttrOf(ch));
196 while (win->_curx < x) {
197 if (waddch_literal(win, blank) == ERR)
203 win->_flags |= _WRAPPED;
204 if (++y > win->_regbottom) {
218 if (++y > win->_regbottom) {
228 win->_flags &= ~_WRAPPED;
234 win->_flags &= ~_WRAPPED;
238 if (waddch_literal(win, (*s++) | AttrOf(ch)) == ERR)
250 _nc_waddch_nosync(WINDOW *win, const chtype c)
251 /* export copy of waddch_nosync() so the string-put functions can use it */
253 return (waddch_nosync(win, c));
257 * The versions below call _nc_synhook(). We wanted to avoid this in the
258 * version exported for string puts; they'll call _nc_synchook once at end
262 /* These are actual entry points */
265 waddch(WINDOW *win, const chtype ch)
269 TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win,
272 if (win && (waddch_nosync(win, ch) != ERR)) {
277 TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code));
282 wechochar(WINDOW *win, const chtype ch)
286 TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win,
289 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));