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