/* INCLUDE FILES */
#include <stdio.h>
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <exec/ports.h>
#include <exec/interrupts.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>

/* DEFINES */
#define INTUITION_REV 29
#define GRAPHICS_REV 29
#define NL 0
#define ESC 27
#define MIX 1
#define MIY 5
#define MAY 27
#define EOS '\0'
#define LF 10
#define GROESSE 512
#define ROT 3
#define SCHWARZ 2
#define WEISS 1
#define BLAU 0
#define MENUE_FLAG  ITEMTEXT|ITEMENABLED|HIGHCOMP /* Flag f. norm. Menpkte.*/
#define STRICH_FLAG ITEMTEXT  /* Flag für die roten Striche */

/* VARIABLEN */
int MAS, SEITE, sei, MAX;
struct Library *OpenLibrary();
struct IntuitionBase *IntuitionBase;
struct Window *Fenster, *OpenWindow();
struct Screen *Skrien, *OpenScreen();
struct GfxBase *GfxBase;
struct RastPort *RPforte;
struct IntuiMessage *nachricht, *GetMsg();
extern struct FileHandle *Open();
struct IOStdReq message, *LNachr, *SNachr;
struct MsgPort *LPforte, *SPforte;
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();
char einzeichen, buffer[512], titel[232], str[79], hel[79];
extern UBYTE *disk();
UBYTE *a[15] [72], *AllocMem();
ULONG class;
USHORT code, qualif;
SHORT x, y, z, s, se, ze, xe, Flagge, meld, ein,
      sicher, blo, bas, baz, bes, bez;
struct IntuiText request_text, ja_text, nein_text, rahmen_text ;
char *FehlerText[3], *FrageText[4];

FastLoad(FName) /* Laden eines Textes und Änderung des akt. Namens */
UBYTE *FName;
{
   int fehler=FALSE, len, ss=s, zz=z, yy=y;

   sprintf(buffer,"%s wird geladen!", FName);
   Meldung();
   if((fehler=Laden(FName)) == TRUE) {
      NamenSetzen(FName);
      StrKopie(titel,FName);
      SetAPen(RPforte,0);
      RectFill(RPforte,4,43,632,226);
      SetAPen(RPforte,1);
      FastText(); s=ss; z=zz; y=yy; CursorAn(); Locate(y,x);
   }
   return(fehler);
}
Speichern(FName, as, az, es, ez)
UBYTE *FName;  /* Speichern eines Textes, der bei as,az anfängt und bei */
int as, az, es, ez; /* es,ez endet u. Änderung des akt. Namens */ 
{
   FILE *file;
   int len=0;

   if(!(file=fopen(FName,"w"))) {
      sprintf(buffer,"Kann %s nicht öffnen!",FName);
      Meldung();
      return(FALSE);
   }
   else {
      sprintf(buffer, "%s wird gespeichert!", FName);
      Meldung();
      FOREVER {
         fprintf(file, "%s\n", a[as] [az]);
         len += strlen(a[as] [az])+1;
         az+=1;
         if(az>SEITE) {
            az=0; as+=1;
         }
         if(as>=es) {
            if(az>ez)
               break;
            if(as>es)
               break;
         }
      }
      fclose(file);
      NamenSetzen(FName);
      StrKopie(titel,FName);
      sprintf(buffer, "Textlänge: %d Bytes", len);
      Meldung();
      sicher = TRUE;
   }
   return(TRUE);
}

