ripoffline.c revision 1.1 1 /* $NetBSD: ripoffline.c,v 1.1 2017/01/11 20:43:03 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.1 2017/01/11 20:43:03 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_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 nlines = srip->nlines < 0 ? -srip->nlines : srip->nlines;
107 w = __newwin(screen, nlines, 0,
108 srip->nlines < 0 ? LINES - nlines : *rtop,
109 0, FALSE);
110 if (w != NULL) {
111 rip->win = w;
112 rip->nlines = srip->nlines;
113 rip++;
114 screen->nripped++;
115 if (rip->nlines > 0)
116 (*rtop) += rip->nlines;
117 LINES -= nlines;
118 }
119 if (srip->init(w, COLS) == ERR)
120 return ERR;
121 #ifdef DEBUG
122 if (w != NULL)
123 __CTRACE(__CTRACE_SCREEN,
124 "newterm: ripped %d lines from the %s\n",
125 nlines, srip->nlines < 0 ? "bottom" : "top");
126 #endif
127 }
128 nrips = 0; /* Reset the stack. */
129 return OK;
130 }
131
132 /*
133 * __ripoffresize --
134 * Called from resizeterm to ensure the ripped off lines are correctly
135 * placed and refreshed.
136 */
137 void
138 __ripoffresize(SCREEN *screen)
139 {
140 int rbot = _cursesi_screen->LINES, i;
141 struct __ripoff *rip;
142
143 for (i = 0, rip = _cursesi_screen->ripped;
144 i < _cursesi_screen->nripped;
145 i++, rip++)
146 {
147 if (rip->nlines > 0)
148 touchwin(rip->win);
149 else {
150 /* Reposition the lower windows. */
151 mvwin(rip->win, rbot + rip->nlines, 0);
152 rbot += rip->nlines;
153 }
154 wnoutrefresh(rip->win);
155 }
156 }
157