#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
struct SimpleSprite { UWORD *posctldata,height,x,y,num; };

#define phZ 28 /*physikalische Zeilenzahl*/
#define maxZeilen 500 /*höchstens 500 Zeilen,textpuffer entsprechend ändern*/
extern struct Window *Dialog,*GWindow1;
extern struct IntuitionBase *IntuitionBase;
extern ULONG GfxBase;
extern struct IntuiMessage *message;
extern ULONG MessageClass;
extern USHORT code;
extern struct RastPort *DPort;
int ednprintpos =0; /*Schreibposition für Ausgaben mit nprint ins Editorf.*/
int KlammerNo=-1;
struct SimpleSprite KlammerSprite = {NULL,8,0,0,3};
struct paar { int knotentyp;
              WORD *CAR;
              WORD *CDR;
            };
struct { long int knotentyp;     /*dient zum Einfügen von Symbolinhalten*/
         char zeichenkette[40];
       } arbeitsatom;
struct varlist { int knotentyp;
                 struct varlist *links;
                 struct varlist *rechts;
                 struct paar *eintrag;
                 struct atom *name;
                 int lokalzahl;
               };
extern struct varlist *suchsymbol();
extern void output();
/*Kleinschrifttabelle :*/
char tabelle1[]="[1234567890ß'\\[0qwertzuiopü+]123asdfghjklöä#/456<yxcvbnm,.-  789 ";

/*Großschrifttabelle :*/
char tabelle2[]="]!\"§$%&/()=?`|{0QWERTZUIOPÜ*}123ASDFGHJKLÖÄ^ 456>YXCVBNM;:_  789 ";

/* transform wandelt RAW-Codes in ASCII-Codes um*/
BYTE ederr=0; /*wird nach Fehlermeldungen auf 1 gesetzt. */
BYTE ctrl=0; /*Flags zum Mitteilen der Sondertasten*/
BYTE alt=0;
char transform(code)
BYTE code;
{  static BYTE shift=0,CapsLock=0; /*shift gedrückt : 1 */
   static BYTE ct=0,al=0;
   char zeichen=0;
   BYTE los=0;
   if(code&128) {los=1; code&=127; } /*Bit 7 ausmaskieren*/
   alt=al;ctrl=ct;
   if(los)
   {  if((code==96)||(code==97)) shift=0; /*Shift losgelassen*/
      if(code==98) CapsLock=0;
      if((code==0x64)||(code==0x65)) alt=al=0;
      if(code==0x63) ctrl=ct=0;
   }
   else if(code<65)
   {  if((!shift)&&(!CapsLock)) zeichen=tabelle1[code];
            else zeichen=tabelle2[code];
      if((zeichen==')')||(zeichen=='s')||(zeichen=='q')||(zeichen=='e'))
         ct=al=0;
      if((zeichen=='ä')&&al) zeichen='\'';
   }
   else if((code>75)&&(code<80)) /*Cursortasten*/
        { zeichen=code-48;
          if(shift) /*Page up-down*/
             zeichen=code-73; /*3:up, 4:down, 5:right, 6:left*/
        }
   else if(code==65) /*Backspace*/
      zeichen=9;
   else if(code==70)  /*Vorsicht : Diese Zeichen sind keine ASCII !*/
      zeichen=8;
   else if((code>=80)&&(code<=83)) /* f1-f4 */
      zeichen=code-66;
   else if((code==96)||(code==97)) shift=1; /*Shift gedrückt*/
   else if(code==98) CapsLock=1;
   else if((code==0x64)||(code==0x65)) alt=al=1;
   else if(code==0x63) ctrl=ct=1;
   else if((code==68)||(code==67)) zeichen=13;
   if((code==0x42)&&(!los)) /*tab*/
   {  ctrl=1;ct=0; zeichen='t'; }
   return zeichen;
}
/* Gadgetdefinitionen für Sondereingaben */
struct IntuiText n1text =
{  1,3,JAM1,10,-11,0,
   NULL,0
};
struct IntuiText rqtxt =
{  1,3,JAM2,18,5,0,
   "ALisp-Requester",0
};
UBYTE DefString[40] = "\0";
UBYTE Undo [40];
struct StringInfo TextString =  /* Fuer Texte in Text-Gadgets */
{  DefString,Undo,0,40,0,0,0,0,0,0,NULL,0,NULL };
USHORT Rand[] =
{ -1,-1,201,-1,201,9,-1,9,-1,-1 };
struct Border StrBorder =
{  0,0,1,0,JAM1,5,&Rand[0],NULL };
struct Gadget Text_gad =
{  NULL,10,30,200,18,
   GADGHCOMP|SELECTED,
   STRINGCENTER|ENDGADGET|GADGIMMEDIATE,
   STRGADGET|REQGADGET,
   (APTR)&StrBorder,
   0,
   &n1text,
   0,
   (APTR)&TextString,
   0,0
};
struct Requester request =
{  NULL,210,56,220,50,0,0,&Text_gad,NULL,&rqtxt,REQACTIVE,3,
   NULL,NULL,NULL,NULL,NULL
};
/* typ = 0 : laden von modul8 aus*/
char *req(typ)
BYTE typ;
{  BYTE flag=1;
   DefString[0]=0;
   Text_gad.GadgetText=&n1text;
   Text_gad.Activation=STRINGCENTER|ENDGADGET|GADGIMMEDIATE;
   Text_gad.Flags=GADGHCOMP|SELECTED;
   /*Den Requester im Dialogfenster darstellen*/
   switch(typ)
   { case 0 : OffMenu(Dialog,2);
              if(GWindow1) WindowToBack(GWindow1);
              n1text.IText="Lispprogramm laden"; break;
     case 1 : n1text.IText="Datei laden"; break;
     case 2 : n1text.IText="Wort suchen"; break;
     case 3 : n1text.IText="Datei/Block speichern"; break;
     case 5 : n1text.IText="Symbolname :";break;
   }
   ModifyIDCMP(Dialog,REQCLEAR);
   if(!Request(&request,Dialog))
   { if(!typ) OnMenu(Dialog,2);
     return(DefString);
   }
   ActivateGadget(&Text_gad,Dialog,&request);
   while(flag)
   {  Wait(1<<Dialog->UserPort->mp_SigBit);
      while(message = (struct IntuiMessage *)GetMsg(Dialog->UserPort))
      {
         MessageClass = message->Class; /* Message retten */
         code = message->Code;
         ReplyMsg(message);    /* Message beantworten */
         if(MessageClass==REQCLEAR)
            flag=0;
      }
   }
   if(!typ)
   { ModifyIDCMP(Dialog,RAWKEY|MENUPICK|GADGETUP);
     if(GWindow1) WindowToFront(GWindow1);
     OnMenu(Dialog,2);
   }
   else
   { ModifyIDCMP(Dialog,RAWKEY|MENUPICK);
   }
   return(DefString);
}
/*------------------------------------*/

