/* @(#)ag_gtxt.c	19.1 (ES0-DMD) 02/25/03 13:52:59 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/* @(#)ag_gtxt.c	19.1  (OAA-ASTRONET) 02/25/03 13:52:59   */
/*
 * HEADER : ag_gtxt.c      - Vers 3.6.001  - Sep 1993 -  L. Fini, OAA
 *                         - Vers 3.6.000  - Oct 1991 -  L. Fini, OAA
 *
 *
 *                           C INTERFACE MODULE
 */


#include <aglenvr.h>
#include <aglstat.h>





/*****************************************************************************/
/*++                      AG_GTXT (Internal AGL Use)                         */

/* AG_GTXT    Draw text                                                      */


/* Text drawing routine. String dimension and orientation can be set via     */
/* AG_SSET. Relative string position with respect to the given point can be  */
/* specified by the center index argument as shown in the following figure   */
/* where a box supposed to enclose the string is sketched.                   */

/*       22     21                   20                  19      18          */
/*         +-----+-------------------+--------------------+-----+            */
/*         |     |                   |                    |     |            */
/*         |     |                   |                    |     |            */
/*         |     |                   |                    |     |            */
/*         |    7|                  6|                    |5    |            */
/*       23+-----+ ***   ****    ****+ ****   *****  *****+-----+17          */
/*         |     |*   *  *   *  *      *   *  *      *    |     |            */
/*         |     |*   *  *   *  *      *   *  *      *    |     |            */
/*         |     |*****  ****   *      *   *  ***    ***  |     |            */
/*         |     |*   *  *   *  *      *   *  *      *    |     |            */
/*         |     |*   *  *   *  *      *   *  *      *    |     |            */
/*         |     |*   *  ****    ***   ****   *****  *    |     |            */
/*         |    8|                   |                    |4    |            */
/*       24+-----+-                 -+0                  -+-----+16          */
/*         |     |                   |                    |     |            */
/*         |     | ****  *   *   ***     ***  *   *  *    |     |            */
/*         |     |*      *   *    *       *   *  *   *    |     |            */
/*         |     |*      *   *    *       *   * *    *    |     |            */
/*         |     |*  **  *****    *       *   **     *    |     |            */
/*         |     |*   *  *   *    *       *   * *    *    |     |            */
/*         |     |*   *  *   *    *       *   *  *   *    |     |            */
/*        9+-----+ ****  *   *   *** + ***    *   *  *****+-----+15          */
/*         |    1|                  2|                    |3    |            */
/*         |     |                   |                    |     |            */
/*         |     |                   |                    |     |            */
/*         |     |                   |                    |     |            */
/*         |     |                   |                    |     |            */
/*         +-----+-------------------+--------------------+-----+            */
/*        10    11                  12                   13     14           */
/*                                                                           */


/* Note: The vertical offset of displacement codes 10,11,12,13,14 and 18,19, */
/*       20,21,22 is the character height. The horizontal offset of codes:   */
/*       14,15,16,17,18 and 22,23,24,9,10, is equal to the character width.  */

/*       The positioning and newline is made with respect to the current     */
/*       character size and could be different than exepected if character   */
/*       size is modified by the related metacharacter sequences (see below).*/

/* The coordinate values are referred to the current graphic mode (either    */
/* NORMALIZED, USER or SPECIAL) and mapped accordingly.  Graphic mode is     */
/* affected by: AG_WDEF, AG_TRNS, and AG_SSET items "NORMAL","USER" and      */
/* "SPECIAL"                                                                 */

/* The text drawing routine provides for interpretation of the following     */
/* metacharacter:                                                            */

