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