some fixes to accented characters
[tangerine.git] / rom / hyperlayers / createlayertaglist.c
blob7b9df046c6a7e3ab0a1cde0698efd6b3418526f8
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/libcall.h>
7 #include <graphics/clip.h>
8 #include <graphics/layers.h>
9 #include <utility/tagitem.h>
10 #include <proto/exec.h>
11 #include <proto/utility.h>
12 #include <proto/graphics.h>
13 #include "basicfuncs.h"
15 /*****************************************************************************
17 NAME */
18 #include <proto/layers.h>
19 AROS_LH8(struct Layer *, CreateLayerTagList,
21 /* SYNOPSIS */
22 AROS_LHA(struct Layer_Info *, li, A0),
23 AROS_LHA(struct BitMap *, bm, A1),
24 AROS_LHA(LONG , x0, D0),
25 AROS_LHA(LONG , y0, D1),
26 AROS_LHA(LONG , x1, D2),
27 AROS_LHA(LONG , y1, D3),
28 AROS_LHA(LONG , flags, D4),
29 AROS_LHA(struct TagItem *, tagList, A2),
31 /* LOCATION */
32 struct LayersBase *, LayersBase, 37, Layers)
34 /* FUNCTION
35 Create a new layer according to the tags given.
37 INPUTS
38 li - pointer to LayerInfo structure
39 bm - pointer to common bitmap
40 x0,y0 - upper left corner of the layer (in parent layer coords)
41 x1,y1 - lower right corner of the layer (in parent layer coords)
42 flags - choose the type of layer by setting some flags
43 If it is to be a super bitmap layer then the tag
44 LA_SUPERBITMAP must be provided along with a
45 pointer to a valid super bitmap.
46 tagList - a list of tags that specify the properties of the
47 layer. The following tags are currently supported:
48 LA_PRIORITY : priority class of the layer. The
49 higher the number the further the
50 layer will be in front of everything
51 else.
52 Default value is UPFRONTPRIORITY.
53 LA_HOOK : Backfill hook
54 LA_SUPERBITMAP : pointer to a superbitmap. The flags
55 must also represent that this
56 layer is supposed to be a superbitmap
57 layer.
58 LA_CHILDOF : pointer to parent layer. If NULL then
59 this layer will be created as a old-style
60 layer.
61 LA_INFRONTOF : pointer to a layer in front of which
62 this layer is to be created.
63 LA_BEHIND : pointer to a layer behind which this layer
64 is to be created. Must not give both LA_INFRONTOF
65 and LA_BEHIND.
66 LA_VISIBLE : FALSE if this layer is to be invisible.
67 Default value is TRUE
68 LA_SHAPE : The region of the layer that comprises its shape.
69 This value is optional. The region must be relative to the layer.
72 RESULT
73 Pointer to the newly created layer. NULL if layer could not be
74 created (Probably out of memory).
75 If the layer is created successful you must not free its shape.
76 The shape is automatically freed when the layer is deleted.
78 NOTES
80 EXAMPLE
82 BUGS
84 SEE ALSO
86 INTERNALS
88 *****************************************************************************/
90 AROS_LIBFUNC_INIT
92 struct BitMap * superbitmap = NULL;
93 struct Hook * hook = NULL, *shapehook = NULL;
94 int priority = UPFRONTPRIORITY;
95 int visible = TRUE;
96 struct Layer * behind = NULL, * infrontof = NULL, * parent = NULL;
97 struct Layer * l;
98 struct RastPort * rp;
99 struct Region * layershape = NULL, *shape;
100 struct TagItem *tag, *tstate = tagList;
102 while((tag = NextTagItem(&tstate)))
104 switch (tag->ti_Tag)
106 case LA_Priority:
107 priority = tag->ti_Data;
108 break;
110 case LA_Hook:
111 hook = (struct Hook *)tag->ti_Data;
112 break;
114 case LA_SuperBitMap:
115 superbitmap = (struct BitMap *)tag->ti_Data;
116 break;
118 case LA_ChildOf:
119 parent = (struct Layer *)tag->ti_Data;
120 break;
122 case LA_InFrontOf:
123 if (infrontof)
124 return NULL;
125 infrontof = (struct Layer *)tag->ti_Data;
126 break;
128 case LA_Behind:
129 if (behind)
130 return NULL;
131 behind = (struct Layer *)tag->ti_Data;
132 break;
134 case LA_Visible:
135 visible = tag->ti_Data;
136 break;
138 case LA_Shape:
139 layershape = (struct Region *)tag->ti_Data;
140 break;
142 case LA_ShapeHook:
143 shapehook = (struct Hook *)tag->ti_Data;
144 break;
148 } /* while((tag = NextTagItem(&tstate))) */
150 if ((flags & LAYERSUPER) && (NULL == superbitmap))
151 return NULL;
153 if (!parent)
155 parent = li->check_lp;
156 if (!parent)
158 /* Root layer not yet installed */
160 if (!(flags & LAYER_ROOT_LAYER)) /* avoid endless recursion */
162 struct TagItem tags[] =
164 {LA_Visible , FALSE },
165 {LA_Priority, ROOTPRIORITY },
166 {TAG_DONE }
169 if (!(CreateLayerTagList(li,
173 GetBitMapAttr(bm, BMA_WIDTH) - 1,
174 GetBitMapAttr(bm, BMA_HEIGHT) - 1,
175 LAYER_ROOT_LAYER,
176 tags)))
178 li->check_lp = NULL;
179 return NULL;
182 parent = li->check_lp;
188 * User gives coordinates reltive to parent.
189 * Adjust the shape to the absolute coordinates
190 * If this is the root layer, I don't have to
191 * do anything. I recognize the root layer if there
192 * is no parent.
195 if (infrontof && infrontof->priority > priority)
196 return NULL;
198 if (behind && behind->priority < priority)
199 return NULL;
201 /* First create the shape region relative to nothing, that is 0,0 origin */
203 shape = NewRectRegion(0, 0, x1 - x0, y1 - y0);
204 if (!shape)
205 return NULL;
207 if (shapehook)
209 struct ShapeHookMsg msg;
211 msg.Action = SHAPEHOOKACTION_CREATELAYER;
212 msg.Layer = 0;
213 msg.ActualShape = layershape;
214 msg.NewBounds.MinX = x0;
215 msg.NewBounds.MinY = y0;
216 msg.NewBounds.MaxX = x1;
217 msg.NewBounds.MaxY = y1;
218 msg.OldBounds.MinX = 0;
219 msg.OldBounds.MinY = 0;
220 msg.OldBounds.MaxX = 0;
221 msg.OldBounds.MaxY = 0;
223 layershape = (struct Region *)CallHookPkt(shapehook, NULL, &msg);
226 if (layershape) if (!AndRegionRegion(layershape, shape))
228 DisposeRegion(shape);
229 return NULL;
232 if (parent)
234 /* Convert from parent layer relative coords to screen relative coords */
236 x0 += parent->bounds.MinX;
237 y0 += parent->bounds.MinY;
238 x1 += parent->bounds.MinX;
239 y1 += parent->bounds.MinY;
242 /* Make shape region relative to screen */
243 _TranslateRect(&shape->bounds, x0, y0);
245 l = AllocMem(sizeof(struct IntLayer), MEMF_CLEAR|MEMF_PUBLIC);
246 rp = CreateRastPort();
249 if (l && rp)
251 l->shape = shape;
252 IL(l)->shapehook = shapehook;
253 l->shaperegion = layershape;
254 l->rp = rp;
256 rp->Layer = l;
257 rp->BitMap = bm;
259 l->bounds.MinX = x0;
260 l->bounds.MaxX = x1;
261 l->bounds.MinY = y0;
262 l->bounds.MaxY = y1;
264 l->Flags = (WORD) flags;
265 l->LayerInfo = li;
266 l->Width = x1 - x0 + 1;
267 l->Height = y1 - y0 + 1;
269 l->SuperBitMap = superbitmap;
270 l->BackFill = hook;
271 l->priority = priority;
273 InitSemaphore(&l->Lock);
274 LockLayer(0, l);
276 if (NULL == (l->DamageList = NewRegion()))
277 goto failexit;
278 if (NULL == (l->VisibleRegion = NewRegion()))
279 goto failexit;
280 if (NULL == (l->visibleshape = NewRegion()))
281 goto failexit;
283 l->visible = visible;
285 if (NULL == li->check_lp)
286 li->check_lp = l;
288 l->parent = parent;
290 if (parent)
291 l->nesting = parent->nesting+1;
292 else
293 l->nesting = 0;
295 LockLayers(li);
299 * If neither a layer in front or behind is
300 * given the search for the place according to
301 * the priority and insert it there. I
302 * determine behind or infrontof here!
304 if (NULL != li->top_layer)
306 if (!infrontof && !behind)
308 int end = FALSE;
309 struct Layer * lastgood;
310 infrontof = parent;
314 lastgood = infrontof;
315 infrontof = infrontof->front;
316 if (NULL == infrontof)
318 infrontof = lastgood;
319 break;
321 if (infrontof->parent != l->parent)
323 infrontof = lastgood;
324 break;
326 while (infrontof->nesting >= l->nesting)
328 lastgood = infrontof;
329 infrontof = infrontof->front;
330 if (NULL == infrontof ||
331 infrontof->priority > l->priority)
333 infrontof = lastgood;
334 end = TRUE;
335 break;
341 while (FALSE == end);
346 if (infrontof || (NULL == behind))
348 if (NULL == infrontof)
349 infrontof = li->top_layer;
351 if (li->top_layer == infrontof)
353 li->top_layer = l;
354 l->front = NULL;
355 l->back = infrontof;
356 if (NULL != infrontof)
357 infrontof->front = l;
359 else
361 l->front = infrontof->front;
362 l->back = infrontof;
363 infrontof->front->back = l;
364 infrontof->front = l;
367 else if (behind)
369 l->front = behind;
370 l->back = behind->back;
371 if (l->back)
372 l->back->front = l;
373 behind->back = l;
378 SetRegion(l->shape, l->visibleshape);
379 if (l->parent)
380 AndRegionRegion(l->parent->shape, l->visibleshape);
383 if (IS_VISIBLE(l))
386 * layer is to be visible
388 struct Layer * _l = l->back;
389 struct Layer * lparent = l->parent;
392 * Does this layer have a layer in front of it?
393 * If yes, then take that layer's VisibleRegion and
394 * cut out that layer's shape. This is then the
395 * VisibleRegion of my layer.
397 if (l->front)
399 SetRegion(l->front->VisibleRegion, l->VisibleRegion);
400 ClearRegionRegion(l->front->visibleshape, l->VisibleRegion);
402 else
403 SetRegion(li->check_lp->shape, l->VisibleRegion);
407 * First tell all layers behind this layer to
408 * back up their parts that the new layer will
409 * be hiding.
411 while (1)
413 if (IS_VISIBLE(_l) && DO_OVERLAP(&l->shape->bounds, &_l->shape->bounds))
414 _BackupPartsOfLayer(_l, l->visibleshape, 0, FALSE, LayersBase);
415 else
416 ClearRegionRegion(l->visibleshape, _l->VisibleRegion);
418 if (_l == lparent)
420 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
421 break;
422 else
423 lparent = lparent->parent;
425 _l = _l->back;
430 * Show the layer according to its visible area
431 * This function creates the cliprects in the area
432 * of the layer.
433 * This also works for invisible layers since their Visible
434 * Region is non existent.
436 if (!IS_ROOTLAYER(l))
437 _ShowLayer(l, LayersBase);
439 else
440 goto failexit;
442 UnlockLayers(li);
444 return l;
446 failexit:
447 if (l)
449 if (l->VisibleRegion)
450 DisposeRegion(l->VisibleRegion);
451 if (l->DamageList)
452 DisposeRegion(l->DamageList);
453 if (l->visibleshape)
454 DisposeRegion(l->visibleshape);
455 FreeMem(l, sizeof(struct IntLayer));
458 if (rp)
459 FreeRastPort(rp);
461 return NULL;
463 AROS_LIBFUNC_EXIT
464 } /* CreateBehindHookLayer */