/* Editor - Menüs */
struct IntuiText edtext15 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "neues Dokument",
   NULL
  };
struct MenuItem edunter15 =
  {
   NULL,
   0,
   60,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext15,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext14 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Datei ausdrucken",
   NULL
  };
struct MenuItem edunter14 =
  {
   &edunter15,
   0,
   48,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext14,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext13 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Datei auswerten",
   NULL
  };
struct MenuItem edunter13 =
  {
   &edunter14,
   0,
   36,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext13,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext12 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Datei speichern",
   NULL
  };
struct MenuItem edunter12 =
  {
   &edunter13,
   0,
   24,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext12,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext11 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Quelltext laden",
   NULL
  };
struct MenuItem edunter11 =
  {
   &edunter12,
   0,
   12,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext11,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext10 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Interpreter     [Ctrl q]",
   NULL
  };
struct MenuItem edunter10 =
  {
   &edunter11,
   0,
   0,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext10,
   NULL,
   0,
   NULL,
   0
  };

struct IntuiText edtext25 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block speichern",
   NULL
  };
struct MenuItem edunter25 =
  {
   NULL,
   0,
   60,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext25,
   NULL,
   0,
   NULL,
   0
  };

struct IntuiText edtext24 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block auswerten",
   NULL
  };
struct MenuItem edunter24 =
  {
   &edunter25,
   0,
   48,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext24,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext23 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block löschen   [Ctrl e]",
   NULL
  };

struct MenuItem edunter23 =
  {
   &edunter24,
   0,
   36,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext23,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext22 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block verlagern [Ctrl m]",
   NULL
  };
struct MenuItem edunter22 =
  {
   &edunter23,
   0,
   24,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext22,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext21 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block kopieren  [Ctrl d]",
   NULL
  };
struct MenuItem edunter21 =
  {
   &edunter22,
   0,
   12,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext21,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext20 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Block markieren [Ctrl b]",
   NULL
  };
struct MenuItem edunter20 =
  {
   &edunter21,
   0,
   0,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext20,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext32 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Symbolwert einfügen",
   NULL
  };
struct MenuItem edunter32 =
  {
   NULL,
   0,
   24,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext32,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext31 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Klammern schließen [)]",
   NULL
  };
struct MenuItem edunter31 =
  {
   &edunter32,
   0,
   12,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext31,
   NULL,
   0,
   NULL,
   0
  };
struct IntuiText edtext30 =
  {
   0,
   1,
   JAM1,
   8,
   1,
   NULL,
   (UBYTE *) "Suchen          [Ctrl s]",
   NULL
  };
struct MenuItem edunter30 =
  {
   &edunter31,
   0,
   0,
   208,
   10,
   ITEMTEXT|ITEMENABLED|HIGHCOMP,
   0,
   (APTR) &edtext30,
   NULL,
   0,
   NULL,
   0
  };
struct Menu edober3 =
  {
   NULL,
   400,
   0,
   200,
   10,
   MENUENABLED,
   "Spezial",
   &edunter30
  };
struct Menu edober2 =
  {
   &edober3,
   200,
   0,
   200,
   10,
   MENUENABLED,
   "Blockbefehle",
   &edunter20
  };
struct Menu edober1 =
  {
   &edober2,
   0,
   0,
   200,
   10,
   MENUENABLED,
   "System",
   &edunter10
  };
ULONG *freispeicherliste;
char *edtextp=0; /*Zeiger auf den Textpuffer*/
struct { char *le[1]; } *zei=0L; /*dynamisches Feld zeile :*/
/*Zeiger auf die Zeilenanfänge*/
int anzZeilen=0;

BYTE EDACTIVE=0; /*Flag : Editor ein- oder ausgeschaltet*/

extern struct SimpleSprite CursorSprite;

struct IntuiText edtext =  /*Ausgabe im Editor*/
  {
   1,
   0,
   JAM2,
   8,
   13,
   NULL,
   "",
   NULL
  };

