// $Id: rpn.hh,v 1.12 1997/01/07 01:07:33 aml Exp $

#ifndef _RPN_DOT_HH_
#define _RPN_DOT_HH_

#define MODE_EVAL 1
#define MODE_FORMULA 2

#define MAX_FORMULA_SIZE 256

#define Refmask  (1 << 15)
#define Refmask2  (1 << 14)
#define Refmask3  (1 << 13)


class Ref;
class Range;
class Stack_elem;
class Formula;

#include "utils.hh"
#include <stdarg.h>
#include "string.hh"
#include "wk1.hh"
#include "xxl_util.hh"
#include "xxl_funcs.hh"



Ref *cell_reference(char *);
Range *range_reference(char *,char *);
short cell_address(short x,short base);
void change_col_to_relative(Ref *pt_ref1, short col);
void change_row_to_relative(Ref *pt_ref1, short col);

#define STACK_VALUE(p) ((p)->type == FORM_FP ? (p)->contents.fp_val : (p)->contents.int_val)

#define IS_RELATIVE(x) ((x) & (1 << 15))

#define EVAL_FIXED_ARGS(Function,sheet,col,row,nargs) {                \
                                      Function *f = new Function();    \
                                      new_top = top-nargs;             \
                                      Stack_elem *p;                   \
                                      p = f->eval(top-1,sheet,col,row);\
                                      *new_top = *p;                 \
                                      delete f;                        \
                                      top = new_top+1;                 }


#define STRING_FIXED_ARGS(NAME,nargs) {\
                           new_top = top-nargs;        \
                           s2 = NAME;                  \
                           s2 += "(";                  \
                           for( ; nargs > 1; nargs--) { \
                               s1 = (top-nargs)->st_val;\
                               s2 += s1;                \
                               s2 += ",";               \
                           }                            \
                           s1 = (top-1)->st_val;       \
                           s2 += s1;                   \
                           s2 += ")";                  \
                           new_top->st_val = s2;       \
                           new_top->type = FORM_STRING;\
                           top = new_top+1;            }
    


#define EVAL_VAR_NUM_ARGS(Function,sheet,col,row) { \
                                      cnt = (int) *aux;            \
                                      new_top = top-cnt;           \
                                      Function *f = new Function();\
                                      Stack_elem *p;               \
                                      for(i=cnt; i>0; i--)         \
                                          p = f->eval(top-i,sheet,col,row);\
                                      *new_top = *p ;            \
                                      delete f;                    \
                                      top = new_top+1  ;           \
                                      aux++; }



#define STRING_VAR_NUM_ARGS(NAME)    {   \
                                         cnt = (int) *aux;           \
                                         new_top = top-cnt;          \
                                         s2 = NAME;                  \
                                         s2 += "(";                  \
                                         for(i=cnt; i>0; i--) {      \
                                             s1 = (top-i)->st_val;   \
                                             s2 += s1;               \
                                             if (i != 1)             \
                                             s2 += ",";              \
                                         }                           \
                                         s2 += ")";                  \
                                         new_top->st_val = s2;       \
                                         new_top->type = FORM_STRING;\
                                         top = new_top+1;            \
                                         aux++;      }                


class Ref {
  public:
    short col;
    short row;
};

class Range {
  public:
    Ref start;
    Ref end;
    
    normalize();
};


class Formula {
  public:
    short typ;
    short size;
    double value;
    char *tmp_formula;
    char  *formula;
    char *st_value;
    Formula();
    void operator=(Formula &right);
    Formula(Formula &right);
    Formula(short siz, char *data);
    ~Formula();
};

struct  types {
    double fp_val;
    Ref ref_val;
    short int_val;
    Range rg_val;
    char *string_val;
    short error_code;
};

class Stack_elem {
  public:
    int type;
    struct types contents;
    string st_val;
    Stack_elem() {contents.string_val = new char[256]; 
                  contents.string_val[0] = 0;
                  contents.error_code = NO_ERROR;}
    ~Stack_elem() {delete [] contents.string_val;}
    operator=(const Stack_elem &right) {
      type = right.type;
      contents.fp_val = right.contents.fp_val;
      contents.ref_val = right.contents.ref_val;
      contents.int_val = right.contents.int_val;
      contents.rg_val = right.contents.rg_val;
      contents.error_code = right.contents.error_code;
      strcpy(contents.string_val,right.contents.string_val);
    }
    Stack_elem(const Stack_elem &right) {
      type = right.type;
      contents.fp_val = right.contents.fp_val;
      contents.ref_val = right.contents.ref_val;
      contents.int_val = right.contents.int_val;
      contents.rg_val = right.contents.rg_val;
      contents.error_code = right.contents.error_code;
      strcpy(contents.string_val,right.contents.string_val);      
    }
};

class Range_iter {
    Range rg;
    short col;
    short row;
  public:
    Range_iter(Range &r);
    Range_iter(){};
    void init(Range &r);
    void first(Ref &ref);
    void next(Ref &ref);
    int last();
};




#endif

/*
$Log: rpn.hh,v $
Revision 1.12  1997/01/07 01:07:33  aml
Error propagation for formulas fixed.
Edit operations in place.

Revision 1.11  1996/10/07 12:35:23  aml
First cut at error handling.
Date formats are in.
Fixed problem with blank cell drawing.

# Revision 1.10  1996/09/19  12:16:56  aml
# Created row and column insert.
# Fixed small problem with display of vergrown cells.
#
Revision 1.9  1996/08/28 17:17:10  aml
Load and save now accept string_value for formula cells.
This fixes previous thought problem of formula values not
being stored.
Functions upper,lower and proper created.
Function if can now return labels.
Fixed problem with function count.
Reasonably stable version, very used to manipulate notas.wk1.

Revision 1.8  1996/08/27 17:18:43  aml
First version of regressive tests created.
Changes were made to allow for string functions.
String function upper created. Raises the problem
that formulas do NOT have a space for string values,
and therefore have to be evaluated upon loading.

Revision 1.7  1996/08/26 17:22:22  aml
Function round fixed.
Many other functions added, from power to mod.

Revision 1.6  1996/04/23 09:42:43  aml
Data structures for ordered scans of rows and columns are in place.
Cell overlap is working.
Forward cell dependences inserted. Automatic recalculation created.
Uniformizaed label entry procedure.

# Revision 1.5  1996/03/11  15:47:43  aml
# Made redraw more efficient by removing at once all cells before redrawing.
# Fixed problem with unsufficient difinition of logical expressions.
# Added >=, <=, <>, @and and @or functions.
#
Revision 1.4  1996/03/08 19:00:17  aml
Fixed problem in string_single_arg macro
Created if function, boolean evaluations and so on.

Revision 1.3  1996/03/07 20:32:46  aml
Created print range ability.
Set in gray non-working menus.
Created RangeKill command.
Created round function and macros for single argument functions.

Revision 1.2  1996/02/16 18:03:59  aml
Fixed a memory bug in formula copy with purify.
Fixed a few minor bugs. Functional, stable version.

Revision 1.1  1996/02/16 17:37:02  aml
Initial revision

*/
