/*

  P-Code interpreter (to run the apple pascal system)
  Copyright (C) 2000 Mario Klebsch

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


  $Log: turtlegr.c,v $
  Revision 1.4  2001/06/06 23:14:19  mario
  Turtlegraphics wird jetzt mit einem #define aktiviert

  Revision 1.3  2001/05/23 21:16:41  mario
  Turtlegraphics wurde als eigener Prozess ausgelagert.

  Revision 1.2  2001/05/20 13:12:02  mario
  CVS-Idents und Logs eingefügt


*/

#ifdef TURTLEGRAPHICS

#ident "$Id: turtlegr.c,v 1.4 2001/06/06 23:14:19 mario Exp $";

#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>

#include "psystem.h"
#include "pcode.h"
#include "Memory.h"
#include "Stack.h"

static FILE *TurtleServer=NULL;

#define TURTLE_SPEEDUP

#ifdef TURTLE_SPEEDUP
static Integer	CurrentTurtleX;
static Integer	CurrentTurtleY;
static Integer	CurrentTurtleAng;
#endif

void StartTurtleServer(void)
{
  int fd[2];
  int pid;
  int i;

  if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)<0)
    {
      perror("socketpair()");
      return;
    }
  if ((pid=fork())<0)
    {
      perror("fork()");
      return;
    }
  if (!pid)
    {
      if (fd[1]!=0)
	{
	  close(0);
	  dup2(fd[1],0);
	}
      if (fd[1]!=1)
	{
	  close(1);
	  dup2(fd[1],1);
	}
      for (i=getdtablesize();i>2;i--)
	close(i);
      execlp("xturtleserver", "xturtleserver", NULL);
      execlp("./xturtleserver", "xturtleserver", NULL);
      perror("xturtleserver");
      _exit(1);
    }
  close(fd[1]);
  TurtleServer=fdopen(fd[0], "wb+");
}

void tprintf(char *format, ...)
{
  va_list ap;
  if (!TurtleServer)
    StartTurtleServer();

  if (TurtleServer)
    {
      va_start(ap, format);
      vfprintf(TurtleServer, format, ap);
      va_end(ap);
      putc('\n', TurtleServer);
    }
}

Integer tgetint(void)
{
  int i=0;
  char	Buffer[20];

  fflush(TurtleServer);

  for (i=0; i<19;i++)
    {
      Buffer[i]=getc(TurtleServer);
      if (Buffer[i]=='\n')
	break;
    }

  Buffer[i]='\0';

  sscanf(Buffer, "%d", &i);
  return ((Integer)i);
}

#ifdef TURTLE_SPEEDUP
void TurnTo(int Angle)
{
  CurrentTurtleAng=Angle;
  while (CurrentTurtleAng<0)
    CurrentTurtleAng+=360;
  while (CurrentTurtleAng>=360)
    CurrentTurtleAng-=360;
}
#endif

