
/* "UNTIL", a graphics editor,
   Copyright (C) 1985, 1990 California Institute of Technology.
   Original authors: Glenn Gribble, port by Steve DeWeerth
   Unix Port Maintainer: John Lazzaro
   Maintainers's address: lazzaro@hobiecat.cs.caltech.edu;
                          CB 425 CU Boulder/Boulder CO 91125. 

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 (Version 1, 1989).

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; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
USA. */


/*******************************************************************************/
/*                                                                             */ 
/*  file contains stuff used to "walk" through the data structure              */
/*  cleaned up by steve - 9 May 1990                                           */
/*                                                                             */ 
/*******************************************************************************/

#include <p2c/p2c.h>

#include "datawalk.h"


#ifndef SYSGLOBALS_H
#include <p2c/sysglobals.h>
#endif

#ifndef NEWASM_H
#include <p2c/newasm.h>
#endif

#ifndef MYLIB_H
#include <p2c/mylib.h>
#endif

#ifndef NEWCRT_H
#include <p2c/newcrt.h>
#endif

#ifndef TABLET_STUFF_H
#include "tablet_stuff.h"
#endif

#ifndef MAT_STUFF_H
#include "mat_stuff.h"
#endif

#ifndef CRT_STUFF_H
#include "crt_stuff.h"
#endif

#ifndef BB_STUFF_H
#include "bb_stuff.h"
#endif

#ifndef GR_STUFF_H
#include "gr_stuff.h"
#endif

#ifndef DISPMOD_H
#include "dispmod.h"
#endif

#ifndef DATA_TYPES_H
#include "data_types.h"
#endif


typedef struct d_rec {
  d_kinds kind;
  union {
    object *op;
    figure *fgp;
    fileSpec *fip;
    pnt_elem *pp;
    path_head *php;
    path_elem *pap;
  } UU;
} d_rec;


/* constants for text attributes */
/* add these constants together in the text fields to get the desired effect */
/* attributes for text should be chosen as follows: */
/* alpha colors - choose 1 only */

#define green           0
#define yellow          4096
#define black           8192
#define red             12288
#define cyan            16384
#define white           20480
#define blue            24576
#define purple          28672
/* other alpha attributes - choose as many as wanted */
#define inv             256
#define blink           512
#define under           1024
#define half            2048


Static short curYval;
Static Char *dispFontArr[maxFonts];


Static void expertOn(void)
{
  dispExpert = true;
  dispColor = blue + half;
}


Static void expertOff(void)
{
  dispExpert = false;
  dispColor = green;
}


Static void doInt(Char *name, long *i)
{
  dispAddMsg(10, curYval, 0, name);
  dispAddInt(25, curYval, 10, i, LONG_MIN, LONG_MAX);
  curYval++;
}


Static void doShort(Char *name, short *s)
{
  dispAddMsg(10, curYval, 0, name);
  dispAddShort(25, curYval, 10, s, -32768L, 32767);
  curYval++;
}


Static void doFont(Char *name, short *f)
{
  short i;

  dispAddMsg(10, curYval, 0, name);
  for (i = 0; i < maxFonts; i++)
    dispFontArr[i] = fonts[i].dispName;
  dispAddSList(25, curYval, 10, f, maxFonts, dispFontArr);
  curYval++;
}


Static void doPtr(Char *name, void **a)
{
  dispAddMsg(10, curYval, 8, name);
  dispAddPtr(25, curYval, 10, a);
  curYval++;
}


Static void doEnum2(Char *name, short *e, short num, Char *vals)
{
  dispAddMsg(10, curYval, 8, name);
  dispAddEnum2(25, curYval, 10, e, num, vals);
  curYval++;
}


Static void doBool(Char *name, boolean *b)
{
  dispAddMsg(10, curYval, 8, name);
  dispAddEnum1(25, curYval, 10, (Char *)b, 1, "False,True");
  curYval++;
}


Static void doStr(Char *name, Char *s)
{
  dispAddMsg(10, curYval, 8, name);
  dispAddStr(25, curYval, 55, s, "");
  curYval++;
}


