blob: 6065923bdf8c6d6033451c6b18ae38463417405e [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301// * this is for making emacs happy: -*-Mode: C++;-*-
2/****************************************************************************
micky3879b9f5e72025-07-08 18:04:53 -04003 * Copyright 2020 Thomas E. Dickey *
4 * Copyright 1999-2012,2013 Free Software Foundation, Inc. *
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05305 * *
6 * Permission is hereby granted, free of charge, to any person obtaining a *
7 * copy of this software and associated documentation files (the *
8 * "Software"), to deal in the Software without restriction, including *
9 * without limitation the rights to use, copy, modify, merge, publish, *
10 * distribute, distribute with modifications, sublicense, and/or sell *
11 * copies of the Software, and to permit persons to whom the Software is *
12 * furnished to do so, subject to the following conditions: *
13 * *
14 * The above copyright notice and this permission notice shall be included *
15 * in all copies or substantial portions of the Software. *
16 * *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * *
25 * Except as contained in this notice, the name(s) of the above copyright *
26 * holders shall not be used in advertising or otherwise to promote the *
27 * sale, use or other dealings in this Software without prior written *
28 * authorization. *
29 ****************************************************************************/
30
31/****************************************************************************
32 * Author: Juergen Pfeifer, 1999 *
33 ****************************************************************************/
34
35#include "internal.h"
36
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053037#include <cursesw.h>
38
micky3879b9f5e72025-07-08 18:04:53 -040039MODULE_ID("$Id: cursespad.cc,v 1.18 2020/02/02 23:34:34 tom Exp $")
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053040
41NCursesPad::NCursesPad(int nlines, int ncols)
42 : NCursesWindow(),
43 viewWin(static_cast<NCursesWindow*>(0)),
44 viewSub(static_cast<NCursesWindow*>(0)),
45 h_gridsize(0), v_gridsize(0),
46 min_row(0), min_col(0)
47{
48 w = ::newpad(nlines, ncols);
49 if (static_cast<WINDOW*>(0) == w) {
50 count--;
51 err_handler("Cannot construct window");
52 }
53 alloced = TRUE;
54}
55
56
57int NCursesPad::driver (int key)
58{
59 // Default implementation
60 switch(key) {
61 case KEY_UP:
62 // =======
63 return REQ_PAD_UP;
64 case KEY_DOWN:
65 // =========
66 return REQ_PAD_DOWN;
67 case KEY_LEFT:
68 // =========
69 return REQ_PAD_LEFT;
70 case KEY_RIGHT:
71 // ==========
72 return REQ_PAD_RIGHT;
73 case KEY_EXIT:
74 // =========
75 case CTRL('X'):
76 // ==========
77 return REQ_PAD_EXIT;
78
79 default: return(key);
80 }
81}
82
83
84void NCursesPad::operator()(void)
85{
86 NCursesWindow* W = Win();
87
88 if (static_cast<NCursesWindow*>(0) != W) {
89 int Width = W->width();
90 int Height = W->height();
91
92 int req = REQ_PAD_REFRESH;
93
94 W->keypad(TRUE);
95 W->meta(TRUE);
96 refresh();
97
98 do {
99 bool changed = FALSE;
100
101 switch (req) {
102 case REQ_PAD_REFRESH:
103 // ================
104 changed = TRUE;
105 break;
106 case REQ_PAD_LEFT:
107 // =============
108 if (min_col > 0) {
109 changed = TRUE;
110 if (min_col < h_gridsize)
111 min_col = 0;
112 else
113 min_col -= h_gridsize;
114 }
115 else
116 OnNavigationError(req);
117 break;
118 case REQ_PAD_RIGHT:
119 // ==============
120 if (min_col < (width() - Width - 1)) {
121 changed = TRUE;
122 if (min_col > (width() - Width - h_gridsize - 1))
123 min_col = width() - Width - 1;
124 else
125 min_col += h_gridsize;
126 }
127 else
128 OnNavigationError(req);
129 break;
130 case REQ_PAD_UP:
131 // ===========
132 if (min_row > 0) {
133 changed = TRUE;
134 if (min_row < v_gridsize)
135 min_row = 0;
136 else
137 min_row -= v_gridsize;
138 }
139 else
140 OnNavigationError(req);
141 break;
142 case REQ_PAD_DOWN:
143 // =============
144 if (min_row < (height() - Height - 1)) {
145 changed = TRUE;
146 if (min_row > (height() - Height - v_gridsize - 1))
147 min_row = height() - Height - 1;
148 else
149 min_row += v_gridsize;
150 }
151 else
152 OnNavigationError(req);
153 break;
154
155 default:
156 OnUnknownOperation(req);
157 }
158
159 if (changed) {
160 noutrefresh();
161 W->syncup();
162 OnOperation(req);
163 viewWin->refresh();
164 }
165 } while( (req=driver(W->getch())) != REQ_PAD_EXIT );
166 }
167}
168
169
170int NCursesPad::refresh()
171{
172 int res = noutrefresh();
173 if (res==OK && (static_cast<NCursesWindow*>(0) != viewWin)) {
174 res = (viewWin->refresh());
175 }
176 return(res);
177}
178
179int NCursesPad::noutrefresh()
180{
181 int res = OK;
182 NCursesWindow* W = Win();
183 if (static_cast<NCursesWindow*>(0) != W) {
184 int high = W->maxy();
185 int wide = W->maxx();
186 res = copywin(*W, min_row, min_col,
187 0, 0, high, wide,
188 FALSE);
189 if (res==OK) {
190 W->syncup();
191 res = viewWin->noutrefresh();
192 }
193 }
194 return (res);
195}
196
197void NCursesPad::setWindow(NCursesWindow& view,
198 int v_grid NCURSES_PARAM_INIT(1),
199 int h_grid NCURSES_PARAM_INIT(1))
200{
201 viewWin = &view;
202 min_row = min_col = 0;
203 if (h_grid <=0 || v_grid <= 0)
204 err_handler("Illegal Gridsize");
205 else {
206 h_gridsize = h_grid;
207 v_gridsize = v_grid;
208 }
209}
210
211void NCursesPad::setSubWindow(NCursesWindow& sub)
212{
213 if (static_cast<NCursesWindow*>(0) == viewWin)
214 err_handler("Pad has no viewport");
215 assert(viewWin != 0);
216 if (!viewWin->isDescendant(sub))
217 THROW(new NCursesException("NCursesFramePad", E_SYSTEM_ERROR));
218 viewSub = &sub;
219}
220
221void NCursesFramedPad::OnOperation(int pad_req)
222{
Steve Kondikae271bc2015-11-15 02:50:53 +0100223 (void) pad_req;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530224 NCursesWindow* W = Win();
225 NCursesWindow* W2 = getWindow();
226
227 if ((static_cast<NCursesWindow*>(0) != W) && (static_cast<NCursesWindow*>(0) != W2)) {
228 int Width = W->width();
229 int Height = W->height();
230 int i, row, col, h_len, v_len;
231
Steve Kondikae271bc2015-11-15 02:50:53 +0100232 int my_width = width();
233
234 if (my_width != 0) {
235 h_len = (Width*Width + my_width - 1) / my_width;
236 if (h_len==0)
237 h_len = 1;
238 if (h_len > Width)
239 h_len = Width;
240 } else {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530241 h_len = 1;
Steve Kondikae271bc2015-11-15 02:50:53 +0100242 }
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530243
Steve Kondikae271bc2015-11-15 02:50:53 +0100244 int my_height = height();
245
246 if (my_height != 0) {
247 v_len = (Height*Height + my_height - 1) / my_height;
248 if (v_len==0)
249 v_len = 1;
250 if (v_len > Height)
251 v_len = Height;
252 } else {
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530253 v_len = 1;
Steve Kondikae271bc2015-11-15 02:50:53 +0100254 }
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530255
Steve Kondikae271bc2015-11-15 02:50:53 +0100256 if (my_width != 0) {
257 col = (min_col * Width + my_width - 1) / my_width;
258 if (col + h_len > Width)
259 col = Width - h_len;
260 } else {
261 col = 0;
262 }
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530263
Steve Kondikae271bc2015-11-15 02:50:53 +0100264 if (my_height != 0) {
265 row = (min_row * Height + my_height - 1) / my_height;
266 if (row + v_len > Height)
267 row = Height - v_len;
268 } else {
269 row = 0;
270 }
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530271
272 W2->vline(1,Width+1,Height);
273 W2->attron(A_REVERSE);
274 if (v_len>=2) {
275 W2->addch(row+1,Width+1,ACS_UARROW);
276 for(i=2;i<v_len;i++)
277 W2->addch(row+i,Width+1,' ');
278 W2->addch(row+v_len,Width+1,ACS_DARROW);
279 }
280 else {
281 for(i=1;i<=v_len;i++)
282 W2->addch(row+i,Width+1,' ');
283 }
284 W2->attroff(A_REVERSE);
285
286 W2->hline(Height+1,1,Width);
287 W2->attron(A_REVERSE);
288 if (h_len >= 2) {
289 W2->addch(Height+1,col+1,ACS_LARROW);
290 for(i=2;i<h_len;i++)
291 W2->addch(Height+1,col+i,' ');
292 W2->addch(Height+1,col+h_len,ACS_RARROW);
293 }
294 else {
295 for(i=1;i<=h_len;i++)
296 W2->addch(Height+1,col+i,' ');
297 }
298 W2->attroff(A_REVERSE);
299 }
300}