|
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 } |