Static dispRec *d_object(object *o)
{
  dispRec *Result, *ret;
  pr_line_rec *WITH;
  pr_inst_rec *WITH1;

  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is an object");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit, ? for help");

  /* Display common factors */
  expertOn();
  doPtr("Next ^o", (void **)(&o->next));
  doPtr("Prev ^o", (void **)(&o->prev));
  dispAddMsg(10, curYval, 0, "BB (x,y)");
  dispAddInt(25, curYval, 10, &o->bb.xl, LONG_MIN, LONG_MAX);
  dispAddInt(35, curYval, 10, &o->bb.yl, LONG_MIN, LONG_MAX);
  dispAddInt(50, curYval, 10, &o->bb.xh, LONG_MIN, LONG_MAX);
  dispAddInt(60, curYval, 10, &o->bb.yh, LONG_MIN, LONG_MAX);
  curYval++;
  doEnum2("Kind", (short *)(&o->kind), 1, "Base,Prim");
  expertOff();


  /* Now check out the kind */
  if (o->kind == o_base) {
    expertOn();
    doPtr("Parent ^fg", (void **)(&o->okind.base.parent));
    Result = dispHead;
    doShort("RefCount", &o->okind.base.refcount);
    doPtr("Paths ^Ph", (void **)(&o->okind.base.paths));
    expertOff();
  }
  else {
    doShort("Color", &o->color.value);
    doShort("Priority", &o->color.priority);

    expertOn();
    doEnum2("PrKind", (short *)(&o->kind), (int)pr_last,
	    "None,Dot,Line,Box,Circle,Ellipse,Ngon,Text,Instance,Last");
    expertOff();
    Result = dispHead;
    curYval++;

    switch (o->kind) {

    case pr_none:
      /* blank case */
      break;

    case pr_dot:
      doInt("X", &o->okind.d.x);
      doInt("Y", &o->okind.d.y);
      break;

    case pr_line:
      WITH = &o->okind.l;
      doBool("Arrow 1", &WITH->h1);
      doBool("Arrow 2", &WITH->h2);
      doBool("Curve", &WITH->curve);
      doBool("Closed", &WITH->closed);
      doShort("L Width", &WITH->lwid);
      Result = dispHead;
      doShort("Wing Width", &WITH->wwid);
      doShort("Wing Length", &WITH->wlen);
      expertOn();
      doPtr("Points ^P", (void **)(&WITH->pnts));
      expertOff();
      break;

    case pr_box:
      doInt("Low X", &o->okind.b.x1);
      doInt("Low Y", &o->okind.b.y1);
      doInt("High X", &o->okind.b.x2);
      doInt("High Y", &o->okind.b.y2);
      Result = dispHead;
      break;

    case pr_circle:
      doInt("Center X", &o->okind.c.cx);
      doInt("Center Y", &o->okind.c.cy);
      doInt("Radius", &o->okind.c.r);
      Result = dispHead;
      break;

    case pr_ellipse:
      doInt("Center X", &o->okind.e.cx);
      doInt("Center Y", &o->okind.e.cy);
      doInt("Radius X", &o->okind.e.a);
      doInt("Radius Y", &o->okind.e.b);
      doInt("Start angle", &o->okind.e.s);
      doInt("Total angle", &o->okind.e.l);
      Result = dispHead;
      doInt("Rotate angle", &o->okind.e.r);
      doBool("Pie Slice", &o->okind.e.pie);
      break;

    case pr_ngon:
      doInt("Center X", &o->okind.n.x);
      doInt("Center Y", &o->okind.n.y);
      doShort("Radius", &o->okind.n.rad);
      Result = dispHead;
      doShort("Sides", &o->okind.n.sides);
      break;

    case pr_text:
      doInt("X", &o->okind.t.x);
      doInt("Y", &o->okind.t.y);
      doEnum2("Origin", (short *)(&o->okind.t.orig), (int)TLR,
	"TUpLeft,TUpCent,TUpRight,TCentLeft,TCentCent,TCentRight,TLowLeft,TLowCent,TLowRight");
      doShort("Scale", &o->okind.t.scale);
      doShort("Rot", &o->okind.t.rot);
      doShort("Slant", &o->okind.t.slant);
      doFont("Font", &o->okind.t.font);
      doShort("Font #", &o->okind.t.font);
      doStr("Words", o->okind.t.words);
      Result = dispHead;
      doStr("TeXWords", o->okind.t.TeXwords);
      break;

    case pr_inst:
      WITH1 = &o->okind.i;
      expertOn();
      doPtr("Contents ^o", (void **)(&WITH1->contents));
      expertOff();
      doInt("Rotation", &WITH1->rot);
      doInt("Tran X", &WITH1->tx);
      doInt("Tran Y", &WITH1->ty);
      doInt("Scale X", &WITH1->sx);
      doInt("Scale Y", &WITH1->sy);
      doInt("Sc Den", &WITH1->den);
      doBool("BBox only", &WITH1->closed);
      Result = dispHead;
      doBool("Mat only", &WITH1->matOnly);
      dispAddMsg(10, curYval, 0, "Matrix:");
      dispAddMsg(25, curYval, 0, "A:");
      dispAddInt(30, curYval, 10, &WITH1->m.a, LONG_MIN, LONG_MAX);
      dispAddMsg(45, curYval, 0, "B:");
      dispAddInt(50, curYval, 10, &WITH1->m.b, LONG_MIN, LONG_MAX);
      curYval++;
      dispAddMsg(25, curYval, 0, "C:");
      dispAddInt(30, curYval, 10, &WITH1->m.c, LONG_MIN, LONG_MAX);
      dispAddMsg(45, curYval, 0, "D:");
      dispAddInt(50, curYval, 10, &WITH1->m.d, LONG_MIN, LONG_MAX);
      curYval++;
      dispAddMsg(25, curYval, 0, "E:");
      dispAddInt(30, curYval, 10, &WITH1->m.e, LONG_MIN, LONG_MAX);
      dispAddMsg(45, curYval, 0, "F:");
      dispAddInt(50, curYval, 10, &WITH1->m.f, LONG_MIN, LONG_MAX);
      dispAddMsg(65, curYval, 0, "G:");
      dispAddInt(69, curYval, 10, &WITH1->m.g, LONG_MIN, LONG_MAX);
    }  /* case o.kind */
  }  /* if (o.kind == o_base) */

  return ret;
}


