

                /*  art  ---  play around with dots...  */


#include <graphics/gfxmacros.h>
#include "stuff.h"

#define PIXI        Ratio
#define MAXWID      MaxUP

#define INSIDE(x,j) ((x) >= 36 && (x) < 36 + ImageWid * PIXI && \
                     (j) >= 21 && (j) < 21 + MaxDN * PIXI)


               extern  ULONG                   msgclass   ;
               extern  USHORT                  msgcode    ;
               extern    int                   gadcode    ;
               extern  struct   Gadget         TGads []   ;
               extern  struct   RastPort     * reep       ;
               extern    int                   no_help    ;
               extern  UWORD                   mrQ        ;
               extern  struct  SUPERwindow SuperWindows [];
               extern    int               CurrentWindow  ;
               extern    int                    bloking   ;
                       struct  Window         * win       ;
                       ULONG                   thisCol = 1;
                       USHORT                   Mx, My    ;
                       USHORT                   izDn      ;
                         int                webefillin = 0;
                         int                  curOnion = 0;
                         int                  togOnion = 1;
                         int                   picking     ;

               void     maybedospotat (),  maybedospot  (),
                      dospot (),  dumb_gadgets (), doKeys ();


      void
art ()
{

    SWITCH  (msgclass)   {
        CS  MOUSEBUTTONS :  switch (msgcode)  {
          CS SELECTDOWN  :  if (izShift (mrQ) && INSIDE (Mx, My))
                                                {  doBox ();           RET;  }
                            ifn (webefillin)  izDn = 1, maybedospotat ();  RET;
          CS  SELECTUP   :  izDn=0; if (webefillin) fill(); new_title ();  RET;
          CS   MENUUP    :  gadcode = PICKG;      dumb_gadgets ();     RET; }
                RET;

        CS  MOUSEMOVE    :  if (izDn)  maybedospotat ();  no_help = 0; RET;
        CS  GADGETUP     :  if (  gadcode > 32 )  {  dumb_gadgets () ; RET; }
                            new_color (gadcode % 32L);                 RET;
        CS  RAWKEY       :  doKeys ();                                 RET;
    }

}  /*  end of art.  In the words of Mark Knopfler,
                                "they never gave us no money - no breaks"!  */


         void
doKeys ()
{
    ULONG bink;


    if (msgcode < 76 || msgcode > 79) {       /*  if it's not an arrow key  */
        switch (msgcode)  {
            case 53:  gadcode = BLOKG;  break;
/*            case 54:  gadcode = NEW_G;  break;  it shouldn't be this easy */
            case 33:  gadcode = SAVEG;  break;
            case 40:  gadcode = LOADG;  break;
            case 51:  gadcode = CLONG;  break;
            case 23:  gadcode = INC_G;  break;
            case 35:  gadcode = FILLG;  break;
            case 49:  gadcode = COPYG;  break;
            case 22:  gadcode = UNDOG;  break;
            case 20:  gadcode = STAKG;  break;
            case 19:  gadcode = ROLLG;  break;
            case 16:  gadcode = SEQ_G;  break;
            case 24:  gadcode = ONIOG;  break;
            case 25:  gadcode = POP_G;  break;
            default:  return;  }

        dumb_gadgets ();
        return;  }

    bink = thisCol;

    switch (msgcode)  {
        case 76:  --bink;  break;
        case 77:  ++bink;  break;
        case 78:  if (bink < 16)  bink += 16;  break;
        case 79:  if (bink > 15)  bink -= 16;  break;  }

    if (bink < 0)  bink += 32; else if (bink > 31)  bink %= 32;
    new_color (bink);

}                                           /* the mysteries of finite math */


                void
maybedospotat ()
{
    REG USHORT i, j, x = Mx - Mx % PIXI,  y = My - My % PIXI;


    ifn (INSIDE (Mx, My))   return;
    ifn (bloking)  {  maybedospot (x, y);  return;  }

    LOOP     ( i = x - bloking * PIXI;  i < x + bloking;  i += PIXI )
        loop ( j = y - bloking * PIXI;  j < y + bloking;  j += PIXI )
                   if INSIDE (i, j)  maybedospot (i, j);

}


                      void
