/*
 *    functions for the graphic output of the pixmap
 */

#include <string.h>

#include "ct1.h"
#ifdef GTK2
PangoFontDescription *font[7], *smallfont[7], *symbfont[7], 
                     *ssymbfont[7], *slfont[7], 
                     *boldfont[7], *textfont[7];
#else
GdkFont *font[7], *smallfont[7], *symbfont[7], 
                  *ssymbfont[7], *slfont[7], 
                  *boldfont[7], *textfont[7];
#endif

#ifndef MIN
#define MIN(a, b)        ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b)        ((a) > (b) ? (a) : (b))
#endif

void
CreatePix ()
/* initializes fonts, linestyles and factors */
{
  float ztab[] = { 0.4, 0.6, 0.8, 1, 1.2 };
  int ltab[] = { 0, 0, 2, 2, 2 };
/*  int ftab[] = { 2, 3, 4, 5, 6 };*/

  size_factor = ztab[zoom_factor];
  if (bondlen_mm != 0 && bondlen_mm != 10.668) size_factor *= bondlen_mm/10.668;
  head.pix_width = 1600;
  head.pix_height = 1600;
  Set_Line (ltab[zoom_factor]);


}

void
FreePix ()
/* erases the drawing area */
{
  GdkRectangle update_rect;
  int i;

  gdk_draw_rectangle (picture,
		      background_gc,
		      TRUE, 0, 0,
		      (gint)drawing_area->allocation.width,
		      (gint)drawing_area->allocation.height);
  if (gridtype==1) {
  	for (i=0+gridx;i<=(int)drawing_area->allocation.width;i=i+50)
  	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (i * size_factor), (gint) (0),
		   (gint) (i * size_factor), (gint) (drawing_area->allocation.height));
	for (i=0+gridy;i<=(int)drawing_area->allocation.height;i=i+50)
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0), (gint) (i*size_factor),
		   (gint) (drawing_area->allocation.width), (gint) (i * size_factor));
		}
   if (gridtype==2){

	for (i=-2560+gridx;i<=5280;i=i+64){
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0+gridx), (gint) ((gridy+i)*size_factor),
		   (gint) (5500+gridx)*size_factor, 
		   (gint) (3200+gridy+i) * size_factor);
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0+gridx), (gint) ((i+gridy)*size_factor),
		   (gint) (5500+gridx)*size_factor, 
		   (gint) (-3200+gridy+i) * size_factor);
			}
		}

  update_rect.x = 0;
  update_rect.y = 0;
  update_rect.width = drawing_area->allocation.width;
  update_rect.height = drawing_area->allocation.height;
  gtk_widget_draw ((GtkWidget *) drawing_area, &update_rect);

}



void
CopyPlane ()
/* updates the display with the contents of the background pixmap */
{
  GdkRectangle update_rect;
  gdk_draw_pixmap (drawing_area->window,
		   drawing_area->style->
		   fg_gc[GTK_WIDGET_STATE (drawing_area)], picture, 0, 0, 0,
		   0, head.pix_width, head.pix_height);
  update_rect.x = 0;
  update_rect.y = 0;
  update_rect.width = (guint16)head.pix_width;
  update_rect.height = (guint16)head.pix_height;
}