Static void d_fileSpec(fileSpec *f)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is a FILE");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit, ? for help");

  doStr("file name", f->fileName);
  doStr("DefMapFile", f->defMapFile);
  expertOn();
  doPtr("Next ^fi", (void **)(&f->next));
  doPtr("Figs ^Fg", (void **)(&f->figures));
  expertOff();

  doEnum2("Status", (short *)(&f->status), 2, "Enfant,Modif,Established");
}


Static void d_path_elem(path_elem *p)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is a path_elem");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit, ? for help");

  expertOn();
  doPtr("Next ^pa", (void **)(&p->next));
  doPtr("Obj ^O", (void **)(&p->obj));
  expertOff();
  doBool("Reverse", &p->rev);
}


Static void d_pathHead(path_head *p)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is a path_head");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit, ? for help");

  expertOn();
  doPtr("Next ^ph", (void **)(&p->next));
  doPtr("Path ^Pa", (void **)(&p->path));
  expertOff();
  doBool("Closed", &p->closed);
  doBool("Fill", &p->fill);
}


Static void d_pnt_list(pnt_elem *p)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is a point_list");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit, ? for help");

  expertOn();
  doPtr("Next ^p", (void **)(&p->next));
  expertOff();
  doInt("X", &p->x);
  doInt("X", &p->y);
}


Static void d_figure(figure *f)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "This is a figure");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit");

  doStr("Name", f->name);
  expertOn();
  doPtr("Next ^fg", (void **)(&f->next));
  doPtr("Guts ^O", (void **)(&f->guts));
  expertOff();
  doStr("Edit date", f->edit_date);
  doStr("Map File", f->mapFile);
  doShort("Grid", &f->grid);
  doShort("Line Wid", &f->linewidth);
  doShort("Wing Len", &f->wing_length);
}


Static void d_globals(void)
{
  dispColor = inv;
  dispAddMsg(-1, 0, 0, "These are global options");
  dispColor = green;
  dispAddMsg(-1, 1, 0, "Press [CNTRL-C] to exit");

  doShort("Line width", &curLWid);
  doBool("Double Arrows", &doubleArrows);
  doShort("WArr-Line Wid", &curLWidW);
  doShort("WArr-Wing Wid", &curWWidW);
  doShort("WArr-Wing Len", &curWLenW);
  doShort("NArr-Wing Wid", &curWWidN);
  doShort("NArr-Wing Len", &curWLenN);
  doEnum2("TextOrigin", (short *)(&curTextOrig), (int)TLR,
    "TUpLeft,TUpCent,TUpRight,TCentLeft,TCentCent,TCentRight,TLowLeft,TLowCent,TLowRight");
  doShort("Text Scale", &curTextScale);
  doShort("Text Rot", &curTextRot);
  doShort("Text Slant", &curTextSlant);
  doShort("Text Font #", &curTextFont);
  doFont("Text Font", &curTextFont);
  doBool("Show Arc Seg", &gr_show_seg);
  doBool("Show Bez Seg", &gr_show_control);
  doShort("Grid", &grid_mul);
  doShort("Grid offset", &grid_rnd);
  doBool("Inst BB", &showInstBB);
  /*doBool('Force to Grid',forceToGrid);*/
  doShort("Inst rots", &curRots);
  doShort("Boop time", &boopTime);
  doShort("Boop freq", &boopFreq);
}


Static Char *dispKinds_NAMES[] = {
  "D_MSG", "D_INT", "D_SINT", "D_STR", "D_ENUM", "D_SLIST", "D_CHAR",
  "D_ARRAY"
} ;


