line.c revision 1.19 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