/******************************************************************
                           EDI-druck

    Programm, das alles, was über die PIPE:edi-druck angeliefert 
    wird, auf den Drucker ausgibt und die in der Datei        
    "s:edi-ersetz" aufgeführten Makros durch entsprechende 
    Steuerzeichen ersetzt. Das Programm beendet sich selbst, wenn 
    es den ASCII-Wert 128 aus der PIPE: liest. 

    In der ersten Zeile können einige Parameter übergeben werden,
    wenn diese mit einem "%"-Zeichen beginnt. Dazu gehören die 
    Anzahl der Zeilen pro Seite, eine Seiten-Nummerierung, sowie
    ein automatisches Überspringen der Perforation

******************************************************************/

#include "exec/tasks.h"
#include "exec/memory.h"
#include "intuition/intuitionbase.h"
#include "stdio.h"

#define LF                    10  /* LF = Zeilenende !! */
#define FF                    12  /* LF = Zeilenende !! */
#define UNGLEICH              !=         
#define ABBRUCH               break
#define ZUM_LESEN             "r"
#define ZUM_SCHREIBEN         "w"
#define TEST_DATEI            "test.text"
#define BOOL                  int
#define ULONG                 unsigned long
#define UBYTE                 unsigned char

#define DEFAULTL 62          /* default: Zeilen pro Seite */
#define DEFAULTS 1           /* default: erste Seitennummer */
#define DEFAULTZ 1           /* default: erste Zeilennummer */
#define LF       10          /* LineFeed */
#define FF       12          /* Formfeed */
#define PRINTER  "prt:" /* Bezeichnung der Printerschnittstelle */
/* Makro, um eine Textzeile auszugeben */
#define putline(pointer,text)   fputs(text,pointer)

UBYTE zeile[120]; 
UBYTE einwort[40];

struct string 
{
   int     laenge;        /* Länge des Suchwortes */
   ULONG   maske;         /* Maske zum verUNDen des hashcode */
   ULONG   hashcode;      /* hashcode des Strings in 4-Bit-Gruppen */
   UBYTE   worte[20];     /* zu suchendes Wort */
   int     elaenge;       /* Länge des Ersatzwortes */
   UBYTE   eworte[20];    /* damit wird ersetzt */
};

int anzahl;               /* enthält die Anzahl der zu suchenden Wörter */
struct string feld[100];  /* Zwischenpuffer für eine Zeile */

UBYTE filename[80] = "s:edi-ersetz";
                          /* String, der die auszulesende Datei bezeichnet */
int Seiten = 0;           /* Zähler für die Seitennummer */
int Zeilen = 0;           /* Zähler der Zeilennummer */
int Laenge = DEFAULTL;    /* Länge einer Seite in Zeilen */
int Zaehler = 0;          /* Zählt die ausgedruckten Zeilen */
BOOL ers_flag = FALSE;

struct Task *maintask,*FindTask();
UBYTE* oldname;

UBYTE *puffer,*makepuffer(),getline();

main()
{
    FILE *fpout,*fopen(),*fp = 0L;

    BOOL puffer_flag;
    int zaehler,zaehler1;
    int zlaenge;
    UBYTE *pointtoit,*pointtonext; 
    struct string *now;
    ULONG hash_it;

    puffer_flag = FALSE;

    if ((fpout = fopen(PRINTER,ZUM_SCHREIBEN)) == NULL)
    {  melde("PRT: ist nicht bereit",FALSE);
       exit(20);
    }
 
    maintask = FindTask(0L);
    oldname = (UBYTE *)maintask->tc_Node.ln_Name;
    maintask->tc_Node.ln_Name = "edi-druck";

    puffer = makepuffer(); 
    if (puffer != 0L) 
       puffer_flag = TRUE;
    else
       if ((fp = fopen("PIPE:edi-druck",ZUM_LESEN)) == NULL)
       {  melde("PIPE: nicht installiert",FALSE);
          fclose(fpout); killpuffer();
          exit(20);
       }


    zlaenge = hole_zeile(fp,zeile);
/*    fprintf(stderr,"%s\n%d\n%.20s\n",zeile,zlaenge,puffer);*/
    zeile_mit(fp,zeile,&zlaenge);

    if (ers_flag)
    {
       if (init_worte() != 0)
       {  goto raus;
       } 

       do         /* wiederhole folgendes für eine Zeile */
       {  hash_it = 0L; pointtonext = pointtoit = zeile;
   
          for (zaehler1 = 0; zaehler1 < zlaenge; zaehler1 ++)
          {  hash_it = (hash_it << 4) + ((*pointtonext++) & 0x0f);  
                           /* Achtung '<<' ist Compiler-spezifisch !! */
                           /* es MUß geschoben nicht rotiert werden */
             for (zaehler = 0; zaehler < anzahl; zaehler++)
             {  now = &(feld[zaehler]);
                if (now->hashcode ==  (now->maske & hash_it)) 
                {  if (strncmp(now->worte, pointtoit-now->laenge+1,
                               now->laenge) == 0)
                   {  
                      zlaenge = ersetze(zaehler1-now->laenge+1,now,zlaenge);
                      hash_it = 0L; pointtonext = zeile;
                      pointtoit = zeile-1;
                      zaehler1 = -1; 
                      break;
                   }
                }
             }
             pointtoit++;
          }
          gibaus(fpout,zeile); 
       }  while ((zlaenge = hole_zeile(fp,zeile)) UNGLEICH -1); 
          /* ... bis alle Zeilen gelesen */
    }
    else
       druckepur(fp,fpout);
  
    fputc(FF,fpout);               /* letzte Seite rausschieben */
  
raus:
    maintask->tc_Node.ln_Name = (char *)oldname;
    if (puffer != NULL) 
       killpuffer();
    else
       fclose(fp);
    fclose(fpout);        /* "Dateien" wieder schließen */
}

