
#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>
#include "resource.h"
#include "PCalcMain.h"
#include "ExecProg.h"
#include "MainForm.h"
#include "Misc.h"
#include "evalexpr.h"


/* define global variables. */
static FieldPtr gExprField;
static FieldPtr gAnswField;


/* prototypes. */
static void SkipSpace(Char**);
static Int  CompareWord(Char**, Char*);
static Int  GetQuotedString(CharPtr*, CharPtr, Int);


/* define functions. */
Int ExecProgram(Char** p)
{
  gExprField = GetObjectPtr(fieldMainExprID);
  gAnswField = GetObjectPtr(fieldMainAnswID);

  SkipSpace(p);
  do {
    /*** '#' character (comment line) ***/
    if (**p == '#') {
      while ((**p != '\n') && (**p != '\0')) (*p)++;
    }
    /*** CR character ***/
    else if (**p == '\n') {
      (*p)++;
    }
    /*** @DISP command ***/
    else if (CompareWord(p, "@DISP ")) {
      Char s[32];
      Int err;

      SkipSpace(p);
      err = GetQuotedString(p, s, sizeof(s));
      if (err != 0) return err;
      SetFieldText(fieldMainAnswID, s);
      g.LastAnsValid = false;
    }
    /*** @SETEXPR command ***/
    else if (CompareWord(p, "@SETEXPR ")) {
      Char s[128];
      Int err;

      SkipSpace(p);
      err = GetQuotedString(p, s, sizeof(s));
      if (err != 0) return err;
      InsPtEnable(true);
      SetFieldText(fieldMainExprID, s);
    }
    /*** @EVAL command ***/
    else if (CompareWord(p, "@EVAL")) {
      Int error;
      Char* expr;
      double x;
      Char s[32];

      expr = FldGetTextPtr(gExprField);
      FldSetSelection(gExprField, 0, 0);
      error = evaluate(&expr, &x);
      if (error == 0) {
	g.Memory[0] = x;
	GetAnswerFormat(x, s, g.DisplayDigit, g.DispAddFormat);
	SetFieldText(fieldMainAnswID, s);
	GetAnswerFormat(x, gLastAnsStr, g.InsertDigit, 0);
	InsPtEnable(false);
	g.LastAnsValid = finite(x) ? true : false;
	g.FirstInput = true;
      } else {
	SndPlaySystemSound(sndError);
	g.LastAnsValid = false;
	g.FirstInput = false;
	InsPtEnable(false);
	return error;
      }
    }
    /*** @STMEM command ***/
    else if (CompareWord(p, "@STMEM ")) {
      Int i;

      SkipSpace(p);
      i = **p - '0';
      if ((i < 0) || (i > kNumMemory)) return PROGERR_OUT_OF_RANGE;
      g.Memory[i] = g.Memory[0];
      (*p)++;
    }
    /*** @INPEXPR ***/
    else if (CompareWord(p, "@INPEXPR")) {
      g.FirstInput = false;
      InsPtEnable(true);
      return PROGSTA_PROMPT_MODE;
    }
    /*** unknown command ***/
    else {
      return PROGERR_UNKNOWN_COMMAND;
    }

    SkipSpace(p);
  } while (**p != '\0');

  return 0;
}


static void SkipSpace(Char** p)
{
  while ((**p == ' ') || (**p == '\t')) (*p)++;
}


static Int CompareWord(Char** str, Char* word)
{
  int len = StrLen(word);

  if (StrNCompare(*str, word, len) != 0) return false;
  *str += len;
  return true;
}


static Int GetQuotedString(CharPtr* p, CharPtr s, Int sz)
{
  CharPtr e = s + sz - 1;

  if (**p != '\"') return PROGERR_NO_QUOTATION;
  (*p)++;
  while ((**p != '\"') && (s < e)) {
    if ((**p == '\0') || (**p == '\n')) return PROGERR_QUOTE_NOT_CLOSED;
    *(s++) = *((*p)++);
  }
  *s = '\0';

  if (**p != '\"') return PROGERR_QUOTE_TOO_LONG;

  (*p)++;
  return 0;
}
