/*
***************************************************************************
*
* Datei:
*    RSysExtern.c
*
* Inhalt:
*    int GetFile(struct Window *wind, char *dir, char *file, char *pattern, char *title, char *oktext);
*    void SaveList(struct Window *wind, char *filename, char *title, struct List *list, int withheader);
*    int SysStarted(int type);
*    void RemoveSpeech(void);
*    int InitSpeech(void);
*    void Speak(char *text);
*
* Bemerkungen:
*    Verwaltung externer Daten und Schnittstellen zu Dateien.
*
* Erstellungsdatum:
*    07-Jul-93    Rolf Böhme
*
* Änderungen:
*    07-Jul-93    Rolf Böhme    Erstellung
*
***************************************************************************
*/

#include "RSysFunc.h"
#include "RSysDebug.h"

char _file[PATHPARTWIDTH],_dir[MAXFULLNAME];

static char *
strip(char *src, char *dest)
{
   BYTE s = 0, d = 0, l = strlen(src);

   while(s < l)
   {
      if(!strchr("'-:/ ", (int)src[s]))
      {
         dest[d++] = src[s++];
      }
      else
         s++;
   }

   dest[d] = STRINGEND;

   return dest;
}


   /*
    * GetFile() bietet einen Filerequester zur Auswahl einer Datei
    * an. Dabei wird unterschieden, ob die Datei zum Sichern oder zum
    * Laden verwendet wird.
    */
int
GetFile(struct Window *wind,char *dir,char *file,
        char *pattern,char *title,char *oktext)
{
   struct FileRequester *AslFileRequest = NULL;
   BYTE  Result = FALSE;
   APTR  req;
   UWORD l = 20,t = 20;
   int mask = FILF_PATGAD;
   char _oktext[MAXSHOW],_title[40],_pattern[10] = "#?",*_cancel = "Cancel";

   DPOS;

   if(SysWnd)
      PrintInfo("Selecting file", NO_SPEAK, 0);

   if (Flags.speakmode)
      Speak(title);

   if (AslBase = OpenLibrary((UBYTE *) "asl.library", 37L))
   {
      if(wind)
      {
         req = LockWindow(wind);
         CenterWindow(wind->WScreen,&t,&l,(UWORD)260,(UWORD)170);
      }

      if(dir && *dir)
         strncpy(_dir,dir,MAXFULLNAME);
      else
         strcpy(_dir,"RAM:");

      if(file && *file)
      {
         char header[PATHPARTWIDTH];

         strip(file, header);

         strncpy(_file,header,PATHPARTWIDTH);
      }
      else
         strcpy(_file,"unknown");

      if(pattern && *pattern)
         strncpy(_pattern,pattern,10);
      else
         strcpy(_pattern,"#?");

      if(title && *title)
         strncpy(_title,title,40);
      else
         strcpy(_title,"Select file");

      if(oktext && *oktext)
         strncpy(_oktext,oktext,MAXSHOW);
      else
         strcpy(_oktext,"Select");

      if(strstr(_oktext,"Save"))
         mask |= FILF_SAVE;

      if (AslFileRequest = AllocAslRequest(ASL_FileRequest,
                              TAG_DONE))
      {
         if (AslRequestTags(AslFileRequest,
                              ASL_Window,     (ULONG)wind,
                              ASL_Hail,       (ULONG)_title,
/*
                              ASL_Height,     (ULONG)170,
                              ASL_Width,      (ULONG)260,
*/
                              ASL_LeftEdge,   (ULONG)l,
                              ASL_TopEdge,    (ULONG)t,
                              ASL_OKText,     (ULONG)_oktext,
                              ASL_CancelText, (ULONG)_cancel,
                              ASL_File,       (ULONG)_file,
                              ASL_Dir,        (ULONG)_dir,
                              ASL_Pattern,    (ULONG)_pattern,
                              ASL_FuncFlags,  (ULONG)mask,
                        TAG_DONE))
         {
            if (AslFileRequest->rf_File)
            {
               if(AslFileRequest->rf_Dir)
               {
                  strncpy(_fullpath,AslFileRequest->rf_Dir,MAXFULLNAME);
                  AddPart((UBYTE *)_fullpath,(UBYTE *)AslFileRequest->rf_File,
                          MAXFULLNAME);
               }
               else
                  strncpy(_fullpath,AslFileRequest->rf_File,MAXFULLNAME);

               Result = TRUE;
            }

            if(AslFileRequest->rf_Pat)
               strncpy(_pattern,AslFileRequest->rf_Pat,10);
         }

         FreeAslRequest(AslFileRequest);
      }
      else
         ErrorHandle(MEMORY_ERR, ALLOC_FAIL, NO_KILL);

      CloseLibrary(AslBase);

      if(wind)
         UnlockWindow(req);
   }
   else
      ErrorHandle(LIBRARY_ERR, OPEN_FAIL, NO_KILL);

   if (SysWnd && strcmp(_oktext, "Check"))
      PrintStatistics();

   DPOS;

   return (Result);
}

   /*
    * SaveList() speichert die Einträge einer Liste (vom Hauptfenster oder
    * intern) in eine Datei ab oder direkt ins Clipboard.
    */
