

              /*  file  ---  pray to the AmigaDOS god ...  */


#include <libraries/dosextens.h>
#include <exec/memory.h>
#include <ctype.h>
#include <stdio.h>
#include "stuff.h"

#define BUFFERSIZE  256L


               extern  struct    Window      * win        ;
               extern  struct    Screen      * scr        ;
               extern   char               *getFileName ();
               extern  ULONG                   msgclass   ;
               extern  USHORT                  msgcode    ;
               extern    int                   gadcode    ;
               extern  struct   RastPort     * reep       ;
               extern    int                   no_help    ;
               extern  UBYTE                   flubb []   ;
               extern  struct   Gadget         namegad    ,
                                               TGads []   ;
                       char       def_name [50] = "NuIm.h";
                       char       def_dir  [50] = "Ram:"  ;
                       void       messWith ();

    SS FileHandle *out;
    static UBYTE *flubber;

    static struct IntuiText
        sweat = { 2, 1,JAM2, 7, 5, NL, (UB) "OverWrite Existing File:", NL },
        filen = { 2, 1,JAM2, 7,15, NL,  NL, &sweat },
        killr = {22,28,JAM2, 6, 3, NL, (UB) "DO IT!", NL },
        pansy = {28,22,JAM2, 6, 3, NL, (UB) "be nice", NL };


       void
cloze ()                /*  note this works like a microcosm of init ()...  */
{

    if (out)  Close (out);
    if (flubber)  FreeMem (flubber, BUFFERSIZE);
    onInput ();

}


                /*===================SAVE===================*/
       void
