/****************************************************************************
    Copyright (C) 1987-2005 by Jeffery P. Hansen

    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., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************/
#ifndef __tkgate_h
#define __tkgate_h

#define TKGATE_EDITOR	1	/* This is the editor */
#define TOUCH_XGATE_ED	0	/* Consider XGate.ed to be undoable */

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <X11/Xlib.h> 
#include <X11/Xresource.h>
#include <X11/cursorfont.h>
#include "config.h"
#include "zoom.h"
#include "tcl.h"
#include "tk.h"
#include "tkgate_config.h"
#include "hash.h"
#include "list.h"
#include "misc.h"
#include "ycmalloc.h"
#include "expr.h"
#include "delay.h"
#include "icon.h"
#include "elements.h"
#include "simulate.h"
#include "module.h"
#include "vparser.h"
#include "scope.h"
#include "gates.h"
#include "wires.h"
#include "generic.h"
#include "functions.h"
#include "print.h"
#include "message.h"
#include "object.h"
#include "cpath.h"

#if TCL_MAJOR_VERSION != 8
#error This program has not been tested with versions of tcl/tk other than 8.*
#endif

/*
 * Versions of tcl/tk from 8.4 change some uses of 'char*' to 'const char*'.  Tkgate
 * now assumes 'const char*' is always used so if we are using an earlier version of
 * tcl/tk we need to cast them back to 'char*'.
 */
#if TCL_MINOR_VERSION <= 3
typedef int New_Tcl_CmdProc(ClientData d,Tcl_Interp *tcl,int argc,const char *argv[]);
#define Tcl_CreateCommand(t,c,f,d,x) Tcl_CreateCommand(t,c,(Tcl_CmdProc*)(f),d,x)
#define Tk_ConfigureWidget(t, w, cs, argc, argv, gw, flags) Tk_ConfigureWidget(t, w, cs, argc, (char**)(argv), gw, flags)
#define Tk_CreateWindowFromPath(tcl, root, name, top) Tk_CreateWindowFromPath(tcl, root, (char*)(name), (char*)(top))
#define Tcl_SetVar(tcl, var , val, flags) Tcl_SetVar(tcl, (char*)(var) , (char*)(val), flags)
#else
typedef Tcl_CmdProc New_Tcl_CmdProc;
#endif

/*
 * Coordinate conversion macros.  The 'ctow' macros convert from circuit
 * to window coordinates while the 'wtoc' mactos convert from window
 * to circuit coordinates.
 */
#define ctow_x(x) ((x) + XGate.circuit->org_x)
#define ctow_y(y) ((y) + XGate.circuit->org_y)
#define wtoc_x(x) ((x) - XGate.circuit->org_x)
#define wtoc_y(y) ((y) - XGate.circuit->org_y)

typedef struct tkggatwin_str TkgGateWin;
typedef struct xgateparams_str XGateParams;

typedef char VALUETYPE;		/* Type for hash table */



/*
 *  TkGate major modes
 */
typedef enum { MM_EDIT, 		/* Circuit editing mode */
	       MM_SIMULATE, 		/* Circuit simulation mode */
	       MM_ANALYZE		/* Critical path analysis mode */
}  MajorMode;

/*
 * Data structure used for building the "Make" menu.
 */
typedef struct  {
  char		*mname;		/* Actual name of the menu */
  int		count;		/* Number of entries on page */
  GKeyMenuEnt	**kme;		/* List of entries on page */
} BuildMenuRoot;

/*
 * Top-level data structure for "Make" menus
 */
typedef struct {
  SHash		*rmap;
  BuildMenuRoot	*roots[MAKEENTRYMAX];
  int numRoot;
}  MakeMenuData;

/*
 * An editstate is the context in which a module is edited.
 */
struct editstate {
  GModuleDef	*env;			/* Module edited in this block */
  GCElement	*inst;			/* Module instance (if opened from instance) */
  GSimModule	*smod;			/* Corresponding simulation module */

  int save_x,save_y;			/* Saved origin position */

  unsigned isInterface : 1;		/* Set if this is the module interface context */

  /*
   * The clip region is used when updating a portion of the screen such as
   * when scrolling.
   */
  struct {
    int isActive;			/* Set if clipping is active */
    int xmin,ymin;			/* The minimum and maximum */
    int xmax,ymax;			/* coordinates of the clip region */
  } clip;

