Improvements to AutoDocs and comments.
[aros:aros.git] / AROS / workbench / libs / icon / geticontaglist.c
1 /*
2     Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3     $Id$
4 */
5
6 #include <aros/debug.h>
7 #include <workbench/icon.h>
8
9 #include "icon_intern.h"
10 #include "support.h"
11 #include "support_builtin.h"
12 #include "identify.h"
13
14 /*****************************************************************************
15
16     NAME */
17 #include <proto/icon.h>
18
19         AROS_LH2(struct DiskObject *, GetIconTagList,
20
21 /*  SYNOPSIS */
22         AROS_LHA(CONST_STRPTR, name, A0),
23         AROS_LHA(const struct TagItem *, tags, A1),
24 /*  LOCATION */
25         struct IconBase *, IconBase, 30, Icon)
26
27 /*  FUNCTION
28         Opens an icon from disk.
29
30     INPUTS
31         name - object path (without .info extension). May be NULL when
32             retrieving a default icon.
33         tags - tag list containing tags described below.
34
35     TAGS
36         ICONA_ErrorCode (LONG *)
37         ICONGETA_GetDefaultType (LONG) - Default icon type to get. This
38                 overrides the "name" parameter.
39         ICONGETA_GetDefaultName (STRPTR) - Name of default icon to get. This
40                 overrides the "name" parameter.
41         ICONGETA_FailIfUnavailable (BOOL) - Find a default icon if there is no
42                 specific icon.
43         ICONGETA_GetPaletteMappedIcon (BOOL)
44         ICONGETA_IsDefaultIcon (LONG *) - Upon completion of this function, the
45             referenced LONG will be set to a boolean value indicating whether
46             the returned icon is a default icon.
47         ICONGETA_RemapIcon (BOOL)
48         ICONGETA_GenerateImageMasks (BOOL)
49         ICONGETA_Label (STRPTR)
50         ICONGETA_Screen (struct Screen *)
51
52     RESULT
53
54     NOTES
55
56     EXAMPLE
57
58     BUGS
59
60     SEE ALSO
61
62     INTERNALS
63
64 *****************************************************************************/
65 {
66     AROS_LIBFUNC_INIT
67
68     struct TagItem       *tstate            = (struct TagItem *)tags;
69     struct TagItem *tag;
70     struct DiskObject    *icon              = NULL;
71     LONG                  defaultType       = -1;
72     CONST_STRPTR          defaultName       = NULL;
73     IPTR                  failIfUnavailable = TRUE;
74     LONG                 *isDefaultIcon     = NULL;
75     
76     IPTR                  getPaletteMappedIcon = TRUE;
77     IPTR                  remapIcon            = TRUE;
78     IPTR                  generateImageMasks   = TRUE;
79     struct Screen        *screen               = NULL;
80     STRPTR                label                = NULL; // FIXME: not used
81     LONG                 error                 = 0;
82     LONG                 *errorCode            = NULL;
83     
84 #   define SET_ISDEFAULTICON(value) (isDefaultIcon != NULL ? *isDefaultIcon = (value) : (value))
85
86     D(bug("[%s] name %s, tags %p\n", __func__, name, tags));
87
88     /* Parse taglist -------------------------------------------------------*/
89     while ((tag = NextTagItem(&tstate)) != NULL)
90     {
91         switch (tag->ti_Tag)
92         {
93             case ICONGETA_GetDefaultType:
94                 if (defaultType == -1)
95                     defaultType = tag->ti_Data; 
96                 break;
97                 
98             case ICONGETA_GetDefaultName:
99                 if (defaultName == NULL)
100                     defaultName = (CONST_STRPTR) tag->ti_Data; 
101                 break;
102                 
103             case ICONGETA_FailIfUnavailable:
104                 failIfUnavailable = tag->ti_Data;
105                 break;
106                 
107             case ICONGETA_IsDefaultIcon:
108                 isDefaultIcon  = (LONG *) tag->ti_Data;
109                 SET_ISDEFAULTICON(FALSE);
110                 break;
111                 
112             case ICONGETA_GetPaletteMappedIcon:
113                 getPaletteMappedIcon = tag->ti_Data;
114                 break;
115                 
116             case ICONGETA_RemapIcon:
117                 remapIcon = tag->ti_Data;
118                 break;
119                 
120             case ICONGETA_GenerateImageMasks:
121                 generateImageMasks = tag->ti_Data;
122                 break;
123                 
124             case ICONGETA_Screen:
125                 screen = (struct Screen *) tag->ti_Data;
126                 break;
127             
128             case ICONGETA_Label:
129                 label = (STRPTR) tag->ti_Data;
130                 break;
131                 
132             case ICONA_ErrorCode:
133                 errorCode = (LONG *) tag->ti_Data;
134                 break;
135         }
136     }
137     
138     if (defaultType != -1 || defaultName != NULL)
139     {
140         if (defaultName != NULL)
141         {
142             BPTR file = OpenDefaultIcon(defaultName, MODE_OLDFILE);
143             
144             D(bug("[%s] Find default icon '%s'\n", __func__, defaultName));
145             if (file != BNULL)
146             {
147                 D(bug("[%s] Found default icon '%s'\n", __func__, defaultName));
148                 icon = ReadIcon(file);
149                 CloseDefaultIcon(file);
150                 SET_ISDEFAULTICON(TRUE);
151             }
152         }
153
154         if (icon == NULL && defaultType != -1 && defaultName == NULL)
155         {
156             CONST_STRPTR defaultIconName = GetDefaultIconName(defaultType);
157             
158             D(bug("[%s] Find default icon type %d\n", __func__, defaultType));
159             if (defaultIconName != NULL)
160             {
161                 icon = GetIconTags
162                 (
163                     NULL,
164                     ICONGETA_GetDefaultName, (IPTR) defaultIconName,
165                     TAG_END
166                 );
167                 D(bug("[%s] Find default icon type %d as %p\n", __func__, defaultType, icon));
168                 
169                 if (icon == NULL)
170                 {
171                     icon = GetBuiltinIcon(defaultType);
172                     D(bug("[%s] Using builtin icon %p\n", __func__, icon));
173                     SET_ISDEFAULTICON(TRUE);
174                 }
175             }
176         }
177     }
178     else if (name != NULL)
179     {
180         BPTR file = OpenIcon(name, MODE_OLDFILE);
181         
182         D(bug("[%s] Find custom icon '%s'\n", __func__, name));
183         if (file != BNULL)
184         {
185             D(bug("[%s] Found custom icon '%s'\n", __func__, name));
186             icon = ReadIcon(file);
187             CloseIcon(file);
188             
189             if (icon != NULL && icon->do_Type == 0)
190             {
191                 /* Force the icon type */
192                 BPTR lock = LockObject(name, ACCESS_READ);
193                 if (lock != BNULL)
194                 {
195                     LONG type = FindType(lock);
196                     if (type != -1) icon->do_Type = type;
197                     
198                     UnLockObject(lock);
199                 }
200             }
201         }
202     } else {
203         /* NULL name = return empty DiskObject */
204         D(bug("[%s] Get an empty DiskObject\n", __func__));
205         icon = NewDiskObject(0);
206     }
207
208     /* Try to identify it by name or type */
209     if (icon == NULL && !failIfUnavailable)
210     {
211         struct IconIdentifyMsg iim;
212
213         D(bug("[%s] Falling back to default icon for %s\n", __func__, name));
214        
215         if (name && (iim.iim_FileLock = LockObject(name, ACCESS_READ)) != BNULL)
216         {
217             D(bug("[%s] Locked %s, identifying\n", __func__, name));
218             if ((iim.iim_FIB = AllocDosObject(DOS_FIB, TAG_DONE)) != NULL)
219             {
220                 if (Examine(iim.iim_FileLock, iim.iim_FIB))
221                 {
222                     iim.iim_SysBase     = (struct Library *) SysBase;
223                     iim.iim_DOSBase     = (struct Library *) DOSBase;
224                     iim.iim_UtilityBase = (struct Library *) UtilityBase;
225                     iim.iim_IconBase    = (struct Library *) IconBase;
226                     iim.iim_Tags        = tags;
227                     
228                     iim.iim_ParentLock  = ParentDir(iim.iim_FileLock);
229                     if (iim.iim_ParentLock == BNULL && IoErr() == 0)
230                         iim.iim_FIB->fib_DirEntryType = ST_ROOT;
231                     iim.iim_FileHandle  = Open(name, MODE_OLDFILE);
232                     
233                     if (LB(IconBase)->ib_IdentifyHook != NULL)
234                     {
235                         /* Use user-provided identify hook */
236                         icon = (struct DiskObject *) CALLHOOKPKT
237                         (
238                             LB(IconBase)->ib_IdentifyHook, NULL, &iim
239                         );
240                         
241                         if (icon != NULL)
242                         {
243                             /*
244                                 Sanity check since we don't trust the 
245                                 user-provided hook too much. ;-)
246                             */
247                             
248                             LONG type = FindType(iim.iim_FileLock);
249                             if (type != -1) icon->do_Type = type;
250                         }
251                     }
252                     
253                     if (icon == NULL)
254                     {
255                         /* Fall back to the default identify function */
256                         D(bug("[%s] Finding default icon for iim %p\n", __func__, &iim));
257                         icon = FindDefaultIcon(&iim);
258                     }
259                     
260                     if (iim.iim_ParentLock != BNULL) UnLock(iim.iim_ParentLock);
261                     if (iim.iim_FileHandle != BNULL) Close(iim.iim_FileHandle);
262                 }
263                 
264                 FreeDosObject(DOS_FIB, iim.iim_FIB);
265             }
266             else
267             {
268                 error = IoErr();
269             }
270             
271             UnLockObject(iim.iim_FileLock);
272         }
273
274         if (icon == NULL && defaultType > 0) {
275             icon = GetBuiltinIcon(defaultType);
276             D(bug("[%s] Using builtin icon %p\n", __func__, icon));
277         }
278
279         if (icon == NULL) {
280             LONG type = (name && Stricmp("Disk", name)==0) ? WBDISK : WBPROJECT;
281             icon = GetBuiltinIcon(type);
282             D(bug("[%s] Using builtin icon %p, type %d\n",  __func__, icon, type));
283         }
284     }
285
286
287     if (!icon)
288         goto exit;
289
290     if (label != NULL) {
291         /* TODO: Add the label specified in 'label' to the icon */
292     }
293
294     if (generateImageMasks) {
295         D(bug("[%s] %p: Generate image masks\n", __func__, icon));
296         /* A side effect of palette mapping the icon... */
297         getPaletteMappedIcon = TRUE;
298     }
299
300     if (getPaletteMappedIcon) {
301         D(bug("[%s] %p: Generate palette mapped icon\n", __func__, icon));
302         /* A side effect of remapping the icon to the DefaultPubScreen */
303         remapIcon = TRUE;
304     }
305
306     if (remapIcon) {
307         if (screen == NULL)
308             IconControl(NULL, ICONCTRLA_GetGlobalScreen, &screen, TAG_END);
309     } else {
310         screen = NULL;
311     }
312
313     /* Any last-minute fixups */
314     PrepareIcon(icon);
315
316     D(bug("[%s] %p: Performing initial layout for screen %p\n", __func__, icon, screen));
317     LayoutIconA(icon, screen, (struct TagItem *)tags);
318
319 exit:
320     /* Set error code */
321     if (errorCode != NULL)
322         *errorCode = error;
323     SetIoErr(error);
324
325     D(bug("[%s] name %s, tags %p => %p\n", __func__, name, tags, icon));
326
327     return icon;
328
329     AROS_LIBFUNC_EXIT
330
331 #   undef SET_ISDEFAULTICON
332
333 } /* GetIconTagList() */