auto_frage(frage)  
char *frage;    /* Text für Autorequest */
{
   int wert;

   request_text.IText = (UBYTE *)frage;
   wert = AutoRequest(Fenster,&request_text,&ja_text,&nein_text,0,0,319,60);
   return(wert);  /* TRUE oder FALSE wird zurückgesendet */
}
TLoeschen() /* Der gesamte Text wird gelöscht */
{
   int len;

   FOREVER {
      *a[se] [ze] = EOS;
      ze--;
      if(ze<0) {
         ze=SEITE; se--;
         if(se<0)
            break;
      }
   }
   se=ze=s=z=0; x=MIX; y=MIY;
   CursorAus();
   SetAPen(RPforte,0);
   RectFill(RPforte,4,43,632,226);
   SetAPen(RPforte,1);
   CursorAn(); Locate(y,x);
   ZSDisplay();
   sicher = TRUE;
}
TLaden(fname)  /* Text wird geladen und der alte wird gelöscht */
UBYTE *fname;
{
   TLoeschen();
   CursorAus();
   FastLoad(fname);
   CursorAn(); Locate(y,x);
   ZSDisplay();
   strcpy(buffer,str);
   Meldung();
}
/* Einrichtung eines Menüs */
NeuesMenue (menue,punkte_namen,menue_punkte,menue_text,punkte_anzahl,weite)
struct Menu       *menue;
char              *punkte_namen[];
struct MenuItem   menue_punkte[];
struct IntuiText  menue_text[];
int               punkte_anzahl;
int               weite;
{
   int i;
   int hoehe = 0;

   for (i=0; i< punkte_anzahl; i++)
   {
      menue_text[i] = rahmen_text;
      menue_text[i].IText = (UBYTE *)punkte_namen[i];
      if(punkte_anzahl==13 && (i==2||i==4||i==6||i==8||i==11))
         menue_text[i].FrontPen = ROT;
      else if(punkte_anzahl==9 && (i==3 || i==5))
         menue_text[i].FrontPen = ROT;
      else if(punkte_anzahl==5 && (i==1 || i==3))
         menue_text[i].FrontPen = ROT;
      menue_punkte[i].NextItem = &menue_punkte[i+1];
      menue_punkte[i].TopEdge = 10 * i;
      menue_punkte[i].LeftEdge = 0;
      menue_punkte[i].Height = 8;
      menue_punkte[i].ItemFill = (APTR)&menue_text[i];
      menue_punkte[i].Flags = MENUE_FLAG;
      if(punkte_anzahl==13 && (i==2||i==4||i==6||i==8||i==11))
         menue_punkte[i].Flags = STRICH_FLAG;
      else if(punkte_anzahl==9 && (i==3 || i==5))
         menue_punkte[i].Flags = STRICH_FLAG;
      else if(punkte_anzahl==5 && (i==1 || i==3))
         menue_punkte[i].Flags = STRICH_FLAG;
      menue_punkte[i].Width = weite;
      menue_punkte[i].MutualExclude = 0x0000;
      menue_punkte[i].Command = 0;
      menue_punkte[i].SubItem = NL;
      menue_punkte[i].NextSelect = NL;
      hoehe += 10;
   }
   menue_punkte[punkte_anzahl-1].NextItem = NULL;
   menue->Height = hoehe;
}
TextAnhaengen(fname) /* Text wird an das Ende des akt. Text angehängt */
UBYTE *fname;
{
   int as2=se, az2=ze, ax=s, ay=z;

   ze+=1;
   if(ze>SEITE) {
      ze=0;se+=1;
      if(se>MAS) {
         ze=SEITE; se=MAS;
         sprintf(buffer, "%s", FehlerText[2]);
         Meldung();
         return(0);
       }
   }
   s = se; z = ze;
   CursorAus();
   sprintf(hel, "%s", titel);
   if(FastLoad(fname)==TRUE) {
      x=MIX; y=MIY;
      sicher = FALSE;
      NamenSetzen(hel);
   }
   else {
      ze=az2; se=as2; z=ay; s=ax;
   }
   ZSDisplay();
   CursorAn(); Locate(y,x);
   strcpy(buffer, str);
   Meldung();
}
BlockLoeschen()  /* Der markierte Block wird gelöscht */
{
   int  rs=se, rz=ze, ay=y;

   if(bes==se && bez==ze) {
      se=bas; ze=baz-1;
      if(ze<0) {
         ze=SEITE; se--;
         if(se<0) { ze=0; se=0; strcpy(a[0] [0], ""); }
      }
      s=se; z=ze;
   }
   else {
      s=bas; z=baz-1;
      if(z<0) { z=SEITE; s--; }
      if(s<0) { z=0; s=0; }
      bez++;
      if(bez>SEITE) { bez=0; bes++; }
      FOREVER {
         StrKopie(a[bas] [baz], a[bes] [bez]);
         baz++; bez++;
         if(baz>SEITE) { baz=0; bas++; }
         if(bez>SEITE) { bez=0; bes++; }
         if((bes==se && bez>ze) || (bes>se))
            break;
      }
      baz--; if(baz<0) { baz=SEITE; bas--; }
      if(bas<0) { bas=0; baz=0; }
      se = bas; ze =baz;
   }
   FOREVER {
      strcpy(a[rs] [rz],"");
      rz--;
      if(rs==se && rz<=ze) break;
      if(rz<0) { rz=SEITE; rs--; }
   }
   blo=0; MenueUeberwachung(0);
   y=MIY; FastText();
   while(ay<y) YZMinus();
   ZSDisplay(); CursorAn(); Locate(y,x);
   sprintf(buffer, "Block gelöscht!");
   meld = TRUE; sicher=FALSE;
}
BlockMarkieren()   
{
   int len, r, rs, rz;

   if(!blo) blo=1;
   if(blo==2) {    /* Blockende wird markiert */
      bes=s; bez=z;
      if(bes<bas) {  /* Blockanfang u. -ende vertauschen, wenn Ende ober- */
         len=bas; bas=bes; bes=len;  /* halb von Anfang */
         len=baz; baz=bez; bez=len;
      }
      if(bes==bas) {
         if(bez<baz) {
            len=bez; bez=baz; baz=len;
         }
      }
      len=s;r=z; rz=x; rs=y; blo++;
      CrsrTop(); FastText();
      s=len; z=r; x=rz; y=rs;
      ZSDisplay(); CursorAn(); Locate(y,x);
      sprintf(buffer, "Blockende markiert!");
      meld = TRUE;
      MenueUeberwachung(2);
   }
   else if(blo==1) {
      bas=s; baz=z; blo++;
      sprintf(buffer, "Blockanfang markiert!");
      meld=TRUE;
      MenueUeberwachung(1);
   }
   return(0);
}
MarkierungLoeschen()
{
   int as2, az2, ax, ay;

   MenueUeberwachung(0);
   blo=0;  as2=s; az2=z; ax=x; ay=y;
   CrsrTop();
   FastText();
   s=as2; z=az2; x=ax; y=ay;
   CursorAn(); Locate(y,x);
   ZSDisplay();
   sprintf(buffer, "Markierung gelöscht!");
   meld=TRUE;
}
MenueUeberwachung(bl) /* Je nach internem Status Menüleiste beeinflussen */
int bl;
{
   int len, h=SHIFTMENU(1);
   if(bl==1) {
      /* Dokument: Laden, Anhängen, Löschen, Speichern u. Drucken aus */
      OffMenu(Fenster, SHIFTMENU(0));
      for(len=1; len<=7; len=len+2)
         OffMenu(Fenster, SHIFTMENU(0)|SHIFTITEM(len));
      OffMenu(Fenster, SHIFTMENU(2));               /* Seitenlänge    aus */
      OffMenu(Fenster, SHIFTMENU(2)|SHIFTITEM(2));  /* Textbreite     aus */
      OffMenu(Fenster, h|SHIFTITEM(6));             /* Block Laden    aus */
      OnMenu(Fenster,  h|SHIFTITEM(4));             /* Mark. Löschen   an */
   }
   if(bl==2) {
      OnMenu(Fenster, h|SHIFTITEM(1));              /* Block Kopieren  an */
      OnMenu(Fenster, h|SHIFTITEM(2));              /* Block Löschen   an */
      OnMenu(Fenster, h|SHIFTITEM(7));              /* Block Speichern an */
      OnMenu(Fenster, h|SHIFTITEM(8));              /* Block Drucken   an */
      OffMenu(Fenster, h);                          /* Block Markier. aus */
   }
   if(bl==0) {
      /* Dokument: Laden, Anhängen, Löschen, Speichern u. Drucken an */
      OnMenu(Fenster, SHIFTMENU(0));
      for(len=1; len<=7; len=len+2)
         OnMenu(Fenster, SHIFTMENU(0)|SHIFTITEM(len));
      OnMenu(Fenster,  SHIFTMENU(2));               /* Seitenlänge     an */
      OnMenu(Fenster, SHIFTMENU(2)|SHIFTITEM(2));   /* Textbreite      an */
      OnMenu(Fenster,  h|SHIFTITEM(6));             /* Block Laden     an */
      OnMenu(Fenster,  h);                          /* Block Markier.  an */
      OffMenu(Fenster, h|SHIFTITEM(4));             /* Mark. Löschen  aus */
      OffMenu(Fenster, h|SHIFTITEM(1));             /* Block Kopieren aus */
      OffMenu(Fenster, h|SHIFTITEM(2));             /* Block Löschen  aus */
      OffMenu(Fenster, h|SHIFTITEM(7));             /* Block Speich.  aus */
      OffMenu(Fenster, h|SHIFTITEM(8));             /* Block Drucken  aus */
   }
}
BLaden(fname)     /* Text wird geladen und an der akt. Crsr-Pos. eingefügt */
UBYTE *fname;
{
   int es=se, ez=ze, ss=s, zz=z, err;

   sei=SEITE;
   FOREVER {
      StrKopie(a[MAS] [sei], a[se] [ze]);
      sei--; ze--;
      if(ze<0) {
         ze=SEITE; se--;
      }
      if(sei<0) {
         sei=SEITE; MAS--;
      }
      if(se==s && ze==z)
         break;
   }
   z++;
   if(z>SEITE) {
      z=0; s++;
   }
   ze=z; se=s;
   err = Laden(fname);
   ze++;
   if(ze>SEITE) {
      ze=0; se++;
      if(se>14) {
         se=14; ze=SEITE; sei=SEITE; MAS=14;
         goto sprung;
      }
   }
   z=sei+1; s=MAS; MAS=14; sei=SEITE;
   if(z>SEITE) {
      z=0; s++;
   }
   if((s==se && ze>=z) || (se>s)) {
      se=MAS; ze=SEITE;
      goto sprung;
   }
   FOREVER {
      StrKopie(a[se] [ze], a[s] [z]);
      z++;
      if(z>SEITE) {
         z=0; s++;
      }
      if(s>MAS)
         break;
      ze++;
      if(ze>SEITE) {
         ze=0; se++;
      }
   }
sprung:   if(err==TRUE) {
      x=MIX;y=MIY;s=ss;z=zz;
      FastText();
      s=ss; z=zz;x=MIX;y=MIY;
      CursorAn(); Locate(y,x);
      ZSDisplay();
      strcpy(buffer, str);
      Meldung(); sicher=FALSE;
   }
   else {
      se=es; ze=ez; s=ss; z=zz;
   }
}
Textlaenge() /* Längen der einzelnen Zeilen werden addiert und Ergebnis */
{            /* u. Textende werden angezeigt */
   int len,i, zaehler=0;

   for(len=0;len<=se;len++) {
      for(i=0;i<=SEITE;i++) {
         zaehler += strlen(a[len] [i]) +1;
         if(len==se && i==ze)
            break;
      }
   }
   sprintf(buffer, "Textlänge: %d Textende: Seite %d Zeile %d!",
            zaehler, se+1, ze+1);
   meld=TRUE;
}
BlockEinfuegen()  /* Block an der akt. Crsr-Pos. einfügen, falls */
{                 /* genügend Speicherplatz vorhanden */
   int es=se, ez=ze, ps, pz, err, hil;

   if((BloPruef()==TRUE)&&(!(bes==s && bez==z))) {
      sprintf(buffer, "Cursor innerhalb des Blocks!");
      meld=TRUE;
      return(0);
   }
   ze++; if(ze>SEITE) { ze=0; se++; }
   err=(MAS-se)*SEITE+SEITE-ze;             /* Anzahl der freien Zeilen */
   hil=(bes-bas-1)*SEITE+SEITE-baz+bez;     /* Blocklänge     in Zeilen */
   if(bes-bas>0) hil++;
   se=es; ze=ez;
   if(err<=0 || err<hil) {
      sprintf(buffer, "Zuwenig Textspeicher frei!");
      meld=TRUE;
      return(0);
   }
   err=FALSE;
   if(s<bas || (s==bas && z<baz)) err=TRUE;
   for(ps=0; ps<=hil; ps++) { ze++; if(ze>SEITE) { ze=0; se++; } }
   ps=se; pz=ze;
   if(!(es==s && ez==z)) {
      FOREVER {
         StrKopie(a[ps] [pz], a[es] [ez]);
         pz--; ez--;
         if(ez<0) {ez=SEITE; es--; }
         if(pz<0) {pz=SEITE; ps--; }
         if(es==s && ez==z) break;
      }
   }
   if(err==TRUE) {
      for(ps=0; ps<=hil; ps++) {
         bez++; baz++;
         if(baz>SEITE) { baz=0; bas++; }
         if(bez>SEITE) { bez=0; bes++; }
      }
   }
   ps=bas; pz=baz; es=s; ez=z; z++; if(z>SEITE) { z=0; s++; }
   FOREVER {
      StrKopie(a[s] [z], a[ps] [pz]);
      pz++; z++;
      if(ps==bes && pz>bez) break;
      if(pz>SEITE) { pz=0; ps++; }
      if(z >SEITE) {  z=0;  s++; }
   }
   pz=y; s=es; z=ez;
   CrsrTop(); FastText();
   y=pz; s=es; z=ez; CursorAn(); Locate(y,x); ZSDisplay();
   sprintf(buffer, "Block kopiert!");
   meld=TRUE; sicher=FALSE;
}
