/*
 * $Id: dxf.trm,v 1.8 1995/12/20 21:47:43 drd Exp $
 *
 */

/* GNUPLOT - dxf.trm */
/*
 * Copyright (C) 1991, 1992
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed
 * as patches to released version.
 *
 * This software  is provided "as is" without express or implied warranty.
 *
 * This file is included by ../term.c.
 *
 * This terminal driver supports:
 *   AutoCad (Release 10.x) dxf file format (import with AutoCad dxfin command)
 *
 *
 * AUTHOR
 *   Florian Hiss  (fhis1231@w204zrz.zrz.tu-berlin.de)
 *
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
*/

/*
 * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
 */

#ifndef GOT_DRIVER_H
#include "driver.h"
#endif

#ifdef TERM_REGISTER
register_term(dxf)
#endif

#ifdef TERM_PROTO
TERM_PUBLIC void DXF_init __P((void));
TERM_PUBLIC void DXF_graphics __P((void));
TERM_PUBLIC void DXF_text __P((void));
TERM_PUBLIC void DXF_linetype __P((int linetype));
TERM_PUBLIC void DXF_move __P((unsigned int x, unsigned int y));
TERM_PUBLIC void DXF_vector __P((unsigned int ux, unsigned int uy));
TERM_PUBLIC void DXF_put_text __P((unsigned int x, unsigned int y, char str[]));
TERM_PUBLIC int DXF_text_angle __P((int angle));
TERM_PUBLIC int DXF_justify_text __P((enum JUSTIFY mode));
TERM_PUBLIC void DXF_reset __P((void));
#define DXF_XMAX (120.0 * DXF_UNIT)
#define DXF_YMAX (80.0 * DXF_UNIT)
#define DXF_HTIC (0.01 * DXF_XMAX)  /* 1.0 percent */
#define DXF_VTIC (0.01 * DXF_YMAX)  /* 1.0 percent */
#define DXF_HCHAR (0.014 * DXF_XMAX) /* 1.4 percent */
#define DXF_VCHAR (0.026 * DXF_YMAX) /* 2.6 percent */
#endif

#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY

#define DXF_UNIT 60.0
#define LINEWIDTH 0.0351  /* default line width is 1 pt */

/* 120 (autocad units) wide by 80 (autocad units) high (default)
   use the GNUPLOT 'set size' command to change the defaults */
#define DXF_TEXTHEIGHT (0.7 * DXF_VCHAR) /* actual text height */
#define DXF_TEXTWIDTH (0.7 * DXF_HCHAR) /* actual text width,
 only a guess, we don't know the width of a character of given height
 of the AutoCad STANDARD text font, so change it if you like */
#define DXF_LINE_TYPES 7 /* number of line types we support. see below  */
#define MAX_LAYER 7  /* number of layers used for the drawing. see below */
#define LT_SCALE 1  /* line type scaling */

static unsigned int DXF_posx;
static unsigned int DXF_posy;
static unsigned int dxf_linetype; /* linetype is mapped to a layer. see below. */
enum JUSTIFY dxf_justify = LEFT;
static float dxf_angle = 0.0; /* either 0 (horizontal) or 90.0 (vertical) */

/* text style used in the entire drawing */
static char *text_style = "STANDARD";
/* text always resides on layer 0 */
#define TEXT_LAYER 0
/* each linetype resides on its own layer. each layer has its own color.
   this avoids difficulties that AutoCad has with proper scaling of
   the linetypes.
   change the colors according to your needs */
static char *layer_name[] = {"0","1","2","3","4","5","6"};
/* the colours are white, red, yellow, green, cyan, blue, magenta.
   change them according to your needs.
   when using a black and white plotting device the colours map to different
   line thicknesses. see description of AutoCad print / plot command */
static char *layer_colour[] = {"7","1","2","3","4","5","6"};
/* support line types AutoCad has to offer by default. */
static char *layer_lines[] = {"CONTINUOUS","DASHED","HIDDEN","CENTER","PHANTOM",
			    "DOT","DASHDOT"};