save ()
{
    USHORT get_spot (), nz, glob;
    unsigned int over, down, in;
    UBYTE marioBros [128], destroy [99];
    int Zpop ();

#define ZPOP  {ifn(Zpop())return;}
#define TPOP(x) {strcpy(flubber, x "\n");ZPOP;}


    out = NL;
    flubber = NL;
    Mess ("FileName:  <Return> == \"Okay\"");
    offInput ();

    ifn (getFileName (win, scr, "Enter FileName to Get It", def_name, def_dir))
        {  onInput ();  RET;  }

    messWith (marioBros);
    out = Open (marioBros, MODE_OLDFILE);

    if (out)  {
        strcpy (destroy, marioBros);
        strcat (destroy, "?");
        filen.IText = destroy;
        Mess ("L-Amiga-V == DOIT!; -B == be nice");

        ifn (AutoRequest (win, &filen, &killr, &pansy, 0L, 0L, 280L, 60L))  {
            cloze ();  Mess ("Save Cancelled - Wrong FileName");  RET;  }

        Mess ("Bet you didn't know that!");

    }                                     /*  kill hurt destroy stoned ...  */

    cloze ();
    glob = gadzon (TGads [8])? 1: 2;
    out = Open (marioBros, MODE_NEWFILE);
    IFN (out)  { ALERT ("Can't Open File!!!"); cloze ();  RET; }
    Mess ("Saving your Image");
    flubber = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_PUBLIC);
    IFN (flubber)  {  cloze ();  ALERT ("NO CHIP MEMORY!!!");  RET;  }

    if gadzon (TGads [18])  {
TPOP ("\n\n/*  You can edit an \"ni_\" declaration, put it in a bigger file,");
TPOP (    "    change its size, and still load it into PopArt for further");
TPOP (   "    blandishment.  The PopArt loader is simple but effective.");
TPOP (  "    It scans thru a file, looking for \"HITE\", \"WIDT\", and");
TPOP ( "    \" ni_dataName[]=\".  Every time it finds \"HITE\" or \"WIDT\",");
TPOP ("    it scans to '(' and extracts the following number.  It knows");
TPOP ("    the difference between a decimal and a hex, and they both must");
TPOP ("    end with ','.  It ignores any line containing \"plane\", and it");
TPOP ("    stops reading \" ni_dataName[]=\" when it encounters \"end of\".");
TPOP ("    It can't deal with data edited to use PlanePick and PlaneOnOff  */");  }

    strcpy (flubber, "\n\n#define ");
    strcat (flubber, flubb);
    strcat (flubber, "SIZE ((long)sizeof(");
    strcat (flubber, flubb);
    strcat (flubber, "))\n");
    ZPOP;
    strcpy (flubber, "#define ");
    strcat (flubber, flubb);
    strcat (flubber, "WIDT (");
    ZPOP;
    decimal (32 * glob, flubber);
    strcat (flubber, ")\n");
    ZPOP;

    strcpy (flubber, "#define ");
    strcat (flubber, flubb);
    strcat (flubber, "HITE (");
    ZPOP;
    decimal (20 * glob, flubber);
    strcat (flubber, ")\n");
    ZPOP;
    strcpy (flubber, "#define DO");
    strcat (flubber, flubb);
    strcat (flubber, "(x,y) popChip(");
    strcat (flubber, flubb);
    strcat (flubber, ",");
    strcat (flubber, flubb);
    strcat (flubber, "SIZE,");
    strcat (flubber, flubb);
    strcat (flubber, "WIDT,");
    strcat (flubber, flubb);
    strcat (flubber, "HITE,x,y)\n");
    ZPOP;

    strcpy (flubber, "\nUSHORT *");
    strcat (flubber, flubb);
    strcat (flubber, "Chip;\n");
    ZPOP;
    strcpy (flubber, "\nUSHORT ");
    strcat (flubber, flubb);
    strcat (flubber, "[]={");
    ZPOP;

    LOOP (in = 0;  in < 5 ;  ++in)  {
        strcpy (flubber, "/* plane ");
        ZPOP;
        strcat (decimal (in + 1, flubber), ", ");
        strcat (flubber, flubb);
        strcat (flubber, " */\n\t");
        ZPOP;

        loop (nz=8, down=PixDown;  down<PixDown+MaxDN*glob/2; ++down)  {
            loop (over=PixOver; over<=PixOver+ImageWid*glob/2-1; over+=16)  {
                char number [16];

                if gadzon (TGads[23])  
                    decimal (get_spot(reep,over,down,in),flubber); 
                else  {
                    strcpy(flubber, "0x0000");
                    hex(get_spot(reep,over,down,in),number);
                    strcpy (&flubber [6 - strlen (number)], number);  }
                    
                strcat (flubber, ",");
                ZPOP;
                ifn(--nz) { strcpy(flubber,"\n\t"); nz=8;             ZPOP; }
            }
        }/*handsupeveryonewhothinksthisispreferabletohavingyourfingersdropofffromtypingtomuch*/

    }                                           /*  looping thru the spots  */

    strcpy (flubber, "}; /* end of ");
    strcat (flubber, flubb);
    strcat (flubber, " image data */\n");
    ZPOP;
    cloze ();
    Mess ("Image Saved");

}                                                          /*  end of save  */


Zpop ()
{
    REG long Qscreen;

    Qscreen = Write (out, flubber, (long) strlen (flubber));

    if (Qscreen != (long) strlen (flubber))  {
        cloze ();  ALERT ("Error Writing File!!!");  return 0;  }

    return 1;

}


                                USHORT
get_spot (reep, xx, yy, plane)  ST RastPort *reep;
{
    REG unsigned int it;
    REG USHORT thing = 0;
    REG UBYTE pixC;


    loop (it = 0; it < 16; ++it)  {
        pixC = (UBYTE) ReadPixel (reep, (long) xx + it, (long) yy);
        if ( (pixC >> plane) & 0x01 )  thing |= 0x8000 >> it;
    }                      /*  end of scan-thru-one-USHORT's-worth-of-dots  */

    return thing;

}                 /*  is it safe to look this up thru the rastport bitmap?  */


                /*===================LOAD===================*/