  struct editstate *parent;		/* The parent edit state */
};

/*
 * A GSelection is a set of selected gates and wires.
 */
typedef struct {
  SHash		*s_gates;	/* Gates in the selection */
  SHash		*s_wires;	/* Wires between gates in s_gates */
  SHash		*s_edgeWires;	/* Wires with one end in s_gates */
  int		s_hasAnchored;	/* Selection has anchored gates */
} GSelection;

/*
 * A GCutBuffer is the object in which a collection of gates and wires
 * are held when doing a cut or copy operation.  A paste operation will
 * cause the contents of the cut buffer to be copied into the current
 * module.  Normally there is only one object of this type.
 */
typedef struct {
  int		cb_minx,cb_maxx;	/* Minimum and maximum x value for cut objects */
  int		cb_miny,cb_maxy;	/* Minimum and maximum y value for cut objects */
  int		cb_ctrx,cb_ctry;	/* Center point of selected region */

  int		cb_dx,cb_dy;		/* Offset for yank operations */
  GModuleDef	*cb_buf;		/* Gates/nets represented as a module */
} GCutBuffer;

/*
 * A GSearchContext is used to control a string search operation.
 */
typedef struct {
  int		mode;		/* Search mode */

  char		*target;	/* Target string */

  HashElem	*m_elem;	/* Current position in table of modules */
  HashElem	*g_elem;	/* Current position in table of gates */
  HashElem	*n_elem;	/* Current position in table of nets */
} GSearchContext;

/*
 * This data structure is used to represent the main editing canvas.
 */
struct tkggatwin_str {
  Tk_Window	win;		/* Main TK window */
  Display	*d;		/* Pointer to X11 display structure */
  Tcl_Interp	*tcl;		/* The Tcl interpteter */
  int		width, height;	/* Size of main window */
  XColor	*bgColor;	/* Background border color of main window */
  XColor	*fgColor;	/* Foreground border color of main window */
  GC		gc;		/* Graphics context */
  XGateParams	*parms;		/* TkGate main object */
  char		*xscroll;	/* Command for x scrolling */
  char		*yscroll;	/* Command for y scrolling */
  char		*takefocus;	/* Should we take focus */
};

/*
 * Top-level circuit data
 */
typedef struct circuit_str Circuit;
struct circuit_str {
  char		*currentFile;	/* Current file name */
  char		*fileVersion;	/* Version of current file */

  GCutBuffer	*cut_buffer;	/* Buffer for cut/paste operations */
  GSelection	*mg_selection;	/* The current multi-gate selection */
  
  SimInterface	simulator;	/* top-level state for the simulator */
  GSearchContext *search;	/* The current search context */

  GModuleDef	*mid_mod;	/* Module interface descriptors */
  GModuleDef	*root_mod;	/* Top-level module */
  GSimModule	*root_ss;	/* Root simulation state */
  EditState	*es;		/* Current editing context */

  SHash		*moduleTable;	/* Table of modules */
  int		numInitScripts;	/* Number of simulation initialization scripts */
  char		**initScripts;	/* Simulation initialization scripts */

  int		c_rememberProbes;
  int		c_numProbes;	/* Number of remembered probes */
  char		**c_probes;	/* Remembered probes */

  GCElement *select;		/* Current single-gate selection */
  GCElement *last;		/* Last selected gate */
  GWire *wsel;			/* Selected wire */
  GWireNode *wnsel;		/* Selected wire node */
  GNet *nsel;			/* Selected net */

  int no_set_modify;		/* Do not set 'modified' flag */

  int rot;			/* Current rotation */
  int mode;			/* Current mode */

  int org_x,org_y;		/* Origin point for viewable */
  int zoom_factor;		/* Zoom factor */

  int discardChanges;		/* Are we discarding changes? */
  int useExtBars;		/* Are we using extender bars? */

  int is_modified;		/* Is the circuit modified? */
};

typedef struct error_list_str ErrorList;
struct error_list_str {
  GError *errlist;
  GError *curerr;
  GError **errors;
  int ErrorCount;
  
  int ErrorXPos;
  int ErrorYPos;
};

typedef struct edit_data_str EditData;
struct edit_data_str {
  MajorMode major_mode;		/* The current major mode */

  int mark_vis;			/* Is the mark visible? */
  int mark_posted;		/* The mark has been posted (should be visible) */
  int mark_x, mark_y;		/* Position of mark */

