fix issues with string truncation and undersized buffers. (NicJA)
[AROS.git] / workbench / system / ftmanager / fontlist_class.c
blob554a763e5620a9607b5baf5a05cde25753c2212e
1 #include <aros/debug.h>
2 #include <proto/alib.h>
3 #include <exec/types.h>
4 #include <exec/lists.h>
5 #include <aros/asmcall.h>
6 #include <utility/hooks.h>
7 #include <libraries/mui.h>
9 #define NO_INLINE_STDARG
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/muimaster.h>
14 #include <proto/dos.h>
15 #include <proto/alib.h>
17 #include <stddef.h>
18 #include <string.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 STACKED ULONG MethodID;
199 STACKED 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 Signal(parent, SIGBREAKF_CTRL_F);
222 DEBUG_ADDDIR(dprintf("flScanDirTask: dir <%s>\n", info->DirName));
224 if (FT_Init_FreeType(&ftlibrary) == 0)
226 DEBUG_ADDDIR(dprintf("flScanDirTask: ftlibrary 0x%x\n", ftlibrary));
228 lock = Lock(info->DirName, ACCESS_READ);
229 if (lock)
231 DEBUG_ADDDIR(dprintf("flScanDirTask: lock 0x%lx\n", lock));
233 olddir = CurrentDir(lock);
235 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
236 if (eac)
238 DEBUG_ADDDIR(dprintf("flScanDirTask: eac 0x%lx\n", eac));
240 eac->eac_LastKey = 0;
244 more = ExAll(lock, (struct ExAllData *) info->Buffer, sizeof(info->Buffer), ED_NAME, eac);
246 DEBUG_ADDDIR(dprintf("flScanDirTask: more %d entries %d\n", more, eac->eac_Entries));
249 if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
251 DEBUG_ADDDIR(dprintf("flScanDirTask: err %d\n", IoErr()));
252 break;
255 if (eac->eac_Entries == 0)
256 continue;
258 ead = (APTR)info->Buffer;
262 FT_Face face;
263 FT_Error error;
265 DEBUG_ADDDIR(dprintf("flScanDirTask: ead 0x%x name %x <%s>\n", ead, ead->ed_Name, ead->ed_Name));
266 error = FT_New_Face(ftlibrary, ead->ed_Name, 0, &face);
267 DEBUG_ADDDIR(dprintf("flScanDirTask: error %d\n", error));
268 if (error == 0)
270 struct MUIS_FontList_Entry *entry;
271 size_t len1, len2, len3;
273 DEBUG_ADDDIR(dprintf("flScanDirTask: family 0x <%s> style 0x%x <%s>\n", face->family_name, face->family_name, face->style_name, face->style_name));
275 strncpy(info->NameBuf, info->DirName, sizeof(info->NameBuf) - 1);
276 AddPart(info->NameBuf, ead->ed_Name, sizeof(info->NameBuf));
278 len1 = strlen(info->NameBuf) + 1;
279 len2 = strlen(face->family_name) + 1;
280 len3 = strlen(face->style_name) + 1;
282 entry = AllocVec(sizeof(*entry) + len1 + len2 + len3, MEMF_PUBLIC);
283 if (entry)
285 char *p = (char *)(entry + 1);
286 entry->FileName = p;
287 memcpy(p, info->NameBuf, len1);
288 p += len1;
289 entry->FamilyName = p;
290 memcpy(p, face->family_name, len2);
291 p += len2;
292 entry->StyleName = p;
293 memcpy(p, face->style_name, len3);
295 if (!DoMethod(app, MUIM_Application_PushMethod,
296 fl, 2, MUIM_FontList_AddEntry, entry))
297 FreeVec(entry);
300 FT_Done_Face(face);
303 ead = ead->ed_Next;
305 while (ead);
307 while (more);
309 DEBUG_ADDDIR(dprintf("flScanDirTask: done\n"));
311 FreeDosObject(DOS_EXALLCONTROL, eac);
314 CurrentDir(olddir);
315 UnLock(lock);
318 FT_Done_FreeType(ftlibrary);
321 Forbid();
322 REMOVE(&info->Node);
323 FreeVec(info);
324 Signal(parent, SIGBREAKF_CTRL_F);
328 ULONG flAddDir(Class *cl, Object *o, struct MUIP_FontList_AddDir *msg)
330 FontListData *dat = INST_DATA(cl, o);
331 struct ScanDirTaskInfo *info;
332 int dirname_len = strlen(msg->DirName) + 1;
334 info = AllocVec(sizeof(*info) + dirname_len, MEMF_CLEAR | MEMF_PUBLIC);
335 if (info)
337 info->DirName = (STRPTR)(info + 1);
338 memcpy(info->DirName, msg->DirName, dirname_len);
340 _pass_info = info;
341 _pass_app = _app(o);
342 _pass_parent = FindTask(NULL);
343 _pass_fl = o;
344 Forbid();
345 info->Proc = CreateNewProcTags(
346 NP_Entry, ScanDirTask,
347 TAG_END);
348 if (info->Proc)
350 ADDTAIL((APTR)&dat->ScanDirTasks, (APTR)info);
351 Permit();
353 Wait(SIGBREAKF_CTRL_F);
354 return TRUE;
357 Permit();
358 FreeVec(info);
361 return FALSE;
365 struct MUIP_FontList_AddEntry
367 STACKED ULONG MethodID;
368 STACKED struct MUIS_FontList_Entry *Entry;
371 ULONG flAddEntry(Class *cl, Object *o, struct MUIP_FontList_AddEntry *msg)
373 DoMethod(o, MUIM_List_InsertSingle, msg->Entry, MUIV_List_Insert_Sorted);
374 FreeVec(msg->Entry);
375 return TRUE;
379 AROS_UFH3(ULONG, FontListDispatch,
380 AROS_UFHA(Class *, cl, A0),
381 AROS_UFHA(Object *, o, A2),
382 AROS_UFHA(Msg, msg, A1))
384 AROS_USERFUNC_INIT
386 ULONG ret;
388 switch (msg->MethodID)
390 case OM_NEW:
391 ret = flNew(cl, o, (struct opSet *)msg);
392 break;
394 case OM_DISPOSE:
395 ret = flDispose(cl, o, msg);
396 break;
398 case MUIM_FontList_AddDir:
399 ret = flAddDir(cl, o, (struct MUIP_FontList_AddDir *)msg);
400 break;
402 case MUIM_FontList_AddEntry:
403 ret = flAddEntry(cl, o, (struct MUIP_FontList_AddEntry *)msg);
404 break;
406 default:
407 ret = DoSuperMethodA(cl, o, msg);
408 break;
411 return ret;
413 AROS_USERFUNC_EXIT
417 void CleanupFontListClass(void)
419 if (FontListClass)
421 MUI_DeleteCustomClass(FontListClass);
422 FontListClass = NULL;
426 int InitFontListClass(void)
428 FontListClass = MUI_CreateCustomClass(NULL, MUIC_List, NULL,
429 sizeof(FontListData), UFHN(FontListDispatch));
430 return FontListClass != NULL;