int edx,edy,edoben; /*Positionen im Fenster*/
int blockanfang=-1,blockende=-1;
BYTE edcheck()
{ char *z;
  if(anzZeilen!=1) return(0);
  z=zei->le[0];
  while(*z==' ') z++;
  return(!(BYTE)(*z));
}
void printcursor()
{  static char zp[6];
   static int x=0,y=0,z=1;
   MoveSprite(&(Dialog->WScreen->ViewPort),&CursorSprite,(edx<<3)+6,((edy-edoben)<<3)+12);
   edtext.FrontPen=3; edtext.IText=zp;
   if(edx!=x)
   {  sprintf(zp,"%2d",(x=edx));
      PrintIText(DPort,&edtext,16,(phZ*8+3));
   }
   if(edy!=y)
   {  sprintf(zp,"%3d",(y=edy));
      PrintIText(DPort,&edtext,56,(phZ*8+3));
   }
   if(anzZeilen!=z)
   {  sprintf(zp,"(%3d)",(z=anzZeilen));
      PrintIText(DPort,&edtext,584,(phZ*8+3));
   }
   if(ederr)  /*Fehlermeldungen löschen, muß als letztes hier stehen*/
   {  ederr=0;
      edtext.IText="                              ";
      PrintIText(DPort,&edtext,88,(phZ*8+3));
   }
   if(KlammerNo>=0)
   {  FreeSprite(KlammerNo); KlammerNo=-1; }
}
void printederr(nr)
int nr;
{  ederr=1;
   switch(nr)
   { case 0 : edtext.IText="Zeile voll"; break;
     case 1 : edtext.IText="Block nicht markiert"; break;
     case 2 : edtext.IText="Datei nicht geöffnet"; break;
     case 3 : edtext.IText="Maximale Zeilenzahl erreicht"; break;
     case 4 : edtext.IText="Schreib-/Lesefehler"; break;
     case 5 : edtext.IText="Suche ergebnislos"; break;
     case 6 : edtext.IText="Cursor innerhalb des Blocks"; break;
     case 7 : edtext.IText="Zuviele geschlossene Klammern"; break;
     case 8 : edtext.IText="Klammer nicht auf dieser Seite"; break;
     case 9 : edtext.IText="Cursor im String/Kommentar";break;
     case 10: edtext.IText="Symbol existiert nicht";break;
     case 11: edtext.IText="Blockanfang markiert";break;
   }
   edtext.FrontPen=3;
   PrintIText(DPort,&edtext,88,(phZ*8+3));
}
BYTE ZNR=1,ZPG=1; /*Zeilennummern/Seitennummern ?*/
int firstNR=0;
int firstPAGE=1;
int linespP=50;
char kopftext[75]="Listing : .lsp";
extern BYTE printerreq();
void callprinter()   /*druckt den Pufferinhalt aus*/
{  long int handle;
   char puffer[85],*z1,*z2;
   int i=0,j=0,h=0,seite,zeile;
   seite=firstPAGE;
   zeile=firstNR;
   MoveSprite(&(Dialog->WScreen->ViewPort),&CursorSprite,0,255);
   if(!printerreq()) { printcursor(); return();}
   printcursor();
   z1=kopftext; while(*z1) {z1++;h++; } /*Kopfzeile mit Leerzeichen füllen*/
   while(h++<74) *z1++=' '; *z1=0;
   handle=open("PRT:",1,i); /*i als dummy*/
   if(handle!=-1)
   {  i=write(handle,kopftext,74);
      if(i!=74) { close(handle); return(); }
      if(ZPG) { sprintf(puffer,"%3d\n\n",seite++);i=write(handle,puffer,5);}
      else  i=write(handle,"\n\n",2);
      for(j=0;j<anzZeilen;j++) /*alle Zeilen ausgeben*/
      { if((j>0)&&(j%linespP==0))
        {  i=write(handle,"\f",1); /*form-feed*/
           i=write(handle,kopftext,74);
           if(ZPG) { sprintf(puffer,"%3d\n\n",seite++);i=write(handle,puffer,5);}
           else i=write(handle,"\n\n",2);
        }
        if(ZNR)
        { sprintf(puffer,"%3d ",zeile++);
          z1=puffer+4; i=h=4;
        }
        else {z1=puffer; i=h=2; }
        z2=zei->le[j];
        while(*z2) { *z1++=*z2; if((*z2++)!=' ') h=i; i++; }
        *((char *)(puffer+h+1))='\n';
        i=write(handle,puffer,h+2);/*und ausdrucken*/
        if(i!=h+2) j=anzZeilen; /*Fehler aufgetreten.*/
      }
      close(handle);
   }
}
void display() /*stellt den aktuellen Ausschnitt dar !*/
{  int i=0;
   char puffer[15];
   SetAPen(Dialog->RPort,0);            /*Fenster löschen*/
   RectFill(Dialog->RPort,2,12,637,phZ*8+12);
   SetAPen(Dialog->RPort,1);
   while((i<phZ)&&(edoben+i<anzZeilen))
   {  edtext.IText=zei->le[edoben+i];
      if((blockanfang<=edoben+i)&&(blockende>=edoben+i))
         edtext.FrontPen=2;
      else
         edtext.FrontPen=1;
      PrintIText(DPort,&edtext,0,(i++)<<3);
   }
   edtext.IText=puffer;
   sprintf(puffer,"x:%2d y:%3d",edx,edy);
   edtext.FrontPen=3;
   PrintIText(DPort,&edtext,0,(phZ*8+3));
   sprintf(puffer,"(%3d)",anzZeilen);
   PrintIText(DPort,&edtext,584,(phZ*8+3));
   printcursor();
}

void zeilendruck()
{ void edclose();
  edtext.IText=zei->le[edy];
  if((blockanfang<=edy)&&(blockende>=edy))
    edtext.FrontPen=2;
  else
    edtext.FrontPen=1;
  PrintIText(DPort,&edtext,0,(edy-edoben)<<3);
}