#define ALLOCSIZE  ((MaxUP * MaxDN * 5L + 10L) * sizeof (USHORT))
#define ARRAYSIZE  ((MaxUP * MaxDN * 5L))

    FILE *in;
    USHORT *imagine;

       void
load ()
{
    char line [128], *liner, example [75], realname [56];
    UBYTE marioBros [128];
    int hite = 40, widt = 4*16, foundit = 0;
    USHORT *stuff = NL;


    in = NL;
    imagine = NL;
    Mess ("Change Data Name to Name to Read!");
    offInput ();

    ifn (getFileName (win, scr, "Enter FileName to Grab", def_name, def_dir))
        {  Rcloze ();  RET;  }

    ifn (stuff = imagine = (USHORT*) AllocMem (ALLOCSIZE, MEMF_CLEAR))  {
        ALERT ("Low Memory!  Help!");  Rcloze ();  RET;  }

    messWith (marioBros);

    ifn (in = fopen (marioBros, "r"))  {
        ALERT ("Error Opening File!!");  Rcloze ();  RET;  }

    strcpy (example, "Loading ");
    strcat (example, marioBros);
    strcat (example, "->");
    strcat (example, flubb);
    Mess (example);
    strcpy (example, "DO");
    strcat (example, flubb);
    strcpy (realname, " ");
    strcat (realname, flubb);
    strcat (realname, "[]=");

    while (fgets (line, 127, in))  {
        if (findstr (line, "HITE") && !findstr (line, example))
            hite = findnum (line, hite);

        if (findstr (line, "WIDT") && !findstr (line, example))  {
            widt = findnum (line, widt);
            if (findstr (line, "2*16"))  widt = 2*16;
            if (findstr (line, "4*16"))  widt = 4*16;  }

        if (findstr (line, realname))  {
            foundit = 1;

            while (fgets (line, 127, in))  {
                if (findstr (line, "plane"))  continue;
                if (findstr (line, "end of"))  break;
                liner = line;
nxnum:          while (!isdigit (*liner) && *liner)  ++liner;
                ifn (*liner)  continue;

                if (liner [0] == '0' && tolower (liner [1]) == 'x')
                      *stuff =  hexToUshort (&liner [2]);
                else  *stuff = (USHORT) atoi (liner);

                while (*liner != ',' && *liner)  ++liner;
                if (++stuff >= &imagine [ARRAYSIZE])  break;
                ifn (*liner)  continue;
                goto nxnum;  }
                
            break;  }

    }                     /*  the less said about such nonsense the better  */

    ifn (foundit)  {  Mess ("Data Item Not Found!!!");  Rcloze ();  RET;  }
    SetAPen (reep, 0L);

    RectFill (reep, (long) PixOver,            (long) PixDown,
                    (long) PixOver + ImageWid, (long) PixDown + MaxDN);

    popChip (imagine, ALLOCSIZE, widt, hite, PixOver, PixDown);
    suck ();
    redrawWorkArea (0);
    Rcloze ();

}                                                          /*  end of load  */


              void
