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