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