Using MUI_List_Title for Dirlist and Volumelist objects caused segfaults.
[cake.git] / workbench / libs / muimaster / classes / dirlist.c
blobb79d7a711d234c5213a7bf6d64456c847527fa65
1 /*
2 Copyright © 2002-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <exec/memory.h>
9 #include <dos/exall.h>
10 #include <dos/datetime.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/dos.h>
14 #include <proto/intuition.h>
15 #include <proto/utility.h>
16 #include <proto/muimaster.h>
18 #include <string.h>
19 #include <stdio.h>
21 #include "mui.h"
22 #include "muimaster_intern.h"
23 #include "support.h"
24 #include "support_classes.h"
25 #include "dirlist_private.h"
27 extern struct Library *MUIMasterBase;
29 static APTR construct_func(struct Hook *hook, APTR pool, struct Dirlist_Entry *entry)
31 struct Dirlist_Entry *new;
33 if ((new = AllocPooled(pool, sizeof(*new))))
35 *new = *entry;
37 return new;
40 static void destruct_func(struct Hook *hook, APTR pool, struct Dirlist_Entry *entry)
42 FreePooled(pool, entry, sizeof(struct Dirlist_Entry));
45 static LONG display_func(struct Hook *hook, char **array, struct Dirlist_Entry *entry)
47 struct Dirlist_DATA *data = hook->h_Data;
48 struct DateTime dt;
50 /* MUI: name | size | Date | Time | Protection | Comment */
51 if (entry)
53 *array++ = entry->fib.fib_FileName;
55 if (entry->fib.fib_DirEntryType > 0)
57 *array++ = "\33r\33I[6:22]";
59 else
61 snprintf(data->size_string, sizeof(data->size_string), "\33r%ld", entry->fib.fib_Size);
62 *array++ = data->size_string;
65 dt.dat_Stamp = entry->fib.fib_Date;
66 dt.dat_Format = FORMAT_DOS;
67 dt.dat_Flags = 0;
68 dt.dat_StrDay = NULL;
69 dt.dat_StrDate = data->date_string;
70 dt.dat_StrTime = data->time_string;
72 DateToStr(&dt);
74 *array++ = data->date_string;
75 *array++ = data->time_string;
77 data->prot_string[0] = (entry->fib.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
78 data->prot_string[1] = (entry->fib.fib_Protection & FIBF_PURE) ? 'p' : '-';
79 data->prot_string[2] = (entry->fib.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
80 data->prot_string[3] = (entry->fib.fib_Protection & FIBF_READ) ? '-' : 'r';
81 data->prot_string[4] = (entry->fib.fib_Protection & FIBF_WRITE) ? '-' : 'w';
82 data->prot_string[5] = (entry->fib.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
83 data->prot_string[6] = (entry->fib.fib_Protection & FIBF_DELETE ) ? '-' : 'd';
84 data->prot_string[7] = '\0';
86 *array++ = data->prot_string;
87 *array = entry->fib.fib_Comment;
89 else
91 *array++ = "Name";
92 *array++ = "Size";
93 *array++ = "Date";
94 *array++ = "Time";
95 *array++ = "Flags";
96 *array = "Comment";
99 return 0;
102 IPTR Dirlist__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg);
104 IPTR Dirlist__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
106 obj = (Object *)DoSuperNewTags
108 cl, obj, NULL,
109 MUIA_List_Format, (IPTR)",,,,,",
110 TAG_MORE, (IPTR) msg->ops_AttrList
113 if (obj)
115 struct Dirlist_DATA *data = INST_DATA(cl, obj);
117 data->status = MUIV_Dirlist_Status_Invalid;
119 data->construct_hook.h_Entry = HookEntry;
120 data->construct_hook.h_SubEntry = (HOOKFUNC)construct_func;
121 data->destruct_hook.h_Entry = HookEntry;
122 data->destruct_hook.h_SubEntry = (HOOKFUNC)destruct_func;
123 data->display_hook.h_Entry = HookEntry;
124 data->display_hook.h_SubEntry = (HOOKFUNC)display_func;
125 data->display_hook.h_Data = data;
127 SetAttrs(obj, MUIA_List_ConstructHook, (IPTR)&data->construct_hook,
128 MUIA_List_DestructHook, (IPTR)&data->destruct_hook,
129 MUIA_List_DisplayHook, (IPTR)&data->display_hook,
130 TAG_DONE);
132 Dirlist__OM_SET(cl, obj, msg);
135 return (IPTR)obj;
138 IPTR Dirlist__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
140 struct Dirlist_DATA *data = INST_DATA(cl, obj);
142 FreeVec(data->path);
144 return DoSuperMethodA(cl, obj, msg);
147 static void ReadDirectory(Object *obj, struct Dirlist_DATA *data)
149 struct FileInfoBlock *fib;
150 BPTR lock;
152 if ((fib = AllocDosObject(DOS_FIB, NULL)))
154 if ((lock = Lock(data->directory, SHARED_LOCK)))
156 BOOL success;
158 success = Examine(lock, fib);
160 if (success && (fib->fib_DirEntryType > 0))
162 for(;;)
164 BOOL isdir;
166 success = ExNext(lock, fib);
168 if (!success)
170 if (IoErr() == ERROR_NO_MORE_ENTRIES) success = TRUE;
172 break;
175 isdir = (fib->fib_DirEntryType > 0);
177 if (data->filterhook)
179 struct ExAllData ead = {0};
181 ead.ed_Name = fib->fib_FileName;
182 ead.ed_Type = fib->fib_DirEntryType;
183 ead.ed_Size = fib->fib_Size;
184 ead.ed_Prot = fib->fib_Protection;
185 ead.ed_Days = fib->fib_Date.ds_Days;
186 ead.ed_Mins = fib->fib_Date.ds_Minute;
187 ead.ed_Ticks = fib->fib_Date.ds_Tick;
188 ead.ed_Comment = fib->fib_Comment;
190 if (!CallHookPkt(data->filterhook, obj, &ead)) continue;
192 else
194 if (isdir && data->filesonly) continue;
195 if (!isdir && data->drawersonly) continue;
197 if (data->rejecticons)
199 WORD len = strlen(fib->fib_FileName);
201 if (len >= 5)
203 if (stricmp(fib->fib_FileName + len - 5, ".info") == 0) continue;
207 if (!isdir || data->filterdrawers)
209 if (data->acceptpattern)
211 if (!MatchPatternNoCase(data->acceptpattern, fib->fib_FileName)) continue;
214 if (data->rejectpattern)
216 if (MatchPatternNoCase(data->rejectpattern, fib->fib_FileName)) continue;
220 if (isdir)
222 set(obj, MUIA_Dirlist_NumDrawers, ++data->numdrawers);
224 else
226 set(obj, MUIA_Dirlist_NumFiles, ++data->numfiles);
227 set(obj, MUIA_Dirlist_NumBytes, data->numbytes + fib->fib_Size);
230 DoMethod(obj, MUIM_List_InsertSingle, (IPTR)fib, MUIV_List_Insert_Bottom);
232 } /* no filterhook */
234 } /* for(;;) */
236 set(obj, MUIA_Dirlist_Status, MUIV_Dirlist_Status_Valid);
239 } /* if (success && (fib->fib_DirEntryType > 0)) */
241 UnLock(lock);
243 } /* if ((lock = Lock(data->directory, SHARED_LOCK))) */
244 FreeDosObject(DOS_FIB, fib);
246 } /* if ((fib = AllocDosObject(DOS_FIB, NULL))) */
249 IPTR Dirlist__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
251 struct Dirlist_DATA *data = INST_DATA(cl, obj);
252 struct TagItem *tag, *tags;
253 BOOL directory_changed = FALSE;
255 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
257 IPTR tidata = tag->ti_Data;
259 switch (tag->ti_Tag)
262 case MUIA_Dirlist_AcceptPattern:
263 data->acceptpattern = (STRPTR)tidata;
264 break;
266 case MUIA_Dirlist_Directory:
267 data->directory = (STRPTR)tidata;
268 directory_changed = TRUE;
269 break;
271 case MUIA_Dirlist_DrawersOnly:
272 data->drawersonly = tidata ? TRUE : FALSE;
273 break;
275 case MUIA_Dirlist_FilesOnly:
276 data->filesonly = tidata ? TRUE : FALSE;
277 break;
279 case MUIA_Dirlist_FilterDrawers:
280 data->filterdrawers = tidata ? TRUE : FALSE;
281 break;
283 case MUIA_Dirlist_FilterHook:
284 data->filterhook = (struct Hook *)tidata;
285 break;
287 case MUIA_Dirlist_MultiSelDirs:
288 data->multiseldirs = tidata ? TRUE : FALSE;
289 break;
291 case MUIA_Dirlist_RejectIcons:
292 data->rejecticons = tidata ? TRUE : FALSE;
293 break;
295 case MUIA_Dirlist_RejectPattern:
296 data->rejectpattern = (STRPTR)tidata;
297 break;
299 case MUIA_Dirlist_SortDirs:
300 data->sortdirs = tidata ? TRUE : FALSE;
301 break;
303 case MUIA_Dirlist_SortHighLow:
304 data->sorthighlow = tidata ? TRUE : FALSE;
305 break;
307 case MUIA_Dirlist_SortType:
308 data->sorttype = tidata;
309 break;
311 case MUIA_Dirlist_Status:
312 data->status = tidata;
313 break;
315 } /* switch (tag->ti_Tag) */
317 } /* for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); ) */
319 if (directory_changed)
321 if (data->status == MUIV_Dirlist_Status_Valid)
323 DoMethod(obj, MUIM_List_Clear);
325 SetAttrs(obj, MUIA_Dirlist_Status , MUIV_Dirlist_Status_Invalid,
326 MUIA_Dirlist_NumBytes , 0 ,
327 MUIA_Dirlist_NumFiles , 0 ,
328 MUIA_Dirlist_NumDrawers, 0 ,
329 TAG_DONE );
333 if (data->directory)
335 ReadDirectory(obj, data);
340 return (msg->MethodID == OM_SET) ? DoSuperMethodA(cl, obj, (Msg)msg) : 0;
344 IPTR Dirlist__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
346 struct Dirlist_DATA *data = INST_DATA(cl, obj);
348 #define STORE *(msg->opg_Storage)
350 switch(msg->opg_AttrID)
352 case MUIA_Dirlist_AcceptPattern:
353 STORE = (IPTR)data->acceptpattern;
354 return 1;
356 case MUIA_Dirlist_Directory:
357 STORE = (IPTR)data->directory;
358 return 1;
360 case MUIA_Dirlist_DrawersOnly:
361 STORE = data->drawersonly;
362 return 1;
364 case MUIA_Dirlist_FilesOnly:
365 STORE = data->filesonly;
366 return 1;
368 case MUIA_Dirlist_FilterDrawers:
369 STORE = data->filterdrawers;
370 return 1;
372 case MUIA_Dirlist_FilterHook:
373 STORE = (IPTR)data->filterhook;
374 return 1;
376 case MUIA_Dirlist_MultiSelDirs:
377 STORE = data->multiseldirs;
378 return 1;
380 case MUIA_Dirlist_NumBytes:
381 STORE = data->numbytes;
382 return 1;
384 case MUIA_Dirlist_NumFiles:
385 STORE = data->numfiles;
386 return 1;
388 case MUIA_Dirlist_NumDrawers:
389 STORE = data->numdrawers;
390 return 1;
392 case MUIA_Dirlist_Path:
393 if (data->path)
395 FreeVec(data->path);
396 data->path = NULL;
399 STORE = 0;
401 if (data->status == MUIV_Dirlist_Status_Valid)
403 struct FileInfoBlock *fib;
405 DoMethod(obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &fib);
407 if (fib)
409 WORD len = strlen(fib->fib_FileName) + strlen(data->directory) + 3;
411 data->path = AllocVec(len, MEMF_ANY);
412 if (data->path)
414 strcpy(data->path, data->directory);
415 if (AddPart(data->path, fib->fib_FileName, len))
417 STORE = (IPTR)data->path;
422 return 1;
424 case MUIA_Dirlist_RejectIcons:
425 STORE = data->rejecticons;
426 return 1;
428 case MUIA_Dirlist_RejectPattern:
429 STORE = (IPTR)data->rejectpattern;
430 return 1;
432 case MUIA_Dirlist_SortDirs:
433 STORE = data->sortdirs;
434 return 1;
436 case MUIA_Dirlist_SortHighLow:
437 STORE = data->sorthighlow;
438 return 1;
440 case MUIA_Dirlist_SortType:
441 STORE = data->sorttype;
442 return 1;
444 case MUIA_Dirlist_Status:
445 STORE = data->status;
446 return 1;
450 return DoSuperMethodA(cl, obj, (Msg)msg);
455 IPTR Dirlist__MUIM_Dirlist_ReRead(struct IClass *cl, Object *obj, struct MUIP_Dirlist_ReRead *msg)
457 struct Dirlist_DATA *data = INST_DATA(cl, obj);
459 set(obj, MUIA_List_Quiet, TRUE);
460 if (data->status == MUIV_Dirlist_Status_Valid)
462 DoMethod(obj, MUIM_List_Clear);
464 SetAttrs(obj, MUIA_Dirlist_Status , MUIV_Dirlist_Status_Invalid,
465 MUIA_Dirlist_NumBytes , 0 ,
466 MUIA_Dirlist_NumFiles , 0 ,
467 MUIA_Dirlist_NumDrawers, 0 ,
468 TAG_DONE );
471 if (data->directory)
473 ReadDirectory(obj, data);
475 set(obj, MUIA_List_Quiet, FALSE);
477 return 0;
481 #if ZUNE_BUILTIN_DIRLIST
482 BOOPSI_DISPATCHER(IPTR, Dirlist_Dispatcher, cl, obj, msg)
484 switch (msg->MethodID)
486 case OM_NEW: return Dirlist__OM_NEW(cl, obj, (struct opSet *)msg);
487 case OM_DISPOSE: return Dirlist__OM_DISPOSE(cl, obj, msg);
488 case OM_SET: return Dirlist__OM_SET(cl, obj, (struct opSet *)msg);
489 case OM_GET: return Dirlist__OM_GET(cl, obj, (struct opGet *)msg);
490 case MUIM_Dirlist_ReRead: return Dirlist__MUIM_Dirlist_ReRead(cl, obj, (struct opGet *)msg);
491 default: return DoSuperMethodA(cl, obj, msg);
494 BOOPSI_DISPATCHER_END
496 const struct __MUIBuiltinClass _MUI_Dirlist_desc =
498 MUIC_Dirlist,
499 MUIC_List,
500 sizeof(struct Dirlist_DATA),
501 (void*)Dirlist_Dispatcher
503 #endif /* ZUNE_BUILTIN_DIRLIST */