 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****    Program          : Intui-Funktionen                     ****/
 /****                                                            ****/
 /****    Version          :    01.07                             ****/
 /****                                                            ****/
 /****    Erstversion      : 21.05.1988                           ****/
 /****                                                            ****/
 /****    Letzte Änderung  : 01.06.1990                           ****/
 /****                                                            ****/
 /****    Compiliert mit   : siehe MAKE                           ****/
 /****                                                            ****/
 /****    Gelinkt mit      : Für Tool.Library                     ****/
 /****                                                            ****/
 /********************************************************************/
 /****                                                            ****/
 /****                                                            ****/
 /****               Copyright by Rüdiger Dreier                  ****/
 /****                                                            ****/
 /****                                                            ****/
 /********************************************************************/
 
 #include "ToolProto.h"
 #include <intuition/intuition.h>
 #include <intuition/intuitionbase.h>
 #include <libraries/dos.h>
 #include <graphics/gfxmacros.h>
 #include <exec/memory.h>
 #include <intuition/intuitionbase.h>
 #include <proto/intuition.h>
 #include <proto/graphics.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 
 #define ACTIVE_SCREEN IntuitionBase->ActiveScreen
 #define ACTIVE_WINDOW IntuitionBase->ActiveWindow
 #define CODE  ((Message!=0) ? Message->Code  : 0)
 #define CLASS ((Message!=0) ? Message->Class : 0)
 #define CircleFill(RP,x,y,r) EllFill(RP,x,y,r,r);
 
 extern struct IntuitionBase *IntuitionBase;
 extern struct GfxBase       *GfxBase;
 
 /* Zeichnet einen Kasten.. */
 VOID __asm Box(register __a1 struct RastPort *RastPort,    /* Der RastPort */
                register __d0 LONG xs,                      /* Start: X     */
                register __d1 LONG ys,                      /* Start: Y     */
                register __d2 LONG xe,                      /* Ende : X     */
                register __d3 LONG ye)                      /* Ende : Y     */
  {
   Move(RastPort,xs,ys);
   Draw(RastPort,xe,ys);
   Draw(RastPort,xe,ye);
   Draw(RastPort,xs,ye);
   Draw(RastPort,xs,ys);
  }
 
 
 /* Gibt eine Text zentriert im Fenster aus */
 VOID __asm Center(register __a1 struct Window *Window,     /* Das Fenster  */
                   register __a0 char *string,              /* Der Text     */
                   register __d0 LONG Color,                /* Die Farbe    */
                   register __d1 LONG y_Pos)                /* Die Y-Pos.   */
  {
   LONG x;
   x=((LONG)Window->Width-strlen(string)*8)/2;
   Print(Window->RPort,string,Color,x,y_Pos);
  }
 
 /* Schaltet ein Gadget ein (ENABLE) */
 VOID __asm Gadget_On(register __a0 struct Gadget *Gadget,  /* Das Gadget   */
                      register __a1 struct Window *Window)  /* Das Fenster  */
  {
   BYTE APen;
   
   if (Gadget->Flags & GADGDISABLED)
    {
     APen=Window->RPort->FgPen;
     SetAPen(Window->RPort, 0L) ;
    /* Zeichenbereich löschen */
     RectFill(Window->RPort,(long)Gadget->LeftEdge,
              (long)Gadget->TopEdge,
              (long)Gadget->LeftEdge+Gadget->Width-1,
              (long)Gadget->TopEdge+Gadget->Height-1);
     SetAPen(Window->RPort, (LONG)APen) ;
    /* Gadget neu zeichnen */
     OnGadget(Gadget, Window, NULL) ;
    }
  }
 
 
 /* Schaltet ein Gadget aus (DISABLE) */
 VOID __asm Gadget_Off(register __a0 struct Gadget *Gadget, /* Das Gadget   */
                       register __a1 struct Window *Window) /* Das Fenster  */
  {
   if (!(Gadget->Flags & GADGDISABLED))
    {
     OffGadget(Gadget, Window, NULL);
    }
  }
 
 
 
 /* Holt horizontale Position des PropGadgets */
 LONG __asm GetPropPosH(register __a0 struct Gadget *Gadget,/* Das Gadget   */
                        register __d0 LONG MaxPos)          /* Max. Pos.    */
  {
   struct PropInfo *PInfo;
   long Pos;
   
   PInfo=(struct PropInfo *)Gadget->SpecialInfo;
   if(MaxPos&&PInfo)
    {
     Pos=(PInfo->HorizPot)*MaxPos/MAXBODY;
     if(Pos==MaxPos)
      {
       Pos--;
      }
     return(Pos);
    }
   else
    {
     return(0);
    }
  }
 
 /* Holt vertikale Position des PropGadgets */
 LONG __asm GetPropPosV(register __a0 struct Gadget *Gadget,/* Das Gadget   */
                        register __d0 LONG MaxPos)          /* Max. Pos.    */
  {
   struct PropInfo *PInfo;
   long Pos;
   
   PInfo=(struct PropInfo *)Gadget->SpecialInfo;
   if(MaxPos&&PInfo)
    {
     Pos=(PInfo->VertPot)*MaxPos/MAXBODY;
     if(Pos==MaxPos)
      {
       Pos--;
      }
     return(Pos);
    }
   else
    {
     return(0);
    }
  }
 