  int tx,ty;
  int lx,ly;
  int sx,sy;

  int scr_x,scr_y;		/* Scrolling origin point */

  int		min_x,max_x;		/* Min and max x-coordinates of current module */ 
  int		min_y,max_y;		/* Min and max y-coordinates of current module */ 
};

/*
 * The single global variable XGate is of this type and is the main structure for
 * the application.
 */
struct  xgateparams_str {
  Tcl_Interp	*tcl;		/* The TCL intepreter */
  Display	*D;		/* X Display */
  Screen	*S;		/* Default screen of display */
  Window	W;		/* Editing window */
  Window	ScopeW;		/* Scope Window */
  Window	root;		/* Root window */
  Colormap	CM;		/* The color map */
  XrmDatabase	rdb;		/* The resource database */

  struct tkggatwin_str *gw;

  int		japaneseMode;	/* Are we in Japanese mode? */

  Tk_Font textF;		/* Normal text */
  Tk_Font textbF;		/* Bold text */
  Tk_Font stextF;		/* Small text */
  Tk_Font stextbF;		/* Small bold text */
#if TKGATE_JSUPPORT
  Tk_Font ktextF;		/* Kanji font */ 
#endif

  Font textXF;			/* Normal text */
  Font textbXF;			/* Bold text */
  Font stextXF;			/* Small text */
  Font stextbXF;		/* Small bold text */
#if TKGATE_JSUPPORT
  Font ktextXF;			/* Kanji font */ 
#endif

  GC instGC;			/* GC for built-in instances (variable font) */
  GC moduleGC;			/* GC for modules (variable font)  */
  GC modportGC;			/* GC for module ports  (variable font) */
  GC frameGC;			/* Dashed line GC for frames  (variable font) */
  GC commentGC;			/* GC for comments (variable font) */
  GC hyperlinkGC;		/* GC for hyperlink comments (variable font) */
  GC wireGC;			/* GC for wire drawing */
  GC busGC;			/* GC for multi-bit wire drawing */
  GC selWireGC;			/* GC for selected wire drawing */
  GC selBusGC;			/* GC for selected multi-bit wire drawing */
  GC toolGC;			/* GC for TkGate tools, etc. */
  GC cpathGC;			/* GC for critical path */
#if TKGATE_JSUPPORT
  GC kanjiGC;			/* GC for kanji (comments only) */ 
#endif

  GC copyGC;			/* Basic GC for copying areas, etc. */

  GC scopeGridGC;		/* Scope GC for grid lines, etc. */
  GC scopeOneGC;		/* Scope GC for non-zero signal values */
  GC scopeZeroGC;		/* Scope GC for 0 signal values */
  GC scopeFloatGC;		/* Scope GC for z,l,h signal values */
  GC scopeUnknownGC;		/* Scope GC for x signal values */
  GC scopeClearGC;		/* Scope GC for clearing signal values */
  GC scopeXHairGC;		/* Scope GC for crosshair. */
  GC scopeSelectGC;		/* Scope GC for scope selection. */

  GC bitGC;			/* special 1-bit GC */

  int inst_pixel;		/* Pixel value for instances */
  int ledoff_pixel;		/* Pixel value for off leds */
  int ledon_pixel;		/* Pixel value for on leds */
  int ledunknown_pixel;		/* Pixel value for led with unknown input */
  int comment_pixel;		/* Pixel value for comments */
  int hyperlink_pixel;		/* Pixel value for hyperlinks */

  struct {			/* Idle event flags */
    int pending;		/*   idle event pending */
    int redraw;			/*   redraw requested */
    int scroll_area;		/*   scroll change in viewable area requested */
    int scroll_new_x;		/*   x-coordinate for new origin */
    int scroll_new_y;		/*   y-coordinate for new origin */
    int scope_redraw;		/*   redraw scope window */
    int trace_redraw;		/*   redraw a trace in scope window */
  } idle_ev;

  struct {			/* Popup menu state */ 
    GCElement	*g;		/*    selected gate */
    GWire	*w;		/*    selected wire */
    GWireNode	*n;		/*    selected wire node */
    int		x,y;		/*    position of pointer */
    int		wx,wy;		/*    untranslated position of pointer */
  } popstate;