void
SaveList(struct Window *wind, char *filename, char *title,
         struct List *list, int withheader)
{
   BPTR  fout;
   struct Node *node;
   int   mode;
   char  out[MAXWRITESIZE], fmt[MAXWRITESIZE];
   int noheader;

   DPOS;

   PrintInfo("Save list to file", NO_SPEAK, 0);

   if (exist(filename))
   {
      mode = MyEasyRequest(wind, (UBYTE *) NAME " ask you",
                           (UBYTE *) "Append|Overwrite|Cancel",
                           (UBYTE *) "The file <%s> exists!",
                           filename);
      switch (mode)
      {
         case 1:
            fout = Open((UBYTE *) filename, MODE_OLDFILE);
            Seek(fout, 0L, OFFSET_END);
            break;

         case 2:
            fout = Open((UBYTE *) filename, MODE_NEWFILE);
            break;

         default:
            return;
            break;
      }
   }
   else
      fout = Open((UBYTE *) filename, MODE_NEWFILE);

   D(kprintf((UBYTE *)"1. Format: %s\nIO-Error: %ld\n",fmt, IoErr()));

   if (fout)
   {
      noheader = RSysFormatOutput(fmt);

      if(!noheader)
      {
         sprintf(out, "----------------------------------------------\n"
                 "%s\n"
                 "----------------------------------------------\n\n",
                 title);

         Write(fout, out, strlen(out));

         if (withheader)
         {
            sprintf(out, "%s\n----------------------------------------------\n",
                    EntryAttr[LastID].ea_header);
            Write(fout, out, strlen(out));
         }
      }

      for (node = list->lh_Head; node->ln_Succ /*&& !IoErr()*/;
           node = node->ln_Succ)
      {
         sprintf(out, fmt, node->ln_Name);
         strcat((char *)out,"\n");

         Write(fout, out, strlen(out));
      }

      D(kprintf((UBYTE *)"Format: %s\nIO-Error: %ld\n",fmt, IoErr()));

      if (IoErr())
         ErrorHandle(FILE_ERR, WRITE_FAIL, NO_KILL);
      else
      {
         Write(fout, (UBYTE *)"\n",1);
         PrintInfo("List was written to file", SPEAK, SEC);
      }

      Close(fout);
   }
   else
      ErrorHandle(FILE_ERR, OPEN_FAIL, NO_KILL);

   PrintStatistics();

   return;
}

   /*
    * SysStarted() überprüft, ob RSys ein zweites Mal gestartet wurde
    * und sendet im zutreffenden Fall einen Argumenttyp der Art der
    * anzuzeigenden Liste an den Task des zuerst gestarteten Programmes
    */
