Home | History | Annotate | Line # | Download | only in libcurses
      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 (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.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