xref: /netbsd-src/lib/libcurses/line.c (revision 6348e3f32a4431b45d07e1da16fd7b12725a45e7)
1 /*	$NetBSD: line.c,v 1.19 2024/12/23 02:58:03 blymn Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998-1999 Brett Lymn
5  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6  * All rights reserved.
7  *
8  * This code has been donated to The NetBSD Foundation by the Author.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: line.c,v 1.19 2024/12/23 02:58:03 blymn Exp $");
35 #endif				/* not lint */
36 
37 #include <string.h>
38 
39 #include "curses.h"
40 #include "curses_private.h"
41 
42 /*
43  * hline --
44  *	Draw a horizontal line of character c on stdscr.
45  */
46 int
47 hline(chtype ch, int count)
48 {
49 
50 	return whline(stdscr, ch, count);
51 }
52 
53 /*
54  * mvhline --
55  *	Move to location (y, x) and draw a horizontal line of character c
56  *	on stdscr.
57  */
58 int
59 mvhline(int y, int x, chtype ch, int count)
60 {
61 
62 	return mvwhline(stdscr, y, x, ch, count);
63 }
64 
65 /*
66  * mvwhline --
67  *	Move to location (y, x) and draw a horizontal line of character c
68  *	in the given window.
69  */
70 int
71 mvwhline(WINDOW *win, int y, int x, chtype ch, int count)
72 {
73 
74 	if (wmove(win, y, x) == ERR)
75 		return ERR;
76 
77 	return whline(win, ch, count);
78 }
79 
80 /*
81  * whline --
82  *	Draw a horizontal line of character c in the given window moving
83  *	towards the rightmost column.  At most count characters are drawn
84  *	or until the edge of the screen, whichever comes first.
85  */
86 int
87 whline(WINDOW *win, chtype ch, int count)
88 {
89 #ifndef HAVE_WCHAR
90 	if (__predict_false(win == NULL))
91 		return ERR;
92 
93 	int ocury, ocurx, n, i;
94 
95 	n = min(count, win->maxx - win->curx);
96 	ocury = win->cury;
97 	ocurx = win->curx;
98 
99 	if (!(ch & __CHARTEXT))
100 		ch |= ACS_HLINE;
101 	for (i = 0; i < n; i++)
102 		mvwaddch(win, ocury, ocurx + i, ch);
103 
104 	wmove(win, ocury, ocurx);
105 	return OK;
106 #else
107 	cchar_t cch;
108 
109 	__cursesi_chtype_to_cchar(ch, &cch);
110 	return whline_set(win, &cch, count);
111 #endif
112 }
113 
114 /*
115  * vline --
116  *	Draw a vertical line of character ch on stdscr.
117  */
118 int
119 vline(chtype ch, int count)
120 {
121 
122 	return wvline(stdscr, ch, count);
123 }
124 
125 /*
126  * mvvline --
127  *	Move to the given location and draw a vertical line of character ch.
128  */
129 int
130 mvvline(int y, int x, chtype ch, int count)
131 {
132 
133 	return mvwvline(stdscr, y, x, ch, count);
134 }
135 
136 /*
137  * mvwvline --
138  *	Move to the given location and draw a vertical line of character ch
139  *	on the given window.
140  */
141 int
142 mvwvline(WINDOW *win, int y, int x, chtype ch, int count)
143 {
144 
145 	if (wmove(win, y, x) == ERR)
146 		return ERR;
147 
148 	return wvline(win, ch, count);
149 }
150 
151 /*
152  * wvline --
153  *	Draw a vertical line of character ch in the given window moving
154  *	towards the bottom of the screen.  At most count characters are drawn
155  *	or until the edge of the screen, whichever comes first.
156  */
157 int
158 wvline(WINDOW *win, chtype ch, int count)
159 {
160 #ifndef HAVE_WCHAR
161 	int ocury, ocurx, n, i;
162 
163 	if (__predict_false(win == NULL))
164 		return ERR;
165 
166 	n = min(count, win->maxy - win->cury);
167 	ocury = win->cury;
168 	ocurx = win->curx;
169 
170 	if (!(ch & __CHARTEXT))
171 		ch |= ACS_VLINE;
172 	for (i = 0; i < n; i++)
173 		mvwaddch(win, ocury + i, ocurx, ch);
174 
175 	wmove(win, ocury, ocurx);
176 	return OK;
177 #else
178 	cchar_t cch;
179 
180 	__cursesi_chtype_to_cchar(ch, &cch);
181 	return wvline_set(win, &cch, count);
182 #endif
183 }
184 
185 int hline_set(const cchar_t *wch, int n)
186 {
187 #ifndef HAVE_WCHAR
188 	return ERR;
189 #else
190 	return whline_set( stdscr, wch, n );
191 #endif /* HAVE_WCHAR */
192 }
193 
194 int mvhline_set(int y, int x, const cchar_t *wch, int n)
195 {
196 #ifndef HAVE_WCHAR
197 	return ERR;
198 #else
199 	return mvwhline_set( stdscr, y, x, wch, n );
200 #endif /* HAVE_WCHAR */
201 }
202 
203 int mvwhline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
204 {
205 #ifndef HAVE_WCHAR
206 	return ERR;
207 #else
208 	if ( wmove( win, y , x ) == ERR )
209 		return ERR;
210 
211 	return whline_set( win, wch, n );
212 #endif /* HAVE_WCHAR */
213 }
214 
215 int whline_set(WINDOW *win, const cchar_t *wch, int n)
216 {
217 #ifndef HAVE_WCHAR
218 	return ERR;
219 #else
220 	int ocury, ocurx, wcn, i, cw;
221 	cchar_t cc;
222 
223 	if (__predict_false(win == NULL))
224 		return ERR;
225 
226 	cc = *wch;
227 	if (!cc.vals[0]) {
228 		cc.vals[0] = WACS_HLINE->vals[0];
229 		cc.attributes |= WACS_HLINE->attributes;
230 	}
231 
232 	cw = wcwidth(cc.vals[0]);
233 	if (cw <= 0)
234 		cw = 1;
235 	if ( ( win->maxx - win->curx ) < cw )
236 		return ERR;
237 	wcn = min( n, ( win->maxx - win->curx ) / cw );
238 	__CTRACE(__CTRACE_LINE, "whline_set: line of %d\n", wcn);
239 	ocury = win->cury;
240 	ocurx = win->curx;
241 
242 	for (i = 0; i < wcn; i++ ) {
243 		__CTRACE(__CTRACE_LINE, "whline_set: (%d,%d)\n",
244 		   ocury, ocurx + i * cw);
245 		mvwadd_wch(win, ocury, ocurx + i * cw, &cc);
246 	}
247 
248 	wmove(win, ocury, ocurx);
249 	__sync(win);
250 	return OK;
251 #endif /* HAVE_WCHAR */
252 }
253 
254 int vline_set(const cchar_t *wch, int n)
255 {
256 #ifndef HAVE_WCHAR
257 	return ERR;
258 #else
259 	return wvline_set(stdscr, wch, n);
260 #endif /* HAVE_WCHAR */
261 }
262 
263 int mvvline_set(int y, int x, const cchar_t *wch, int n)
264 {
265 #ifndef HAVE_WCHAR
266 	return ERR;
267 #else
268 	return mvwvline_set(stdscr, y, x, wch, n);
269 #endif /* HAVE_WCHAR */
270 }
271 
272 int mvwvline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
273 {
274 #ifndef HAVE_WCHAR
275 	return ERR;
276 #else
277 	if (wmove(win, y, x) == ERR)
278 		return ERR;
279 
280 	return wvline_set(win, wch, n);
281 #endif /* HAVE_WCHAR */
282 }
283 
284 int wvline_set(WINDOW *win, const cchar_t *wch, int n)
285 {
286 #ifndef HAVE_WCHAR
287 	return ERR;
288 #else
289 	int ocury, ocurx, wcn, i;
290 	cchar_t cc;
291 
292 	if (__predict_false(win == NULL))
293 		return ERR;
294 
295 	wcn = min(n, win->maxy - win->cury);
296 	__CTRACE(__CTRACE_LINE, "wvline_set: line of %d\n", wcn);
297 	ocury = win->cury;
298 	ocurx = win->curx;
299 
300 	cc = *wch;
301 	if (!cc.vals[0]) {
302 		cc.vals[0] = WACS_VLINE->vals[0];
303 		cc.attributes |= WACS_VLINE->attributes;
304 	}
305 	for (i = 0; i < wcn; i++) {
306 		mvwadd_wch(win, ocury + i, ocurx, &cc);
307 		__CTRACE(__CTRACE_LINE, "wvline_set: (%d,%d)\n",
308 		    ocury + i, ocurx);
309 	}
310 
311 	wmove(win, ocury, ocurx);
312 	__sync(win);
313 	return OK;
314 #endif /* HAVE_WCHAR */
315 }
316