int
SysStarted(int type)
{
   struct MsgPort *TestPort;
   struct MsgPort *ReplyPort = NULL;
   SysMsg *mess;
   int   ret = FALSE;

   DPOS;

   if (ReplyPort = CreatePort((UBYTE *) "SysReplyPort", NULL))
   {
      mess = (SysMsg *) MyAllocVec(sizeof(SysMsg),
                                   MEMF_CLEAR | MEMF_PUBLIC, NO_KILL);

      if (mess)
      {
         mess->sm_message.mn_Node.ln_Type = NT_MESSAGE;
         mess->sm_message.mn_ReplyPort = ReplyPort;
         mess->sm_message.mn_Length = sizeof(SysMsg);
         mess->sm_newtype = type;

         Forbid();

         if (TestPort = FindPort((UBYTE *) ID_PORT_NAME))
         {
            PutMsg(TestPort, (struct Message *) mess);

            WaitPort(ReplyPort);

            ret = TRUE;
         }

         Permit();

         MyFreeVec(mess);
      }

      DeletePort(ReplyPort);
   }

   return (ret);
}

struct Library *TranslatorBase = NULL;
struct MsgPort *narratorPort;
struct narrator_rb request;

   /*
    * RemoveSpeech() entfernt die Ressourcen für die Sprachausgabe
    * und schließt das Device, das für die Sprachausgabe des Amigas
    * zuständig ist, das narrator.device
    */
void
RemoveSpeech(void)
{
   DPOS;

   if (narratorPort)
      DeleteMsgPort(narratorPort);      /* Port schliessen */

   if (TranslatorBase)
      CloseLibrary(TranslatorBase);     /* Lib schliessen */

   if (request.message.io_Device)
      CloseDevice((struct IORequest *) & request);      /* Device schliessen */

   return;
}

   /*
    * InitSpeech() öffnet die Ressourcen für die Sprachausgabe
    * Anm: Auf einem 4000er stürzt an dieser Stelle das Programm ab!
    */
int
InitSpeech(void)
{
   DPOS;

   if (TranslatorBase = OpenLibrary((UBYTE *) "translator.library", 0))
      if (narratorPort = CreateMsgPort())
      {
         if (NOT(OpenDevice((UBYTE *) "narrator.device", 0,
                            (struct IORequest *) & request, 0)))
            return (TRUE);
         else
            ErrorHandle(DEVICE_ERR, OPEN_FAIL, NO_KILL);
      }
      else
         ErrorHandle(PORT_ERR, CREATE_FAIL, NO_KILL);
   else
      ErrorHandle(LIBRARY_ERR, OPEN_FAIL, NO_KILL);

   RemoveSpeech();

   return (FALSE);
}

   /*
    * Speak() gibt einen Text über das narrator.device aus
    */
void
Speak(char *text)
{
   UBYTE help[BUFSIZE + 2];
   UBYTE translate[3 * BUFSIZE];
   UBYTE Channel[4] =
   {
      1, 2, 4, 8
   };

   DPOS;

   strncpy((char *)help, text, BUFSIZE);

   if (!ispunct((int)text[strlen(text) - 1]))
      strcat((char *)help, ".");

   if (NOT(Translate(help, (strlen((char *)help) * sizeof(char)),
                     translate, sizeof(translate))))
   {
      request.message.io_Message.mn_ReplyPort = narratorPort;

      request.message.io_Command = CMD_WRITE;   /* Kommando Schreiben */
      request.message.io_Data = (APTR) translate;       /* Pointer auf Text */
      request.message.io_Length = sizeof(translate);    /* Groesse des Textes */

      request.rate         = DEFRATE;   /* Worte pro Minute: 40 < rate < 400 */
      request.pitch        = DEFPITCH; /* 65 < pitch < 320 */
      request.sex          = DEFSEX;     /* Geschlecht : auch MALE */
      request.volume       = DEFVOL;  /* Lautstaerke max 64 */
      request.mode         = DEFMODE;   /* Aussprache-Modus */
      request.sampfreq     = DEFFREQ;
      request.F0enthusiasm = DEFF0ENTHUS;
      request.F0perturb    = DEFF0PERT;
      request.priority     = DEFPRIORITY;
      request.ch_masks     = (UBYTE *) Channel;     /* Kanaele */
      request.nm_masks     = sizeof(Channel);

      DoIO((struct IORequest *) & request);     /* Text aussprechen */
   }

   return;
}
