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
hline(chtype ch,int count)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
mvhline(int y,int x,chtype ch,int count)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
mvwhline(WINDOW * win,int y,int x,chtype ch,int count)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
whline(WINDOW * win,chtype ch,int count)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
vline(chtype ch,int count)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
mvvline(int y,int x,chtype ch,int count)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
mvwvline(WINDOW * win,int y,int x,chtype ch,int count)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
wvline(WINDOW * win,chtype ch,int count)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 
hline_set(const cchar_t * wch,int n)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 
mvhline_set(int y,int x,const cchar_t * wch,int n)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 
mvwhline_set(WINDOW * win,int y,int x,const cchar_t * wch,int n)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 
whline_set(WINDOW * win,const cchar_t * wch,int n)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 
vline_set(const cchar_t * wch,int n)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 
mvvline_set(int y,int x,const cchar_t * wch,int n)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 
mvwvline_set(WINDOW * win,int y,int x,const cchar_t * wch,int n)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 
wvline_set(WINDOW * win,const cchar_t * wch,int n)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