4 // PopupMenu Library - Topographical Menu Map
6 // Copyright (C)2000 Henrik Isaksson <henrik@boing.nu>
7 // All Rights Reserved.
14 #include "pmtopography.h"
16 #include <exec/lists.h>
17 #include <exec/memory.h>
18 #include <proto/exec.h>
19 #include <clib/alib_protos.h>
22 static BOOL
PM_MapShadowPart(PMTRList
*top
, PMSRList
*delta
,
23 const PMSR
*shrect
, WORD l
, WORD t
, UWORD ss
,
24 UWORD direction
, UBYTE Type
);
28 // PM_AddTopographicRegion - add a rectangular region of height h to the topographic map.
30 BOOL
PM_AddTopographicRegion(PMTRList
*lst
, WORD l
, WORD t
, WORD r
, WORD b
, WORD h
)
33 PMTR
*worknode
, *nextnode
;
41 rect
.n
.Length
=sizeof(PMTR
);
43 d1(KPrintF("Adding topographic region: %ld %ld %ld %ld, height: %ld\n", l
, t
, r
, b
, h
));
46 // Step 1: Remove all parts in l that would overlap rect.
48 worknode
= (PMTR
*)(lst
->mlh_Head
); /* First node */
49 while ((nextnode
= (PMTR
*)PM_NextNode(worknode
)))
51 if (PM_RegionOverlap(worknode
, &rect
))
53 PM_UnlinkRegion(lst
, worknode
);
54 PM_SubTopographicRects(lst
, worknode
, &rect
);
55 PM_FreeTopographicNode(worknode
);
61 // Step 2: Add rect to l.
63 tmprect
=PM_CopyTopographicNode(&rect
);
66 PM_AddRegionToList(lst
, tmprect
);
75 // PM_CopyTopographicNode - copy a PMTopographicRect, or allocate a new if A is NULL.
77 PMTR
*PM_CopyTopographicNode(PMTR
*A
)
81 newnode
=(PMTR
*) AllocVec(sizeof(PMTR
), MEMF_ANY
);
89 // PM_SubTopographicRects - like PM_SubRects but preserves height
91 BOOL
PM_SubTopographicRects(PMTRList
*dest
, PMTR
*worknode
, PMTR
*rect
)
93 PMTR tmprect
, *rectptr
;
96 tmprect
.Height
= worknode
->Height
;
98 tmprect
.Left
= worknode
->Left
;
99 tmprect
.Right
= worknode
->Right
;
101 tmprect
.n
.Length
= sizeof(tmprect
);
103 if (rect
->Top
>worknode
->Top
&& rect
->Top
<worknode
->Bottom
)
105 tmprect
.Top
= worknode
->Top
;
106 tmprect
.Bottom
= rect
->Top
;
108 rectptr
= PM_CopyTopographicNode(&tmprect
);
110 PM_AddToList((PMDList
*)dest
, (PMNode
*)rectptr
);
115 if (rect
->Bottom
>worknode
->Top
&& rect
->Bottom
<worknode
->Bottom
)
117 tmprect
.Top
= rect
->Bottom
;
118 tmprect
.Bottom
= worknode
->Bottom
;
120 rectptr
= PM_CopyTopographicNode(&tmprect
);
122 PM_AddToList((PMDList
*)dest
, (PMNode
*)rectptr
);
127 tmprect
.Top
= MAX(rect
->Top
, worknode
->Top
);
128 tmprect
.Bottom
= MIN(rect
->Bottom
, worknode
->Bottom
);
130 if (rect
->Left
>worknode
->Left
&& rect
->Left
<worknode
->Right
)
132 tmprect
.Left
= worknode
->Left
;
133 tmprect
.Right
= rect
->Left
;
135 rectptr
= PM_CopyTopographicNode(&tmprect
);
137 PM_AddToList((PMDList
*)dest
, (PMNode
*)rectptr
);
142 if (rect
->Right
>worknode
->Left
&& rect
->Right
<worknode
->Right
)
144 tmprect
.Left
= rect
->Right
;
145 tmprect
.Right
= worknode
->Right
;
147 rectptr
= PM_CopyTopographicNode(&tmprect
);
149 PM_AddShadowToList((PMDList
*)dest
, (PMNode
*)rectptr
);
160 BOOL
PM_MapShadow(PMTRList
*top
, PMSRList
*delta
,
161 WORD l
, WORD t
, WORD r
, WORD b
,
162 UWORD menulevel
, UWORD direction
)
174 // The five following calls will create shadows for a lightsource
175 // positioned somewhere near the top left corner of the screen.
191 ss
= menulevel
* 2 + 8;
193 d1(KPrintF("%s/%s/%ld: left=%ld top=%ld right=%ld bottom=%ld\n", __FILE__
, __FUNC__
, __LINE__
, l
, t
, r
, b
));
195 if (direction
& PMSHADOW_HORIZ
)
197 shrect
.Right
= l
+ ss
;
200 if (direction
& PMSHADOW_VERT
)
202 shrect
.Bottom
= t
+ ss
;
205 if ((PMSHADOW_HORIZ
| PMSHADOW_VERT
) == direction
)
207 // bottom right corner
209 d1(KPrintF("%s/%s/%ld: Shadow 3\n", __FILE__
, __FUNC__
, __LINE__
));
210 Success
= PM_MapShadowPart(top
, delta
, &shrect
, l
, t
, ss
, direction
, SHADOWFLAG_BOTTOM
| SHADOWFLAG_RIGHT
);
212 else if (direction
& PMSHADOW_HORIZ
)
214 d1(KPrintF("%s/%s/%ld: PMSHADOW_HORIZ\n", __FILE__
, __FUNC__
, __LINE__
));
217 shrect
.Bottom
= t
+ ss
;
218 Success
= PM_MapShadowPart(top
, delta
, &shrect
, l
, t
, ss
, direction
, SHADOWFLAG_RIGHT
| SHADOWFLAG_TOP
);
225 Success
= PM_MapShadowPart(top
, delta
, &shrect
, l
, t
, ss
, direction
, SHADOWFLAG_RIGHT
);
228 else if (direction
& PMSHADOW_VERT
)
230 d1(KPrintF("%s/%s/%ld: PMSHADOW_VERT\n", __FILE__
, __FUNC__
, __LINE__
));
233 shrect
.Right
= l
+ ss
;
234 Success
= PM_MapShadowPart(top
, delta
, &shrect
, l
, t
, ss
, direction
, SHADOWFLAG_BOTTOM
| SHADOWFLAG_LEFT
);
239 shrect
.Left
= l
+ ss
;
241 Success
= PM_MapShadowPart(top
, delta
, &shrect
, l
, t
, ss
, direction
, SHADOWFLAG_BOTTOM
);
249 static BOOL
PM_MapShadowPart(PMTRList
*top
, PMSRList
*delta
,
250 const PMSR
*shrect
, WORD l
, WORD t
, UWORD ss
,
251 UWORD direction
, UBYTE Type
)
253 PMTR
*topnode
, *nexttopnode
;
256 d1(KPrintF("%s/%s/%ld: Left=%ld Top=%ld Right=%ld Bottom=%ld\n", \
257 __FILE__
, __FUNC__
, __LINE__
, shrect
->Left
, shrect
->Top
, shrect
->Right
, shrect
->Bottom
));
259 topnode
= (PMTR
*)(top
->mlh_Head
); /* First node */
260 while ((nexttopnode
= (PMTR
*)PM_NextNode(topnode
)))
267 d1(KPrintF("Mapping shadow to region: %ld %ld %ld %ld, height: %ld\n", \
268 topnode
->Left
, topnode
->Top
, topnode
->Right
, topnode
->Bottom
, topnode
->Height
));
270 if (direction
& PMSHADOW_HORIZ
)
271 dx
= topnode
->Height
* 2;
272 if (direction
& PMSHADOW_VERT
)
273 dy
= topnode
->Height
* 2;
275 rect
.pmsr_Type
= Type
;
277 rect
.Left
= MAX(shrect
->Left
, topnode
->Left
);
278 rect
.Right
= MIN(shrect
->Right
-dx
, topnode
->Right
);
279 rect
.Top
= MAX(shrect
->Top
, topnode
->Top
);
280 rect
.Bottom
= MIN(shrect
->Bottom
-dy
, topnode
->Bottom
);
281 rect
.n
.Length
= sizeof(PMSR
);
283 if (direction
& PMSHADOW_LEFT
)
285 if (rect
.Left
< l
+ ss
- (topnode
->Height
* 2))
286 rect
.Left
= l
+ ss
- (topnode
->Height
* 2);
289 if (direction
& PMSHADOW_TOP
)
291 if (rect
.Top
< t
+ss
-(topnode
->Height
*2))
292 rect
.Top
= t
+ss
-(topnode
->Height
*2);
295 d1(KPrintF("%s/%s/%ld: Left=%ld Top=%ld RIght=%ld Bottom=%ld\n", \
296 __FILE__
, __FUNC__
, __LINE__
, rect
.Left
, rect
.Top
, rect
.Right
, rect
.Bottom
));
297 if (rect
.Right
> rect
.Left
&& rect
.Bottom
> rect
.Top
)
299 newnode
= PM_CopyShadowNode(&rect
);
302 AddHead((struct List
*)delta
, (struct Node
*)newnode
);
310 topnode
= nexttopnode
;