static TBOOLEAN vector_was_last = FALSE;

TERM_PUBLIC void DXF_init()
{
	DXF_posx = DXF_posy = 0;
	dxf_linetype = 0;
	dxf_angle = 0.0;
	vector_was_last = FALSE;
}

TERM_PUBLIC void DXF_graphics()
{
	register struct termentry *t = term;
	int i;
	static char GPFAR dxfi1[] = "\
999\n\
%% GNUPLOT: dxf file for AutoCad\n\
  0\nSECTION\n  2\nHEADER\n\
  9\n$EXTMIN\n\
 10\n0.000\n 20\n0.000\n\
  9\n$EXTMAX\n\
 10\n%-6.3f\n 20\n%-6.3f\n\
  9\n$LIMMIN\n\
 10\n0.000\n 20\n0.000\n\
  9\n$LIMMAX\n\
 10\n%-6.3f\n 20\n%-6.3f\n\
  9\n$TEXTSTYLE\n  7\n%s\n\
  9\n$TEXTSIZE\n 40\n%-6.3f\n\
  9\n$PLINEWID\n 40\n%-6.4f\n\
  9\n$LTSCALE\n  40\n%-6.3f\n\
  9\n$COORDS\n 70\n  1\n\
  9\n$CELTYPE\n 6\nBYLAYER\n\
  9\n$CLAYER\n  8\n0\n\
  9\n$CECOLOR\n 62\n   %s\n\
  9\n$MENU\n  1\nacad\n\
  0\nENDSEC\n\
  0\nSECTION\n  2\nTABLES\n";
static char GPFAR dxfi2[] = "\
0\nTABLE\n  2\nLTYPE\n 70\n    %d\n\
0\nLTYPE\n  2\nCONTINUOUS\n 70\n    64\n\
  3\nSolid line\n 72\n    65\n 73\n      0\n 40\n0.0\n\
  0\nLTYPE\n  2\nDASHED\n 70\n    64\n\
  3\n__ __ __ __ __ __ __ __ __ __ __ __ __ __ __\n\
 72\n    65\n 73\n     2\n 40\n0.75\n 49\n0.5\n 49\n-0.25\n\
  0\nLTYPE\n  2\nHIDDEN\n 70\n    64\n\
  3\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\
 72\n    65\n 73\n     2\n 40\n0.375\n 49\n0.25\n 49\n-0.125\n\
  0\nLTYPE\n  2\nCENTER\n 70\n    64\n\
  3\n____ _ ____ _ ____ _ ____ _ ____ _ ____ _ ____\n\
 72\n    65\n 73\n     4\n 40\n2.0\n 49\n1.25\n 49\n-0.25\n\
 49\n0.25\n 49\n-0.25\n\
  0\nLTYPE\n  2\nPHANTOM\n 70\n    64\n\
  3\n_____ _ _ _____ _ _ _____ _ _ _____ _ _ ____\n\
 72\n    65\n 73\n     6\n 40\n2.5\n 49\n1.25\n\
 49\n-0.25\n 49\n0.25\n 49\n-0.25\n 49\n0.25\n 49\n-0.25\n\
  0\nLTYPE\n  2\nDOT\n 70\n    64\n\
  3\n...............................................\n\
 72\n    65\n 73\n     2\n 40\n0.25\n 49\n0.0\n 49\n-0.25\n\
  0\nLTYPE\n  2\nDASHDOT\n 70\n    64\n\
  3\n__ . __ . __ . __ . __ . __ . __ . __ . __ . __\n\
 72\n    65\n 73\n     4\n 40\n1.0\n 49\n0.5\n 49\n-0.25\n\
 49\n0.0\n 49\n-0.25\n\
  0\nENDTAB\n";

	fprintf(outfile, dxfi1,
		t->xmax/DXF_UNIT,t->ymax/DXF_UNIT,
		t->xmax/DXF_UNIT,t->ymax/DXF_UNIT,
		text_style,
		DXF_TEXTHEIGHT/DXF_UNIT,
		LINEWIDTH,
		(double)LT_SCALE,
		layer_colour[0]);
	/* the linetype table */
	fprintf(outfile, dxfi2, DXF_LINE_TYPES);
	/* the layer table */
	fprintf(outfile,"  0\nTABLE\n  2\nLAYER\n 70\n   %-d\n",MAX_LAYER);
	for (i = 1; i <= MAX_LAYER; i++)
		fprintf(outfile,"  0\nLAYER\n  2\n%s\n 70\n   64\n62\n   %s\n  6\n%s\n",
			layer_name[i-1],layer_colour[i-1],layer_lines[i-1]);
	fprintf(outfile,"  0\nENDTAB\n0\nENDSEC\n");
	/* no blocks for insertion */
	fprintf(outfile,"  0\nSECTION\n  2\nBLOCKS\n  0\nENDSEC\n");
	/* start the entity section */
	fprintf(outfile,"  0\nSECTION\n");
	fprintf(outfile,"  2\nENTITIES\n");
}