saveColors ()
{
    USHORT nz = 12;
    unsigned int in;
    UBYTE marioBros [128], destroy [99];
    int Zpop ();

#define ZPOP  {ifn(Zpop())return;}


    out = NL;
    flubber = NL;
    Mess ("FileName:  <Return> == \"Okay\"");
    offInput ();

    ifn (getFileName (win, scr, "Enter FileName to Get Colors", def_name, def_dir))
        {  onInput ();  RET;  }

    messWith (marioBros);
    out = Open (marioBros, MODE_OLDFILE);

    if (out)  {
        strcpy (destroy, marioBros);
        strcat (destroy, "?");
        filen.IText = destroy;
        Mess ("L-Amiga-V == DOIT!; -B == be nice");

        ifn (AutoRequest (win, &filen, &killr, &pansy, 0L, 0L, 280L, 60L))  {
            cloze ();  Mess ("Save Cancelled - Wrong FileName");  RET;  }

        Mess ("Bet you didn't know that!");

    }

    cloze ();
    out = Open (marioBros, MODE_NEWFILE);
    IFN (out)  { ALERT ("Can't Open File!!!"); cloze ();  RET; }
    Mess ("Saving your Colors");
    flubber = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_PUBLIC);
    IFN (flubber)  {  cloze ();  ALERT ("NO CHIP MEMORY!!!");  RET;  }

    strcpy (flubber, "\n#define ");
    strcat (flubber, flubb);
    strcat (flubber, "COLORS(vp) LoadRGB4((vp),");
    strcat (flubber, flubb);
    strcat (flubber, "CMAP,32L)\n");
    ZPOP;
    strcpy (flubber, "\nUWORD ");
    strcat (flubber, flubb);
    strcat (flubber, "CMAP[]={\n\t");
    ZPOP;

    LOOP (in = 0;  in < 32 ;  ++in)  {  char number [16];
        strcpy (flubber, "0x000");
        hex ((int) GetRGB4 (scr->ViewPort.ColorMap, (long) in), number);
        strcpy (&flubber [5 - strlen (number)], number);
        strcat (flubber, ",");
        ZPOP;
        ifn (--nz)  {  strcpy (flubber, "\n\t");  nz = 12;            ZPOP; }

    }

    strcpy (flubber, "\n}; /* end of ");
    strcat (flubber, flubb);
    strcat (flubber, "CMAP */\n");
    ZPOP;
    cloze ();
    Mess ("Colors Saved");

}                                                    /*  end of saveColors  */


              void
loadColors ()
{
    char line [128], *liner, example [75], realname [56];
    UBYTE marioBros [128];
    int stuff, hite = 40, widt = 4*16, foundit = 0;
    UWORD cmap [32];
    long pragma = 0;


    in = NL;
    imagine = NL;
    Mess ("Change Data Name to Name to Read!");
    offInput ();
    stuff = 0;

    ifn (getFileName (win, scr, "Enter FileName to Load Colors", def_name, def_dir))
        {  Rcloze ();  RET;  }

    messWith (marioBros);

    ifn (in = fopen (marioBros, "r"))
        {  ALERT ("Error Opening File!!");  Rcloze ();  RET;  }

    strcpy (example, "Loading ");
    strcat (example, marioBros);
    strcat (example, "->");
    strcat (example, flubb);
    strcat (example, "CMAP");
    Mess (example);
    strcpy (example, "DO");
    strcat (example, flubb);
    strcpy (realname, " ");
    strcat (realname, flubb);
    strcat (realname, "CMAP[]=");

    while (fgets (line, 127, in))  {
        if (findstr (line, realname))  {
            foundit = 1;

            while (fgets (line, 127, in))  {
                liner = line;
nxnum:          while (!isdigit (*liner) && *liner)  ++liner;
                ifn (*liner)  continue;

                if (liner [0] == '0' && tolower (liner [1]) == 'x')
                      cmap [stuff] =  hexToUshort (&liner [2]);
                else  cmap [stuff] = (USHORT) atoi (liner);

                while (*liner != ',' && *liner)  ++liner;
                if (++stuff >= 32)  break;
                ifn (*liner)  continue;
                goto nxnum;  }

            break;  }
            
    }                                       /*  end of while-therez- lines  */

    ifn (foundit)  {  Mess ("Data Item Not Found!!!");  Rcloze ();  RET;  }
    SetAPen (reep, 0L);
    Rcloze ();
    if (++stuff > 32)  stuff = 32;
    LoadRGB4 (&(scr->ViewPort), cmap, (long) stuff);
    Mess ("New Colors Loaded");

}                                                    /*  end of loadColors  */



         void
