#include <dos/dos.h>
#include <dos/rdargs.h>
#include <exec/libraries.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>

#define __USE_SYSBASE
#define REG(x)  register __## x
#define LVOText -0x3C

/* Much easier to define function pointer variables, and do type-casting this way. */
typedef void __asm (*text)(REG(a1) struct RastPort *, REG(a0) STRPTR, REG(d0) WORD, REG(a6) struct Library *);

/* Global function pointer */
text            gfx_Text;

static const STRPTR version = "\0$VER: OutlineFont 1.3 "__AMIGADATE__" Nyberg,Gapen,Rotvel";
static const STRPTR programName = "OutlineFont";
static const STRPTR template = "FRONTPEN/N/A,BACKPEN/N/A,OUTLINEWIDTH/N/A,SHADOW/S";

__far LONG fgpen, bgpen, owidth;
__far BOOL shadow;

void __asm __saveds
of_Text(REG(a1) struct RastPort *rp,
        REG(a0) STRPTR str,
        REG(d0) WORD len,
        REG(a6) struct Library *base)
{
    int x,y;
    struct Task *task;
    UBYTE *nstr;
    
    task = FindTask(NULL);
    nstr = task->tc_Node.ln_Name;
    if( nstr[0]=='W' && nstr[3]=='k' && nstr[4]=='b' && nstr[8]=='h' )
    {
        if( GetAPen(rp)==fgpen && GetDrMd(rp)==JAM1 )
        {
            x=rp->cp_x;
            y=rp->cp_y;
        
            SetAPen(rp,bgpen);

            Move(rp,x+owidth,y+owidth);
            (*gfx_Text)(rp,str,len,base);

            if (shadow == FALSE)
            {
                Move(rp,x-owidth,y-owidth);
                (*gfx_Text)(rp,str,len,base);
        
                Move(rp,x+owidth,y-owidth);
                (*gfx_Text)(rp,str,len,base);
        
                Move(rp,x-owidth,y+owidth);
                (*gfx_Text)(rp,str,len,base);
            }
            SetAPen(rp,fgpen);
        
            Move(rp,x,y);
            (*gfx_Text)(rp,str,len,base);
        }
        else (*gfx_Text)(rp,str,len,base);
    }
    else (*gfx_Text)(rp,str,len,base);
}

ULONG main(void)
{
    struct RDArgs *args, *argptr;
    LONG opts[4] = { 0, 0, 0, 0, };
    
    /* Read program arguments with AmigaDOS ReadArgs() */
    if( args = AllocDosObject(DOS_RDARGS, NULL) )
    {
        if( argptr = ReadArgs(template, opts, args) )
        {
            if (opts[0]) fgpen  = *((LONG *) opts[0]);
            if (opts[1]) bgpen  = *((LONG *) opts[1]);
            if (opts[2]) owidth = *((LONG *) opts[2]);
            if (opts[3]) shadow = opts[3]; 
            FreeArgs(argptr);
        }
        else 
        {
            PrintFault(IoErr(), programName);
            return RETURN_ERROR;
        }
        FreeDosObject(DOS_RDARGS, args);

        /* Patch graphics.library/Text() */
        gfx_Text = (text)SetFunction((struct Library *)GfxBase, LVOText, (APTR)of_Text);
    
        /* Wait for ctrl-c */
        Wait(SIGBREAKF_CTRL_C);

        /* Unpatch */
        SetFunction((struct Library *)GfxBase, LVOText, (APTR)gfx_Text);
    }
    else 
    {
        PrintFault(IoErr(), programName);
        return RETURN_ERROR;
    }
    return RETURN_OK;
}
