ripoffline.c revision 1.2.2.1 1 /* $NetBSD: ripoffline.c,v 1.2.2.1 2017/04/21 16:53:10 bouyer 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.2.2.1 2017/04/21 16:53:10 bouyer 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_SCREEN, "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)
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 (rip->nlines < 0)
82 n += -rip->nlines;
83 else
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, int *rtop)
97 {
98 int i, nlines;
99 const struct ripoff *srip;
100 struct __ripoff *rip;
101 WINDOW *w;
102
103 *rtop = 0;
104 rip = screen->ripped;
105 for (i = 0, srip = ripoffs; i < nrips; i++, srip++) {
106 if (srip->nlines == 0)
107 continue;
108 nlines = srip->nlines < 0 ? -srip->nlines : srip->nlines;
109 w = __newwin(screen, nlines, 0,
110 srip->nlines < 0 ? LINES - nlines : *rtop,
111 0, FALSE);
112 if (w != NULL) {
113 rip->win = w;
114 rip->nlines = srip->nlines;
115 rip++;
116 screen->nripped++;
117 if (rip->nlines > 0)
118 (*rtop) += rip->nlines;
119 LINES -= nlines;
120 }
121 if (srip->init(w, COLS) == ERR)
122 return ERR;
123 #ifdef DEBUG
124 if (w != NULL)
125 __CTRACE(__CTRACE_SCREEN,
126 "newterm: ripped %d lines from the %s\n",
127 nlines, srip->nlines < 0 ? "bottom" : "top");
128 #endif
129 }
130 nrips = 0; /* Reset the stack. */
131 return OK;
132 }
133
134 /*
135 * __ripoffresize --
136 * Called from resizeterm to ensure the ripped off lines are correctly
137 * placed and refreshed.
138 */
139 void
140 __ripoffresize(SCREEN *screen)
141 {
142 int rbot = screen->LINES, i;
143 struct __ripoff *rip;
144
145 for (i = 0, rip = screen->ripped; i < screen->nripped; i++, rip++) {
146 if (rip->nlines > 0)
147 touchwin(rip->win);
148 else {
149 /* Reposition the lower windows. */
150 mvwin(rip->win, rbot + rip->nlines, 0);
151 rbot += rip->nlines;
152 }
153 wnoutrefresh(rip->win);
154 }
155 }
156
157 /*
158 * __unripoffline --
159 * Used by __slk_init to remove the ripoffline reservation it made
160 * because the terminal natively supports soft label keys.
161 */
162 int
163 __unripoffline(int (*init)(WINDOW *, int))
164 {
165 struct ripoff *rip;
166 int i, unripped = 0;
167
168 for (i = 0, rip = ripoffs; i < nrips; i++, rip++) {
169 if (rip->init == init) {
170 rip->nlines = 0;
171 unripped++;
172 }
173 }
174 return unripped;
175 }
176