/* * Copyright 2014 Chris Young * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Compatibility functions for AmigaOS 3 */ #ifndef __amigaos4__ #include "os3support.h" #include #include #include #include #include #include #include #include #include #include #include #include "utils/log.h" #define SUCCESS (TRUE) #define FAILURE (FALSE) #define NO ! ULONG __slab_max_size = 4096; /* Enable clib2's slab allocator */ /* Diskfont */ struct OutlineFont *OpenOutlineFont(STRPTR fileName, struct List *list, ULONG flags) { BPTR fh = 0; int64 size = 0; struct TagItem *ti; UBYTE *buffer; STRPTR fname, otagpath, fontpath; struct BulletBase *BulletBase; struct OutlineFont *of = NULL; struct GlyphEngine *gengine; char *p = 0; struct FontContentsHeader fch; if(p = strrchr(fileName, '.')) *p = '\0'; fontpath = (STRPTR)ASPrintf("FONTS:%s.font", fileName); fh = Open(fontpath, MODE_OLDFILE); if(fh == 0) { LOG("Unable to open FONT %s", fontpath); FreeVec(fontpath); return NULL; } if(Read(fh, &fch, sizeof(struct FontContentsHeader)) != sizeof(struct FontContentsHeader)) { LOG("Unable to read FONT %s", fontpath); FreeVec(fontpath); Close(fh); return NULL; } Close(fh); if(fch.fch_FileID != OFCH_ID) { LOG("%s is not an outline font!", fontpath); FreeVec(fontpath); return NULL; } otagpath = (STRPTR)ASPrintf("FONTS:%s.otag", fileName); fh = Open(otagpath, MODE_OLDFILE); if(p) *p = '.'; if(fh == 0) { LOG("Unable to open OTAG %s", otagpath); FreeVec(otagpath); return NULL; } size = GetFileSize(fh); buffer = (struct TagItem *)AllocVec(size, MEMF_ANY); if(buffer == NULL) { LOG("Unable to allocate memory"); Close(fh); FreeVec(otagpath); return NULL; } Read(fh, buffer, size); Close(fh); /* The first tag is supposed to be OT_FileIdent and should equal 'size' */ struct TagItem *tag = (struct TagItem *)buffer; if((tag->ti_Tag != OT_FileIdent) || (tag->ti_Data != (ULONG)size)) { LOG("Invalid OTAG file"); FreeVec(buffer); FreeVec(otagpath); return NULL; } /* Relocate all the OT_Indirect tags */ while (ti = NextTagItem(&tag)) { if(ti->ti_Tag & OT_Indirect) { ti->ti_Data += buffer; } } /* Find OT_Engine and open the font engine */ if(ti = FindTagItem(OT_Engine, buffer)) { LOG("Using font engine %s", ti->ti_Data); fname = ASPrintf("%s.library", ti->ti_Data); } else { LOG("Cannot find OT_Engine tag"); FreeVec(buffer); FreeVec(otagpath); return NULL; } BulletBase = OpenLibrary(fname, 0L); if(BulletBase == NULL) { LOG("Unable to open font engine %s", fname); FreeVec(buffer); FreeVec(fname); FreeVec(otagpath); } FreeVec(fname); gengine = OpenEngine(); SetInfo(gengine, OT_OTagPath, otagpath, OT_OTagList, buffer, TAG_DONE); of = AllocVec(sizeof(struct OutlineFont), MEMF_CLEAR); if(of == NULL) return NULL; of->BulletBase = BulletBase; of->GEngine = gengine; of->OTagPath = otagpath; of->olf_OTagList = buffer; return of; } void CloseOutlineFont(struct OutlineFont *of, struct List *list) { struct BulletBase *BulletBase = of->BulletBase; CloseEngine(of->GEngine); CloseLibrary(BulletBase); FreeVec(of->OTagPath); FreeVec(of->olf_OTagList); FreeVec(of); } /* DOS */ int64 GetFileSize(BPTR fh) { int32 size = 0; struct FileInfoBlock *fib = AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY); if(fib == NULL) return 0; ExamineFH(fh, fib); size = fib->fib_Size; FreeVec(fib); return (int64)size; } void FreeSysObject(ULONG type, APTR obj) { switch(type) { case ASOT_PORT: DeleteMsgPort(obj); break; case ASOT_IOREQUEST: DeleteIORequest(obj); break; } } /* Exec */ struct Node *GetHead(struct List *list) { struct Node *res = NULL; if ((NULL != list) && (NULL != list->lh_Head->ln_Succ)) { res = list->lh_Head; } return res; } struct Node *GetPred(struct Node *node) { if (node->ln_Pred->ln_Pred == NULL) return NULL; return node->ln_Pred; } struct Node *GetSucc(struct Node *node) { if (node->ln_Succ->ln_Succ == NULL) return NULL; return node->ln_Succ; } /* Intuition */ uint32 GetAttrs(Object *obj, Tag tag1, ...) { va_list ap; Tag tag = tag1; ULONG data = 0; int i = 0; va_start(ap, tag1); while(tag != TAG_DONE) { data = va_arg(ap, ULONG); i += GetAttr(tag, obj, (void *)data); tag = va_arg(ap, Tag); } va_end(ap); return i; } ULONG RefreshSetGadgetAttrsA(struct Gadget *g, struct Window *w, struct Requester *r, struct TagItem *tags) { ULONG retval; BOOL changedisabled = FALSE; BOOL disabled; if (w) { if (FindTagItem(GA_Disabled,tags)) { changedisabled = TRUE; disabled = g->Flags & GFLG_DISABLED; } } retval = SetGadgetAttrsA(g,w,r,tags); if (w && (retval || (changedisabled && disabled != (g->Flags & GFLG_DISABLED)))) { RefreshGList(g,w,r,1); retval = 1; } return retval; } ULONG RefreshSetGadgetAttrs(struct Gadget *g, struct Window *w, struct Requester *r, Tag tag1, ...) { return RefreshSetGadgetAttrsA(g,w,r,(struct TagItem *) &tag1); } APTR NewObject(struct IClass * classPtr, CONST_STRPTR classID, ULONG tagList, ...) { return NewObjectA(classPtr, classID, (const struct TagItem *) &tagList); } /* Utility */ struct FormatContext { STRPTR Index; LONG Size; BOOL Overflow; }; STATIC VOID ASM StuffChar( REG(a3, struct FormatContext * Context), REG(d0, UBYTE Char)) { /* Is there still room? */ if(Context->Size > 0) { (*Context->Index) = Char; Context->Index++; Context->Size--; /* Is there only a single character left? */ if(Context->Size == 1) { /* Provide null-termination. */ (*Context->Index) = '\0'; /* Don't store any further characters. */ Context->Size = 0; } } else { Context->Overflow = TRUE; } } BOOL VSPrintfN( LONG MaxLen, STRPTR Buffer, const STRPTR FormatString, const va_list VarArgs) { BOOL result = FAILURE; /* format a text, but place only up to MaxLen * characters in the output buffer (including * the terminating NUL) */ if (Buffer == NULL || FormatString == NULL) return(result); if(MaxLen > 1) { struct FormatContext Context; Context.Index = Buffer; Context.Size = MaxLen; Context.Overflow = FALSE; RawDoFmt(FormatString,(APTR)VarArgs,(VOID (*)())StuffChar,(APTR)&Context); if(NO Context.Overflow) result = SUCCESS; } return(result); } BOOL SPrintfN( LONG MaxLen, STRPTR Buffer, const STRPTR FormatString, ...) { va_list VarArgs; BOOL result = FAILURE; /* format a text, varargs version */ if (Buffer == NULL && FormatString == NULL) return result; va_start(VarArgs,FormatString); result = VSPrintfN(MaxLen,Buffer,FormatString,VarArgs); va_end(VarArgs); return(result); } char *ASPrintf(const char *fmt, ...) { int r; va_list ap; static char buffer[2048]; char *rbuf; va_start(ap, fmt); r = VSPrintfN(2048, buffer, (const STRPTR)fmt, ap); va_end(ap); r = strlen(buffer); rbuf = AllocVec(r+1, MEMF_CLEAR); if (rbuf != NULL) { strncpy(rbuf, buffer, r); } return rbuf; } /* C */ char *strlwr(char *str) { size_t i; size_t len = strlen(str); for(i=0; i