void startWalk(d_kinds kind, void *p)
{
  dispRec *ce, *ignore;
  d_rec stack[10];
  long stackP;
  d_rec current;

  Char c;
  Char name[101];
  dispRec *l;

  boolean done, quit;
  object *WITH;
  Char STR1[256];
  Char STR3[256];
  Char STR4[256];

  ce = NULL;
  for (stackP = 0; stackP <= 9; stackP++)
    stack[stackP].UU.op = NULL;
  stackP = 0;

  current.kind = kind;
  current.UU.op = p;
  quit = false;

  do {
    dispBegin();
    curYval = 2;
    switch (current.kind) {

    case d_obj:
      if (ce == NULL)
	ce = d_object(current.UU.op);
      else
	ignore = d_object(current.UU.op);
      break;

    case d_fig:
      d_figure(current.UU.fgp);
      break;

    case d_file:
      d_fileSpec(current.UU.fip);
      break;

    case d_pnt:
      d_pnt_list(current.UU.pp);
      break;

    case d_pHead:
      d_pathHead(current.UU.php);
      break;

    case d_path:
      d_path_elem(current.UU.pap);
      break;

    case d_gbl:
      d_globals();
      break;
    }

    dispDisp("\020\027\016\025\003", &c, &ce);

    if (current.kind == d_obj) {
      WITH = current.UU.op;

      /* Deal with things that need to be updated */
      switch (WITH->kind) {

      case pr_inst:
        set_instance_mat(current.UU.op);
        break;

      case pr_ellipse:
        set_ellipse_mbb(current.UU.op);
        break;
      }
    }

    if (c == '\003')   /* We are done */
      quit = true;
    else if (c == '\025') {
      if (stack[stackP].UU.op != NULL)
	current = stack[stackP];
      stackP = (stackP + 1) % 10;
    } else if ((uchar)c < 32 && ((1L << c) & 0x814000L) != 0) {
      l = dispHead;

      if (c == '\027') {   /* Walk */
	while (l != NULL && (l->kind != d_msg || l->y != ce->y))
	  l = l->next;
      } else {
	if (c == '\016')
	  strcpy(name, "next");
	else
	  strcpy(name, "prev");
	do {
	  done = (l->kind == d_msg && strbegins(strlower(STR1, l->UU.msgp),
						name));
	  if (!done)
	    l = l->next;
	} while (!(l == NULL || done));

	/* Now, find a current element that corresponds to the Next or Prev element */
	ce = dispHead;
	if (l != NULL) {
	  while (ce != NULL && ce->y != l->y && ce != l)
	    ce = ce->next;
	}
      }

      nc_gotoXY(0, 21);
      if (l == NULL)
	printf("\007\tBARF, l=NIL\n");
      else if (l->kind != d_msg)
	printf("\007\tBARF, l^.kind<>d_msg\n");
      else {
	/*writeln(#I'C=',c,' name=',l^.msgp^);*/
	strcpy(name, l->UU.msgp);
	if (ce->kind != d_int)
	  printf("\007CE is wrong kind, = %s\n",
		 dispKinds_NAMES[(long)ce->kind]);
	else if (strpos2(name, "^", 1) != 0 && *ce->UU.U1.icur != 0) {
	  strcpy(name, name + strpos2(name, "^", 1));
	  strcpy(STR3, strltrim(strrtrim(strcpy(STR4, name))));
	  strcpy(name, STR3);
	  if (isupper(name[0])) {  /* Push */
	    stackP = (stackP - 1) % 10;
	    stack[stackP] = current;
	  }
	  strlower(name, name);
	  if (!strcmp(name, "o")) {
	    current.kind = d_obj;
	    current.UU.op = (object *)(*ce->UU.U1.icur);
	  } else if (!strcmp(name, "fg")) {
	    current.kind = d_fig;
	    current.UU.fgp = (figure *)(*ce->UU.U1.icur);
	  } else if (!strcmp(name, "fi")) {
	    current.kind = d_file;
	    current.UU.fip = (fileSpec *)(*ce->UU.U1.icur);
	  } else if (!strcmp(name, "p")) {
	    current.kind = d_pnt;
	    current.UU.pp = (pnt_elem *)(*ce->UU.U1.icur);
	  } else if (!strcmp(name, "ph")) {
	    current.kind = d_pHead;
	    current.UU.php = (path_head *)(*ce->UU.U1.icur);
	  } else if (!strcmp(name, "pa")) {
	    current.kind = d_path;
	    current.UU.pap = (path_elem *)(*ce->UU.U1.icur);
	  }
	}
      }
    }
  } while (!quit);
  a_cleara();  /* steve */
}


