revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / popupmenu / pmtopography.c
blobce9eb7efddee3fb42dfcd3a9715cf92a812760fd
1 //
2 // pmtopography.h
3 //
4 // PopupMenu Library - Topographical Menu Map
5 //
6 // Copyright (C)2000 Henrik Isaksson <henrik@boing.nu>
7 // All Rights Reserved.
8 //
10 #include "pmtopography.h"
12 #include <exec/lists.h>
13 #include <exec/memory.h>
14 #include <proto/exec.h>
15 #include <clib/alib_protos.h>
18 // PM_AddTopographicRegion - add a rectangular region of height h to the topographic map.
20 BOOL PM_AddTopographicRegion(PMTRList *lst, WORD l, WORD t, WORD r, WORD b, WORD h)
22 PMTR rect, *tmprect;
23 PMTR *worknode, *nextnode;
24 BOOL fail=FALSE;
26 rect.Left=l;
27 rect.Top=t;
28 rect.Right=r;
29 rect.Bottom=b;
30 rect.Height=h;
31 rect.n.Length=sizeof(PMTR);
33 //kprintf("Adding topographic region: %ld %ld %ld %ld, height: %ld\n", l, t, r, b, h);
36 // Step 1: Remove all parts in l that would overlap rect.
38 worknode = (PMTR *)(lst->mlh_Head); /* First node */
39 while((nextnode = (PMTR *)PM_NextNode(worknode))) {
40 if(PM_RegionOverlap(worknode, &rect)) {
41 PM_UnlinkRegion(lst, worknode);
42 PM_SubTopographicRects(lst, worknode, &rect);
43 PM_FreeTopographicNode(worknode);
45 worknode = nextnode;
49 // Step 2: Add rect to l.
51 tmprect=PM_CopyTopographicNode(&rect);
52 if(tmprect) {
53 PM_AddRegionToList(lst, tmprect);
54 } else fail=TRUE;
56 return (!(BOOL)fail);
60 // PM_CopyTopographicNode - copy a PMTopographicRect, or allocate a new if A is NULL.
62 PMTR *PM_CopyTopographicNode(PMTR *A)
64 PMTR *newnode=NULL;
66 newnode=(PMTR *)AllocVec(sizeof(PMTR), MEMF_ANY);
67 if(newnode) {
68 if(A) {
69 CopyMem(A, newnode, sizeof(PMTR));
73 return newnode;
77 // PM_SubTopographicRects - like PM_SubRects but preserves height
79 BOOL PM_SubTopographicRects(PMTRList *dest, PMTR *worknode, PMTR *rect)
81 PMTR tmprect, *rectptr;
82 BOOL fail=FALSE;
84 tmprect.Height=worknode->Height;
86 tmprect.Left=worknode->Left;
87 tmprect.Right=worknode->Right;
90 tmprect.n.Length=sizeof(tmprect);
92 if(rect->Top>worknode->Top && rect->Top<worknode->Bottom) {
93 tmprect.Top=worknode->Top;
94 tmprect.Bottom=rect->Top;
96 rectptr=PM_CopyTopographicNode(&tmprect);
97 if(rectptr) PM_AddToList((PMDList *)dest, (PMNode *)rectptr);
98 else fail=TRUE;
101 if(rect->Bottom>worknode->Top && rect->Bottom<worknode->Bottom) {
102 tmprect.Top=rect->Bottom;
103 tmprect.Bottom=worknode->Bottom;
105 rectptr=PM_CopyTopographicNode(&tmprect);
106 if(rectptr) PM_AddToList((PMDList *)dest, (PMNode *)rectptr);
107 else fail=TRUE;
110 tmprect.Top=MAX(rect->Top, worknode->Top);
111 tmprect.Bottom=MIN(rect->Bottom, worknode->Bottom);
113 if(rect->Left>worknode->Left && rect->Left<worknode->Right) {
114 tmprect.Left=worknode->Left;
115 tmprect.Right=rect->Left;
117 rectptr=PM_CopyTopographicNode(&tmprect);
118 if(rectptr) PM_AddToList((PMDList *)dest, (PMNode *)rectptr);
119 else fail=TRUE;
122 if(rect->Right>worknode->Left && rect->Right<worknode->Right) {
123 tmprect.Left=rect->Right;
124 tmprect.Right=worknode->Right;
126 rectptr=PM_CopyTopographicNode(&tmprect);
127 if(rectptr) PM_AddShadowToList((PMDList *)dest, (PMNode *)rectptr);
128 else fail=TRUE;
131 return (!(BOOL)fail);
135 // PM_MapShadow
137 BOOL PM_MapShadow(PMTRList *top, PMSRList *delta,
138 WORD l, WORD t, WORD r, WORD b,
139 UWORD menulevel, UWORD direction)
141 PMTR *topnode, *nexttopnode;
142 PMSR rect, shrect, *newnode;
143 BOOL fail=FALSE;
144 UWORD dx, dy, ss;
146 shrect.Left=l;
147 shrect.Top=t;
148 shrect.Right=r;
149 shrect.Bottom=b;
151 ss=menulevel*2+1+4;
153 if(direction&PMSHADOW_HORIZ) {
154 shrect.Right=l+ss;
157 if(direction&PMSHADOW_VERT) {
158 shrect.Bottom=t+ss;
161 topnode = (PMTR *)(top->mlh_Head); /* First node */
162 while((nexttopnode = (PMTR *)PM_NextNode(topnode))) {
164 dx=dy=0;
166 //kprintf("Mapping shadow to region: %ld %ld %ld %ld, height: %ld\n", topnode->Left, topnode->Top, topnode->Right, topnode->Bottom, topnode->Height);
169 if(direction&PMSHADOW_HORIZ) dx=topnode->Height*2;
170 if(direction&PMSHADOW_VERT) dy=topnode->Height*2;
172 rect.Left=MAX(shrect.Left, topnode->Left);
173 rect.Right=MIN(shrect.Right-dx, topnode->Right);
174 rect.Top=MAX(shrect.Top, topnode->Top);
175 rect.Bottom=MIN(shrect.Bottom-dy, topnode->Bottom);
176 rect.n.Length=sizeof(PMSR);
178 if(direction&PMSHADOW_LEFT) {
179 if(rect.Left<l+ss-(topnode->Height*2))
180 rect.Left=l+ss-(topnode->Height*2);
183 if(direction&PMSHADOW_TOP) {
184 if(rect.Top<t+ss-(topnode->Height*2))
185 rect.Top=t+ss-(topnode->Height*2);
188 if(rect.Right>rect.Left && rect.Bottom>rect.Top) {
189 newnode=PM_CopyShadowNode(&rect);
190 if(newnode) {
191 AddHead((struct List *)delta, (struct Node *)newnode);
195 topnode=nexttopnode;
198 return (!(BOOL)fail);