locale.library: correctly return the position of remaining datastream
[AROS.git] / workbench / libs / popupmenu / pmshadow.c
blobc508bf7d758f3c333ae7663f0ef7a4a2c0137747
1 //
2 // pmshadow.c
3 //
4 // PopupMenu Library - Shadows
5 //
6 // Copyright (C)2000 Henrik Isaksson <henrik@boing.nu>
7 // All Rights Reserved.
8 //
10 #include "pmshadow.h"
12 #include <exec/memory.h>
14 #include <proto/exec.h>
15 #include <clib/alib_protos.h>
17 #include <stdio.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)) {
31 return TRUE;
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)))
37 return TRUE;
39 return FALSE;
43 // PM_CopyShadowNode - copy a PMShadowRect.
45 PMSR *PM_CopyShadowNode(PMSR *A)
47 PMSR *newnode=NULL;
49 if(A) {
50 ((PMGLN *)A)->Length=sizeof(PMSR);
52 newnode=(PMSR *)PM_CopyNode((PMNode *)A);
55 return newnode;
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;
64 BOOL fail=FALSE;
66 // Definition: "old shadow" = worknode
67 // "new shadow" = rect
69 // Now, check existance and size of the following four regions:
71 // +-------------+
72 // | A |
73 // +---+-----+---+
74 // | C | new | D |
75 // +---+-----+---+
76 // | B |
77 // +-------------+
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)
85 return TRUE;*/
87 tmprect.Left=worknode->Left;
88 tmprect.Right=worknode->Right;
90 // For A to exist, the rect's upper edge must be inside the
91 // old shadow.
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
105 // old shadow.
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");
151 return (!fail);
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;
161 BOOL fail=FALSE;
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);
192 if(cpy) {
193 PM_AddShadowToList(sigma, cpy);
196 deltanode=nextdeltanode;
199 return (!fail);
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;
208 PMSR rect;
209 BOOL fail=FALSE;
211 rect.Left=l;
212 rect.Top=t;
213 rect.Right=l+w;
214 rect.Bottom=t+h;
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;
232 return (!fail);
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)
240 PMSR tmprect, *cpy;
242 tmprect.Left=l;
243 tmprect.Top=t;
244 tmprect.Right=r;
245 tmprect.Bottom=b;
247 cpy=PM_CopyShadowNode(&tmprect);
248 if(cpy) {
249 PM_AddShadowToList(list, cpy);
250 return TRUE;
252 return FALSE;