/* This file is part of the origami distrubution. (Amiga Port)
 *
 * Source code written by Thomas Hadig in September 1991
 * Version : 1.6.92.1, February 1994
 * (C) 1991-94 by Thomas Hadig
 * may be distributed unchanged ! (see copyright notes)
 */

/*{{{}}}*/
/*{{{  #includes*/
/*{{{  stardard includes*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
/*}}}  */
#define DOS_DOSASL_H
#define DOS_DATETIME_H
#include <clib/dos_protos.h>
#undef DOS_DOSASL_H
#undef DOS_DATETIME_H
#include <clib/exec_protos.h>

#define AMIGA_MISC_C
#define I_VIRTUAL_C
#define I_FOLDING_C
#define I_GETMSG_C
#define I_MAIN_C
#define I_PROMPT_C
#define I_MESSAGES_C
#define I_ORIEDT_C
#define I_LOOP_C
#define I_FINDS_C
#define I_KEYBOARD_C

#include <origami/origami.h>
#include <h/envvar_str.h>

/*{{{  ASL*/
#ifdef ASL
#include <libraries/asl.h>
#include <clib/asl_protos.h>
#endif
/*}}}  */
/*}}}  */
/*{{{  variables*/
private char filename_for_stat[_POSIX_PATH_MAX]="";
private int mode_of_file;
#ifdef AREXX
  public char *portname=(char *)0;
#endif
/*}}}  */

/*{{{  fileprompt*/
public char *fileprompt (char n[_POSIX_PATH_MAX])
 {
  /*{{{  read from statusline*/
  s_readprompt(n,get_msg(M_FILENAME),_POSIX_PATH_MAX,misc_history);
  if (!*n)
   {
    if (bd.f.real_tail == bd.f.real_head)
      *n = '\0';
    else if (!aborted)
      strcpy(n,get_data(bd.f.real_tail));
   }
  /*}}}  */
  /*{{{  ASL requester*/
#  ifdef ASL
  /*{{{  get requester, if posible*/
  if (*n=='~')
   {
    /*{{{  variables*/
    char file[_POSIX_PATH_MAX],path[_POSIX_PATH_MAX];
    struct AslBase *AslBase;
    struct FileRequester *req1;
    /*}}}  */

    file[0]=0x00;
    /*{{{  get path*/
    if (!n[1])                                /* ~ : path="" */
      path[0]=0x00;
    else if (n[1]=='/')                       /* ~/file= S:file */
     {
      n[0]='S';
      n[1]=':';
      return n;
     }
    else if (n[1]!='~')                       /* ~my_path : path=my_path */
     {
      char *p=n+1;
      while (isspace (*p)) p++;
      strcpy (path,p);                      /* with leading white space */
     }
    else if (bd.f.real_tail == bd.f.real_head) /* ~~ : path=path_of_old_file */
      stcgfp (path,get_data(bd.f.real_tail));  /* old file exists */
    else                                       /* old file exists not */
      path[0]=0;
    /*}}}  */
    /*{{{  asl.library*/
    if (AslBase = (struct AslBase *)OpenLibrary (AslName,0L))
     /*{{{  try requester*/
     {
      if (req1 = AllocFileRequest ())
       {
        if (AslRequestTags (req1,ASL_Hail,"Origami-File-Requester",
            ASL_File,file,ASL_Dir,path))
         {
          strcpy (n,req1->rf_Dir);
          if ((strlen(n))&&(n[strlen(n)-1]!=':')&&(n[strlen(n)-1]!='/'))
            strcat (n,"/");
          strncat (n,req1->rf_File,_POSIX_PATH_MAX-strlen(n));
          FreeFileRequest (req1);
          return n;
         }
        FreeFileRequest (req1);
        n[0]=0;
        return n;
       }
     }
     /*}}}  */
    /*}}}  */
    /*{{{  read from statusline*/
    s_readprompt(n,get_msg(M_FILENAME),_POSIX_PATH_MAX,misc_history);
    if (!*n)
      if (bd.f.real_tail == bd.f.real_head)
        *n = '\0';
      else if (!aborted)
        strcpy (n,get_data(bd.f.real_tail));
    /*}}}  */
   }
  /*}}}  */
#  endif
  /*}}}  */
  return(n);
 }
/*}}}  */

/*{{{  my_fopen*/
public FILE *my_fopen (char *name,char *mode)
 {
  struct stat st;

  strcpy (filename_for_stat,name);
  if (!stat (name,&st))
    mode_of_file = st.st_mode &
       (S_ISCRIPT|S_IPURE|S_IREAD|S_IWRITE|S_IEXECUTE|S_IDELETE);
  else mode_of_file = (S_IREAD|S_IWRITE|S_IEXECUTE|S_IDELETE);
  return fopen (name,mode);
 }
