pdcurses/window.c

changeset 97
2d43f05b284c
equal deleted inserted replaced
96:5314ebdcb38d 97:2d43f05b284c
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
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
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
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
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
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
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
294 WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
295 {
296 WINDOW *win;
297 int i;
298 int j = begy - orig->_begy;
299 int k = begx - orig->_begx;
300
301 PDC_LOG(("subwin() - called: lines %d cols %d begy %d begx %d\n",
302 nlines, ncols, begy, begx));
303
304 /* make sure window fits inside the original one */
305
306 if (!orig || (begy < orig->_begy) || (begx < orig->_begx) ||
307 (begy + nlines) > (orig->_begy + orig->_maxy) ||
308 (begx + ncols) > (orig->_begx + orig->_maxx))
309 return (WINDOW *)NULL;
310
311 if (!nlines)
312 nlines = orig->_maxy - 1 - j;
313 if (!ncols)
314 ncols = orig->_maxx - 1 - k;
315
316 if ( !(win = PDC_makenew(nlines, ncols, begy, begx)) )
317 return (WINDOW *)NULL;
318
319 /* initialize window variables */
320
321 win->_attrs = orig->_attrs;
322 win->_bkgd = orig->_bkgd;
323 win->_leaveit = orig->_leaveit;
324 win->_scroll = orig->_scroll;
325 win->_nodelay = orig->_nodelay;
326 win->_use_keypad = orig->_use_keypad;
327 win->_immed = orig->_immed;
328 win->_sync = orig->_sync;
329 win->_pary = j;
330 win->_parx = k;
331 win->_parent = orig;
332
333 for (i = 0; i < nlines; i++, j++)
334 win->_y[i] = orig->_y[j] + k;
335
336 win->_flags |= _SUBWIN;
337
338 return win;
339 }
340
341 WINDOW *derwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
342 {
343 return subwin(orig, nlines, ncols, begy + orig->_begy, begx + orig->_begx);
344 }
345
346 int mvderwin(WINDOW *win, int pary, int parx)
347 {
348 int i, j;
349 WINDOW *mypar;
350
351 if (!win || !(win->_parent))
352 return ERR;
353
354 mypar = win->_parent;
355
356 if (pary < 0 || parx < 0 || (pary + win->_maxy) > mypar->_maxy ||
357 (parx + win->_maxx) > mypar->_maxx)
358 return ERR;
359
360 j = pary;
361
362 for (i = 0; i < win->_maxy; i++)
363 win->_y[i] = (mypar->_y[j++]) + parx;
364
365 win->_pary = pary;
366 win->_parx = parx;
367
368 return OK;
369 }
370
371 WINDOW *dupwin(WINDOW *win)
372 {
373 WINDOW *new;
374 chtype *ptr, *ptr1;
375 int nlines, ncols, begy, begx, i;
376
377 if (!win)
378 return (WINDOW *)NULL;
379
380 nlines = win->_maxy;
381 ncols = win->_maxx;
382 begy = win->_begy;
383 begx = win->_begx;
384
385 if ( !(new = PDC_makenew(nlines, ncols, begy, begx))
386 || !(new = PDC_makelines(new)) )
387 return (WINDOW *)NULL;
388
389 /* copy the contents of win into new */
390
391 for (i = 0; i < nlines; i++)
392 {
393 for (ptr = new->_y[i], ptr1 = win->_y[i];
394 ptr < new->_y[i] + ncols; ptr++, ptr1++)
395 *ptr = *ptr1;
396
397 new->_firstch[i] = 0;
398 new->_lastch[i] = ncols - 1;
399 }
400
401 new->_curx = win->_curx;
402 new->_cury = win->_cury;
403 new->_maxy = win->_maxy;
404 new->_maxx = win->_maxx;
405 new->_begy = win->_begy;
406 new->_begx = win->_begx;
407 new->_flags = win->_flags;
408 new->_attrs = win->_attrs;
409 new->_clear = win->_clear;
410 new->_leaveit = win->_leaveit;
411 new->_scroll = win->_scroll;
412 new->_nodelay = win->_nodelay;
413 new->_use_keypad = win->_use_keypad;
414 new->_tmarg = win->_tmarg;
415 new->_bmarg = win->_bmarg;
416 new->_parx = win->_parx;
417 new->_pary = win->_pary;
418 new->_parent = win->_parent;
419 new->_bkgd = win->_bkgd;
420 new->_flags = win->_flags;
421
422 return new;
423 }
424
425 WINDOW *resize_window(WINDOW *win, int nlines, int ncols)
426 {
427 WINDOW *new;
428 int i, save_cury, save_curx, new_begy, new_begx;
429
430 PDC_LOG(("resize_window() - called: nlines %d ncols %d\n",
431 nlines, ncols));
432
433 if (!win)
434 return (WINDOW *)NULL;
435
436 if (win->_flags & _SUBPAD)
437 {
438 if ( !(new = subpad(win->_parent, nlines, ncols,
439 win->_begy, win->_begx)) )
440 return (WINDOW *)NULL;
441 }
442 else if (win->_flags & _SUBWIN)
443 {
444 if ( !(new = subwin(win->_parent, nlines, ncols,
445 win->_begy, win->_begx)) )
446 return (WINDOW *)NULL;
447 }
448 else
449 {
450 if (win == SP->slk_winptr)
451 {
452 new_begy = SP->lines - SP->slklines;
453 new_begx = 0;
454 }
455 else
456 {
457 new_begy = win->_begy;
458 new_begx = win->_begx;
459 }
460
461 if ( !(new = PDC_makenew(nlines, ncols, new_begy, new_begx)) )
462 return (WINDOW *)NULL;
463 }
464
465 save_curx = min(win->_curx, new->_maxx);
466 save_cury = min(win->_cury, new->_maxy);
467
468 if (!(win->_flags & (_SUBPAD|_SUBWIN)))
469 {
470 if ( !(new = PDC_makelines(new)) )
471 return (WINDOW *)NULL;
472
473 werase(new);
474
475 copywin(win, new, 0, 0, 0, 0, min(win->_maxy, new->_maxy) - 1,
476 min(win->_maxx, new->_maxx) - 1, FALSE);
477
478 for (i = 0; i < win->_maxy && win->_y[i]; i++)
479 if (win->_y[i])
480 free(win->_y[i]);
481 }
482
483 new->_flags = win->_flags;
484 new->_attrs = win->_attrs;
485 new->_clear = win->_clear;
486 new->_leaveit = win->_leaveit;
487 new->_scroll = win->_scroll;
488 new->_nodelay = win->_nodelay;
489 new->_use_keypad = win->_use_keypad;
490 new->_tmarg = (win->_tmarg > new->_maxy - 1) ? 0 : win->_tmarg;
491 new->_bmarg = (win->_bmarg == win->_maxy - 1) ?
492 new->_maxy - 1 : min(win->_bmarg, (new->_maxy - 1));
493 new->_parent = win->_parent;
494 new->_immed = win->_immed;
495 new->_sync = win->_sync;
496 new->_bkgd = win->_bkgd;
497
498 new->_curx = save_curx;
499 new->_cury = save_cury;
500
501 free(win->_firstch);
502 free(win->_lastch);
503 free(win->_y);
504
505 *win = *new;
506 free(new);
507
508 return win;
509 }
510
511 int wresize(WINDOW *win, int nlines, int ncols)
512 {
513 return (resize_window(win, nlines, ncols) ? OK : ERR);
514 }
515
516 void wsyncup(WINDOW *win)
517 {
518 WINDOW *tmp;
519
520 PDC_LOG(("wsyncup() - called\n"));
521
522 for (tmp = win; tmp; tmp = tmp->_parent)
523 touchwin(tmp);
524 }
525
526 int syncok(WINDOW *win, bool bf)
527 {
528 PDC_LOG(("syncok() - called\n"));
529
530 if (!win)
531 return ERR;
532
533 win->_sync = bf;
534
535 return OK;
536 }
537
538 void wcursyncup(WINDOW *win)
539 {
540 WINDOW *tmp;
541
542 PDC_LOG(("wcursyncup() - called\n"));
543
544 for (tmp = win; tmp && tmp->_parent; tmp = tmp->_parent)
545 wmove(tmp->_parent, tmp->_pary + tmp->_cury, tmp->_parx + tmp->_curx);
546 }
547
548 void wsyncdown(WINDOW *win)
549 {
550 WINDOW *tmp;
551
552 PDC_LOG(("wsyncdown() - called\n"));
553
554 for (tmp = win; tmp; tmp = tmp->_parent)
555 {
556 if (is_wintouched(tmp))
557 {
558 touchwin(win);
559 break;
560 }
561 }
562 }

mercurial