/* Die beiden folgenden Routinen verändern ..Pot und ..Body entsprechend */
/* den übergebenen Werten. Schrittweite ist für ..Body und MaxPos/NewPos */
/* für ..Pot verantwortlich. Bsp: Es soll ein Bereich mit 15 Zeilen ge-  */
/* scrollt werden, wobei je 5 Zeilen gleichzeitig angezeigt werden können*/
/* MaxPos ist somit 11 (von Zeile 0 bis 10 kann jede als oberste der 5   */
/* auftauchen). Schrittweite ist 3 (Z0-4, Z5-9 und Z10-14 können jeweils */
/* angezeigt werden). NewPos gibt dann die aktuelle Position an (z.B. 9) */
/* Klick der Anwender dann NEBEN den Schieberegler, so spring der um     */
/* max. Schrittweite weiter, d.h. aus Position 9 wird z.B. 4. Da hier mit*/
/* Ganzzahlen gerechnet wird, gibt es manchmal Probleme, wenn der An-    */
/* wender den Regler selbst verschoben hat. Hat er den Regler z.B. so    */
/* verschoben, daß die Position gerade noch als 9 erkannt wird (und noch */
/* nicht als 8), dann kann es passieren, daß durch Anklicken neben dem   */
/* Regler als nächste Position 3 und nicht 4 angegeben wird.             */
 
 
 
 /* Setzt PropGadget auf horizontalen Wert */
 VOID __asm SetPropPosH(register __a0 struct Gadget *Gadget,/* Das Gadget   */
                        register __a1 struct Window *Window,/* Das Fenster  */
                        register __d0 LONG MaxPos,          /* Die MaxPos   */
                        register __d1 LONG Schrittweite,    /* Schrittweite */
                        register __d2 LONG NewPos)          /* Neue Posit.  */
  {
   struct PropInfo *PInfo;
   LONG Position;
   
   PInfo=(struct PropInfo *)Gadget->SpecialInfo;
   if(MaxPos)
    {
     if(MaxPos>1)
      {
       Position=MAXBODY*NewPos/(MaxPos-1);
      }
     else
      {
       Position=MAXBODY;
      }
     if(Position>=MAXBODY)
      {
       Position=MAXBODY;
      }
     ModifyProp(Gadget,
                Window,
                NULL,
                PInfo->Flags,
                Position,
                PInfo->VertPot,
                (MAXBODY/Schrittweite),
                PInfo->VertBody);
    }
  }
 
 
 
 /* Setzt PropGadget auf vertikalen Wert */
 VOID __asm SetPropPosV(register __a0 struct Gadget *Gadget,/* Das Gadget   */
                        register __a1 struct Window *Window,/* Das Fenster  */
                        register __d0 LONG MaxPos,          /* Die MaxPos   */
                        register __d1 LONG Schrittweite,    /* Schrittweite */
                        register __d2 LONG NewPos)           /* Neue Posit.  */
  {
   struct PropInfo *PInfo;
   LONG Position;
   
   PInfo=(struct PropInfo *)Gadget->SpecialInfo;
   if(MaxPos)
    {
     if(MaxPos>1)
      {
       Position=MAXBODY*NewPos/(MaxPos-1);
      }
     else
      {
       Position=MAXBODY;
      }
     if(Position>=MAXBODY)
      {
       Position=MAXBODY;
      }
     ModifyProp(Gadget,
                Window,
                NULL,
                PInfo->Flags,
                PInfo->HorizPot,
                Position,
                PInfo->HorizBody,
                (MAXBODY/Schrittweite));
    }
  }
 
