2 Copyright © 2002-2014, The AROS Development Team. All rights reserved.
9 #include <exec/types.h>
10 #include <clib/alib_protos.h>
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/iffparse.h>
15 #include <proto/muimaster.h>
17 #include "muimaster_intern.h"
21 extern struct Library
*MUIMasterBase
;
28 /* len bytes data follows */
31 struct MUI_DataspaceData
33 /* We store this as a linear list, but it has O(n) when looking
34 ** for an entry, which is bad because this is the most frequently used
43 IPTR
Dataspace__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
45 struct MUI_DataspaceData
*data
;
46 struct TagItem
*tags
, *tag
;
48 obj
= (Object
*) DoSuperMethodA(cl
, obj
, (Msg
) msg
);
52 data
= INST_DATA(cl
, obj
);
54 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
58 case MUIA_Dataspace_Pool
:
59 data
->pool
= (APTR
) tag
->ti_Data
;
64 NewList((struct List
*)&data
->list
);
68 if (!(data
->pool_allocated
= CreatePool(0, 4096, 4096)))
70 CoerceMethod(cl
, obj
, OM_DISPOSE
);
73 data
->current_pool
= data
->pool_allocated
;
77 data
->current_pool
= data
->pool
;
84 IPTR
Dataspace__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
86 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
87 if (data
->pool_allocated
)
88 DeletePool(data
->pool_allocated
);
90 CoerceMethod(cl
, obj
, MUIM_Dataspace_Clear
);
91 return DoSuperMethodA(cl
, obj
, msg
);
94 IPTR
Dataspace__MUIM_Add(struct IClass
*cl
, Object
*obj
,
95 struct MUIP_Dataspace_Add
*msg
)
97 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
98 struct Dataspace_Node
*replace
;
99 struct Dataspace_Node
*node
;
101 if (NULL
== msg
->data
|| msg
->len
< 1 || msg
->id
< 1)
104 node
= (struct Dataspace_Node
*)AllocVecPooled(data
->current_pool
,
105 sizeof(struct Dataspace_Node
) + msg
->len
);
111 replace
= List_First(&data
->list
);
114 if (replace
->id
== msg
->id
)
116 Remove((struct Node
*)replace
);
117 FreeVecPooled(data
->current_pool
, replace
);
120 replace
= Node_Next(replace
);
123 AddTail((struct List
*)&data
->list
, (struct Node
*)node
);
125 node
->len
= msg
->len
;
126 CopyMem(msg
->data
, node
+ 1, node
->len
);
130 IPTR
Dataspace__MUIM_Clear(struct IClass
*cl
, Object
*obj
,
131 struct MUIP_Dataspace_Clear
*msg
)
133 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
134 struct Dataspace_Node
*node
;
136 node
= List_First(&data
->list
);
139 struct Dataspace_Node
*tmp
= node
;
140 node
= Node_Next(node
);
142 FreeVecPooled(data
->current_pool
, tmp
);
148 IPTR
Dataspace__MUIM_Find(struct IClass
*cl
, Object
*obj
,
149 struct MUIP_Dataspace_Find
*msg
)
151 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
152 struct Dataspace_Node
*find
;
154 find
= List_First(&data
->list
);
157 if (find
->id
== msg
->id
)
159 return (IPTR
) (find
+ 1);
161 find
= Node_Next(find
);
167 IPTR
Dataspace__MUIM_Merge(struct IClass
*cl
, Object
*obj
,
168 struct MUIP_Dataspace_Merge
*msg
)
173 IPTR
Dataspace__MUIM_Remove(struct IClass
*cl
, Object
*obj
,
174 struct MUIP_Dataspace_Remove
*msg
)
176 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
177 struct Dataspace_Node
*node
;
179 node
= List_First(&data
->list
);
182 if (node
->id
== msg
->id
)
184 Remove((struct Node
*)node
);
185 FreeVecPooled(data
->current_pool
, node
);
188 node
= Node_Next(node
);
194 IPTR
Dataspace__MUIM_ReadIFF(struct IClass
*cl
, Object
*obj
,
195 struct MUIP_Dataspace_ReadIFF
*msg
)
197 struct ContextNode
*cn
;
204 cn
= CurrentChunk(msg
->handle
);
209 if (!(buffer
= AllocVec(cn
->cn_Size
, 0)))
213 read
= ReadChunkBytes(msg
->handle
, buffer
, cn
->cn_Size
);
222 while (p
< buffer
+ read
)
224 /* Since data can be stored on uneven addresses we must read
225 ** them byte by byte as MC68000 doesn't like this
227 id
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
229 len
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
232 /* p might be uneven but MUIM_Dataspace_Add use CopyMem() */
234 /* Now add the data */
235 DoMethod(obj
, MUIM_Dataspace_Add
, (IPTR
) p
, len
, id
);
242 IPTR
Dataspace__MUIM_WriteIFF(struct IClass
*cl
, Object
*obj
,
243 struct MUIP_Dataspace_WriteIFF
*msg
)
245 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
246 struct Dataspace_Node
*iter
;
249 if ((rc
= PushChunk(msg
->handle
, msg
->type
, msg
->id
, IFFSIZE_UNKNOWN
)))
252 iter
= List_First(&data
->list
);
255 ULONG len
= iter
->len
+ 8;
256 /* Data is stored in big-endian whatever your machine.
257 * Be sure sure to convert data to big endian.
259 iter
->id
= AROS_LONG2BE(iter
->id
);
260 iter
->len
= AROS_LONG2BE(iter
->len
);
261 rc
= WriteChunkBytes(msg
->handle
, &iter
->id
, len
); /* ID - LEN - DATA */
262 iter
->id
= AROS_LONG2BE(iter
->id
);
263 iter
->len
= AROS_LONG2BE(iter
->len
);
268 iter
= Node_Next(iter
);
270 if ((rc
= PopChunk(msg
->handle
)))
276 BOOPSI_DISPATCHER(IPTR
, Dataspace_Dispatcher
, cl
, obj
, msg
)
280 switch (msg
->MethodID
)
282 /* Whenever an object shall be created using NewObject(), it will be
283 ** sent a OM_NEW method.
286 return Dataspace__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
288 return Dataspace__OM_DISPOSE(cl
, obj
, msg
);
289 case MUIM_Dataspace_Add
:
290 DoMethod(obj
, MUIM_Semaphore_Obtain
);
291 res
= Dataspace__MUIM_Add(cl
, obj
, (APTR
) msg
);
292 DoMethod(obj
, MUIM_Semaphore_Release
);
294 case MUIM_Dataspace_Clear
:
295 DoMethod(obj
, MUIM_Semaphore_Obtain
);
296 res
= Dataspace__MUIM_Clear(cl
, obj
, (APTR
) msg
);
297 DoMethod(obj
, MUIM_Semaphore_Release
);
299 case MUIM_Dataspace_Find
:
300 DoMethod(obj
, MUIM_Semaphore_ObtainShared
);
301 res
= Dataspace__MUIM_Find(cl
, obj
, (APTR
) msg
);
302 DoMethod(obj
, MUIM_Semaphore_Release
);
303 /* now that sem is released, imagine that the object gets freed ...
304 * it really needs that the caller locks the object,
305 * and release it when done with the result
308 case MUIM_Dataspace_Merge
:
309 DoMethod(obj
, MUIM_Semaphore_Obtain
);
310 res
= Dataspace__MUIM_Merge(cl
, obj
, (APTR
) msg
);
311 DoMethod(obj
, MUIM_Semaphore_Release
);
313 case MUIM_Dataspace_Remove
:
314 DoMethod(obj
, MUIM_Semaphore_Obtain
);
315 res
= Dataspace__MUIM_Remove(cl
, obj
, (APTR
) msg
);
316 DoMethod(obj
, MUIM_Semaphore_Release
);
318 case MUIM_Dataspace_ReadIFF
:
319 DoMethod(obj
, MUIM_Semaphore_Obtain
);
320 res
= (IPTR
) Dataspace__MUIM_ReadIFF(cl
, obj
, (APTR
) msg
);
321 DoMethod(obj
, MUIM_Semaphore_Release
);
323 case MUIM_Dataspace_WriteIFF
:
324 DoMethod(obj
, MUIM_Semaphore_Obtain
);
325 res
= (IPTR
) Dataspace__MUIM_WriteIFF(cl
, obj
, (APTR
) msg
);
326 DoMethod(obj
, MUIM_Semaphore_Release
);
330 return DoSuperMethodA(cl
, obj
, msg
);
332 BOOPSI_DISPATCHER_END
337 const struct __MUIBuiltinClass _MUI_Dataspace_desc
=
339 MUIC_Dataspace
, /* Class name */
340 MUIC_Semaphore
, /* super class name */
341 sizeof(struct MUI_DataspaceData
), /* size of class own datas */
342 (void *) Dataspace_Dispatcher
/* class dispatcher */