#if __SASC
#include "snap.h"
#endif

/* Auto: make "CCEXTRA=-wq -qf"
*/

#define SCREENTOP\
   (screen->TopEdge << ((screen->ViewPort.Modes & LACE)? 0: 1))

IMPORT struct SnapRsrc *SnapRsrc;
IMPORT struct IntuitionBase *IntuitionBase;
#if 0
IMPORT struct DiskFontBase *DiskfontBase;
#endif
IMPORT struct Library *	DiskfontBase;

struct Screen *WhichScreen()
{
    REGISTER struct Screen *screen;
    REGISTER ULONG lock;

    lock = LockIBase(0);
    screen = IntuitionBase->FirstScreen;
    while (screen && IntuitionBase->MouseY < SCREENTOP) {
        screen = screen->NextScreen;
    }
    if (screen == NULL) {     /* Shouldn't happen */
        screen = IntuitionBase->ActiveScreen;
    }
    UnlockIBase(lock);
    return screen;
}

struct Window *WhichWindow(screen)
struct Screen *screen;
{
    struct Layer *layer;
    layer = (struct Layer *)WhichLayer(&screen->LayerInfo,
      (LONG)screen->MouseX, (LONG)screen->MouseY);
    if (layer) {
        return (struct Window *)layer->Window;
    } else {
        return NULL;
    }
}

VOID FreePlanes(bm, width, height)
struct BitMap *bm;
LONG width, height;
{
    SHORT i;
    for (i=0; i < bm->Depth; i++) {
        if (bm->Planes[i]) {
            FreeRaster(bm->Planes[i], width, height);
        }
    }
}

WORD AllocPlanes(bm, width, height)
struct BitMap *bm;
LONG width, height;
{
    WORD i;
    for (i=0; i < bm->Depth; i++) {
        bm->Planes[i] = NULL;
    }
    for (i=0; i < bm->Depth; i++) {
        if (!(bm->Planes[i] = AllocRaster(width, height))) {
            return 0;
        }
        BltClear((char *)bm->Planes[i], RASSIZE(width, height), NULL);
    }
    return 1;
}

VOID CacheWindow(struct Window *Win,
                 LONG xoff, LONG yoff,
                 SHORT fw, SHORT fh,
                 struct TextFont *font)
{
    struct CacheWindow *cw;

    if (!(cw = Create(CacheWindow))) {
        return;
    }
    cw->Window = Win;
    cw->xoff = xoff;
    cw->yoff = yoff;
    cw->fw = fw;
    cw->fh = fh;
    cw->font = font;
    AddHead((struct List *)&SnapRsrc->CachedWindows, (struct Node *)cw);
    if (SnapRsrc->CacheSize > 0) {
        --SnapRsrc->CacheSize;
    } else {
        cw = (struct CacheWindow *)RemTail((struct List *)&SnapRsrc->CachedWindows);
        Kill(cw);
    }
}

VOID CacheSync(Font)
struct TextFont *Font;
{
    struct CacheWindow *cw;
    struct CacheWindow *safe;

    SAFEMAPLIST(&SnapRsrc->CachedWindows, struct CacheWindow *, cw, safe) {
        if (cw->font == SnapRsrc->AlternateFont) {
            Remove((struct Node *)cw);
            Kill(cw);
        }
    }
}

struct CacheWindow *GetCachedWindow(Screen, Win)
struct Screen *Screen;
struct Window *Win;
{
    struct CacheWindow *cw;

    MAPLIST(&SnapRsrc->CachedWindows, struct CacheWindow *, cw) {
        if (cw->Window == Win) {
            LONG LockVal = LockIBase(0L);
            REGISTER struct Window *w = Screen->FirstWindow;
            while (w && w != Win) {
                w = w->NextWindow;
            }
            UnlockIBase(LockVal);
            if (!w) {
                return NULL;
            }
            Remove((struct Node *)cw);
            AddHead((struct List *)&SnapRsrc->CachedWindows, (struct Node *)cw);
            return cw;
        }
    }
    return NULL;
}

struct TextFont *SmartOpenFont(ta)
struct TextAttr *ta;
{
    struct TextFont *MemF;
    struct TextFont *DskF = NULL;

    if ((MemF = OpenFont(ta)) && ta->ta_YSize == MemF->tf_YSize) {
        return MemF;
    }

    if (DiskfontBase) {
        DskF = OpenDiskFont(ta);
    }

    if (!MemF) {
        return DskF;
    }
    if (!DskF) {
        return MemF;
    }
    if (abs(ta->ta_YSize - MemF->tf_YSize) <=
        abs(ta->ta_YSize - DskF->tf_YSize)) {
        CloseFont(DskF);
        return MemF;
    }
    CloseFont(MemF);
    return DskF;
}