maybedospot (atx, aty)   USHORT atx, aty;                        /* uh huh  */
{
    REG UBYTE x = (int) (atx - 35) / PIXI, y = (int) (aty - 20) / PIXI;

#define even(x) ((x)%2)
#define  odd(x) (!even(x))                                      /*  duh...  */


    if (!gadzon (TGads [ 1 ]) && !gadzon (TGads [ 2 ]))  {
        dospot (atx, aty, x, y);                                RET;  }

    if (gadzon (TGads [ 2 ]))  {
        if ((even (x) && odd (y)) || (odd (x) && even (y)))
            dospot (atx, aty, x, y);                            RET; }

    if  ((odd (x) && odd (y)) || (even (x) && even (y)))
            dospot (atx, aty, x, y);
            
}                                     /*  end of maybedospot ... maybe ... */


                                void
dospot ( x, y, imageX, imageY )      USHORT  x, y; UBYTE   imageX, imageY;
{
    ULONG spot;
    extern int popping;


    spot = popping && curOnion != CurrentWindow?
        ReadPixel (zreep (curOnion), imageX + 4L, imageY + 14L): thisCol;

    SetAPen (zreep (CurrentWindow), spot);
    SetAPen (reep, spot);

    IFN ( reep->DrawMode & COMPLEMENT )
        WritePixel (reep, (long) (imageX+PixOver), (long) (imageY+PixDown)),
        WritePixel (zreep (CurrentWindow), imageX +  4L, imageY + 14L);

    RectFill (reep, x - 1L, y - 1L, x + PIXI - 2L, y + PIXI - 2L);

    if (togOnion && !popping)  {
        spot = (long) ReadPixel (zreep (curOnion), imageX + 4L, imageY + 14L);

        if (spot != thisCol)  {
            SetAPen (reep, spot);
            WritePixel (reep, (long) x, (long) y);
            SetAPen (reep, (long) thisCol);  }

    }

}                                                   /* dismal end of dospot */


        void
suck ()                       /*  copy the working image into a new window  */
{

    ClipBlit (reep, (long) PixOver, (long) PixDown,
             zreep (CurrentWindow), 4L, 14L, (long) ImageWid,
                                        (long) MaxDN, (long) 0xc0);

}                                                    /*  one suck later...  */


        void
blow ()                    /*  copy a window image into the working images  */
{

    ClipBlit (zreep (CurrentWindow), 4L, 14L,
               reep, (LONG) PixOver,  (LONG) PixDown,
                     (LONG) ImageWid, (LONG) MaxDN, (LONG) 0xc0);

    redrawWorkArea (0);

}       /*  sorry about the names.  You gotta admit they jog the memory...  */


        void
copy ()                    /*  copy the working image into the undo buffer  */
{

    ClipBlit (reep, (LONG) PixOver,  (LONG) PixDown,
              reep, (LONG) UbfOver,  (LONG) UbfDown,
                    (LONG) ImageWid, (LONG) MaxDN, (LONG) 0xc0);

}                                          /*  long long long long long...  */


        void
undo ()                        /*  copy the buffer back the working images  */
{

    ClipBlit (reep, (LONG) UbfOver,  (LONG) UbfDown,
              reep, (LONG) PixOver,  (LONG) PixDown,
                    (LONG) ImageWid, (LONG) MaxDN, (LONG) 0xc0);

    suck ();
    redrawWorkArea (0);

}                                     /*  long long long long long long...  */


              void
newOnion (it)
{
    REG LONG rX, rY, spot;
        LONG XX, YY, wasspot = thisCol;


    if (curOnion == CurrentWindow || !togOnion)  return;
    Mess ("Redrawing shadow area...");
    offInput ();

    LOOP   (rX = 36, XX = 4L;  rX < 36 + ImageWid * Ratio;  rX += Ratio, ++XX)
        loop (rY = 21, YY = 14L;  rY < 21 + MaxDN * Ratio;  rY += Ratio, ++YY)  {
            spot = (long) ReadPixel (zreep (it), XX, YY);
            if (spot != wasspot)  SetAPen (reep, wasspot = spot);
/*          if (spot != ReadPixel (reep, rX, rY))  */
            WritePixel (reep, rX, rY);  }

    SetAPen (reep, (long) thisCol);
    Mess ("Finished Reshadowing");
    onInput ();

}

                     void
