/******************************************************************************
*
*                   WBUtil        written  1989 by R.Beck
*                  ¯¯¯¯¯¯¯¯
* Compilieren: cc WBUtil +x3
*              ln WBUtil detach.o -lc
*/

#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <graphics/text.h>
#include <devices/printer.h>
#include <libraries/dosextens.h>
#include <functions.h>

#define Line(rp,x1,y1,x2,y2) Move(rp,x1,y1);Draw(rp,x2,y2)

#define Small 0      /* Fenster-Größen */
#define Large 1
#define SIZE 1       /* Gadget-ID für die einzelnen Programmfunktionen */
#define CLI 2
#define SHELL 3
#define DUMP 4
#define PRINTER 5
#define FASTMEM 6
#define MEMORY 7
#define EDIT 8
#define CUSTM 9

long _stack=8000,_priority=0,_BackGroundIO=0;   /* Info für detach.o */
char *_procname="WBUtil 1989 by R.Beck";

struct IntuitionBase *IntuitionBase;   /* Library-Pointer */
struct GfxBase *GfxBase;

/* Parameter für die Zeichensätze */

struct TextAttr LargeAttr = { (STRPTR)"topaz.font",9,0,0 };
struct Font *LargeFont;
struct TextAttr SmallAttr = { (STRPTR)"topaz.font",8,0,0 };
struct Font *SmallFont;


/* Gadget-Parameter */

struct Gadget g1={0,28,0,23,10,GADGHNONE,GADGIMMEDIATE,BOOLGADGET,
   0,0,0,0,0,SIZE};
struct Gadget g2={&g1,53,0,37,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,CLI};
struct Gadget g3={&g2,93,0,57,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,SHELL};
struct Gadget g4={&g3,153,0,47,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,DUMP};
struct Gadget g5={&g4,203,0,77,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,PRINTER};
struct Gadget g6={&g5,283,0,77,10,GADGHNONE,GADGIMMEDIATE,BOOLGADGET,
   0,0,0,0,0,FASTMEM};
struct Gadget g7={&g6,360,0,112,10,GADGHNONE,GADGIMMEDIATE,BOOLGADGET,
   0,0,0,0,0,MEMORY};
struct Gadget g8={&g7,473,0,46,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,EDIT};
struct Gadget g9={&g8,522,0,66,10,GADGHCOMP,RELVERIFY,BOOLGADGET,
   0,0,0,0,0,CUSTM};


/* Definition der Fensterdarstellungen */

struct NewWindow LargeWindow = {
   0,0,587,10,0,1,CLOSEWINDOW|VANILLAKEY|GADGETDOWN|GADGETUP,
   WINDOWCLOSE|SMART_REFRESH,&g9,NULL,NULL,NULL,NULL,
   -1,-1,-1,-1,WBENCHSCREEN };
struct NewWindow SmallWindow = {
   0,0,51,10,0,1,CLOSEWINDOW|GADGETDOWN,
   WINDOWCLOSE|SMART_REFRESH,&g1,NULL,NULL,NULL,NULL,
   -1,-1,-1,-1,WBENCHSCREEN };
struct Window *MyWindow;
struct RastPort *RP;


UBYTE MemFree=TRUE;  /* ist das FastMem schon belegt ? */


void _cli_parse() {} /* die unnötigen Compiler-Funktionen werden durch leere */
void _wb_parse() {}  /* ersetzt, das spart (Disk-)Speicher */

void CloseAll()      /* belegten Speicher freigeben */
{
   if(LargeFont) CloseFont(LargeFont);
   if(SmallFont) CloseFont(SmallFont);
   if(MyWindow) CloseWindow(MyWindow);
   if(IntuitionBase) CloseLibrary(IntuitionBase);
   if(GfxBase) CloseLibrary(GfxBase);
}

void OpenAll()    /* alles nötige anmelden */
{
  if(!(IntuitionBase=(struct IntuitionBase*)
    OpenLibrary("intuition.library",0L)))
      CloseAll();
   if(!(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L)))
      CloseAll();
   if(!(LargeFont=OpenFont(&LargeAttr))) CloseAll();
   if(!(SmallFont=OpenFont(&SmallAttr))) CloseAll();
}

