xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/pdcurses/window.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 RCSID("$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 
39         delwin() deletes the named window, freeing all associated
40         memory. In the case of overlapping windows, subwindows should be
41         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 
81         resize_window() allows the user to resize an existing window. It
82         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
86         the window. (However, you still can call it _on_ subwindows.) It
87         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 
PDC_makenew(int nlines,int ncols,int begy,int begx)135 WINDOW *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 
PDC_makelines(WINDOW * win)190 WINDOW *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 
PDC_sync(WINDOW * win)223 void 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 
newwin(int nlines,int ncols,int begy,int begx)233 WINDOW *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 
delwin(WINDOW * win)255 int 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 
mvwin(WINDOW * win,int y,int x)279 int 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 
subwin(WINDOW * orig,int nlines,int ncols,int begy,int begx)294 WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
295 {
296     WINDOW *win;
297     int i, j, k;
298 
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 
309     j = begy - orig->_begy;
310     k = begx - orig->_begx;
311 
312     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 
derwin(WINDOW * orig,int nlines,int ncols,int begy,int begx)342 WINDOW *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 
mvderwin(WINDOW * win,int pary,int parx)347 int 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 
dupwin(WINDOW * win)372 WINDOW *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 
resize_window(WINDOW * win,int nlines,int ncols)426 WINDOW *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 
wresize(WINDOW * win,int nlines,int ncols)512 int wresize(WINDOW *win, int nlines, int ncols)
513 {
514     return (resize_window(win, nlines, ncols) ? OK : ERR);
515 }
516 
wsyncup(WINDOW * win)517 void 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 
syncok(WINDOW * win,bool bf)527 int 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 
wcursyncup(WINDOW * win)539 void 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 
wsyncdown(WINDOW * win)549 void 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 }
564