redrawWorkArea (total)
{
    REG LONG realX, realY, spot;      /*  "real" meaning the working image  */
        LONG XX, YY, wasspot = thisCol;


    Mess ("Redrawing work area...");
    offInput ();                              /*  turn off mouse reporting  */

    LOOP (realX = 35, XX = PixOver;
          realX < 35 + ImageWid * Ratio;
          realX += Ratio, ++XX)

        loop (realY = 20, YY = PixDown;
              realY < 20 + MaxDN * Ratio;
              realY += Ratio, ++YY)  {

            spot = (long) ReadPixel (reep, XX, YY);
            if (spot != wasspot)  SetAPen (reep, wasspot = spot);

            if (total || spot != ReadPixel (reep, realX, realY))
                RectFill (reep, realX, realY, realX+PIXI-1L, realY+PIXI-1L);

        }                                       /*  looping thru the spots  */

    SetAPen (reep, (long) thisCol);
    Mess ("Finished Redrawing");
    onInput ();
    if (togOnion)  newOnion (curOnion);

}


             void
flash_blok ()                            /*  complement the mouse location  */
{
    static USHORT patsy [] = { 0x5555, 0xaaaa };


    SetDrMd (reep, COMPLEMENT);
    SetAfPt (reep, patsy, 1L);
    maybedospotat ();
    SetAfPt (reep, NULL, 0L);
    SetDrMd (reep, JAM2);

}


                void
dumb_gadgets ()                                      /*  title says all...  */
{

    SWITCH (gadcode)  {  extern struct Window *seqwin;
        CS  BLOKG  :  blokOnOff ();                                     RET;
        CS  NEW_G  :  anim (&TGads  [3]);   new ();                     RET;
        CS  PICKG  :                       pick ();  input ();          RET;
        CS  SAVEG  :  if izCtrl (mrQ)  increment ();  else  anim (&TGads [ 5]);
                      save ();                                          RET;
        CS  LOADG  :  if izCtrl (mrQ)  stor ();  else anim (&TGads [6]);
                      load ();                                          RET;
        CS  CLONG  :  anim (&TGads [ 7]);  stor ();           RET;
        CS  INC_G  :  anim (&TGads [10]);  increment ();                RET;
        CS  INS_G  :                       increment ();  save ();      RET;

        CS  FILLG  :  anim (&TGads [12]);

                      ifn (webefillin)  fillermouse (), webefillin = 1;
                          else      ClearPointer (win), webefillin = 0; RET;

        CS  COPYG  :   copy ();                                         RET;
        CS  UNDOG  :   undo ();                                         RET;
        CS  STAKG  :  stack ();                                         RET;
        CS  ROLLG  :  anim (&TGads [ 9]);  /* roll(); is in anim.c!*/   RET;

        CS  SEQ_G  :  if (seqwin)  WindowToFront (seqwin);
                          else  openSeqWin ();                          RET;

        CS  CNL_G  :  stor ();  load ();                                RET;
        CS  POP_G  :  popOnOff ();                                      RET;
        CS  XWB_G  :  clozeWB ();                                       RET;
        CS  TWEKG  :  tweakColors ();                                       RET;
        CS  ONIOG  :  togOnion = !togOnion;

                      ifn (togOnion)  onionOff ();
                          else       onionOn  (), newOnion (curOnion);  RET;

/*      CS  FREEG  :  free ();                                          RET;*/
    }                                 /*  switch, whip, paddle, spank, etc  */

}                                            /*  done all the dumb gadgets  */


       void
new ()             /*  "new" is a computer euphemism for "KILL EVERYTHING"  */
{

        hotHelp  ("To the Great Bit Bucket!!!", 2, 1);

        RectFill  ( reep,  35L,                    20L,
                           34L + ImageWid * Ratio, 19L + MaxDN * Ratio );

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

        RectFill  ( zreep (CurrentWindow), 4L, 14L,
                            3L + ImageWid, 13L + MaxDN );

        if (togOnion)  newOnion (curOnion);

}


    int  no_help = 0;

       void
