4 // PopupMenu Library - Shadows
6 // Copyright (C)2000 Henrik Isaksson <henrik@boing.nu>
7 // All Rights Reserved.
12 #include <exec/memory.h>
14 #include <proto/exec.h>
15 #include <clib/alib_protos.h>
19 #define ADDSHADOW(l,s) { rectptr=PM_CopyShadowNode(s); if(rectptr) PM_AddShadowToList(l, rectptr); else fail=TRUE; }
20 #define INSIDEX(a, b1, b2) (a>b1 && a<b2)
21 #define INSIDE(a, b1, b2) (a>=b1 && a<=b2)
22 #define INTERVALOVERLAP(a1, a2, b1, b2) (INSIDE(a1, b1, b2) || INSIDE(a2, b1, b2) || INSIDE(b1, a1, a2) || INSIDE(b2, a1, a2))
25 // PM_ShadowOverlap - return TRUE if the two rects touch each other anywhere
27 BOOL
PM_ShadowOverlap(PMSR
*A
, PMSR
*B
)
29 if(INTERVALOVERLAP(A
->Top
+1, A
->Bottom
, B
->Top
+1, B
->Bottom
)) {
30 if(INTERVALOVERLAP(A
->Left
+1, A
->Right
, B
->Left
+1, B
->Right
)) {
35 if((A
->Top
==B
->Top
&& (A
->Left
==B
->Left
|| A
->Right
==B
->Right
)) ||
36 (A
->Bottom
==B
->Bottom
&& (A
->Left
==B
->Left
|| A
->Right
==B
->Right
)))
43 // PM_CopyShadowNode - copy a PMShadowRect.
45 PMSR
*PM_CopyShadowNode(PMSR
*A
)
50 ((PMGLN
*)A
)->Length
=sizeof(PMSR
);
52 newnode
=(PMSR
*)PM_CopyNode((PMNode
*)A
);
59 // PM_SubRects - subtract one rect from another to a list of new rects
61 BOOL
PM_SubRects(PMSRList
*dest
, PMSR
*worknode
, PMSR
*rect
)
63 PMSR tmprect
, *rectptr
;
66 // Definition: "old shadow" = worknode
67 // "new shadow" = rect
69 // Now, check existance and size of the following four regions:
79 /*printf(" (%ld %ld %ld %ld) <> (%ld %ld %ld %ld) transformed to:\n",
80 rect->Left, rect->Top, rect->Right, rect->Bottom,
81 worknode->Left, worknode->Top, worknode->Right, worknode->Bottom);*/
83 /*if(rect->Left==worknode->Left && rect->Right==worknode->Right &&
84 rect->Top==worknode->Top && rect->Bottom==worknode->Bottom)
87 tmprect
.Left
=worknode
->Left
;
88 tmprect
.Right
=worknode
->Right
;
90 // For A to exist, the rect's upper edge must be inside the
93 if(INSIDEX(rect
->Top
, worknode
->Top
, worknode
->Bottom
)) {
94 tmprect
.Top
=worknode
->Top
;
95 tmprect
.Bottom
=rect
->Top
;
97 // Add the new rect to the list
99 //printf("A: %ld %ld %ld %ld\n", tmprect.Left, tmprect.Top, tmprect.Right, tmprect.Bottom);
101 ADDSHADOW(dest
, &tmprect
);
104 // For B to exist, the rect's lower edge must be inside the
107 if(INSIDEX(rect
->Bottom
, worknode
->Top
, worknode
->Bottom
)) {
108 tmprect
.Top
=rect
->Bottom
;
109 tmprect
.Bottom
=worknode
->Bottom
;
111 // Add the new rect to the list
113 //printf("B: %ld %ld %ld %ld\n", tmprect.Left, tmprect.Top, tmprect.Right, tmprect.Bottom);
115 ADDSHADOW(dest
, &tmprect
);
118 tmprect
.Top
=MAX(rect
->Top
, worknode
->Top
);
119 tmprect
.Bottom
=MIN(rect
->Bottom
, worknode
->Bottom
);
121 // For C to exist, the left edge of the new shadow must be
122 // inside the old one.
124 if(INSIDEX(rect
->Left
, worknode
->Left
, worknode
->Right
)) {
125 tmprect
.Left
=worknode
->Left
;
126 tmprect
.Right
=rect
->Left
;
128 // Add the new rect to the list
130 //printf("C: %ld %ld %ld %ld\n", tmprect.Left, tmprect.Top, tmprect.Right, tmprect.Bottom);
132 ADDSHADOW(dest
, &tmprect
);
135 // For D to exist, the right edge of the new shadow must be
136 // inside the old one.
138 if(INSIDEX(rect
->Right
, worknode
->Left
, worknode
->Right
)) {
139 tmprect
.Left
=rect
->Right
;
140 tmprect
.Right
=worknode
->Right
;
142 // Add the new rect to the list
144 //printf("D: %ld %ld %ld %ld\n", tmprect.Left, tmprect.Top, tmprect.Right, tmprect.Bottom);
146 ADDSHADOW(dest
, &tmprect
);
149 //printf("--- End of transformation ---\n");
155 // PM_AddShadow - Add a new shadow to sigma and add the change to delta.
157 BOOL
PM_AddShadow(PMSRList
*sigma
, PMSRList
*delta
)
159 PMSR
*sigmanode
, *nextsigmanode
;
160 PMSR
*deltanode
, *nextdeltanode
;
164 // Find old (sigma) shadows overlapped by the new one.
166 sigmanode
= (PMSR
*)(sigma
->mlh_Head
); /* First node */
167 if(!IsListEmpty((struct List
*)sigma
))
168 while((nextsigmanode
= (PMSR
*)PM_NextNode(sigmanode
))) {
170 deltanode
= (PMSR
*)(delta
->mlh_Head
); /* First node */
171 while((nextdeltanode
= (PMSR
*)PM_NextNode(deltanode
))) {
173 if(PM_ShadowOverlap(deltanode
, sigmanode
)) {
174 PM_UnlinkShadow(delta
, deltanode
); // Remove from delta list
175 PM_SubRects(delta
, deltanode
, sigmanode
);
176 PM_FreeShadowNode(deltanode
); // Free the old shadow
179 deltanode
=nextdeltanode
;
182 sigmanode
= nextsigmanode
;
186 // Now we add whatever is left in delta to sigma.
188 deltanode
= (PMSR
*)(delta
->mlh_Head
); /* First node */
189 while((nextdeltanode
= (PMSR
*)PM_NextNode(deltanode
))) {
191 PMSR
*cpy
=PM_CopyShadowNode(deltanode
);
193 PM_AddShadowToList(sigma
, cpy
);
196 deltanode
=nextdeltanode
;
203 // PM_SubMenuRect - subtract a menu rect from the shadow list.
205 BOOL
PM_SubMenuRect(PMSRList
*sigma
, WORD l
, WORD t
, WORD w
, WORD h
)
207 PMSR
*sigmanode
, *nextsigmanode
;
217 // Find old (sigma) shadows overlapped by the new one.
219 sigmanode
= (PMSR
*)(sigma
->mlh_Head
); /* First node */
220 while((nextsigmanode
= (PMSR
*)PM_NextNode(sigmanode
))) {
222 if(PM_ShadowOverlap(&rect
, sigmanode
)) {
223 PM_UnlinkShadow(sigma
, sigmanode
); // Remove from delta list
224 PM_SubRects(sigma
, sigmanode
, &rect
);
225 PM_FreeShadowNode(sigmanode
); // Free the old shadow
229 sigmanode
= nextsigmanode
;
236 // PM_AddRect - add a rectangle to a list of shadows.
238 BOOL
PM_AddRect(PMSRList
*list
, WORD l
, WORD t
, WORD r
, WORD b
)
247 cpy
=PM_CopyShadowNode(&tmprect
);
249 PM_AddShadowToList(list
, cpy
);