blob: 24c5fd29d3c4eb6ce5bcb826f9fdd60bf04a54cd [file] [log] [blame]
Patrick Georgi3b77b722011-07-07 15:41:53 +02001/* Public Domain Curses */
2
3#include <curspriv.h>
4
5RCSID("$Id: window.c,v 1.62 2008/07/13 16:08:18 wmcbrine Exp $")
6
7/*man-start**************************************************************
8
9 Name: window
10
11 Synopsis:
12 WINDOW *newwin(int nlines, int ncols, int begy, int begx);
13 WINDOW *derwin(WINDOW* orig, int nlines, int ncols,
14 int begy, int begx);
15 WINDOW *subwin(WINDOW* orig, int nlines, int ncols,
16 int begy, int begx);
17 WINDOW *dupwin(WINDOW *win);
18 int delwin(WINDOW *win);
19 int mvwin(WINDOW *win, int y, int x);
20 int mvderwin(WINDOW *win, int pary, int parx);
21 int syncok(WINDOW *win, bool bf);
22 void wsyncup(WINDOW *win);
23 void wcursyncup(WINDOW *win);
24 void wsyncdown(WINDOW *win);
25
26 WINDOW *resize_window(WINDOW *win, int nlines, int ncols);
27 int wresize(WINDOW *win, int nlines, int ncols);
28 WINDOW *PDC_makelines(WINDOW *win);
29 WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx);
30 void PDC_sync(WINDOW *win);
31
32 Description:
33 newwin() creates a new window with the given number of lines,
34 nlines and columns, ncols. The upper left corner of the window
35 is at line begy, column begx. If nlines is zero, it defaults to
36 LINES - begy; ncols to COLS - begx. Create a new full-screen
37 window by calling newwin(0, 0, 0, 0).
38
Stefan Reinauere11835e2011-10-31 12:54:00 -070039 delwin() deletes the named window, freeing all associated
40 memory. In the case of overlapping windows, subwindows should be
Patrick Georgi3b77b722011-07-07 15:41:53 +020041 deleted before the main window.
42
43 mvwin() moves the window so that the upper left-hand corner is
44 at position (y,x). If the move would cause the window to be off
45 the screen, it is an error and the window is not moved. Moving
46 subwindows is allowed.
47
48 subwin() creates a new subwindow within a window. The
49 dimensions of the subwindow are nlines lines and ncols columns.
50 The subwindow is at position (begy, begx) on the screen. This
51 position is relative to the screen, and not to the window orig.
52 Changes made to either window will affect both. When using this
53 routine, you will often need to call touchwin() before calling
54 wrefresh().
55
56 derwin() is the same as subwin(), except that begy and begx are
57 relative to the origin of the window orig rather than the
58 screen. There is no difference between subwindows and derived
59 windows.
60
61 mvderwin() moves a derived window (or subwindow) inside its
62 parent window. The screen-relative parameters of the window are
63 not changed. This routine is used to display different parts of
64 the parent window at the same physical position on the screen.
65
66 dupwin() creates an exact duplicate of the window win.
67
68 wsyncup() causes a touchwin() of all of the window's parents.
69
70 If wsyncok() is called with a second argument of TRUE, this
71 causes a wsyncup() to be called every time the window is
72 changed.
73
74 wcursyncup() causes the current cursor position of all of a
75 window's ancestors to reflect the current cursor position of the
76 current window.
77
78 wsyncdown() causes a touchwin() of the current window if any of
79 its parent's windows have been touched.
80
Stefan Reinauere11835e2011-10-31 12:54:00 -070081 resize_window() allows the user to resize an existing window. It
Patrick Georgi3b77b722011-07-07 15:41:53 +020082 returns the pointer to the new window, or NULL on failure.
83
84 wresize() is an ncurses-compatible wrapper for resize_window().
85 Note that, unlike ncurses, it will NOT process any subwindows of
Stefan Reinauere11835e2011-10-31 12:54:00 -070086 the window. (However, you still can call it _on_ subwindows.) It
Patrick Georgi3b77b722011-07-07 15:41:53 +020087 returns OK or ERR.
88
89 PDC_makenew() allocates all data for a new WINDOW * except the
90 actual lines themselves. If it's unable to allocate memory for
91 the window structure, it will free all allocated memory and
92 return a NULL pointer.
93
94 PDC_makelines() allocates the memory for the lines.
95
96 PDC_sync() handles wrefresh() and wsyncup() calls when a window
97 is changed.
98
99 Return Value:
100 newwin(), subwin(), derwin() and dupwin() return a pointer
101 to the new window, or NULL on failure. delwin(), mvwin(),
102 mvderwin() and syncok() return OK or ERR. wsyncup(),
103 wcursyncup() and wsyncdown() return nothing.
104
105 Errors:
106 It is an error to call resize_window() before calling initscr().
107 Also, an error will be generated if we fail to create a newly
108 sized replacement window for curscr, or stdscr. This could
109 happen when increasing the window size. NOTE: If this happens,
110 the previously successfully allocated windows are left alone;
111 i.e., the resize is NOT cancelled for those windows.
112
113 Portability X/Open BSD SYS V
114 newwin Y Y Y
115 delwin Y Y Y
116 mvwin Y Y Y
117 subwin Y Y Y
118 derwin Y - Y
119 mvderwin Y - Y
120 dupwin Y - 4.0
121 wsyncup Y - 4.0
122 syncok Y - 4.0
123 wcursyncup Y - 4.0
124 wsyncdown Y - 4.0
125 resize_window - - -
126 wresize - - -
127 PDC_makelines - - -
128 PDC_makenew - - -
129 PDC_sync - - -
130
131**man-end****************************************************************/
132
133#include <stdlib.h>
134
135WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx)
136{
137 WINDOW *win;
138
139 PDC_LOG(("PDC_makenew() - called: lines %d cols %d begy %d begx %d\n",
140 nlines, ncols, begy, begx));
141
142 /* allocate the window structure itself */
143
144 if ((win = calloc(1, sizeof(WINDOW))) == (WINDOW *)NULL)
145 return win;
146
147 /* allocate the line pointer array */
148
149 if ((win->_y = malloc(nlines * sizeof(chtype *))) == NULL)
150 {
151 free(win);
152 return (WINDOW *)NULL;
153 }
154
155 /* allocate the minchng and maxchng arrays */
156
157 if ((win->_firstch = malloc(nlines * sizeof(int))) == NULL)
158 {
159 free(win->_y);
160 free(win);
161 return (WINDOW *)NULL;
162 }
163
164 if ((win->_lastch = malloc(nlines * sizeof(int))) == NULL)
165 {
166 free(win->_firstch);
167 free(win->_y);
168 free(win);
169 return (WINDOW *)NULL;
170 }
171
172 /* initialize window variables */
173
174 win->_maxy = nlines; /* real max screen size */
175 win->_maxx = ncols; /* real max screen size */
176 win->_begy = begy;
177 win->_begx = begx;
178 win->_bkgd = ' '; /* wrs 4/10/93 -- initialize background to blank */
179 win->_clear = (bool) ((nlines == LINES) && (ncols == COLS));
180 win->_bmarg = nlines - 1;
181 win->_parx = win->_pary = -1;
182
183 /* init to say window all changed */
184
185 touchwin(win);
186
187 return win;
188}
189
190WINDOW *PDC_makelines(WINDOW *win)
191{
192 int i, j, nlines, ncols;
193
194 PDC_LOG(("PDC_makelines() - called: lines %d cols %d\n", nlines, ncols));
195
196 if (!win)
197 return (WINDOW *)NULL;
198
199 nlines = win->_maxy;
200 ncols = win->_maxx;
201
202 for (i = 0; i < nlines; i++)
203 {
204 if ((win->_y[i] = malloc(ncols * sizeof(chtype))) == NULL)
205 {
206 /* if error, free all the data */
207
208 for (j = 0; j < i; j++)
209 free(win->_y[j]);
210
211 free(win->_firstch);
212 free(win->_lastch);
213 free(win->_y);
214 free(win);
215
216 return (WINDOW *)NULL;
217 }
218 }
219
220 return win;
221}
222
223void PDC_sync(WINDOW *win)
224{
225 PDC_LOG(("PDC_sync() - called:\n"));
226
227 if (win->_immed)
228 wrefresh(win);
229 if (win->_sync)
230 wsyncup(win);
231}
232
233WINDOW *newwin(int nlines, int ncols, int begy, int begx)
234{
235 WINDOW *win;
236
237 PDC_LOG(("newwin() - called:lines=%d cols=%d begy=%d begx=%d\n",
238 nlines, ncols, begy, begx));
239
240 if (!nlines)
241 nlines = LINES - begy;
242 if (!ncols)
243 ncols = COLS - begx;
244
245 if ( (begy + nlines > SP->lines || begx + ncols > SP->cols)
246 || !(win = PDC_makenew(nlines, ncols, begy, begx))
247 || !(win = PDC_makelines(win)) )
248 return (WINDOW *)NULL;
249
250 werase(win);
251
252 return win;
253}
254
255int delwin(WINDOW *win)
256{
257 int i;
258
259 PDC_LOG(("delwin() - called\n"));
260
261 if (!win)
262 return ERR;
263
264 /* subwindows use parents' lines */
265
266 if (!(win->_flags & (_SUBWIN|_SUBPAD)))
267 for (i = 0; i < win->_maxy && win->_y[i]; i++)
268 if (win->_y[i])
269 free(win->_y[i]);
270
271 free(win->_firstch);
272 free(win->_lastch);
273 free(win->_y);
274 free(win);
275
276 return OK;
277}
278
279int mvwin(WINDOW *win, int y, int x)
280{
281 PDC_LOG(("mvwin() - called\n"));
282
283 if (!win || (y + win->_maxy > LINES || y < 0)
284 || (x + win->_maxx > COLS || x < 0))
285 return ERR;
286
287 win->_begy = y;
288 win->_begx = x;
289 touchwin(win);
290
291 return OK;
292}
293
294WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
295{
296 WINDOW *win;
Patrick Georgi83f75bf2016-12-13 15:47:22 +0100297 int i, j, k;
Patrick Georgi3b77b722011-07-07 15:41:53 +0200298
299 PDC_LOG(("subwin() - called: lines %d cols %d begy %d begx %d\n",
300 nlines, ncols, begy, begx));
301
302 /* make sure window fits inside the original one */
303
304 if (!orig || (begy < orig->_begy) || (begx < orig->_begx) ||
305 (begy + nlines) > (orig->_begy + orig->_maxy) ||
306 (begx + ncols) > (orig->_begx + orig->_maxx))
307 return (WINDOW *)NULL;
308
Patrick Georgi83f75bf2016-12-13 15:47:22 +0100309 j = begy - orig->_begy;
310 k = begx - orig->_begx;
311
Patrick Georgi3b77b722011-07-07 15:41:53 +0200312 if (!nlines)
313 nlines = orig->_maxy - 1 - j;
314 if (!ncols)
315 ncols = orig->_maxx - 1 - k;
316
317 if ( !(win = PDC_makenew(nlines, ncols, begy, begx)) )
318 return (WINDOW *)NULL;
319
320 /* initialize window variables */
321
322 win->_attrs = orig->_attrs;
323 win->_bkgd = orig->_bkgd;
324 win->_leaveit = orig->_leaveit;
325 win->_scroll = orig->_scroll;
326 win->_nodelay = orig->_nodelay;
327 win->_use_keypad = orig->_use_keypad;
328 win->_immed = orig->_immed;
329 win->_sync = orig->_sync;
330 win->_pary = j;
331 win->_parx = k;
332 win->_parent = orig;
333
334 for (i = 0; i < nlines; i++, j++)
335 win->_y[i] = orig->_y[j] + k;
336
337 win->_flags |= _SUBWIN;
338
339 return win;
340}
341
342WINDOW *derwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
343{
344 return subwin(orig, nlines, ncols, begy + orig->_begy, begx + orig->_begx);
345}
346
347int mvderwin(WINDOW *win, int pary, int parx)
348{
349 int i, j;
350 WINDOW *mypar;
351
352 if (!win || !(win->_parent))
353 return ERR;
354
355 mypar = win->_parent;
356
357 if (pary < 0 || parx < 0 || (pary + win->_maxy) > mypar->_maxy ||
358 (parx + win->_maxx) > mypar->_maxx)
359 return ERR;
360
361 j = pary;
362
363 for (i = 0; i < win->_maxy; i++)
364 win->_y[i] = (mypar->_y[j++]) + parx;
365
366 win->_pary = pary;
367 win->_parx = parx;
368
369 return OK;
370}
371
372WINDOW *dupwin(WINDOW *win)
373{
374 WINDOW *new;
375 chtype *ptr, *ptr1;
376 int nlines, ncols, begy, begx, i;
377
378 if (!win)
379 return (WINDOW *)NULL;
380
381 nlines = win->_maxy;
382 ncols = win->_maxx;
383 begy = win->_begy;
384 begx = win->_begx;
385
386 if ( !(new = PDC_makenew(nlines, ncols, begy, begx))
387 || !(new = PDC_makelines(new)) )
388 return (WINDOW *)NULL;
389
390 /* copy the contents of win into new */
391
392 for (i = 0; i < nlines; i++)
393 {
394 for (ptr = new->_y[i], ptr1 = win->_y[i];
395 ptr < new->_y[i] + ncols; ptr++, ptr1++)
396 *ptr = *ptr1;
397
398 new->_firstch[i] = 0;
399 new->_lastch[i] = ncols - 1;
400 }
401
402 new->_curx = win->_curx;
403 new->_cury = win->_cury;
404 new->_maxy = win->_maxy;
405 new->_maxx = win->_maxx;
406 new->_begy = win->_begy;
407 new->_begx = win->_begx;
408 new->_flags = win->_flags;
409 new->_attrs = win->_attrs;
410 new->_clear = win->_clear;
411 new->_leaveit = win->_leaveit;
412 new->_scroll = win->_scroll;
413 new->_nodelay = win->_nodelay;
414 new->_use_keypad = win->_use_keypad;
415 new->_tmarg = win->_tmarg;
416 new->_bmarg = win->_bmarg;
417 new->_parx = win->_parx;
418 new->_pary = win->_pary;
419 new->_parent = win->_parent;
420 new->_bkgd = win->_bkgd;
421 new->_flags = win->_flags;
422
423 return new;
424}
425
426WINDOW *resize_window(WINDOW *win, int nlines, int ncols)
427{
428 WINDOW *new;
429 int i, save_cury, save_curx, new_begy, new_begx;
430
431 PDC_LOG(("resize_window() - called: nlines %d ncols %d\n",
432 nlines, ncols));
433
434 if (!win)
435 return (WINDOW *)NULL;
436
437 if (win->_flags & _SUBPAD)
438 {
439 if ( !(new = subpad(win->_parent, nlines, ncols,
440 win->_begy, win->_begx)) )
441 return (WINDOW *)NULL;
442 }
443 else if (win->_flags & _SUBWIN)
444 {
445 if ( !(new = subwin(win->_parent, nlines, ncols,
446 win->_begy, win->_begx)) )
447 return (WINDOW *)NULL;
448 }
449 else
450 {
451 if (win == SP->slk_winptr)
452 {
453 new_begy = SP->lines - SP->slklines;
454 new_begx = 0;
455 }
456 else
457 {
458 new_begy = win->_begy;
459 new_begx = win->_begx;
460 }
461
462 if ( !(new = PDC_makenew(nlines, ncols, new_begy, new_begx)) )
463 return (WINDOW *)NULL;
464 }
465
466 save_curx = min(win->_curx, new->_maxx);
467 save_cury = min(win->_cury, new->_maxy);
468
469 if (!(win->_flags & (_SUBPAD|_SUBWIN)))
470 {
471 if ( !(new = PDC_makelines(new)) )
472 return (WINDOW *)NULL;
473
474 werase(new);
475
476 copywin(win, new, 0, 0, 0, 0, min(win->_maxy, new->_maxy) - 1,
477 min(win->_maxx, new->_maxx) - 1, FALSE);
478
479 for (i = 0; i < win->_maxy && win->_y[i]; i++)
480 if (win->_y[i])
481 free(win->_y[i]);
482 }
483
484 new->_flags = win->_flags;
485 new->_attrs = win->_attrs;
486 new->_clear = win->_clear;
487 new->_leaveit = win->_leaveit;
488 new->_scroll = win->_scroll;
489 new->_nodelay = win->_nodelay;
490 new->_use_keypad = win->_use_keypad;
491 new->_tmarg = (win->_tmarg > new->_maxy - 1) ? 0 : win->_tmarg;
492 new->_bmarg = (win->_bmarg == win->_maxy - 1) ?
493 new->_maxy - 1 : min(win->_bmarg, (new->_maxy - 1));
494 new->_parent = win->_parent;
495 new->_immed = win->_immed;
496 new->_sync = win->_sync;
497 new->_bkgd = win->_bkgd;
498
499 new->_curx = save_curx;
500 new->_cury = save_cury;
501
502 free(win->_firstch);
503 free(win->_lastch);
504 free(win->_y);
505
506 *win = *new;
507 free(new);
508
509 return win;
510}
511
512int wresize(WINDOW *win, int nlines, int ncols)
513{
514 return (resize_window(win, nlines, ncols) ? OK : ERR);
515}
516
517void wsyncup(WINDOW *win)
518{
519 WINDOW *tmp;
520
521 PDC_LOG(("wsyncup() - called\n"));
522
523 for (tmp = win; tmp; tmp = tmp->_parent)
524 touchwin(tmp);
525}
526
527int syncok(WINDOW *win, bool bf)
528{
529 PDC_LOG(("syncok() - called\n"));
530
531 if (!win)
532 return ERR;
533
534 win->_sync = bf;
535
536 return OK;
537}
538
539void wcursyncup(WINDOW *win)
540{
541 WINDOW *tmp;
542
543 PDC_LOG(("wcursyncup() - called\n"));
544
545 for (tmp = win; tmp && tmp->_parent; tmp = tmp->_parent)
546 wmove(tmp->_parent, tmp->_pary + tmp->_cury, tmp->_parx + tmp->_curx);
547}
548
549void wsyncdown(WINDOW *win)
550{
551 WINDOW *tmp;
552
553 PDC_LOG(("wsyncdown() - called\n"));
554
555 for (tmp = win; tmp; tmp = tmp->_parent)
556 {
557 if (is_wintouched(tmp))
558 {
559 touchwin(win);
560 break;
561 }
562 }
563}