Rcloze ()
{

    if (in)  fclose (in);
    if (imagine)  FreeMem (imagine, ALLOCSIZE);
    onInput ();
    in = 0;
    imagine = 0;

}


            void
increment ()
{

    inky (flubb, 9);
    RefreshGadgets (&namegad, win, (long) NL);
    inky (def_name, 31);

}


inky (dunk, size)       char *dunk;
{
    int numat, numiz;
    char cat [128], *boid, dink [128];


    strcpy (dink, dunk);
    if ((numat = hazNum (dink)) == -1)  numat = izIn (dink, '.');
    numiz = atoi (&dink [numat]);
    strcpy (cat, &dink [numat]);
    boid = cat;
    while (*boid && boid < &cat [127] && isdigit (*boid))  ++boid;
    dink [numat] = 0;
    decimal (++numiz, &dink [numat]);
    strcat (dink, boid);
    strncpy (dunk, dink, size);

}                    /*  parsers have got to be the ugliest code around...  */


                char *
decimal (it, s)  unsigned int it;  char *s;
{
    REG int v;
    REG char *p;
    long pwr10 ();


    loop (v = 7;  v > -1;  --v)  s [7 - v] = '0' + ( it/pwr10(v) ) % 10;
    s [8] = 0;
    p = s;
    while (p [0] == '0' && p [1] != 0)  ++p;
    if (p != s)  strcpy (s, p);
    return s;

}


          long
pwr10 (x)
{
    REG long r = 10;


    if (x == 0)  return 1;
    while (--x)  r *= 10;
    return r;

}


    static char table [] = "0123456789abcdef";

             char *
hex (it, s)  char *s;
{
    REG int v;
    REG char *p;


    loop (v = 3;  v > -1;  --v)  s [3 - v] = table [(it >> (v * 4)) & 0xf];
    s [4] = 0;
    p = s;
    while (p [0] == '0' && p [1] != 0)  ++p;
    if (p != s)  strcpy (s, p);
    return s;

}

          
                USHORT
hexToUshort (s)  char *s;
{
    REG USHORT g = 0;
    REG int v = 0, k, q;


    while (!isxdigit (*s) && *s)  ++s;
    ifn (*s)  return 0;
    while ( isxdigit (s [  v]))  ++v;
    if    (!isxdigit (s [--v]))  return 0;

    loop (q = v;  v >= 0;  --v)  {  
        k = 0;
        while (table [k] != tolower (s [v]) && k < 16)  ++k;
        g |= k << ((q - v) * 4);  }

    return g;

}


                    void
messWith (marioBros)  char *marioBros;
{

    marioBros [0] = 0;                             /*  no '\000' bullshit!  */

    if (izIn (def_name, ':') >= strlen (def_name))  {
        strcpy (marioBros, def_dir);

        if (def_dir [strlen (def_dir)-1] != ':' &&
            def_dir [strlen (def_dir)-1] != '/')  strcat (marioBros, "/");  }

    strcat (marioBros, def_name);

}      /*  allow part of path and filename in dir and name, or all in name  */


hazNum (s)  char *s;
{
    REG int reggae = 0;


    while (*s)  {  if (isdigit (*s))  return reggae; ++reggae,  ++s; }
    return -1;

}                                                /*  I love C ... I need C  */


izIn (s, d)  char *s, d;
{
    REG int reggae = 0;


    while (*s)  { if (*s == d)  break;   ++s, ++reggae;  }
    return reggae;

}                                 /*  return location of d, or length of s  */


findstr (a, b)  char *a, *b;
{

    while (*a && *a != *b)  ++a;
    ifn (*a)  return 0;
    while (*a == *b && *a && *b)  ++a, ++b;
    return !*b;

}                                    /*  return a boolean for if b is in a  */


findnum (a, defalt)  char *a;
{

    while (*a  !=  '('   && *a)  ++a;
    while (!isdigit (*a) && *a)  ++a;
    ifn (*a)  return defalt;
    return atoi (a);

}