hole_zeile(fp,text)
FILE *fp;
UBYTE *text;
{
     register int ein; register int zaehler = 0;
     register UBYTE pein;

     if (puffer != NULL)
     {  
        while ((pein = getline()) != LF && pein != '\0')
           text[zaehler++] = (UBYTE) pein;   /* kopieren und weiter */
        if (pein == '\0') 
           ein = EOF;
        else
           ein = pein;
     }
     else
     {  while ((ein = fgetc(fp))!= LF && ein != EOF)
           text[zaehler++] = (UBYTE) ein;    /* kopieren und weiter */
     }

     text[zaehler] = '\0';  /* Zeichenkette mit 0 abschließen */
     if (ein == EOF && zaehler == 0) return -1;
     return zaehler;    /* -1, wenn kein Zeichen gelesen werden konnte */
}

init_worte()
{
    int i,j,c,laenge; FILE *fpin;

    fpin = fopen(filename,ZUM_LESEN);

    if (fpin == NULL) 
    {  sprintf(zeile,"'%s' geht nicht auf",filename);
       melde(zeile,FALSE);
       return 1;
    }
    i = 0;
    do
    {  j = 0; 
       if ((c = fgetc(fpin)) == EOF) 
          break;     /* ein Wort lesen */
       c = getdez(feld[i].worte,&(feld[i].laenge),fpin,c);
       if (c == EOF) 
          break;
       while ((c = fgetc(fpin))== ' ') ;   /* Leerzeichen überlesen */

       c = getdez(feld[i].eworte,&(feld[i].elaenge),fpin,c);

       laenge = (feld[i].laenge) > 8 ? 8 : feld[i].laenge; 
                  /* nicht länger als 8 Zeichen */
       if (laenge == 0) continue;
       feld[i].maske    = 0x000fL;
       feld[i].hashcode = feld[i].worte[0] & 0x000fL;

       for (j=1; j < laenge; j++)
       {   feld[i].maske = (feld[i].maske << 4) + 0x000fL;
           feld[i].hashcode = (feld[i].hashcode << 4) + 
                                (feld[i].worte[j] & 0x000f);
       }

       while (c != LF && c != EOF)
          c = fgetc(fpin);
       i++;
    }  while (c != EOF);

    anzahl = i;

    fclose(fpin); return 0;
}

ersetze(posi,zeiger,zlen)
int posi;
struct string *zeiger;
int zlen;
{   register int i,j; UBYTE *p = zeile + posi;
 
    if (zeiger->laenge > zeiger->elaenge)
    {  strncpy(p,zeiger->eworte,zeiger->elaenge);
       strcpy(p+zeiger->elaenge, p+zeiger->laenge);
       return(zlen-zeiger->laenge+zeiger->elaenge);
    } 

    if (zeiger->laenge == zeiger->elaenge)
    {  strncpy(zeile+posi,zeiger->eworte,zeiger->elaenge);
       return(zlen);
    }
    
    j = zeiger->elaenge-zeiger->laenge;
    for (i = zlen +j; i >= posi+zeiger->elaenge; i--)
       zeile[i] = zeile[i-j];
    strncpy(zeile+posi,zeiger->eworte,zeiger->elaenge);
    return(zlen+j);
} 

druckepur(fp,fpout)
long fp,fpout;
{
   gibaus(fpout,zeile);

   while (hole_zeile(fp,zeile) UNGLEICH -1)
      gibaus(fpout,zeile);
}
     