void updisplay()
{ if(edy+1>=anzZeilen) return();
  edy++; edoben++;
  ScrollRaster(DPort,0,8,4,13,635,12+8*phZ);
  edtext.IText=zei->le[edy];
  if((blockanfang<=edy)&&(blockende>=edy))
    edtext.FrontPen=2;
  else
    edtext.FrontPen=1;
  PrintIText(DPort,&edtext,0,8*(phZ-1));
  printcursor();
}

void downdisplay()
{ if(edoben<=0) return();
  edoben--;edy--;
  ScrollRaster(DPort,0,-8,4,13,635,12+8*phZ);
  edtext.IText=zei->le[edy];
  if((blockanfang<=edy)&&(blockende>=edy))
    edtext.FrontPen=2;
  else
    edtext.FrontPen=1;
  PrintIText(DPort,&edtext,0,0);
  printcursor();
}

void unmark() /*hebt Blockmarkierungen auf*/
{  int i,merke;
   if((blockende>=edoben)&&(blockanfang<=edoben+phZ-1)) /*Bereich sichtbar*/
   {  i=blockanfang; blockanfang=32000; /* wird nie erreicht*/
      if(i<edoben) i=edoben;
      merke=edy;
      while((i<=blockende)&&(i<=edoben+phZ-1))
      { edy=i++; zeilendruck(); }
      edy=merke;
   }
   blockanfang=blockende=-1;
}

void mark() /*markiert einen Block*/
{  int i,merke;
   if((blockanfang<=edoben+phZ-1)&&(blockende>=edoben)) /*Bereich sichtbar*/
   {  i=blockanfang;
      if(i<edoben) i=edoben;
      merke=edy;
      while((i<=blockende)&&(i<=edoben+phZ-1))
      { edy=i++; zeilendruck(); }
      edy=merke;
   }
}
void newdoc() /*richtet neues Dokument ein, löscht altes*/
{  int i;
   char *x;
   edx=0;edy=0;edoben=0;
   freispeicherliste=edtextp+80;
   for(i=1;i<499;i++) /*Freispeicherliste initialisieren*/
     *((ULONG *)(edtextp+80*i))=(edtextp+80*(i+1));
   *((ULONG *)(edtextp+80*499))=0L; /*Listenende*/
   /*erste Zeile definieren :*/
   x=edtextp;
   for(i=0;i<78;i++) *x++=' ';
   *(edtextp+78)=0; /*Endmarkierung der ersten Zeile*/
   anzZeilen=1; zei->le[0]=edtextp;
   blockanfang=blockende=-1;
}
WORD *KData; /*Daten für das Klammersprite*/
BYTE edinit()
{  void edclose();
   ULONG *z;
   int i;
   edtextp=AllocMem(maxZeilen*80,1L);
   if(edtextp<=0L) return(0);
   zei=AllocMem(maxZeilen*4,1L);
   if(zei<=0L) {edclose(); return(0);}
   KData=AllocMem(40L,3L);
   if(KData>0)
   {  KlammerSprite.posctldata=KData;
      z=KData;
      *z++=0L;*z++=0xf0000000; for(i=0;i<6;i++) *z++=0x80000000;
      *z++=0xf0000000; *z=0L;
      SetRGB4(&(Dialog->WScreen->ViewPort),21,13,4,1);
   }
   newdoc();
   return(1);
}

void edclose()
{  if(edtextp>0) FreeMem(edtextp,maxZeilen*80);
   edtextp=0L;
   if(zei>0) FreeMem(zei,maxZeilen*4);
   if(KData>0) FreeMem(KData,40L);
   zei=0;
}

void insertline()
{  char *z1,*z2;
   int i;
   if(anzZeilen>=maxZeilen) /*Puffer voll*/
   {  DisplayBeep(Dialog->WScreen); printederr(3); return(); }
   for(i=anzZeilen-1;i>edy;i--)
     zei->le[i+1]=zei->le[i];
   anzZeilen++;
   if(blockanfang>edy) blockanfang++;
   if(blockende>edy) blockende++;
   zei->le[edy+1]=freispeicherliste;
   freispeicherliste=*freispeicherliste;
   z1=zei->le[edy]+edx; z2=zei->le[edy+1];
   for(i=edx;i<78;i++)
   {  *z2++=*z1; *z1++=' '; }
   for(i=78-edx;i<78;i++) *z2++=' '; *z2=0;
   edx=0;
   zeilendruck();edy++; /*letzte Zeile erneuern*/
   if((edy+1==anzZeilen)&&(edy-edoben<phZ)) /*Zeile einfach ausgeben*/
     zeilendruck();
   else if(edy-edoben<phZ) /*neue Zeile paßt noch drauf*/
        { ScrollRaster(DPort,0,-8,4,13+((edy-edoben)<<3),635,12+8*phZ);
          zeilendruck();
        }
        else /*neue Zeile paßt nicht mehr*/
        { ScrollRaster(DPort,0,8,4,13,635,12+8*phZ);
          edoben++; zeilendruck();
        }
   printcursor();
}

void delline()
{  int i;
   char *z;
   if(anzZeilen==1)
   {  z=zei->le[0]; for(i=0;i<78;i++) *z++=' ';
      edx=0; zeilendruck(); printcursor(); return();
      /*eine Zeile muß existieren !*/
   }
   z=zei->le[edy];
   for(i=edy;i<anzZeilen-1;i++)
     zei->le[i]=zei->le[i+1];
   anzZeilen--;
   *((ULONG*)z)=freispeicherliste;
   freispeicherliste=z;
   if(blockanfang>edy) blockanfang--;
   if(blockende>=edy) blockende--;
   if(blockanfang>blockende) { blockanfang=blockende=-1; }
   if((edy!=0)&&(edy==edoben))
   { edoben--;edy--; display(); }
   else
   {  ScrollRaster(DPort,0,8,4,13+((edy-edoben)<<3),635,12+8*phZ);
      if(edy!=0) edy--;
      if(edoben+phZ-1<anzZeilen)
      {  i=edy; edy=edoben+phZ-1; zeilendruck(); edy=i; }
      printcursor();
   }
}