TERM_PUBLIC void DXF_text()
{
	if (vector_was_last) fprintf(outfile,"  0\nSEQEND\n");
	fprintf(outfile,"  0\nENDSEC\n  0\nEOF\n");
}

TERM_PUBLIC void DXF_linetype(linetype)
	int linetype;
{
	linetype = abs(linetype);
	linetype = linetype%DXF_LINE_TYPES;
	dxf_linetype = linetype;
}

TERM_PUBLIC void DXF_move(x, y)
	unsigned int x, y;
{
	DXF_posx = x;
	DXF_posy = y;
	if (vector_was_last) fprintf(outfile,"  0\nSEQEND\n");
	vector_was_last = FALSE;
	fprintf(outfile,"  0\nPOLYLINE\n  8\n%s\n 66\n   1\n",layer_name[dxf_linetype]);
	fprintf(outfile,"  6\n%s\n",layer_lines[dxf_linetype]);
	fprintf(outfile,"  0\nVERTEX\n  8\n%s\n",layer_name[dxf_linetype]);
	fprintf(outfile,"  6\n%s\n",layer_lines[dxf_linetype]);
	fprintf(outfile," 10\n%-6.3f\n 20\n%-6.3f\n 30\n0.000\n",DXF_posx/DXF_UNIT,DXF_posy/DXF_UNIT);
}

TERM_PUBLIC void DXF_vector(ux, uy)
	unsigned int ux, uy;
{
	DXF_posx = ux;
	DXF_posy = uy;
	vector_was_last = TRUE;
	fprintf(outfile,"  0\nVERTEX\n  8\n%s\n",layer_name[dxf_linetype]);
	fprintf(outfile,"  6\n%s\n",layer_lines[dxf_linetype]);
	fprintf(outfile,"  10\n%-6.3f\n  20\n%-6.3f\n  30\n0.000\n",
					DXF_posx/DXF_UNIT,DXF_posy/DXF_UNIT);
}

