xref: /illumos-gate/usr/src/lib/libcurses/screen/waddch.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 /*LINTLIBRARY*/
41 
42 #include	<sys/types.h>
43 #include	"curses_inc.h"
44 
45 /*
46  * This routine prints the character in the current position.
47  * Think of it as putc.
48  */
49 
50 int
51 waddch(WINDOW *win, chtype c)
52 {
53 	short	x = win->_curx;
54 	short	y = win->_cury;
55 	chtype	rawc = _CHAR(c);
56 	chtype	rawattrs = _ATTR(c);
57 	int	rv = OK;
58 	bool	savimmed = win->_immed;
59 	bool	savsync = win->_sync;
60 
61 	win->_immed = win->_sync = FALSE;
62 
63 #ifdef	DEBUG
64 	if (outf)
65 		if (c == rawc)
66 			fprintf(outf, "'%c'", rawc);
67 		else
68 			fprintf(outf, "'%c' %o, raw %o", c, c, rawc);
69 #endif	/* DEBUG */
70 
71 	win->_insmode = FALSE;
72 	if (_scrmax > 1 && _mbvalid(win) == ERR)
73 		goto next;
74 	if (_mbtrue && ISMBIT(rawc)) {
75 		rv = _mbaddch(win, rawattrs, RBYTE(rawc));
76 		win->_immed = savimmed;
77 		win->_sync = savsync;
78 		goto nextw;
79 	}
80 
81 	switch (rawc) {
82 		case '\n':
83 			(void) wclrtoeol(win);
84 			goto new_line;
85 		case '\r':
86 			goto move_to_begin_line;
87 		case '\b':
88 			if (--x < 0)
89 move_to_begin_line:
90 				x = 0;
91 			win->_curx = x;
92 			win->_flags |= _WINMOVED;
93 			goto out_move_only;
94 		default:
95 			if (rawc < ' ' || rawc == _CTRL('?')) {
96 				if (rawc == '\t') {
97 					int	newx;
98 					chtype	space = ' ' | rawattrs;
99 
100 					if ((newx = x + (TABSIZE -
101 					    (x % TABSIZE))) > win->_maxx) {
102 						newx = win->_maxx;
103 					}
104 					for (; x < newx; x++) {
105 						if (waddch(win, space) == ERR)
106 							goto next;
107 					}
108 				} else {
109 					if ((waddch(win, (chtype)
110 					    '^'|rawattrs) == ERR) ||
111 					    (waddch(win, (chtype)
112 					    _UNCTRL(rawc)|rawattrs) == ERR)) {
113 next :
114 						rv = ERR;
115 				}
116 			}
117 			x = win->_curx;
118 			y = win->_cury;
119 			win->_immed = savimmed;
120 			win->_sync = savsync;
121 			break;
122 		}
123 #ifdef	DEBUG
124 		if ((win->_attrs) && outf)
125 			fprintf(outf, "(attrs %o, %o=>%o)", win->_attrs,
126 			    c, c | win->_attrs);
127 #endif	/* DEBUG */
128 
129 		/* clear any partial multi-column character */
130 		if (_scrmax > 1 && ISMBIT(win->_y[y][x]) &&
131 		    (rv = _mbclrch(win, y, x)) == ERR) {
132 			x = win->_curx;
133 			y = win->_cury;
134 			win->_immed = savimmed;
135 			win->_sync = savsync;
136 			break;
137 		}
138 
139 		if ((c = _WCHAR(win, c)|rawattrs) != win->_y[y][x]) {
140 			if (x < win->_firstch[y])
141 				win->_firstch[y] = x;
142 			if (x > win->_lastch[y])
143 				win->_lastch[y] = x;
144 			win->_y[y][x] = c;
145 #ifdef	_VR3_COMPAT_CODE
146 			if (_y16update)
147 				/* LINTED */
148 				win->_y16[y][x] = _TO_OCHTYPE(c);
149 #endif	/* _VR3_COMPAT_CODE */
150 		}
151 		if (++x == win->_maxx) {
152 new_line:
153 			if (y == win->_bmarg) {
154 				if (wscrl(win, 1) == ERR) {
155 					rv = ERR;
156 					if (x == win->_maxx)
157 						--x;
158 #ifdef	DEBUG
159 					if (outf) {
160 						int	i;
161 
162 						fprintf(outf, "ERR because "
163 						    "(%d, %d) > (%d, %d)\n",
164 						    x, y, win->_maxx,
165 						    win->_maxy);
166 						fprintf(outf, "line: '");
167 						for (i = 0; i < win->_maxy;
168 						    i++)
169 							fprintf(outf, "%c",
170 							    win->_y[y-1][i]);
171 						fprintf(outf, "'\n");
172 					}
173 #endif	/* DEBUG */
174 					break;
175 				} else {
176 					savimmed = 1;
177 				}
178 			} else {
179 				y++;
180 			}
181 			x = 0;
182 		} else {
183 			savimmed += 2;
184 		}
185 #ifdef	FULLDEBUG
186 		if (outf) {
187 			fprintf(outf, "ADDCH: 2: y = %d, x = %d, "
188 			    "firstch = %d, lastch = %d\n", y, x,
189 			    win->_firstch[y], win->_lastch[y]);
190 		}
191 #endif	/* FULLDEBUG */
192 		break;
193 	}
194 	win->_cury = y;
195 	win->_curx = x;
196 
197 nextw:
198 	/* sync with ancestor structures */
199 	if (win->_sync)
200 		wsyncup(win);
201 
202 	if (savimmed == 3)
203 		return ((*_quick_ptr)(win, c));
204 
205 	win->_flags |= _WINCHANGED;
206 
207 out_move_only:
208 
209 	return ((savimmed == 1) ? wrefresh(win) : rv);
210 }
211