void copyblock()
{  int laenge,i;
   laenge=blockende-blockanfang+1;
   if((blockende<0)||(blockende<blockanfang))
   { DisplayBeep(Dialog->WScreen); printederr(1); return(); }
   if(anzZeilen+laenge>maxZeilen)
   { DisplayBeep(Dialog->WScreen); printederr(3); return(); }
   if((edy>=blockanfang)&&(edy<=blockende))
   {  DisplayBeep(Dialog->WScreen); printederr(6);return(); }
   /*Speicherliste umkopieren*/
   for(i=anzZeilen-1;i>=edy;i--)
     zei->le[i+laenge]=zei->le[i];
   if(blockanfang>edy) blockanfang+=laenge; /*wurde mitverschoben*/
   for(i=edy;i<edy+laenge;i++) /*neue Zeilen anlegen*/
   {  zei->le[i]=freispeicherliste;
      freispeicherliste=*freispeicherliste;
      strcpy(zei->le[i],zei->le[blockanfang+i-edy]);
   }
   blockanfang=blockende=-1; /*Blockbindung aufheben*/
   anzZeilen+=laenge;
   display();
}
void moveblock()
{  char *merke;
   int laenge,i,j,pos;
   laenge=blockende-blockanfang+1;
   if((blockende<0)||(blockende<blockanfang))
   { DisplayBeep(Dialog->WScreen); printederr(1); return(); }
   if((edy>=blockanfang)&&(edy<=blockende))
   {  DisplayBeep(Dialog->WScreen); printederr(6);return(); }
   /*Speicherliste umkopieren*/
   pos=edy;
   if(edy<blockanfang) /*hochkopieren*/
   {  for(i=0;i<laenge;i++)
      {  merke=zei->le[blockanfang+i];
         for(j=blockanfang+i-1;j>=pos;j--)
            zei->le[j+1]=zei->le[j];
         zei->le[pos++]=merke;
      }
   }
   else /*runterkopieren*/
   {  for(i=0;i<laenge;i++)
      {  merke=zei->le[blockanfang];
         for(j=blockanfang+1;j<pos;j++)
            zei->le[j-1]=zei->le[j];
         zei->le[pos-1]=merke;
      }
   }
   blockanfang=blockende=-1;
   display();
}
/* Variableninhalte einfügen*/
void insertvalue()
{  struct varlist *merke;
   void transfer1();
   int oben;
   if(anzZeilen==maxZeilen) {printederr(3); return(); }
   strcpy(arbeitsatom.zeichenkette,req(5));
   merke=suchsymbol(&arbeitsatom,0);
   if(!merke) {printederr(10); return();}
   ednprintpos=0;
   output(merke->eintrag->CAR); /*Symbolinhalt puffern*/
   if(edcheck()) /*ev. erster Eintrag ?*/
   {  EDACTIVE=0;transfer1();EDACTIVE=1;display(); }
   else
   { blockanfang=anzZeilen;
     EDACTIVE=0;transfer1();EDACTIVE=1; /*keine Fehlermeldung ausgeben*/
     blockende=anzZeilen-1;
     moveblock();
   }
}
void delblock()
{  int laenge,i;
   char *z;
   laenge=blockende-blockanfang+1;
   if((blockende<0)||(blockende<blockanfang))
   {  DisplayBeep(Dialog->WScreen); printederr(1); return(); }
   for(i=blockanfang;i<anzZeilen-laenge;i++)
   {  if(i<=blockende)
      { *((ULONG*)zei->le[i])=freispeicherliste;
        freispeicherliste=(ULONG *)zei->le[i];
      }
      zei->le[i]=zei->le[i+laenge];
   }
   anzZeilen-=laenge;
   if(edy>blockende) {edy-=laenge; edoben-=laenge; }
   else if(edy>=blockanfang)
   {  edy=blockanfang-1;
      if(edoben>=blockanfang)
         edoben=blockanfang-1;
   }
   if(edy<0) edoben=edy=0;
   /*Vorsicht ev. alle ! Zeilen gelöscht :*/
   if(anzZeilen==0)
   {  anzZeilen=1; zei->le[0]=freispeicherliste;
      freispeicherliste=*freispeicherliste;
      z=zei->le[0];
      for(i=0;i<78;i++) *z++=' '; *z=0;
   }
   blockanfang=blockende=-1;
   display();
}

