/* Sag
   Vorlesen von deutschsprachigen Textdateien
   Entstanden aus Speechd, P. Kittel 11.10.89
     und AmigaBASIC-Programm SagDatei5, P. Kittel 15.8.90
   Version mit Abbruch durch Ctrl-C statt eigenem Fenster
   Version mit zusätzlichen Eingabeparametern
   Version 2, 20.4.91 */

#include <stdio.h>
#include <exec/types.h>
#include <exec/tasks.h>
#include "sag.h"
#include <stdlib.h>
#include <dos.h>
#include <libraries/dosextens.h>
#include <devices/narrator.h>

#ifdef LATTICE
/* Nach einem Posting von Richard Leinfellner in adsp.14.bugs am 14.1.91 */
int CXBRK()     { return(0); }   /* Disable Lattice Ctrl-C handling */
int chkabort()  { return(0); }   /* really */
#endif

#define PUFFER 2000

extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();

static UWORD param[7]={105, 0, 165, 0, 20590, 64, 0};


int sdazu(s, sn, s2)
char *s,*s2;
int *sn;
{
int i=0, z=1, m=PUFFER-1;
while (*sn<m && z==1)
  if ((s[*sn]=s2[i++])=='\0')  { z=0; } else { *sn=*sn+1; }
return(z);
}


int para(arg)
char *arg;
{
int r=-1, s=0;
char c, *a;
a=arg+2;
while ((c=*a) && s<6)
  { if (c<'0' || c>'9')
      { s=9; }
        else
      { if (r<0) r=0;
        r=r*10+c-'0';
        s++; if (s>5) r=-1;
        a++;
      }
  }
return(r);
}


  

