ripoffline.c revision 1.5 1 /* $NetBSD: ripoffline.c,v 1.5 2018/10/03 13:22:29 roy Exp $ */
2
3 /*-
4 * Copyright (c) 2017 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roy Marples.
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. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: ripoffline.c,v 1.5 2018/10/03 13:22:29 roy Exp $");
35 #endif /* not lint */
36
37 #include "curses.h"
38 #include "curses_private.h"
39
40 /* List of ripoffline calls */
41 static struct ripoff {
42 int nlines;
43 int (*init)(WINDOW *, int);
44 } ripoffs[MAX_RIPS];
45 static int nrips;
46
47 /*
48 * ripoffline --
49 * Ripoff a line from the top of bottom of stdscr.
50 * Must be called before initscr or newterm.
51 */
52 int
53 ripoffline(int line, int (*init)(WINDOW *, int))
54 {
55
56 #ifdef DEBUG
57 __CTRACE(__CTRACE_WINDOW, "ripoffline: %d\n", line);
58 #endif
59
60 if (nrips >= MAX_RIPS || init == NULL)
61 return ERR; /* This makes sense, but not standards compliant. */
62 if (line == 0)
63 return OK;
64 ripoffs[nrips].nlines = line < 0 ? -1 : 1;
65 ripoffs[nrips++].init = init;
66 return OK;
67 }
68
69 /*
70 * __rippedlines --
71 * Returns the number of ripped lines from the screen.
72 */
73 int
74 __rippedlines(const SCREEN *screen, int line)
75 {
76 const struct __ripoff *rip;
77 int i, n;
78
79 n = 0;
80 for (i = 0, rip = screen->ripped; i < screen->nripped; i++, rip++) {
81 if (line < 1 && rip->nlines < 0)
82 n += -rip->nlines;
83 else if (line > 0 && rip->nlines > 0)
84 n += rip->nlines;
85 }
86 return n;
87 }
88
89 /*
90 * __ripoffscreen --
91 * Rips lines from the screen by creating a WINDOW per ripoffline call.
92 * Although the POSIX API only allows for one line WINDOWS to be created,
93 * this implemenation allows for N lines if needed.
94 */
95 int
96 __ripoffscreen(SCREEN *screen)
97 {
98 int i, nlines, rbot, rtop;
99 const struct ripoff *srip;
100 struct __ripoff *rip;
101 WINDOW *w;
102
103 rip = screen->ripped;
104 rbot = LINES;
105 rtop = 0;
106 for (i = 0, srip = ripoffs; i < nrips; i++, srip++) {
107 if (srip->nlines == 0)
108 continue;
109 nlines = srip->nlines < 0 ? -srip->nlines : srip->nlines;
110 w = __newwin(screen, nlines, 0,
111 srip->nlines < 0 ? rbot - nlines : rtop,
112 0, FALSE, FALSE);
113 if (w != NULL) {
114 rip->win = w;
115 rip->nlines = srip->nlines;
116 rip++;
117 screen->nripped++;
118 if (srip->nlines > 0)
119 rtop += nlines;
120 else
121 rbot -= nlines;
122 }
123 if (srip->init(w, COLS) == ERR)
124 return ERR;
125 #ifdef DEBUG
126 if (w != NULL)
127 __CTRACE(__CTRACE_WINDOW,
128 "newterm: %p ripped %d line(s) from the %s\n",
129 w, nlines, srip->nlines < 0 ? "bottom" : "top");
130 #endif
131 }
132 nrips = 0; /* Reset the stack. */
133 return OK;
134 }
135
136 /*
137 * __ripoffresize --
138 * Called from resizeterm to ensure the ripped off lines are correctly
139 * placed and refreshed.
140 */
141 int
142 __ripoffresize(SCREEN *screen)
143 {
144 int rbot = screen->LINES, i, nlines, ret = OK;
145 struct __ripoff *rip;
146
147 for (i = 0, rip = screen->ripped; i < screen->nripped; i++, rip++) {
148 if (rip->nlines == 0)
149 continue;
150 nlines = rip->nlines < 0 ? -rip->nlines : rip->nlines;
151 if (wresize(rip->win, nlines, screen->COLS) == ERR)
152 ret = ERR;
153 if (rip->nlines < 0) {
154 /* Reposition the lower windows. */
155 if (mvwin(rip->win, rbot + rip->nlines, 0) == ERR)
156 ret = ERR;
157 else
158 rbot += rip->nlines;
159 }
160 }
161
162 return ret;
163 }
164
165 /*
166 * __ripofftouch --
167 * Displays the ripped off lines from initscr.
168 */
169 void
170 __ripofftouch(SCREEN *screen)
171 {
172 int i;
173 struct __ripoff *rip;
174
175 for (i = 0, rip = screen->ripped; i < screen->nripped; i++, rip++) {
176 touchwin(rip->win);
177 wnoutrefresh(rip->win);
178 }
179 }
180
181 /*
182 * __unripoffline --
183 * Used by __slk_init to remove the ripoffline reservation it made
184 * because the terminal natively supports soft label keys.
185 */
186 int
187 __unripoffline(int (*init)(WINDOW *, int))
188 {
189 struct ripoff *rip;
190 int i, unripped = 0;
191
192 for (i = 0, rip = ripoffs; i < nrips; i++, rip++) {
193 if (rip->init == init) {
194 rip->nlines = 0;
195 unripped++;
196 }
197 }
198 return unripped;
199 }
200