void DrawDump()      /* Dump-Gadget zeichnen */
{
   SetAPen(RP,1L);
   RectFill(RP,153L,0L,199L,9L);
   SetAPen(RP,0L);
   Move(RP,157L,8L); Text(RP,"DUMP",4L);
}

void DrawFM()       /* FASTMEM-Gadget zeichnen */
{
   SetAPen(RP,1L);
   RectFill(RP,283L,0L,359L,9L);
   SetAPen(RP,0L);
   Move(RP,286L,8L); Text(RP,"FASTMEM",7L);
   if(!MemFree)
   {
      SetAPen(RP,3L);
      Line(RP,283L,0L,359L,9L);
      Line(RP,283L,9L,359L,0L);
   }
}

void DisplayMemory() /* Zeigt Speicher im Memory-Gadget an */
{
   register long chip,fast;    /* Menge an vorhandenem Speicher */
   char MemString[8];          /* Speicheranzeige in ASCII */

   SetAPen(RP,2L);                        /* schwarzer Hintergrund */
   RectFill(RP,360L,0L,472L,9L);
   SetAPen(RP,3L);                        /* rote Schrift  "C" , "F" */ 
   Line (RP,363L,3L,360L,3L);
   Draw(RP,360L,6L); Draw(RP,363L,6L);
   Line (RP,415L,3L,412L,3L);
   Draw(RP,412L,7L); Line(RP,412L,5L,415L,5L);

   SetFont(RP,SmallFont);                 /* weiße Anzeige */ 
   SetAPen(RP,1L);
   chip=AvailMem(MEMF_CHIP);              /* Speicher-Größen feststellen */
   fast=AvailMem(MEMF_FAST);
   sprintf(MemString,"%7ld",fast);        /* und als Text ausgeben */
   Move(RP,416L,8L); Text(RP,MemString,7L);
   sprintf(MemString,"%6ld",chip);
   Move(RP,364L,8L); Text(RP,MemString,6L);
   SetFont(RP,LargeFont);
}

void DrawCM()     /* Zeichnet Custom-Gadget */
{
   SetAPen(RP,1L);
   RectFill(RP,522L,0L,586L,9L);
   SetAPen(RP,0L);
   Move(RP,524L,8L); Text(RP,"NUMBER",6L);
}

void SetUp(mode)  /* öffnet das große (Large) oder kleine (Small) Fenster */
BYTE mode;        /* und führt die entsprechenden Zeichnungen aus */
{
   register COUNT i;

   switch(mode)
   {
    case Small:
      if(!(MyWindow=OpenWindow(&SmallWindow)))
         CloseAll();
      break;
    case Large:
      if(!(MyWindow=OpenWindow(&LargeWindow)))
         CloseAll();
   }
   RP=MyWindow->RPort;

   SetAPen(RP,1L);                                    /* Sizing-Gadget */
   RectFill(RP,28L,0L,(long)MyWindow->Width-1,9L);
   SetAPen(RP,2L);
   for(i=0;i<8;i++)
   {
      Move(RP,30L,(long)1+i); Draw(RP,47L,(long)8-i);
   }
   
   if(mode==Large)
   {
      SetAPen(RP,0L);   SetFont(RP,LargeFont);
      SetDrMd(RP,JAM1);
      Move(RP,57L,8L);  Text(RP,"CLI",3L);            /* Beschriftung */
      Move(RP,96L,8L);  Text(RP,"SHELL",5L);
      Move(RP,476L,8L); Text(RP,"EDIT",4L);
      Move(RP,206L,8L); Text(RP,"PRINTER",7L);
      SetAPen(RP,2L);
      Line(RP,90L,1L,90L,8L);  Line(RP,92L,1L,92L,8L);   /* Trennbalken */
      Line(RP,200L,1L,200L,8L);  Line(RP,202L,1L,202L,8L);
      RectFill(RP,51L,0L,52L,9L);
      RectFill(RP,150L,0L,152L,9L);
      RectFill(RP,280L,0L,282L,9L);
      RectFill(RP,519L,0L,521L,9L);

      DrawDump();                            /* Dump-Gadget zeichnen */

      DrawFM();                              /* FastMem-Gadget */

      DisplayMemory();                       /* Memory-Anzeige */

      DrawCM();                              /* Number-Gadget */

   } /* Ende Large-mode */
}   
 