void closebrackets()
{  int i,j=0,h=0,zaehler=0;
   BYTE string=0,flag;
   char *z;
   if(edx==0) {h=1;j=-1;} /*nur bis zur vorangehenden Zeile suchen*/
   for(i=0;i<=edy-h;i++)  /*alle Zeilen bis zur Position durchsuchen*/
   {  z=zei->le[i];flag=1;
      while((*z!=0)&& flag &&(j<edx))
      { if(i==edy) j++;
        switch(*z)
        { case ';' : if(!string) flag=0; else z++; break;/*Kommentar*/
          case '"' : if(string) string=0; else string=1; z++; break;
          case '(' : if(!string) zaehler++; z++; break;
          case ')' : if(!string) zaehler--; z++; break;
          default  : z++;
        }
      }
   } j=0;
   if(((!flag)&&(!h))||string) {printederr(9); return(); }
   if(zaehler==0) return(); /*alles ok*/
   if(zaehler<0) { DisplayBeep(Dialog->WScreen); printederr(7); return(); }
                 /*zuviele Klammern*/
   while(zaehler)
   { while((*(zei->le[edy]+77)==' ')&&zaehler) /*einfügen*/
     {  zaehler--;
        z=zei->le[edy]+76;
        for(i=76;i>=edx;i--)
        { *(z+1)=*z; z--; }
        *(z+1)=')';
     }
     zeilendruck();
     if(zaehler) /*neue Zeile einfügen*/
     {  if(anzZeilen<maxZeilen)
        { if(j==1) {edx=78; insertline(); }
          else { j=edx; insertline(); edx=j; edy--; j=1; }
        }
        else { zaehler=0; DisplayBeep(Dialog->WScreen); printederr(3);}
     }
   }
   printcursor();
}
void showbracket() /*zeigt jeweils die korrespondierende Klammer an*/
{ char *z;
  int i,j=0,nr=1;
  char string=0,flag;
  /*feststellen, ob Position in einem String liegt*/
  for(i=edoben;i<=edy;i++)
  {  z=zei->le[i]; *(z+79)=string; flag=1;
     /*Markierungen in leerstehendes Zeichen eintragen*/
     while((*z)&&flag&&(j<edx))
     {  if(i==edy) j++;
        switch(*z)
        { case ';' : if(!string) {*(zei->le[i]+79)|=1; flag=0;} break;
          case '"' : if(string) string=0; else string=2; break;
        }
        z++;
     }
  }
  if(string||(!flag))
  {  printederr(9);return();} /* Cursor steht in einem String/Kommentar */
  i=edx-2;z=zei->le[edy]+i;flag=0;j=edy;
  while((nr>0)&&(j>=edoben))
  {  while((i>=0)&&(nr>0))
     {  if(!string)
        {  if(*z==')') nr++;
           else if(*z=='(') nr--;
           else if(*z=='"') string=1;
           z--; i--;
        }
        else
        {  if(*z=='"') string=0; z--;i--; }
     } j--;
     if((nr>0)&&(j>=edoben)) /*vorangehende Zeile untersuchen*/
     {  z=zei->le[j]+77;i=77;
        if(*(zei->le[j]+79)&1) /*Zeile endet mit Kommentar */
        {  i=0; z=zei->le[j]; string=(*(zei->le[j]+79))&2;
           while((i<77)&&((*z!=';')||string))
           { if(*z=='"') {if(string) string=0; else string=1; }
             z++;i++;
           }
           i--; z--; string=0; /*ein Zeichen vor Kommentar*/
        }
     }
  }
  if(nr==0)
  {  if(KlammerNo<0)
     { *KData=0; *(KData+1)=0; KlammerNo=GetSprite(&KlammerSprite,3);}
     if(KlammerNo>=0)
       MoveSprite(&(Dialog->WScreen->ViewPort),&KlammerSprite,((i+1)<<3)+6,(((j+1)-edoben)<<3)+12);
  }
  else printederr(8);
}
extern char *textpuffer;
void transfer1() /*Puffer->Editor*/
{ char *z1,*z2,*z;
  int i;
  BYTE flag;
  if(anzZeilen>=maxZeilen) {DisplayBeep(Dialog->WScreen); printederr(3); return(); }
  z1=textpuffer; flag=edcheck();
  do
  {  if(flag)
     { z2=zei->le[0]; flag=0; }
     else
     { z2=freispeicherliste;
       zei->le[anzZeilen++]=freispeicherliste;
       freispeicherliste=*freispeicherliste;
     }
     i=0;
     while((*z1)&&(*z1!='\n')&&(i<78))
     { i++;  *z2++=*z1++; }
     if((i==78)&&(*(z2-1)!=' ')) /*Zeilenumbruch erforderlich*/
     {  i=76; z=z1-2;
        while((i>3)&&(*z!=' ')) { i--; z--; }
        if(i>3)
        { i++; z1=z+1; z2=z2-(78-i); }
        else i=78; /*klappt aber nicht*/
     }
     if(i<78) while(i++<78) *z2++=' ';
     *z2=0;
     if(*z1=='\n') z1++;
  }while((*z1)&&(anzZeilen<maxZeilen));
  if(EDACTIVE) display();
  if((anzZeilen==maxZeilen)&&(*z1)){DisplayBeep(Dialog->WScreen);
     if(EDACTIVE) printederr(3);}/*paßte nicht !*/
}
void transfer2(unten,oben) /*kopiert einen Editorbereich in den Puffer*/
{ char *z1,*z2,*z3;
  int i;
  z1=textpuffer;
  for(i=unten;i<=oben;i++)
  { z2=zei->le[i];z3=z2+77;
    while((z3>=z2)&&(*z3==' ')) z3--;
    while(z2<=z3) *z1++=*z2++; /*Zeilenenden nicht mitkopieren*/
    *z1++='\n';
  }
  *(z1-1)=0;
}
void reumbruch() /*kittet zwei Zeilen wieder zusammen*/
{ int i=78,j=0;
  char *z1,*z2;
  z1=zei->le[edy]+77;z2=zei->le[edy-1]+77;
  while((*z1==' ')&&(i>0)) {z1--; i--; } z1=zei->le[edy];
  while((*z2==' ')&&(j<78)) {z2--; j++; } z2++;
  if(i<j) /*paßt noch in die vorangehende Zeile*/
  {  while((i--)>0)
       *z2++=*z1++;   /*Zeile hochkopieren*/
     delline();       /*korrigiert auch die Darstellung */
     edx=78-j; zeilendruck(); printcursor();
  }
  else printederr(0);
}
void suchen(begriff) /*sucht eine Zeichenkette und zeigt sie an*/
char *begriff;
{ BYTE flag=1;
  int x,y;
  char *z1,*z2,*z3;
  static char letzteSuche[31]="";
  if(*begriff==0) strcpy(begriff,letzteSuche);
  else strcpy(letzteSuche,begriff);
  x=edx+1;y=edy;
  z2=zei->le[edy]+edx+1;
  while(flag&&(y<anzZeilen))
  { if(x>=78) /* nächste Zeile*/
    {  y++; x=0; z2=zei->le[y]; }
    else
    { z3=z2;
      z1=begriff;
      while((*z3==*z1)&&(*z1)) { z3++; z1++; }
      if(!(*z1)) /*gefunden*/
        flag=0;
      else
      { x++;z2++; }
    }
  }
  if(!flag)
  {  edx=x;edy=y; edoben=edy; display(); }
  else printederr(5);
}
extern char freqtext[],realfilename[];
extern int dir();
extern int AReq();
extern BYTE load(),esave();
extern struct Menu ober1;
BYTE ed() /*Editoraufruf, gibt 1 zurück, falls Daten übertragen werden*/
{  BYTE ende=1,nachricht=0;
   int i;
   char zeichen,*z1,*z2,puffer[6];
   EDACTIVE=1;
   SetWindowTitles(Dialog,"ALisp - Editorfenster",-1);
   if(GWindow1) WindowToBack(GWindow1); /*Grafik ausblenden*/
   SetAPen(Dialog->RPort,0);            /*Fenster löschen*/
   RectFill(Dialog->RPort,2,200,637,254);
   SetAPen(Dialog->RPort,1);
   edtext.FrontPen=3;
   edtext.IText="x:   y:";
   SetAPen(Dialog->RPort,1);
   Move(DPort,0,phZ*8+14); Draw(DPort,639,phZ*8+14);
   PrintIText(DPort,&edtext,0,(phZ*8+3));
   sprintf(puffer,"(%3d)",anzZeilen); edtext.IText=puffer;
   PrintIText(DPort,&edtext,584,(phZ*8+3));
   edtext.FrontPen=1;
   ON_DISPLAY;
   display();
   SetMenuStrip(Dialog,&edober1);
   do
   {  Wait(1<<Dialog->UserPort->mp_SigBit);
      while((message=GetMsg(Dialog->UserPort))&&ende)
      {  MessageClass=message->Class;
         code=message->Code;
         ReplyMsg(message);
         if((MessageClass==RAWKEY)||(MessageClass==MENUPICK))
         {  if(MessageClass==RAWKEY)
               zeichen=transform(code);
            else
            { zeichen=0;
              if(MENUNUM(code)!=MENUNULL)
               switch(MENUNUM(code))
               {case 0: switch(ITEMNUM(code))
                        { case 0: zeichen='q'; ctrl=1; break; /*Quit*/
                          case 1: strcpy(freqtext,"Quelltext laden");
                                  i=dir();
                                  if(!i)  break;
                                  if(i==1) z1=req(1);
                                      else z1=realfilename;
                                  i=(int)load(z1,1); /*laden*/
                                  if(i==1){transfer1();}/*geklappt*/
                                  else /*Fehlerauswertung*/
                                  {  DisplayBeep(Dialog->WScreen);
                                     printederr(i); }
                                  break;
                          case 2: transfer2(0,anzZeilen-1);
                                  strcpy(freqtext,"Quelltext sichern");
                                  i=dir();
                                  if(!i) break;
                                  if(i==1) z1=req(3);
                                      else z1=realfilename;
                                  i=(int)esave(z1);
                                  if(i!=1) {DisplayBeep(Dialog->WScreen);printederr(i);}
                                  break;
                          case 3: transfer2(0,anzZeilen-1);nachricht=1;
                                  zeichen='q'; ctrl=1; break;
                          case 4: callprinter(); break;
                          case 5: if(AReq()){newdoc(); display();} break;
                        } break;
                case 1: switch(ITEMNUM(code))
                        { case 0: zeichen='b'; ctrl=1; break;
                          case 1: zeichen='d'; ctrl=1; break;
                          case 2: zeichen='m'; ctrl=1; break;
                          case 3: zeichen='e'; ctrl=1; break;
                          case 4: if(blockende<0) { DisplayBeep(Dialog->WScreen);
                                                    printederr(1);break; }
                                  transfer2(blockanfang,blockende);
                                  nachricht=1;
                                  zeichen='q'; ctrl=1; break;
                          case 5: /*Block speichern*/
                                  if(blockende<0) { DisplayBeep(Dialog->WScreen);
                                                    printederr(1);break; }
                                  transfer2(blockanfang,blockende);
                                  strcpy(freqtext,"Block sichern");
                                  i=dir(); zeichen=0;
                                  if(!i) break;
                                  if(i==1) z1=req(3);
                                      else z1=realfilename;
                                  i=(int)esave(z1);
                                  if(i!=1){DisplayBeep();printederr(i);}
                                  break;
                        } break;
                case 2: switch(ITEMNUM(code))
                        { case 0: zeichen='s'; ctrl=1; break;
                          case 1: zeichen=')'; ctrl=1; break;
                          case 2: insertvalue(); break;
                        } break;
               }
            }
            if(((unsigned int)zeichen>31)&&(zeichen!=(char)222)&&(zeichen!=(char)254)&&
            (!ctrl)&&((!alt)||(zeichen=='\''))) /*Zeichen druckbar*/
            {  if(*(zei->le[edy]+77)==' ') /*paßt noch in die Zeile*/
               {  z1=zei->le[edy]+77;z2=z1-1;
                  for(i=76;i>=edx;i--)
                    *z1--=*z2--;
                  *(zei->le[edy]+edx)=zeichen;
                  zeilendruck();
                  if(edx<=76) { edx++; printcursor(); }
                  if(zeichen==')') showbracket();
               }
               else
               { if((edx<77)||(anzZeilen==maxZeilen))
                 { DisplayBeep(Dialog->WScreen);
                   if(edx<77) printederr(0);
                         else printederr(3);}
                 else /*neue Zeile beginnen*/
                 { /*Trennzeichen suchen*/
                   if((zeichen=='(')||(zeichen==')')||(zeichen==' '))
                     i=78;
                   else
                   { i=77; z1=zei->le[edy]+77;
                     while((i>1)&&(*z1!='(')&&(*z1!=')')&&(*z1!=' '))
                     {  z1--; i--; }
                     if(i<=1) /*Umbruch nicht möglich !*/
                       i=78;
                     else i++;
                   }
                   edx=i; insertline(); edx=78-i;
                   *(zei->le[edy]+edx++)=zeichen;
                   zeilendruck();printcursor();
                   if(zeichen==')') showbracket();
                 }
               }
            }
            else
             switch(zeichen)
             { case 'q':ende=0;break; /*vorl.Ende nach F1*/
               case 16:
               case  3: if(edy==0) break;
                        if(edoben>phZ-1) {edoben-=phZ; edy-=phZ; }
                        else { edoben=edy=0; }
                        display(); break;
               case 17:
               case  4: if(edy==anzZeilen-1) break;
                        if(edoben<anzZeilen-phZ)
                          {edoben+=phZ; edy+=phZ;
                           if(edy>=anzZeilen) edy=anzZeilen-1; display(); }
                        else {edy=anzZeilen-1; printcursor(); }
                        break;
               case  5: /*zum Zeilendende/-anfang*/
                        z1=zei->le[edy]+77;i=77;  /*Zeilenende suchen*/
                        while((*z1--==' ')&&(i>0)) i--;
                        i++; if(i>77) i=77;
                        edx=i; printcursor(); break;
               case  6: edx=0; printcursor(); break;
               case  8: if(edx>=77)
                        {edx=77; *(zei->le[edy]+77)=' ';zeilendruck();break;}
                        edx++; /*Del*/
               case  9: if(edx==0) /*Backspace*/
                        { if(edy>0) reumbruch();
                        }
                        else
                        { z1=zei->le[edy]+edx-1;z2=z1+1;
                          for(i=edx;i<78;i++)
                            *z1++=*z2++;
                          *(zei->le[edy]+77)=' '; edx--;
                          zeilendruck();printcursor();
                        }
                        break;
               case 14:
               case 28: if(!ctrl)
                        { if(edy==0) break;
                          if(edy==edoben) downdisplay();
                          else { edy--; printcursor(); }
                        }
                        else
                          if(edy>0) {edoben=edy=0; display(); }
                        break;
               case 15:
               case 29: if(!ctrl)
                        { if(edy+1>=anzZeilen) break;
                          if(edy==edoben+phZ-1) updisplay();
                          else { edy++; printcursor(); }
                        }
                        else if(anzZeilen-edoben>phZ)
                        {  edoben=anzZeilen-phZ;edy=anzZeilen-1; display(); }
                        else { edy=anzZeilen-1; printcursor(); }
                        break;
               case 30: if(!ctrl)
                        { if(edx>76) break;  /*Zeichen nach rechts*/
                          edx++; printcursor();
                        }
                        else
                        { i=edx+1; z1=zei->le[edy]+i;
                          while((i<78)&&(*z1!='(')&&(*z1!=')'))
                          {  i++; z1++; }
                          if(i<78) { edx=i; printcursor(); }
                        } break;
               case 31: if(!ctrl)
                        {  if(edx==0) break;
                           edx--; printcursor();
                        }
                        else
                        { i=edx-1; z1=zei->le[edy]+i;
                          while((i>=0)&&(*z1!='(')&&(*z1!=')'))
                          {  i--; z1--; }
                          if(i>=0) { edx=i; printcursor(); }
                        } break;
               case 13: if(ctrl&&(anzZeilen<maxZeilen)) edx=78;
                        insertline();
                        break;
               case 'b':if((blockanfang<0)||(blockende>=0))
                        { if(blockende>=0) unmark();
                          blockanfang=edy;
                          printederr(11);
                        }
                        else
                        {  if(blockanfang>edy)
                           { blockende=blockanfang;
                             blockanfang=edy;
                           }
                           else
                             blockende=edy;
                           mark();
                        }
                        break;
               case 'y':delline();break;
               case 'd':copyblock(); break;
               case 'm':moveblock(); break;
               case 'e':if(AReq()) delblock(); break;
               case ')':closebrackets(); break;
               case 't':if(edx<74) {edx+=4; printcursor(); } break;
               case 'i':if(anzZeilen<maxZeilen){edx=78;insertline();} break;
               case 's':z1=req(2); suchen(z1); break;
               default : ;
             }
         }
      }
   }while(ende);
   OFF_DISPLAY;
   ClearMenuStrip(Dialog);
   SetMenuStrip(Dialog,&ober1);
   SetWindowTitles(Dialog,"ALisp - Dialogfenster",-1);
   if(GWindow1) WindowToFront(GWindow1); /*Grafik einblenden*/
   if(KlammerNo>=0) { FreeSprite(KlammerNo); KlammerNo=-1; }
   EDACTIVE=0;
   return(nachricht);
}
