2 Copyright © 2002-2006, 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 the is the most fequently 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((const struct TagItem
**)&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
) DeletePool(data
->pool_allocated
);
88 else CoerceMethod(cl
,obj
,MUIM_Dataspace_Clear
);
89 return DoSuperMethodA(cl
, obj
, msg
);
92 IPTR
Dataspace__MUIM_Add(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_Add
*msg
)
94 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
95 struct Dataspace_Node
*replace
;
96 struct Dataspace_Node
*node
;
98 if (NULL
== msg
->data
|| msg
->len
< 1 || msg
->id
< 1)
101 node
= (struct Dataspace_Node
*)AllocVecPooled(data
->current_pool
,
102 sizeof(struct Dataspace_Node
)+msg
->len
);
108 replace
= List_First(&data
->list
);
111 if (replace
->id
== msg
->id
)
113 Remove((struct Node
*)replace
);
114 FreeVecPooled(data
->current_pool
, replace
);
117 replace
= Node_Next(replace
);
120 AddTail((struct List
*)&data
->list
,(struct Node
*)node
);
122 node
->len
= msg
->len
;
123 CopyMem(msg
->data
, node
+ 1, node
->len
);
127 IPTR
Dataspace__MUIM_Clear(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_Clear
*msg
)
129 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
130 struct Dataspace_Node
*node
;
132 node
= List_First(&data
->list
);
135 struct Dataspace_Node
*tmp
= node
;
136 node
= Node_Next(node
);
138 FreeVecPooled(data
->current_pool
, tmp
);
144 IPTR
Dataspace__MUIM_Find(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_Find
*msg
)
146 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
147 struct Dataspace_Node
*find
;
149 find
= List_First(&data
->list
);
152 if (find
->id
== msg
->id
)
154 return (IPTR
)(find
+ 1);
156 find
= Node_Next(find
);
162 IPTR
Dataspace__MUIM_Merge(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_Merge
*msg
)
167 IPTR
Dataspace__MUIM_Remove(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_Remove
*msg
)
169 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
170 struct Dataspace_Node
*node
;
172 node
= List_First(&data
->list
);
175 if (node
->id
== msg
->id
)
177 Remove((struct Node
*)node
);
178 FreeVecPooled(data
->current_pool
, node
);
181 node
= Node_Next(node
);
187 IPTR
Dataspace__MUIM_ReadIFF(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_ReadIFF
*msg
)
189 struct ContextNode
*cn
;
196 cn
= CurrentChunk(msg
->handle
);
201 if (!(buffer
= AllocVec(cn
->cn_Size
,0)))
205 read
= ReadChunkBytes(msg
->handle
,buffer
,cn
->cn_Size
);
214 while (p
< buffer
+ read
)
216 /* Since data can be stored on uneven addresses we must read
217 ** them byte by byte as MC68000 doesn't like this
219 id
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
221 len
= (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
224 /* p might be uneven but MUIM_Dataspace_Add use CopyMem() */
226 /* Now add the data */
227 DoMethod(obj
, MUIM_Dataspace_Add
, (IPTR
)p
, len
, id
);
234 IPTR
Dataspace__MUIM_WriteIFF(struct IClass
*cl
, Object
*obj
, struct MUIP_Dataspace_WriteIFF
*msg
)
236 struct MUI_DataspaceData
*data
= INST_DATA(cl
, obj
);
237 struct Dataspace_Node
*iter
;
240 if ((rc
= PushChunk(msg
->handle
,msg
->type
,msg
->id
,IFFSIZE_UNKNOWN
))) return rc
;
242 iter
= List_First(&data
->list
);
245 ULONG len
= iter
->len
+8;
246 /* Data is stored in big-endian whatever your machine.
247 * Be sure sure to convert data to big endian.
249 iter
->id
= AROS_LONG2BE(iter
->id
);
250 iter
->len
= AROS_LONG2BE(iter
->len
);
251 rc
= WriteChunkBytes(msg
->handle
, &iter
->id
, len
); /* ID - LEN - DATA */
252 iter
->id
= AROS_LONG2BE(iter
->id
);
253 iter
->len
= AROS_LONG2BE(iter
->len
);
258 iter
= Node_Next(iter
);
260 if ((rc
= PopChunk(msg
->handle
))) return rc
;
265 BOOPSI_DISPATCHER(IPTR
, Dataspace_Dispatcher
, cl
, obj
, msg
)
269 switch (msg
->MethodID
)
271 /* Whenever an object shall be created using NewObject(), it will be
272 ** sent a OM_NEW method.
274 case OM_NEW
: return Dataspace__OM_NEW(cl
, obj
, (struct opSet
*) msg
);
275 case OM_DISPOSE
: return Dataspace__OM_DISPOSE(cl
, obj
, msg
);
276 case MUIM_Dataspace_Add
:
277 DoMethod(obj
, MUIM_Semaphore_Obtain
);
278 res
= Dataspace__MUIM_Add(cl
, obj
, (APTR
)msg
);
279 DoMethod(obj
, MUIM_Semaphore_Release
);
281 case MUIM_Dataspace_Clear
:
282 DoMethod(obj
, MUIM_Semaphore_Obtain
);
283 res
= Dataspace__MUIM_Clear(cl
, obj
, (APTR
)msg
);
284 DoMethod(obj
, MUIM_Semaphore_Release
);
286 case MUIM_Dataspace_Find
:
287 DoMethod(obj
, MUIM_Semaphore_ObtainShared
);
288 res
= Dataspace__MUIM_Find(cl
, obj
, (APTR
)msg
);
289 DoMethod(obj
, MUIM_Semaphore_Release
);
290 /* now that sem is released, imagine that the object gets freed ...
291 * it really needs that the caller locks the object,
292 * and release it when done with the result
295 case MUIM_Dataspace_Merge
:
296 DoMethod(obj
, MUIM_Semaphore_Obtain
);
297 res
= Dataspace__MUIM_Merge(cl
, obj
, (APTR
)msg
);
298 DoMethod(obj
, MUIM_Semaphore_Release
);
300 case MUIM_Dataspace_Remove
:
301 DoMethod(obj
, MUIM_Semaphore_Obtain
);
302 res
= Dataspace__MUIM_Remove(cl
, obj
, (APTR
)msg
);
303 DoMethod(obj
, MUIM_Semaphore_Release
);
305 case MUIM_Dataspace_ReadIFF
:
306 DoMethod(obj
, MUIM_Semaphore_Obtain
);
307 res
= (IPTR
)Dataspace__MUIM_ReadIFF(cl
, obj
, (APTR
)msg
);
308 DoMethod(obj
, MUIM_Semaphore_Release
);
310 case MUIM_Dataspace_WriteIFF
:
311 DoMethod(obj
, MUIM_Semaphore_Obtain
);
312 res
= (IPTR
)Dataspace__MUIM_WriteIFF(cl
, obj
, (APTR
)msg
);
313 DoMethod(obj
, MUIM_Semaphore_Release
);
317 return DoSuperMethodA(cl
, obj
, msg
);
319 BOOPSI_DISPATCHER_END
324 const struct __MUIBuiltinClass _MUI_Dataspace_desc
= {
325 MUIC_Dataspace
, /* Class name */
326 MUIC_Semaphore
, /* super class name */
327 sizeof(struct MUI_DataspaceData
), /* size of class own datas */
328 (void*)Dataspace_Dispatcher
/* class dispatcher */