revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / diskfont / diskfontfunc.c
blob11caae95da6d41b908149469e272166795c73f96
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Hook for handling fonts in FONTS:
6 Lang: English.
7 */
9 /****************************************************************************************/
11 #include <exec/initializers.h>
12 #include <dos/dosextens.h>
13 #include <proto/dos.h>
14 #include <proto/graphics.h>
15 #include <proto/arossupport.h>
16 //#include <proto/alib.h>
17 #include <string.h>
19 #include "diskfont_intern.h"
21 /****************************************************************************************/
23 #include <aros/debug.h>
25 /****************************************************************************************/
27 struct DirEntry;
29 struct FileEntry
31 struct MinNode Node;
32 struct DirEntry *DirEntry;
33 STRPTR FileName;
34 struct DateStamp FileChanged;
35 UWORD ContentsID;
36 UBYTE SupportedStyles;
37 UBYTE FontStyle;
38 ULONG Numentries;
39 struct TTextAttr *Attrs;
42 struct DirEntry
44 struct MinNode Node;
45 BPTR DirLock;
46 struct DateStamp DirChanged;
47 struct MinList FileList;
50 struct DF_FontsData /*DiskFontData */
52 #ifdef PROGDIRFONTSDIR
53 struct DirEntry *ProgdirDirEntry;
54 #endif
55 struct DirEntry *CurrentDirEntry;
56 struct FileEntry *CurrentFileEntry, *PrevFileEntry;
57 UWORD AttrsIndex;
58 struct FileEntry *RememberFileEntry;
59 UWORD RememberIndex;
62 struct DF_FileData
64 struct FontDescrHeader *FDH;
65 STRPTR FilePart;
66 STRPTR OrigName;
67 struct TTextAttr *LastAttr;
68 UWORD AttrsIndex;
69 UWORD RememberIndex;
70 struct TTextAttr ExtraAttr;
73 typedef enum {DF_FONTSDATA, DF_FILEDATA} DF_DataType;
75 struct DF_Data
77 DF_DataType Type;
78 struct TTextAttr *ReqAttr;
79 union
81 struct DF_FontsData FontsData;
82 struct DF_FileData FileData;
83 } u;
87 /****************************************************************************************/
89 /*****************/
90 /* ReadFileEntry */
91 /*****************/
93 /****************************************************************************************/
95 STATIC struct FileEntry *ReadFileEntry(struct ExAllData *ead, struct DiskfontBase *DiskfontBase)
97 struct FontDescrHeader *fdh;
98 struct FileEntry *retval = NULL;
99 ULONG size, strsize, tagcount;
100 int i;
101 struct TagItem *tagitems;
102 STRPTR filename;
104 D(bug("ReadFileEntry: ead: 0x%lx\n", ead));
105 D(bug("ReadFileEntry: name=\"%s\"\n", ead->ed_Name));
107 fdh = ReadFontDescr(ead->ed_Name, DiskfontBase);
108 if (fdh == NULL)
110 D(bug("ReadFileEntry: error in ReadFontDescr\n"));
111 return NULL;
114 strsize = (strlen(ead->ed_Name) + 1 + 1) & ~1;
115 size = sizeof(struct FileEntry) + strsize + fdh->NumEntries * sizeof(struct TTextAttr);
116 if (fdh->ContentsID == OFCH_ID) /* Reserve extra Attr for outline fonts */
117 size += sizeof(struct TTextAttr);
119 for (i = 0; i < fdh->NumEntries; i++)
120 if (fdh->TAttrArray[i].tta_Tags != NULL)
121 size += NumTags(fdh->TAttrArray[i].tta_Tags, DiskfontBase) * sizeof(struct TagItem);
123 retval = AllocVec(size, MEMF_ANY|MEMF_CLEAR);
124 if (retval == NULL)
126 D(bug("ReadFileEntry: Could not allocate memory\n"));
127 FreeFontDescr(fdh, DiskfontBase);
128 ReturnPtr("ReadFileEntry", struct FileEntry *, NULL);
131 filename = (STRPTR)(retval + 1);
132 strcpy(filename, ead->ed_Name);
133 retval->FileName = filename;
134 retval->FileChanged = *(struct DateStamp *)&ead->ed_Days;
136 retval->Numentries = fdh->NumEntries;
137 retval->ContentsID = fdh->ContentsID;
138 retval->Attrs = (struct TTextAttr *)(filename + strsize);
139 memcpy(retval->Attrs, fdh->TAttrArray, fdh->NumEntries * sizeof(struct TTextAttr));
140 if (retval->ContentsID == OFCH_ID)
142 int ind = retval->Numentries;
144 retval->Numentries++;
145 retval->SupportedStyles = OTAG_GetSupportedStyles(fdh->OTagList, DiskfontBase);
146 retval->FontStyle = OTAG_GetFontStyle(fdh->OTagList, DiskfontBase);
147 retval->Attrs[ind].tta_Name = filename;
148 retval->Attrs[ind].tta_Flags = OTAG_GetFontFlags(fdh->OTagList, DiskfontBase);
151 tagitems = (struct TagItem *)(retval->Attrs + retval->Numentries);
153 for (i = 0; i < fdh->NumEntries; i++)
155 retval->Attrs[i].tta_Name = retval->FileName;
157 if (fdh->TAttrArray[i].tta_Tags != NULL)
159 tagcount = NumTags(fdh->TAttrArray[i].tta_Tags, DiskfontBase);
160 CopyTagItems(tagitems, fdh->TAttrArray[i].tta_Tags, DiskfontBase);
161 retval->Attrs[i].tta_Tags = tagitems;
162 tagitems += tagcount;
164 else
165 retval->Attrs[i].tta_Tags = NULL;
168 FreeFontDescr(fdh, DiskfontBase);
170 ReturnPtr("ReadFileEntry", struct FileEntry *, retval);
173 /****************************************************************************************/
175 /*****************/
176 /* FreeFileEntry */
177 /*****************/
179 /****************************************************************************************/
181 STATIC VOID FreeFileEntry(struct FileEntry *feptr, struct DiskfontBase *DiskfontBase)
183 FreeVec(feptr);
186 /****************************************************************************************/
188 /****************/
189 /* FreeFileList */
190 /****************/
192 /****************************************************************************************/
194 STATIC VOID FreeFileList(struct MinList *filelist, struct DiskfontBase *DiskfontBase)
196 struct FileEntry *feptr, *nextfeptr;
198 D(bug("FreeFileList(filelist=%p)\n", filelist));
200 ForeachNodeSafe(filelist, feptr, nextfeptr)
202 REMOVE(feptr);
203 FreeFileEntry(feptr, DiskfontBase);
206 ReturnVoid("FreeFileList");
209 /****************************************************************************************/
211 /****************/
212 /* GetFileList */
213 /****************/
215 /****************************************************************************************/
217 /* Build the list of .font file names using Examine() */
218 STATIC BOOL GetFileList(struct DirEntry *direntry, struct DiskfontBase *DiskfontBase)
220 struct MinList newlist;
221 struct FileEntry *fe, *nextfe;
222 BOOL retval = TRUE, more;
223 struct ExAllControl *eac;
224 struct ExAllData *ead, *eadit;
226 D(bug("GetFileList(direntry=%p)\n", direntry));
228 NEWLIST(&newlist);
230 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
231 eac->eac_LastKey = 0;
232 ead = (struct ExAllData *)AllocMem(1024, MEMF_ANY);
236 more = ExAll(direntry->DirLock, ead, 1024, ED_DATE, eac);
237 if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES))
238 retval = FALSE;
239 else if (eac->eac_Entries == 0)
240 continue;
241 else
243 for (eadit = ead; eadit != NULL; eadit = eadit->ed_Next)
245 ULONG namelen = strlen(eadit->ed_Name);
247 D(bug("GetFileList: Scanning file: %s\n", eadit->ed_Name));
249 /* Maybe this can be done in a hook function passed in eac */
250 if (namelen < 5 || strncmp(eadit->ed_Name+namelen-5, ".font", 5) != 0)
252 D(bug("GetFileList: wrong suffix: %s\n", eadit->ed_Name+namelen-5));
253 continue;
256 /* Is a FileEntry for this file already in the list */
257 for (fe = (struct FileEntry *)GetHead(&direntry->FileList);
258 fe != NULL;
259 fe = (struct FileEntry *)GetSucc(fe))
261 if (strcmp(eadit->ed_Name, fe->FileName) == 0)
262 break;
265 if (fe == NULL)
267 D(bug("GetFileList: Filename not yet in memory\n"));
269 fe = ReadFileEntry(eadit, DiskfontBase);
270 if (fe != NULL)
272 fe->DirEntry = direntry;
274 D(bug("GetFileList: Add to list: 0x%lx\n", fe));
275 ADDTAIL(&newlist, fe);
278 else
280 struct DateStamp ds;
281 REMOVE(fe);
283 ds.ds_Days = eadit->ed_Days;
284 ds.ds_Minute = eadit->ed_Mins;
285 ds.ds_Tick = eadit->ed_Ticks;
287 D(bug("GetFileList: Found filename already in memory\n"));
289 if (CompareDates(&ds, &fe->FileChanged) == 0)
291 D(bug("GetFileList: File's date not changed: Add to list 0x%lx\n", fe));
292 ADDTAIL(&newlist, fe);
294 else
296 D(bug("GetFileList: Date changed rereading information\n"));
298 FreeFileEntry(fe, DiskfontBase);
300 fe = ReadFileEntry(eadit, DiskfontBase);
301 if (fe == NULL)
303 D(bug("GetFileList: Reading information failed\n"));
304 retval = FALSE;
305 break;
307 else
309 fe->DirEntry = direntry;
310 D(bug("GetFileList: Reading OK, add to list: 0x%lx\n", fe));
311 ADDTAIL(&newlist, fe);
315 } /* for (eadit = ... */
317 } while (more && retval);
319 FreeDosObject(DOS_EXALLCONTROL, eac);
320 FreeMem(ead, 1024);
322 if (!retval)
324 D(bug("GetFileList: Not OK freeing FileList\n"));
325 FreeFileList(&newlist, DiskfontBase);
327 else
329 /* Remove FileEntries that are still in memory but not anymore
330 * on disk */
331 FreeFileList(&direntry->FileList, DiskfontBase);
333 ForeachNodeSafe(&newlist, fe, nextfe)
335 REMOVE(fe);
336 ADDTAIL(&direntry->FileList, fe);
337 D(bug("GetFileList: Adding fe=%p\n", fe));
341 ReturnBool ("GetFileList", retval);
344 /****************************************************************************************/
346 /*********************/
347 /* StreamOutFileList */
348 /*********************/
350 /****************************************************************************************/
352 STATIC BOOL StreamOutFileList(struct MinList *filelist, BPTR fh, struct DiskfontBase *DiskfontBase)
354 struct FileEntry *fe;
355 ULONG i;
356 BOOL ok = TRUE;
358 ForeachNode(filelist, fe)
360 D(bug("StreamOutFileList: Writing file %s\n", fe->FileName));
361 ok = ok && WriteString(&DiskfontBase->dsh, fe->FileName, (APTR)fh);
362 D(bug("StreamOutFileList: Write days: %d minute: %d, tick: %d\n",
363 fe->FileChanged.ds_Days, fe->FileChanged.ds_Minute,
364 fe->FileChanged.ds_Tick));
365 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Days, (APTR)fh);
366 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Minute, (APTR)fh);
367 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Tick, (APTR)fh);
368 ok = ok && WriteWord(&DiskfontBase->dsh, fe->ContentsID, (APTR)fh);
369 ok = ok && WriteByte(&DiskfontBase->dsh, fe->SupportedStyles, (APTR)fh);
370 ok = ok && WriteByte(&DiskfontBase->dsh, fe->FontStyle, (APTR)fh);
371 D(bug("StreamOutFileList: Write numentries=%d\n", fe->Numentries));
372 ok = ok && WriteLong(&DiskfontBase->dsh, fe->Numentries, (APTR)fh);
374 for (i=0; ok && i<fe->Numentries; i++)
376 ok = ok && WriteWord(&DiskfontBase->dsh, fe->Attrs[i].tta_YSize, (APTR)fh);
377 ok = ok && WriteByte(&DiskfontBase->dsh, fe->Attrs[i].tta_Style, (APTR)fh);
378 ok = ok && WriteByte(&DiskfontBase->dsh, fe->Attrs[i].tta_Flags, (APTR)fh);
379 ok = ok && WriteTagsNum(fh, fe->Attrs[i].tta_Tags, DiskfontBase);
382 ok = ok && WriteString(&DiskfontBase->dsh, "", (APTR)fh);
384 return ok;
387 /****************************************************************************************/
389 /********************/
390 /* StreamInFileList */
391 /********************/
393 /****************************************************************************************/
395 STATIC BOOL StreamInFileList(struct DirEntry *direntry, BPTR fh, struct DiskfontBase *DiskfontBase)
397 struct FileEntry *fe, fe2;
398 ULONG i, numtags, totnumtags;
399 BOOL ok = TRUE;
400 struct TTextAttr *attrs;
401 struct TagItem *tagptr;
403 for (ok = ReadString(&DiskfontBase->dsh, &fe2.FileName, (APTR)fh);
404 ok && strlen(fe2.FileName)>0;
405 ok = ok && ReadString(&DiskfontBase->dsh, &fe2.FileName, (APTR)fh))
407 D(bug("StreamInFileList: reading data for \"%s\"\n", fe2.FileName));
409 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Days, (APTR)fh);
410 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Minute, (APTR)fh);
411 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Tick, (APTR)fh);
412 D(bug("StreamInFileList: read days: %d minute: %d tick: %d\n",
413 fe2.FileChanged.ds_Days, fe2.FileChanged.ds_Minute,
414 fe2.FileChanged.ds_Tick));
415 ok = ok && ReadWord(&DiskfontBase->dsh, &fe2.ContentsID, (APTR)fh);
416 ok = ok && ReadByte(&DiskfontBase->dsh, &fe2.SupportedStyles, (APTR)fh);
417 ok = ok && ReadByte(&DiskfontBase->dsh, &fe2.FontStyle, (APTR)fh);
418 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.Numentries, (APTR)fh);
420 if (ok)
422 int namelen = (strlen(fe2.FileName) + 1 + 1) & ~1;
423 attrs = AllocVec(fe2.Numentries * sizeof(struct TTextAttr), MEMF_ANY|MEMF_CLEAR);
425 ok = ok && attrs != NULL;
427 if (ok)
428 for (i = 0; i < fe2.Numentries; i++)
429 attrs[i].tta_Tags = NULL;
431 for (i = 0, totnumtags = 0; ok && i < fe2.Numentries; i++)
433 ok = ok && ReadWord(&DiskfontBase->dsh, &attrs[i].tta_YSize, (APTR)fh);
434 ok = ok && ReadByte(&DiskfontBase->dsh, &attrs[i].tta_Style, (APTR)fh);
435 ok = ok && ReadByte(&DiskfontBase->dsh, &attrs[i].tta_Flags, (APTR)fh);
436 if (ok)
438 attrs[i].tta_Tags = ReadTagsNum(fh, &numtags, DiskfontBase);
439 D(bug("StreamInFileList: read tags %p\n", attrs[i].tta_Tags));
440 totnumtags += numtags;
441 ok = ok && numtags > 0;
444 D(bug("StreamInFileList: totnumtags == %u\n", totnumtags));
446 if (ok)
448 ULONG size = sizeof(struct FileEntry) +
449 namelen +
450 fe2.Numentries * sizeof(struct TTextAttr) +
451 totnumtags * sizeof(struct TagItem);
453 fe = (struct FileEntry *)AllocVec(size, MEMF_ANY);
454 ok = ok && fe != NULL;
456 if (ok)
458 fe->DirEntry = direntry;
459 fe->FileName = (STRPTR)(fe+1);
460 strcpy(fe->FileName, fe2.FileName);
461 fe->FileChanged = fe2.FileChanged;
462 fe->ContentsID = fe2.ContentsID;
463 fe->SupportedStyles = fe2.SupportedStyles;
464 fe->FontStyle = fe2.FontStyle;
465 fe->Numentries = fe2.Numentries;
466 fe->Attrs = (struct TTextAttr *)(fe->FileName + namelen);
468 tagptr = (struct TagItem *)(fe->Attrs + fe2.Numentries);
469 for (i = 0; i < fe2.Numentries; i++)
471 fe->Attrs[i].tta_Name = fe->FileName;
472 fe->Attrs[i].tta_YSize = attrs[i].tta_YSize;
473 fe->Attrs[i].tta_Style = attrs[i].tta_Style;
474 fe->Attrs[i].tta_Flags = attrs[i].tta_Flags;
475 numtags = CopyTagItems(tagptr, attrs[i].tta_Tags, DiskfontBase);
476 fe->Attrs[i].tta_Tags = tagptr;
477 tagptr += numtags;
479 ADDTAIL(&direntry->FileList, fe);
482 if (attrs != NULL)
484 for (i = 0; i < fe2.Numentries; i++)
485 if (attrs[i].tta_Tags != NULL)
487 D(bug("StreamInFileList: freeing tags %p\n", attrs[i].tta_Tags));
488 FreeVec(attrs[i].tta_Tags);
490 FreeVec(attrs);
494 FreeVec(fe2.FileName);
496 if (ok)
498 D(bug("StreamInFileList: FileName empty\n"));
499 FreeVec(fe2.FileName);
501 else
503 D(bug("StreamInFileList: Error reading chachefile\n"));
504 FreeFileList(&direntry->FileList, DiskfontBase);
507 return ok;
510 /****************************************************************************************/
512 /****************/
513 /* FreeDirEntry */
514 /****************/
516 /****************************************************************************************/
518 STATIC VOID FreeDirEntry(struct DirEntry *direntry, struct DiskfontBase *DiskfontBase)
520 if (direntry!=NULL)
522 FreeFileList(&direntry->FileList, DiskfontBase);
523 UnLock(direntry->DirLock);
524 FreeVec(direntry);
528 /****************************************************************************************/
530 /****************/
531 /* ReadDirEntry */
532 /****************/
534 /****************************************************************************************/
536 STATIC struct DirEntry *ReadDirEntry(BPTR dirlock, struct DirEntry *direntry, struct DiskfontBase *DiskfontBase)
538 struct Process *Self;
539 APTR oldwinptr;
540 struct FileInfoBlock *fib;
541 BPTR olddir;
542 BPTR fh;
544 D(bug("ReadDirEntry(dirlock=0x%lx, direntry=0x%lx)\n", dirlock, direntry));
546 Self = (struct Process *) FindTask(NULL);
547 oldwinptr = Self->pr_WindowPtr;
548 Self->pr_WindowPtr = (APTR) -1;
550 fib = AllocDosObject(DOS_FIB, NULL);
551 if (fib == NULL)
553 D(bug("ReadDirEntry: Could not allocate DosObject\n"));
554 Self->pr_WindowPtr = oldwinptr;
555 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
557 Examine(dirlock, fib);
558 Self->pr_WindowPtr = oldwinptr;
560 olddir = CurrentDir(dirlock);
562 if (direntry == NULL)
564 direntry = AllocVec(sizeof(struct DirEntry), MEMF_ANY | MEMF_CLEAR);
565 if (direntry==NULL)
567 D(bug("ReadDirEntry: Could not allocate DirEntry\n"));
568 FreeDosObject(DOS_FIB, fib);
569 CurrentDir(olddir);
570 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
572 else
573 D(bug("ReadDirEntry: allocated direntry = 0x%lx\n", direntry));
575 direntry->DirLock = dirlock;
576 NEWLIST(&direntry->FileList);
578 /* Try to read the direntry from the file */
579 fh = Open(CACHE_FILE, MODE_OLDFILE);
580 if (fh != BNULL)
582 BOOL ok;
584 ok = ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Days, (APTR)fh);
585 ok = ok && ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Minute, (APTR)fh);
586 ok = ok && ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Tick, (APTR)fh);
588 if (ok)
589 ok = StreamInFileList(direntry, fh, DiskfontBase);
591 Close(fh);
593 /* TODO: */
594 #if 0
595 /* This part is disabled because in emul_handler on UNIX the date
596 * of a parent directory is changed only when a file is added or
597 * removed from the directory
600 /* If dates are the same return the direntry as is */
601 if (ok && CompareDates(&direntry->DirChanged, &fib->fib_Date) == 0)
603 D(bug("ReadDirEntry: date in cache not changed\n"));
604 FreeDosObject(DOS_FIB, fib);
605 Self->pr_WindowPtr = oldwinptr;
606 CurrentDir(olddir);
607 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
609 #endif
612 else
614 CurrentDir(direntry->DirLock);
615 UnLock(dirlock);
616 if (CompareDates(&direntry->DirChanged, &fib->fib_Date) == 0)
618 D(bug("ReadDirEntry: direntry 0x%lx not changed\n", direntry));
619 FreeDosObject(DOS_FIB, fib);
620 Self->pr_WindowPtr = oldwinptr;
621 CurrentDir(olddir);
622 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
626 direntry->DirChanged = fib->fib_Date;
628 if (!GetFileList(direntry, DiskfontBase))
630 D(bug("ReadDirEntry: Error reading FileList\n"));
631 FreeDosObject(DOS_FIB, fib);
632 CurrentDir(olddir);
633 UnLock(direntry->DirLock);
634 FreeVec(direntry);
635 Self->pr_WindowPtr = oldwinptr;
636 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
639 /* If everything went OK Write the cache file */
640 fh = Open(CACHE_FILE, MODE_NEWFILE);
641 if (fh != BNULL)
643 BOOL ok;
645 ok = WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Days, (APTR)fh);
646 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Minute, (APTR)fh);
647 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Tick, (APTR)fh);
649 if (ok)
650 ok = StreamOutFileList(&direntry->FileList, fh, DiskfontBase);
652 Close(fh);
654 if (ok)
656 Examine(direntry->DirLock, fib);
657 direntry->DirChanged = fib->fib_Date;
658 fh = Open(CACHE_FILE, MODE_OLDFILE);
659 if (fh != BNULL)
661 Seek(fh, 0, OFFSET_BEGINNING);
662 ok = WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Days, (APTR)fh);
663 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Minute, (APTR)fh);
664 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Tick, (APTR)fh);
665 Close(fh);
669 if (!ok)
670 DeleteFile(CACHE_FILE);
673 FreeDosObject(DOS_FIB, fib);
674 CurrentDir(olddir);
675 Self->pr_WindowPtr = oldwinptr;
677 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
680 /****************************************************************************************/
682 /****************/
683 /* FreeResouces */
684 /****************/
686 /****************************************************************************************/
688 STATIC VOID FreeResources(struct DF_Data *df_data, struct DiskfontBase *DiskfontBase)
690 D(bug("FreeResources(df_data=%p)\n", df_data));
692 ReleaseSemaphore(&DiskfontBase->fontssemaphore);
694 switch (df_data->Type)
696 case DF_FONTSDATA:
697 #ifdef PROGDIRFONTSDIR
698 FreeDirEntry(df_data->u.FontsData.ProgdirDirEntry, DiskfontBase);
699 #endif
700 break;
702 case DF_FILEDATA:
703 if (df_data->u.FileData.FDH != NULL)
704 FreeFontDescr(df_data->u.FileData.FDH, DiskfontBase);
705 break;
708 FreeMem(df_data, sizeof (struct DF_Data));
710 ReturnVoid("FreeResources");
713 /****************************************************************************************/
715 /****************************/
716 /* CleanUpFontsDirEntryList */
717 /****************************/
719 /****************************************************************************************/
721 VOID CleanUpFontsDirEntryList(struct DiskfontBase *DiskfontBase)
723 struct DirEntry *direntry, *direntry2;
725 ForeachNodeSafe(&DiskfontBase->fontsdirentrylist, direntry, direntry2)
726 FreeDirEntry(direntry, DiskfontBase);
728 ReturnVoid("CleanUpFontsDirEntryList");
731 /****************************************************************************************/
733 /******************/
734 /* AllocResources */
735 /******************/
737 /****************************************************************************************/
739 STATIC struct DF_Data *AllocResources(struct TTextAttr *reqattr, struct DiskfontBase *DiskfontBase)
741 struct DF_Data *df_data;
743 D(bug("AllocResources(void)\n"));
745 ObtainSemaphore(&DiskfontBase->fontssemaphore);
747 /* Allocate user data */
748 if ((df_data = AllocMem( sizeof (struct DF_Data), MEMF_ANY | MEMF_CLEAR)))
750 df_data->ReqAttr = reqattr;
752 if (reqattr==NULL || FilePart(reqattr->tta_Name)==reqattr->tta_Name)
754 struct DevProc *dp = NULL;
755 struct MinList newdirlist;
756 struct DirEntry *direntry, *direntry2;
758 df_data->Type = DF_FONTSDATA;
760 #ifdef PROGDIRFONTSDIR
763 struct Process *Self;
764 APTR oldwinptr;
765 BPTR lock;
767 df_data->u.FontsData.ProgdirDirEntry = NULL;
769 if (!GetProgramDir())
770 break;
772 Self = (struct Process *) FindTask(NULL);
773 oldwinptr = Self->pr_WindowPtr;
774 Self->pr_WindowPtr = (APTR) -1;
775 lock = Lock(PROGDIRFONTSDIR, ACCESS_READ);
776 Self->pr_WindowPtr = oldwinptr;
778 D(bug("AllocResources: PROGDIR:Fonts DirLock = 0x%lx\n", lock));
780 if (!lock)
781 break;
783 df_data->u.FontsData.ProgdirDirEntry = ReadDirEntry(lock, NULL, DiskfontBase);
784 D(bug("AllocResources: PROGDIR:Fonts direntry 0x%lx\n", df_data->u.FontsData.ProgdirDirEntry));
785 } while (0);
786 #endif
788 NEWLIST(&newdirlist);
789 while((dp = GetDeviceProc(FONTSDIR, dp))!=NULL)
791 BPTR lock;
793 D(bug("AllocResources: FONTS: lock = 0x%lx\n", dp->dvp_Lock));
795 lock = DupLock(dp->dvp_Lock);
796 if (lock==BNULL)
798 D(bug("AllocResources: Could not duplicate lock\n"));
799 continue;
802 /* See if direntry is already in memory */
803 for (direntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
804 direntry != NULL;
805 direntry = (struct DirEntry *)GetSucc(direntry))
807 if (SameLock(direntry->DirLock, lock) == LOCK_SAME)
809 REMOVE(direntry);
810 break;
814 /* Read or update fonts information in this directory */
815 direntry = ReadDirEntry(lock, direntry, DiskfontBase);
816 if (direntry!=NULL)
818 D(bug("AllocResources: addtail direntry 0x%lx\n", direntry));
819 D(bug("AllocResources: first FileEntry: %p\n", GetHead(&direntry->FileList)));
820 ADDTAIL(&newdirlist, direntry);
822 else
823 D(bug("AllocResources: Error reading DirEntry\n"));
826 /* Clean up directory lists that are in memory but not in the
827 * FONTS: assign anymore */
828 ForeachNodeSafe(&DiskfontBase->fontsdirentrylist, direntry, direntry2)
830 REMOVE(direntry);
831 FreeDirEntry(direntry, DiskfontBase);
834 ForeachNodeSafe(&newdirlist, direntry, direntry2)
836 REMOVE(direntry);
837 ADDTAIL(&DiskfontBase->fontsdirentrylist, direntry);
840 FreeDeviceProc(dp);
842 else
844 struct FontDescrHeader *fdh;
846 df_data->Type = DF_FILEDATA;
847 fdh = ReadFontDescr(reqattr->tta_Name, DiskfontBase);
848 df_data->u.FileData.FDH = fdh;
850 if (fdh != NULL)
852 if (fdh->ContentsID==OFCH_ID)
854 UBYTE SupportedStyles = OTAG_GetSupportedStyles(fdh->OTagList, DiskfontBase);
856 df_data->u.FileData.ExtraAttr.tta_Name = reqattr->tta_Name;
857 df_data->u.FileData.ExtraAttr.tta_YSize = reqattr->tta_YSize;
858 df_data->u.FileData.ExtraAttr.tta_Style = OTAG_GetFontStyle(fdh->OTagList, DiskfontBase);
859 df_data->u.FileData.ExtraAttr.tta_Flags = OTAG_GetFontFlags(fdh->OTagList, DiskfontBase);
861 df_data->u.FileData.ExtraAttr.tta_Tags = NULL;
862 if (reqattr->tta_Style & FSF_TAGGED)
864 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_TAGGED;
865 df_data->u.FileData.ExtraAttr.tta_Tags = reqattr->tta_Tags;
868 if ((reqattr->tta_Style & FSF_BOLD)
869 && !(df_data->u.FileData.ExtraAttr.tta_Style & FSF_BOLD)
870 && (SupportedStyles & FSF_BOLD))
872 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_BOLD;
875 if ((reqattr->tta_Style & FSF_ITALIC)
876 && !(df_data->u.FileData.ExtraAttr.tta_Style & FSF_ITALIC)
877 && (SupportedStyles & FSF_ITALIC))
879 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_ITALIC;
886 ReturnPtr("AllocResources", struct DF_Data *, df_data);
889 /****************************************************************************************/
891 /*******************/
892 /* DF_IteratorInit */
893 /*******************/
895 /****************************************************************************************/
897 APTR DF_IteratorInit(struct TTextAttr *reqattr, struct DiskfontBase *DiskfontBase)
899 struct DF_Data *df_data;
901 D(bug("DF_IteratorInit(reqattr=0x%lx)\n", reqattr));
903 df_data = AllocResources(reqattr, DiskfontBase);
904 if (df_data == NULL)
906 D(bug("DF_IteratorInit: Error executing Allocresources\n"));
907 ReturnPtr("DF_IteratorInit", APTR, NULL);
910 switch (df_data->Type)
912 case DF_FONTSDATA:
913 df_data->u.FontsData.CurrentDirEntry = NULL;
914 df_data->u.FontsData.CurrentFileEntry = NULL;
916 #ifdef PROGDIRFONTSDIR
917 if (df_data->u.FontsData.ProgdirDirEntry != NULL)
919 D(bug("DF_IteratorInit: ProgdirDirEntry found\n"));
920 df_data->u.FontsData.CurrentDirEntry = df_data->u.FontsData.ProgdirDirEntry;
921 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.ProgdirDirEntry->FileList);
923 else
924 D(bug("DF_IteratorInit: No ProgdirEntry found\n"));
925 #endif
926 if (df_data->u.FontsData.CurrentDirEntry == NULL || df_data->u.FontsData.CurrentFileEntry == NULL)
928 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
929 if (df_data->u.FontsData.CurrentDirEntry != NULL)
930 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
933 D(bug("DF_IteratorInit: CurrentDirEntry: %p CurrentFileEntry: %p\n",
934 df_data->u.FontsData.CurrentDirEntry, df_data->u.FontsData.CurrentFileEntry));
936 /* If DirEntry was empty search for one that is not empty */
937 while (df_data->u.FontsData.CurrentDirEntry != NULL && df_data->u.FontsData.CurrentFileEntry == NULL)
939 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
940 if (df_data->u.FontsData.CurrentDirEntry != NULL)
941 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
943 D(bug("DF_IteratorInit: CurrentDirEntry: %p CurrentFileEntry: %p\n",
944 df_data->u.FontsData.CurrentDirEntry, df_data->u.FontsData.CurrentFileEntry));
946 df_data->u.FontsData.AttrsIndex = 0;
948 break;
950 case DF_FILEDATA:
951 df_data->u.FileData.AttrsIndex = 0;
952 df_data->u.FileData.FilePart = FilePart(df_data->ReqAttr->tta_Name);
953 df_data->u.FileData.LastAttr = NULL;
954 break;
957 ReturnPtr("DF_IteratorInit", APTR, df_data);
960 /****************************************************************************************/
962 /**********************/
963 /* DF_IteratorGetNext */
964 /**********************/
966 /****************************************************************************************/
968 struct TTextAttr *DF_IteratorGetNext(APTR iterator, struct DiskfontBase *DiskfontBase)
970 struct TTextAttr *retval = NULL;
971 struct DF_Data *df_data = (struct DF_Data *)iterator;
973 D(bug("DF_IteratorGetNext(iterator=0x%lx)\n", iterator));
975 if (df_data==NULL)
976 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
978 switch (df_data->Type)
980 case DF_FONTSDATA:
981 if (df_data->u.FontsData.CurrentDirEntry==NULL)
982 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
984 retval = df_data->u.FontsData.CurrentFileEntry->Attrs + df_data->u.FontsData.AttrsIndex;
985 D(bug("DF_IteratorGetNext:\n"
986 " ContentsID: 0x%x == 0x%x\n"
987 " ReqAttr: %p\n"
988 " AttrIndex: %d, Numentries: %d\n",
989 df_data->u.FontsData.CurrentFileEntry->ContentsID, OFCH_ID,
990 df_data->ReqAttr,
991 df_data->u.FontsData.AttrsIndex, df_data->u.FontsData.CurrentFileEntry->Numentries));
993 if (df_data->u.FontsData.CurrentFileEntry->ContentsID == OFCH_ID
994 && df_data->ReqAttr != NULL
995 && df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-1)
997 D(bug("DF_IteratorGetNext: Setting last outline element\n"));
999 /* The last attr for a outline font is filled with values matching
1000 * as close as possible the reqattr */
1001 retval->tta_YSize = df_data->ReqAttr->tta_YSize;
1002 retval->tta_Style = df_data->u.FontsData.CurrentFileEntry->FontStyle;
1004 retval->tta_Tags = NULL;
1006 if (df_data->ReqAttr->tta_Style & FSF_TAGGED)
1008 retval->tta_Style |= FSF_TAGGED;
1009 retval->tta_Tags = df_data->ReqAttr->tta_Tags;
1012 if ((df_data->ReqAttr->tta_Style & FSF_BOLD)
1013 && !(retval->tta_Style & FSF_BOLD)
1014 && (df_data->u.FontsData.CurrentFileEntry->SupportedStyles & FSF_BOLD))
1016 retval->tta_Style |= FSF_BOLD;
1019 if ((df_data->ReqAttr->tta_Style & FSF_ITALIC)
1020 && !(retval->tta_Style & FSF_ITALIC)
1021 && (df_data->u.FontsData.CurrentFileEntry->SupportedStyles & FSF_ITALIC))
1023 retval->tta_Style |= FSF_ITALIC;
1027 /* Let the iterator point to the next attr */
1028 if ((df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-1)
1029 || (df_data->u.FontsData.CurrentFileEntry->ContentsID == OFCH_ID
1030 && df_data->ReqAttr==NULL &&
1031 df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-2
1035 df_data->u.FontsData.PrevFileEntry = df_data->u.FontsData.CurrentFileEntry;
1036 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetSucc(df_data->u.FontsData.CurrentFileEntry);
1037 df_data->u.FontsData.AttrsIndex = 0;
1038 if (df_data->u.FontsData.CurrentFileEntry == NULL)
1040 while (df_data->u.FontsData.CurrentDirEntry != NULL && df_data->u.FontsData.CurrentFileEntry == NULL)
1042 #ifdef PROGDIRFONTSDIR
1043 if (df_data->u.FontsData.CurrentDirEntry == df_data->u.FontsData.ProgdirDirEntry)
1044 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
1045 else
1046 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
1047 #else
1048 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
1049 #endif
1050 if (df_data->u.FontsData.CurrentDirEntry != NULL)
1051 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
1056 else
1057 df_data->u.FontsData.AttrsIndex++;
1058 break;
1060 case DF_FILEDATA:
1061 if (df_data->u.FileData.LastAttr != NULL)
1063 df_data->u.FileData.LastAttr->tta_Name = df_data->u.FileData.OrigName;
1064 df_data->u.FileData.LastAttr = NULL;
1067 /* Do not return the best-match attribute if it is not an outline font! */
1069 if (df_data->u.FileData.FDH==NULL
1070 || df_data->u.FileData.AttrsIndex > df_data->u.FileData.FDH->NumEntries
1071 || (df_data->u.FileData.FDH->ContentsID != OFCH_ID &&
1072 df_data->u.FileData.AttrsIndex == df_data->u.FileData.FDH->NumEntries))
1074 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
1076 /* Get the TextAttr the iterator is pointing to
1077 * If it points to the element after the last element return
1078 * the Extra Attr that matches the outline font as close as possible
1080 if (df_data->u.FileData.AttrsIndex == df_data->u.FileData.FDH->NumEntries)
1081 retval = &df_data->u.FileData.ExtraAttr;
1082 else
1084 retval = &df_data->u.FileData.FDH->TAttrArray[df_data->u.FileData.AttrsIndex];
1085 df_data->u.FileData.OrigName = retval->tta_Name;
1086 retval->tta_Name = df_data->u.FileData.FilePart;
1087 df_data->u.FileData.LastAttr = retval;
1090 /* Let the iterator point to the next element.
1092 df_data->u.FileData.AttrsIndex++;
1094 break;
1097 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, retval);
1100 /****************************************************************************************/
1102 /***********************/
1103 /* DF_IteratorRemember */
1104 /***********************/
1106 /****************************************************************************************/
1108 VOID DF_IteratorRemember(APTR iterator, struct DiskfontBase *DiskfontBase)
1110 struct DF_Data *df_data = (struct DF_Data *)iterator;
1112 D(bug("DF_IteratorRemember(iterator=0x%lx)\n", iterator));
1114 switch (df_data->Type)
1116 case DF_FONTSDATA:
1117 if (df_data->u.FontsData.AttrsIndex > 0)
1119 df_data->u.FontsData.RememberIndex = df_data->u.FontsData.AttrsIndex-1;
1120 df_data->u.FontsData.RememberFileEntry = df_data->u.FontsData.CurrentFileEntry;
1122 else
1124 df_data->u.FontsData.RememberFileEntry = df_data->u.FontsData.PrevFileEntry;
1125 df_data->u.FontsData.RememberIndex = df_data->u.FontsData.RememberFileEntry->Numentries-1;
1126 if (df_data->u.FontsData.RememberFileEntry->ContentsID == OFCH_ID
1127 && df_data->ReqAttr == NULL
1130 df_data->u.FontsData.RememberIndex--;
1134 D(bug("DF_IteratorRemember: Remembered font: %s/%d\n",
1135 df_data->u.FontsData.RememberFileEntry->Attrs[df_data->u.FontsData.RememberIndex].tta_Name,
1136 df_data->u.FontsData.RememberFileEntry->Attrs[df_data->u.FontsData.RememberIndex].tta_YSize));
1137 break;
1139 case DF_FILEDATA:
1140 df_data->u.FileData.RememberIndex = df_data->u.FileData.AttrsIndex-1;
1142 D(bug("DF_IteratorRemember: Remembered font: %s(%d)\n",
1143 df_data->ReqAttr->tta_Name, df_data->u.FileData.RememberIndex));
1144 break;
1148 /****************************************************************************************/
1150 /***************************/
1151 /* DF_IteratorRememberOpen */
1152 /***************************/
1154 /****************************************************************************************/
1156 struct TextFont *DF_IteratorRememberOpen(APTR iterator, struct DiskfontBase *DiskfontBase)
1158 struct DF_Data *df_data = (struct DF_Data *)iterator;
1159 struct FontDescrHeader *fdh = NULL;
1160 struct TTextAttr *RememberAttr = NULL;
1161 struct TextFont *tf = NULL;
1162 BPTR olddir = 0, lock, dirlock;
1164 D(bug("DF_IteratorRememberOpen(iterator=0x%lx)\n", iterator));
1166 /* Set current dir and get the Remember TextAttr */
1167 switch (df_data->Type)
1169 case DF_FONTSDATA:
1171 struct FileEntry *rementry = df_data->u.FontsData.RememberFileEntry;
1173 olddir = CurrentDir(rementry->DirEntry->DirLock);
1174 fdh = ReadFontDescr(rementry->FileName, DiskfontBase);
1175 if (fdh == NULL)
1176 RememberAttr = NULL;
1177 else if (rementry->ContentsID == OFCH_ID
1178 && df_data->u.FontsData.RememberIndex == rementry->Numentries - 1)
1180 /* It is the TAttr generated for best matching */
1181 RememberAttr = &rementry->Attrs[df_data->u.FontsData.RememberIndex];
1183 else
1184 RememberAttr = &fdh->TAttrArray[df_data->u.FontsData.RememberIndex];
1186 break;
1188 case DF_FILEDATA:
1189 if (df_data->u.FileData.LastAttr != NULL)
1191 df_data->u.FileData.LastAttr->tta_Name = df_data->u.FileData.OrigName;
1192 df_data->u.FileData.LastAttr = NULL;
1195 RememberAttr = NULL;
1196 lock = Lock(df_data->ReqAttr->tta_Name, ACCESS_READ);
1197 if (lock == BNULL)
1199 D(bug("DF_IteratorRememberOpen: Could not lock file\n"));
1200 break;
1203 dirlock = ParentDir(lock);
1204 UnLock(lock);
1205 if (dirlock == BNULL)
1207 D(bug("DF_IteratorRememberOpen: Could not get ParentDir\n"));
1208 break;
1210 olddir = CurrentDir(dirlock);
1212 fdh = df_data->u.FileData.FDH;
1213 if (df_data->u.FileData.RememberIndex == fdh->NumEntries)
1214 RememberAttr = &df_data->u.FileData.ExtraAttr;
1215 else
1216 RememberAttr = &fdh->TAttrArray[df_data->u.FileData.RememberIndex];
1217 break;
1220 if (RememberAttr == NULL)
1221 return NULL;
1223 if (fdh != NULL)
1225 D(bug("DF_IteratorRememberOpen: Font Description read\n"));
1227 if (IS_OUTLINE_FONT(RememberAttr))
1229 D(bug("DF_IteratorRememberOpen: loading outline font\n"));
1231 tf = OTAG_ReadOutlineFont(RememberAttr,
1232 df_data->ReqAttr,
1233 fdh->OTagList,
1234 DiskfontBase);
1235 D(bug("DF_IteratorRememberOpen: tf=0x%lx\n", tf));
1238 else
1240 D(bug("DF_IteratorRememberOpen: loading bitmap font\n"));
1242 tf = ReadDiskFont(RememberAttr,
1243 FilePart(df_data->ReqAttr->tta_Name),
1244 DiskfontBase);
1246 D(bug("DF_IteratorRememberOpen: tf=0x%lx\n", tf));
1249 else
1250 D(bug("DF_IteratorRememberOpen: Font Description read failed\n"));
1252 dirlock = CurrentDir(olddir);
1253 switch (df_data->Type)
1255 case DF_FONTSDATA:
1256 FreeFontDescr(fdh, DiskfontBase);
1257 break;
1259 case DF_FILEDATA:
1260 UnLock(dirlock);
1261 break;
1264 if (tf != NULL)
1266 struct DiskFontHeader *dfh;
1268 /* PPaint's personal.font/8 has not set FPF_DISKFONT,
1269 (FPF_ROMFONT neither), but AmigaOS diskfont.library
1270 still shows FPF_DISKFONT set when opening this font */
1272 tf->tf_Flags &= ~FPF_ROMFONT;
1273 tf->tf_Flags |= FPF_DISKFONT;
1275 D(bug("Adding font: %p\n", tf));
1277 /* Forbid() must be called before AddFont, because AddFont clears
1278 tf_Accessors and in the worst case it could happen to us that
1279 after the AddFont() another task opens and closes/frees the
1280 diskfont, before we manage to increase tf_Accessors. */
1282 Forbid();
1284 AddFont(tf);
1285 tf->tf_Accessors++;
1287 dfh = (struct DiskFontHeader *)((UBYTE *)(tf) - (IPTR)OFFSET(DiskFontHeader, dfh_TF));
1289 /* Paranoia check */
1290 if (dfh->dfh_FileID == DFH_ID)
1291 ADDTAIL(&DiskfontBase->diskfontlist, &dfh->dfh_DF);
1293 Permit();
1295 D(bug("Font added\n"));
1298 return tf;
1301 /****************************************************************************************/
1303 /*******************/
1304 /* DF_IteratorFree */
1305 /*******************/
1307 /****************************************************************************************/
1309 VOID DF_IteratorFree(APTR iterator, struct DiskfontBase *DiskfontBase)
1311 struct DF_Data *df_data = (struct DF_Data *)iterator;
1313 FreeResources(df_data, DiskfontBase);
1316 /****************************************************************************************/
1318 /*******************/
1319 /* DF_OpenFontPath */
1320 /*******************/
1322 /****************************************************************************************/
1324 struct TextFont *DF_OpenFontPath(struct TextAttr *reqattr, struct DiskfontBase *DiskfontBase)
1326 struct TextFont *tf = NULL;
1327 struct FontDescrHeader *fdh;
1328 BPTR olddir, lock, dirlock;
1330 D(bug("DF_OpenFontPath(reqattr=0x%lx)\n", reqattr));
1332 lock = Lock(reqattr->ta_Name, ACCESS_READ);
1333 if (lock == BNULL)
1335 D(bug("DF_OpenFontPath: Could not lock file\n"));
1336 return NULL;
1339 dirlock = ParentDir(lock);
1340 UnLock(lock);
1341 if (dirlock == BNULL)
1343 D(bug("DF_OpenFontPath: Could not get ParentDir\n"));
1344 return NULL;
1347 olddir = CurrentDir(dirlock);
1349 fdh = ReadFontDescr(reqattr->ta_Name, DiskfontBase);
1351 if (fdh != NULL)
1353 WORD max_match_weight = 0, match_weight;
1354 LONG match_index = -1;
1355 int i;
1357 D(bug("DF_OpenFontPath: Font Description read\n"));
1359 for (i=0; i<fdh->NumEntries; i++)
1361 match_weight = WeighTAMatch((struct TextAttr *)reqattr,
1362 (struct TextAttr *)&fdh->TAttrArray[i],
1363 fdh->TAttrArray[i].tta_Tags);
1365 if (match_weight > max_match_weight)
1367 max_match_weight = match_weight;
1368 match_index = i;
1372 if (match_index >= 0)
1374 if (IS_OUTLINE_FONT(&fdh->TAttrArray[match_index]))
1376 D(bug("DF_OpenFontPath: loading outline font\n"));
1378 tf = OTAG_ReadOutlineFont(&fdh->TAttrArray[match_index],
1379 (struct TTextAttr *)reqattr,
1380 fdh->OTagList,
1381 DiskfontBase);
1382 D(bug("DF_OpenFontPath: tf=0x%lx\n", tf));
1385 else
1387 D(bug("DF_OpenFontPath: loading bitmap font\n"));
1389 tf = ReadDiskFont(&fdh->TAttrArray[match_index],
1390 reqattr->ta_Name,
1391 DiskfontBase);
1393 D(bug("DF_OpenFontPath: tf=0x%lx\n", tf));
1396 else
1397 D(bug("DF_OpenFontPath: No matching font found\n"));
1399 FreeFontDescr(fdh, DiskfontBase);
1401 else
1402 D(bug("DF_OpenFontPath: Font Description read failed\n"));
1404 CurrentDir(olddir);
1405 UnLock(dirlock);
1407 if (tf != NULL)
1409 struct DiskFontHeader *dfh;
1411 /* PPaint's personal.font/8 has not set FPF_DISKFONT,
1412 (FPF_ROMFONT neither), but AmigaOS diskfont.library
1413 still shows FPF_DISKFONT set when opening this font */
1415 tf->tf_Flags &= ~FPF_ROMFONT;
1416 tf->tf_Flags |= FPF_DISKFONT;
1418 D(bug("Adding font: %p\n", tf));
1420 /* Forbid() must be called before AddFont, because AddFont clears
1421 tf_Accessors and in the worst case it could happen to us that
1422 after the AddFont() another task opens and closes/frees the
1423 diskfont, before we manage to increase tf_Accessors. */
1425 Forbid();
1427 AddFont(tf);
1428 tf->tf_Accessors++;
1430 dfh = (struct DiskFontHeader *)((UBYTE *)(tf) - (IPTR)OFFSET(DiskFontHeader, dfh_TF));
1432 /* Paranoia check */
1433 if (dfh->dfh_FileID == DFH_ID)
1434 ADDTAIL(&DiskfontBase->diskfontlist, &dfh->dfh_DF);
1436 Permit();
1438 D(bug("Font added\n"));
1441 return tf;