using kprintf to output debug, which may be redirected to serial, is not a good idea...
[AROS-Contrib.git] / scalos / main / DefIcons.c
blob85e1cf4a1aa275252c487893857f614dd287c05b
1 // DefIcons.c
2 // $Date$
3 // $Revision$
6 #include <ctype.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <exec/types.h>
11 #include <exec/execbase.h>
12 #include <exec/memory.h>
13 #include <dos/dosextens.h>
14 #include <dos/dostags.h>
15 #include <dos/filehandler.h>
16 #ifdef __amigaos4__
17 #include <dos/anchorpath.h>
18 #endif
19 #include <libraries/iffparse.h>
20 #include <libraries/locale.h>
21 #include <intuition/intuitionbase.h>
22 #include <workbench/startup.h>
23 #include <workbench/workbench.h>
24 #include <utility/tagitem.h>
26 #define __USE_SYSBASE
28 #include <proto/exec.h>
29 #include <proto/intuition.h>
30 #include <proto/dos.h>
31 #include <proto/wb.h>
32 #include <proto/icon.h>
33 #include <proto/utility.h>
34 #include <proto/locale.h>
35 #include <proto/iconobject.h>
36 #include "debug.h"
37 #include <proto/scalos.h>
39 #include <clib/alib_protos.h>
41 #include <defs.h>
42 #include <scalos/scalos.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
48 #include <DefIcons.h>
50 #include "scalos_structures.h"
51 #include "FsAbstraction.h"
52 #include "functions.h"
53 #include "Variables.h"
55 //----------------------------------------------------------------------------
57 // local data structures
59 #define IOBUFFERLEN 480
60 #define NO_TYPE_NODE ((struct TypeNode *) -1)
62 #define DEFICON_THEME_PREFIX "THEME:DefIcons/def_"
63 #define DEFICON_PATH_PREFIX "def_"
65 //----------------------------------------------------------------------------
67 // local functions
69 static void ReloadDefIcons(void);
71 static VOID InitTypeTree(struct TypeNode *parentnode,STRPTR *desclist);
72 static struct TypeNode *AllocTypeNode(STRPTR *description);
73 static VOID AddSon(struct TypeNode *parent,struct TypeNode *son);
75 static LONG match(CONST_STRPTR a, CONST_STRPTR b, size_t len);
76 static struct TypeNode *DefIconsIdentifyDisk(BPTR lock);
77 static struct TypeNode *DefIconsIdentifyProject(CONST_STRPTR Name, T_ExamineData *fib);
78 static void DeleteTypeNode(struct TypeNode *tn);
79 static Object *ReadDefIconObjectForName(ULONG IconType, CONST_STRPTR TypeName,
80 BPTR dirLock, CONST_STRPTR OriginalName, struct TagItem *TagList);
81 static Object *ReadDefIconObjectForNameFallback(ULONG IconType, CONST_STRPTR TypeName,
82 BPTR dirLock, CONST_STRPTR OriginalName, struct TagItem *TagList);
83 static Object *CloneDefIconObject(Object *IconObj, BPTR dirLock,
84 CONST_STRPTR OriginalName, struct TagItem *TagList);
85 static STRPTR DefIconsGetDeviceName(CONST_STRPTR DosDevice, ULONG *DosType);
87 //----------------------------------------------------------------------------
89 // local data items
91 /* A table of clearly invalid ASCII characters (8 bits). */
92 static const UBYTE InvalidTab[256] =
94 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
95 1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
96 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
97 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
98 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
99 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
100 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
101 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
102 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
103 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
104 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
105 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
106 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
107 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
108 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
109 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
112 static struct TypeNode *RootType = NULL;
113 static BPTR seglist = (BPTR)NULL;
114 static BOOL DefIconsInit = FALSE;
115 static ULONG DefIconsPrefsCRC = 0;
117 static Object *CachedDefIconObjects[1 + WBAPPICON];
119 //----------------------------------------------------------------------------
121 // public data items
122 SCALOSSEMAPHORE DefIconsSemaphore;
123 SCALOSSEMAPHORE DefIconsCacheSemaphore;
125 //----------------------------------------------------------------------------
127 LONG InitDefIcons(void)
129 ScalosInitSemaphore(&DefIconsSemaphore);
130 ScalosInitSemaphore(&DefIconsCacheSemaphore);
132 DefIconsInit = TRUE;
134 ReloadDefIcons();
136 return RETURN_OK;
140 static void ReloadDefIcons(void)
142 static CONST_STRPTR DefIconsPrefsFileName = "ENV:deficons.prefs";
144 CleanupDefIcons();
146 ScalosObtainSemaphore(&DefIconsSemaphore);
148 DefIconsPrefsCRC = GetPrefsCRCFromName(DefIconsPrefsFileName);
149 seglist = LoadSeg((STRPTR) DefIconsPrefsFileName);
151 d1(kprintf("%s/%s/%ld: SegList=%08lx\n", __FILE__, __FUNC__, __LINE__, seglist));
153 if (seglist)
155 STRPTR inittable;
157 inittable = ((STRPTR)BADDR(seglist))+4;
158 InitTypeTree(NO_TYPE_NODE, &inittable);
160 d1(kprintf("%s/%s/%ld: RootType=%08lx\n", __FILE__, __FUNC__, __LINE__, RootType));
163 ScalosReleaseSemaphore(&DefIconsSemaphore);
167 void CleanupDefIcons(void)
169 ULONG n;
171 if (DefIconsInit)
173 ScalosObtainSemaphore(&DefIconsSemaphore);
175 DeleteTypeNode(RootType);
176 RootType = NULL;
178 if (seglist)
180 UnLoadSeg(seglist);
181 seglist = (BPTR)NULL;
184 ScalosReleaseSemaphore(&DefIconsSemaphore);
187 // Cleanup cached DefIcons
188 ScalosObtainSemaphore(&DefIconsCacheSemaphore);
189 for (n = 0; n < Sizeof(CachedDefIconObjects); n++)
191 if (CachedDefIconObjects[n])
193 DisposeIconObject(CachedDefIconObjects[n]);
194 CachedDefIconObjects[n] = NULL;
197 ScalosReleaseSemaphore(&DefIconsCacheSemaphore);
201 void NewDefIconsPrefs(struct internalScaWindowTask *iwt, struct NotifyMessage *msg)
203 struct SM_NewPreferences *smnp;
205 d1(KPrintF("%s/%s/%ld: smnp_PrefsFlags=%08lx\n", __FILE__, __FUNC__, __LINE__, SMNPFLAGF_DEFICONSPREFS));
207 smnp = (struct SM_NewPreferences *) SCA_AllocMessage(MTYP_NewPreferences, 0);
208 if (smnp)
210 smnp->smnp_PrefsFlags = SMNPFLAGF_DEFICONSPREFS;
211 PutMsg(iInfos.xii_iinfos.ii_MainMsgPort, &smnp->ScalosMessage.sm_Message);
216 BOOL ChangedDefIconsPrefs(void)
218 ULONG NewDefIconsPrefsCRC;
219 BOOL Changed = FALSE;
221 NewDefIconsPrefsCRC = GetPrefsCRCFromName("ENV:deficons.prefs");
222 d1(kprintf("%s/%s/%ld: NewDefIconsPrefsCRC=%08lx DefIconsPrefsCRC=%08lx\n",
223 __FILE__, __FUNC__, __LINE__, NewDefIconsPrefsCRC, DefIconsPrefsCRC));
225 if (NewDefIconsPrefsCRC != DefIconsPrefsCRC)
227 struct ScaWindowStruct *ws;
229 Changed = TRUE;
231 // Remove all references to DefIcons structure members
232 SCA_LockWindowList(SCA_LockWindowList_Shared);
233 for (ws=winlist.wl_WindowStruct; ws; ws = (struct ScaWindowStruct *) ws->ws_Node.mln_Succ)
235 struct internalScaWindowTask *iwt = (struct internalScaWindowTask *) ws->ws_WindowTask;
237 DoMethod(iwt->iwt_WindowTask.mt_WindowObject, SCCM_IconWin_ClearIconFileTypes);
239 SCA_UnLockWindowList();
241 FileTypeFlush(FALSE);
242 ReloadDefIcons();
245 return Changed;
249 static VOID InitTypeTree(struct TypeNode *parentnode,STRPTR *desclist)
251 struct TypeNode *newTn = NULL;
253 while (1)
255 switch(**desclist)
257 case TYPE_DOWN_LEVEL:
258 (*desclist)++;
259 InitTypeTree(newTn, desclist);
260 break;
262 case TYPE_UP_LEVEL:
263 (*desclist)++;
264 /* fall thru next case */
265 case TYPE_END:
266 return;
267 break;
269 default:
270 if ((newTn = AllocTypeNode(desclist))) /* desclist will be incremented by */
271 /* AllocTypeNode */
273 if (parentnode != NO_TYPE_NODE)
275 AddSon(parentnode, newTn);
277 else
279 if (RootType)
280 RootType->tn_RightBrother = newTn;
281 else
282 RootType = newTn;
285 break;
292 static struct TypeNode *AllocTypeNode(STRPTR *description)
294 struct TypeNode *nd;
295 ULONG j;
296 STRPTR arg;
297 STRPTR name;
299 j = 0;
300 name = *description;
301 arg = name + strlen(name) + 1;
302 while (*arg != ACT_END)
304 j++;
305 switch(*(arg++))
307 case ACT_MATCH:
308 arg = arg + 3 + abs((BYTE)arg[2]);
309 break;
310 case ACT_SEARCH:
311 case ACT_SEARCHSKIPSPACES:
312 arg = arg + 1 + abs((BYTE)arg[0]);
313 break;
314 case ACT_PROTECTION:
315 arg += 8;
316 break;
317 case ACT_FILESIZE:
318 case ACT_MINSIZEMB:
319 arg += 4;
320 break;
321 case ACT_NAMEPATTERN:
322 case ACT_DOSDEVICE:
323 case ACT_DEVICENAME:
324 case ACT_CONTENTS:
325 arg = arg + strlen(arg) + 1;
326 break;
327 case ACT_DOSTYPE:
328 arg = arg + 1 + arg[0];
329 break;
333 if ((nd = ScalosAlloc(sizeof(struct TypeNode) + j * sizeof(struct Magic))))
335 nd->tn_RightBrother = nd->tn_FirstSon = nd->tn_Parent = NULL;
336 nd->tn_IconObject = NULL;
337 nd->tn_Name = name;
339 j = 0;
340 arg = name + strlen(name) + 1;
341 while (*arg != ACT_END)
343 switch(nd->tn_Description[j].action = *(arg++))
345 case ACT_MATCH:
346 nd->tn_Description[j].arg1 = *(arg++);
347 nd->tn_Description[j].arg1 <<= 8;
348 nd->tn_Description[j].arg1 |= *(arg++);
349 nd->tn_Description[j].arg2 = (BYTE)*(arg++);
350 nd->tn_Description[j].str = (STRPTR) arg;
351 arg += abs(nd->tn_Description[j].arg2);
352 break;
353 case ACT_SEARCH:
354 case ACT_SEARCHSKIPSPACES:
355 nd->tn_Description[j].arg2 = (BYTE)*(arg++);
356 nd->tn_Description[j].str = arg;
357 arg += abs(nd->tn_Description[j].arg2);
358 break;
359 case ACT_FILESIZE:
360 case ACT_MINSIZEMB:
361 nd->tn_Description[j].arg2 = *(arg++);
362 nd->tn_Description[j].arg2 <<= 8;
363 nd->tn_Description[j].arg2 |= *(arg++);
364 nd->tn_Description[j].arg2 <<= 8;
365 nd->tn_Description[j].arg2 |= *(arg++);
366 nd->tn_Description[j].arg2 <<= 8;
367 nd->tn_Description[j].arg2 |= *(arg++);
368 break;
369 case ACT_DOSTYPE:
370 nd->tn_Description[j].arg2 = (BYTE)*(arg++);
371 nd->tn_Description[j].str = (STRPTR) arg;
372 arg += nd->tn_Description[j].arg2;
373 break;
374 case ACT_NAMEPATTERN:
375 case ACT_DOSDEVICE:
376 case ACT_DEVICENAME:
377 case ACT_CONTENTS:
378 nd->tn_Description[j].str = arg;
379 arg += strlen(arg) + 1;
380 break;
381 case ACT_PROTECTION:
382 nd->tn_Description[j].arg1 = *(arg++);
383 nd->tn_Description[j].arg1 <<= 8;
384 nd->tn_Description[j].arg1 |= *(arg++);
385 nd->tn_Description[j].arg1 <<= 8;
386 nd->tn_Description[j].arg1 |= *(arg++);
387 nd->tn_Description[j].arg1 <<= 8;
388 nd->tn_Description[j].arg1 |= *(arg++);
389 nd->tn_Description[j].arg2 = *(arg++);
390 nd->tn_Description[j].arg2 <<= 8;
391 nd->tn_Description[j].arg2 |= *(arg++);
392 nd->tn_Description[j].arg2 <<= 8;
393 nd->tn_Description[j].arg2 |= *(arg++);
394 nd->tn_Description[j].arg2 <<= 8;
395 nd->tn_Description[j].arg2 |= *(arg++);
396 break;
399 j++;
401 nd->tn_Description[j].action = ACT_END;
404 *description = arg+1; /* increment *description for recursion */
406 return(nd);
411 static VOID AddSon(struct TypeNode *parent,struct TypeNode *son)
413 struct TypeNode *nd;
415 if (!parent || !son)
416 return;
418 if ((nd = parent->tn_FirstSon))
420 while (nd->tn_RightBrother)
421 nd = nd->tn_RightBrother;
423 nd->tn_RightBrother = son;
425 else
426 parent->tn_FirstSon = son;
428 son->tn_Parent = parent;
433 /* compare two buffers of length 'len'. These functions cannot be replaced */
434 /* with strn(i)cmp() because the buffers may contain NULLs */
435 static LONG match(CONST_STRPTR a, CONST_STRPTR b, size_t len)
437 if (len > 0) /* case sensitive */
439 while (*a == *b)
441 if (!(--len))
442 return(0);
444 a++;
445 b++;
448 else /* ignore case */
450 while (toupper(*a) == toupper(*b))
452 if (!(++len)) return(0);
454 a++;
455 b++;
459 return(*a - *b);
464 /* DefIconsIdentify(BPTR dirLock, CONST_STRPTR *Name, ULONG IconType):
466 * Heuristically identify the type of a file.
468 * IMPORTANT: this function usually returns a TypeNode *, but may also return
469 * one of the special values WBDISK and WBDRAWER
470 it returns NULL for failure
473 struct TypeNode *DefIconsIdentify(BPTR dirLock, CONST_STRPTR Name, IPTR IconType)
475 struct TypeNode *type = NULL;
476 T_ExamineData *fib = NULL;
477 BPTR lock;
478 BPTR oldDirLock;
480 debugLock_d1(dirLock);
481 d1(KPrintF("%s/%s/%ld: Name=<%s>\n", __FILE__, __FUNC__, __LINE__, Name));
483 oldDirLock = CurrentDir(dirLock);
485 if ((lock = Lock((STRPTR) Name, ACCESS_READ)) && ScalosExamineBegin(&fib) &&
486 ScalosExamineLock(lock, &fib))
488 debugLock_d1(lock);
490 if (ScalosExamineIsDrawer(fib))
492 BPTR dirlock;
494 if ((dirlock = ParentDir(lock)))
496 Object *IconObj;
498 type = (struct TypeNode *) WBDRAWER;
499 UnLock(dirlock);
501 // extra check for WBGARBAGE
502 IconObj = NewIconObjectTags(Name,
503 TAG_END);
504 if (IconObj)
506 GetAttr(IDTA_Type, IconObj, (APTR) &type);
507 DisposeIconObject(IconObj);
510 else
512 type = DefIconsIdentifyDisk(lock);
515 else
517 type = DefIconsIdentifyProject(Name, fib);
520 else
522 d1(KPrintF("%s/%s/%ld: Name=<%s>\n", __FILE__, __FUNC__, __LINE__, Name));
524 if (!stricmp(Name, "disk"))
526 BPTR curdir;
528 curdir = CurrentDir((BPTR)NULL);
529 CurrentDir(curdir);
531 if ((lock = ParentDir(curdir)))
532 UnLock(lock);
533 else
534 type = (struct TypeNode *)WBDISK;
536 else if (ICONTYPE_NONE != IconType)
538 type = (struct TypeNode *) IconType;
542 ScalosExamineEnd(&fib);
543 if (lock)
544 UnLock(lock);
546 CurrentDir(oldDirLock);
548 d1(KPrintF("%s/%s/%ld: type=%08lx\n", __FILE__, __FUNC__, __LINE__, type));
550 return(type);
554 static struct TypeNode *DefIconsIdentifyDisk(BPTR lock)
556 struct InfoData *infoData = NULL;
557 struct TypeNode *type = (struct TypeNode *) WBDISK;
558 STRPTR AllocatedDevName = NULL;
560 debugLock_d1(lock);
562 ScalosObtainSemaphoreShared(&DefIconsSemaphore);
564 do {
565 struct TypeNode *candidate;
566 struct TypeNode *tn;
567 const struct DosList *VolumeNode;
568 CONST_STRPTR DosDevice = "";
569 CONST_STRPTR DeviceName = "";
570 ULONG DosType = MAKE_ID('D','O','S',0);
572 tn = RootType;
573 while (tn && 0 != Stricmp(tn->tn_Name, "disk"))
574 tn = tn->tn_RightBrother;
576 if (NULL == tn)
577 break;
579 infoData = ScalosAllocInfoData();
580 if (NULL == infoData)
581 break;
583 if (!Info(lock, infoData))
584 break;
586 type = tn;
587 d1(KPrintF("%s/%s/%ld: type=<%s>\n", __FILE__, __FUNC__, __LINE__, type->tn_Name));
588 d1(KPrintF("%s/%s/%ld: id_NumBlocks=%lu id_DiskType=%08lx id_VolumeNode=%08lx\n", \
589 __FILE__, __FUNC__, __LINE__, \
590 infoData->id_NumBlocks, infoData->id_DiskType, infoData->id_VolumeNode));
592 VolumeNode = BADDR(infoData->id_VolumeNode);
593 if (TypeOfMem((APTR) VolumeNode) & MEMF_PUBLIC)
595 d1(KPrintF("%s/%s/%ld: dol_Type=%ld dol_Name=%08lx dol_Task=%08lx\n", \
596 __FILE__, __FUNC__, __LINE__, VolumeNode->dol_Type, VolumeNode->dol_Name, VolumeNode->dol_Task));
598 if (VolumeNode->dol_Task && (TypeOfMem(VolumeNode->dol_Task) & MEMF_PUBLIC))
600 struct Task *DevTask = VolumeNode->dol_Task->mp_SigTask;
602 d1(KPrintF("%s/%s/%ld: dol_DiskType=%08lx\n", __FILE__, __FUNC__, __LINE__, VolumeNode->dol_misc.dol_volume.dol_DiskType));
604 DosDevice = DevTask->tc_Node.ln_Name;
605 d1(KPrintF("%s/%s/%ld: DevTask=<%s>\n", __FILE__, __FUNC__, __LINE__, DosDevice));
607 AllocatedDevName = DefIconsGetDeviceName(DosDevice, &DosType);
608 if (AllocatedDevName)
609 DeviceName = AllocatedDevName;
610 d1(KPrintF("%s/%s/%ld: DeviceName=<%s>\n", __FILE__, __FUNC__, __LINE__, DeviceName));
613 loop:
614 candidate = type->tn_FirstSon;
615 loop1:
616 while (candidate)
618 struct Magic *curr;
619 BOOL matching = 1;
622 curr = candidate->tn_Description;
626 switch (curr->action)
628 case ACT_END:
629 if (matching)
631 type = candidate;
632 goto loop; /* ////// */
634 break;
636 case ACT_OR:
637 if (matching)
639 type = candidate;
640 goto loop; /* ////// */
642 else
644 matching = 1;
646 break;
648 case ACT_MATCH:
649 case ACT_SEARCH:
650 case ACT_SEARCHSKIPSPACES:
651 case ACT_FILESIZE:
652 case ACT_NAMEPATTERN:
653 case ACT_PROTECTION:
654 case ACT_ISASCII:
655 matching = 0;
656 break;
658 case ACT_MINSIZEMB:
659 if (matching)
661 ULONG BlocksPerMByte = (1024 * 1024) / infoData->id_BytesPerBlock;
663 d1(KPrintF("%s/%s/%ld: BlocksPerMByte=%lu id_NumBlocks=%lu\n", __FILE__, __FUNC__, __LINE__, BlocksPerMByte, infoData->id_NumBlocks));
665 if ((infoData->id_NumBlocks / BlocksPerMByte) < curr->arg2)
666 matching = 0;
668 break;
670 case ACT_DOSDEVICE:
671 if (matching)
673 UBYTE buf[150];
675 matching = 0;
676 if (ParsePatternNoCase(curr->str, (STRPTR) buf, sizeof(buf)) >= 0 &&
677 MatchPatternNoCase((STRPTR) buf, (STRPTR) DosDevice))
678 matching = 1;
680 break;
682 case ACT_DEVICENAME:
683 if (matching)
685 UBYTE buf[150];
687 matching = 0;
688 if (ParsePatternNoCase(curr->str, (STRPTR) buf, sizeof(buf)) >= 0 &&
689 MatchPatternNoCase((STRPTR) buf, (STRPTR) DeviceName))
690 matching = 1;
692 break;
694 case ACT_DOSTYPE:
695 if (matching)
697 UBYTE DosTypeString[5];
699 memcpy(DosTypeString, &DosType, sizeof(DosType));
700 DosTypeString[4] = '\0';
702 d1(KPrintF("%s/%s/%ld: arg2=%ld DosType=<%s> str=<%s>\n", __FILE__, __FUNC__, __LINE__, curr->arg2, DosTypeString, curr->str));
704 if (abs(curr->arg2) > sizeof(ULONG) ||
705 match((CONST_STRPTR)DosTypeString, curr->str, curr->arg2))
707 matching = 0;
709 break;
711 break;
713 case ACT_CONTENTS:
714 if (matching)
716 LONG result;
717 struct AnchorPath *ap;
718 BPTR OldDir = CurrentDir(lock);
720 matching = 0;
722 ap = ScalosAllocAnchorPath(APF_DOWILD, 0);
723 if (ap)
725 result = MatchFirst(curr->str, ap);
726 if (RETURN_OK == result)
727 matching = 1;
729 d1(KPrintF("%s/%s/%ld: str=<%s> result=%ld\n", __FILE__, __FUNC__, __LINE__, curr->str, result));
731 MatchEnd(ap);
732 ScalosFreeAnchorPath(ap);
735 CurrentDir(OldDir);
737 break;
739 } while ((curr++)->action != ACT_END);
741 candidate = candidate->tn_RightBrother;
744 /* don't consider valid a macroclass alone */
745 if (type->tn_Description->action == ACT_MACROCLASS)
747 candidate = type->tn_RightBrother;
748 type = type->tn_Parent;
749 goto loop1; /* ////// */
751 } while (0);
753 ScalosReleaseSemaphore(&DefIconsSemaphore);
755 if (AllocatedDevName)
756 ScalosFree(AllocatedDevName);
757 ScalosFreeInfoData(&infoData);
759 return type;
763 static struct TypeNode *DefIconsIdentifyProject(CONST_STRPTR Name, T_ExamineData *fib)
765 UBYTE *Buffer = NULL;
766 BPTR File = (BPTR) NULL;
767 struct TypeNode *type = (struct TypeNode *) WBPROJECT;
768 struct TypeNode *tn;
770 ScalosObtainSemaphoreShared(&DefIconsSemaphore);
772 tn = RootType;
773 while (tn && 0 != Stricmp(tn->tn_Name, "project"))
774 tn = tn->tn_RightBrother;
776 if (tn && (Buffer = ScalosAlloc(IOBUFFERLEN)) && (File = Open((STRPTR) Name,MODE_OLDFILE)))
778 WORD Size;
780 type = tn;
782 d1(KPrintF("%s/%s/%ld: fib_FileName=<%s> type=<%s>\n", __FILE__, __FUNC__, __LINE__, fib->fib_FileName, type->tn_Name));
784 /* Read the first IOBUFFERLEN bytes. */
785 if ((Size = Read(File,Buffer,IOBUFFERLEN)) >= 0)
787 struct TypeNode *candidate;
788 const UBYTE *buf;
790 loop:
791 candidate = type->tn_FirstSon;
792 loop1:
793 while (candidate)
795 struct Magic *curr;
796 BOOL matching = 1;
799 curr = candidate->tn_Description;
800 buf = Buffer;
804 switch (curr->action)
806 case ACT_END:
807 if (matching)
809 type = candidate;
810 goto loop; /* ////// */
812 break;
814 case ACT_OR:
815 if (matching)
817 type = candidate;
818 goto loop; /* ////// */
820 else
822 matching = 1;
823 buf = Buffer;
825 break;
827 case ACT_MATCH:
828 if (matching)
830 if (Size - (buf - Buffer) < curr->arg1 + abs(curr->arg2) ||
831 match((STRPTR)&buf[curr->arg1],curr->str,abs(curr->arg2)))
832 matching = 0;
834 break;
836 case ACT_SEARCH:
837 case ACT_SEARCHSKIPSPACES:
838 if (matching)
840 WORD loop;
843 loop = Size - (buf - Buffer) - abs(curr->arg2);
845 while (loop >= 0)
847 if (!match((STRPTR)buf,curr->str,curr->arg2))
848 break;
850 if (curr->action == ACT_SEARCHSKIPSPACES && !isspace(*buf))
851 loop = -1;
852 else
854 loop--;
855 buf++;
859 if (loop < 0) matching = 0;
861 break;
863 case ACT_FILESIZE:
864 if (matching)
866 if (0 != Cmp64(ScalosExamineGetSize(fib), MakeU64(curr->arg2)))
867 //if (fib->fib_Size != curr->arg2)
868 matching = 0;
870 break;
872 case ACT_NAMEPATTERN:
873 if (matching)
875 UBYTE buf[150];
877 matching = 0;
878 if (ParsePatternNoCase(curr->str,(STRPTR)buf,sizeof(buf)) >= 0 &&
879 MatchPatternNoCase((STRPTR)buf, (STRPTR)ScalosExamineGetName(fib)))
880 matching = 1;
882 break;
884 case ACT_PROTECTION:
885 if (matching)
887 if ((ScalosExamineGetProtection(fib) & curr->arg1) != curr->arg2)
888 matching = 0;
890 break;
892 case ACT_ISASCII:
893 if (matching)
895 matching = 0;
896 if (Size)
898 buf = &Buffer[Size];
900 while (buf > Buffer && !InvalidTab[*(--buf)]);
902 if (buf == Buffer) matching = 1;
905 break;
907 case ACT_MINSIZEMB:
908 case ACT_DOSDEVICE:
909 case ACT_DEVICENAME:
910 case ACT_CONTENTS:
911 matching = 0;
912 break;
914 } while ((curr++)->action != ACT_END);
916 candidate = candidate->tn_RightBrother;
919 /* don't consider valid a macroclass alone */
920 if (type->tn_Description->action == ACT_MACROCLASS)
922 candidate = type->tn_RightBrother;
923 type = type->tn_Parent;
924 goto loop1; /* ////// */
927 if (!stricmp(type->tn_Name,"iff"))
929 struct TypeNode *new;
930 STRPTR desc;
933 if ((desc = ScalosAlloc(14)))
935 STRPTR descp = desc;
937 strncpy(desc,(char *)&Buffer[8],4);
938 desc[4] = 0;
939 desc[5] = ACT_MATCH;
940 desc[6] = 0;
941 desc[7] = 8;
942 desc[8] = 4;
943 strncpy(&desc[9],(char *)&Buffer[8],4);
944 desc[13] = ACT_END;
946 if ((new = AllocTypeNode(&descp)))
948 AddSon(type,new);
950 type = new;
952 else
953 ScalosFree(desc);
959 ScalosReleaseSemaphore(&DefIconsSemaphore);
961 if (File)
962 Close(File);
963 if (Buffer)
964 ScalosFree(Buffer);
965 return type;
969 static void DeleteTypeNode(struct TypeNode *tn)
971 while (tn)
973 struct TypeNode *tnNext = tn->tn_RightBrother;
975 DeleteTypeNode(tn->tn_FirstSon);
977 if (tn->tn_IconObject)
979 DisposeIconObject(tn->tn_IconObject);
980 tn->tn_IconObject = NULL;
982 ScalosFree(tn);
984 tn = tnNext;
989 Object *ReturnDefIconObjTags(BPTR dirLock, CONST_STRPTR Name, ULONG FirstTag, ...)
991 Object *o = NULL;
992 struct TagItem *TagList;
993 va_list args;
995 d1(KPrintF("%s/%s/%ld: Name=<%s>\n", __FILE__, __FUNC__, __LINE__, Name));
997 va_start(args, FirstTag);
999 TagList = ScalosVTagList(FirstTag, args);
1001 if (TagList)
1003 o = ReturnDefIconObj(dirLock, Name, TagList);
1004 FreeTagItems(TagList);
1007 va_end(args);
1009 return o;
1012 Object *ReturnDefIconObj(BPTR dirLock, CONST_STRPTR Name, struct TagItem *TagList)
1014 struct TypeNode *tn;
1015 Object *IconObj = NULL;
1017 if (Name && strlen(Name) > 0)
1018 tn = DefIconsIdentify(dirLock, Name, GetTagData(IDTA_Type, ICONTYPE_NONE, TagList));
1019 else
1020 tn = DefIconsIdentifyDisk(dirLock);
1022 d1(KPrintF("%s/%s/%ld: tn=%08lx Name=<%s>\n", __FILE__, __FUNC__, __LINE__, tn, Name));
1023 debugLock_d1(dirLock);
1025 switch ((IPTR) tn)
1027 case WBDISK:
1028 IconObj = ReadDefIconObjectForNameFallback(WBDISK,
1029 "disk", dirLock, Name, TagList);
1030 d1(KPrintF("%s/%s/%ld: WBDISK IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1031 break;
1033 case WBDRAWER:
1034 IconObj = ReadDefIconObjectForNameFallback(WBDRAWER,
1035 "drawer", dirLock, Name, TagList);
1036 d1(KPrintF("%s/%s/%ld: WBDRAWER IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1037 break;
1039 case WBAPPICON:
1040 IconObj = ReadDefIconObjectForNameFallback(WBAPPICON,
1041 "appicon", dirLock, Name, TagList);
1042 d1(KPrintF("%s/%s/%ld: WBAPPICON IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1043 if (NULL == IconObj)
1045 IconObj = ReadDefIconObjectForNameFallback(WBPROJECT,
1046 "project", dirLock, Name, TagList);
1048 d1(KPrintF("%s/%s/%ld: WBAPPICON IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1049 break;
1051 case ICONTYPE_NONE:
1052 IconObj = ReadDefIconObjectForNameFallback(WBPROJECT,
1053 "project", dirLock, Name, TagList);
1054 d1(KPrintF("%s/%s/%ld: ??? IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1055 break;
1057 default:
1058 if (IS_TYPENODE(tn))
1060 d1(KPrintF("%s/%s/%ld: tn=%08lx tn_IconObject=%08lx\n", __FILE__, __FUNC__, __LINE__, tn, tn->tn_IconObject));
1061 if (tn->tn_IconObject)
1063 // We have a cached iconObject, try to clone it now
1064 IconObj = CloneDefIconObject(tn->tn_IconObject, dirLock, Name, TagList);
1065 d1(KPrintF("%s/%s/%ld: CloneDefIconObject returned IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1068 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1069 if (NULL == IconObj)
1071 struct TypeNode *tn2 = tn;
1073 while (tn2 && NULL == IconObj)
1075 IconObj = ReadDefIconObjectForName(WBPROJECT,
1076 tn2->tn_Name, dirLock, Name, TagList);
1078 d1(KPrintF("%s/%s/%ld: IconObj=%08lx tn2=%08lx <%s> Parent=%08lx\n", \
1079 __FILE__, __FUNC__, __LINE__, IconObj, tn2, tn2->tn_Name, tn2->tn_Parent));
1080 tn2 = tn2->tn_Parent;
1083 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1084 tn->tn_IconObject = IconObj;
1085 if (tn->tn_IconObject)
1087 IconObj = CloneDefIconObject(tn->tn_IconObject, dirLock, Name, TagList);
1088 d1(KPrintF("%s/%s/%ld: CloneDefIconObject returned IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1089 if (NULL == IconObj)
1091 // Cloning failed
1092 IconObj = tn->tn_IconObject;
1093 tn->tn_IconObject = NULL;
1098 if (NULL == IconObj)
1100 IconObj = GetDefIconObjectTags(WBPROJECT,
1101 IDTA_Text, (IPTR) Name,
1102 TAG_MORE, (IPTR) TagList,
1103 TAG_END);
1105 break;
1108 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1110 return IconObj;
1114 static Object *ReadDefIconObjectForName(ULONG IconType, CONST_STRPTR TypeName,
1115 BPTR dirLock, CONST_STRPTR OriginalName, struct TagItem *TagList)
1117 STRPTR DefIconPath;
1118 Object *IconObj = NULL;
1120 DefIconPath = AllocPathBuffer();
1121 d1(KPrintF("%s/%s/%ld: DefIconPath=%08lx TypeName=<%s>\n", __FILE__, __FUNC__, __LINE__, \
1122 DefIconPath, TypeName));
1123 if (DefIconPath)
1125 struct WBArg OriginalLocation;
1127 strcpy(DefIconPath, DEFICON_THEME_PREFIX);
1128 SafeStrCat(DefIconPath, TypeName, Max_PathLen);
1130 OriginalLocation.wa_Lock = dirLock;
1131 OriginalLocation.wa_Name = (STRPTR) OriginalName;
1133 d1(KPrintF("%s/%s/%ld: DefIconPath=<%s>\n", __FILE__, __FUNC__, __LINE__, DefIconPath));
1135 IconObj = (Object *) NewIconObjectTags(DefIconPath,
1136 IDTA_IconLocation, (IPTR) &OriginalLocation,
1137 IDTA_SupportedIconTypes, GetTagData(IDTA_SupportedIconTypes, CurrentPrefs.pref_SupportedIconTypes, TagList),
1138 IDTA_SizeConstraints, GetTagData(IDTA_SizeConstraints, (IPTR) &CurrentPrefs.pref_IconSizeConstraints, TagList),
1139 IDTA_ScalePercentage, GetTagData(IDTA_ScalePercentage, CurrentPrefs.pref_IconScaleFactor, TagList),
1140 TagList ? TAG_MORE : TAG_IGNORE, (IPTR) TagList,
1141 TAG_END);
1143 d1(kprintf("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1145 if (NULL == IconObj)
1147 stccpy(DefIconPath, CurrentPrefs.pref_DefIconPath, Max_PathLen);
1148 AddPart(DefIconPath, DEFICON_PATH_PREFIX, Max_PathLen);
1149 SafeStrCat(DefIconPath, TypeName, Max_PathLen);
1151 d1(KPrintF("%s/%s/%ld: DefIconPath=<%s>\n", __FILE__, __FUNC__, __LINE__, DefIconPath));
1153 IconObj = (Object *) NewIconObjectTags(DefIconPath,
1154 IDTA_IconLocation, (IPTR) &OriginalLocation,
1155 IDTA_SupportedIconTypes, GetTagData(IDTA_SupportedIconTypes, CurrentPrefs.pref_SupportedIconTypes, TagList),
1156 IDTA_SizeConstraints, GetTagData(IDTA_SizeConstraints, (IPTR) &CurrentPrefs.pref_IconSizeConstraints, TagList),
1157 IDTA_ScalePercentage, GetTagData(IDTA_ScalePercentage, CurrentPrefs.pref_IconScaleFactor, TagList),
1158 TagList ? TAG_MORE : TAG_IGNORE, (IPTR) TagList,
1159 TAG_END);
1161 d1(kprintf("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1164 FreePathBuffer(DefIconPath);
1167 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1169 return IconObj;
1173 static Object *ReadDefIconObjectForNameFallback(ULONG IconType, CONST_STRPTR TypeName,
1174 BPTR dirLock, CONST_STRPTR OriginalName, struct TagItem *TagList)
1176 Object *IconObj = NULL;
1178 ScalosObtainSemaphoreShared(&DefIconsCacheSemaphore);
1179 if (IconType >= WBDISK && IconType <= WBAPPICON && CachedDefIconObjects[IconType])
1181 // We have a cached iconObject, try to clone it now
1182 IconObj = CloneDefIconObject(CachedDefIconObjects[IconType], dirLock, OriginalName, TagList);
1183 d1(KPrintF("%s/%s/%ld: CloneDefIconObject returned IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1185 ScalosReleaseSemaphore(&DefIconsCacheSemaphore);
1187 if (NULL == IconObj)
1189 IconObj = ReadDefIconObjectForName(IconType, TypeName,
1190 dirLock, OriginalName, TagList);
1192 if (IconType >= WBDISK && IconType <= WBAPPICON && IconObj)
1194 ScalosObtainSemaphore(&DefIconsCacheSemaphore);
1196 if (CachedDefIconObjects[IconType])
1197 DisposeIconObject(CachedDefIconObjects[IconType]);
1199 CachedDefIconObjects[IconType] = IconObj;
1200 IconObj = CloneDefIconObject(CachedDefIconObjects[IconType], dirLock, OriginalName, TagList);
1201 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1202 if (NULL == IconObj)
1204 // Cloning failed
1205 IconObj = CachedDefIconObjects[IconType];
1206 CachedDefIconObjects[IconType] = NULL;
1209 ScalosReleaseSemaphore(&DefIconsCacheSemaphore);
1211 else
1213 IconObj = GetDefIconObjectTags(IconType,
1214 IDTA_Text, (IPTR) OriginalName,
1215 TAG_MORE, (IPTR) TagList,
1216 TAG_END);
1220 return IconObj;
1224 static Object *CloneDefIconObject(Object *IconObj, BPTR dirLock,
1225 CONST_STRPTR OriginalName, struct TagItem *TagList)
1227 struct WBArg OriginalLocation;
1228 struct TagItem CloneTags[6];
1230 if (NULL == IconObj)
1231 return NULL;
1233 OriginalLocation.wa_Lock = dirLock;
1234 OriginalLocation.wa_Name = (STRPTR) OriginalName;
1236 d1(KPrintF("%s/%s/%ld: DefIconPath=<%s>\n", __FILE__, __FUNC__, __LINE__, OriginalName));
1237 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1239 CloneTags[0].ti_Tag = IDTA_IconLocation;
1240 CloneTags[0].ti_Data = (IPTR) &OriginalLocation;
1242 CloneTags[1].ti_Tag = IDTA_SupportedIconTypes;
1243 CloneTags[1].ti_Data = GetTagData(IDTA_SupportedIconTypes, CurrentPrefs.pref_SupportedIconTypes, TagList);
1245 CloneTags[2].ti_Tag = IDTA_SizeConstraints;
1246 CloneTags[2].ti_Data = GetTagData(IDTA_SizeConstraints, (IPTR) &CurrentPrefs.pref_IconSizeConstraints, TagList);
1248 CloneTags[3].ti_Tag = IDTA_ScalePercentage;
1249 CloneTags[3].ti_Data = GetTagData(IDTA_ScalePercentage, CurrentPrefs.pref_IconScaleFactor, TagList);
1251 CloneTags[4].ti_Tag = TagList ? TAG_MORE : TAG_IGNORE;
1252 CloneTags[4].ti_Data = (IPTR) TagList;
1254 CloneTags[5].ti_Tag = TAG_END;
1255 CloneTags[5].ti_Data = 0;
1257 IconObj = (Object *) DoMethod(IconObj,
1258 IDTM_CloneIconObject, CloneTags);
1260 d1(KPrintF("%s/%s/%ld: IconObj=%08lx\n", __FILE__, __FUNC__, __LINE__, IconObj));
1262 return IconObj;
1266 // DosDevice : DOS device name ("DH0"), without trailing ":"
1267 static STRPTR DefIconsGetDeviceName(CONST_STRPTR DosDevice, ULONG *DosType)
1269 STRPTR DevName = NULL;
1271 do {
1272 struct DosList *dl;
1273 struct FileSysStartupMsg *fssm;
1274 struct DosEnvec *env;
1275 CONST_STRPTR BDevName;
1276 size_t Length;
1278 dl = LockDosList(LDF_DEVICES | LDF_READ);
1280 dl = FindDosEntry(dl, DosDevice, LDF_DEVICES);
1281 if (NULL == dl)
1282 break;
1284 if (BNULL == dl->dol_misc.dol_handler.dol_Startup)
1285 break;
1287 fssm = BADDR(dl->dol_misc.dol_handler.dol_Startup);
1288 if (!(TypeOfMem(fssm) & MEMF_PUBLIC))
1289 break;
1291 if (BNULL == fssm->fssm_Device)
1292 break;
1294 BDevName = BADDR(fssm->fssm_Device);
1295 if (!(TypeOfMem((APTR) BDevName) & MEMF_PUBLIC))
1296 break;
1298 Length = BDevName[0];
1299 DevName = ScalosAlloc(1 + Length);
1300 if (NULL == DevName)
1301 break;
1303 memcpy(DevName, BDevName + 1, Length);
1304 DevName[Length] = '\0';
1306 env = BADDR(fssm->fssm_Environ);
1307 if (NULL == env)
1308 break;
1309 if (!(TypeOfMem((APTR) env) & MEMF_PUBLIC))
1310 break;
1312 *DosType = env->de_DosType;
1313 } while (0);
1315 UnLockDosList(LDF_DEVICES | LDF_READ);
1317 return DevName;