/* Diese Funktion bereitet alles vor, damit die Flood-Funktion */
/* benutzt werden kann.                                        */
 LONG __asm PrepareTmpRas(register __a1 struct RastPort *RP)/* Der RastPort */
  {
   struct TmpRas   *Ras;
   struct BitMap   *BitMap;
   LONG Breite,Hoehe;
   BYTE *Plane;
   
   BitMap=RP->BitMap; /* BitMap des RastPorts */
   
/* Berechnen von Breite und Höhe (stimmt nicht unbedingt */
/* mit Werten des Windows überein, besonders nicht bei   */
/* SuperBitMaps. Auch bei Fensterbreiten wie 630 wird    */
/* 640 errechnet. RASSIZE berechnet aber aus beiden      */
/* das gleiche Ergebnis (immer ganze Worte)              */
   Breite=BitMap->BytesPerRow*8;
   Hoehe =BitMap->Rows;
   
   if(RP->TmpRas)return(0); /* Schon ein TmpRas */
   
   Plane=AllocRaster(Breite,Hoehe); /* Speicher für Plane */
   if(!Plane)return(0);
   
/* Speicher für Struktur holen */
   Ras=AllocMem(sizeof(struct TmpRas),MEMF_CLEAR);
   if(!Ras)
    {
     FreeRaster(Plane,Breite,Hoehe);
     return(0);
    }
   
/* Struktur initialisieren */
   InitTmpRas(Ras,Plane,RASSIZE(Breite,Hoehe));
   
   RP->TmpRas=Ras; /* RastPort mitteilen */
   
   return((LONG)Ras); /* Wert ungleich NULL */
  }
 
/* Die Funktion gibt den belegten Speicher wieder frei */
 VOID __asm ClearTmpRas(register __a1 struct RastPort *RP)   /* Der RastPort */
  {
   struct TmpRas *TRas;
   struct BitMap *BitMap;
   BYTE *Plane;
   
   TRas=RP->TmpRas;   /* Zeiger auf Struktur  */
   BitMap=RP->BitMap; /* Die BitMap           */
   
   RP->TmpRas=NULL;   /* Verknüpfung aufheben */
   Plane=TRas->RasPtr;/* Zeiger auf BitPlane  */
   
/* Beide Speicherbereiche freigeben */
   FreeRaster(Plane,BitMap->BytesPerRow*8,BitMap->Rows);
   FreeMem(TRas,sizeof(struct TmpRas));
  }
 
 LONG __asm PrepareArea(register __a1 struct RastPort *RP,
                        register __d0 LONG MaxPoints)
  {
   UWORD *Liste;
   struct AreaInfo *AI;
   Liste=0;
   if(PrepareTmpRas(RP))
    {
     	
     AI=(struct AreaInfo *)AllocMem(sizeof(struct AreaInfo),MEMF_CLEAR);
     if(!AI)
      {
       ClearTmpRas(RP);
       return(0);
      }
     
     Liste=AllocMem(MaxPoints*5,MEMF_CLEAR);
     if(!Liste)
      {
       FreeMem(AI,sizeof(struct AreaInfo));
       ClearTmpRas(RP);
       return(0);
      }
     InitArea(AI,Liste,MaxPoints);
     RP->AreaInfo=AI;
    }
   return((LONG)Liste);
  }
 
 VOID __asm ClearArea(register __a1 struct RastPort *RP)
  {
   struct AreaInfo *AI;
   if(AI=RP->AreaInfo)
    {
     FreeMem(AI->VctrTbl,AI->MaxCount*5);
     FreeMem(AI,sizeof(struct AreaInfo));
    }
   ClearTmpRas(RP);
  }
 
