Home | History | Annotate | Line # | Download | only in libcurses
line.c revision 1.18
      1 /*	$NetBSD: line.c,v 1.18 2024/09/08 09:36:47 rillig Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998-1999 Brett Lymn
      5  *                         (blymn (at) baea.com.au, brett_lymn (at) 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.18 2024/09/08 09:36:47 rillig 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 	int ocury, ocurx, n, i;
     91 
     92 	n = min(count, win->maxx - win->curx);
     93 	ocury = win->cury;
     94 	ocurx = win->curx;
     95 
     96 	if (!(ch & __CHARTEXT))
     97 		ch |= ACS_HLINE;
     98 	for (i = 0; i < n; i++)
     99 		mvwaddch(win, ocury, ocurx + i, ch);
    100 
    101 	wmove(win, ocury, ocurx);
    102 	return OK;
    103 #else
    104 	cchar_t cch;
    105 
    106 	__cursesi_chtype_to_cchar(ch, &cch);
    107 	return whline_set(win, &cch, count);
    108 #endif
    109 }
    110 
    111 /*
    112  * vline --
    113  *	Draw a vertical line of character ch on stdscr.
    114  */
    115 int
    116 vline(chtype ch, int count)
    117 {
    118 
    119 	return wvline(stdscr, ch, count);
    120 }
    121 
    122 /*
    123  * mvvline --
    124  *	Move to the given location and draw a vertical line of character ch.
    125  */
    126 int
    127 mvvline(int y, int x, chtype ch, int count)
    128 {
    129 
    130 	return mvwvline(stdscr, y, x, ch, count);
    131 }
    132 
    133 /*
    134  * mvwvline --
    135  *	Move to the given location and draw a vertical line of character ch
    136  *	on the given window.
    137  */
    138 int
    139 mvwvline(WINDOW *win, int y, int x, chtype ch, int count)
    140 {
    141 
    142 	if (wmove(win, y, x) == ERR)
    143 		return ERR;
    144 
    145 	return wvline(win, ch, count);
    146 }
    147 
    148 /*
    149  * wvline --
    150  *	Draw a vertical line of character ch in the given window moving
    151  *	towards the bottom of the screen.  At most count characters are drawn
    152  *	or until the edge of the screen, whichever comes first.
    153  */
    154 int
    155 wvline(WINDOW *win, chtype ch, int count)
    156 {
    157 #ifndef HAVE_WCHAR
    158 	int ocury, ocurx, n, i;
    159 
    160 	n = min(count, win->maxy - win->cury);
    161 	ocury = win->cury;
    162 	ocurx = win->curx;
    163 
    164 	if (!(ch & __CHARTEXT))
    165 		ch |= ACS_VLINE;
    166 	for (i = 0; i < n; i++)
    167 		mvwaddch(win, ocury + i, ocurx, ch);
    168 
    169 	wmove(win, ocury, ocurx);
    170 	return OK;
    171 #else
    172 	cchar_t cch;
    173 
    174 	__cursesi_chtype_to_cchar(ch, &cch);
    175 	return wvline_set(win, &cch, count);
    176 #endif
    177 }
    178 
    179 int hline_set(const cchar_t *wch, int n)
    180 {
    181 #ifndef HAVE_WCHAR
    182 	return ERR;
    183 #else
    184 	return whline_set( stdscr, wch, n );
    185 #endif /* HAVE_WCHAR */
    186 }
    187 
    188 int mvhline_set(int y, int x, const cchar_t *wch, int n)
    189 {
    190 #ifndef HAVE_WCHAR
    191 	return ERR;
    192 #else
    193 	return mvwhline_set( stdscr, y, x, wch, n );
    194 #endif /* HAVE_WCHAR */
    195 }
    196 
    197 int mvwhline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
    198 {
    199 #ifndef HAVE_WCHAR
    200 	return ERR;
    201 #else
    202 	if ( wmove( win, y , x ) == ERR )
    203 		return ERR;
    204 
    205 	return whline_set( win, wch, n );
    206 #endif /* HAVE_WCHAR */
    207 }
    208 
    209 int whline_set(WINDOW *win, const cchar_t *wch, int n)
    210 {
    211 #ifndef HAVE_WCHAR
    212 	return ERR;
    213 #else
    214 	int ocury, ocurx, wcn, i, cw;
    215 	cchar_t cc;
    216 
    217 	cc = *wch;
    218 	if (!cc.vals[0]) {
    219 		cc.vals[0] = WACS_HLINE->vals[0];
    220 		cc.attributes |= WACS_HLINE->attributes;
    221 	}
    222 
    223 	cw = wcwidth(cc.vals[0]);
    224 	if (cw <= 0)
    225 		cw = 1;
    226 	if ( ( win->maxx - win->curx ) < cw )
    227 		return ERR;
    228 	wcn = min( n, ( win->maxx - win->curx ) / cw );
    229 	__CTRACE(__CTRACE_LINE, "whline_set: line of %d\n", wcn);
    230 	ocury = win->cury;
    231 	ocurx = win->curx;
    232 
    233 	for (i = 0; i < wcn; i++ ) {
    234 		__CTRACE(__CTRACE_LINE, "whline_set: (%d,%d)\n",
    235 		   ocury, ocurx + i * cw);
    236 		mvwadd_wch(win, ocury, ocurx + i * cw, &cc);
    237 	}
    238 
    239 	wmove(win, ocury, ocurx);
    240 	__sync(win);
    241 	return OK;
    242 #endif /* HAVE_WCHAR */
    243 }
    244 
    245 int vline_set(const cchar_t *wch, int n)
    246 {
    247 #ifndef HAVE_WCHAR
    248 	return ERR;
    249 #else
    250 	return wvline_set(stdscr, wch, n);
    251 #endif /* HAVE_WCHAR */
    252 }
    253 
    254 int mvvline_set(int y, int x, const cchar_t *wch, int n)
    255 {
    256 #ifndef HAVE_WCHAR
    257 	return ERR;
    258 #else
    259 	return mvwvline_set(stdscr, y, x, wch, n);
    260 #endif /* HAVE_WCHAR */
    261 }
    262 
    263 int mvwvline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
    264 {
    265 #ifndef HAVE_WCHAR
    266 	return ERR;
    267 #else
    268 	if (wmove(win, y, x) == ERR)
    269 		return ERR;
    270 
    271 	return wvline_set(win, wch, n);
    272 #endif /* HAVE_WCHAR */
    273 }
    274 
    275 int wvline_set(WINDOW *win, const cchar_t *wch, int n)
    276 {
    277 #ifndef HAVE_WCHAR
    278 	return ERR;
    279 #else
    280 	int ocury, ocurx, wcn, i;
    281 	cchar_t cc;
    282 
    283 	wcn = min(n, win->maxy - win->cury);
    284 	__CTRACE(__CTRACE_LINE, "wvline_set: line of %d\n", wcn);
    285 	ocury = win->cury;
    286 	ocurx = win->curx;
    287 
    288 	cc = *wch;
    289 	if (!cc.vals[0]) {
    290 		cc.vals[0] = WACS_VLINE->vals[0];
    291 		cc.attributes |= WACS_VLINE->attributes;
    292 	}
    293 	for (i = 0; i < wcn; i++) {
    294 		mvwadd_wch(win, ocury + i, ocurx, &cc);
    295 		__CTRACE(__CTRACE_LINE, "wvline_set: (%d,%d)\n",
    296 		    ocury + i, ocurx);
    297 	}
    298 
    299 	wmove(win, ocury, ocurx);
    300 	__sync(win);
    301 	return OK;
    302 #endif /* HAVE_WCHAR */
    303 }
    304