gibaus(fp,zeile)
long fp;
UBYTE *zeile;
{   
   if (Zeilen)                    /* wenn Zeilennumern erwünscht */
      fprintf(fp,"%4d  ",Zeilen++);

   putline(fp,zeile);                          /* Zeile ausgeben */
   fputc('\n',fp);                         /* Linefeed hinterher */

   if ((++Zaehler % Laenge) == 0)            /* prüfe Seitenende */
   {  if (Seiten)                          /* wenn Seitennummern */
      {  putline(fp,"\x0A                                   Seite "); 
         fprintf(fp,"%3d\n",Seiten++);          /* ausgeben + LF */
      }                            /* neue Zeilennummer ausgeben */
      if (Laenge != 72)                         /* am Seitenende */
         fputc(FF,fp);                      /* Formfeed ausgeben */
   }
}

int getdez(wort,laenge,fpin,c) 
UBYTE *wort;
int *laenge,c;
FILE *fpin;
{
   int j = 0;
   while (c != ' ' && c != '\n' && c != EOF) 
   {  
      if (c == '/')                 /* folgt ein Dezimalwert ? */
      {  c = (fgetc(fpin)-48)*10;
         c = (c + (fgetc(fpin)-48))*10;       /* herausfiltern */
         c += fgetc(fpin)-48;
      }
      wort[j++] = (UBYTE) (255 & c);  /* und speichern */
      c = fgetc(fpin);
   }
   wort[j] = '\0';   *laenge = j;

   return c;
}

struct IntuiText weiter = { (UBYTE)0,(UBYTE)0,(UBYTE)JAM1,
                            (SHORT)5,(SHORT)3,NULL,(UBYTE*)"weiter", 0L } ;
struct IntuiText abbruch = { (UBYTE)0,(UBYTE)0,(UBYTE)JAM1,            
                            (SHORT)5,(SHORT)3,NULL,(UBYTE*)"abbruch",0L } ;
struct IntuiText showt  = { (UBYTE)0,(UBYTE)0,(UBYTE)JAM1,            
                            (SHORT)20,(SHORT)10,NULL,(UBYTE*)0L , 0L } ;

struct IntuitionBase *IntuitionBase, *OpenLibrary();

melde(text,flag)
UBYTE* text;
BOOL flag;
{
    long ergibt = 0L,AutoRequest();
    UBYTE *speicher,*AllocMem();
    struct Window* win;

    IntuitionBase = OpenLibrary("intuition.library",0L);
    if (IntuitionBase != NULL)
    {  win = IntuitionBase->ActiveWindow;
       showt.IText = text; 
       ergibt = AutoRequest(win,&showt,flag ? &weiter:NULL,&abbruch,0L,0L,
                (long)IntuiTextLength(&showt)+80L,60L);
       CloseLibrary(IntuitionBase);
    }
    return ergibt;
}

zeile_mit(fp,zeile,zlaenge)
FILE *fp;
UBYTE *zeile;
int *zlaenge;
{
    UBYTE *pointit,c,*index();
    int j; 

    if (*zeile != '%') return;

    if (pointit = index(zeile,'Z'))
      if ((Zeilen = atoi(++pointit)) == 0)
          Zeilen = DEFAULTZ;
    if (pointit = index(zeile,'S'))
      if ((Seiten = atoi(++pointit)) == 0)
          Seiten = DEFAULTS;
    if (pointit = index(zeile,'L'))
      if ((Laenge = atoi(++pointit)) == 0)
          Laenge = DEFAULTL;
    if (pointit = index(zeile,'D'))
    {  ers_flag = TRUE; j = 0;
       while ((c = *(++pointit)) != ' ' && c != '\n' && c != '\0')
          filename[j++] = c;
       if (j>0) filename[j] = '\0';
    }
    *zlaenge = hole_zeile(fp,zeile);
}

long lenne;

UBYTE *makepuffer()
{
   UBYTE * AllocMem();
   register UBYTE *zeiger; 
   long len; 
   register int c;
   int filedesk;

   filedesk = open("PIPE:edi-druck",0); /* zum lesen */

   if (read(filedesk,&len,4L) != 4L)
      return NULL;
   lenne = len+100L;

   if ((puffer = AllocMem(lenne,MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
   {  close(filedesk);
      return NULL;
   }
   zeiger = puffer;

   read(filedesk,puffer,len);
   puffer[len] = '\0';

   close(filedesk);
   return puffer;
}

killpuffer()
{
   FreeMem(puffer,lenne);
}

UBYTE getline()
{
   static UBYTE *zeiger = 0L;

   if (puffer[zeiger] != '\0')
      return puffer[zeiger++];
   else
      return '\0';
}   