void
Display_Mol ()
/* calls the individual bond and text drawing functions to display the
   picture */
{
  struct data *hpc;
  struct dc *hpc_c;
  struct spline *hpc_sp;
  int d,i;
  char *c;
  struct xy_co *coord;
  int tmpx1,tmpx2,tmpy1,tmpy2,tmptx1,tmptx2,tmpty1,tmpty2;
  GdkRectangle update_rect;

  if (head.pix_width == 0 || head.pix_height == 0)
    return;
  gdk_draw_rectangle (picture,
		      background_gc,
		      TRUE, 0, 0, head.pix_width, head.pix_height);

  if (gridtype==1) {
  	for (i=0+gridx;i<=head.pix_width;i=i+64)
  	    gdk_draw_line (picture,drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
	   (gint) (i * size_factor), (gint) (0),
		   (gint) (i * size_factor), (gint) (head.pix_height));
	for (i=0+gridy;i<=head.pix_height;i=i+64)
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0), (gint) (i*size_factor),
		   (gint) (head.pix_width), (gint) (i * size_factor));
   }

   if (gridtype==2){

	for (i=-2560+gridx;i<=6400;i=i+64){
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0+gridx), (gint) ((gridy+i)*size_factor),
		   (gint) (5500+gridx)*size_factor, 
		   (gint) (3200+gridy+i) * size_factor);
	    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_INSENSITIVE],
		   (gint) (0+gridx), (gint) ((i+gridy)*size_factor),
		   (gint) (5500+gridx)*size_factor, 
		   (gint) (-3200+gridy+i) * size_factor);
			}
		}
		
  hpc = da_root.next;
  if (!hpc)
    fprintf (stderr,
	     "Help - somebody ate my atoms (hp->n=%d, da_root.next NULL)!!!\n",
	     hp->n);
  for (d = 0; d < hp->n; d++)
    {
    int x=hpc->x;
    int y=hpc->y;
    int tx=hpc->tx;
    int ty=hpc->ty;
#if 1
	if ( !use_whiteout) {
		i=has_label(hpc->x,hpc->y);
		if (i>=0) {
		int ox=x;
				x += (4.*size_factor*(i+1)/calc_vector(abs(tx-x),abs(ty-y))) *(tx-x);
				y += (4.*size_factor*(i+1)/calc_vector(abs(tx-ox),abs(ty-y))) *(ty-y);
				}
		i=has_label(hpc->tx,hpc->ty);
		if (i>=0) {
		int otx=tx;
				tx -= (4.*size_factor*(i+1)/calc_vector(abs(tx-x),abs(ty-y))) *(tx-x);
				ty -= (4.*size_factor*(i+1)/calc_vector(abs(otx-x),abs(ty-y))) *(ty-y);
				}
		}		
#endif
      switch (hpc->bond)
	{
	case 0:
	  Drawline (x, y, tx, ty, hpc->smarked + hpc->tmarked,hpc->color);	/*single */
	  break;
	case 1:
	  {			/*leftdouble */
	    coord = multi_bonds (x, y, tx, ty, mb_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (hpc->x, hpc->y, hpc->tx, hpc->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 2:
	  {			/*rightdouble */
	    coord = multi_bonds (tx, ty, x, y, mb_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 5:
	  DrawWedge (x, y, tx, ty,
		     hpc->smarked + hpc->tmarked, hpc->color);
	  break;
	case 6:
	  DrawDashedWedge (x, y, tx, ty,
			   hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 7:
	  DrawWiggly (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 8:
	  DrawArrow (x, y, tx, ty, 1,
		     hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 9:
	  DrawArrow (x, y, tx, ty, 2,
		     hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 10:
	  DrawWide (x, y, tx, ty,
		    hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 11:
	  DrawCircle (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 12:
	  DrawDotted (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 13:
	  DrawAcross (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 4:
	  {			/*middouble */
	    coord = center_double_bond (x, y, tx, ty, db_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord++;
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 3:
	  {			/*triple */
	    coord = multi_bonds (x, y, tx, ty, mb_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord = multi_bonds (hpc->tx, hpc->ty, hpc->x, hpc->y, mb_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 14:
	  {			/*left partial double */
	    coord = multi_bonds (x, y, tx, ty, mb_dist);
	    DrawDashed (coord->x, coord->y, coord->tx, coord->ty,
			hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 15:
	  {			/*right partial double */
	    coord = multi_bonds (tx, ty, x, y, mb_dist);
	    DrawDashed (coord->x, coord->y, coord->tx, coord->ty,
			hpc->smarked + hpc->tmarked,hpc->color);
	    Drawline (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	case 16:		/*zebra dashed single bond */
	  DrawStripe (x, y, tx, ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  break;
	case 18:
	  {			/*triple, equal lengths */
	    coord = center_double_bond (x, y, tx, ty, 2*db_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord++;
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  Drawline (x, y, tx, ty, hpc->smarked + hpc->tmarked,hpc->color);	/*single */
	  }
	  break;
	case 19:
	  {			/*quadruple */
	    coord = center_double_bond (x, y, tx, ty, db_dist+3);
	    tmpx1=coord->x;
	    tmpy1=coord->y;
            tmptx1=coord->tx;
            tmpty1=coord->ty;
            coord++;	    
	    tmpx2=coord->x;
	    tmpy2=coord->y;
            tmptx2=coord->tx;
            tmpty2=coord->ty;
	    coord = center_double_bond (tmpx1, tmpy1, tmptx1, tmpty1, db_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord++;
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord = center_double_bond (tmpx2, tmpy2,tmptx2, tmpty2, db_dist);
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	    coord++;
	    Drawline (coord->x, coord->y, coord->tx, coord->ty,
		      hpc->smarked + hpc->tmarked,hpc->color);
	  }
	  break;
	}
      hpc = hpc->next;
      if (!hpc)
	{
	  fprintf (stderr,
		   "Help - somebody ate my atoms (d=%d,hp->n=%d)!!!\n", d,
		   hp->n);
	  hp->n = d;
	  continue;
	}
    }

  hpc_c = dac_root.next;
  for (d = 0; d < hp->nc; d++)
    {
      c = hpc_c->c;
      Drawstring (hpc_c->x, hpc_c->y, c, hpc_c->direct, hpc_c->marked, hpc_c->color,hpc_c->font,hpc_c->size,0);
      hpc_c = hpc_c->next;
    }

  hpc_sp = sp_root.next;
  for (d = 0; d < hp->nsp; d++)
    {
      Drawspline (hpc_sp->x0, hpc_sp->y0, hpc_sp->x1, hpc_sp->y1,
		  hpc_sp->x2, hpc_sp->y2, hpc_sp->x3, hpc_sp->y3,
		  hpc_sp->type, hpc_sp->marked,hpc_sp->color);
      hpc_sp = hpc_sp->next;
    }

  if (drawmode == 4 && addflag==1 && !xbmflag)
    {
      gdk_draw_rectangle (picture, mygc[2], TRUE, refx * size_factor - 1,
			  refy * size_factor - 1, 3, 3);
    }
  gdk_draw_pixmap (drawing_area->window,
		   drawing_area->style->
		   fg_gc[GTK_WIDGET_STATE (drawing_area)], picture, 0, 0, 0,
		   0, head.pix_width, head.pix_height);
  update_rect.x = 0;
  update_rect.y = 0;
  update_rect.width = (guint16)head.pix_width;
  update_rect.height = (guint16)head.pix_height;
  gtk_widget_draw ((GtkWidget *) drawing_area, &update_rect);
}

void
draw_preview_bonds (x, y, tx, ty, b)
/* calls the individual bond functions to create the preview image */
     int x, y, tx, ty, b;
{
  struct xy_co *coord;

  switch (b)
    {
    case 0:
      Drawline (x, y, tx, ty, 0, 0);	/*single */
      break;
    case 1:
      {				/*leftdouble */
	coord = multi_bonds (x, y, tx, ty, mb_dist);
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0,0);
	Drawline (x, y, tx, ty, 0, 0);
      }
      break;
    case 2:
      {				/*rightdouble */
	coord = multi_bonds (tx, ty, x, y, mb_dist);
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0,0);
	Drawline (x, y, tx, ty, 0,0);
      }
      break;
    case 5:
      DrawWedge (x, y, tx, ty, 0, 0);
      break;
    case 6:
      DrawDashedWedge (x, y, tx, ty, 0, 0);
      break;
    case 7:
      DrawWiggly (x, y, tx, ty, 0, 0);
      break;
    case 8:
      DrawArrow (x, y, tx, ty, 1, 0, 0);
      break;
    case 9:
      DrawArrow (x, y, tx, ty, 2, 0, 0);
      break;
    case 10:
      DrawWide (x, y, tx, ty, 0, 0);
      break;
    case 11:
      DrawCircle (x, y, tx, ty, 0, 0);
      break;
    case 12:
      DrawDotted (x, y, tx, ty, 0, 0);
      break;
    case 13:
      DrawAcross (x, y, tx, ty, 0, 0);
      break;
    case 4:
      {				/*middouble */
	coord = center_double_bond (x, y, tx, ty, db_dist);
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
	coord++;
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
      }
      break;
    case 3:
      {				/*triple */
	coord = multi_bonds (x, y, tx, ty, mb_dist);
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
	Drawline (x, y, tx, ty, 0, 0);
	coord = multi_bonds (tx, ty, x, y, mb_dist);
	Drawline (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
	Drawline (x, y, tx, ty, 0, 0);
      }
      break;
    case 14:
      {				/*left partial double */
	coord = multi_bonds (x, y, tx, ty, mb_dist);
	DrawDashed (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
	Drawline (x, y, tx, ty, 0, 0);
      }
      break;
    case 15:
      {				/*right partial double */
	coord = multi_bonds (tx, ty, x, y, mb_dist);
	DrawDashed (coord->x, coord->y, coord->tx, coord->ty, 0, 0);
	Drawline (x, y, tx, ty, 0, 0);
      }
      break;
    case 16:			/*zebra dashed single bond */
      DrawStripe (x, y, tx, ty, 0, 0);
      break;
    }
}

void
Drawline (int x, int y, int tx, int ty, int active, int color)
/* draws a single bond */
{
  if ( xbmflag)
    gdk_draw_line (picture, drawing_area->style->black_gc,
		   (gint) (x * size_factor), (gint) (y * size_factor),
		   (gint) (tx * size_factor), (gint) (ty * size_factor));
  else if (active)
    gdk_draw_line (picture, drawing_area->style->bg_gc[GTK_STATE_SELECTED],
		   (gint) (x * size_factor), (gint) (y * size_factor),
		   (gint) (tx * size_factor), (gint) (ty * size_factor));
  else
    gdk_draw_line (picture, mygc[color],
		   (gint) (x * size_factor), (gint) (y * size_factor),
		   (gint) (tx * size_factor), (gint) (ty * size_factor));
}

void
DrawAcross (int x, int y, int tx, int ty, int active,int color)
/* draws a single bond on a white background */
{
  gint npoints = 4;
  GdkPoint mypoints[4];
  struct xy_co *coord;
  GdkGC *thegc;


  thegc = background_gc;

  coord = center_double_bond (x, y, tx, ty, 6);
  mypoints[0].x = (coord->x + (coord->tx - coord->x) / 4) * size_factor;
  mypoints[0].y = (coord->y + (coord->ty - coord->y) / 4) * size_factor;
  mypoints[1].x = (coord->tx - (coord->tx - coord->x) / 4) * size_factor;
  mypoints[1].y = (coord->ty - (coord->ty - coord->y) / 4) * size_factor;
  coord++;
  mypoints[2].x = (coord->tx - (coord->tx - coord->x) / 4) * size_factor;
  mypoints[2].y = (coord->ty - (coord->ty - coord->y) / 4) * size_factor;
  mypoints[3].x = (coord->x + (coord->tx - coord->x) / 4) * size_factor;
  mypoints[3].y = (coord->y + (coord->ty - coord->y) / 4) * size_factor;
  gdk_draw_polygon (picture, thegc, TRUE, (GdkPoint *) mypoints,
		    (gint) npoints);

  if (xbmflag)
  thegc=drawing_area->style->black_gc;
  else if (active)
  thegc=drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else 
  thegc=mygc[color];
    gdk_draw_line (picture, thegc,
		   (gint) (x * size_factor), (gint) (y * size_factor),
		   (gint) (tx * size_factor), (gint) (ty * size_factor));
}

void
DrawDashed (int x, int y, int tx, int ty, int active,int color)
/* draws a dashed bond */
{
  GdkGC *thegc;
  GdkSegment mypoints[6];
  int xlen, ylen, i;
  gint nsegments = 6;

  xlen = tx - x;
  ylen = ty - y;

  for (i = 0; i < nsegments; i++)
    {
      mypoints[i].x1 = (gint16) ((x + 2 * i * 0.09 * xlen) * size_factor);
      mypoints[i].y1 = (gint16) ((y + 2 * i * 0.09 * ylen) * size_factor);
      mypoints[i].x2 = (gint16) ((x + (2 * i + 1) * 0.09 * xlen) * size_factor);
      mypoints[i].y2 = (gint16) ((y + (2 * i + 1) * 0.09 * ylen) * size_factor);
    }
  if (xbmflag)
  thegc= drawing_area->style->black_gc;
  else if (active)
  thegc=drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
  thegc=mygc[color];
  
    gdk_draw_segments (picture,
		       thegc,
		       (GdkSegment *) mypoints, (gint) nsegments);
}

void
DrawDotted (int x, int y, int tx, int ty, int active, int color)
/* draws a dotted bond */
{
  GdkGC *thegc;
  GdkPoint mypoints[100];
  int xlen, ylen, i;
  gint npoints ;
  int len;
  float step;

  xlen = tx - x;
  ylen = ty - y;

len=(int) rint(calc_vector(abs(xlen),abs(ylen))/6.3);
 step = 1./len;
npoints=len;
if (npoints>99)npoints=99;

  for (i = 0; i < npoints; i++)
    {
      mypoints[i].x = (gint16) ((x + i * step * xlen) * size_factor);
      mypoints[i].y = (gint16) ((y + i * step * ylen) * size_factor);
    }
  if (xbmflag)
  thegc= drawing_area->style->black_gc;
  else if (active)
  thegc=drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
  thegc=mygc[color];

    gdk_draw_points (picture, thegc,
		     (GdkPoint *) mypoints, (gint) npoints);
}

void
DrawWide (int x, int y, int tx, int ty, int active,int color)
/* draws a wide single bond */
{
  gint npoints = 4;
  GdkPoint mypoints[4];
  struct xy_co *coord;
  GdkGC *thegc;

  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
  thegc=mygc[color];
  coord = center_double_bond (x, y, tx, ty, 6); 
  mypoints[0].x = (gint16) (coord->x * size_factor);
  mypoints[0].y = (gint16) (coord->y * size_factor);
  mypoints[1].x = (gint16) (coord->tx * size_factor);
  mypoints[1].y = (gint16) (coord->ty * size_factor);
  coord++;
  mypoints[2].x = (gint16) (coord->tx * size_factor);
  mypoints[2].y = (gint16) (coord->ty * size_factor);
  mypoints[3].x = (gint16) (coord->x * size_factor);
  mypoints[3].y = (gint16) (coord->y * size_factor);
  gdk_draw_polygon (picture, thegc, TRUE, (GdkPoint *) mypoints,
		    (gint) npoints);

}

void
DrawStripe (int x, int y, int tx, int ty, int active, int color)
/* draws a striped single bond */
{
  int i;
  GdkPoint mypoints[4];
  struct xy_co *coord;
  GdkGC *thegc;

  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
  thegc=mygc[color];
  coord = center_double_bond (x, y, tx, ty, 4); 
  mypoints[0].x = (gint16) (coord->x * size_factor);
  mypoints[0].y = (gint16) (coord->y * size_factor);
  mypoints[1].x = (gint16) (coord->tx * size_factor);
  mypoints[1].y = (gint16) (coord->ty * size_factor);
  coord++;
  mypoints[2].x = (gint16) (coord->x * size_factor);
  mypoints[2].y = (gint16) (coord->y * size_factor);
  mypoints[3].x = (gint16) (coord->tx * size_factor);
  mypoints[3].y = (gint16) (coord->ty * size_factor);
  for (i = 0; i < 10; i++)
    {
      gdk_draw_line (picture, thegc,
		     mypoints[0].x + i * (mypoints[1].x - mypoints[0].x) / 10,
		     mypoints[0].y + i * (mypoints[1].y - mypoints[0].y) / 10,
		     mypoints[2].x + i * (mypoints[3].x - mypoints[2].x) / 10,
		     mypoints[2].y + i * (mypoints[3].y -
					  mypoints[2].y) / 10);
    }
}


void
DrawCircle (int x, int y, int tx, int ty, int active,int color)
/* draws a circle of radius (tx/ty)-(x/y) around (x/y) */
{
  GdkGC *thegc;
  int topleftx, toplefty;
  int radius;

  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active )
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
    thegc=mygc[color];
  radius = calc_vector (abs (tx - x), abs (ty - y)) * size_factor;

  topleftx = x * size_factor - radius;
  toplefty = y * size_factor - radius;
  gdk_draw_arc (picture, thegc, FALSE, topleftx, toplefty, 2 * radius,
		2 * radius, 0, 360 * 64);
  if (drawmode == 3 && !xbmflag)
    {
      thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
      gdk_draw_rectangle (picture, thegc, TRUE, x * size_factor - 1,
			  y * size_factor - 1, 3, 3);
      gdk_draw_rectangle (picture, thegc, TRUE, tx * size_factor - 1,
			  ty * size_factor - 1, 3, 3);
    }
}


void
DrawWiggly (int x, int y, int tx, int ty, int active, int color)
/* draws a wavy line */
{
  gint ax, ay, width, height, angle1, angle2;
  int narcs, veclen, boxlen;
  int i, xlen, ylen, ang;
  int boxcorx, boxcory;

  GdkGC *thegc;
  
  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
  thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
  thegc=mygc[color];

  narcs = 5;

  xlen = tx - x;
  ylen = ty - y;

  veclen = calc_vector (abs (tx - x), abs (ty - y));
  ang = (int)
    (180. +
    asin (copysign ((float) ylen / (float) veclen, (double) (xlen * -ylen) )) * 180. /
    3.14159);

  boxlen = (int) (0.2 * veclen);
  boxcorx = (int) ((1. - (float) xlen / (float) veclen) * boxlen / 2);
  boxcory = (int) ((1. - (float) ylen / (float) veclen) * boxlen / 2);

  for (i = 0; i < narcs; ++i)
    {
      ax = (gint)((x + 0.2 * i * xlen - boxcorx) * size_factor);
      ay = (gint)((y + 0.2 * i * ylen - boxcory) * size_factor);
      width = boxlen * size_factor;
      height = boxlen * size_factor;
      angle1 = ang * 64;
      angle2 = (gint) (-180 * 64 * pow (-1, (double)i));
      if (x > tx)
	angle2 *= -1;
      gdk_draw_arc (picture, thegc, FALSE, ax, ay, width, height, angle1,
		    angle2);
    }

}

void
DrawArrow (int x, int y, int tx, int ty, int head, int active, int color)
/* draws an arrow with either full or one-sided arrowhead */
{
  int xlen, ylen, xbase, ybase;
  gint npoints;
  float veclen, headfact, scalefact;
  GdkPoint mypoints[3];
  GdkGC *thegc;

  if (xbmflag)
    thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
    thegc= mygc[color];
    
  xlen = tx - x;
  ylen = ty - y;
  veclen = sqrt ((double)(xlen * xlen + ylen * ylen));
  scalefact=64./veclen; /* keep arrowhead size constant (64=std length)*/ 
/*  headfact = 1. - 20. / veclen;*/
  headfact = 0.8;
  xbase = x + headfact * xlen*scalefact;
  ybase = y + headfact * ylen*scalefact;

  xbase = (int) (tx - 0.2 *xlen*scalefact);
  ybase = (int) (ty - 0.2 *ylen*scalefact);

  mypoints[0].x = tx * size_factor;
  mypoints[0].y = ty * size_factor;

if (select_char (tx,ty,1) != NULL){
      xbase = x+headfact*xlen-12*xlen/veclen;
      ybase = y+headfact*ylen-12*ylen/veclen;
      mypoints[0].x = (gint16) ((tx-12*xlen/veclen)*size_factor);
      mypoints[0].y = (gint16) ((ty-12*ylen/veclen)*size_factor);
}
  mypoints[1].x = (gint16) ((xbase + 0.1 * ylen) * size_factor);
  mypoints[1].y = (gint16) ((ybase - 0.1 * xlen) * size_factor);
  mypoints[1].x = (gint16) ((xbase + 0.1 * ylen*scalefact) * size_factor);
  mypoints[1].y = (gint16) ((ybase - 0.1 * xlen*scalefact) * size_factor);

  if (head == 1)
    {
      mypoints[2].x = (gint16) (xbase * size_factor);	/*on baseline */
      mypoints[2].y = (gint16) (ybase * size_factor);
    }
  else
    {

      mypoints[2].x = (gint16) ((xbase - 0.1 * ylen) * size_factor);
      mypoints[2].y = (gint16) ((ybase + 0.1 * xlen) * size_factor);

      mypoints[2].x = (gint16) ((xbase - 0.1 * ylen*scalefact) * size_factor);
      mypoints[2].y = (gint16) ((ybase + 0.1 * xlen*scalefact) * size_factor);

    }

  npoints = 3;
  gdk_draw_line (picture, thegc, x * size_factor, y * size_factor,
		 tx * size_factor, ty * size_factor);
  gdk_draw_polygon (picture, thegc, TRUE, (GdkPoint *) mypoints,
		    (gint) npoints);
}

void
DrawDashedWedge (int x, int y, int tx, int ty, int active,int color)
/* draws the dashed wedge for a bond behind the image plane */
{
  int i, xlen, ylen;
  GdkGC *thegc;
  int len;
  float step,factor;
  
  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else 
  thegc= mygc[color];
  
  xlen = tx - x;
  ylen = ty - y;

len=(int) rint(calc_vector(abs(xlen),abs(ylen))/8.);
if (len<8) len=8;
 step = 1./len;
 factor=0.0125;
 if (len>20) factor= 0.00125;
 if (len==8) {
   factor =0.03;
 }
  for (i = 1; i < len; i++)
    gdk_draw_line (picture, thegc,
		   (x + step * i * xlen - factor * ylen * i) * size_factor,
		   (y + step * i * ylen + factor * xlen * i) * size_factor,
		   (x + step * i * xlen + factor * ylen * i) * size_factor,
		   (y + step * i * ylen - factor * xlen * i) * size_factor);
}

void
DrawWedge (int x, int y, int tx, int ty, int active, int color)
/* draws the wedge-shaped single bond 'pointing towards the viewer' */
{
  int xlen, ylen;
  gint npoints;
  GdkPoint mypoints[3];
  GdkGC *thegc;
  struct data *hpc;
  struct xy_co *coord;
  int d;
  float area;

  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
    thegc = mygc[color];
  xlen = tx - x;
  ylen = ty - y;
  
  float c=1.;
  if (xlen*xlen+ylen*ylen <=1000.) c=2.;

  mypoints[0].x = (gint16) (x * size_factor);
  mypoints[0].y = (gint16) (y * size_factor);
  mypoints[1].x = (gint16) ((tx - 0.1 *c * ylen) * size_factor);
  mypoints[1].y = (gint16) ((ty + 0.1 *c* xlen) * size_factor);
  mypoints[2].x = (gint16) ((tx + 0.1 *c* ylen) * size_factor);
  mypoints[2].y = (gint16) ((ty - 0.1 *c* xlen) * size_factor);

  hpc = da_root.next;
  for (d = 0; d < hp->n; d++)
    {
      if (hpc->bond == 10)
	{
	  if ((abs (hpc->x - tx) < 3 && abs (hpc->y - ty) < 3)
	      || (abs (hpc->tx - tx) < 3 && abs (hpc->ty - ty) < 3))
	    {
	      coord =
		center_double_bond (hpc->x, hpc->y, hpc->tx, hpc->ty, 6);

	      if (abs (hpc->x - tx) < 3 && abs (hpc->y - ty) < 3)
		{

		  mypoints[1].x = (gint16) (coord->x * size_factor);
		  mypoints[1].y = (gint16) (coord->y * size_factor);
		  coord++;
		  mypoints[2].x = (gint16) (coord->x * size_factor);
		  mypoints[2].y = (gint16) (coord->y * size_factor);
		}
	      else
		{
		  mypoints[1].x = (gint16) (coord->tx * size_factor);
		  mypoints[1].y = (gint16) (coord->ty * size_factor);
		  coord++;
		  mypoints[2].x = (gint16) (coord->tx * size_factor);
		  mypoints[2].y = (gint16) (coord->ty * size_factor);
		}
	      area =
		0.5 * abs (mypoints[0].x * (mypoints[1].y - mypoints[2].y) +
			    mypoints[1].x * (mypoints[2].y - mypoints[0].y) +
			    mypoints[2].x * (mypoints[0].y - mypoints[1].y));

	      if (fabs (area) < 76. * size_factor)
		{
		  mypoints[1].x = (gint16) ((tx - 0.05 * ylen) * size_factor);
		  mypoints[1].y = (gint16) ((ty + 0.05 * xlen) * size_factor);
		  mypoints[2].x = (gint16) ((tx + 0.05 * ylen) * size_factor);
		  mypoints[2].y = (gint16) ((ty - 0.05 * xlen) * size_factor);
		}
	    }
	}
      hpc = hpc->next;
    }
  npoints = 3;
  gdk_draw_polygon (picture, thegc, TRUE, (GdkPoint *) mypoints,
		    (gint) npoints);
}

void
Drawspline (int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3,
	    int type, int active, int color)
/* draws a spline curve, optionally with full of half arrowhead  */
{
  int xlen, ylen, xbase, ybase;
  double px0, py0, px1, py1;
  int i;
  double t;
  gint npoints;
  GdkPoint mypoints[21];
  GdkGC *thegc;
  
  if (xbmflag)
    thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
    thegc = mygc[color];
    
  if (drawmode == 3 && !xbmflag)
    {
      gdk_draw_rectangle (picture, thegc, TRUE, x0 * size_factor - 1,
			  y0 * size_factor - 1, 3, 3);
      gdk_draw_rectangle (picture, thegc, TRUE, x1 * size_factor - 1,
			  y1 * size_factor - 1, 3, 3);
      gdk_draw_rectangle (picture, thegc, TRUE, x2 * size_factor - 1,
			  y2 * size_factor - 1, 3, 3);
      gdk_draw_rectangle (picture, thegc, TRUE, x3 * size_factor - 1,
			  y3 * size_factor - 1, 3, 3);
    }
  px0 = (double)x0;
  py0 = (double)y0;
  for (i = 0; i < 21; i++)
    {
      t = (float) i / 20.;
      px1 =
	t * t * t * (double) x3 + 3. * t * t * (1. - t) * (double) x2 +
	3. * t * (1. - t) * (1. - t) * (double) x1 + (1. - t) * (1. -
								 t) * (1. -
								       t) *
	px0;
      py1 =
	t * t * t * (double) y3 + 3. * t * t * (1. - t) * (double) y2 +
	3. * t * (1. - t) * (1. - t) * (double) y1 + (1. - t) * (1. -
								 t) * (1. -
								       t) *
	py0;
      mypoints[i].x = (gint16) (px1 * size_factor);
      mypoints[i].y = (gint16) (py1 * size_factor);
    }
  npoints = 21;
  if (type >= 0) {
 /* move end of last line segment back a bit to keep it from protruding 
    beneath the arrowhead */
    xbase= mypoints[20].x;
    ybase= mypoints[20].y;
    mypoints[20].x = mypoints[20].x - (gint16) ( 0.03*(mypoints[20].x-mypoints[19].x));	
    mypoints[20].y = mypoints[20].y - (gint16) (0.03*(mypoints[20].y-mypoints[19].y));	
    gdk_draw_lines (picture, thegc, mypoints, npoints);
    mypoints[20].x=xbase;
    mypoints[20].y=ybase;
    }
    
  if (type == -1)
    gdk_draw_polygon (picture, thegc, TRUE, mypoints, npoints);
  if (type == -2)
    gdk_draw_points (picture, thegc, mypoints, npoints);

  if (type <= 0)
    return;

  for (i=0;i<4;i++){ /* find acceptable arrowhead length */
  xlen = mypoints[20].x - mypoints[19-i].x;
  ylen = mypoints[20].y - mypoints[19-i].y;
  xbase = mypoints[19-i].x;
  ybase = mypoints[19-i].y;
  if (xlen*xlen+ylen*ylen >200 *size_factor*size_factor) break;
  
  }

  if (xlen*xlen+ylen*ylen >400 *size_factor*size_factor) {
  xlen -= (mypoints[20].x - mypoints[19].x)/2;
  ylen -= (mypoints[20].y - mypoints[19].y)/2;
  xbase = mypoints[19].x +(mypoints[20].x - mypoints[19].x)/2 ;
  ybase = mypoints[19].y +(mypoints[20].y - mypoints[19].y)/2 ;
  }

  if (xlen != 0)
    xlen = (int) copysign (10. * size_factor, (double)xlen);
  if (ylen != 0)
    ylen = (int) copysign (10. * size_factor, (double)ylen);

  /* tip of arrow at original endpoint of last line */
  mypoints[0].x = mypoints[20].x;	
  mypoints[0].y = mypoints[20].y;	

  /* calculate both possible positions for arrow side */
  mypoints[1].x = (gint16) (xbase + 0.5 * ylen);
  mypoints[1].y = (gint16) (ybase - 0.5 * xlen);

  if (type == 1)
    {

      mypoints[2].x = (gint16) (xbase - 0.5 * ylen);
      mypoints[2].y = (gint16) (ybase + 0.5 * xlen);

      /* and choose the one facing outward (farther from the starting point) */
      px0 = (double) 
	((mypoints[1].x - x0 * size_factor) * (mypoints[1].x -
					      x0 * size_factor) +
	(mypoints[1].y - y0 * size_factor) * (mypoints[1].y -
					      y0 * size_factor));
      px1 = (double)
	((mypoints[2].x - x0 * size_factor) * (mypoints[2].x -
					      x0 * size_factor) +
	(mypoints[2].y - y0 * size_factor) * (mypoints[2].y -
					      y0 * size_factor));

      if (px0 < px1)
	{
	  mypoints[1].x = mypoints[2].x;
	  mypoints[1].y = mypoints[2].y;
	}

      mypoints[2].x = (gint16)xbase;	/*on baseline */
      mypoints[2].y = (gint16)ybase;
    }
  else
    {
      mypoints[2].x = (gint16) (xbase - 0.5 * ylen);	/* on opposite side of line */
      mypoints[2].y = (gint16) (ybase + 0.5 * xlen);
    }

  npoints = 3;
  gdk_draw_polygon (picture, thegc, TRUE, (GdkPoint *) mypoints,
		    (gint) npoints);
}


void
Drawstring (int x, int y, char *cc, int direct, int active, int thecolor, int serif_flag, int size, int preview)
/* draws a label with sub- and superscripting, symbols and text justification */
{
  int ha, tw, a;
  int nch, textl, chl, chr;
  int d, hx, n;
  int shiftall = 0;
  int variance[MAXCL];
  gchar *c;
#ifdef GTK2
  int dummy;
  gchar l[8];
  gunichar hc, hl;
  gunichar text[MAXCL];
  gunichar symbol[MAXCL];
  gunichar slanted[MAXCL];
  gunichar bold[MAXCL];
  static PangoLayout *thelayout;
#else
  char *l, *hc, hl[2];
  unsigned char text[MAXCL];
  char symbol[MAXCL];
  char slanted[MAXCL];
  char bold[MAXCL];
#endif
  GdkGC *thegc;
  int save_x, sub_lastx, sup_lastx;
  int fontsize;
  
  fontsize=size;
  if (zoom_factor <2) fontsize-=2-zoom_factor;
  if (zoom_factor >2) fontsize+=zoom_factor-2;
  if (fontsize<0 ) fontsize=curfontsize;
  if (fontsize>6) fontsize=6;
  if (preview) fontsize=0;
  
  if (xbmflag)
  thegc = drawing_area->style->black_gc;
  else if (active)
    thegc = drawing_area->style->bg_gc[GTK_STATE_SELECTED];
  else
    thegc = mygc[thecolor];
    
  x = x * size_factor;
  hx = x;
  y = y * size_factor;
  
#ifdef GTK2
memset(l,0,8*sizeof(gchar));
    c=g_locale_to_utf8(cc,-1,NULL,NULL,NULL);
  if (!c)  c=g_convert(cc,-1,"UTF-8","ISO8859-1",NULL,NULL,NULL); 
  if (!c) {
  fprintf(stderr,"invalid character in chemtool file\n");
  return;
  }
  if (!thelayout) thelayout = gtk_widget_create_pango_layout(drawing_area,"X");
  pango_layout_set_font_description(thelayout,font[fontsize]);
  pango_layout_get_pixel_size(thelayout, &tw, &a);  
  pango_layout_set_text(thelayout, "x", -1);
  pango_layout_set_font_description(thelayout,font[fontsize]);
  pango_layout_get_pixel_size(thelayout, &tw, &ha);
  ha = ha/2;
  n = (int) g_utf8_strlen(c,-1);
#else  
  c=cc;
  a = gdk_char_height (font[fontsize], 'X');
  ha = gdk_char_height (font[fontsize], 'x') / 2;
  a += 6;
  n = (int)strlen (c);
  tw = gdk_char_width (font[fontsize], 'x') ;
#endif

#ifdef GTK2
  for (d = 0; d < n; d++)
    {
      symbol[d] = FALSE;
      slanted[d] = FALSE;
      bold[d]=FALSE;
      
      hc = g_utf8_get_char(c);

      if (shiftall != 0)
	{
	  if (hc == '}')
	    {
	      shiftall = 0;
	      if (!(c=g_utf8_next_char(c)))continue;
	      --n;
	      hc=g_utf8_get_char(c);
	    }
	  variance[d] = shiftall;
	}
      if (shiftall == 0)
	{
	  if ((variance[d] = Extra_char (hc,ha)) != 0)
	    {
	      c=g_utf8_next_char(c);
	      if ((hc=g_utf8_get_char(c)))
		{
		  --n;
		  if (hc == '{')
		    {
		      --n;
		      shiftall = variance[d];
			c=g_utf8_next_char(c);		    
			hc=g_utf8_get_char(c);
		    }
		}
	      else
		{
		  variance[d] = 0;
		  n=d;
		  continue;
		}
	    }
	}
      text[d] = hc;
      c = g_utf8_next_char(c);
      if (text[d] == '@' && (hl=g_utf8_get_char(c)))
	{
	  symbol[d] = TRUE;
	  text[d] = hl;
          c = g_utf8_next_char(c);
	  --n;
	}

      else if (text[d] == '|' && (hl=g_utf8_get_char(c)))
	{
	  slanted[d] = TRUE;
	  text[d] = hl;
          c = g_utf8_next_char(c);
	  --n;
	}

      else if (text[d] == '#' && (hl=g_utf8_get_char(c)))
	{
	  bold[d] = TRUE;
	  text[d] = hl;
          c = g_utf8_next_char(c);
	  --n;
	}

      else if (text[d] == '\\' && (hl=g_utf8_get_char(c)))
	{
	text[d] = ' ';
	}
    }

#else
  hc = c;
  for (d = 0; d < n; d++)
    {
      symbol[d] = FALSE;
      slanted[d] = FALSE;
      bold[d]=FALSE;
      if (shiftall != 0)
	{
	  if (*hc == '}')
	    {
	      shiftall = 0;
	      if (*(hc + 1))
		hc++;
	      --n;
	    }
	  variance[d] = shiftall;
	}
      if (shiftall == 0)
	{
	  if ((variance[d] = Extra_char (*hc)) != 0)
	    {
	      if (*(hc + 1))
		{
		  hc++;
		  --n;
		  if (*hc == '{')
		    {
		      shiftall = variance[d];
		      hc++;
		      --n;
		    }
		}
	      else
		{
		  variance[d] = 0;
		}
	    }
	}
      text[d] = (unsigned char) *hc++;
      if (text[d] == '@' && *hc)
	{
	  symbol[d] = TRUE;
	  text[d] = (unsigned char) *hc++;
	  --n;
	}

      else if (text[d] == '|' && *hc)
	{
	  slanted[d] = TRUE;
	  text[d] = (unsigned char) *hc++;
	  --n;
	}

      else if (text[d] == '#' && *hc)
	{
	  bold[d] = TRUE;
	  text[d] = (unsigned char) *hc++;
	  --n;
	}

      else if (text[d] == '\\' && *hc)
	{
	text[d] = ' ';
	}
    }
#endif

  nch = n;
  if (nch > 0)
    {
      chl = 0;
      chr = 0;
      x = save_x = sub_lastx = sup_lastx = 0;
      for (d = 0; d < nch; d++)
	{
#ifdef GTK2
/*          l = g_locale_to_utf8((const gchar*) &text[d],1,NULL,NULL,NULL); */
memset(l,0,8*sizeof(gchar));
g_unichar_to_utf8(text[d],l);
#endif          
	  if (variance[d])
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,smallfont[fontsize]);
              pango_layout_get_pixel_size(thelayout, &tw, &dummy);
#else             
	      tw = gdk_char_width (smallfont[fontsize], (gchar)text[d]) + 2;
#endif
	      if (symbol[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,ssymbfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
		tw = gdk_char_width (ssymbfont[fontsize], (gchar)text[d]);
#endif
	      if (variance[d] < 0)
		{
		  if (save_x < x)
		    x = sub_lastx;
		  x = sub_lastx = x + tw;
		}
	      else
		{
		  if (save_x < x)
		    x = sup_lastx;
		  x = sup_lastx = x + tw;
		}
	    }
	  else /* not sub- or superscripted */
	    {
#ifdef GTK2
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,font[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
#else
	      tw = 1 + gdk_char_width (font[fontsize], (gchar)text[d]);
#endif
	      if (symbol[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,symbfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
		tw = gdk_char_width (symbfont[fontsize], (gchar)text[d]);
#endif
	      if (bold[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,boldfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	      	tw = gdk_char_width (boldfont[fontsize], (gchar)text[d]);
#endif
	      if (slanted[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,slfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
		tw = 1 + gdk_char_width (slfont[fontsize], (gchar)text[d]);
#endif
	      if (save_x < x) 
		{
		  if (sub_lastx < sup_lastx)
		    x = sup_lastx;
		  else
		    x = sub_lastx;
		}
	      x = save_x = sub_lastx = sup_lastx = x + tw;
	      chr = tw;
	    }
	  if (chl == 0)
	    chl = tw;
	}
	if (x != sub_lastx || x != sup_lastx) save_x+= tw; /* if the label ends with a sub/superscripted character, */
							   /* add its length to the current position (which is before */
							   /* the sub/superscript to allow vertical alignment of simultaneous */
							   /* sub- and superscripts */
      textl = save_x;
      switch (direct)
	{
	case 0:
	  hx = hx - chl / 2;
	  break;
	case -1:
	  hx = hx - (textl - 1) / 2;
	  break;
	case -2:
	  hx = hx + chr / 2 - (textl - 1);
	  break;
	}
    }
  nch = n;
  x = hx;
  save_x = sub_lastx = sup_lastx = x;
  for (d = 0; d < n; d++)
    {
#ifdef GTK2
/*          l = g_locale_to_utf8((const gchar*) &text[d],1,NULL,NULL,NULL);*/
memset(l,0,8*sizeof(gchar));
	g_unichar_to_utf8(text[d], l);
#endif          
      if (variance[d])
	{
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,smallfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	  tw = gdk_char_width (smallfont[fontsize], (gchar)text[d]) + 2;
#endif
	  if (symbol[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,ssymbfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	    tw = gdk_char_width (ssymbfont[fontsize], (gchar)text[d]);
#endif
	  if (variance[d] < 0)
	    {
	      if (save_x < x)
		x = sub_lastx;
	      sub_lastx = x + tw;
	    }
	  else
	    {
	      if (save_x < x)
		x = sup_lastx;
	      sup_lastx = x + tw;
	    }
	}
      else
	{ /* not sub- or superscripted */
#ifdef GTK2
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,font[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
#else                
	  tw = 1 + gdk_char_width (font[fontsize], (gchar)text[d]);
#endif
	  if (symbol[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,symbfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	    tw = gdk_char_width (symbfont[fontsize], (gchar)text[d]);
#endif
	  if (bold[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,boldfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	    tw = gdk_char_width (boldfont[fontsize], (gchar)text[d]);
#endif	    
	  if (slanted[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,slfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	    tw = 1 + gdk_char_width (slfont[fontsize], (gchar)text[d]);
#endif
	  if (save_x < x)
	    {
	      if (sub_lastx < sup_lastx)
		x = sup_lastx;
	      else
		x = sub_lastx;
	    }
	  save_x = sub_lastx = sup_lastx = x + tw;
	}

/* erase a circular area slightly larger than the current character to
   create some space around the label */
   if (text[d] != 183) {
    if (preview)
      gdk_draw_arc (picture, drawing_area->style->white_gc, 1,
		    x - 5 * size_factor,
		    y - a + ha - 5 * size_factor + variance[d],
		    tw + 8 * size_factor, a + 10 * size_factor, 0, 360 * 64);
	else
      if (use_whiteout) gdk_draw_arc (picture, background_gc, 1,
		    x - 2 * size_factor,
		    y -a + ha + size_factor * variance[d],
		    tw + 8 * size_factor, a + 2 * size_factor, 0, 360 * 64);
      x = x + tw;
      }
    }

  n = nch;
  x = hx;

#ifdef GTK2
  y -= a ;
#endif
  
 
  save_x = sub_lastx = sup_lastx = x;
  for (d = 0; d < n; d++)
    {
#ifdef GTK2
	memset(l,0,8*sizeof(gchar));
/*#ifdef GTK2*/
/*          l = g_locale_to_utf8((const gchar*) &text[d],1,NULL,NULL,NULL);*/
g_unichar_to_utf8(text[d],l);
	if (symbol[d]) {
	unsigned int unicodechar=text[d]+848;
	
	switch (unicodechar){ /* catch sequence mismatches with X Symbol font*/
			case 915: /*C*/
			case 947: /*c*/
				unicodechar+=20;
				break;
			case 918:
			case 950: /*f*/
				unicodechar+=16;
				break;
			case 919:	
			case 951: /*g*/
				unicodechar-=4;
				break;
			case 920:
			case 952: /*h*/
				unicodechar-=1;
				break;
			case 922: /*J is vartheta*/
				unicodechar=977;
				break;
			case 954: /*j is varphi*/
				unicodechar=981;
				break;
			case 923:
			case 924:
			case 925:
			case 955:
			case 956:
			case 957:
				unicodechar-=1;
				break;
			case 926: /*N*/
				unicodechar=78;
				break;
			case 958: /*n*/
				unicodechar=118;
				break;
			case 929: /*Q*/
				unicodechar=920;
				break;
			case 961: /*p*/
				unicodechar=952;
				break;
			case 962: 
				unicodechar-=1;
				break;
			case 966:/*v*/
				unicodechar=982;
				break;
			case 967: /*w*/
				unicodechar=969;
				break;
			case 968:
				unicodechar=958;
				break;
			case 969:
				unicodechar-=1;
				break;
			case 970:
				unicodechar=950;
				break;						
			case 930: /*R*/
				unicodechar-=1;
				break;
			case 934: /*V*/
				unicodechar=962;
				break;
			case 935: /*W*/
				unicodechar+=2;
				break;	
			case 936: /*X*/
				unicodechar=926;
				break;
			case 937: /*Y*/
				unicodechar-=1;
				break;
			case 938:
				unicodechar=90;
				break;	
			case 1031: /*centered dot*/									case 775: /* bullet */
				unicodechar=8226;
				break;	
			default:
				break;
			}				 

	g_unichar_to_utf8((gunichar)unicodechar,l);
	}
#else      
      hl[0] = (char)text[d];
      hl[1] = 0;
      l = &hl[0];
#endif

      if (variance[d])
	{
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,smallfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	  tw = gdk_char_width (smallfont[fontsize], (gchar)text[d]) + 2;
#endif
	  if (symbol[d])
#ifdef GTK2
                {
                  pango_layout_set_text(thelayout,l,-1);
                  pango_layout_set_font_description(thelayout,ssymbfont[fontsize]);
                  pango_layout_get_pixel_size(thelayout, &tw, &dummy);
                }
#else                
	    tw = gdk_char_width (ssymbfont[fontsize], (gchar)text[d]);
#endif

	  if (variance[d] < 0)
	    {
	      if (save_x < x)
		x = sub_lastx;
	      sub_lastx = x + tw;
	    }
	  else
	    {
	      if (save_x < x)
		x = sup_lastx;
	      sup_lastx = x + tw;
	    }

	  if (symbol[d])
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,ssymbfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha+variance[d],thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha+variance[d],thelayout);
#else
	      gdk_draw_text (picture, ssymbfont[fontsize],
			     background_gc, x,
			     y + ha + variance[d], l, (gint)strlen (l));
	      gdk_draw_text (picture, ssymbfont[fontsize], thegc, x,
			     y + ha + variance[d], l, (gint)strlen (l));
#endif
	    }
	  else
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,smallfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha+variance[d],thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha+variance[d],thelayout);
#else
	      gdk_draw_text (picture, smallfont[fontsize],
			     background_gc, x,
			     y + ha + variance[d], l, (gint)strlen (l));
	      gdk_draw_text (picture, smallfont[fontsize], thegc, x,
			     y + ha + variance[d], l, (gint)strlen (l));
#endif
	    }
	  x = x + tw;
	}
      else /* not sub- or superscripted */
	{
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,font[fontsize]);
              pango_layout_get_pixel_size(thelayout,&tw,&dummy);
#else
	  tw = 1 + gdk_char_width (font[fontsize], (gchar)text[d]);
#endif	  
	  if (symbol[d])
#ifdef GTK2
            {
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,symbfont[fontsize]);
              pango_layout_get_pixel_size(thelayout,&tw,&dummy);
             } 
#else
	    tw = gdk_char_width (symbfont[fontsize], (gchar)text[d]);
#endif	    
	  if (bold[d])
#ifdef GTK2
            {
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,boldfont[fontsize]);
              pango_layout_get_pixel_size(thelayout,&tw,&dummy);
             } 
#else
	    tw = gdk_char_width (boldfont[fontsize], (gchar)text[d]);
#endif	    
	  if (slanted[d])
#ifdef GTK2
            {
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,slfont[fontsize]);
              pango_layout_get_pixel_size(thelayout,&tw,&dummy);
             } 
#else
	    tw = 1 + gdk_char_width (slfont[fontsize],(gchar) text[d]);
#endif
	  if (save_x < x)
	    {
	      if (sub_lastx < sup_lastx)
		x = sup_lastx;
	      else
		x = sub_lastx;
	    }

	  if (symbol[d])
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,symbfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha,thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha,thelayout);
#else
	      gdk_draw_text (picture, symbfont[fontsize], background_gc,
			     x, y + ha, l, (gint)strlen (l));
	      gdk_draw_text (picture, symbfont[fontsize], thegc, x, y + ha, l,
			     (gint)strlen (l));
#endif
	    }
	  else if (bold[d])
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,boldfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha,thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha,thelayout);
#else
	      gdk_draw_text (picture, boldfont[fontsize], background_gc,
			     x, y + ha, l, (gint)strlen (l));
	      gdk_draw_text (picture, boldfont[fontsize], thegc, x, y + ha, l, (gint)strlen (l));
#endif
	    }
	  else if (slanted[d])
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,slfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha,thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha,thelayout);
#else
	      gdk_draw_text (picture, slfont[fontsize], background_gc,
			     x, y + ha, l, (gint)strlen (l));
	      gdk_draw_text (picture, slfont[fontsize], thegc, x, y + ha, l, (gint)strlen (l));
#endif
	    }
	  else if (serif_flag)
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,textfont[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha,thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha,thelayout);
#else
	      gdk_draw_text (picture, textfont[fontsize], background_gc,
			     x, y + ha, l, (gint)strlen (l));
	      gdk_draw_text (picture, textfont[fontsize], thegc, x, y + ha, l, (gint)strlen (l));
#endif
	    }
	  else
	    {
#ifdef GTK2
              pango_layout_set_text(thelayout,l,-1);
              pango_layout_set_font_description(thelayout,font[fontsize]);
              gdk_draw_layout(picture,background_gc,x,y+ha,thelayout);
              gdk_draw_layout(picture,thegc,x,y+ha,thelayout);
#else
	      gdk_draw_text (picture, font[fontsize], background_gc,
			     x, y + ha, l, (gint)strlen (l));
	      gdk_draw_text (picture, font[fontsize], thegc, x, y + ha, l, (gint)strlen (l));
#endif
	    }
	  x = x + tw;
	  save_x = sub_lastx = sup_lastx = x;
	}
    }
}

#ifdef GTK2
int
Extra_char (gunichar c, int ha)
#else
int
Extra_char (char c)
#endif
/* process control characters for sub- and superscripting */
{
#ifndef GTK2
  int ha = gdk_char_height (font[zoom_factor], 'x') / 2;
#endif
  if (c == '_')
    return (ha);
  if (c == '^')
    return (-ha);
  return (0);
}

int
Load_Font ()
/* load the normal, subscript and symbol fonts for all zoom scales */
{

#ifdef GTK2

int i;

  gchar *pangosymtype[]= {"Symbol 8", "Symbol 10", "Symbol 12", "Symbol 14",
                          "Symbol 18", "Symbol 20", "Symbol 24" };
  gchar *pangossymtype[]= {"Symbol 8", "Symbol 8", "Symbol 10", "Symbol 12",
                          "Symbol 14", "Symbol 18", "Symbol 24" };
  gchar *pangofntype[]= { "Helvetica 8", "Helvetica 10", "Helvetica 12",
                          "Helvetica 14", "Helvetica 17", "Helvetica 20", 
                          "Helvetica 24"};
  gchar *pangosfntype[]= { "Helvetica 8", "Helvetica 8", "Helvetica 10",
                           "Helvetica 12", "Helvetica 14", "Helvetica 14", 
                           "Helvetica 20"};
  gchar *pangosltype[]= { "Helvetica oblique 8", "Helvetica oblique 10",
                          "Helvetica oblique 12",  "Helvetica oblique 14",
                          "Helvetica oblique 18", "Helvetica oblique 18",
                          "Helvetica oblique 24"};
  gchar *pangobtype[]= { "Helvetica bold 8", "Helvetica bold 10",
                         "Helvetica bold 12",  "Helvetica bold 14",
                         "Helvetica bold 18", "Helvetica bold 18",
                         "Helvetica bold 24"};
  gchar *pangotexttype[]= { "Times 8", "Times 10",
                            "Times 12",  "Times 14",
                            "Times 18", "Times 18",
                            "Times 24"};
  for (i=0;i<7;i++){
  font[i]=pango_font_description_from_string(pangofntype[i]);
  symbfont[i]=pango_font_description_from_string(pangosymtype[i]);
  ssymbfont[i]=pango_font_description_from_string(pangossymtype[i]);
  smallfont[i]=pango_font_description_from_string(pangosfntype[i]);
  slfont[i]=pango_font_description_from_string(pangosltype[i]);
  boldfont[i]=pango_font_description_from_string(pangobtype[i]);
  textfont[i]=pango_font_description_from_string(pangotexttype[i]);
  }                                                                                                                                                                                                                                                                                                                           

#else

int i,fnt;

/* NB: entries 0 and 1 are used for preview only, the default font is 4(!) */
  gchar *symtype75[] = { "*-symbol-*-*-8-*", "*-symbol-*-*-10-*",
    "*-symbol-*-*-12-*", "*-symbol-*-*-14-*", "*-symbol-*-*-18-*",
    "*-symbol-*-*-18-*", "*-symbol-*-*-24-*"
  };

  gchar *ssymtype75[] = { "*-symbol-*-*-8-*", "*-symbol-*-*-8-*",
    "*-symbol-*-*-10-*", "*-symbol-*-*-12-*", "*-symbol-*-*-14-*",
    "*-symbol-*-*-18-*", "*-symbol-*-*-24-*"
  };

  gchar *symtype100[] = { "*-symbol-*-*-11-*", "*-symbol-*-*-14-*",
    "*-symbol-*-*-17-*", "*-symbol-*-*-20-*", "*-symbol-*-*-25-*",
    "*-symbol-*-*-25-*", "*-symbol-*-*-34-*"
  };

  gchar *ssymtype100[] = { "*-symbol-*-*-11-*", "*-symbol-*-*-11-*",
    "*-symbol-*-*-14-*", "*-symbol-*-*-17-*", "*-symbol-*-*-20-*",
    "*-symbol-*-*-25-*", "*-symbol-*-*-34-*"
  };

  gchar *fntype75[] =
    { "*-helvetica-medium-r-normal--8-*", "*-helvetica-medium-r-normal--10-*",
    "*-helvetica-medium-r-normal--12-*", "*-helvetica-medium-r-normal--14-*",
    "*-helvetica-medium-r-normal--18-*",
    "*-helvetica-medium-r-normal--18-*", "*-helvetica-medium-r-normal--24-*"
  };

  gchar *fntype100[] =
    { "*-helvetica-medium-r-normal--11-*", "*-helvetica-medium-r-normal--14-*",
    "*-helvetica-medium-r-normal--17-*", "*-helvetica-medium-r-normal--20-*",
    "*-helvetica-medium-r-normal--25-*",
    "*-helvetica-medium-r-normal--25-*", "*-helvetica-medium-r-normal--34-*"
  };

  gchar *fallback[] = { "5x7", "6x10", "7x13", "9x15", "8x16",
    "10x20", "12x24"
  };

  gchar *sfntype75[] =
    { "*-helvetica-medium-r-normal--8-*", "*-helvetica-medium-r-normal--8-*",
    "*-helvetica-medium-r-normal--10-*", "*-helvetica-medium-r-normal--12-*",
    "*-helvetica-bold-r-normal--14-*",
    "*-helvetica-bold-r-normal--14-*", "*-helvetica-medium-r-normal--20-*"
  };

  gchar *sfntype100[] =
    { "*-helvetica-medium-r-normal--11-*", "*-helvetica-medium-r-normal--11-*",
    "*-helvetica-medium-r-normal--14-*", "*-helvetica-medium-r-normal--17-*",
    "*-helvetica-bold-r-normal--20-*",
    "*-helvetica-bold-r-normal--20-*", "*-helvetica-medium-r-normal--25-*"
  };
/*  {"5x7", "5x7", "6x10", "8x13", "7x14",
   "8x13bold", "10x20"};*/

  gchar *sltype75[] =
    { "*-helvetica-medium-o-normal--8-*", "*-helvetica-medium-o-normal--10-*",
    "*-helvetica-medium-o-normal--12-*", "*-helvetica-medium-o-normal--14-*",
    "*-helvetica-medium-o-normal--18-*",
    "*-helvetica-medium-o-normal--18-*", "*-helvetica-medium-o-normal--24-*"
  };
  gchar *sltype100[] =
    { "*-helvetica-medium-o-normal--11-*", "*-helvetica-medium-o-normal--14-*",
    "*-helvetica-medium-o-normal--17-*", "*-helvetica-medium-o-normal--20-*",
    "*-helvetica-medium-o-normal--25-*",
    "*-helvetica-medium-o-normal--25-*", "*-helvetica-medium-o-normal--34-*"
  };

  gchar *btype75[] =
    { "*-helvetica-bold-r-normal--8-*", "*-helvetica-bold-r-normal--10-*",
    "*-helvetica-bold-r-normal--12-*", "*-helvetica-bold-r-normal--14-*",
    "*-helvetica-bold-r-normal--18-*",
    "*-helvetica-bold-r-normal--18-*", "*-helvetica-bold-r-normal--24-*"
  };
  gchar *btype100[] =
    { "*-helvetica-bold-r-normal--11-*", "*-helvetica-bold-r-normal--14-*",
    "*-helvetica-bold-r-normal--17-*", "*-helvetica-bold-r-normal--20-*",
    "*-helvetica-bold-r-normal--25-*",
    "*-helvetica-bold-r-normal--25-*", "*-helvetica-bold-r-normal--34-*"
  };

  gchar *texttype75[] =
    { "*-times-medium-r-normal--8-*", "*-times-medium-r-normal--10-*",
    "*-times-medium-r-normal--12-*", "*-times-medium-r-normal--14-*",
    "*-times-medium-r-normal--18-*",
    "*-times-medium-r-normal--18-*", "*-times-medium-r-normal--24-*"
  };
  gchar *texttype100[] =
    { "*-times-medium-r-normal--11-*", "*-times-medium-r-normal--14-*",
    "*-times-medium-r-normal--17-*", "*-times-medium-r-normal--20-*",
    "*-times-medium-r-normal--25-*",
    "*-times-medium-r-normal--25-*", "*-times-medium-r-normal--34-*"
  };


for (i=0;i<7;i++) {

  if (font[i])
    gdk_font_unref (font[i]);
  if (symbfont[i])
    gdk_font_unref (symbfont[i]);
  if (smallfont[i])
    gdk_font_unref (smallfont[i]);
  if (ssymbfont[i])
    gdk_font_unref (ssymbfont[i]);
  if (slfont[i])
    gdk_font_unref (slfont[i]);
  if (boldfont[i])
    gdk_font_unref (boldfont[i]);
  if (textfont[i])
    gdk_font_unref (textfont[i]);
   
   fnt=i;
  if ((font[i] = gdk_font_load (fntype75[fnt])) == NULL)
     if((font[i] = gdk_font_load (fntype100[fnt])) == NULL)
    {
      fprintf (stderr, "failed to load font %s !!!\n", fntype75[fnt]);
      if ((font[i] = gdk_font_load (fallback[fnt])) == NULL)
	return (0);
    }
  if ((symbfont[i] = gdk_font_load (symtype75[fnt])) == NULL)
     if((symbfont[i] = gdk_font_load (symtype100[fnt])) == NULL)
    {
      fprintf (stderr, "Failed to load symbol font, using standard font\n");
      symbfont[i] = font[i];
    }
  if ((ssymbfont[i] = gdk_font_load (ssymtype75[fnt])) == NULL)
  	if((ssymbfont[i] = gdk_font_load (ssymtype100[fnt])) == NULL)
   ssymbfont[i] = font[i];
  if ((smallfont[i] = gdk_font_load (sfntype75[fnt])) == NULL)
      if ((smallfont[i] = gdk_font_load (sfntype100[fnt])) == NULL)
    smallfont[i] = font[i];
  if ((slfont[i] = gdk_font_load (sltype75[fnt])) == NULL)
	if ((slfont[i] = gdk_font_load (sltype100[fnt])) == NULL) 
    slfont[i] = font[i];
  if ((boldfont[i] = gdk_font_load (btype75[fnt])) == NULL)
	if ((boldfont[i] = gdk_font_load (btype100[fnt])) == NULL)
    boldfont[i] = font[i];
  if ((textfont[i] = gdk_font_load (texttype75[fnt])) == NULL)
	if ((textfont[i] = gdk_font_load (texttype100[fnt])) == NULL)
    textfont[i] = font[i];
 } 

#endif

  return (1);
}

void
Set_Line (int lsty)
/* define standard line attributes for bond drawing */
{
  int i;

  for (i=0; i<7; i++)
  gdk_gc_set_line_attributes (mygc[i], lsty, 0,
                              GDK_CAP_BUTT, GDK_JOIN_MITER);

  gdk_gc_set_line_attributes (background_gc, lsty, 0,
			      GDK_CAP_BUTT, GDK_JOIN_MITER);
  gdk_gc_set_line_attributes (drawing_area->style->black_gc, lsty, 0,
			      GDK_CAP_BUTT, GDK_JOIN_MITER);
}


syntax highlighted by Code2HTML, v. 0.9.1