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)
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 ****************************************************************
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
;
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
;
67 cv
->c_slprev
= pcv
->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
;
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
;
84 cv
->c_slnext
->c_slprev
= cv
;
85 LayerCleanupMemory(&pcv
->c_blank
);
93 struct viewport
*vp
, *nvp
;
98 cv
->c_slprev
->c_slnext
= 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
;
106 FreeCanvas(cv
->c_slperp
);
107 LayerCleanupMemory(&cv
->c_blank
);
116 /* remove from canvas chain as SetCanvasWindow might call
117 * some layer function */
118 for (cvp
= &D_cvlist
; *cvp
; cvp
= &(*cvp
)->c_next
)
125 p
= cv
->c_layer
? Layer2Window(cv
->c_layer
) : 0;
126 SetCanvasWindow(cv
, 0);
128 WindowChanged(p
, 'u');
129 if (flayer
== cv
->c_layer
)
131 for (vp
= cv
->c_vplist
; vp
; vp
= nvp
)
138 evdeq(&cv
->c_captev
);
139 LayerCleanupMemory(&cv
->c_blank
);
148 for (; cv
; cv
= cv
->c_slnext
)
154 for (cvp
= cv
->c_slperp
; cvp
; cvp
= cvp
->c_slnext
)
157 n
= CountCanvas(cvp
->c_slperp
);
175 for (cvp
= cv
->c_slperp
; cvp
; cvp
= cvp
->c_slnext
)
178 n
= CountCanvas(cvp
->c_slperp
);
189 struct canvas
*cv
, *mcv
= 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)
200 if (x
>= D_forecv
->c_xs
&& x
<= D_forecv
->c_xe
)
202 if (x
< cv
->c_xs
|| x
> cv
->c_xe
)
204 if (y
< D_forecv
->c_ys
&& y
< cv
->c_ys
)
206 if (y
> D_forecv
->c_ye
+ 1 && y
> cv
->c_ye
+ 1)
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)
217 if (x
< D_forecv
->c_xs
&& x
< cv
->c_xs
)
219 if (x
> D_forecv
->c_xe
&& x
> cv
->c_xe
)
226 if (m
&& (!mm
|| m
< mm
))
232 return mcv
? mcv
: D_forecv
;
236 SetCanvasWindow(cv
, wi
)
240 struct win
*p
= 0, **pp
;
242 struct canvas
*cvp
, **cvpp
;
245 display
= cv
->c_display
;
249 /* remove old layer */
250 for (cvpp
= &l
->l_cvlist
; (cvp
= *cvpp
); cvpp
= &cvp
->c_lnext
)
254 *cvpp
= cvp
->c_lnext
;
260 if (p
&& cv
== D_forecv
)
263 ReleaseAutoWritelock(display
, p
);
267 SetTimeout(&p
->w_silenceev
, p
->w_silencewait
* 1000);
268 evenq(&p
->w_silenceev
);
273 if (l
->l_cvlist
== 0 && (p
== 0 || l
!= p
->w_savelayer
))
277 /* find right layer to display on canvas */
278 if (wi
&& wi
->w_type
!= W_TYPE_GROUP
)
281 if (wi
->w_savelayer
&& (wi
->w_blocked
|| wi
->w_savelayer
->l_cvlist
== 0))
288 l
->l_data
= (char *)wi
;
293 /* add our canvas to the layer's canvaslist */
294 ASSERT(l
->l_cvlist
!= cv
);
295 cv
->c_lnext
= l
->l_cvlist
;
298 cv
->c_xoff
= cv
->c_xs
;
299 cv
->c_yoff
= cv
->c_ys
;
300 RethinkViewportOffsets(cv
);
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
;
311 display_windows(0, 0, wi
);
316 if (wi
&& D_other
== wi
)
317 D_other
= wi
->w_next
; /* Might be 0, but that's OK. */
321 fore
= D_fore
; /* XXX ? */
325 ObtainAutoWritelock(display
, wi
);
328 * Place the window at the head of the most-recently-used list
332 for (pp
= &windows
; (p
= *pp
); pp
= &p
->w_next
)
346 cv_winid_fn(ev
, data
)
351 struct canvas
*cv
= (struct canvas
*)data
;
353 display
= cv
->c_display
;
354 if (D_status
== STATUS_ON_WIN
)
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)
374 if ((cv
= (struct canvas
*)calloc(1, sizeof *cv
)) == 0)
377 cv
->c_xe
= D_width
- 1;
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
);
384 cv
->c_display
= display
;
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
;
405 RethinkDisplayViewports();
406 D_forecv
= cv
; /* default input focus */
410 static struct canvas
**
411 CreateCanvasChainRec(cv
, cvp
)
415 for (; cv
; cv
= cv
->c_slnext
)
418 cvp
= CreateCanvasChainRec(cv
->c_slperp
, cvp
);
429 RecreateCanvasChain()
432 cvp
= CreateCanvasChainRec(D_canvas
.c_slperp
, &D_cvlist
);
437 EqualizeCanvas(cv
, gflag
)
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
)
449 EqualizeCanvas(cv2
->c_slperp
, gflag
);
460 struct canvas
*cv2
, *cvn
, *fcv
;
461 int nh
, i
, maxi
, hh
, m
, w
, wsum
;
471 debug2("ResizeCanvas: %d,%d", xs
, ys
);
472 debug2(" %d,%d\n", xe
, ye
);
475 if (cv
->c_slorient
== SLICE_UNKN
)
477 ASSERT(!cv
->c_slnext
&& !cv
->c_slperp
);
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;
490 if (focusminwidth
|| focusminheight
)
492 debug("searching for focus canvas\n");
494 while (cv2
->c_slback
)
496 if (cv2
->c_slback
== cv
->c_slback
)
499 focusmin
= cv
->c_slorient
== SLICE_VERT
? focusminheight
: focusminwidth
;
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
);
511 m
= CountCanvas(cv
) * 2;
512 nh
= cv
->c_slorient
== SLICE_VERT
? ye
- ys
+ 2 : xe
- xs
+ 2;
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
);
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;
539 hh
= cv2
->c_slweight
? nh
* cv2
->c_slweight
/ w
: 0;
540 w
-= cv2
->c_slweight
;
542 debug2(" should %d min %d\n", hh
, m
);
548 debug2("need: %d, got %d\n", 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
;
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
;
567 cv
->c_slback
->c_ye
++;
568 cv
->c_slprev
->c_ye
++;
571 SetCanvasWindow(cv
, 0);
575 m
= cv
->c_slperp
? CountCanvasPerp(cv
) * 2 - 1 : 1;
578 hh
= cv
->c_slweight
? nh
* cv
->c_slweight
/ w
: 0;
581 debug2(" should %d min %d\n", hh
, m
);
585 debug1(" -> %d\n", hh
);
589 int hx
= need
* (hh
- m
- 1) / got
;
590 debug3(" -> %d - %d = %d\n", hh
, hx
, hh
- hx
);
594 debug2(" now need=%d got=%d\n", need
, got
);
597 /* hh is window size plus pation line */
598 if (i
+ hh
> maxi
+ 2)
601 debug1(" not enough space, reducing to %d\n", hh
);
603 if (i
+ hh
== maxi
+ 1)
606 debug(" incrementing as no other canvas will fit\n");
608 if (cv
->c_slorient
== SLICE_VERT
)
613 cv
->c_ye
= i
+ hh
- 2;
620 cv
->c_xe
= i
+ hh
- 2;
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;
633 if (!cv
->c_slperp
->c_slnext
)
635 debug("deleting perp node\n");
636 FreePerp(cv
->c_slperp
);
644 static struct canvas
*
649 debug("Creating new perp node\n");
651 if ((pcv
= (struct canvas
*)calloc(1, sizeof *cv
)) == 0)
654 pcv
->c_display
= cv
->c_display
;
655 pcv
->c_slnext
= cv
->c_slnext
;
656 pcv
->c_slprev
= cv
->c_slprev
;
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
;
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
;
669 pcv
->c_slnext
->c_slprev
= pcv
;
671 pcv
->c_slprev
->c_slnext
= pcv
;
672 pcv
->c_slweight
= cv
->c_slweight
;
673 CanvasInitBlank(pcv
);
679 cv
->c_slorient
= SLICE_UNKN
;
692 debug2("AddCanvas orient %d, forecv is %d\n", orient
, cv
->c_slorient
);
694 if (cv
->c_slorient
!= SLICE_UNKN
&& cv
->c_slorient
!= orient
)
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
)
717 return -1; /* can't fit in */
719 if ((cv
= (struct canvas
*)calloc(1, sizeof *cv
)) == 0)
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
;
728 cv
->c_slnext
->c_slprev
= cv
;
729 cv
->c_slorient
= orient
;
730 cv
->c_slback
= D_forecv
->c_slback
;
738 cv
->c_display
= display
;
740 cv
->c_captev
.type
= EV_TIMEOUT
;
741 cv
->c_captev
.data
= (char *)cv
;
742 cv
->c_captev
.handler
= cv_winid_fn
;
750 EqualizeCanvas(cv
->c_slperp
, 0);
752 RecreateCanvasChain();
753 RethinkDisplayViewports();
754 ResizeLayersToCanvases();
764 debug("RemCanvas\n");
766 if (cv
->c_slorient
== SLICE_UNKN
)
772 if (!cv
->c_slnext
->c_slnext
&& cv
->c_slback
->c_slback
)
774 /* two canvases in slice, kill perp node */
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
;
786 D_forecv
= cv
->c_slprev
;
788 D_forecv
= cv
->c_slnext
;
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
;
800 cv
->c_slback
->c_ye
= ++ye
; /* caption line no longer needed */
803 EqualizeCanvas(cv
->c_slperp
, 0);
806 D_fore
= Layer2Window(D_forecv
->c_layer
);
807 flayer
= D_forecv
->c_layer
;
809 RecreateCanvasChain();
810 RethinkDisplayViewports();
811 ResizeLayersToCanvases();
817 struct canvas
*cv
= D_forecv
, *ocv
= 0;
822 cv
->c_slprev
->c_slnext
= cv
->c_slnext
;
827 cv
->c_slnext
->c_slprev
= cv
->c_slprev
;
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
);
837 D_canvas
.c_slperp
= cv
;
838 cv
->c_slback
= &D_canvas
;
841 ASSERT(!cv
->c_slperp
);
843 D_canvas
.c_ye
++; /* caption line no longer needed */
844 ResizeCanvas(&D_canvas
);
845 RecreateCanvasChain();
846 RethinkDisplayViewports();
847 ResizeLayersToCanvases();
851 DupLayoutCv(cvf
, cvt
, save
)
852 struct canvas
*cvf
, *cvt
;
857 cvt
->c_slorient
= cvf
->c_slorient
;
858 cvt
->c_slweight
= cvf
->c_slweight
;
863 cvt
->c_display
= display
;
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
;
877 struct win
*p
= cvf
->c_layer
? Layer2Window(cvf
->c_layer
) : 0;
878 cvt
->c_layer
= p
? &p
->w_layer
: 0;
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
);
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
);
904 for (; cv
; cv
= cv
->c_slnext
)
908 PutWindowCv(cv
->c_slperp
);
911 p
= cv
->c_layer
? (struct win
*)cv
->c_layer
->l_data
: 0;
913 SetCanvasWindow(cv
, p
);