/*     \{    - Begin grouping                                                */
/*     \}    - End grouping                                                  */
/*     \^    - move the following part of the string up by half a character  */
/*     \_    - move the following part of the string down by half a character*/
/*     \<    - Backspace by a single character                               */
/*     \+    - Increase character size by 20%          (1)                   */
/*     \-    - Decrease character size by 20%          (1)                   */
/*     \!    - Force interpretation of the following part as a metasequence  */
/*             (this is needed to allow metasequences starting with 'n' not  */
/*             to be interpreted as newlines)                                */
/*     \0    - select font 0 (Default font)            (1,2)                 */
/*     \1    - select font 1 (Quality roman font)      (1,2)                 */
/*     \2    - select font 2 (Greek font)              (1,2)                 */
/*     \3    - select font 3 (Script font)             (1,2)                 */
/*     \4    - select font 4 (Old English)             (1,2)                 */
/*     \5    - select font 5 (Tiny roman font)         (1,2)                 */
/*     \[    - Increase line width (bolding)           (4)                   */
/*     \]    - Decrease line width (bolding)           (4)                   */
/*     \#<n> - Draw marker number <n> into the line    (3)                   */
/*     \n    - Perform a "newline"                                           */
/*     ~~    - Draw a single '~' character                                   */
/*     \~    - Draw a single '~' character                                   */
/*     ~\    - Draw a single '\' character                                   */
/*     \\    - Draw a single '\' character                                   */

/*  The above "single character" instructions MUST NOT BE FOLLOWED BY BLANK  */

/* The character '~' can also be used instead of '\' as metacharacter flag   */
/* The '~' is more suited to C programs where '\' has a special meaning.     */

/* All selections made by metacharacters are valid from the point in the     */
/* string where they are defined up either to the end of current group (the  */
/* part of the string enclosed in \{..\}) or to the end of the string        */


/* Note 1: The same action of this metacharacter commands can be selected    */
/*         permanently via the suitable AG_SSET command                      */

/* Note 2: Correspondance of font characters (and ASCII codes) can be obtai- */
/*         ned by running the test program "fonts"                           */

/* Note 3: This function allows to include a marker symbol within a text     */
/*         string. See routine AG_GPLM for the defined marker symbols.       */
/*         The syntax for includeing markers is sligtly different from the   */
/*         one used in AGL vers. 3.5x !!                                     */

/* Note 4: This functions are optionally supported by device drivers.        */

/*  AGL also interprets a set of 'TEX like' keywords as listed below.        */
/*  Unfortunately, due to the fact that most of them require special         */
/*  characters to be shown, only the names are listed, while the exact       */
/*  meaning can only be seen by means of the "fonts" program, which is       */
/*  created as part of the standard AGL installation procedure.              */

/* If the metacharacter sequence is more than one character long (escape     */
/* not included, of course), it MUST BE FOLLOWED BY A BLANK SPACE.           */


/*       \AA            \Alpha         \Aquarius      \Aries                 */
/*       \Beta          \Cancer        \Capricorn     \Chi                   */
/*       \Delta         \Earth         \Epsilon       \Eta                   */
/*       \Gamma         \Gemini        \Iota          \Jupiter               */
/*       \Kappa         \Lambda        \Leo           \Libra                 */
/*       \Mars          \Mercury       \Moon          \Mu                    */
/*       \Neptune       \Nu            \Omega         \Omicron               */
/*       \PI            \Phi           \Pisces        \Pluto                 */
/*       \Psi           \Rho           \Sagittarius   \Saturn                */
/*       \Scorpio       \Sigma         \Sqrt          \Tau                   */
/*       \Taurus        \Theta         \Upsilon       \Uranus                */
/*       \Venus         \Virgo         \Xi            \Zeta                  */
/*       \aleph         \alpha         \asteroid      \beta                  */
/*       \bigcirc       \black         \blue          \cent                  */
/*       \chi           \circ          \cyan          \clover                */
/*       \clubsuit      \comet         \dag           \ddag                  */
/*       \default       \delta         \diamond       \div                   */
/*       \downarro      \epsilon       \equinox       \equiv                 */
/*       \eta           \firtree       \gamma         \ge                    */
/*       \greek         \green         \hbar          \heart                 */
/*       \infty         \int           \iota          \italic                */
/*       \kappa         \lambda        \larrow        \le                    */
/*       \magenta       \mp            \mu            \!nabla                */
/*       \!ne           \!nu           \odot          \oint                  */
/*       \old           \omega         \omicron       \oplus                 */
/*       \otimes        \palmtree      \paragraph     \parallel              */
/*       \partial       \perp          \phi           \pi                    */
/*       \pm            \propto        \psi           \red                   */
/*       \rho           \rightarrow    \roman         \script                */
/*       \shield        \sigma         \snow          \spade                 */
/*       \sqrt          \sum           \tau           \theta                 */
/*       \times         \tiny          \uparrow       \upsilon               */
/*       \varepsilon    \varphi        \vartheta      \white                 */
/*       \xi            \yellow        \zeta                                 */