TERM_PUBLIC void DXF_put_text(x, y, str)
	unsigned int x, y;
	char str[];
{
	int stl;
	float xleftpos, yleftpos, xrightpos,yrightpos;

	/* shut up gcc warnings  - SB */
	xleftpos = yleftpos = xrightpos = yrightpos = 1.0; /* dummy */
	/* ignore empty strings */
	if (str[0] == '\0') return;

	stl = 0; while (str[stl] != '\0') ++stl; /* get string length */

	if (vector_was_last) fprintf(outfile,"  0\nSEQEND\n");
	vector_was_last = FALSE;
	fprintf(outfile,"  0\nTEXT\n  8\n%s\n",layer_name[TEXT_LAYER]);
	if (dxf_angle != 90.0)
	{
	   switch (dxf_justify)
	   {
	   	case LEFT  : xleftpos = (float) x;
			     yleftpos = (float)(y-DXF_VCHAR/4.0);
			     xrightpos = (float)(x+stl*DXF_TEXTWIDTH);
			     yrightpos = yleftpos; break;
	   	case RIGHT : xleftpos = (float)(x-stl*DXF_TEXTWIDTH);
			     yleftpos = (float)(y-DXF_VCHAR/4.0);
			     xrightpos = (float) x;
			     yrightpos = yleftpos; break;
		case CENTRE: xleftpos = (float)(x-stl*DXF_TEXTWIDTH/2.0);
			     yleftpos = (float)(y-DXF_VCHAR/4.0);
			     xrightpos = (float) x;  /* center point */
			     yrightpos = yleftpos;
			     break;
	    }
	}
	else
	{
	    switch (dxf_justify)
	    {
	   	case LEFT  : xleftpos = (float)(x+DXF_VCHAR/4.0);
			     yleftpos = (float) y;
			     xrightpos = xleftpos;
			     yrightpos = (float)(y+stl*DXF_TEXTWIDTH); break;
	   	case RIGHT : xleftpos = (float)(x+DXF_VCHAR/4.0);
			     yleftpos = (float)(y-stl*DXF_HCHAR);
			     xrightpos = xleftpos;
			     yrightpos = (float) y; break;
		case CENTRE: xleftpos = (float)(x+DXF_VCHAR/4.0);
			     yleftpos = (float)(y-stl*DXF_TEXTWIDTH/2.0);
			     xrightpos = xleftpos;
			     yrightpos = (float) y;  /* center point */
			     break;
	    }
	}
	fprintf(outfile," 10\n%-6.3f\n 20\n%-6.3f\n 30\n0.000\n",
				xleftpos/DXF_UNIT,yleftpos/DXF_UNIT);
	fprintf(outfile," 40\n%-6.3f\n  1\n%s\n 50\n%-6.3f\n",
			DXF_TEXTHEIGHT/DXF_UNIT,str,dxf_angle);
	fprintf(outfile,"  7\n%s\n",text_style);
	if (dxf_justify != LEFT)
	{
		fprintf(outfile," 72\n%d\n",dxf_justify);
		fprintf(outfile," 11\n%-6.3f\n 21\n%-6.3f\n 31\n0.000\n",
				xrightpos/DXF_UNIT,yrightpos/DXF_UNIT);
	}
}

TERM_PUBLIC int DXF_text_angle(angle)
	int angle;
{
	dxf_angle = 0.0;
	if (angle == 1) dxf_angle = 90.0;
	return(TRUE);
}

TERM_PUBLIC int DXF_justify_text(mode)
	enum JUSTIFY mode;
{
	dxf_justify = mode;
	return(TRUE);
}

TERM_PUBLIC void DXF_reset()
{
	DXF_posx = DXF_posy = 0;
}

#endif /* TERM_BODY */

#ifdef TERM_TABLE
TERM_TABLE_START(dxf_driver)
   "dxf", "dxf-file for AutoCad (default size 120x80)",
       DXF_XMAX,DXF_YMAX,DXF_VCHAR, DXF_HCHAR,
       DXF_VTIC, DXF_HTIC, options_null,DXF_init, DXF_reset,
       DXF_text, null_scale, DXF_graphics, DXF_move, DXF_vector,
       DXF_linetype, DXF_put_text, DXF_text_angle,
       DXF_justify_text, do_point, do_arrow, set_font_null
TERM_TABLE_END(dxf_driver)

#undef LAST_TERM
#define LAST_TERM dxf_driver

#endif /* TERM_TABLE */
#endif /* TERM_PROTO_ONLY */

/*
 * NAME: dxf
 *
 * OPTIONS: none
 *
 * SUPPORTS: dxf-file for AutoCad (Release 10.x)
 *
 * Further Info: Import into AutoCad with the dxfin commad.
 *		 The default size is 120x80 (AutoCad units) but can 
 *	 	 be changed via set size.
 *		 This terminal uses seven colours (white, red, yellow, 
 *		 green, cyan, blue, magenta). To change them you'll 
 *		 have to change the source-file.
 *		 When using a black and white plotting device the
 *		 colours map to different line thicknesses. see
 *		 description of AutoCad print / plot command.
 *
 */