void main(argc,argv)
int argc;
char *argv[];
{
struct MsgPort *writeport=0;
struct narrator_rb *writeNarrator=0;
static BYTE audChanMask[4]={ 3, 5, 10, 12 };
struct FileHandle *ein;
UWORD curdat[7];
int i,j,k,l,m,ai,bn,sn=1,tn=1,gl,z,eo1=0,fle=0,flf=0,fha=0,fv,p1,s0,s1;
int *snp,*tnp,*bnp;
char a,a1,c,lvok=12,cr=13,lf=10,ta=9,s[PUFFER],t[PUFFER],aa[20],bb[300];
char *vok="AEIOUYÄÖÜäöü";


for (i=0; i<7; i++) curdat[i]=param[i];
s[0]=' '; m=PUFFER-1;
snp=&sn; tnp=&tn; bnp=&bn;

if (argc<2 || argv[1][0]=='?')
  { puts(" Vorlesen einer deutschen Klartext-Datei.");
    puts(" Aufruf:  sag  Dateiname  [-K] [-Hn] [-R] [-Gn] [-W] [-Fn] [-Ln]");
    puts(" -K   der Name der Datei wird nicht laut vorgelesen");
    puts(" -Hn  Höhe der Stimme (pitch), Normalwert 105,   65-320");
    puts(" -M   mit Satzmelodie");
    puts(" -Gn  Geschwindigkeit (rate),  Normalwert 165,   40-400");
    puts(" -W   weibliche Stimme");
    puts(" -Fn  Frequenz,                Normalwert 20590, 15000-28000");
    puts(" -Ln  Lautstärke,              Normalwert 64,    0-64\n");
    exit(FALSE);
  }
ein=(struct FileHandle *)Open(argv[1],MODE_OLDFILE);
if (ein == 0)
  { puts(" Datei nicht lesbar.");
    exit(FALSE);
  }
printf("\n Vorlesen der Datei %s auf Deutsch.\n\n",argv[1]);

a1=1;
strcpy(bb,"Vorleesen der Datei "); bn=20;
z=sdazu(bb, bnp, argv[1]);
bb[bn++]=';'; bb[bn++]=' '; bb[bn++]=';'; bb[bn++]=' ';
bb[bn++]=';'; bb[bn++]=' '; bb[bn++]=';'; bb[bn]='\0';

if (argc>2)
  for (i=2; i<argc; i++)
    { if (argv[i][0]=='-')
      { c=argv[i][1]; bn=para(argv[i]);
        if (c=='K' || c=='k')   bb[0]='\0';
        if (c=='H' || c=='h')
          { if (bn<65 ) bn=65;
            if (bn>320) bn=320;
            curdat[0]=bn;
          }
        if (c=='M' || c=='m')   curdat[1]=1;
        if (c=='G' || c=='g')
          { if (bn<40 )  bn=40;
            if (bn>400)  bn=400;
            curdat[2]=bn;
          }
        if (c=='W' || c=='w')   curdat[3]=1;
        if (c=='F' || c=='f')
          { if (bn<15000)  bn=15000;
            if (bn>28000)  bn=28000;
            curdat[4]=bn;
          }
        if (c=='L' || c=='l')
          { if (bn>64)  bn=64;
            curdat[5]=bn;
          }
      }
    }

writeport=CreatePort(0,0);
if (writeport==0)
  { puts("Port nicht anlegbar.");
    goto abschluss1;
  }

writeNarrator=(struct narrator_rb *)CreateExtIO(writeport,
                                    sizeof(struct narrator_rb));
if (writeNarrator==NULL)
  { puts("Struct narrator_rb nicht anlegbar.");
    goto abschluss2;
  }

z=OpenDevice("narrator.device",0,writeNarrator,0);
if (z!=0)
  { puts("Narrator.device nicht ansprechbar.");
    goto abschluss3;
  }

writeNarrator->ch_masks=(audChanMask);
writeNarrator->nm_masks=sizeof(audChanMask);
writeNarrator->message.io_Data=(APTR)s;
writeNarrator->message.io_Length=sn;
writeNarrator->message.io_Command=CMD_WRITE;
writeNarrator->mouths=0;
writeNarrator->rate    =curdat[2];
writeNarrator->pitch   =curdat[0];
writeNarrator->mode    =curdat[1];
writeNarrator->sex     =curdat[3];
writeNarrator->volume  =curdat[5];
writeNarrator->sampfreq=curdat[4];

bn=0; gl=0;

/* Hauptschleife */
while (!(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) && eo1==0)
  { c=a1;
    if (bb[bn])
      { a=uca[(UBYTE)bb[bn++]]; a1=a;
      }
           else
      { z=Read(ein, &a, 1); a=uca[(UBYTE)a]; a1=a;
        if (z==0) { eo1=2; a='!'; }
      }

    /* Höchstens 10 gleiche Zeichen hintereinander */
    if (a1==c)
      { gl++;
        if (gl>10)  { gl=10; a='|'; }
      } else
      { gl=0; }

    /* Klammern mit Spaces einrahmen */
    if (a==')' || a=='(')
      { aa[0]=' '; aa[1]=a; aa[2]=' '; aa[3]='\0';
        if (z=sdazu(s, snp, aa)) eo1=1;
        a=' '; fle=0;
      }

    /* Bei einem H vor einem Vokal das H und den Vokal verdoppeln */
    if (fha)
      for (i=0; i<lvok; i++)
        { if (vok[i]==a)
            { aa[0]='H'; aa[1]=a; aa[2]='\0';
              if (z=sdazu(s, snp, aa)) eo1=1;
              i=lvok;
            }
        }
    fha=0;
    /* Bei einem H ggf. davorstehenden Vokal verdoppeln */
    if (a=='H')
      if (c!='C')
        { fha=1;
          for (i=0; i<lvok; i++)
            if (vok[i]==c)
              { aa[0]=c; aa[1]='\0';
                if (z=sdazu(s, snp, aa)) eo1=1;
                i=lvok;
              }
        }

  /* Prüfung auf Satzende */
  p1=(a=='.' || a=='!' || a=='?' || a==',' || a==';' || a==':');
  if (a==ta) { p1=1; a=' '; }  /* Auch TAB als Satzende behandeln */
  if (a==' ')
    { flf=0;
      /* Mehr als 3 Leerzeichen wie Satzende behandeln */
      if (fle==0)
        { aa[0]=' '; aa[1]=' '; aa[2]='\0'; fle=1;
          if (z=sdazu(s, snp, aa)) eo1=1;
        } else
        { fle++;
          if (fle>3)
            { aa[0]=' '; aa[1]='\0';
              if (z=sdazu(s, snp, aa)) eo1=1;
              a='!'; p1=1; fle=0;
            }
         }
    } else
    { fle=0;
      /* Mehrfache Leerzeilen als Satzende behandeln */
      if (a==cr || a==lf)
        { if (flf>2 || a==c)
            { aa[0]=' '; aa[1]='!'; aa[2]=' '; aa[3]='\0'; p1=1;
              if (z=sdazu(s, snp, aa)) eo1=1;
            } else
            { a=' '; flf++; }
        } else
        { flf=0; }
    }

  /* Vor einer Ziffer das Minus aussprechen */
  if (a>='0' && a<='9' && c=='-')
    { strcpy(aa," MIINUS ");
      if (z=sdazu(s, snp, aa)) eo1=1;
    }

  if (p1 || eo1)
    { if (a=='.')
      /* Hinter einer Ziffer oder im Dateinamen den Punkt aussprechen */
        { if (c>='0' && c<='9' || c=='.' || bb[bn])
            { strcpy(aa," PUNKT ");
            } else
            { aa[0]=' '; aa[1]='\0';
            }
          a='!';
          if (z=sdazu(s, snp, aa)) eo1=1;
        }

      /* Hinter einer Ziffer das Komma aussprechen */
      if (a==',')
        { if (c>='0' && c<='9')
            { strcpy(aa," KOMMA ");
            } else
            { aa[0]=' '; aa[1]='\0';
            }
          a='!';
          if (z=sdazu(s, snp, aa)) eo1=1;
        }

      /* Doppelpunkt immer aussprechen */
      if (a==':')
        { strcpy(aa," :");
          if (z=sdazu(s, snp, aa)) eo1=1;
        }

      /* Am Ende entweder Fragezeichen oder Minus dazu */
      if (eo1)
        { aa[0]=a; aa[1]='\0'; 
        } else
        { aa[0]=' ';
          aa[1]=(a1=='?') ? a1 : '-';
          aa[2]='\0';
        }
      if (z=sdazu(s, snp, aa)) eo1=1;

      /*    german msg$,msgt$: */

      aa[0]=' '; aa[1]='\0';
      if (z=sdazu(s, snp, aa)) eo1=1;

      /* Suche nach Wörtern ohne Vokale,
         ggf. Aufteilung dieser in Einzelbuchstaben mit Spaces drumrum */
      s0=0; tn=1; t[0]=' ';
      while (s0<sn)
        { a=' ';
          while (a==' ' || a=='-' || a=='.' || nt0[(UBYTE)a]<0)
            { if (tn<m)
                { t[tn++]=s[s0++]; }
                       else
                { a='!'; s0=sn; s1=sn; eo1=1; }
              a=s[s0];
            }
          s1=s0;
          if (s0<sn)
            { fv=1;
              while (a!=' ' && a!='-' && a!='.' && nt0[(UBYTE)a]>=0)
                { for (i=0; i<lvok; i++)
                    if (vok[i]==a)  { fv=0; i=lvok;}
                  a=s[++s1];
                }
              if (fv)
                { aa[0]=' '; aa[2]=' '; aa[3]='\0';
                  for (i=s0; i<s1; i++)
                    { aa[1]=s[i];
                      if (z=sdazu(t, tnp, aa))
                        { i=s1; s0=sn; s1=sn; eo1=1; }
                    }
                } else
                { for (i=s0; i<s1; i++)
                    if (tn<m)
                      { t[tn++]=s[i]; }
                           else
                      { i=s1; s0=sn; s1=sn; eo1=1; }
                }

            }
          s0=s1;
        }
      t[tn]='\0';

      /* Höchstens zwei Leerzeichen hintereinander */
      fv=tn-2;
      for (i=0; i<fv; i++)
        if (t[i]==' ' || t[i]=='!')
          if (t[i+1]==' ')
            if (t[i+2]==' ') t[i+1]='!';

      /* Eigentliche Umcodierung */
      sn=1; s[0]=' ';
      for (i=0; i<tn; i++)
        { ai=t[i]; if (ai<0) ai+=256;
          if (nt0[ai]>0)
            { fv=(int)(nt1[ai]+nt0[ai]);
              for (j=(int)(nt1[ai]); j<fv; j++)
                 { k=-1; l=0; c='!';
                   while (k<0 && c!='\0')
                     { c=te[j][l];
                       if (c!='\0' && c!=t[i+l]) k=0;
                       l++;
                     }
                   if (k)
                     { a=ph[j][0]; i=i+l-2; l=0;
                       while (a)
                         if (sn<m)
                           { s[sn]=a; sn++;
                             l++; a=ph[j][l];
                           } else
                           { a=0; k=0; j=fv; i=tn; eo1=1; }
                       j=fv;
                     }
                 }
            }
        }

      /* Vorn und hinten Qs weg */
      s[sn]='\0';
      a=s[sn-1];
      while (a=='Q')  { s[sn-1]='\0'; sn--; a=s[sn-1]; }
      a=s[0]; s0=0;
      while (a=='Q')  { s[s0]=' ';    s0++; a=s[s0];   }

      /* Bei doppelten Qs das erste duch Space ersetzen */
      fv=sn-2;
      for (i=0; i<fv; i++)
        if (s[i]=='Q')
          if (s[i+1]=='Q')  s[i]=' ';

      /*    SAY s$,current% */
      writeNarrator->message.io_Data=(APTR)s;
      writeNarrator->message.io_Length=sn;
      writeNarrator->message.io_Command=CMD_WRITE;
      DoIO(writeNarrator);

      sn=1; s[0]=' ';
      fha=0; fv=0; fle=0; flf=0; p1=0;
    } else
    { aa[0]=a; aa[1]='\0';
      if (z=sdazu(s, snp, aa)) eo1=1;
    }
  }

CloseDevice(writeNarrator);

abschluss3:
if (writeNarrator) DeleteExtIO(writeNarrator);

abschluss2:
if (writeport) DeletePort(writeport);

abschluss1:
if (ein) Close(ein);

}