pick ()
{

    Mess ("Click on a Color (\"Pick\" to Cancel)");
    pickmouse ();

    forever {
        no_help = 1;
        picking = 1;
        if (!input ())  quit ("Wrong color picked...");
        picking = 0;
        no_help = 0;
        Mx = win->MouseX;
        My = win->MouseY;

        if ( (msgclass == MOUSEBUTTONS && msgcode == SELECTUP) ||
             (msgclass == GADGETUP     && gadcode != PICKG   )    )  {
            ClearPointer (win);
            Mess ("New Color Picked");
            new_color ((ULONG) ReadPixel (reep, (long) Mx, (long) My));
            Wait (1L << win->UserPort->mp_SigBit);
            break;  }

        if ( msgclass == GADGETUP     && gadcode == PICKG )  {
            ClearPointer (win);
            Mess ("Cancelled - No New Color Picked");
            Wait (1L << win->UserPort->mp_SigBit);
            break;  }
    }                                                   /*  end of forever  */

    if (webefillin)  fillermouse ();
        else ClearPointer (win);


}       /*  you can pick your mouse and you can pick your friends, but ...  */


    static ULONG fillcolor;
    void fillazoid ();

        void
fill ()
{

    if (!INSIDE (Mx, My))  return;
    fillcolor = (ULONG) ReadPixel (reep, (long) Mx, (long) My);
    if (fillcolor == thisCol)  {  Mess ("Same Color Picked!");  return;  }
    Mess ("Here We Go!");
    copy ();
    offInput ();
    fillazoid (Mx - Mx % PIXI, My - My % PIXI, 170);
    onInput ();
    Mess ("Done Filling");

}       /*  you can fill your mouse and you can fill your friends, but ...  */


                    void
fillazoid (xx, yy, count)
{

    ifn (--count)  return;
    ifn (INSIDE (xx, yy))  return;
    if (fillcolor != (ULONG) ReadPixel (reep, xx - 1L, yy - 1L))  return;
    maybedospot (xx, yy);

    switch (rand () % 4)  {
        case 0: fillazoid (xx - PIXI, yy, count);
                fillazoid (xx + PIXI, yy, count);
                fillazoid (xx, yy + PIXI, count);
                fillazoid (xx, yy - PIXI, count);
        case 1: fillazoid (xx + PIXI, yy, count);
                fillazoid (xx, yy + PIXI, count);
                fillazoid (xx, yy - PIXI, count);
                fillazoid (xx - PIXI, yy, count);
        case 2: fillazoid (xx, yy + PIXI, count);
                fillazoid (xx, yy - PIXI, count);
                fillazoid (xx - PIXI, yy, count);
                fillazoid (xx + PIXI, yy, count);
        case 3: fillazoid (xx, yy - PIXI, count);
                fillazoid (xx - PIXI, yy, count);
                fillazoid (xx + PIXI, yy, count);
                fillazoid (xx, yy + PIXI, count);  }


}   /*  why so many fillazoids?  the order they are called affects the outer
                                            boundary of the filled area...  */

                 void
SchRep (waz)
{
    long xx, yy;


    Mess ("SchRepping Color");
    offInput ();

    LOOP  (xx = 35; xx < ImageWid * PIXI + 35; xx += PIXI)
        loop (yy = 20; yy < MaxDN * PIXI + 20; yy += PIXI)
            if (waz == ReadPixel (reep, xx, yy))
                maybedospot ((USHORT) xx + 1, (USHORT) yy + 1);

    Mess ("SchRepped Color");
    onInput ();

}


new_title ()
{
    static char buff [125], number [16] ;

    strcpy ( buff, "PopArt  -  by PHLIP  -  " );
    strcat ( buff, decimal ((int) Mx, number) );
    strcat ( buff, "  ");
    strcat ( buff, decimal ((int) My, number) );
    strcat ( buff, "         ");

    SetWindowTitles (win,  buff, -1L);

}                          /*  pop out the mouseXY, for position new stuff  */

