/*
** AmigaWelt-Grafikkurs: Beispiel 2
** Copyright (C) 11-Feb-1988 by Ralph Babel
** all rights reserved - alle Rechte vorbehalten
*/

/*** included files ***/

#include <exec/types.h>
#include <exec/ports.h>
#include <libraries/dos.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

/*** types ***/

typedef int bool;

/*** external symbol references ***/

#ifndef __ARGS
#ifdef AZTEC_C
#define __ARGS(a) ()
#else
#define __ARGS(a) a
#endif
#endif

struct Library *OpenLibrary __ARGS((char *, ULONG));
VOID CloseLibrary __ARGS((struct Library *));
struct Window *OpenWindow __ARGS((struct NewWindow *));
VOID CloseWindow __ARGS((struct Window *));
VOID SetAPen __ARGS((struct RastPort *, ULONG));
VOID SetDrMd __ARGS((struct RastPort *, ULONG));
VOID Move __ARGS((struct RastPort *, LONG, LONG));
VOID Draw __ARGS((struct RastPort *, LONG, LONG));
VOID WritePixel __ARGS((struct RastPort *, LONG, LONG));
struct Message *WaitPort __ARGS((struct MsgPort *));
struct Message *GetMsg __ARGS((struct MsgPort *));
VOID ReplyMsg __ARGS((struct Message *));
VOID printf __ARGS((char *, ));

STATIC VOID Line __ARGS((struct RastPort *, WORD, WORD, WORD, WORD, UBYTE,
 UBYTE));
STATIC bool MouseInWindowP __ARGS((struct Window *, struct IntuiMessage *));

/*** global symbols ***/

struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;

/*** constants ***/

#define COLOR 1

/*** data section ***/

STATIC struct NewWindow NW =
 {
 160, 64,         /* SHORT LeftEdge, TopEdge; */
 320, 68,         /* SHORT Width, Height; */
 -1, -1,          /* UBYTE DetailPen, BlockPen; */
 SIZEVERIFY
 | MOUSEBUTTONS
 | MOUSEMOVE
 | CLOSEWINDOW,   /* ULONG IDCMPFlags; */
 WINDOWSIZING
 | WINDOWDRAG
 | WINDOWDEPTH
 | WINDOWCLOSE
 | SMART_REFRESH
 | REPORTMOUSE
 | RMBTRAP
 | NOCAREREFRESH, /* ULONG Flags; */
 NULL,            /* struct Gadget *FirstGadget; */
 NULL,            /* struct Image *CheckMark; */
 "Beispiel 2",    /* UBYTE *Title; */
 NULL,            /* struct Screen *Screen; */
 NULL,            /* struct BitMap *BitMap; */
 80, 32,          /* SHORT MinWidth, MinHeight; */
 ~0, ~0,          /* USHORT MaxWidth, MaxHeight; */
 WBENCHSCREEN     /* USHORT Type; */
 };

/*** code section ***/

STATIC bool MouseInWindowP(w, im)
struct Window *w;
struct IntuiMessage *im;
 {
 return im->MouseX >= w->BorderLeft && im->MouseX < w->Width - w->BorderRight
  && im->MouseY >= w->BorderTop && im->MouseY < w->Height - w->BorderBottom;
 }

STATIC VOID Line(rp, startx, starty, endx, endy, mode, color)
struct RastPort *rp;
WORD startx, starty, endx, endy;
UBYTE mode;
UBYTE color;
 {
 SetDrPt(rp, 0xffff);
 SetDrMd(rp, mode);
 SetAPen(rp, color);
 Move(rp, startx, starty);
 Draw(rp, endx, endy);
 }

/*** entry point ***/

LONG main()
 {
 struct IntuiMessage *im, IM;
 struct RastPort *rp;
 struct Window *w;
 BOOL running;
 LONG result;
 WORD startx, starty, endx, endy;
 enum modes { IGNORE, PIXEL, LINE } mode;
 BOOL oldline;

 result = RETURN_FAIL;

 if((GfxBase = (struct GfxBase *)
  OpenLibrary("graphics.library", LIBRARY_VERSION)) != NULL)
  {
  if((IntuitionBase = (struct IntuitionBase *)
   OpenLibrary("intuition.library", LIBRARY_VERSION)) != NULL)
   {
   result = RETURN_ERROR;

   if((w = OpenWindow(&NW)) != NULL)
    {
    rp = w->RPort;
    mode = IGNORE;
    oldline = FALSE;

    for(running = TRUE; running; )
     {
     if(WaitPort(w->UserPort) != NULL)
      {
      while(running
       && (im = (struct IntuiMessage *)GetMsg(w->UserPort)) != NULL)
       {
       IM = *im;
       ReplyMsg((struct Message *)im);
       switch(IM.Class)
        {
        case MOUSEBUTTONS:
         switch(IM.Code)
          {
          case MENUDOWN:
           if(mode == IGNORE && MouseInWindowP(w, &IM))
            {
            mode = LINE;
            startx = IM.MouseX;
            starty = IM.MouseY;
            oldline = FALSE;
            }
           break;
          case SELECTDOWN:
           if(mode == IGNORE)
            mode = PIXEL;
           break;
          case MENUUP:
           if(mode == LINE)
            {
            if(oldline)
             {
             Line(rp, startx, starty, endx, endy, COMPLEMENT, 0xff);
             oldline = FALSE;
             Line(rp, startx, starty, endx, endy, JAM1, COLOR);
             }
            mode = IGNORE;
            }
           break;
          case SELECTUP:
           if(mode == PIXEL)
            mode = IGNORE;
           break;
          }
         /* drop through! */
        case MOUSEMOVE:
         switch(mode)
          {
          case PIXEL:
           if(MouseInWindowP(w, &IM))
            {
            SetDrMd(rp, JAM1);
            SetAPen(rp, COLOR);
            WritePixel(rp, IM.MouseX, IM.MouseY);
            }
           break;
          case LINE:
           if(oldline)
            {
            Line(rp, startx, starty, endx, endy, COMPLEMENT, 0xff);
            oldline = FALSE;
            }
           if(MouseInWindowP(w, &IM))
            {
            Line(rp, startx, starty, endx = IM.MouseX, endy = IM.MouseY,
             COMPLEMENT, 0xff);
            oldline = TRUE;
            }
           break;
          }
         break;
        case CLOSEWINDOW:
         running = FALSE;
         break;
        }
       }
      }
     }
    CloseWindow(w);
    }
   else
    printf("Unable to open window.\n");
   CloseLibrary((struct Library *)IntuitionBase);
   }
  else
   printf("Cannot open intuition!?!\n");
  CloseLibrary((struct Library *)GfxBase);
  }
 else
  printf("Cannot open graphics?!?\n");

 return result; /* exit(result); */
 }
