xref: /netbsd-src/lib/libcurses/line.c (revision 6348e3f32a4431b45d07e1da16fd7b12725a45e7)
1*6348e3f3Sblymn /*	$NetBSD: line.c,v 1.19 2024/12/23 02:58:03 blymn Exp $	*/
266cab71cSblymn 
366cab71cSblymn /*-
466cab71cSblymn  * Copyright (c) 1998-1999 Brett Lymn
566cab71cSblymn  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
666cab71cSblymn  * All rights reserved.
766cab71cSblymn  *
866cab71cSblymn  * This code has been donated to The NetBSD Foundation by the Author.
966cab71cSblymn  *
1066cab71cSblymn  * Redistribution and use in source and binary forms, with or without
1166cab71cSblymn  * modification, are permitted provided that the following conditions
1266cab71cSblymn  * are met:
1366cab71cSblymn  * 1. Redistributions of source code must retain the above copyright
1466cab71cSblymn  *    notice, this list of conditions and the following disclaimer.
1566cab71cSblymn  * 2. The name of the author may not be used to endorse or promote products
16c03a48d6Swiz  *    derived from this software without specific prior written permission
1766cab71cSblymn  *
1866cab71cSblymn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1966cab71cSblymn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2066cab71cSblymn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2166cab71cSblymn  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2266cab71cSblymn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2366cab71cSblymn  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2466cab71cSblymn  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2566cab71cSblymn  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2666cab71cSblymn  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2766cab71cSblymn  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2866cab71cSblymn  *
2966cab71cSblymn  *
3066cab71cSblymn  */
3166cab71cSblymn 
3266cab71cSblymn #include <sys/cdefs.h>
3366cab71cSblymn #ifndef lint
34*6348e3f3Sblymn __RCSID("$NetBSD: line.c,v 1.19 2024/12/23 02:58:03 blymn Exp $");
3566cab71cSblymn #endif				/* not lint */
3666cab71cSblymn 
37e124de36Sblymn #include <string.h>
38e124de36Sblymn 
3966cab71cSblymn #include "curses.h"
4066cab71cSblymn #include "curses_private.h"
4166cab71cSblymn 
4266cab71cSblymn /*
4366cab71cSblymn  * hline --
4466cab71cSblymn  *	Draw a horizontal line of character c on stdscr.
4566cab71cSblymn  */
4666cab71cSblymn int
4766cab71cSblymn hline(chtype ch, int count)
4866cab71cSblymn {
4950a63ac8Sroy 
5066cab71cSblymn 	return whline(stdscr, ch, count);
5166cab71cSblymn }
5266cab71cSblymn 
5366cab71cSblymn /*
5466cab71cSblymn  * mvhline --
5566cab71cSblymn  *	Move to location (y, x) and draw a horizontal line of character c
5666cab71cSblymn  *	on stdscr.
5766cab71cSblymn  */
5866cab71cSblymn int
5966cab71cSblymn mvhline(int y, int x, chtype ch, int count)
6066cab71cSblymn {
6150a63ac8Sroy 
6266cab71cSblymn 	return mvwhline(stdscr, y, x, ch, count);
6366cab71cSblymn }
6466cab71cSblymn 
6566cab71cSblymn /*
6666cab71cSblymn  * mvwhline --
6766cab71cSblymn  *	Move to location (y, x) and draw a horizontal line of character c
6866cab71cSblymn  *	in the given window.
6966cab71cSblymn  */
7066cab71cSblymn int
7166cab71cSblymn mvwhline(WINDOW *win, int y, int x, chtype ch, int count)
7266cab71cSblymn {
7350a63ac8Sroy 
742a780e62Sblymn 	if (wmove(win, y, x) == ERR)
7566cab71cSblymn 		return ERR;
7666cab71cSblymn 
7766cab71cSblymn 	return whline(win, ch, count);
7866cab71cSblymn }
7966cab71cSblymn 
8066cab71cSblymn /*
8166cab71cSblymn  * whline --
8266cab71cSblymn  *	Draw a horizontal line of character c in the given window moving
8366cab71cSblymn  *	towards the rightmost column.  At most count characters are drawn
8466cab71cSblymn  *	or until the edge of the screen, whichever comes first.
8566cab71cSblymn  */
8666cab71cSblymn int
8766cab71cSblymn whline(WINDOW *win, chtype ch, int count)
8866cab71cSblymn {
89452834f2Sdrochner #ifndef HAVE_WCHAR
90*6348e3f3Sblymn 	if (__predict_false(win == NULL))
91*6348e3f3Sblymn 		return ERR;
92*6348e3f3Sblymn 
939c6a61e7Suwe 	int ocury, ocurx, n, i;
9466cab71cSblymn 
9566cab71cSblymn 	n = min(count, win->maxx - win->curx);
964eb5fad7Suwe 	ocury = win->cury;
9766cab71cSblymn 	ocurx = win->curx;
9866cab71cSblymn 
99d096f2efSjdc 	if (!(ch & __CHARTEXT))
100d096f2efSjdc 		ch |= ACS_HLINE;
10166cab71cSblymn 	for (i = 0; i < n; i++)
1029c6a61e7Suwe 		mvwaddch(win, ocury, ocurx + i, ch);
10366cab71cSblymn 
1049c6a61e7Suwe 	wmove(win, ocury, ocurx);
10566cab71cSblymn 	return OK;
106452834f2Sdrochner #else
1071765a45bSuwe 	cchar_t cch;
108452834f2Sdrochner 
109452834f2Sdrochner 	__cursesi_chtype_to_cchar(ch, &cch);
1101765a45bSuwe 	return whline_set(win, &cch, count);
111452834f2Sdrochner #endif
11266cab71cSblymn }
11366cab71cSblymn 
11466cab71cSblymn /*
11566cab71cSblymn  * vline --
11666cab71cSblymn  *	Draw a vertical line of character ch on stdscr.
11766cab71cSblymn  */
11866cab71cSblymn int
11966cab71cSblymn vline(chtype ch, int count)
12066cab71cSblymn {
12150a63ac8Sroy 
12266cab71cSblymn 	return wvline(stdscr, ch, count);
12366cab71cSblymn }
12466cab71cSblymn 
12566cab71cSblymn /*
12666cab71cSblymn  * mvvline --
1275b28f239Srillig  *	Move to the given location and draw a vertical line of character ch.
12866cab71cSblymn  */
12966cab71cSblymn int
13066cab71cSblymn mvvline(int y, int x, chtype ch, int count)
13166cab71cSblymn {
13250a63ac8Sroy 
13366cab71cSblymn 	return mvwvline(stdscr, y, x, ch, count);
13466cab71cSblymn }
13566cab71cSblymn 
13666cab71cSblymn /*
13766cab71cSblymn  * mvwvline --
13866cab71cSblymn  *	Move to the given location and draw a vertical line of character ch
13966cab71cSblymn  *	on the given window.
14066cab71cSblymn  */
14166cab71cSblymn int
14266cab71cSblymn mvwvline(WINDOW *win, int y, int x, chtype ch, int count)
14366cab71cSblymn {
14450a63ac8Sroy 
1452a780e62Sblymn 	if (wmove(win, y, x) == ERR)
14666cab71cSblymn 		return ERR;
14766cab71cSblymn 
14866cab71cSblymn 	return wvline(win, ch, count);
14966cab71cSblymn }
15066cab71cSblymn 
15166cab71cSblymn /*
15266cab71cSblymn  * wvline --
15366cab71cSblymn  *	Draw a vertical line of character ch in the given window moving
15466cab71cSblymn  *	towards the bottom of the screen.  At most count characters are drawn
15566cab71cSblymn  *	or until the edge of the screen, whichever comes first.
15666cab71cSblymn  */
15766cab71cSblymn int
15866cab71cSblymn wvline(WINDOW *win, chtype ch, int count)
15966cab71cSblymn {
160452834f2Sdrochner #ifndef HAVE_WCHAR
16166cab71cSblymn 	int ocury, ocurx, n, i;
16266cab71cSblymn 
163*6348e3f3Sblymn 	if (__predict_false(win == NULL))
164*6348e3f3Sblymn 		return ERR;
165*6348e3f3Sblymn 
16666cab71cSblymn 	n = min(count, win->maxy - win->cury);
16766cab71cSblymn 	ocury = win->cury;
16866cab71cSblymn 	ocurx = win->curx;
16966cab71cSblymn 
170d096f2efSjdc 	if (!(ch & __CHARTEXT))
171d096f2efSjdc 		ch |= ACS_VLINE;
17266cab71cSblymn 	for (i = 0; i < n; i++)
17366cab71cSblymn 		mvwaddch(win, ocury + i, ocurx, ch);
17466cab71cSblymn 
1752a780e62Sblymn 	wmove(win, ocury, ocurx);
17666cab71cSblymn 	return OK;
177452834f2Sdrochner #else
1781765a45bSuwe 	cchar_t cch;
179452834f2Sdrochner 
180452834f2Sdrochner 	__cursesi_chtype_to_cchar(ch, &cch);
1811765a45bSuwe 	return wvline_set(win, &cch, count);
182452834f2Sdrochner #endif
18366cab71cSblymn }
184e124de36Sblymn 
185e124de36Sblymn int hline_set(const cchar_t *wch, int n)
186e124de36Sblymn {
187e124de36Sblymn #ifndef HAVE_WCHAR
188e124de36Sblymn 	return ERR;
189e124de36Sblymn #else
190e124de36Sblymn 	return whline_set( stdscr, wch, n );
191e124de36Sblymn #endif /* HAVE_WCHAR */
192e124de36Sblymn }
193e124de36Sblymn 
194e124de36Sblymn int mvhline_set(int y, int x, const cchar_t *wch, int n)
195e124de36Sblymn {
196e124de36Sblymn #ifndef HAVE_WCHAR
197e124de36Sblymn 	return ERR;
198e124de36Sblymn #else
199e124de36Sblymn 	return mvwhline_set( stdscr, y, x, wch, n );
200e124de36Sblymn #endif /* HAVE_WCHAR */
201e124de36Sblymn }
202e124de36Sblymn 
203e124de36Sblymn int mvwhline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
204e124de36Sblymn {
205e124de36Sblymn #ifndef HAVE_WCHAR
206e124de36Sblymn 	return ERR;
207e124de36Sblymn #else
2082a780e62Sblymn 	if ( wmove( win, y , x ) == ERR )
209e124de36Sblymn 		return ERR;
210e124de36Sblymn 
211e124de36Sblymn 	return whline_set( win, wch, n );
212e124de36Sblymn #endif /* HAVE_WCHAR */
213e124de36Sblymn }
214e124de36Sblymn 
215e124de36Sblymn int whline_set(WINDOW *win, const cchar_t *wch, int n)
216e124de36Sblymn {
217e124de36Sblymn #ifndef HAVE_WCHAR
218e124de36Sblymn 	return ERR;
219e124de36Sblymn #else
2201eecb61dSuwe 	int ocury, ocurx, wcn, i, cw;
221e124de36Sblymn 	cchar_t cc;
222e124de36Sblymn 
223*6348e3f3Sblymn 	if (__predict_false(win == NULL))
224*6348e3f3Sblymn 		return ERR;
225*6348e3f3Sblymn 
2261765a45bSuwe 	cc = *wch;
2271765a45bSuwe 	if (!cc.vals[0]) {
2281765a45bSuwe 		cc.vals[0] = WACS_HLINE->vals[0];
2291765a45bSuwe 		cc.attributes |= WACS_HLINE->attributes;
2301765a45bSuwe 	}
2311765a45bSuwe 
2321765a45bSuwe 	cw = wcwidth(cc.vals[0]);
2331765a45bSuwe 	if (cw <= 0)
234452834f2Sdrochner 		cw = 1;
235e124de36Sblymn 	if ( ( win->maxx - win->curx ) < cw )
236e124de36Sblymn 		return ERR;
237e124de36Sblymn 	wcn = min( n, ( win->maxx - win->curx ) / cw );
238e124de36Sblymn 	__CTRACE(__CTRACE_LINE, "whline_set: line of %d\n", wcn);
2391eecb61dSuwe 	ocury = win->cury;
240e124de36Sblymn 	ocurx = win->curx;
241e124de36Sblymn 
242e124de36Sblymn 	for (i = 0; i < wcn; i++ ) {
243e124de36Sblymn 		__CTRACE(__CTRACE_LINE, "whline_set: (%d,%d)\n",
2441eecb61dSuwe 		   ocury, ocurx + i * cw);
2451eecb61dSuwe 		mvwadd_wch(win, ocury, ocurx + i * cw, &cc);
246e124de36Sblymn 	}
247e124de36Sblymn 
2481eecb61dSuwe 	wmove(win, ocury, ocurx);
2491369811dSroy 	__sync(win);
250e124de36Sblymn 	return OK;
251e124de36Sblymn #endif /* HAVE_WCHAR */
252e124de36Sblymn }
253e124de36Sblymn 
254e124de36Sblymn int vline_set(const cchar_t *wch, int n)
255e124de36Sblymn {
256e124de36Sblymn #ifndef HAVE_WCHAR
257e124de36Sblymn 	return ERR;
258e124de36Sblymn #else
259e124de36Sblymn 	return wvline_set(stdscr, wch, n);
260e124de36Sblymn #endif /* HAVE_WCHAR */
261e124de36Sblymn }
262e124de36Sblymn 
263e124de36Sblymn int mvvline_set(int y, int x, const cchar_t *wch, int n)
264e124de36Sblymn {
265e124de36Sblymn #ifndef HAVE_WCHAR
266e124de36Sblymn 	return ERR;
267e124de36Sblymn #else
268e124de36Sblymn 	return mvwvline_set(stdscr, y, x, wch, n);
269e124de36Sblymn #endif /* HAVE_WCHAR */
270e124de36Sblymn }
271e124de36Sblymn 
272e124de36Sblymn int mvwvline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
273e124de36Sblymn {
274e124de36Sblymn #ifndef HAVE_WCHAR
275e124de36Sblymn 	return ERR;
276e124de36Sblymn #else
2772a780e62Sblymn 	if (wmove(win, y, x) == ERR)
278e124de36Sblymn 		return ERR;
279e124de36Sblymn 
280e124de36Sblymn 	return wvline_set(win, wch, n);
281e124de36Sblymn #endif /* HAVE_WCHAR */
282e124de36Sblymn }
283e124de36Sblymn 
284e124de36Sblymn int wvline_set(WINDOW *win, const cchar_t *wch, int n)
285e124de36Sblymn {
286e124de36Sblymn #ifndef HAVE_WCHAR
287e124de36Sblymn 	return ERR;
288e124de36Sblymn #else
289e124de36Sblymn 	int ocury, ocurx, wcn, i;
290e124de36Sblymn 	cchar_t cc;
291e124de36Sblymn 
292*6348e3f3Sblymn 	if (__predict_false(win == NULL))
293*6348e3f3Sblymn 		return ERR;
294*6348e3f3Sblymn 
295e124de36Sblymn 	wcn = min(n, win->maxy - win->cury);
296e124de36Sblymn 	__CTRACE(__CTRACE_LINE, "wvline_set: line of %d\n", wcn);
297e124de36Sblymn 	ocury = win->cury;
298e124de36Sblymn 	ocurx = win->curx;
299e124de36Sblymn 
3001765a45bSuwe 	cc = *wch;
3011765a45bSuwe 	if (!cc.vals[0]) {
3021765a45bSuwe 		cc.vals[0] = WACS_VLINE->vals[0];
3031765a45bSuwe 		cc.attributes |= WACS_VLINE->attributes;
3041765a45bSuwe 	}
305e124de36Sblymn 	for (i = 0; i < wcn; i++) {
306e124de36Sblymn 		mvwadd_wch(win, ocury + i, ocurx, &cc);
307e124de36Sblymn 		__CTRACE(__CTRACE_LINE, "wvline_set: (%d,%d)\n",
308e124de36Sblymn 		    ocury + i, ocurx);
309e124de36Sblymn 	}
3101369811dSroy 
3112a780e62Sblymn 	wmove(win, ocury, ocurx);
3121369811dSroy 	__sync(win);
313e124de36Sblymn 	return OK;
314e124de36Sblymn #endif /* HAVE_WCHAR */
315e124de36Sblymn }
316