2 /***************************************************************************
4 ****************************************************************************
5 * ncurses is copyright (C) 1992-1995 *
7 * zmbenhal@netcom.com *
9 * esr@snark.thyrsus.com *
11 * Permission is hereby granted to reproduce and distribute ncurses *
12 * by any means and for any fee, whether alone or as part of a *
13 * larger distribution, in source or in binary form, PROVIDED *
14 * this notice is included with any such distribution, and is not *
15 * removed from any of its header files. Mention of ncurses in any *
16 * applications linked with it is highly appreciated. *
18 * ncurses comes AS IS with no warranty, implied or expressed. *
20 ***************************************************************************/
25 ** The routines waddch(), wattr_on(), wattr_off(), wchgat().
29 #include <curses.priv.h>
32 MODULE_ID("$Id: lib_addch.c,v 1.30 1997/04/12 17:45:55 tom Exp $")
34 int wattr_on(WINDOW *win, const attr_t at)
36 T((T_CALLED("wattr_on(%p,%s)"), win, _traceattr(at)));
37 T(("... current %s", _traceattr(win->_attrs)));
38 toggle_attr_on(win->_attrs,at);
42 int wattr_off(WINDOW *win, const attr_t at)
44 T((T_CALLED("wattr_off(%p,%s)"), win, _traceattr(at)));
45 T(("... current %s", _traceattr(win->_attrs)));
46 toggle_attr_off(win->_attrs,at);
50 int wchgat(WINDOW *win, int n, attr_t attr, short color, const void *opts GCC_UNUSED)
54 T((T_CALLED("wchgat(%p,%d,%s,%d)"), win, n, _traceattr(attr), color));
56 toggle_attr_on(attr,COLOR_PAIR(color));
58 for (i = win->_curx; i <= win->_maxx && (n == -1 || (n-- > 0)); i++)
59 win->_line[win->_cury].text[i]
60 = ch_or_attr(TextOf(win->_line[win->_cury].text[i]),attr);
66 * Ugly microtweaking alert. Everything from here to end of module is
67 * likely to be speed-critical -- profiling data sure says it is!
68 * Most of the important screen-painting functions are shells around
69 * waddch(). So we make every effort to reduce function-call overhead
70 * by inlining stuff, even at the cost of making wrapped copies for
71 * export. Also we supply some internal versions that don't call the
72 * window sync hook, for use by string-put functions.
75 static inline chtype render_char(WINDOW *win, chtype ch)
76 /* compute a rendition of the given char correct for the current context */
78 if (TextOf(ch) == ' ')
79 ch = ch_or_attr(ch, win->_bkgd);
80 else if (!(ch & A_ATTRIBUTES))
81 ch = ch_or_attr(ch, (win->_bkgd & A_ATTRIBUTES));
82 TR(TRACE_VIRTPUT, ("bkg = %#lx -> ch = %#lx", win->_bkgd, ch));
87 chtype _nc_background(WINDOW *win)
88 /* make render_char() visible while still allowing us to inline it below */
90 return(render_char(win, BLANK));
93 chtype _nc_render(WINDOW *win, chtype ch)
94 /* make render_char() visible while still allowing us to inline it below */
96 chtype c = render_char(win,ch);
97 return (ch_or_attr(c,win->_attrs));
100 /* check if position is legal; if not, return error */
101 #ifdef NDEBUG /* treat this like an assertion */
102 #define CHECK_POSITION(win, x, y) \
107 TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \
108 "(_maxx = %d, _maxy = %d)", win, x, y, \
109 win->_maxx, win->_maxy)); \
113 #define CHECK_POSITION(win, x, y) /* nothing */
117 int waddch_literal(WINDOW *win, chtype ch)
124 CHECK_POSITION(win, x, y);
127 * If we're trying to add a character at the lower-right corner more
128 * than once, fail. (Moving the cursor will clear the flag).
130 if (win->_flags & _WRAPPED) {
133 win->_flags &= ~_WRAPPED;
136 ch = render_char(win, ch);
137 ch = ch_or_attr(ch,win->_attrs);
138 TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs)));
140 if (win->_line[y].text[x] != ch) {
141 if (win->_line[y].firstchar == _NOCHANGE)
142 win->_line[y].firstchar = win->_line[y].lastchar = x;
143 else if (x < win->_line[y].firstchar)
144 win->_line[y].firstchar = x;
145 else if (x > win->_line[y].lastchar)
146 win->_line[y].lastchar = x;
150 win->_line[y].text[x++] = ch;
151 TR(TRACE_VIRTPUT, ("(%d, %d) = %s", y, x, _tracechtype(ch)));
152 if (x > win->_maxx) {
154 * The _WRAPPED flag is useful only for telling an application
155 * that we've just wrapped the cursor. We don't do anything
156 * with this flag except set it when wrapping, and clear it
157 * whenever we move the cursor. If we try to wrap at the
158 * lower-right corner of a window, we cannot move the cursor
159 * (since that wouldn't be legal). So we return an error
160 * (which is what SVr4 does). Unlike SVr4, we can successfully
161 * add a character to the lower-right corner.
163 win->_flags |= _WRAPPED;
164 if (++y > win->_regbottom) {
185 int waddch_nosync(WINDOW *win, const chtype c)
186 /* the workhorse function -- add a character to the given window */
188 register chtype ch = c;
194 CHECK_POSITION(win, x, y);
196 if (ch & A_ALTCHARSET)
199 switch ((int)TextOf(ch)) {
201 x += (TABSIZE-(x%TABSIZE));
204 * Space-fill the tab on the bottom line so that we'll get the
205 * "correct" cursor position.
207 if ((! win->_scroll && (y == win->_regbottom))
208 || (x <= win->_maxx)) {
209 while (win->_curx < x) {
210 if (waddch_literal(win, (' ' | AttrOf(ch))) == ERR)
216 win->_flags |= _WRAPPED;
217 if (++y > win->_regbottom) {
231 if (++y > win->_regbottom) {
241 win->_flags &= ~_WRAPPED;
246 win->_flags &= ~_WRAPPED;
250 if (is7bits(TextOf(ch)) && iscntrl(TextOf(ch)))
251 return(waddstr(win, unctrl((unsigned char)ch)));
255 return waddch_literal(win, ch);
264 int _nc_waddch_nosync(WINDOW *win, const chtype c)
265 /* export copy of waddch_nosync() so the string-put functions can use it */
267 return(waddch_nosync(win, c));
271 * The versions below call _nc_synhook(). We wanted to avoid this in the
272 * version exported for string puts; they'll call _nc_synchook once at end
276 /* These are actual entry points */
278 int waddch(WINDOW *win, const chtype ch)
282 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win, _tracechtype(ch)));
284 if (waddch_nosync(win, ch) != ERR)
290 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_RETURN("%d"), code));
294 int wechochar(WINDOW *win, const chtype ch)
298 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win, _tracechtype(ch)));
300 if (waddch_literal(win, ch) != ERR)
302 bool save_immed = win->_immed;
305 win->_immed = save_immed;
308 TR(TRACE_VIRTPUT|TRACE_CCALLS, (T_RETURN("%d"), code));