USHORT WaitKey()    /* Erwartet einen Tastendruck */
{
   register struct IntuiMessage *message;
   register ULONG Class=0;
   register USHORT Code='\0';

   while(Class!=VANILLAKEY || Code=='\0')
   {
      Wait(1L << MyWindow->UserPort->mp_SigBit);
      message= (struct IntuiMessage *)GetMsg(MyWindow->UserPort);
      Class= message->Class;  Code=message->Code;
      ReplyMsg(message);
   }
   return(Code);
}

void Dump(Req,x,y,w,h)    /* führt Hardcopy-Befehl aus */
struct IODRPReq *Req;
UWORD x,y,w,h;
{
   Req->io_SrcX=x;      Req->io_SrcY=y;
   Req->io_SrcWidth=w;  Req->io_SrcHeight=h;
   DoIO(Req);
}

UBYTE PosterDump(Faktor)    /* erzeugt Hardcopy im Format Faktor * Faktor */
USHORT Faktor;
{
   struct MsgPort *myPort;    /* Device-Verwaltung */
   struct IODRPReq *myReq;
   register UCOUNT x,y;       /* Zähler-variable */
   register struct Screen *s; /* zu druckender Screen */

   if(Faktor==0 || Faktor >5) return(0);   /* nicht mehr als 25 Einzelbilder */

   if(!(myPort=CreatePort(0L,0L))) return(0);
   if(!(myReq=(struct IODRPReq *)CreateExtIO(myPort,(long)sizeof(struct IODRPReq))))
   {
      DeletePort(myPort);
      return(0);
   }
   if(OpenDevice("printer.device",0L,myReq,0L))
   {
      DeleteExtIO(myReq,(long)sizeof(struct IODRPReq));
      DeletePort(myPort);
      return(0);
   }

   Delay(500L);            /* 10 Sekunden warten, bis richtiger Screen oben */
   s=IntuitionBase->FirstScreen;
   myReq->io_Command =PRD_DUMPRPORT;
   myReq->io_RastPort=&(s->RastPort);
   myReq->io_ColorMap=s->ViewPort.ColorMap;
   myReq->io_Modes   =s->ViewPort.Modes;
   myReq->io_Special =SPECIAL_FULLCOLS|SPECIAL_ASPECT;

   for(x=0;x<Faktor;x++)         /* nun die Einzelbilder ausdrucken */
      for(y=0;y<Faktor;y++)
      {
         SetAPen(RP,0L);
         RectFill(RP,153L,0L,199L,9L);
         SetAPen(RP,1L);
         Move(RP,156L,8L);Text(RP,"Wait",4L);
         
         Dump(myReq,(UWORD)(x*s->ViewPort.DWidth/Faktor),
                    (UWORD)(y*s->ViewPort.DHeight/Faktor),
                    (UWORD)(s->ViewPort.DWidth/Faktor),
                    (UWORD)(s->ViewPort.DHeight/Faktor));
         
         if(!(x==Faktor-1 && y==Faktor-1))
         {  /* Dem Anwender Zeit zur Papierjustage lassen */
            SetAPen(RP,0L);
            RectFill(RP,153L,0L,199L,9L);
            SetAPen(RP,1L);
            Move(RP,156L,8L);Text(RP,"Push",4L);
            WaitKey();
         }
      } /* for y */

   CloseDevice(myReq);
   DeleteExtIO(myReq,(long)sizeof(struct IODRPReq));
   DeletePort(myPort);
   return(1);
}

