Bring back --with-sys-screenrc configure flag.
[screen-lua.git] / src / canvas.c
blob0121892658cdd87b370d996ec7362b1d09c2a2f0
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 * http://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"
30 #include "screen.h"
31 #include "extern.h"
32 #include "canvas.h"
33 #include "list_generic.h"
35 extern struct display *display;
36 extern struct win *fore, *windows;
37 extern struct layer *flayer;
38 extern int captionalways;
39 extern struct LayFuncs BlankLf;
40 extern int focusminwidth, focusminheight;
42 static void
43 CanvasInitBlank(cv)
44 struct canvas *cv;
46 cv->c_blank.l_cvlist = cv;
47 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
48 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
49 cv->c_blank.l_x = cv->c_blank.l_y = 0;
50 cv->c_blank.l_layfn = &BlankLf;
51 cv->c_blank.l_data = 0;
52 cv->c_blank.l_next = 0;
53 cv->c_blank.l_bottom = &cv->c_blank;
54 cv->c_blank.l_blocking = 0;
55 cv->c_layer = &cv->c_blank;
58 static void
59 FreePerp(pcv)
60 struct canvas *pcv;
62 struct canvas *cv;
64 if (!pcv->c_slperp)
65 return;
66 cv = pcv->c_slperp;
67 cv->c_slprev = pcv->c_slprev;
68 if (cv->c_slprev)
69 cv->c_slprev->c_slnext = cv;
70 cv->c_slback = pcv->c_slback;
71 if (cv->c_slback && cv->c_slback->c_slperp == pcv)
72 cv->c_slback->c_slperp = cv;
73 cv->c_slorient = pcv->c_slorient;
74 cv->c_slweight = pcv->c_slweight;
75 while (cv->c_slnext)
77 cv = cv->c_slnext;
78 cv->c_slorient = pcv->c_slorient;
79 cv->c_slback = pcv->c_slback;
80 cv->c_slweight = pcv->c_slweight;
82 cv->c_slnext = pcv->c_slnext;
83 if (cv->c_slnext)
84 cv->c_slnext->c_slprev = cv;
85 LayerCleanupMemory(&pcv->c_blank);
86 free(pcv);
89 void
90 FreeCanvas(cv)
91 struct canvas *cv;
93 struct viewport *vp, *nvp;
94 struct canvas **cvp;
95 struct win *p;
97 if (cv->c_slprev)
98 cv->c_slprev->c_slnext = cv->c_slnext;
99 if (cv->c_slnext)
100 cv->c_slnext->c_slprev = cv->c_slprev;
101 if (cv->c_slback && cv->c_slback->c_slperp == cv)
102 cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev;
103 if (cv->c_slperp)
105 while (cv->c_slperp)
106 FreeCanvas(cv->c_slperp);
107 LayerCleanupMemory(&cv->c_blank);
108 free(cv);
109 return;
112 if (display)
114 if (D_forecv == cv)
115 D_forecv = 0;
116 /* remove from canvas chain as SetCanvasWindow might call
117 * some layer function */
118 for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next)
119 if (*cvp == cv)
121 *cvp = cv->c_next;
122 break;
125 p = cv->c_layer ? Layer2Window(cv->c_layer) : 0;
126 SetCanvasWindow(cv, 0);
127 if (p)
128 WindowChanged(p, 'u');
129 if (flayer == cv->c_layer)
130 flayer = 0;
131 for (vp = cv->c_vplist; vp; vp = nvp)
133 vp->v_canvas = 0;
134 nvp = vp->v_next;
135 vp->v_next = 0;
136 free(vp);
138 evdeq(&cv->c_captev);
139 LayerCleanupMemory(&cv->c_blank);
140 free(cv);
144 CountCanvas(cv)
145 struct canvas *cv;
147 int num = 0;
148 for (; cv; cv = cv->c_slnext)
150 if (cv->c_slperp)
152 struct canvas *cvp;
153 int nump = 1, n;
154 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
155 if (cvp->c_slperp)
157 n = CountCanvas(cvp->c_slperp);
158 if (n > nump)
159 nump = n;
161 num += nump;
163 else
164 num++;
166 return num;
170 CountCanvasPerp(cv)
171 struct canvas *cv;
173 struct canvas *cvp;
174 int num = 1, n;
175 for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext)
176 if (cvp->c_slperp)
178 n = CountCanvas(cvp->c_slperp);
179 if (n > num)
180 num = n;
182 return num;
185 struct canvas *
186 FindCanvas(x, y)
187 int x, y;
189 struct canvas *cv, *mcv = 0;
190 int m, mm = 0;
192 for (cv = D_cvlist; cv; cv = cv->c_next)
194 /* ye + 1 because of caption line */
195 if (x >= cv->c_xs && x <= cv->c_xe && y >= cv->c_ys && y <= cv->c_ye + 1)
196 return cv;
197 if (cv == D_forecv)
198 continue;
199 m = 0;
200 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe)
202 if (x < cv->c_xs || x > cv->c_xe)
203 continue;
204 if (y < D_forecv->c_ys && y < cv->c_ys)
205 continue;
206 if (y > D_forecv->c_ye + 1 && y > cv->c_ye + 1)
207 continue;
208 if (y < cv->c_ys)
209 m = cv->c_ys - y;
210 if (y > cv->c_ye + 1)
211 m = y - (cv->c_ye + 1);
213 if (y >= D_forecv->c_ys && y <= D_forecv->c_ye + 1)
215 if (y < cv->c_ys || y > cv->c_ye + 1)
216 continue;
217 if (x < D_forecv->c_xs && x < cv->c_xs)
218 continue;
219 if (x > D_forecv->c_xe && x > cv->c_xe)
220 continue;
221 if (x < cv->c_xs)
222 m = cv->c_xs - x;
223 if (x > cv->c_xe)
224 m = x - cv->c_xe;
226 if (m && (!mm || m < mm))
228 mcv = cv;
229 mm = m;
232 return mcv ? mcv : D_forecv;
235 void
236 SetCanvasWindow(cv, wi)
237 struct canvas *cv;
238 struct win *wi;
240 struct win *p = 0, **pp;
241 struct layer *l;
242 struct canvas *cvp, **cvpp;
244 l = cv->c_layer;
245 display = cv->c_display;
247 if (l)
249 /* remove old layer */
250 for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
251 if (cvp == cv)
252 break;
253 ASSERT(cvp);
254 *cvpp = cvp->c_lnext;
256 p = Layer2Window(l);
257 l = cv->c_layer;
258 cv->c_layer = 0;
260 if (p && cv == D_forecv)
262 #ifdef MULTIUSER
263 ReleaseAutoWritelock(display, p);
264 #endif
265 if (p->w_silence)
267 SetTimeout(&p->w_silenceev, p->w_silencewait * 1000);
268 evenq(&p->w_silenceev);
270 D_other = fore;
271 D_fore = 0;
273 if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer))
274 KillLayerChain(l);
277 /* find right layer to display on canvas */
278 if (wi && wi->w_type != W_TYPE_GROUP)
280 l = &wi->w_layer;
281 if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0))
282 l = wi->w_savelayer;
284 else
286 l = &cv->c_blank;
287 if (wi)
288 l->l_data = (char *)wi;
289 else
290 l->l_data = 0;
293 /* add our canvas to the layer's canvaslist */
294 ASSERT(l->l_cvlist != cv);
295 cv->c_lnext = l->l_cvlist;
296 l->l_cvlist = cv;
297 cv->c_layer = l;
298 cv->c_xoff = cv->c_xs;
299 cv->c_yoff = cv->c_ys;
300 RethinkViewportOffsets(cv);
302 if (flayer == 0)
303 flayer = l;
305 if (wi && wi->w_type == W_TYPE_GROUP)
307 /* auto-start windowlist on groups */
308 struct display *d = display;
309 struct layer *oldflayer = flayer;
310 flayer = l;
311 display_windows(0, 0, wi);
312 flayer = oldflayer;
313 display = d;
316 if (wi && D_other == wi)
317 D_other = wi->w_next; /* Might be 0, but that's OK. */
318 if (cv == D_forecv)
320 D_fore = wi;
321 fore = D_fore; /* XXX ? */
322 if (wi)
324 #ifdef MULTIUSER
325 ObtainAutoWritelock(display, wi);
326 #endif
328 * Place the window at the head of the most-recently-used list
330 if (windows != wi)
332 for (pp = &windows; (p = *pp); pp = &p->w_next)
333 if (p == wi)
334 break;
335 ASSERT(p);
336 *pp = p->w_next;
337 p->w_next = windows;
338 windows = p;
339 WListLinkChanged();
345 static void
346 cv_winid_fn(ev, data)
347 struct event *ev;
348 char *data;
350 int ox, oy;
351 struct canvas *cv = (struct canvas *)data;
353 display = cv->c_display;
354 if (D_status == STATUS_ON_WIN)
356 SetTimeout(ev, 1);
357 evenq(ev);
358 return;
360 ox = D_x;
361 oy = D_y;
362 if (cv->c_ye + 1 < D_height)
363 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
364 if (ox != -1 && oy != -1)
365 GotoPos(ox, oy);
369 MakeDefaultCanvas()
371 struct canvas *cv;
373 ASSERT(display);
374 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
375 return -1;
376 cv->c_xs = 0;
377 cv->c_xe = D_width - 1;
378 cv->c_ys = 0;
379 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways;
380 debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye);
381 cv->c_xoff = 0;
382 cv->c_yoff = 0;
383 cv->c_next = 0;
384 cv->c_display = display;
385 cv->c_vplist = 0;
386 cv->c_slnext = 0;
387 cv->c_slprev = 0;
388 cv->c_slperp = 0;
389 cv->c_slweight = 1;
390 cv->c_slback = &D_canvas;
391 D_canvas.c_slperp = cv;
392 D_canvas.c_xs = cv->c_xs;
393 D_canvas.c_xe = cv->c_xe;
394 D_canvas.c_ys = cv->c_ys;
395 D_canvas.c_ye = cv->c_ye;
396 cv->c_slorient = SLICE_UNKN;
397 cv->c_captev.type = EV_TIMEOUT;
398 cv->c_captev.data = (char *)cv;
399 cv->c_captev.handler = cv_winid_fn;
401 CanvasInitBlank(cv);
402 cv->c_lnext = 0;
404 D_cvlist = cv;
405 RethinkDisplayViewports();
406 D_forecv = cv; /* default input focus */
407 return 0;
410 static struct canvas **
411 CreateCanvasChainRec(cv, cvp)
412 struct canvas *cv;
413 struct canvas **cvp;
415 for (; cv; cv = cv->c_slnext)
417 if (cv->c_slperp)
418 cvp = CreateCanvasChainRec(cv->c_slperp, cvp);
419 else
421 *cvp = cv;
422 cvp = &cv->c_next;
425 return cvp;
428 void
429 RecreateCanvasChain()
431 struct canvas **cvp;
432 cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist);
433 *cvp = 0;
436 void
437 EqualizeCanvas(cv, gflag)
438 struct canvas *cv;
439 int gflag;
441 struct canvas *cv2;
442 for (; cv; cv = cv->c_slnext)
444 if (cv->c_slperp && gflag)
446 cv->c_slweight = CountCanvasPerp(cv);
447 for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext)
448 if (cv2->c_slperp)
449 EqualizeCanvas(cv2->c_slperp, gflag);
451 else
452 cv->c_slweight = 1;
456 void
457 ResizeCanvas(cv)
458 struct canvas *cv;
460 struct canvas *cv2, *cvn, *fcv;
461 int nh, i, maxi, hh, m, w, wsum;
462 int need, got;
463 int xs, ys, xe, ye;
464 int focusmin = 0;
466 xs = cv->c_xs;
467 ys = cv->c_ys;
468 xe = cv->c_xe;
469 ye = cv->c_ye;
470 cv = cv->c_slperp;
471 debug2("ResizeCanvas: %d,%d", xs, ys);
472 debug2(" %d,%d\n", xe, ye);
473 if (cv == 0)
474 return;
475 if (cv->c_slorient == SLICE_UNKN)
477 ASSERT(!cv->c_slnext && !cv->c_slperp);
478 cv->c_xs = xs;
479 cv->c_xe = xe;
480 cv->c_ys = ys;
481 cv->c_ye = ye;
482 cv->c_xoff = cv->c_xs;
483 cv->c_yoff = cv->c_ys;
484 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
485 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
486 return;
489 fcv = 0;
490 if (focusminwidth || focusminheight)
492 debug("searching for focus canvas\n");
493 cv2 = D_forecv;
494 while (cv2->c_slback)
496 if (cv2->c_slback == cv->c_slback)
498 fcv = cv2;
499 focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth;
500 if (focusmin > 0)
501 focusmin--;
502 else if (focusmin < 0)
503 focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
504 debug1("found, focusmin=%d\n", focusmin);
506 cv2 = cv2->c_slback;
509 if (focusmin)
511 m = CountCanvas(cv) * 2;
512 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
513 nh -= m;
514 if (nh < 0)
515 nh = 0;
516 if (focusmin > nh)
517 focusmin = nh;
518 debug1("corrected to %d\n", focusmin);
521 /* pass 1: calculate weight sum */
522 for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext)
524 debug1(" weight %d\n", cv2->c_slweight);
525 wsum += cv2->c_slweight;
527 debug1("wsum = %d\n", wsum);
528 if (wsum == 0)
529 wsum = 1;
530 w = wsum;
532 /* pass 2: calculate need/excess space */
533 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
534 for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext)
536 m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1;
537 if (cv2 == fcv)
538 m += focusmin;
539 hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0;
540 w -= cv2->c_slweight;
541 nh -= hh;
542 debug2(" should %d min %d\n", hh, m);
543 if (hh <= m + 1)
544 need += m + 1 - hh;
545 else
546 got += hh - m - 1;
548 debug2("need: %d, got %d\n", need, got);
549 if (need > got)
550 need = got;
552 /* pass 3: distribute space */
553 nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2;
554 i = cv->c_slorient == SLICE_VERT ? ys : xs;
555 maxi = cv->c_slorient == SLICE_VERT ? ye : xe;
556 w = wsum;
557 for (; cv; cv = cvn)
559 cvn = cv->c_slnext;
560 if (i > maxi)
562 if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev)
564 cv->c_slprev->c_slorient = SLICE_UNKN;
565 if (!captionalways)
567 cv->c_slback->c_ye++;
568 cv->c_slprev->c_ye++;
571 SetCanvasWindow(cv, 0);
572 FreeCanvas(cv);
573 continue;
575 m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1;
576 if (cv == fcv)
577 m += focusmin;
578 hh = cv->c_slweight ? nh * cv->c_slweight / w : 0;
579 w -= cv->c_slweight;
580 nh -= hh;
581 debug2(" should %d min %d\n", hh, m);
582 if (hh <= m + 1)
584 hh = m + 1;
585 debug1(" -> %d\n", hh);
587 else
589 int hx = need * (hh - m - 1) / got;
590 debug3(" -> %d - %d = %d\n", hh, hx, hh - hx);
591 got -= (hh - m - 1);
592 hh -= hx;
593 need -= hx;
594 debug2(" now need=%d got=%d\n", need, got);
596 ASSERT(hh >= m + 1);
597 /* hh is window size plus pation line */
598 if (i + hh > maxi + 2)
600 hh = maxi + 2 - i;
601 debug1(" not enough space, reducing to %d\n", hh);
603 if (i + hh == maxi + 1)
605 hh++;
606 debug(" incrementing as no other canvas will fit\n");
608 if (cv->c_slorient == SLICE_VERT)
610 cv->c_xs = xs;
611 cv->c_xe = xe;
612 cv->c_ys = i;
613 cv->c_ye = i + hh - 2;
614 cv->c_xoff = xs;
615 cv->c_yoff = i;
617 else
619 cv->c_xs = i;
620 cv->c_xe = i + hh - 2;
621 cv->c_ys = ys;
622 cv->c_ye = ye;
623 cv->c_xoff = i;
624 cv->c_yoff = ys;
626 cv->c_xoff = cv->c_xs;
627 cv->c_yoff = cv->c_ys;
628 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1;
629 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
630 if (cv->c_slperp)
632 ResizeCanvas(cv);
633 if (!cv->c_slperp->c_slnext)
635 debug("deleting perp node\n");
636 FreePerp(cv->c_slperp);
637 FreePerp(cv);
640 i += hh;
644 static struct canvas *
645 AddPerp(cv)
646 struct canvas *cv;
648 struct canvas *pcv;
649 debug("Creating new perp node\n");
651 if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
652 return 0;
653 pcv->c_next = 0;
654 pcv->c_display = cv->c_display;
655 pcv->c_slnext = cv->c_slnext;
656 pcv->c_slprev = cv->c_slprev;
657 pcv->c_slperp = cv;
658 pcv->c_slback = cv->c_slback;
659 if (cv->c_slback && cv->c_slback->c_slperp == cv)
660 cv->c_slback->c_slperp = pcv;
661 pcv->c_slorient = cv->c_slorient;
662 pcv->c_xoff = 0;
663 pcv->c_yoff = 0;
664 pcv->c_xs = cv->c_xs;
665 pcv->c_xe = cv->c_xe;
666 pcv->c_ys = cv->c_ys;
667 pcv->c_ye = cv->c_ye;
668 if (pcv->c_slnext)
669 pcv->c_slnext->c_slprev = pcv;
670 if (pcv->c_slprev)
671 pcv->c_slprev->c_slnext = pcv;
672 pcv->c_slweight = cv->c_slweight;
673 CanvasInitBlank(pcv);
674 cv->c_slweight = 1;
675 cv->c_slnext = 0;
676 cv->c_slprev = 0;
677 cv->c_slperp = 0;
678 cv->c_slback = pcv;
679 cv->c_slorient = SLICE_UNKN;
680 return pcv;
684 AddCanvas(orient)
685 int orient;
687 struct canvas *cv;
688 int xs, xe, ys, ye;
689 int h, num;
691 cv = D_forecv;
692 debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient);
694 if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient)
695 if (!AddPerp(cv))
696 return -1;
698 cv = D_forecv;
699 xs = cv->c_slback->c_xs;
700 xe = cv->c_slback->c_xe;
701 ys = cv->c_slback->c_ys;
702 ye = cv->c_slback->c_ye;
703 if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext)
704 ye--; /* need space for caption */
705 debug2("Adding Canvas to slice %d,%d ", xs, ys);
706 debug2("%d,%d\n", xe, ye);
708 num = CountCanvas(cv->c_slback->c_slperp) + 1;
709 debug1("Num = %d\n", num);
710 if (orient == SLICE_VERT)
711 h = ye - ys + 1;
712 else
713 h = xe - xs + 1;
715 h -= 2 * num - 1;
716 if (h < 0)
717 return -1; /* can't fit in */
719 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0)
720 return -1;
722 D_forecv->c_slback->c_ye = ye; /* in case we modified it above */
723 D_forecv->c_slorient = orient; /* in case it was UNKN */
724 cv->c_slnext = D_forecv->c_slnext;
725 cv->c_slprev = D_forecv;
726 D_forecv->c_slnext = cv;
727 if (cv->c_slnext)
728 cv->c_slnext->c_slprev = cv;
729 cv->c_slorient = orient;
730 cv->c_slback = D_forecv->c_slback;
732 cv->c_xs = xs;
733 cv->c_xe = xe;
734 cv->c_ys = ys;
735 cv->c_ye = ye;
736 cv->c_xoff = 0;
737 cv->c_yoff = 0;
738 cv->c_display = display;
739 cv->c_vplist = 0;
740 cv->c_captev.type = EV_TIMEOUT;
741 cv->c_captev.data = (char *)cv;
742 cv->c_captev.handler = cv_winid_fn;
744 CanvasInitBlank(cv);
745 cv->c_lnext = 0;
747 cv->c_next = 0;
749 cv = cv->c_slback;
750 EqualizeCanvas(cv->c_slperp, 0);
751 ResizeCanvas(cv);
752 RecreateCanvasChain();
753 RethinkDisplayViewports();
754 ResizeLayersToCanvases();
755 return 0;
758 void
759 RemCanvas()
761 int xs, xe, ys, ye;
762 struct canvas *cv;
764 debug("RemCanvas\n");
765 cv = D_forecv;
766 if (cv->c_slorient == SLICE_UNKN)
767 return;
768 while (cv->c_slprev)
769 cv = cv->c_slprev;
770 if (!cv->c_slnext)
771 return;
772 if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback)
774 /* two canvases in slice, kill perp node */
775 cv = D_forecv;
776 debug("deleting perp node\n");
777 FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext);
778 FreePerp(cv->c_slback);
780 xs = cv->c_slback->c_xs;
781 xe = cv->c_slback->c_xe;
782 ys = cv->c_slback->c_ys;
783 ye = cv->c_slback->c_ye;
784 /* free canvas */
785 cv = D_forecv;
786 D_forecv = cv->c_slprev;
787 if (!D_forecv)
788 D_forecv = cv->c_slnext;
789 FreeCanvas(cv);
791 cv = D_forecv;
792 while (D_forecv->c_slperp)
793 D_forecv = D_forecv->c_slperp;
795 /* if only one canvas left, set orient back to unknown */
796 if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp)
798 cv->c_slorient = SLICE_UNKN;
799 if (!captionalways)
800 cv->c_slback->c_ye = ++ye; /* caption line no longer needed */
802 cv = cv->c_slback;
803 EqualizeCanvas(cv->c_slperp, 0);
804 ResizeCanvas(cv);
806 D_fore = Layer2Window(D_forecv->c_layer);
807 flayer = D_forecv->c_layer;
809 RecreateCanvasChain();
810 RethinkDisplayViewports();
811 ResizeLayersToCanvases();
814 void
815 OneCanvas()
817 struct canvas *cv = D_forecv, *ocv = 0;
819 if (cv->c_slprev)
821 ocv = cv->c_slprev;
822 cv->c_slprev->c_slnext = cv->c_slnext;
824 if (cv->c_slnext)
826 ocv = cv->c_slnext;
827 cv->c_slnext->c_slprev = cv->c_slprev;
829 if (!ocv)
830 return;
831 if (cv->c_slback && cv->c_slback->c_slperp == cv)
832 cv->c_slback->c_slperp = ocv;
833 cv->c_slorient = SLICE_UNKN;
834 while (D_canvas.c_slperp)
835 FreeCanvas(D_canvas.c_slperp);
836 cv = D_forecv;
837 D_canvas.c_slperp = cv;
838 cv->c_slback = &D_canvas;
839 cv->c_slnext = 0;
840 cv->c_slprev = 0;
841 ASSERT(!cv->c_slperp);
842 if (!captionalways)
843 D_canvas.c_ye++; /* caption line no longer needed */
844 ResizeCanvas(&D_canvas);
845 RecreateCanvasChain();
846 RethinkDisplayViewports();
847 ResizeLayersToCanvases();
850 void
851 DupLayoutCv(cvf, cvt, save)
852 struct canvas *cvf, *cvt;
853 int save;
855 while(cvf)
857 cvt->c_slorient = cvf->c_slorient;
858 cvt->c_slweight = cvf->c_slweight;
859 if (cvf == D_forecv)
860 D_forecv = cvt;
861 if (!save)
863 cvt->c_display = display;
864 if (!cvf->c_slperp)
866 cvt->c_captev.type = EV_TIMEOUT;
867 cvt->c_captev.data = (char *)cvt;
868 cvt->c_captev.handler = cv_winid_fn;
869 cvt->c_blank.l_cvlist = 0;
870 cvt->c_blank.l_layfn = &BlankLf;
871 cvt->c_blank.l_bottom = &cvt->c_blank;
873 cvt->c_layer = cvf->c_layer;
875 else
877 struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0;
878 cvt->c_layer = p ? &p->w_layer : 0;
880 if (cvf->c_slperp)
882 cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas));
883 cvt->c_slperp->c_slback = cvt;
884 CanvasInitBlank(cvt->c_slperp);
885 DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save);
887 if (cvf->c_slnext)
889 cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas));
890 cvt->c_slnext->c_slprev = cvt;
891 cvt->c_slnext->c_slback = cvt->c_slback;
892 CanvasInitBlank(cvt->c_slnext);
894 cvf = cvf->c_slnext;
895 cvt = cvt->c_slnext;
899 void
900 PutWindowCv(cv)
901 struct canvas *cv;
903 struct win *p;
904 for (; cv; cv = cv->c_slnext)
906 if (cv->c_slperp)
908 PutWindowCv(cv->c_slperp);
909 continue;
911 p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0;
912 cv->c_layer = 0;
913 SetCanvasWindow(cv, p);