/*}}}  */
/*{{{  my_fclose*/
public int my_fclose(FILE *fp)
 {
  int ret;

  ret = fclose (fp);
  chmod (filename_for_stat,mode_of_file);
  return ret;
 }
/*}}}  */
/*{{{  getpid*/
public int getpid(void) { return (int)FindTask (0L); }
/*}}}  */
/*{{{  usleep*/
public void usleep (long x) { if (x>20000) Delay (x/20000); }
/*}}}  */
/*{{{  sleep*/
public void sleep(int len) { Delay (50*len); }
/*}}}  */

/*{{{  getascnum*/
private char *getascnum (char *cptr,short *sptr)
 {
  if (!isdigit(cptr[0])) return (char*)0;
  *sptr = atoi (cptr);
  while (isdigit(cptr[0])) cptr++;
  return cptr;
 }
/*}}}  */
/*{{{  get_size*/
private void get_size (char *p,short *x, short *y, short *w, short *h)
 {
  if (p = getascnum (p,x))
  if (*p==0x2F)               /* / */
  if (p = getascnum (p+1,y))
  if (*p==0x2F)               /* / */
  if (p = getascnum (p+1,w))
  if (*p==0x2F)               /* / */
  getascnum (p+1,h);
  return;
 }
/*}}}  */
/*{{{  handle_amiga_args*/
public char *handle_amiga_args (char *ptr)
 {
  if (ptr && *ptr)
   {
    switch (toupper(*ptr))
     {
      /*{{{  Arexx Port[=NAME]*/
      case 'A':
       {
#      ifdef AREXX
        arexx = True;
        while ((*++ptr)&&(*ptr!='='));
        if (*ptr=='=')
         {
          ++ptr;
          if (*ptr) portname=ptr;
         }
        break;
#      else
        return "Arexx not supported in this version !";
#      endif
      }
      /*}}}  */
      /*{{{  Screen[=size]*/
      case 'S':
       {
        short i;

        screen_yes = True;
        while ((*++ptr)&&(*ptr!='='));
        if (*ptr=='=') get_size (++ptr,&screenw,&screenh,&i,&i);
        if ((screenh)&&(screenh<100)) screenh=100;
        if ((screenw)&&(screenw<200)) screenw=200;
        break;
       }
      /*}}}  */
      /*{{{  Window[=size]*/
      case 'W':
       {
        while ((*++ptr)&&(*ptr!='='));
        if (*ptr=='=') get_size (++ptr,&windx,&windy,&windw,&windh);
        if ((windh)&&(windh<100)) windh=100;
        if ((windw)&&(windw<200)) windw=200;
        break;
       }
      /*}}}  */
      /*{{{  default*/
      default: {return "Unknown Amiga Option !";}
      /*}}}  */
     }
   }
  return (char*)0;
 }
/*}}}  */

#ifdef AREXX
/*{{{  includes*/
#include <rexx/rxslib.h>
#include <proto/rexxsyslib.h>
#include <clib/alib_protos.h>
/*}}}  */

/*{{{  GetARexxMsg*/
public struct RexxMsg *GetARexxMsg(void)
 {
  struct RexxMsg *tmp;

  /*{{{  is there a arexx port ? is there a message ?*/
  if ((!_arexx)||(arexx==False)||(!(tmp=(struct RexxMsg *)GetMsg(_arexx->port))))
    return NULL;
  /*}}}  */
  /*{{{  is this a reply ? no*/
  if (tmp->rm_Node.mn_Node.ln_Type!=NT_REPLYMSG) return tmp;
  /*}}}  */
  /*{{{  handle reply*/
  /*
   * Free the arguments and the message...
   */
  DeleteArgstring(tmp->rm_Args[0]);
  DeleteRexxMsg(tmp);
  _arexx->outstanding-=1;
  return NULL;
  /*}}}  */
 }
/*}}}  */
/*{{{  ReplyARexxMsg*/
public void ReplyARexxMsg(struct RexxMsg *rmsg,char *RString,long Error)
 {
  /*{{{  is there a port and a message ?*/
  if ((arexx==False)||(!_arexx)||(!rmsg)) return;
  /*}}}  */
  rmsg->rm_Result2=0;
  /*{{{  handle errors*/
  if (!(rmsg->rm_Result1=Error))
   {
    /*{{{  return ErrorString on Error*/
    if ((rmsg->rm_Action & (1L << RXFB_RESULT))&&(RString))
     {
      rmsg->rm_Result2=
        (LONG)CreateArgstring(RString,(LONG)strlen(RString));
     }
    /*}}}  */
   }
  /*}}}  */
  ReplyMsg((struct Message *)rmsg);
 }