void TurtleGraphics(word EntryPoint)
{
  int	i;
  char	func[64];
  char	*p;

  i=0;
  for (i=0; i<sizeof(func); i++)
    if (!(func[i]=MemRdByte(EntryPoint,i)))
      break;

  p=&func[16];
  if (strcmp(p, "INITTURTLE")==0)
    tprintf("INITTURTLE");
  else if (strcmp(p, "TURN")==0)
    {
      Integer i=PopInteger();
      tprintf("TURN %d",i);
#ifdef TURTLE_SPEEDUP
      TurnTo(CurrentTurtleAng+i);
#endif
    }
  else if (strcmp(p, "TURNTO")==0)
    {
      Integer i=PopInteger();
      tprintf("TURNTO %d",i);
#ifdef TURTLE_SPEEDUP
      TurnTo(i);
#endif
    }
  else if (strcmp(p, "MOVE")==0)
    {
      Integer i=PopInteger();
      tprintf("MOVE %d",i);
#ifdef TURTLE_SPEEDUP
      CurrentTurtleX+=rint(cos(CurrentTurtleAng*3.14/180)*i);
      CurrentTurtleY+=rint(sin(CurrentTurtleAng*3.14/180)*i);
#endif
    }
  else if (strcmp(p, "MOVETO")==0)
    {
      Integer y=PopInteger();
      Integer x=PopInteger();
      tprintf("MOVETO %d %d",x,y);
#ifdef TURTLE_SPEEDUP
      CurrentTurtleX=x;
      CurrentTurtleY=y;
#endif
    }
  else if (strcmp(p, "PENCOLOR")==0)
    tprintf("PENCOLOR %d",Pop());
  else if (strcmp(p, "TEXTMODE")==0)
    tprintf("TEXTMODE");
  else if (strcmp(p, "GRAFMODE")==0)
    tprintf("GRAFMODE");
  else if (strcmp(p, "FILLSCREEN")==0)
    tprintf("FILLSCREEN %d",Pop());
  else if (strcmp(p, "VIEWPORT")==0)
    {
      int yMax=PopInteger();
      int yMin=PopInteger();
      int xMax=PopInteger();
      int xMin=PopInteger();
      tprintf("VIEWPORT %d %d %d %d",xMin, xMax, yMin, yMax);
    }
  else if (strcmp(p, "TURTLEX")==0)
    {
      Pop();
      Pop();
#ifdef TURTLE_SPEEDUP
      Push(CurrentTurtleX);
#else
      tprintf("TURTLEX");
      Push(tgetint());
#endif
    }
  else if (strcmp(p, "TURTLEY")==0)
    {
      Pop();
      Pop();
#ifdef TURTLE_SPEEDUP
      Push(CurrentTurtleY);
#else
      tprintf("TURTLEY");
      Push(tgetint());
#endif
    }
  else if (strcmp(p, "TURTLEANG")==0)
    {
      Pop();
      Pop();
#ifdef TURTLE_SPEEDUP
      Push(CurrentTurtleAng);
#else
      tprintf("TURTLEANG");
      Push(tgetint());
#endif
    }
  else if (strcmp(p, "SCREENBIT")==0)
    {
      Integer y=PopInteger();
      Integer x=PopInteger();
      tprintf("SCREENBIT %d %d",x ,y);
      Push(tgetint());
    }
  else if (strcmp(p, "DRAWBLOCK")==0)
    {
      int	x;
      int	y;
      Integer Mode    = PopInteger();
      Integer YScreen = PopInteger();
      Integer XScreen = PopInteger();
      Integer Height  = PopInteger();
      Integer Width   = PopInteger();
      Integer YSkip   = PopInteger();
      Integer XSkip   = PopInteger();
      Integer RowSize = PopInteger();
      word Source     = Pop();

      tprintf("DRAWBLOCK %d %d %d %d %d %d %d %d",
	      (((XSkip+Width+7)&~7)-(XSkip&~7))>>3, XSkip&7, 0,
	      Width, Height, XScreen, YScreen, Mode);
      for (y=0; y<Height; y++)
	for (x=(XSkip&7);x<((XSkip+Width+7)&~7);x+=8)
	  putc(MemRdByte(Source, (y+YSkip)*RowSize+x/8), TurtleServer);
    }
  else if (strcmp(p, "WCHAR")==0)
    {
      tprintf("WCHAR %d",Pop()&0xff);
#ifdef TURTLE_SPEEDUP
      CurrentTurtleX += 7;
#endif
    }
  else if (strcmp(p, "WSTRING")==0)
    {
      word Addr=Pop();
      int  Len=MemRdByte(Addr, 0);
      int  i;

      tprintf("WSTRING %d",Len);
      for (i=0;i<Len; i++)
	putc(MemRdByte(Addr, i+1), TurtleServer);
#ifdef TURTLE_SPEEDUP
      CurrentTurtleX += 7*Len;
#endif
    }
  else if (strcmp(p, "CHARTYPE")==0)
    tprintf("WCHAR %d",Pop()&0x0f);
  else
    XeqError(XNOTIMP);
  fflush(TurtleServer);
}

void GraphicsClear(void)
{
  int status;
  if (TurtleServer)
    {
      fclose(TurtleServer);
      TurtleServer=NULL;
      wait(&status);
    }
}

#endif /* TURTLEGRAPHICS */
