* Put a FIXME for most of the #define xxxBase contructs
[AROS.git] / workbench / system / ftmanager / fontlist_class.c
blob94fd1326f0eb68cfefb2b21e5489c6af48c0a51c
1 #define NO_INLINE_STDARG
2 #include <aros/debug.h>
3 #include <proto/alib.h>
4 #include <exec/types.h>
5 #include <exec/lists.h>
6 #include <aros/asmcall.h>
7 #include <utility/hooks.h>
8 #include <libraries/mui.h>
10 #include <proto/exec.h>
11 #include <proto/intuition.h>
12 #include <proto/muimaster.h>
13 #include <proto/dos.h>
14 #include <proto/alib.h>
16 #include <stddef.h>
17 #include <string.h>
19 #include "etask.h"
20 #include "fontlist_class.h"
21 #include "globals.h"
23 struct FontListData
25 struct MinList ScanDirTasks;
27 typedef struct FontListData FontListData;
29 struct ScanDirTaskInfo
31 struct MinNode Node;
32 struct Process *Proc;
33 STRPTR DirName;
34 char NameBuf[256];
35 char Buffer[4096];
39 AROS_UFH3(APTR, flConstructFunc,
40 AROS_UFHA(struct Hook *, hook, A0),
41 AROS_UFHA(APTR, pool, A2),
42 AROS_UFHA(struct MUIS_FontList_Entry *, entry, A1))
44 AROS_USERFUNC_INIT
46 struct MUIS_FontList_Entry *new_entry;
47 size_t len1 = strlen(entry->FileName) + 1;
48 size_t len2 = strlen(entry->FamilyName) + 1;
49 size_t len3 = strlen(entry->StyleName) + 1;
51 new_entry = AllocPooled(pool, sizeof(*entry) + len1 + len2 + len3);
52 if (new_entry)
54 STRPTR p = (STRPTR)(new_entry + 1);
55 new_entry->FileName = p;
56 memcpy(p, entry->FileName, len1);
57 p += len1;
58 new_entry->FamilyName = p;
59 memcpy(p, entry->FamilyName, len2);
60 p += len2;
61 new_entry->StyleName = p;
62 memcpy(p, entry->StyleName, len3);
65 return new_entry;
67 AROS_USERFUNC_EXIT
71 struct Hook flConstructHook = {{NULL, NULL}, UFHN(flConstructFunc) };
73 AROS_UFH3(void, flDestructFunc,
74 AROS_UFHA(struct Hook *, hook, A0),
75 AROS_UFHA(APTR, pool, A2),
76 AROS_UFHA(struct MUIS_FontList_Entry *, entry, A1))
78 AROS_USERFUNC_INIT
80 size_t len1 = strlen(entry->FileName) + 1;
81 size_t len2 = strlen(entry->FamilyName) + 1;
82 size_t len3 = strlen(entry->StyleName) + 1;
84 FreePooled(pool, entry, sizeof(*entry) + len1 + len2 + len3);
86 AROS_USERFUNC_EXIT
90 struct Hook flDestructHook = {{NULL, NULL}, UFHN(flDestructFunc) };
92 AROS_UFH3(ULONG, flDisplayFunc,
93 AROS_UFHA(struct Hook *, hook, A0),
94 AROS_UFHA(STRPTR *, array, A2),
95 AROS_UFHA(struct MUIS_FontList_Entry *, entry, A1))
97 AROS_USERFUNC_INIT
99 array[0] = entry->FamilyName;
100 array[1] = entry->StyleName;
101 return 0;
103 AROS_USERFUNC_EXIT
107 struct Hook flDisplayHook = {{NULL, NULL}, UFHN(flDisplayFunc) };
109 AROS_UFH3(LONG, flCompareFunc,
110 AROS_UFHA(struct Hook *, hook, A0),
111 AROS_UFHA(struct MUIS_FontList_Entry *, entry2, A2),
112 AROS_UFHA(struct MUIS_FontList_Entry *, entry1, A1))
114 AROS_USERFUNC_INIT
116 LONG ret = strcmp(entry1->FamilyName, entry2->FamilyName);
117 if (ret == 0)
118 ret = strcmp(entry1->StyleName, entry2->StyleName);
119 return ret;
121 AROS_USERFUNC_EXIT
125 struct Hook flCompareHook = {{NULL, NULL}, UFHN(flCompareFunc) };
128 IPTR flNew(Class *cl, Object *o, struct opSet *msg)
130 struct opSet method;
131 struct TagItem tags[8];
133 tags[0].ti_Tag = MUIA_Frame;
134 tags[0].ti_Data = MUIV_Frame_InputList;
135 tags[1].ti_Tag = MUIA_Background;
136 tags[1].ti_Data = MUII_ListBack;
137 tags[2].ti_Tag = MUIA_List_ConstructHook;
138 tags[2].ti_Data = (IPTR)&flConstructHook;
139 tags[3].ti_Tag = MUIA_List_DestructHook;
140 tags[3].ti_Data = (IPTR)&flDestructHook;
141 tags[4].ti_Tag = MUIA_List_DisplayHook;
142 tags[4].ti_Data = (IPTR)&flDisplayHook;
143 tags[4].ti_Tag = MUIA_List_DisplayHook;
144 tags[4].ti_Data = (IPTR)&flDisplayHook;
145 tags[5].ti_Tag = MUIA_List_CompareHook;
146 tags[5].ti_Data = (IPTR)&flCompareHook;
147 tags[6].ti_Tag = MUIA_List_Format;
148 tags[6].ti_Data = (IPTR)",";
149 tags[7].ti_Tag = TAG_MORE;
150 tags[7].ti_Data = (IPTR)msg->ops_AttrList;
152 method.MethodID = OM_NEW;
153 method.ops_AttrList = tags;
154 method.ops_GInfo = NULL;
156 o = (Object *)DoSuperMethodA(cl, o, (Msg)&method);
157 if (o)
159 FontListData *dat = INST_DATA(cl, o);
160 NewList((struct List *) &dat->ScanDirTasks);
163 DEBUG_FONTWINDOW(dprintf("FontList: created object 0x%lx.\n", o));
165 return (IPTR)o;
169 IPTR flDispose(Class *cl, Object *o, Msg msg)
171 FontListData *dat = INST_DATA(cl, o);
172 struct ScanDirTaskInfo *info;
173 BOOL done;
177 done = TRUE;
179 Forbid();
180 for (info = (APTR)dat->ScanDirTasks.mlh_Head; info->Node.mln_Succ; info = (APTR)info->Node.mln_Succ)
182 done = FALSE;
183 Signal(&info->Proc->pr_Task, SIGBREAKF_CTRL_C);
185 Permit();
187 if (!done)
188 Wait(SIGBREAKF_CTRL_F);
190 while (!done);
192 return DoSuperMethodA(cl, o, msg);
196 struct MUIP_FontList_AddDir
198 ULONG MethodID;
199 STRPTR DirName;
202 struct ScanDirTaskInfo *_pass_info;
203 Object *_pass_app;
204 struct Task *_pass_parent;
205 Object *_pass_fl;
207 void ScanDirTask(void)
209 struct ScanDirTaskInfo *info = _pass_info;
210 Object *app = _pass_app;
211 struct Task *parent = _pass_parent;
212 Object *fl = _pass_fl;
213 BPTR lock;
214 struct ExAllControl *eac;
215 struct ExAllData *ead;
216 ULONG more;
217 BPTR olddir;
218 FT_Library ftlibrary;
220 #warning FIXME: Possible thread race conflicts not checked !!!
221 void *test = GetIntETask(parent)->iet_acpd;
222 GetIntETask(FindTask(NULL))->iet_acpd = test;
224 Signal(parent, SIGBREAKF_CTRL_F);
226 DEBUG_ADDDIR(dprintf("flScanDirTask: dir <%s>\n", info->DirName));
228 if (FT_Init_FreeType(&ftlibrary) == 0)
230 DEBUG_ADDDIR(dprintf("flScanDirTask: ftlibrary 0x%x\n", ftlibrary));
232 lock = Lock(info->DirName, ACCESS_READ);
233 if (lock)
235 DEBUG_ADDDIR(dprintf("flScanDirTask: lock 0x%lx\n", lock));
237 olddir = CurrentDir(lock);
239 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
240 if (eac)
242 DEBUG_ADDDIR(dprintf("flScanDirTask: eac 0x%lx\n", eac));
244 eac->eac_LastKey = 0;
248 more = ExAll(lock, (struct ExAllData *) info->Buffer, sizeof(info->Buffer), ED_NAME, eac);
250 DEBUG_ADDDIR(dprintf("flScanDirTask: more %d entries %d\n", more, eac->eac_Entries));
253 if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
255 DEBUG_ADDDIR(dprintf("flScanDirTask: err %d\n", IoErr()));
256 break;
259 if (eac->eac_Entries == 0)
260 continue;
262 ead = (APTR)info->Buffer;
266 FT_Face face;
267 FT_Error error;
269 DEBUG_ADDDIR(dprintf("flScanDirTask: ead 0x%x name %x <%s>\n", ead, ead->ed_Name, ead->ed_Name));
270 error = FT_New_Face(ftlibrary, ead->ed_Name, 0, &face);
271 DEBUG_ADDDIR(dprintf("flScanDirTask: error %d\n", error));
272 if (error == 0)
274 struct MUIS_FontList_Entry *entry;
275 size_t len1, len2, len3;
277 DEBUG_ADDDIR(dprintf("flScanDirTask: family 0x <%s> style 0x%x <%s>\n", face->family_name, face->family_name, face->style_name, face->style_name));
279 strncpy(info->NameBuf, info->DirName, sizeof(info->NameBuf));
280 AddPart(info->NameBuf, ead->ed_Name, sizeof(info->NameBuf));
282 len1 = strlen(info->NameBuf) + 1;
283 len2 = strlen(face->family_name) + 1;
284 len3 = strlen(face->style_name) + 1;
286 entry = AllocVec(sizeof(*entry) + len1 + len2 + len3, MEMF_PUBLIC);
287 if (entry)
289 char *p = (char *)(entry + 1);
290 entry->FileName = p;
291 memcpy(p, info->NameBuf, len1);
292 p += len1;
293 entry->FamilyName = p;
294 memcpy(p, face->family_name, len2);
295 p += len2;
296 entry->StyleName = p;
297 memcpy(p, face->style_name, len3);
299 if (!DoMethod(app, MUIM_Application_PushMethod,
300 fl, 2, MUIM_FontList_AddEntry, entry))
301 FreeVec(entry);
304 FT_Done_Face(face);
307 ead = ead->ed_Next;
309 while (ead);
311 while (more);
313 DEBUG_ADDDIR(dprintf("flScanDirTask: done\n"));
315 FreeDosObject(DOS_EXALLCONTROL, eac);
318 CurrentDir(olddir);
319 UnLock(lock);
322 FT_Done_FreeType(ftlibrary);
325 Forbid();
326 REMOVE(&info->Node);
327 FreeVec(info);
328 Signal(parent, SIGBREAKF_CTRL_F);
332 ULONG flAddDir(Class *cl, Object *o, struct MUIP_FontList_AddDir *msg)
334 FontListData *dat = INST_DATA(cl, o);
335 struct ScanDirTaskInfo *info;
336 int dirname_len = strlen(msg->DirName) + 1;
338 info = AllocVec(sizeof(*info) + dirname_len, MEMF_CLEAR | MEMF_PUBLIC);
339 if (info)
341 info->DirName = (STRPTR)(info + 1);
342 memcpy(info->DirName, msg->DirName, dirname_len);
344 _pass_info = info;
345 _pass_app = _app(o);
346 _pass_parent = FindTask(NULL);
347 _pass_fl = o;
348 Forbid();
349 info->Proc = CreateNewProcTags(
350 NP_Entry, ScanDirTask,
351 TAG_END);
352 if (info->Proc)
354 ADDTAIL((APTR)&dat->ScanDirTasks, (APTR)info);
355 Permit();
357 Wait(SIGBREAKF_CTRL_F);
358 return TRUE;
361 Permit();
362 FreeVec(info);
365 return FALSE;
369 struct MUIP_FontList_AddEntry
371 ULONG MethodID;
372 struct MUIS_FontList_Entry *Entry;
375 ULONG flAddEntry(Class *cl, Object *o, struct MUIP_FontList_AddEntry *msg)
377 DoMethod(o, MUIM_List_InsertSingle, msg->Entry, MUIV_List_Insert_Sorted);
378 FreeVec(msg->Entry);
379 return TRUE;
383 AROS_UFH3(ULONG, FontListDispatch,
384 AROS_UFHA(Class *, cl, A0),
385 AROS_UFHA(Object *, o, A2),
386 AROS_UFHA(Msg, msg, A1))
388 AROS_USERFUNC_INIT
390 ULONG ret;
392 switch (msg->MethodID)
394 case OM_NEW:
395 ret = flNew(cl, o, (struct opSet *)msg);
396 break;
398 case OM_DISPOSE:
399 ret = flDispose(cl, o, msg);
400 break;
402 case MUIM_FontList_AddDir:
403 ret = flAddDir(cl, o, (struct MUIP_FontList_AddDir *)msg);
404 break;
406 case MUIM_FontList_AddEntry:
407 ret = flAddEntry(cl, o, (struct MUIP_FontList_AddEntry *)msg);
408 break;
410 default:
411 ret = DoSuperMethodA(cl, o, msg);
412 break;
415 return ret;
417 AROS_USERFUNC_EXIT
421 void CleanupFontListClass(void)
423 if (FontListClass)
425 MUI_DeleteCustomClass(FontListClass);
426 FontListClass = NULL;
430 int InitFontListClass(void)
432 FontListClass = MUI_CreateCustomClass(NULL, MUIC_List, NULL,
433 sizeof(FontListData), UFHN(FontListDispatch));
434 return FontListClass != NULL;