  int cpath_flashState;		/* State for flashing cpath */
  int cpath_len;		/* Length of current critical path */
  char **cpath_pelems;		/* The current critcal path */

  int		width,height;	/* Size of edit window */

  unsigned state;		/* Mouse button state mask */

  EditData	*ed;		/* Basic editor data */
  Circuit	*circuit;	/* Top-level circuit data */
  ErrorList	*errl;		/* Error list manager data */

  int ErrorMarkTimeout;		/* Status flag for drawing the error "X" marker. */
};


typedef struct{
  char	 		*command;
  New_Tcl_CmdProc	*func;
} Tkg_Command;

EditState *new_EditState();
void delete_EditState(EditState*);

void editstate_saveOrig(EditState *es);
void editstate_fullUpdate(EditState *es);
void editstate_regionUpdate(EditState *es,int xmin,int ymin,int xmax,int ymax);
void editstate_setCurrent(EditState *es);
int editstate_setPath(EditState **es,const char *path);
int editstate_checkPath(EditState **es,const char *path);
void editstate_flushModules(EditState **es);
void editstate_Init(EditState *es);
void editstate_update(EditState *es);
void editstate_push(EditState **es,GModuleDef *M,GCElement *g);
void editstate_pop(EditState **es);
void editstate_navigateToModule(EditState **es,GModuleDef *M);
char *editstate_getPath(EditState *es,char *buf);
void editstate_makeRootAtTop(EditState **es);

void unselectAll(EditState*);

EditState *outoferrorblocks(EditState *es,EditState *o);

void configureMainWindow(Tcl_Interp *);
void message(int,const char*,...);

int checkValidName(const char *name,SHash *H);
void pickValidName(char *buf,const char *name,const char *base,SHash *H);

void logError(int code,const char *fname,int lnum,const char *s,...);

int VerilogBasicGateCall(FILE *f,GCElement *g);
int VerilogBasicGateParmList(FILE *f,GCElement *g);
void VerilogBasicGateComment(FILE *f,GCElement *g,int);
int VerilogWriteModules(const char *name,int writeLibBlocks);
int VerilogSave(const char *name);
int VerilogOpen(EditState **es,const char *name);
int VerilogOpenLibrary(EditState **es,const char *name);

int isVerilogFile(const char*);

void selectGate(EditState *es,int tx,int ty);
void unselectGate(EditState *es);

unsigned transition_type(int from,int to);

void sel_clear(EditState*);
void sel_move(EditState*,int,int);
void sel_draw(EditState*);
void sel_dropFixup(EditState*);
void sel_delete(EditState*);
void sel_copy(EditState*);
void sel_kill(EditState*);
void sel_yank(EditState*);
int sel_select(EditState*);
int sel_selectAll(EditState *es);
int sel_isSelGate(GCElement *g);
void sel_appendGate(EditState*,GCElement*);
int sel_num(EditState*);
void sel_updateMenuState();
int sel_finish(EditState *es);
void sel_anchor(EditState *es,int);
void sel_setTech(EditState *es,const char*);
void sel_alignHorz(EditState *es);
void sel_alignVert(EditState *es);
void sel_clearDelta();
void sel_interfaceReset(EditState *es);

void icon_init();
void SetUpCursors();
void MakeHashTables();

int DoTcl(char*,...);
void InitTclProcs(Tcl_Interp *tcl);

void mousedownmovement(EditState *es);
void mouseuptransition(EditState *es);
void mousedowntransition(EditState *es);

void selectobject(EditState *es);
void dropobject(EditState *es);

void mark_draw();
void mark_flush();
void mark_hide();
void mark_redraw();
void mark_post();
void mark_unpost();

void net_editProps(GNet *n,int x,int y);

void wm_MoveTo(int x,int y);
void wm_DrawTo(int x,int y);
void wm_GetDimensions(int *X,int *Y);
void wm_SetCursor(int id);

void SetBatCursor();
void SetModified();
void ClearModified();
void FlagRedraw();
void ClearErrorMark();
void DrawErrorPositionMark();
void ReqScopeRedisplay();
int modifyOK(EditState *es,unsigned flags);

void XGate_clearSelection();
void XGate_setOrigin(int x,int y);

