/*
 * Logo.c :
 * --------
 * Auteur         : Xavier Mertens
 * Version        : 1 
 * Révision       : 01
 * Langage        : Lattice c v5.0
 * Compatibilité  : 1.3 - 2.x - Arexx  
 * Description    : Démo d'interface Arexx.
 *
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <arexx/myminrexx.h>
#include <proto/all.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

#define MY_NAME "REXX_LOGO"
#define TWO_PI  (3.141595653589793*2)
#define WFLAGS  WINDOWDRAG|WINDOWDEPTH|GIMMEZEROZERO

BOOL SetUpArea(int numargs,char **args);
void CleanExit(char *errmsg);
BOOL InterpretCommand(struct RexxMsg *msg);

struct NewWindow NewTurtleW={
  0,0,0,0,0,1,NULL,WFLAGS,NULL,NULL,
  "Arexx Démo v1.01 écrit par Xavier Mertens,août 92",
  NULL,NULL,20,20,-1,-1,WBENCHSCREEN
};

struct Window        *TWindow=NULL;
struct MsgPort       *MyPort=NULL;
struct IntuitionBase *IntuitionBase=NULL;
struct RxsLib        *RexxSysBase=NULL;
struct GfxBase       *GfxBase=NULL;
struct RastPort      *RPort;

double angle=0.0,
       posx=0,
       posy=0;

double scalex=1.0,
       scaley=1.0;

BOOL penup=TRUE;
LONG pencolor=0;
USHORT width,
       height;

/* Initialisation de l'aire de dessin */

BOOL SetUpArea(int numargs,char **args){
  NewTurtleW.LeftEdge=atoi(args[1]);
  NewTurtleW.TopEdge=atoi(args[2]);
  width=atoi(args[3]);
  height=atoi(args[4]);
  NewTurtleW.Width=width+8;
  NewTurtleW.Height=height+14;
  if(width<=20 || height<=20)
    return(FALSE);
  if(!(TWindow=OpenWindow(&NewTurtleW)))
    return(FALSE);
  RPort=TWindow->RPort;
  Move(RPort,0,0);
  return(TRUE);
}

/* Routine sans commentaire! */

void CleanExit(char *errmsg){
  if(TWindow)       CloseWindow(TWindow);
  if(IntuitionBase) CloseLibrary(IntuitionBase);
  if(GfxBase)       CloseLibrary(GfxBase);
  if(MyPort)        DeletePort(MyPort);
  if(RexxSysBase)   CloseLibrary(RexxSysBase);
  if(errmsg){
    puts(errmsg);
    exit(5);
  }
  exit(0);
}

/* Routine principale : interpretation des message ARexx */

BOOL InterpretCommand(struct RexxMsg *msg){
  char *result="1";
  long primary=0,
       secondary=0;
  int i,
      cmdcount,
      pos;
  char command[4][20];
  BOOL notdead=TRUE;
  pos=0;
  for(i=0,cmdcount=0;i<strlen(msg->rm_Args[0]);i++){
    char c=msg->rm_Args[0][i];
    if(c==' '){
      command[cmdcount++][pos]='\0';
      pos=0;
    }
    else
      command[cmdcount][pos++]=(isupper(c) ? c : toupper(c));
  }
  command[cmdcount++][pos]='\0';
  for(i=cmdcount;i<4;i++)
    *command[i]='\0';
  if(strcmp(strupr(command[0]),"CLEAR")==NULL){
    if(*command[1]){
      SetAPen(RPort,atoi(command[1]));
      RectFill(RPort,0,0,width,height);
      SetAPen(RPort,pencolor);
    }
    else
      ERR_NUM_ARGS;
  }
  else
    if(strcmp(strupr(command[0]),"HOME")==NULL){
      posx=posy=angle=0.0;
      scalex=scaley=1.0;
    }
  else
    if(strcmp(strupr(command[0]),"PEN")==NULL){
      if(*command[1]){
        if(strcmp(strupr(command[1]),"UP")==NULL)
          penup=TRUE;
        else
          if(strcmp(strupr(command[1]),"DOWN")==NULL)
            penup=FALSE;
        else
          if(strcmp(strupr(command[1]),"COLOR")==NULL){
            if(*command[2]){
              pencolor=atoi(command[2]);
              SetAPen(RPort,pencolor);
            }
            else
              ERR_NUM_ARGS;
          }
          else
            ERR_BAD_TOKEN;
      }
      else
        ERR_NUM_ARGS;
    }
  else
    if(strcmp(strupr(command[0]),"AHEAD")==NULL){
      if(*command[1]){
        double distance=atof(command[1]);
        if( distance >0.0){
          posx+=cos(angle)*distance*scalex;
          posy+=sin(angle)*distance*scaley;
          if(penup)
            Move(RPort,(SHORT)posx,(SHORT)posy);
          else
            Draw(RPort,(SHORT)posx,(SHORT)posy);
        }
        else
          ERR_INVALID_ARGS;
      }
      else
        ERR_NUM_ARGS;
    }
  else
    if(strcmp(strupr(command[0]),"DIMENSIONS")==NULL){
      if(*command[1] && *command[2]){
        double dx=atof(command[1]);
        double dy=atof(command[2]);
        if( dx>0.0 && dy>0.0){
          scalex=width/dx;
          scaley=height/dy;
        }
        else
          ERR_INVALID_ARGS;
      }
      else
        ERR_NUM_ARGS;
    }
  else
    if(strcmp(strupr(command[0]),"TURN")==NULL){
      if(*command[1])
        angle+=(atof(command[1])/360.0*TWO_PI);
      else
        ERR_NUM_ARGS;
    }
  else
    if(strcmp(strupr(command[0]),"DIE")==NULL)
      notdead=FALSE;
  else
    ERR_BAD_TOKEN;
  ReplyRexxCommand(msg,primary,secondary,result);
  return(notdead);
}

void main(int argc,char **argv){
  BOOL notdone=TRUE;
  struct RexxMsg *RxMsg;
  if(argc==0)
    CleanExit(NULL);
  if(argc!=5){
    puts("Logo v1.01 écrit par Xavier Mertens - Août 92");
    CleanExit("Syntaxe : Logo <x> <y> <largeur> <hauteur>");
  }
  if(!(RexxSysBase=OpenLibrary("rexxsyslib.library",NULL)))
    CleanExit("Pas de rexxsyslib.library?");
  if(!(IntuitionBase=OpenLibrary("intuition.library",NULL)))
    CleanExit("Pas d'intuition.library?");
  if(!(GfxBase=OpenLibrary("graphics.library",NULL)))
    CleanExit("Pas de graphics.library?");
  if(!SetUpArea(argc,argv))
    CleanExit("Pas de fenêtre?");
  if(!(MyPort=SetupMyPort(MY_NAME)))
    CleanExit("Pas de port?");
  while(notdone){
    WaitPort(MyPort);
    while(notdone && (RxMsg = (struct RexxMsg *)GetMsg(MyPort))){
      notdone=InterpretCommand(RxMsg);
    }
  }
  CleanExit(NULL);
}

/* Eof */
