Release v.5.0.0
[screen.git] / src / canvas.c
blob74aa7a6ceffef52f3e64517a2690c729500b7fd6
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include "config.h"
31 #include "canvas.h"
33 #include "screen.h"
34 #include "help.h"
35 #include "list_generic.h"
36 #include "resize.h"
37 #include "winmsg.h"
39 static void CanvasInitBlank(Canvas *cv)
41 cv->c_blank.l_cvlist = cv;
42 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
43 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
44 cv->c_blank.l_x = cv->c_blank.l_y = 0;
45 cv->c_blank.l_layfn = &BlankLf;
46 cv->c_blank.l_data = NULL;
47 cv->c_blank.l_next = NULL;
48 cv->c_blank.l_bottom = &cv->c_blank;
49 cv->c_blank.l_blocking = 0;
50 cv->c_layer = &cv->c_blank;
53 static void FreePerp(Canvas *pcv)
55 Canvas *cv;
57 if (!pcv->c_slperp)
58 return;
59 cv = pcv->c_slperp;
60 cv->c_slprev = pcv->c_slprev;
61 if (cv->c_slprev)
62 cv->c_slprev->c_slnext = cv;
63 cv->c_slback = pcv->c_slback;
64 if (cv->c_slback && cv->c_slback->c_slperp == pcv)
65 cv->c_slback->c_slperp = cv;
66 cv->c_slorient = pcv->c_slorient;
67 cv->c_slweight = pcv->c_slweight;
68 while (cv->c_slnext) {
69 cv = cv->c_slnext;
70 cv->c_slorient = pcv->c_slorient;
71 cv->c_slback = pcv->c_slback;
72 cv->c_slweight = pcv->c_slweight;
74 cv->c_slnext = pcv->c_slnext;
75 if (cv->c_slnext)
76 cv->c_slnext->c_slprev = cv;
77 LayerCleanupMemory(&pcv->c_blank);
78 free(pcv);
81 void FreeCanvas(Canvas *cv)
83 Viewport *vp, *nvp;
84 Window *win;
86 if (cv->c_slprev)
87 cv->c_slprev->c_slnext = cv->c_slnext;
88 if (cv->c_slnext)
89 cv->c_slnext->c_slprev = cv->c_slprev;
90 if (cv->c_slback && cv->c_slback->c_slperp == cv)
91 cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
92 if (cv->c_slperp) {
93 while (cv->c_slperp)
94 FreeCanvas(cv->c_slperp);
95 LayerCleanupMemory(&cv->c_blank);
96 free(cv);
97 return;
100 if (display) {
101 if (D_forecv == cv)
102 D_forecv = NULL;
103 /* remove from canvas chain as SetCanvasWindow might call
104 * some layer function */
105 for (Canvas **cvp = &D_cvlist; *cvp; cvp = &(*cvp)->c_next)
106 if (*cvp == cv) {
107 *cvp = cv->c_next;
108 break;
111 win = cv->c_layer ? Layer2Window(cv->c_layer) : NULL;
112 SetCanvasWindow(cv, NULL);
113 if (win)
114 WindowChanged(win, 'u');
115 if (flayer == cv->c_layer)
116 flayer = NULL;
117 for (vp = cv->c_vplist; vp; vp = nvp) {
118 vp->v_canvas = NULL;
119 nvp = vp->v_next;
120 vp->v_next = NULL;
121 free(vp);
123 evdeq(&cv->c_captev);
124 LayerCleanupMemory(&cv->c_blank);
125 free(cv);
128 int CountCanvas(Canvas *cv)
130 int num = 0;
131 for (; cv; cv = cv->c_slnext) {
132 if (cv->c_slperp) {
133 num += CountCanvasPerp(cv);
134 } else
135 num++;
137 return num;
140 int CountCanvasPerp(Canvas *cv)
142 int num = 1;
143 for (Canvas *cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
144 if (cvp->c_slperp) {
145 int n = CountCanvas(cvp->c_slperp);
146 if (n > num)
147 num = n;
149 return num;
152 Canvas *FindCanvas(int x, int y)
154 Canvas *mcv = NULL;
155 int m, mm = 0;
157 for (Canvas *cv = D_cvlist; cv; cv = cv->c_next) {
158 if (x >= cv->c_xs && x <= cv->c_xe) {
159 if (y >= cv->c_ys && y <= cv->c_ye)
160 return cv;
161 if (captiontop && y == cv->c_ys - 1)
162 return cv;
163 if (!captiontop && y == cv->c_ye + 1)
164 return cv;
166 if (cv == D_forecv)
167 continue;
168 m = 0;
169 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe) {
170 if (x < cv->c_xs || x > cv->c_xe)
171 continue;
172 if (y < D_forecv->c_ys && y < cv->c_ys)
173 continue;
174 if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
175 continue;
176 if (y < cv->c_ys)
177 m = cv->c_ys - y;
178 if (y > cv->c_ye + 1)
179 m = y - (cv->c_ye + 1);
181 if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1) {
182 if (y < cv->c_ys || y > cv->c_ye + 1)
183 continue;
184 if (x < D_forecv->c_xs && x < cv->c_xs)
185 continue;
186 if (x > D_forecv->c_xe && x > cv->c_xe)
187 continue;
188 if (x < cv->c_xs)
189 m = cv->c_xs - x;
190 if (x > cv->c_xe)
191 m = x - cv->c_xe;
193 if (m && (!mm || m < mm)) {
194 mcv = cv;
195 mm = m;
198 return mcv ? mcv : D_forecv;
201 void SetCanvasWindow(Canvas *cv, Window *window)
203 Window *p = NULL, **pp;
204 Layer *l;
205 Canvas *cvp, **cvpp;
207 l = cv->c_layer;
208 display = cv->c_display;
210 if (l) {
211 /* remove old layer */
212 for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
213 if (cvp == cv)
214 break;
215 *cvpp = cvp->c_lnext;
217 p = Layer2Window(l);
218 l = cv->c_layer;
219 cv->c_layer = NULL;
221 if (p && cv == D_forecv) {
222 ReleaseAutoWritelock(display, p);
223 if (p->w_silence) {
224 SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
225 evenq(&p->w_silenceev);
227 D_other = fore;
228 D_fore = NULL;
230 if (l->l_cvlist == NULL && (p == NULL || l != p->w_savelayer))
231 KillLayerChain(l);
234 /* find right layer to display on canvas */
235 if (window && window->w_type != W_TYPE_GROUP) {
236 l = &window->w_layer;
237 if (window->w_savelayer && (window->w_blocked || window->w_savelayer->l_cvlist == NULL))
238 l = window->w_savelayer;
239 } else {
240 l = &cv->c_blank;
241 if (window)
242 l->l_data = (char *)window;
243 else
244 l->l_data = NULL;
247 /* add our canvas to the layer's canvaslist */
248 cv->c_lnext = l->l_cvlist;
249 l->l_cvlist = cv;
250 cv->c_layer = l;
251 cv->c_xoff = cv->c_xs;
252 cv->c_yoff = cv->c_ys;
253 RethinkViewportOffsets(cv);
255 if (flayer == NULL)
256 flayer = l;
258 if (window && window->w_type == W_TYPE_GROUP) {
259 /* auto-start windowlist on groups */
260 Display *d = display;
261 Layer *oldflayer = flayer;
262 flayer = l;
263 display_windows(0, 0, window);
264 flayer = oldflayer;
265 display = d;
268 if (window && D_other == window)
269 D_other = window->w_prev_mru; /* Might be 0, but that's OK. */
270 if (cv == D_forecv) {
271 D_fore = window;
272 fore = D_fore; /* XXX ? */
273 if (window) {
274 ObtainAutoWritelock(display, window);
276 * Place the window at the head of the most-recently-used list
278 if (mru_window != window) {
279 for (pp = &mru_window; (p = *pp); pp = &p->w_prev_mru)
280 if (p == window)
281 break;
282 *pp = p->w_prev_mru;
283 p->w_prev_mru = mru_window;
284 mru_window = p;
285 WListLinkChanged();
291 static void cv_winid_fn(Event *ev, void *data)
293 int ox, oy;
294 Canvas *cv = (Canvas *)data;
296 display = cv->c_display;
297 if (D_status == STATUS_ON_WIN) {
298 SetTimeout(ev, 1);
299 evenq(ev);
300 return;
302 ox = D_x;
303 oy = D_y;
304 if (cv->c_ye + 1 < D_height)
305 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
306 if (ox != -1 && oy != -1)
307 GotoPos(ox, oy);
310 int MakeDefaultCanvas(void)
312 Canvas *cv;
314 if ((cv = calloc(1, sizeof(Canvas))) == NULL)
315 return -1;
316 cv->c_xs = 0;
317 cv->c_xe = D_width - 1;
318 cv->c_ys = (D_has_hstatus == HSTATUS_FIRSTLINE) + captionalways * captiontop;
319 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways * !captiontop;
320 cv->c_xoff = 0;
321 cv->c_yoff = 0;
322 cv->c_next = NULL;
323 cv->c_display = display;
324 cv->c_vplist = NULL;
325 cv->c_slnext = NULL;
326 cv->c_slprev = NULL;
327 cv->c_slperp = NULL;
328 cv->c_slweight = 1;
329 cv->c_slback = &D_canvas;
330 D_canvas.c_slperp = cv;
331 D_canvas.c_xs = cv->c_xs;
332 D_canvas.c_xe = cv->c_xe;
333 D_canvas.c_ys = cv->c_ys;
334 D_canvas.c_ye = cv->c_ye;
335 cv->c_slorient = SLICE_UNKN;
336 cv->c_captev.type = EV_TIMEOUT;
337 cv->c_captev.data = (char *)cv;
338 cv->c_captev.handler = cv_winid_fn;
340 CanvasInitBlank(cv);
341 cv->c_lnext = NULL;
343 D_cvlist = cv;
344 RethinkDisplayViewports();
345 D_forecv = cv; /* default input focus */
346 return 0;
349 static Canvas **CreateCanvasChainRec(Canvas *cv, Canvas **cvp)
351 for (; cv; cv = cv->c_slnext) {
352 if (cv->c_slperp)
353 cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
354 else {
355 *cvp = cv;
356 cvp = &cv->c_next;
359 return cvp;
362 void RecreateCanvasChain(void)
364 Canvas **cvp;
365 cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
366 *cvp = NULL;
369 void EqualizeCanvas(Canvas *cv, bool gflag)
371 for (; cv; cv = cv->c_slnext) {
372 if (cv->c_slperp && gflag) {
373 cv->c_slweight = CountCanvasPerp(cv);
374 for (Canvas *cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
375 if (cv2->c_slperp)
376 EqualizeCanvas(cv2->c_slperp, gflag);
377 } else
378 cv->c_slweight = 1;
382 void ResizeCanvas(Canvas *cv)
384 Canvas *cv2, *cvn, *fcv;
385 int nh, i, maxi, hh, m, w, wsum;
386 int need, got;
387 int xs, ys, xe, ye;
388 int focusmin = 0;
390 xs = cv->c_xs;
391 ys = cv->c_ys;
392 xe = cv->c_xe;
393 ye = cv->c_ye;
394 cv = cv->c_slperp;
395 if (cv == NULL)
396 return;
397 if (cv->c_slorient == SLICE_UNKN) {
398 cv->c_xs = xs;
399 cv->c_xe = xe;
400 cv->c_ys = ys;
401 cv->c_ye = ye;
402 cv->c_xoff = cv->c_xs;
403 cv->c_yoff = cv->c_ys;
404 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
405 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
406 return;
409 fcv = NULL;
410 if (focusminwidth || focusminheight) {
411 cv2 = D_forecv;
412 while (cv2->c_slback) {
413 if (cv2->c_slback == cv->c_slback) {
414 fcv = cv2;
415 focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
416 if (focusmin > 0)
417 focusmin--;
418 else if (focusmin < 0)
419 focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
421 cv2 = cv2->c_slback;
424 if (focusmin) {
425 m = CountCanvas(cv) * 2;
426 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
427 nh -= m;
428 if (nh < 0)
429 nh = 0;
430 if (focusmin > nh)
431 focusmin = nh;
434 /* pass 1: calculate weight sum */
435 for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext) {
436 wsum += cv2->c_slweight;
438 if (wsum == 0)
439 wsum = 1;
440 w = wsum;
442 /* pass 2: calculate need/excess space */
443 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
444 for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext) {
445 m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
446 if (cv2 == fcv)
447 m += focusmin;
448 hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
449 w -= cv2->c_slweight;
450 nh -= hh;
451 if (hh <= m + 1)
452 need += m + 1 - hh;
453 else
454 got += hh - m - 1;
456 if (need > got)
457 need = got;
459 /* pass 3: distribute space */
460 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
461 i = cv->c_slorient == SLICE_VERT ? ys : xs;
462 maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
463 w = wsum;
464 for (; cv; cv = cvn) {
465 cvn = cv->c_slnext;
466 if (i > maxi) {
467 if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp
468 && !cv->c_slprev->c_slprev) {
469 cv->c_slprev->c_slorient = SLICE_UNKN;
470 if (!captionalways) {
471 if (captiontop) {
472 cv->c_slback->c_ys--;
473 cv->c_slprev->c_ys--;
474 } else {
475 cv->c_slback->c_ye++;
476 cv->c_slprev->c_ye++;
480 SetCanvasWindow(cv, NULL);
481 FreeCanvas(cv);
482 continue;
484 m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
485 if (cv == fcv)
486 m += focusmin;
487 hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
488 w -= cv->c_slweight;
489 nh -= hh;
490 if (hh <= m + 1) {
491 hh = m + 1;
492 } else {
493 int hx = need * (hh - m - 1) / got;
494 got -= (hh - m - 1);
495 hh -= hx;
496 need -= hx;
498 /* hh is window size plus pation line */
499 if (i + hh > maxi + 2) {
500 hh = maxi + 2 - i;
502 if (i + hh == maxi + 1) {
503 hh++;
505 if (cv->c_slorient == SLICE_VERT) {
506 cv->c_xs = xs;
507 cv->c_xe = xe;
508 cv->c_ys = i;
509 cv->c_ye = i + hh - 2;
510 cv->c_xoff = xs;
511 cv->c_yoff = i;
512 } else {
513 cv->c_xs = i;
514 cv->c_xe = i + hh - 2;
515 cv->c_ys = ys;
516 cv->c_ye = ye;
517 cv->c_xoff = i;
518 cv->c_yoff = ys;
520 cv->c_xoff = cv->c_xs;
521 cv->c_yoff = cv->c_ys;
522 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
523 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
524 if (cv->c_slperp) {
525 ResizeCanvas(cv);
526 if (!cv->c_slperp->c_slnext) {
527 FreePerp(cv->c_slperp);
528 FreePerp(cv);
531 i += hh;
535 static Canvas *AddPerp(Canvas *cv)
537 Canvas *pcv;
539 if ((pcv = calloc(1, sizeof(Canvas))) == NULL)
540 return NULL;
541 pcv->c_next = NULL;
542 pcv->c_display = cv->c_display;
543 pcv->c_slnext = cv->c_slnext;
544 pcv->c_slprev = cv->c_slprev;
545 pcv->c_slperp = cv;
546 pcv->c_slback = cv->c_slback;
547 if (cv->c_slback && cv->c_slback->c_slperp == cv)
548 cv->c_slback->c_slperp = pcv;
549 pcv->c_slorient = cv->c_slorient;
550 pcv->c_xoff = 0;
551 pcv->c_yoff = 0;
552 pcv->c_xs = cv->c_xs;
553 pcv->c_xe = cv->c_xe;
554 pcv->c_ys = cv->c_ys;
555 pcv->c_ye = cv->c_ye;
556 if (pcv->c_slnext)
557 pcv->c_slnext->c_slprev = pcv;
558 if (pcv->c_slprev)
559 pcv->c_slprev->c_slnext = pcv;
560 pcv->c_slweight = cv->c_slweight;
561 CanvasInitBlank(pcv);
562 cv->c_slweight = 1;
563 cv->c_slnext = NULL;
564 cv->c_slprev = NULL;
565 cv->c_slperp = NULL;
566 cv->c_slback = pcv;
567 cv->c_slorient = SLICE_UNKN;
568 return pcv;
571 int AddCanvas(int orient)
573 Canvas *cv;
574 int xs, xe, ys, ye;
575 int h, num;
577 cv = D_forecv;
579 if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
580 if (!AddPerp(cv))
581 return -1;
583 cv = D_forecv;
584 xs = cv->c_slback->c_xs;
585 xe = cv->c_slback->c_xe;
586 ys = cv->c_slback->c_ys;
587 ye = cv->c_slback->c_ye;
588 if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext) {
589 if (captiontop)
590 ys++; /* need space for caption */
591 else
592 ye--; /* need space for caption */
595 num = CountCanvas(cv->c_slback->c_slperp) + 1;
596 if (orient == SLICE_VERT)
597 h = ye - ys + 1;
598 else
599 h = xe - xs + 1;
601 h -= 2 * num - 1;
602 if (h < 0)
603 return -1; /* can't fit in */
605 if ((cv = calloc(1, sizeof(Canvas))) == NULL)
606 return -1;
608 D_forecv->c_slback->c_ys = ys; /* in case we modified it above */
609 D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
610 D_forecv->c_slorient = orient; /* in case it was UNKN */
611 cv->c_slnext = D_forecv->c_slnext;
612 cv->c_slprev = D_forecv;
613 D_forecv->c_slnext = cv;
614 if (cv->c_slnext)
615 cv->c_slnext->c_slprev = cv;
616 cv->c_slorient = orient;
617 cv->c_slback = D_forecv->c_slback;
619 cv->c_xs = xs;
620 cv->c_xe = xe;
621 cv->c_ys = ys;
622 cv->c_ye = ye;
623 cv->c_xoff = 0;
624 cv->c_yoff = 0;
625 cv->c_display = display;
626 cv->c_vplist = NULL;
627 cv->c_captev.type = EV_TIMEOUT;
628 cv->c_captev.data = (char *)cv;
629 cv->c_captev.handler = cv_winid_fn;
631 CanvasInitBlank(cv);
632 cv->c_lnext = NULL;
634 cv->c_next = NULL;
636 cv = cv->c_slback;
637 EqualizeCanvas(cv->c_slperp, 0);
638 ResizeCanvas(cv);
639 RecreateCanvasChain();
640 RethinkDisplayViewports();
641 ResizeLayersToCanvases();
642 return 0;
645 void RemCanvas(void)
647 Canvas *cv;
648 int ys, ye;
650 cv = D_forecv;
652 ys = cv->c_slback->c_ys;
653 ye = cv->c_slback->c_ye;
655 if (cv->c_slorient == SLICE_UNKN)
656 return;
657 while (cv->c_slprev)
658 cv = cv->c_slprev;
659 if (!cv->c_slnext)
660 return;
661 if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback) {
662 /* two canvases in slice, kill perp node */
663 cv = D_forecv;
664 FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
665 FreePerp(cv->c_slback);
667 /* free canvas */
668 cv = D_forecv;
669 D_forecv = cv->c_slprev;
670 if (!D_forecv)
671 D_forecv = cv->c_slnext;
672 FreeCanvas(cv);
674 cv = D_forecv;
675 while (D_forecv->c_slperp)
676 D_forecv = D_forecv->c_slperp;
678 /* if only one canvas left, set orient back to unknown */
679 if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp) {
680 cv->c_slorient = SLICE_UNKN;
681 if (!captionalways) {
682 if (captiontop)
683 cv->c_slback->c_ys = --ys; /* caption line no longer needed */
684 else
685 cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
688 cv = cv->c_slback;
689 EqualizeCanvas(cv->c_slperp, 0);
690 ResizeCanvas(cv);
692 D_fore = Layer2Window(D_forecv->c_layer);
693 flayer = D_forecv->c_layer;
695 RecreateCanvasChain();
696 RethinkDisplayViewports();
697 ResizeLayersToCanvases();
700 void OneCanvas(void)
702 Canvas *cv = D_forecv, *ocv = NULL;
704 if (cv->c_slprev) {
705 ocv = cv->c_slprev;
706 cv->c_slprev->c_slnext = cv->c_slnext;
708 if (cv->c_slnext) {
709 ocv = cv->c_slnext;
710 cv->c_slnext->c_slprev = cv->c_slprev;
712 if (!ocv)
713 return;
714 if (cv->c_slback && cv->c_slback->c_slperp == cv)
715 cv->c_slback->c_slperp = ocv;
716 cv->c_slorient = SLICE_UNKN;
717 while (D_canvas.c_slperp)
718 FreeCanvas(D_canvas.c_slperp);
719 cv = D_forecv;
720 D_canvas.c_slperp = cv;
721 cv->c_slback = &D_canvas;
722 cv->c_slnext = NULL;
723 cv->c_slprev = NULL;
724 if (!captionalways) {
725 if (captiontop)
726 D_canvas.c_ys--; /* caption line no longer needed */
727 else
728 D_canvas.c_ye++; /* caption line no longer needed */
730 ResizeCanvas(&D_canvas);
731 RecreateCanvasChain();
732 RethinkDisplayViewports();
733 ResizeLayersToCanvases();
736 void DupLayoutCv(Canvas *cvf, Canvas *cvt, bool save)
738 while (cvf) {
739 cvt->c_slorient = cvf->c_slorient;
740 cvt->c_slweight = cvf->c_slweight;
741 if (cvf == D_forecv)
742 D_forecv = cvt;
743 if (!save) {
744 cvt->c_display = display;
745 if (!cvf->c_slperp) {
746 cvt->c_captev.type = EV_TIMEOUT;
747 cvt->c_captev.data = (char *)cvt;
748 cvt->c_captev.handler = cv_winid_fn;
749 cvt->c_blank.l_cvlist = NULL;
750 cvt->c_blank.l_layfn = &BlankLf;
751 cvt->c_blank.l_bottom = &cvt->c_blank;
753 cvt->c_layer = cvf->c_layer;
754 } else {
755 Window *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : NULL;
756 cvt->c_layer = p ? &p->w_layer : NULL;
758 if (cvf->c_slperp) {
759 cvt->c_slperp = calloc(1, sizeof(Canvas));
760 cvt->c_slperp->c_slback = cvt;
761 CanvasInitBlank(cvt->c_slperp);
762 DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
764 if (cvf->c_slnext) {
765 cvt->c_slnext = calloc(1, sizeof(Canvas));
766 cvt->c_slnext->c_slprev = cvt;
767 cvt->c_slnext->c_slback = cvt->c_slback;
768 CanvasInitBlank(cvt->c_slnext);
770 cvf = cvf->c_slnext;
771 cvt = cvt->c_slnext;
775 void PutWindowCv(Canvas *cv)
777 Window *p;
778 for (; cv; cv = cv->c_slnext) {
779 if (cv->c_slperp) {
780 PutWindowCv(cv->c_slperp);
781 continue;
783 p = cv->c_layer ? (Window *)cv->c_layer->l_data : NULL;
784 cv->c_layer = NULL;
785 SetCanvasWindow(cv, p);