main()
{
   register UBYTE End=FALSE;     /* Programm beenden ? */
   register UBYTE ActSize=Large; /* ist das große oder kleine Fenster offen ? */
   register struct Rememberkey *remkey=0; /* Speicherverwaltung von Intuition */
   register ULONG Size;          /* Größe eines Speicherblocks */
   register struct Screen *s;    /* Sucht einen gewünschten Screen */
   struct FileHandle *handle;    /* für Zugriff auf Editor-Variable */
   char Buffer[256];             /* nimmt Editor-Befehlsstring auf */
   struct IntuiMessage *message; /* Zeiger auf Intuition-Nachricht */
   ULONG Class;                  /* wichtige Bestandteile einer Message */
   USHORT Code,GadID;

   OpenAll();
   SetUp(ActSize);   /* Hauptfenster öffnen */
   DisplayMemory();
   while(!End)
   {
      Wait(1L << MyWindow->UserPort->mp_SigBit);

      message= (struct IntuiMessage *)GetMsg(MyWindow->UserPort);
      Class= message->Class;     /* wichtige Informationen merken */
      GadID= ( (struct Gadget*)(message->IAddress) )->GadgetID;
      ReplyMsg(message);         /* und Nachricht zurücksenden */

      switch(Class)
      {
       case CLOSEWINDOW:
         End=TRUE;
         break;

       case GADGETDOWN:                /* Gadget angewählt */
       case GADGETUP:
         if(ActSize) DisplayMemory();  /* im großen Fenster Speicher anzeigen */
         switch(GadID)
         {
          case SIZE:
            CloseWindow(MyWindow);     /* Fenstergröße umschalten */
            ActSize=1-ActSize;
            SetUp(ActSize);
            break;

          case CLI:
            Execute("newcli con:0/11/640/245/CLI",NULL,NULL);
            break;

          case SHELL:
            Execute("newshell newcon:0/11/640/245/SHELL",NULL,NULL);
            break;

          case DUMP:                   /* Hardcopy drucken */
            SetAPen(RP,0L);
            RectFill(RP,153L,0L,199L,9L);
            SetAPen(RP,1L);
            Move(RP,156L,8L);Text(RP,"1..5",4L);
            if(!PosterDump(WaitKey()-'0'))
	    	DisplayBeep(0L);
            DrawDump();                     /* Gadget restaurieren */
            break;

          case PRINTER:
            Execute("run SYS:Preferences PRINTER",NULL,NULL);
            break;

          case FASTMEM:
            if(MemFree)        /* ist noch FastMem da ? */
            {
               Size=0x200000;  /* zunächst je 2 Meg. anfordern */
               do
               {
                  while(AllocRemember(remkey,Size,MEMF_FAST))
                     ;         /* möglichst oft große Blöcke anfordern */
                  Size/=2;     /* nun nur noch halbgroße Blöcke */
               } while(Size>=8L);
               MemFree=FALSE;
            }
            else              /* FastMem soll wieder eingeschaltet werden */
            {
               FreeRemember(remkey,1L);
               MemFree=TRUE;
            }
            DrawFM();         /* Gadget neu zeichnen */
            Delay(2L);        /* Warten, bis das Betriebssystem die Listen */
            DisplayMemory();  /* erneuert hat, dann neuen Wert anzeigen */
            break;

          case MEMORY:
            break;            /* Speicher wurde bereits angezeigt */

          case EDIT:          /* Editor aus Variable editor starten */
               if(handle=Open("ENV:editor",MODE_OLDFILE))
               {
                  strcpy(Buffer,"run ");        /* Editor als eigenen Process */
                  Read(handle,Buffer+4,252L);   /* Namen des Editors holen */
                  Execute(Buffer,NULL,NULL);    /* und aufrufen */
               }
               Close(handle);
	    break;

          case CUSTM:                           /* Custom-Screen anwählen */
            SetAPen(RP,0L);
            RectFill(RP,522L,0L,586L,9L);
            SetAPen(RP,1L);
            Move(RP,526L,8L); Text(RP,"0 .. 9",6L); /*Zifferneingabe verlangen*/

            Code=WaitKey()-'0';
            if(0<=Code && Code<=9)  /* wurde eine Ziffer gedrückt ? */
            {
               for(s=IntuitionBase->ActiveScreen; s->NextScreen && Code; Code--)
	          s=s->NextScreen;
               ScreenToFront(s);    /* gewünschten Screen anzeigen */
            }
            DrawCM();         /* Gadget restaurieren */
            break;            
         } /* switch GadID */
      } /* switch Class */
   } /* while !End */

   CloseAll();
}