/*}}}  */
/*{{{  SetARexxLastError*/
/*{{{  Description*/
/*
 * This function will set an error string for the ARexx
 * application in the variable defined as <appname>.LASTERROR
 *
 * Note that this can only happen if there is an ARexx message...
 *
 * This returns TRUE if it worked, FALSE if it did not...
 */
/*}}}  */
public short SetARexxLastError(struct Message *rmsg,char *ErrorString)
{
  if ((!_arexx)||(!rmsg)||(!CheckRexxMsg(rmsg)))
    return FALSE;
  /*
   * Note that SetRexxVar() has more than just a TRUE/FALSE
   * return code, but for this "basic" case, we just care if
   * it works or not.
   */
  if (!SetRexxVar(rmsg,_arexx->errorname,ErrorString,
    (long)strlen(ErrorString)))
  {
    return TRUE;
  }
  return FALSE;
}
/*}}}  */
extern int _Backstdout;

/*{{{  handle_rexx*/
public int handle_rexx (void)
 {
  AREXX_COM *com=_arexx->command;
  char *p=_arexx->msg->rm_Args[0];

  /*{{{  is there an arg ? ... set rm_Args[1]*/
  while ((*p)&&(!isspace(*p))) p++;
  if (*p)
   {
    *p++=0;
    while (isspace(*p)) p++;
    if (*p) _arexx->msg->rm_Args[1]=p;
   }
  else _arexx->msg->rm_Args[1]=0;
  /*}}}  */
  /*{{{  look for build-in command*/
  p=_arexx->msg->rm_Args[0];
  /*{{{  PUTARG*/
  if (!stricmp(p,"PUTARG"))
   {
    if ((_arexx->msg->rm_Args[1])&&(_arexx->hist>-1))
      add_history (_arexx->hist,_arexx->msg->rm_Args[1]);
    ReplyARexxMsg (_arexx->msg,NULL,0);
    return 0;
   }
  /*}}}  */
  /*{{{  ISDEF*/
  if (!strcmp (p,"ISDEF"))
   {
    /*{{{  need one argument*/
    if (!_arexx->msg->rm_Args[1])
     {
      SetARexxLastError ((struct Message *)_arexx->msg,
        "17 : Need one argument !");
      ReplyARexxMsg (_arexx->msg,NULL,10);
      return 0;
     }
    /*}}}  */
    while ((com)&&(stricmp (_arexx->msg->rm_Args[1],com->name))) com=com->Next;
    /*{{{  return COMMAND NOT IMPLEMENTED !*/
    if (!com)
     {
      SetARexxLastError ((struct Message *)_arexx->msg,
        "10 : Command not implemented !");
      ReplyARexxMsg (_arexx->msg,NULL,5);
      return 0;
     }
    /*}}}  */
    ReplyARexxMsg (_arexx->msg,NULL,0);
    return 0;
   }
  /*}}}  */
  /*}}}  */
  /*{{{  look for command in defined list*/
  while ((com)&&(stricmp (p,com->name))) com=com->Next;
  /*}}}  */
  /*{{{  return COMMAND NOT IMPLEMENTED !*/
  if (!com)
   {
    SetARexxLastError ((struct Message *)_arexx->msg,
      "100 : Command not implemented !");
    ReplyARexxMsg (_arexx->msg,NULL,100);
    return 0;
   }
  /*}}}  */
  if ((_arexx->msg->rm_Args[1])&&(_arexx->hist>-1))
    add_history (_arexx->hist,_arexx->msg->rm_Args[1]);
  _arexx->mac = com->mac;
  return 1;
 }
/*}}}  */
#endif

/*{{{  user_signal_handle*/
public void user_signal_handle (void)
 {
  /*{{{  handle AREXX commands*/
#  ifdef AREXX
  if ((arexx==True)&&(_arexx)&&(!executing_macro))
   {
    switch (_arexx->tag)
     {
      /*{{{  1: start new macro*/
      case 1:
       {
        call_number_macro (_arexx->mac);
        _arexx->tag=2;
        break;
       }
      /*}}}  */
      /*{{{  2: macro has been executed*/
      case 2:
       {
        char tmp[100],*p=tmp,**ptr= &p;

        if (_arexx->hist)
          access_history (0,_arexx->hist,FALSE,NULL,ptr);
        else
          sprintf (tmp,"Rec : %d\n",_arexx->mac);
        ReplyARexxMsg (_arexx->msg,*ptr,0);
        _arexx->tag=0;
       }
      /*}}}  */
     }
   }
#  endif
  /*}}}  */
 }