int required_bits(int n);
unsigned htoi(const char *s);
const char *article(const char *m);
void badermessage(int t,const char *m);
void batmessage(int t,const char *m);
int posongate(GWire *w,GCElement *g,int *p,int *n);
int findwirepos(GWire *w,GWire *l);
int GetPadPosition(GCElement *g,const char *name);
void panicSave(int);
FILE *openInPath(const char*);
int badaddr(void *S);
void PickInterval(int *R,int *I);

void Tkg_changeColor(GC gc,int func,int pixel);

int fontheight(Tk_Font F);

void line(int x1,int y1,int x2,int y2);
void box(int x,int y,int w,int h);
void mk_gate(int x,int y,GGateInfo *gi,int rot,int selected);

char *filterParen(char *buf,const char *s);

void setEditMode(EditState *es,int mode);

void DrawPinIOMark(GWire *w,int d,int iod);

int gat_editProps(ClientData d,Tcl_Interp *tcl,int argc,const char *argv[]);
int gat_setCircProp(ClientData d,Tcl_Interp *tcl,int argc,const char *argv[]);

int dce_DrawString(GC gc,int x,int y,int p,const char *s);
int RelPosDrawString(Window W,Tk_Font F,GC gc,int x,int y,const char *S,int p);
int PosDrawString(Window W,Tk_Font F,GC gc,int x,int y,const char *S,int p);
void GKDrawString(Display *D,Window W,GC gc,int x,int y,const char *s,int l);
int GKTextWidth(Tk_Font F,const char *S,int l);
void DrawTextCursor(Window W,int x,int y);

void PSDrawText(FILE *f,int x,int y,int fsize,const char *text,int just);

void cpath_show(int n,const char *netNames[]);
void cpath_initNetDelayTable();
void cpath_flushNetDelayTable();
void cpath_registerNetDelay(const char *,int,int);
void cpath_registerNetAlias(const char *,const char*);
int  cpath_getNetDelay(const char *,int*,int*);
void cpath_showNetDelay(GNet *n);

GSearchContext *new_GSearchContext();
void search_init(GSearchContext*);
void search_clear(GSearchContext*);
void search_find(GSearchContext*,const char *,int);

void scrollbar_update();
void scrollbar_bbx_update();

char *msgLookup(const char*);

void dohyperlink(const char*);

void makeMakeMenu(const char *m);

MajorMode tkgate_currentMode();
void tkgate_setMajorMode(MajorMode mm);

void init_gates();

int verify_circuit();

void setEditCursor(int mode);
void SyncModified();

void TkGate_init(Tcl_Interp*);
void TkGate_initDelay();
void SetErrorPosition(int,int);

void gateCleanUp();

Circuit *new_Circuit(int);
void delete_Circuit(Circuit *);
void Circuit_clearProbes(Circuit*);
void Circuit_extractProbes(Circuit*);
void Circuit_repostProbes(Circuit*);
void Circuit_setTitle(const char*);
void Circuit_setCurrentFile(const char*);
void Circuit_setCurrentFileVersion(const char*);

extern XGateParams XGate;

extern char *BODYFONT; 
extern char *SMALLFONT; 
extern char *BOLDBODYFONT; 
extern char *BOLDSMALLFONT; 
extern char *KANJIFONT; 
extern int KANJIFONT_WIDTH;

extern char *ps_cfont;
extern char *ps_rfont;
extern char *ps_bfont;
extern char *ps_ifont;
extern char *ps_bifont;
extern char *ps_syfont;
extern char *ps_kfont;

extern int INVERTER;
extern int Mark;
extern int SIZEHASH;
extern int REPCOUNTMARK;
extern char *tkg_errorLogFile;
extern char *tkg_siteName;
extern char *tkg_defaultTech;

extern int MAXPORTRANGE;
extern int MAXWIRERANGE;
extern int GATERANGE;
extern int SELMODETHRESH;

extern struct versionDef VERSIONS[];
extern int numVersions;
extern int lastcheckpoint;
extern int blockmovestyle;
extern int changedp;
extern int startrekp;
extern int baderp;
extern int batp;
extern int batc;
extern int floatjoints;
extern int regionUpdate;

extern int idleGateWin_pending;

extern int ycLineNumber;
extern const char *ycFileName;

extern SHash *message_table;

extern char tkgate_homedir[STRMAX];
extern char *tkgate_exampledir;
extern char *tkgate_tutorialdir;
extern MakeMenuData *makeMenuData;

extern int debugContinuousVerify;
extern int debugSimInterface;

extern NHash *GateIdxHash;

#endif
