// Emacs will be in -*- Mode: c++ -*-
//
// ********** DO NOT REMOVE THIS BANNER **********
//
// SUMMARY: Language for a Finite Element Method
// RELEASE: 2.0
// USAGE  : You may copy freely these files and use it for
//          teaching or research. These or part of these may
//          not be sold or used for a commercial purpose with-
//          out our consent : fax (33)1 44 27 44 11
//
// AUTHORS:  D. Bernardi, Y. Darmaillac F. Hecht,
//           P. Parole O. Pironneau C. Prud'homme
// ORG    :
// E-MAIL :   pironneau@ann.jussieu.fr
//
// ORIG-DATE:     June-94
// LAST-MOD:     24-Jan-96 at 15:01:16 by Prud'homme Christophe
//
// DESCRIPTION:
// DESCRIP-END.
//

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <Windows.h>
#include <SegLoad.h>
#include <StandardFile.h>
#include <new.h>
/*
 * FreeFem includes
 */
#include <opclass.h>
#include <disk.h>
#include <lexical.h>
#include <syntaxic.h>
#include <rgraph.h>

/*
 * for the three following lines see syntaxic.cpp
 */
extern void parse (char *);
extern char errbuf[];
extern float xfmin, xfmax;  // used to print on graphics max & min of function
extern triangulation t;

static float aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax;
static int carre, lacouleur;
static WindowRecord wgRecord0;
static WindowPtr   grafWindow0;
static  Rect    boundsRect;

int getcolor();
void putpixel(int ix,int iy, int couleur);
int scalx(float x);
int scaly(float y);
void out_of_memory ();
void NEW_HANDLER (void);

void out_of_memory ()
{
  cout << "FreeFEM error: operator new failed; not enough memory" << endl;
  exit (-1);
}

void NEW_HANDLER (void){  set_new_handler (&out_of_memory);}

void message(char *s){    printf("%s \n", s);   }

void erreur(char *s)
{
    printf("\n Fatal error\n");
    exit(0);
}

void initgraphique(void)
{
   	InitGraf((Ptr) &qd.thePort);
	InitFonts();
  	InitWindows();
    InitMenus();
 	FlushEvents(everyEvent,0);
   	TEInit();
	InitDialogs(0L);
  	InitCursor();

    boundsRect.top = 45;
 	boundsRect.left = 15;
   boundsRect.right = 460;
	boundsRect.bottom = 460 ;
  grafWindow0=NewCWindow(&wgRecord0, &boundsRect, "\pGraphics",true, 8,
NULL, true, 0);
    ShowWindow(grafWindow0);
 	BringToFront(grafWindow0);
   SelectWindow(grafWindow0);
	SetPort(grafWindow0);
    aspx = boundsRect.right - boundsRect.left -10;
   aspy = boundsRect.bottom - boundsRect.top - 10;
  carre = aspx == aspy;
    lacouleur = getcolor();
}

void closegraphique(void){  CloseWindow(grafWindow0);  }

void rattente(int waitm)
{
 char c=' '; Str255 buf;
/*    you may prefer to use carriage return to move to the next graph */
/*   getc(stdin);
*/
buf[0]= 11; MoveTo(10,10); TextSize(9);
if(xfmin != xfmax)
{
	sprintf((char*)(buf+1),"%10.3e",xfmin);	DrawString(buf);
 	MoveTo(10,20);
 	sprintf((char*)(buf+1),"%10.3e",xfmax);	DrawString(buf);
}
if(waitm)
 {
 	MoveTo(10,30);
 	sprintf((char*)(buf+1), "Click mouse");
 	DrawString(buf);
 	while(!Button()){ };
 }
}



void reffecran(void){  EraseRect(&(grafWindow0->portRect));}

int getcolor(void){ return 0;}
void putpixel(int ix,int iy, int couleur){}
void couleur(int c){  }

void cadre(float xmin,float xmax,float ymin,float ymax)
{
  rxmin = xmin;
  rxmax = xmax;
  rymin = ymin;
  rymax = ymax;
  echx = aspx / (xmax - xmin);
  echy = aspy / (ymax - ymin);
}

void cadreortho(float centrex, float centrey, float rayon)
{
  int xasp,yasp, getmaxx, getmaxy;
  getmaxx = xasp =aspx; getmaxy = yasp = aspy;
  if (getmaxx * (float)xasp > getmaxy * (float)yasp)
  {
    rymin = centrey - rayon;
    rymax = centrey + rayon;
    echy= getmaxy / (2 * rayon);
    echx= (echy * xasp) / yasp;
    rxmin= centrex - getmaxx / (2 * echx);
    rxmax= centrex + getmaxx / (2 * echx);
  }
  else
  {
    rxmin = centrex - rayon;
    rxmax = centrex + rayon;
    echx = getmaxx / (2 * rayon);
    echy = (echx * yasp) / xasp;
    rymin = centrey - getmaxy / (2 * echy);
    rymax = centrey + getmaxy / (2 * echy);
  }
}

int scalx(float x){  return (x - rxmin) * echx;}
int scaly(float y){  return (rymax - y) * echy;}
void pointe(float x, float y){  putpixel(scalx(x), scaly(y), lacouleur);}
void rmoveto(float x, float y){  MoveTo(5+scalx(x), 5+scaly(y));}
void rlineto(float x, float y){  LineTo(5+scalx(x),5+ scaly(y));}


void raffpoly(int n, float *poly)
{
  PolyHandle thePoly;
  int i;
  thePoly =OpenPoly();
   rmoveto(poly[0], poly[1]);
    for(i=1; i<n; i++)
    rlineto(poly[2*i], poly[2*i+1]);
    ClosePoly();
    FillPoly(thePoly,&qd.white);
    FramePoly(thePoly);
    KillPoly(thePoly);
}

int pStrCopy (StringPtr p1, StringPtr p2)
/* copies a pascal string `p1 into a C string */
{
  int len,i;
  len = *p1++;
  for(i=1;i<=len;i++) *p2++=*p1++;
  *p2 = 0;
  return 0;
}

int getprog(char* fn,int argc, char** argvptr)
{
    Point SFGwhere = { 90, 82 };
    SFReply reply;
    SFTypeList  myTypes;

    InitGraf((Ptr) &qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    FlushEvents(everyEvent,0);
    TEInit();
    InitDialogs(0L);
    InitCursor();
    myTypes[0] = 'TEXT';
    SFGetFile(SFGwhere, "\p", 0L, 1, myTypes, 0L, &reply );
    if (!reply.good) return (-1);
	if(noErr != SetVol(0, reply.vRefNum))
			erreur("Could not set current volume folder");
    pStrCopy(reply.fName, (StringPtr)fn);
    return (2);
}

void execute(char* what)
{
    // exec(what); link with unix lib
}

/* MAIN of freefem*/
int
main (int argc, char **argv)
{
  char       *prog;
  char       *fname;

  NEW_HANDLER (); // see dependent system files ({pc,x,mac}rgraph.{h,cpp})

  fname = new char[256];

  printf ("PROGRAM\n");
  argc = getprog (fname, argc, argv);
  OPTION = 0;
  if (argc == 2)
    {
      prog = readprog (fname);
      parse (prog); // parse prog buffer
      /*
       * Freeing the triangulation
       */
      delete [] t.rp;
      delete [] t.tr;
      delete [] t.ng;
      delete [] t.ngt;
    }
  else
    printf ("To launch freefem you must type freefem  and a file name\n");
  return 0;
}