/*  When specifying metasequences the minimum number of characters required  */
/*  for matching may be used.                                                */

/*  The "!" character in front of sequences starting with "n" is required to */
/*  avoid the interpretation as newline single character sequence.           */


void AG_GTXT (xc,yc,text,centre)

 double xc,yc;                /* String position                             */
 char *text;                  /* String to draw (max 132 chars)              */
 int  centre;                 /* Centre index (see above)                    */
                                                                         /*--*/
{
static char *modnam = "GTXT";
double xstart=xc, ystart=yc;
char *chstrg = text;
int font;
int the_color,was_color;
float hoffset,voffset;
int curlwdt;
struct AGL_char my_char;
double twd,thg,cwd,chg;
double rescalx, rescaly;
DEFINE_AGLDVCOM;

AG_DMSG(modnam,(char *)0);

font = DY(curfont);

if((centre<0) ||(centre>24)) {
	AGL_puterr(ILLPOSWNG,modnam);
	centre=1;
}

#ifndef NO_METAFILE_SUPPORT
if ( DY(filact) == SOFTMETAFILE ) {
	int nc=strlen(chstrg);
	int is;
	float xxx[2];
	enum METACODE cod = MFGTXT;

	xxx[0]=xc; xxx[1]=yc;

	is = fwrite((void *)&cod,sizeof(int),1,DY(metafile));
	is = fwrite((void *)xxx,sizeof(float),2,DY(metafile));
	is = fwrite((void *)&centre,sizeof(int),1,DY(metafile));
	is = fwrite((void *)&nc,sizeof(int),1,DY(metafile));
	is = fwrite((void *)chstrg,sizeof(char),nc,DY(metafile));
	if(is != nc) 
		AGL_puterr(MFWRITERR,modnam); 
}
#endif

if(AGL_status.curvwp == VWPEMPTY) { 
	AGL_puterr(NOVWPERR,modnam); 
	return; 
}

if(DY(modeflag)!=NORMAL)
	AGL_cnvt(&xstart,&ystart);	/* Convert reference coordinates    */

AGL_strd(chstrg,font,&twd,&thg);	/* Compute text   dimensions        */
AGL_strd("X",font,&cwd,&chg);		/* Compute character dimensions     */

switch(centre) {			/* compute horizontal offset        */
					/* value is in "pixels"             */
	case 9: case 10: case 22: case 23: case 24: 
		hoffset = cwd;
		break;
	case 0: case 2: case 6: case 12: case 20:
		hoffset = -(twd*0.5);
		break;
	case 3: case 4: case 5: case 13: case 19:
		hoffset = -twd;
		break;
	case 14: case 15: case 16: case 17: case 18:
		hoffset = -(twd + cwd);
		break;
	case 1: case 7: case 8: case 11: case 21:
	default:
		hoffset = 0.0;
		break;
}

switch(centre) {				/* compute vertical   offset */
						/* value is in "pixels"      */
	case 10: case 11: case 12: case 13: case 14:
		voffset = thg;
		break;
	case 0: case 4: case 8: case 16: case 24:
		voffset = thg*0.5 - chg;
		break;
	case 5: case 6: case 7: case 17: case 23:
		voffset = -chg;
		break;
	case 18: case 19: case 20: case 21: case 22:
		voffset = -(chg*2.0);
		break;
	case 1: case 2: case 3: case 9: case 15:
		voffset = thg-chg;
		break;
}

rescalx = rescaly = DY(scale) * CHARMULT(AGL_status.devid);

rescalx *= DY(chrhsize) * RSLX(AGL_status.devid);
rescaly *= DY(chrvsize) * RSLY(AGL_status.devid);

hoffset *= rescalx;				/* Scale and normalize      */
voffset *= rescaly;

AG_TSET(0.0,0.0,DY(changle),3);			/* Rotate character offset  */
AG_TROT(&hoffset,&voffset,1);

xstart += hoffset;				/* Drawing starts here      */
ystart += voffset;

AGL_status.errstat = AGLNOERR;

my_char.modifier.mfact = 1.0;
my_char.modifier.font = font;
my_char.modifier.lwdt = DY(textlw);
my_char.modifier.vshift=0.0;
my_char.modifier.backspace=0;
my_char.modifier.newline=0;
my_char.modifier.slant=0.0;
the_color=DY(color);
was_color=the_color;
my_char.modifier.color=the_color;

curlwdt = DY(lwidth);

hoffset=0.0;					/* Reuse hoffset and voffset */
voffset=0.0;

while ((chstrg=AGL_mchar(chstrg,&my_char))!=NULL) {
	int i;
	double xpos,ypos;
	double factx= rescalx * my_char.modifier.mfact;
	double facty= rescaly * my_char.modifier.mfact;
	float advance,haux,vaux;

	if(my_char.modifier.color!=the_color) {		/* change color      */
		the_color=my_char.modifier.color;
		DY(color)=the_color;
		AGL_sclr();
	}

	if(my_char.modifier.lwdt != curlwdt) { 		/* change line width */
		AGL_swdt(my_char.modifier.lwdt); 	/* if required       */
		curlwdt=my_char.modifier.lwdt; 
	}
	advance= factx*my_char.descriptor.width;

	if(my_char.modifier.newline>0) {
		hoffset = 0.0;
		voffset -= my_char.descriptor.heigth*facty*2.0;
		my_char.modifier.vshift = 0;
	}
	if(my_char.modifier.backspace>0)
		hoffset -= my_char.modifier.backspace*advance;

	haux=hoffset;
	vaux=voffset + my_char.modifier.vshift * my_char.descriptor.heigth * facty;

	AG_TSET(0.0,0.0,0.0,1);
	AG_TROT(&haux,&vaux,1);

	RBUFFR(0)=xstart+haux;		/* Allow even rounding of coord.   */
	RBUFFR(1)=ystart+vaux;
	IBUFFR(0)=6;
	CHANNEL = DY(curchan);
	INITFUNCT(AGLDVCOM);
	xpos=RBUFFR(0);			/* xpos,ypos are the coordinates   */
	ypos=RBUFFR(1);			/* of the "closest" pixel          */

	AG_TSET(xpos,ypos,0.0,1);

	AGL_ch2pl(&my_char,1);
	for(i=0;i<my_char.descriptor.nstrokes;i++) {
		AG_MAGN(factx,facty,
		        my_char.descriptor.strokes[i].XV,
		        my_char.descriptor.strokes[i].YV,
		        my_char.descriptor.strokes[i].nvects);
		AG_TROT(my_char.descriptor.strokes[i].XV,
		        my_char.descriptor.strokes[i].YV,
		        my_char.descriptor.strokes[i].nvects);
		AGL_gpll(&my_char.descriptor.strokes[i]);
	}

	if(AGL_status.errstat != AGLNOERR) 
		AGL_siger(modnam);

	hoffset += advance;
}
AGL_swdt(DY(lwidth));			/* Reset line width for graphics    */

if(the_color != was_color) {		/* reset color if changed         */
	DY(color)=was_color;
	AGL_sclr();
}
}

