New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / workbench / libs / diskfont / diskfontfunc.c
blobfd952058027f090e9d1722821e1fa615426822c7
1 /*
2 Copyright © 1995-2001, 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_intern *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;
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 + fdh->NumEntries);
152 for (i = 0; i < fdh->NumEntries; i++)
154 retval->Attrs[i].tta_Name = retval->FileName;
156 if (fdh->TAttrArray[i].tta_Tags != NULL)
158 tagcount = NumTags(fdh->TAttrArray[i].tta_Tags, DiskfontBase);
159 CopyTagItems(tagitems, fdh->TAttrArray[i].tta_Tags, DiskfontBase);
160 retval->Attrs[i].tta_Tags = tagitems;
161 tagitems += tagcount;
163 else
164 retval->Attrs[i].tta_Tags = NULL;
167 FreeFontDescr(fdh, DiskfontBase);
169 ReturnPtr("ReadFileEntry", struct FileEntry *, retval);
172 /****************************************************************************************/
174 /*****************/
175 /* FreeFileEntry */
176 /*****************/
178 /****************************************************************************************/
180 STATIC VOID FreeFileEntry(struct FileEntry *feptr, struct DiskfontBase_intern *DiskfontBase)
182 FreeVec(feptr);
185 /****************************************************************************************/
187 /****************/
188 /* FreeFileList */
189 /****************/
191 /****************************************************************************************/
193 STATIC VOID FreeFileList(struct MinList *filelist, struct DiskfontBase_intern *DiskfontBase)
195 struct FileEntry *feptr, *nextfeptr;
197 D(bug("FreeFileList(filelist=%p)\n", filelist));
199 ForeachNodeSafe(filelist, feptr, nextfeptr)
201 REMOVE(feptr);
202 FreeFileEntry(feptr, DiskfontBase);
205 ReturnVoid("FreeFileList");
208 /****************************************************************************************/
210 /****************/
211 /* GetFileList */
212 /****************/
214 /****************************************************************************************/
216 /* Build the list of .font file names using Examine() */
217 STATIC BOOL GetFileList(struct DirEntry *direntry, struct DiskfontBase_intern *DiskfontBase)
219 struct MinList newlist;
220 struct FileEntry *fe, *nextfe;
221 BOOL retval = TRUE, more;
222 struct ExAllControl *eac;
223 struct ExAllData *ead, *eadit;
225 D(bug("GetFileList(direntry=%p)\n", direntry));
227 NEWLIST(&newlist);
229 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
230 eac->eac_LastKey = 0;
231 ead = (struct ExAllData *)AllocMem(1024, MEMF_ANY);
235 more = ExAll(direntry->DirLock, ead, 1024, ED_DATE, eac);
236 if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES))
237 retval = FALSE;
238 else if (eac->eac_Entries == 0)
239 continue;
240 else
242 for (eadit = ead; eadit != NULL; eadit = eadit->ed_Next)
244 ULONG namelen = strlen(eadit->ed_Name);
246 D(bug("GetFileList: Scanning file: %s\n", eadit->ed_Name));
248 /* Maybe this can be done in a hook function passed in eac */
249 if (namelen < 5 || strncmp(eadit->ed_Name+namelen-5, ".font", 5) != 0)
251 D(bug("GetFileList: wrong suffix: %s\n", eadit->ed_Name+namelen-5));
252 continue;
255 /* Is a FileEntry for this file already in the list */
256 for (fe = (struct FileEntry *)GetHead(&direntry->FileList);
257 fe != NULL;
258 fe = (struct FileEntry *)GetSucc(fe))
260 if (strcmp(eadit->ed_Name, fe->FileName) == 0)
261 break;
264 if (fe == NULL)
266 D(bug("GetFileList: Filename not yet in memory\n"));
268 fe = ReadFileEntry(eadit, DiskfontBase);
269 if (fe != NULL)
271 fe->DirEntry = direntry;
273 D(bug("GetFileList: Add to list: 0x%lx\n", fe));
274 ADDTAIL(&newlist, fe);
277 else
279 struct DateStamp ds;
280 REMOVE(fe);
282 ds.ds_Days = eadit->ed_Days;
283 ds.ds_Minute = eadit->ed_Mins;
284 ds.ds_Tick = eadit->ed_Ticks;
286 D(bug("GetFileList: Found filename already in memory\n"));
288 if (CompareDates(&ds, &fe->FileChanged) == 0)
290 D(bug("GetFileList: File's date not changed: Add to list 0x%lx\n", fe));
291 ADDTAIL(&newlist, fe);
293 else
295 D(bug("GetFileList: Date changed rereading information\n"));
297 FreeFileEntry(fe, DiskfontBase);
299 fe = ReadFileEntry(eadit, DiskfontBase);
300 if (fe == NULL)
302 D(bug("GetFileList: Reading information failed\n"));
303 retval = FALSE;
304 break;
306 else
308 fe->DirEntry = direntry;
309 D(bug("GetFileList: Reading OK, add to list: 0x%lx\n", fe));
310 ADDTAIL(&newlist, fe);
314 } /* for (eadit = ... */
316 } while (more && retval);
318 FreeDosObject(DOS_EXALLCONTROL, eac);
319 FreeMem(ead, 1024);
321 if (!retval)
323 D(bug("GetFileList: Not OK freeing FileList\n"));
324 FreeFileList(&newlist, DiskfontBase);
326 else
328 /* Remove FileEntries that are still in memory but not anymore
329 * on disk */
330 FreeFileList(&direntry->FileList, DiskfontBase);
332 ForeachNodeSafe(&newlist, fe, nextfe)
334 REMOVE(fe);
335 ADDTAIL(&direntry->FileList, fe);
336 D(bug("GetFileList: Adding fe=%p\n", fe));
340 ReturnBool ("GetFileList", retval);
343 /****************************************************************************************/
345 /*********************/
346 /* StreamOutFileList */
347 /*********************/
349 /****************************************************************************************/
351 STATIC BOOL StreamOutFileList(struct MinList *filelist, BPTR fh, struct DiskfontBase_intern *DiskfontBase)
353 struct FileEntry *fe;
354 ULONG i;
355 BOOL ok = TRUE;
357 ForeachNode(filelist, fe)
359 D(bug("StreamOutFileList: Writing file %s\n", fe->FileName));
360 ok = ok && WriteString(&DiskfontBase->dsh, fe->FileName, fh);
361 D(bug("StreamOutFileList: Write days: %d minute: %d, tick: %d\n",
362 fe->FileChanged.ds_Days, fe->FileChanged.ds_Minute,
363 fe->FileChanged.ds_Tick));
364 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Days, fh);
365 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Minute, fh);
366 ok = ok && WriteLong(&DiskfontBase->dsh, fe->FileChanged.ds_Tick, fh);
367 ok = ok && WriteWord(&DiskfontBase->dsh, fe->ContentsID, fh);
368 ok = ok && WriteByte(&DiskfontBase->dsh, fe->SupportedStyles, fh);
369 ok = ok && WriteByte(&DiskfontBase->dsh, fe->FontStyle, fh);
370 D(bug("StreamOutFileList: Write numentries=%d\n", fe->Numentries));
371 ok = ok && WriteLong(&DiskfontBase->dsh, fe->Numentries, fh);
373 for (i=0; ok && i<fe->Numentries; i++)
375 ok = ok && WriteWord(&DiskfontBase->dsh, fe->Attrs[i].tta_YSize, fh);
376 ok = ok && WriteByte(&DiskfontBase->dsh, fe->Attrs[i].tta_Style, fh);
377 ok = ok && WriteByte(&DiskfontBase->dsh, fe->Attrs[i].tta_Flags, fh);
378 ok = ok && WriteTagsNum(fh, fe->Attrs[i].tta_Tags, DiskfontBase);
381 ok = ok && WriteString(&DiskfontBase->dsh, "", fh);
383 return ok;
386 /****************************************************************************************/
388 /********************/
389 /* StreamInFileList */
390 /********************/
392 /****************************************************************************************/
394 STATIC BOOL StreamInFileList(struct DirEntry *direntry, BPTR fh, struct DiskfontBase_intern *DiskfontBase)
396 struct FileEntry *fe, fe2;
397 ULONG i, numtags, totnumtags;
398 BOOL ok = TRUE;
399 struct TTextAttr *attrs;
400 struct TagItem *tagptr;
402 for (ok = ReadString(&DiskfontBase->dsh, &fe2.FileName, fh);
403 ok && strlen(fe2.FileName)>0;
404 ok = ok && ReadString(&DiskfontBase->dsh, &fe2.FileName, fh))
406 D(bug("StreamInFileList: reading data for \"%s\"\n", fe2.FileName));
408 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Days, fh);
409 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Minute, fh);
410 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.FileChanged.ds_Tick, fh);
411 D(bug("StreamInFileList: read days: %d minute: %d tick: %d\n",
412 fe2.FileChanged.ds_Days, fe2.FileChanged.ds_Minute,
413 fe2.FileChanged.ds_Tick));
414 ok = ok && ReadWord(&DiskfontBase->dsh, &fe2.ContentsID, fh);
415 ok = ok && ReadByte(&DiskfontBase->dsh, &fe2.SupportedStyles, fh);
416 ok = ok && ReadByte(&DiskfontBase->dsh, &fe2.FontStyle, fh);
417 ok = ok && ReadLong(&DiskfontBase->dsh, &fe2.Numentries, fh);
419 if (ok)
421 attrs = AllocVec(fe2.Numentries * sizeof(struct TTextAttr), MEMF_ANY|MEMF_CLEAR);
423 ok = ok && attrs != NULL;
425 if (ok)
426 for (i = 0; i < fe2.Numentries; i++)
427 attrs[i].tta_Tags = NULL;
429 for (i = 0, totnumtags = 0; ok && i < fe2.Numentries; i++)
431 ok = ok && ReadWord(&DiskfontBase->dsh, &attrs[i].tta_YSize, fh);
432 ok = ok && ReadByte(&DiskfontBase->dsh, &attrs[i].tta_Style, fh);
433 ok = ok && ReadByte(&DiskfontBase->dsh, &attrs[i].tta_Flags, fh);
434 if (ok)
436 attrs[i].tta_Tags = ReadTagsNum(fh, &numtags, DiskfontBase);
437 D(bug("StreamInFileList: read tags %p\n", attrs[i].tta_Tags));
438 totnumtags += numtags;
439 ok = ok && numtags > 0;
442 D(bug("StreamInFileList: totnumtags == %u\n", totnumtags));
444 if (ok)
446 ULONG size = sizeof(struct FileEntry) +
447 strlen(fe2.FileName)+1 +
448 fe2.Numentries * sizeof(struct TTextAttr) +
449 totnumtags * sizeof(struct TagItem);
451 fe = (struct FileEntry *)AllocVec(size, MEMF_ANY);
452 ok = ok && fe != NULL;
454 if (ok)
456 fe->DirEntry = direntry;
457 fe->FileName = (STRPTR)(fe+1);
458 strcpy(fe->FileName, fe2.FileName);
459 fe->FileChanged = fe2.FileChanged;
460 fe->ContentsID = fe2.ContentsID;
461 fe->SupportedStyles = fe2.SupportedStyles;
462 fe->FontStyle = fe2.FontStyle;
463 fe->Numentries = fe2.Numentries;
464 fe->Attrs = (struct TTextAttr *)(fe->FileName + strlen(fe2.FileName)+1);
466 tagptr = (struct TagItem *)(fe->Attrs + fe2.Numentries);
467 for (i = 0; i < fe2.Numentries; i++)
469 fe->Attrs[i].tta_Name = fe->FileName;
470 fe->Attrs[i].tta_YSize = attrs[i].tta_YSize;
471 fe->Attrs[i].tta_Style = attrs[i].tta_Style;
472 fe->Attrs[i].tta_Flags = attrs[i].tta_Flags;
473 numtags = CopyTagItems(tagptr, attrs[i].tta_Tags, DiskfontBase);
474 fe->Attrs[i].tta_Tags = tagptr;
475 tagptr += numtags;
477 ADDTAIL(&direntry->FileList, fe);
480 if (attrs != NULL)
482 for (i = 0; i < fe2.Numentries; i++)
483 if (attrs[i].tta_Tags != NULL)
485 D(bug("StreamInFileList: freeing tags %p\n", attrs[i].tta_Tags));
486 FreeVec(attrs[i].tta_Tags);
488 FreeVec(attrs);
492 FreeVec(fe2.FileName);
494 if (ok)
496 D(bug("StreamInFileList: FileName empty\n"));
497 FreeVec(fe2.FileName);
499 else
501 D(bug("StreamInFileList: Error reading chachefile\n"));
502 FreeFileList(&direntry->FileList, DiskfontBase);
505 return ok;
508 /****************************************************************************************/
510 /****************/
511 /* FreeDirEntry */
512 /****************/
514 /****************************************************************************************/
516 STATIC VOID FreeDirEntry(struct DirEntry *direntry, struct DiskfontBase_intern *DiskfontBase)
518 if (direntry!=NULL)
520 FreeFileList(&direntry->FileList, DiskfontBase);
521 UnLock(direntry->DirLock);
522 FreeVec(direntry);
526 /****************************************************************************************/
528 /****************/
529 /* ReadDirEntry */
530 /****************/
532 /****************************************************************************************/
534 STATIC struct DirEntry *ReadDirEntry(BPTR dirlock, struct DirEntry *direntry, struct DiskfontBase_intern *DiskfontBase)
536 struct Process *Self;
537 APTR oldwinptr;
538 struct FileInfoBlock *fib;
539 BPTR olddir;
540 BPTR fh;
542 D(bug("ReadDirEntry(dirlock=0x%lx, direntry=0x%lx)\n", dirlock, direntry));
544 Self = (struct Process *) FindTask(NULL);
545 oldwinptr = Self->pr_WindowPtr;
546 Self->pr_WindowPtr = (APTR) -1;
548 fib = AllocDosObject(DOS_FIB, NULL);
549 if (fib == NULL)
551 D(bug("ReadDirEntry: Could not allocate DosObject\n"));
552 Self->pr_WindowPtr = oldwinptr;
553 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
555 Examine(dirlock, fib);
556 Self->pr_WindowPtr = oldwinptr;
558 olddir = CurrentDir(dirlock);
560 if (direntry == NULL)
562 direntry = AllocVec(sizeof(struct DirEntry), MEMF_ANY | MEMF_CLEAR);
563 if (direntry==NULL)
565 D(bug("ReadDirEntry: Could not allocate DirEntry\n"));
566 FreeDosObject(DOS_FIB, fib);
567 CurrentDir(olddir);
568 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
570 else
571 D(bug("ReadDirEntry: allocated direntry = 0x%lx\n", direntry));
573 direntry->DirLock = dirlock;
574 NEWLIST(&direntry->FileList);
576 /* Try to read the direntry from the file */
577 fh = Open(CACHE_FILE, MODE_OLDFILE);
578 if (fh != NULL)
580 BOOL ok;
582 ok = ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Days, fh);
583 ok = ok && ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Minute, fh);
584 ok = ok && ReadLong(&DiskfontBase->dsh, &direntry->DirChanged.ds_Tick, fh);
586 if (ok)
587 ok = StreamInFileList(direntry, fh, DiskfontBase);
589 Close(fh);
591 #warning CHECKME
592 #if 0
593 /* This part is disabled because in emul_handler on UNIX the date
594 * of a parent directory is changed only when a file is added or
595 * removed from the directory
598 /* If dates are the same return the direntry as is */
599 if (ok && CompareDates(&direntry->DirChanged, &fib->fib_Date) == 0)
601 D(bug("ReadDirEntry: date in cache not changed\n"));
602 FreeDosObject(DOS_FIB, fib);
603 Self->pr_WindowPtr = oldwinptr;
604 CurrentDir(olddir);
605 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
607 #endif
610 else
612 CurrentDir(direntry->DirLock);
613 UnLock(dirlock);
614 if (CompareDates(&direntry->DirChanged, &fib->fib_Date) == 0)
616 D(bug("ReadDirEntry: direntry 0x%lx not changed\n", direntry));
617 FreeDosObject(DOS_FIB, fib);
618 Self->pr_WindowPtr = oldwinptr;
619 CurrentDir(olddir);
620 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
624 direntry->DirChanged = fib->fib_Date;
626 if (!GetFileList(direntry, DiskfontBase))
628 D(bug("ReadDirEntry: Error reading FileList\n"));
629 FreeDosObject(DOS_FIB, fib);
630 CurrentDir(olddir);
631 UnLock(direntry->DirLock);
632 FreeVec(direntry);
633 Self->pr_WindowPtr = oldwinptr;
634 ReturnPtr("ReadDirEntry", struct DirEntry *, NULL);
637 /* If everything went OK Write the cache file */
638 fh = Open(CACHE_FILE, MODE_NEWFILE);
639 if (fh != NULL)
641 BOOL ok;
643 ok = WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Days, fh);
644 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Minute, fh);
645 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Tick, fh);
647 if (ok)
648 ok = StreamOutFileList(&direntry->FileList, fh, DiskfontBase);
650 Close(fh);
652 if (ok)
654 Examine(direntry->DirLock, fib);
655 direntry->DirChanged = fib->fib_Date;
656 fh = Open(CACHE_FILE, MODE_OLDFILE);
657 if (fh != NULL)
659 Seek(fh, 0, OFFSET_BEGINNING);
660 ok = WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Days, fh);
661 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Minute, fh);
662 ok = ok && WriteLong(&DiskfontBase->dsh, fib->fib_Date.ds_Tick, fh);
663 Close(fh);
667 if (!ok)
668 DeleteFile(CACHE_FILE);
671 FreeDosObject(DOS_FIB, fib);
672 CurrentDir(olddir);
673 Self->pr_WindowPtr = oldwinptr;
675 ReturnPtr("ReadDirEntry", struct DirEntry *, direntry);
678 /****************************************************************************************/
680 /****************/
681 /* FreeResouces */
682 /****************/
684 /****************************************************************************************/
686 STATIC VOID FreeResources(struct DF_Data *df_data, struct DiskfontBase_intern *DiskfontBase)
688 D(bug("FreeResources(df_data=%p)\n", df_data));
690 ReleaseSemaphore(&DiskfontBase->fontssemaphore);
692 switch (df_data->Type)
694 case DF_FONTSDATA:
695 #ifdef PROGDIRFONTSDIR
696 FreeDirEntry(df_data->u.FontsData.ProgdirDirEntry, DiskfontBase);
697 #endif
698 break;
700 case DF_FILEDATA:
701 if (df_data->u.FileData.FDH != NULL)
702 FreeFontDescr(df_data->u.FileData.FDH, DiskfontBase);
703 break;
706 FreeMem(df_data, sizeof (struct DF_Data));
708 ReturnVoid("FreeResources");
711 /****************************************************************************************/
713 /****************************/
714 /* CleanUpFontsDirEntryList */
715 /****************************/
717 /****************************************************************************************/
719 VOID CleanUpFontsDirEntryList(struct DiskfontBase_intern *DiskfontBase)
721 struct DirEntry *direntry, *direntry2;
723 ForeachNodeSafe(&DiskfontBase->fontsdirentrylist, direntry, direntry2)
724 FreeDirEntry(direntry, DiskfontBase);
726 ReturnVoid("CleanUpFontsDirEntryList");
729 /****************************************************************************************/
731 /******************/
732 /* AllocResources */
733 /******************/
735 /****************************************************************************************/
737 STATIC struct DF_Data *AllocResources(struct TTextAttr *reqattr, struct DiskfontBase_intern *DiskfontBase)
739 struct DF_Data *df_data;
741 D(bug("AllocResources(void)\n"));
743 ObtainSemaphore(&DiskfontBase->fontssemaphore);
745 /* Allocate user data */
746 if ((df_data = AllocMem( sizeof (struct DF_Data), MEMF_ANY | MEMF_CLEAR)))
748 df_data->ReqAttr = reqattr;
750 if (reqattr==NULL || FilePart(reqattr->tta_Name)==reqattr->tta_Name)
752 struct DevProc *dp = NULL;
753 struct MinList newdirlist;
754 struct DirEntry *direntry, *direntry2;
756 df_data->Type = DF_FONTSDATA;
758 #ifdef PROGDIRFONTSDIR
761 struct Process *Self;
762 APTR oldwinptr;
763 BPTR lock;
765 df_data->u.FontsData.ProgdirDirEntry = NULL;
767 if (!GetProgramDir())
768 break;
770 Self = (struct Process *) FindTask(NULL);
771 oldwinptr = Self->pr_WindowPtr;
772 Self->pr_WindowPtr = (APTR) -1;
773 lock = Lock(PROGDIRFONTSDIR, ACCESS_READ);
774 Self->pr_WindowPtr = oldwinptr;
776 D(bug("AllocResources: PROGDIR:Fonts DirLock = 0x%lx\n", lock));
778 if (!lock)
779 break;
781 df_data->u.FontsData.ProgdirDirEntry = ReadDirEntry(lock, NULL, DiskfontBase);
782 D(bug("AllocResources: PROGDIR:Fonts direntry 0x%lx\n", df_data->u.FontsData.ProgdirDirEntry));
783 } while (0);
784 #endif
786 NEWLIST(&newdirlist);
787 while((dp = GetDeviceProc(FONTSDIR, dp))!=NULL)
789 BPTR lock;
791 D(bug("AllocResources: FONTS: lock = 0x%lx\n", dp->dvp_Lock));
793 lock = DupLock(dp->dvp_Lock);
794 if (lock==NULL)
796 D(bug("AllocResources: Could not duplicate lock\n"));
797 continue;
800 /* See if direntry is already in memory */
801 for (direntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
802 direntry != NULL;
803 direntry = (struct DirEntry *)GetSucc(direntry))
805 if (SameLock(direntry->DirLock, lock) == LOCK_SAME)
807 REMOVE(direntry);
808 break;
812 /* Read or update fonts information in this directory */
813 direntry = ReadDirEntry(lock, direntry, DiskfontBase);
814 if (direntry!=NULL)
816 D(bug("AllocResources: addtail direntry 0x%lx\n", direntry));
817 D(bug("AllocResources: first FileEntry: %p\n", GetHead(&direntry->FileList)));
818 ADDTAIL(&newdirlist, direntry);
820 else
821 D(bug("AllocResources: Error reading DirEntry\n"));
824 /* Clean up directory lists that are in memory but not in the
825 * FONTS: assign anymore */
826 ForeachNodeSafe(&DiskfontBase->fontsdirentrylist, direntry, direntry2)
828 REMOVE(direntry);
829 FreeDirEntry(direntry, DiskfontBase);
832 ForeachNodeSafe(&newdirlist, direntry, direntry2)
834 REMOVE(direntry);
835 ADDTAIL(&DiskfontBase->fontsdirentrylist, direntry);
838 FreeDeviceProc(dp);
840 else
842 struct FontDescrHeader *fdh;
844 df_data->Type = DF_FILEDATA;
845 fdh = ReadFontDescr(reqattr->tta_Name, DiskfontBase);
846 df_data->u.FileData.FDH = fdh;
848 if (fdh != NULL)
850 if (fdh->ContentsID==OFCH_ID)
852 UBYTE SupportedStyles = OTAG_GetSupportedStyles(fdh->OTagList, DiskfontBase);
854 df_data->u.FileData.ExtraAttr.tta_Name = reqattr->tta_Name;
855 df_data->u.FileData.ExtraAttr.tta_YSize = reqattr->tta_YSize;
856 df_data->u.FileData.ExtraAttr.tta_Style = OTAG_GetFontStyle(fdh->OTagList, DiskfontBase);
857 df_data->u.FileData.ExtraAttr.tta_Flags = OTAG_GetFontFlags(fdh->OTagList, DiskfontBase);
859 df_data->u.FileData.ExtraAttr.tta_Tags = NULL;
860 if (reqattr->tta_Style & FSF_TAGGED)
862 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_TAGGED;
863 df_data->u.FileData.ExtraAttr.tta_Tags = reqattr->tta_Tags;
866 if ((reqattr->tta_Style & FSF_BOLD)
867 && !(df_data->u.FileData.ExtraAttr.tta_Style & FSF_BOLD)
868 && (SupportedStyles & FSF_BOLD))
870 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_BOLD;
873 if ((reqattr->tta_Style & FSF_ITALIC)
874 && !(df_data->u.FileData.ExtraAttr.tta_Style & FSF_ITALIC)
875 && (SupportedStyles & FSF_ITALIC))
877 df_data->u.FileData.ExtraAttr.tta_Style |= FSF_ITALIC;
884 ReturnPtr("AllocResources", struct DF_Data *, df_data);
887 /****************************************************************************************/
889 /*******************/
890 /* DF_IteratorInit */
891 /*******************/
893 /****************************************************************************************/
895 APTR DF_IteratorInit(struct TTextAttr *reqattr, struct DiskfontBase_intern *DiskfontBase)
897 struct DF_Data *df_data;
899 D(bug("DF_IteratorInit(reqattr=0x%lx)\n", reqattr));
901 df_data = AllocResources(reqattr, DiskfontBase);
902 if (df_data == NULL)
904 D(bug("DF_IteratorInit: Error executing Allocresources\n"));
905 ReturnPtr("DF_IteratorInit", APTR, NULL);
908 switch (df_data->Type)
910 case DF_FONTSDATA:
911 df_data->u.FontsData.CurrentDirEntry = NULL;
912 df_data->u.FontsData.CurrentFileEntry = NULL;
914 #ifdef PROGDIRFONTSDIR
915 if (df_data->u.FontsData.ProgdirDirEntry != NULL)
917 D(bug("DF_IteratorInit: ProgdirDirEntry found\n"));
918 df_data->u.FontsData.CurrentDirEntry = df_data->u.FontsData.ProgdirDirEntry;
919 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.ProgdirDirEntry->FileList);
921 else
922 D(bug("DF_IteratorInit: No ProgdirEntry found\n"));
923 #endif
924 if (df_data->u.FontsData.CurrentDirEntry == NULL || df_data->u.FontsData.CurrentFileEntry == NULL)
926 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
927 if (df_data->u.FontsData.CurrentDirEntry != NULL)
928 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
931 D(bug("DF_IteratorInit: CurrentDirEntry: %p CurrentFileEntry: %p\n",
932 df_data->u.FontsData.CurrentDirEntry, df_data->u.FontsData.CurrentFileEntry));
934 /* If DirEntry was empty search for one that is not empty */
935 while (df_data->u.FontsData.CurrentDirEntry != NULL && df_data->u.FontsData.CurrentFileEntry == NULL)
937 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
938 if (df_data->u.FontsData.CurrentDirEntry != NULL)
939 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
941 D(bug("DF_IteratorInit: CurrentDirEntry: %p CurrentFileEntry: %p\n",
942 df_data->u.FontsData.CurrentDirEntry, df_data->u.FontsData.CurrentFileEntry));
944 df_data->u.FontsData.AttrsIndex = 0;
946 break;
948 case DF_FILEDATA:
949 df_data->u.FileData.AttrsIndex = 0;
950 df_data->u.FileData.FilePart = FilePart(df_data->ReqAttr->tta_Name);
951 df_data->u.FileData.LastAttr = NULL;
952 break;
955 ReturnPtr("DF_IteratorInit", APTR, df_data);
958 /****************************************************************************************/
960 /**********************/
961 /* DF_IteratorGetNext */
962 /**********************/
964 /****************************************************************************************/
966 struct TTextAttr *DF_IteratorGetNext(APTR iterator, struct DiskfontBase_intern *DiskfontBase)
968 struct TTextAttr *retval = NULL;
969 struct DF_Data *df_data = (struct DF_Data *)iterator;
971 D(bug("DF_IteratorGetNext(iterator=0x%lx)\n", iterator));
973 if (df_data==NULL)
974 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
976 switch (df_data->Type)
978 case DF_FONTSDATA:
979 if (df_data->u.FontsData.CurrentDirEntry==NULL)
980 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
982 retval = df_data->u.FontsData.CurrentFileEntry->Attrs + df_data->u.FontsData.AttrsIndex;
983 D(bug("DF_IteratorGetNext:\n"
984 " ContentsID: 0x%x == 0x%x\n"
985 " ReqAttr: %p\n"
986 " AttrIndex: %d, Numentries: %d\n",
987 df_data->u.FontsData.CurrentFileEntry->ContentsID, OFCH_ID,
988 df_data->ReqAttr,
989 df_data->u.FontsData.AttrsIndex, df_data->u.FontsData.CurrentFileEntry->Numentries));
991 if (df_data->u.FontsData.CurrentFileEntry->ContentsID == OFCH_ID
992 && df_data->ReqAttr != NULL
993 && df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-1)
995 D(bug("DF_IteratorGetNext: Setting last outline element\n"));
997 /* The last attr for a outline font is filled with values matching
998 * as close as possible the reqattr */
999 retval->tta_YSize = df_data->ReqAttr->tta_YSize;
1000 retval->tta_Style = df_data->u.FontsData.CurrentFileEntry->FontStyle;
1002 retval->tta_Tags = NULL;
1004 if (df_data->ReqAttr->tta_Style & FSF_TAGGED)
1006 retval->tta_Style |= FSF_TAGGED;
1007 retval->tta_Tags = df_data->ReqAttr->tta_Tags;
1010 if ((df_data->ReqAttr->tta_Style & FSF_BOLD)
1011 && !(retval->tta_Style & FSF_BOLD)
1012 && (df_data->u.FontsData.CurrentFileEntry->SupportedStyles & FSF_BOLD))
1014 retval->tta_Style |= FSF_BOLD;
1017 if ((df_data->ReqAttr->tta_Style & FSF_ITALIC)
1018 && !(retval->tta_Style & FSF_ITALIC)
1019 && (df_data->u.FontsData.CurrentFileEntry->SupportedStyles & FSF_ITALIC))
1021 retval->tta_Style |= FSF_ITALIC;
1025 /* Let the iterator point to the next attr */
1026 if ((df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-1)
1027 || (df_data->u.FontsData.CurrentFileEntry->ContentsID == OFCH_ID
1028 && df_data->ReqAttr==NULL &&
1029 df_data->u.FontsData.AttrsIndex == df_data->u.FontsData.CurrentFileEntry->Numentries-2
1033 df_data->u.FontsData.PrevFileEntry = df_data->u.FontsData.CurrentFileEntry;
1034 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetSucc(df_data->u.FontsData.CurrentFileEntry);
1035 df_data->u.FontsData.AttrsIndex = 0;
1036 if (df_data->u.FontsData.CurrentFileEntry == NULL)
1038 while (df_data->u.FontsData.CurrentDirEntry != NULL && df_data->u.FontsData.CurrentFileEntry == NULL)
1040 #ifdef PROGDIRFONTSDIR
1041 if (df_data->u.FontsData.CurrentDirEntry == df_data->u.FontsData.ProgdirDirEntry)
1042 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetHead(&DiskfontBase->fontsdirentrylist);
1043 else
1044 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
1045 #else
1046 df_data->u.FontsData.CurrentDirEntry = (struct DirEntry *)GetSucc(df_data->u.FontsData.CurrentDirEntry);
1047 #endif
1048 if (df_data->u.FontsData.CurrentDirEntry != NULL)
1049 df_data->u.FontsData.CurrentFileEntry = (struct FileEntry *)GetHead(&df_data->u.FontsData.CurrentDirEntry->FileList);
1054 else
1055 df_data->u.FontsData.AttrsIndex++;
1056 break;
1058 case DF_FILEDATA:
1059 if (df_data->u.FileData.LastAttr != NULL)
1061 df_data->u.FileData.LastAttr->tta_Name = df_data->u.FileData.OrigName;
1062 df_data->u.FileData.LastAttr = NULL;
1065 /* Do not return the best-match attribute if it is not an outline font! */
1067 if (df_data->u.FileData.FDH==NULL
1068 || df_data->u.FileData.AttrsIndex > df_data->u.FileData.FDH->NumEntries
1069 || (df_data->u.FileData.FDH->ContentsID != OFCH_ID &&
1070 df_data->u.FileData.AttrsIndex == df_data->u.FileData.FDH->NumEntries))
1072 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, NULL);
1074 /* Get the TextAttr the iterator is pointing to
1075 * If it points to the element after the last element return
1076 * the Extra Attr that matches the outline font as close as possible
1078 if (df_data->u.FileData.AttrsIndex == df_data->u.FileData.FDH->NumEntries)
1079 retval = &df_data->u.FileData.ExtraAttr;
1080 else
1082 retval = &df_data->u.FileData.FDH->TAttrArray[df_data->u.FileData.AttrsIndex];
1083 df_data->u.FileData.OrigName = retval->tta_Name;
1084 retval->tta_Name = df_data->u.FileData.FilePart;
1085 df_data->u.FileData.LastAttr = retval;
1088 /* Let the iterator point to the next element.
1090 df_data->u.FileData.AttrsIndex++;
1092 break;
1095 ReturnPtr("DF_IteratorGetNext", struct TTextAttr *, retval);
1098 /****************************************************************************************/
1100 /***********************/
1101 /* DF_IteratorRemember */
1102 /***********************/
1104 /****************************************************************************************/
1106 VOID DF_IteratorRemember(APTR iterator, struct DiskfontBase_intern *DiskfontBase)
1108 struct DF_Data *df_data = (struct DF_Data *)iterator;
1110 D(bug("DF_IteratorRemember(iterator=0x%lx)\n", iterator));
1112 switch (df_data->Type)
1114 case DF_FONTSDATA:
1115 if (df_data->u.FontsData.AttrsIndex > 0)
1117 df_data->u.FontsData.RememberIndex = df_data->u.FontsData.AttrsIndex-1;
1118 df_data->u.FontsData.RememberFileEntry = df_data->u.FontsData.CurrentFileEntry;
1120 else
1122 df_data->u.FontsData.RememberFileEntry = df_data->u.FontsData.PrevFileEntry;
1123 df_data->u.FontsData.RememberIndex = df_data->u.FontsData.RememberFileEntry->Numentries-1;
1124 if (df_data->u.FontsData.RememberFileEntry->ContentsID == OFCH_ID
1125 && df_data->ReqAttr == NULL
1128 df_data->u.FontsData.RememberIndex--;
1132 D(bug("DF_IteratorRemember: Remembered font: %s/%d\n",
1133 df_data->u.FontsData.RememberFileEntry->Attrs[df_data->u.FontsData.RememberIndex].tta_Name,
1134 df_data->u.FontsData.RememberFileEntry->Attrs[df_data->u.FontsData.RememberIndex].tta_YSize));
1135 break;
1137 case DF_FILEDATA:
1138 df_data->u.FileData.RememberIndex = df_data->u.FileData.AttrsIndex-1;
1140 D(bug("DF_IteratorRemember: Remembered font: %s(%d)\n",
1141 df_data->ReqAttr->tta_Name, df_data->u.FileData.RememberIndex));
1142 break;
1146 /****************************************************************************************/
1148 /***************************/
1149 /* DF_IteratorRememberOpen */
1150 /***************************/
1152 /****************************************************************************************/
1154 struct TextFont *DF_IteratorRememberOpen(APTR iterator, struct DiskfontBase_intern *DiskfontBase)
1156 struct DF_Data *df_data = (struct DF_Data *)iterator;
1157 struct FontDescrHeader *fdh = NULL;
1158 struct TTextAttr *RememberAttr = NULL;
1159 struct TextFont *tf = NULL;
1160 BPTR olddir = 0, lock, dirlock;
1162 D(bug("DF_IteratorRememberOpen(iterator=0x%lx)\n", iterator));
1164 /* Set current dir and get the Remember TextAttr */
1165 switch (df_data->Type)
1167 case DF_FONTSDATA:
1169 struct FileEntry *rementry = df_data->u.FontsData.RememberFileEntry;
1171 olddir = CurrentDir(rementry->DirEntry->DirLock);
1172 fdh = ReadFontDescr(rementry->FileName, DiskfontBase);
1173 if (rementry->ContentsID == OFCH_ID
1174 && df_data->u.FontsData.RememberIndex == rementry->Numentries - 1)
1176 /* It is the TAttr generated for best matching */
1177 RememberAttr = &rementry->Attrs[df_data->u.FontsData.RememberIndex];
1179 else
1180 RememberAttr = &fdh->TAttrArray[df_data->u.FontsData.RememberIndex];
1182 break;
1184 case DF_FILEDATA:
1185 if (df_data->u.FileData.LastAttr != NULL)
1187 df_data->u.FileData.LastAttr->tta_Name = df_data->u.FileData.OrigName;
1188 df_data->u.FileData.LastAttr = NULL;
1191 RememberAttr = NULL;
1192 lock = Lock(df_data->ReqAttr->tta_Name, ACCESS_READ);
1193 if (lock == NULL)
1195 D(bug("DF_IteratorRememberOpen: Could not lock file\n"));
1196 break;
1199 dirlock = ParentDir(lock);
1200 UnLock(lock);
1201 if (dirlock == NULL)
1203 D(bug("DF_IteratorRememberOpen: Could not get ParentDir\n"));
1204 break;
1206 olddir = CurrentDir(dirlock);
1208 fdh = df_data->u.FileData.FDH;
1209 if (df_data->u.FileData.RememberIndex == fdh->NumEntries)
1210 RememberAttr = &df_data->u.FileData.ExtraAttr;
1211 else
1212 RememberAttr = &fdh->TAttrArray[df_data->u.FileData.RememberIndex];
1213 break;
1216 if (RememberAttr == NULL)
1217 return NULL;
1219 if (fdh != NULL)
1221 D(bug("DF_IteratorRememberOpen: Font Description read\n"));
1223 if (IS_OUTLINE_FONT(RememberAttr))
1225 D(bug("DF_IteratorRememberOpen: loading outline font\n"));
1227 tf = OTAG_ReadOutlineFont(RememberAttr,
1228 df_data->ReqAttr,
1229 fdh->OTagList,
1230 DiskfontBase);
1231 D(bug("DF_IteratorRememberOpen: tf=0x%lx\n", tf));
1234 else
1236 D(bug("DF_IteratorRememberOpen: loading bitmap font\n"));
1238 tf = ReadDiskFont(RememberAttr,
1239 FilePart(df_data->ReqAttr->tta_Name),
1240 DiskfontBase);
1242 D(bug("DF_IteratorRememberOpen: tf=0x%lx\n", tf));
1245 else
1246 D(bug("DF_IteratorRememberOpen: Font Description read failed\n"));
1248 dirlock = CurrentDir(olddir);
1249 switch (df_data->Type)
1251 case DF_FONTSDATA:
1252 FreeFontDescr(fdh, DiskfontBase);
1253 break;
1255 case DF_FILEDATA:
1256 UnLock(dirlock);
1257 break;
1260 if (tf != NULL)
1262 struct DiskFontHeader *dfh;
1264 /* PPaint's personal.font/8 has not set FPF_DISKFONT,
1265 (FPF_ROMFONT neither), but AmigaOS diskfont.library
1266 still shows FPF_DISKFONT set when opening this font */
1268 tf->tf_Flags &= ~FPF_ROMFONT;
1269 tf->tf_Flags |= FPF_DISKFONT;
1271 D(bug("Adding font: %p\n", tf));
1273 /* Forbid() must be called before AddFont, because AddFont clears
1274 tf_Accessors and in the worst case it could happen to us that
1275 after the AddFont() another task opens and closes/frees the
1276 diskfont, before we manage to increase tf_Accessors. */
1278 Forbid();
1280 AddFont(tf);
1281 tf->tf_Accessors++;
1283 dfh = (struct DiskFontHeader *)((UBYTE *)(tf) - (LONG)OFFSET(DiskFontHeader, dfh_TF));
1285 /* Paranoia check */
1286 if (dfh->dfh_FileID == DFH_ID)
1287 ADDTAIL(&DiskfontBase->diskfontlist, &dfh->dfh_DF);
1289 Permit();
1291 D(bug("Font added\n"));
1294 return tf;
1297 /****************************************************************************************/
1299 /*******************/
1300 /* DF_IteratorFree */
1301 /*******************/
1303 /****************************************************************************************/
1305 VOID DF_IteratorFree(APTR iterator, struct DiskfontBase_intern *DiskfontBase)
1307 struct DF_Data *df_data = (struct DF_Data *)iterator;
1309 FreeResources(df_data, DiskfontBase);
1312 /****************************************************************************************/
1314 /*******************/
1315 /* DF_OpenFontPath */
1316 /*******************/
1318 /****************************************************************************************/
1320 struct TextFont *DF_OpenFontPath(struct TextAttr *reqattr, struct DiskfontBase_intern *DiskfontBase)
1322 struct TextFont *tf = NULL;
1323 struct FontDescrHeader *fdh;
1324 BPTR olddir, lock, dirlock;
1326 D(bug("DF_OpenFontPath(reqattr=0x%lx)\n", reqattr));
1328 lock = Lock(reqattr->ta_Name, ACCESS_READ);
1329 if (lock == NULL)
1331 D(bug("DF_OpenFontPath: Could not lock file\n"));
1332 return NULL;
1335 dirlock = ParentDir(lock);
1336 UnLock(lock);
1337 if (dirlock == NULL)
1339 D(bug("DF_OpenFontPath: Could not get ParentDir\n"));
1340 return NULL;
1343 olddir = CurrentDir(dirlock);
1345 fdh = ReadFontDescr(reqattr->ta_Name, DiskfontBase);
1347 if (fdh != NULL)
1349 WORD max_match_weight = 0, match_weight;
1350 LONG match_index = -1;
1351 int i;
1353 D(bug("DF_OpenFontPath: Font Description read\n"));
1355 for (i=0; i<fdh->NumEntries; i++)
1357 match_weight = WeighTAMatch((struct TextAttr *)reqattr,
1358 (struct TextAttr *)&fdh->TAttrArray[i],
1359 fdh->TAttrArray[i].tta_Tags);
1361 if (match_weight > max_match_weight)
1363 max_match_weight = match_weight;
1364 match_index = i;
1368 if (match_index >= 0)
1370 if (IS_OUTLINE_FONT(&fdh->TAttrArray[match_index]))
1372 D(bug("DF_OpenFontPath: loading outline font\n"));
1374 tf = OTAG_ReadOutlineFont(&fdh->TAttrArray[match_index],
1375 (struct TTextAttr *)reqattr,
1376 fdh->OTagList,
1377 DiskfontBase);
1378 D(bug("DF_OpenFontPath: tf=0x%lx\n", tf));
1381 else
1383 D(bug("DF_OpenFontPath: loading bitmap font\n"));
1385 tf = ReadDiskFont(&fdh->TAttrArray[match_index],
1386 reqattr->ta_Name,
1387 DiskfontBase);
1389 D(bug("DF_OpenFontPath: tf=0x%lx\n", tf));
1392 else
1393 D(bug("DF_OpenFontPath: No matching font found\n"));
1395 FreeFontDescr(fdh, DiskfontBase);
1397 else
1398 D(bug("DF_OpenFontPath: Font Description read failed\n"));
1400 CurrentDir(olddir);
1401 UnLock(dirlock);
1403 if (tf != NULL)
1405 struct DiskFontHeader *dfh;
1407 /* PPaint's personal.font/8 has not set FPF_DISKFONT,
1408 (FPF_ROMFONT neither), but AmigaOS diskfont.library
1409 still shows FPF_DISKFONT set when opening this font */
1411 tf->tf_Flags &= ~FPF_ROMFONT;
1412 tf->tf_Flags |= FPF_DISKFONT;
1414 D(bug("Adding font: %p\n", tf));
1416 /* Forbid() must be called before AddFont, because AddFont clears
1417 tf_Accessors and in the worst case it could happen to us that
1418 after the AddFont() another task opens and closes/frees the
1419 diskfont, before we manage to increase tf_Accessors. */
1421 Forbid();
1423 AddFont(tf);
1424 tf->tf_Accessors++;
1426 dfh = (struct DiskFontHeader *)((UBYTE *)(tf) - (LONG)OFFSET(DiskFontHeader, dfh_TF));
1428 /* Paranoia check */
1429 if (dfh->dfh_FileID == DFH_ID)
1430 ADDTAIL(&DiskfontBase->diskfontlist, &dfh->dfh_DF);
1432 Permit();
1434 D(bug("Font added\n"));
1437 return tf;