/*}}}  */
/*{{{  menu functions*/
#ifdef MENU
#include <intuition/intuition.h>

/*{{{  search_insert_menu*/
private struct Menu *search_insert_menu (char *ptr)
 {
  struct Menu *m=menu_root,*lm=0;;

  while (m)
   /*{{{  search menu entry*/
   {
    if (!strcmp (m->MenuName,ptr)) return m;
    lm = m;
    m=m->NextMenu;
   }
   /*}}}  */
  if (!(m= (struct Menu *)malloc (sizeof (struct Menu)))) return 0;
  m->NextMenu = 0;
  if (!(m->MenuName = strdup (ptr)))
   /*{{{  error*/
   {
    free (m);
    return 0;
   }
   /*}}}  */
  m->FirstItem = 0;
  if (menu_root) lm->NextMenu = m;
  else menu_root = m;
  return m;
 }
/*}}}  */
/*{{{  search_insert_item*/
private void search_insert_item (struct Menu *me, char *ptr)
 {
  struct MenuItem *m=me->FirstItem,*lm=0;
  struct IntuiText *i;

  while (m)
   /*{{{  search item*/
   {
    if (!strcmp (((struct IntuiText *)m->ItemFill)->IText,ptr)) return;
    lm = m;
    m = m->NextItem;
   }
   /*}}}  */
  if (!(m = (struct MenuItem *)malloc (sizeof (struct MenuItem))))
    return;
  if (!(i = (struct IntuiText *)malloc (sizeof (struct IntuiText))))
   /*{{{  error*/
   {
    free (m);
    return;
   }
   /*}}}  */
  if (!(i->IText = strdup (ptr)))
   /*{{{  error*/
   {
    free (m);
    free (i);
    return;
   }
   /*}}}  */
  if (lm) lm->NextItem = m;
  else me->FirstItem = m;
  m->NextItem = 0;
  m->ItemFill = (APTR)i;
  return;
 }
/*}}}  */
#endif
/*}}}  */
/*{{{  os_ext_handle*/
public void os_ext_handle (FILE *f, int j)
 {
  char str[_POSIX_PATH_MAX],*p=str,*pp;
  int i=_POSIX_PATH_MAX;
  *p++=j;
  while ((i--)&&(*p=getc(f))&&(*(p++)!=EOF));
  if (!*str) return;
  if (!strncmp (str,"AREXX",5))
   /*{{{  AREXX os-extensions*/
   {
    if ((arexx==False)||(!_arexx)) return;
    p=str+5;
    if (!*p) return;
    if (isspace (*p))
     /*{{{  AREXX command,macro-number*/
     {
      while ((*p)&&(isspace(*p++)));
      if (!*p) return;
      pp=p-1;
      while ((*p)&&(*p++!=','));
      if (!*p)return;
       {
        AREXX_COM *com;

        if (!(com = malloc (sizeof (AREXX_COM)+(p-pp)+1))) return;
        *(p-1)=0;
        com->mac = atoi(p);
        strcpy (com->name,pp);
        com->Next = _arexx->command;
        _arexx->command= com;
       }
     }
     /*}}}  */
    else
     /*{{{  AREXXHIST number*/
     {
      if (strncmp (p,"HIST",4)) return;
      p+=4;
      while ((*p)&&(isspace(*p))) p++;
      if (!*p) return;
      _arexx->hist = atoi(p);
     }
     /*}}}  */
   }
   /*}}}  */
#ifdef MENU
  else if (!strncmp (str,"MENU",4))
   /*{{{  MENU menuname[,itemname]*/
   {
    p=str+4;
    while ((*p)&&(isspace(*p++)));
    if (!*p) return;
    pp=p-1;
    while ((*p)&&(*p++!=','));
    if (!*(p-1))
     /*{{{  only menuname*/
     {
      search_insert_menu(pp);
      return;
     }
     /*}}}  */
    else
     /*{{{  menu and itemname*/
     {
      struct Menu *cur_menu;

      *(p-1)=0;
      while ((*p)&&(isspace(*p++)));
      if (!(cur_menu = search_insert_menu (pp))) return;
      search_insert_item (cur_menu,p-1);
      return;
     }
     /*}}}  */
   }
   /*}}}  */
#endif
 }
/*}}}  */

/*{{{  strerror*/
public char *strerror(int errno)
 {
  return (errno<__sys_nerr ? __sys_errlist[errno] : "unknown");
 }
/*}}}  */
