#ifdef WINDOWS
#include <io.h>
#include <fcntl.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "../../../config.h"

#include <gtk/gtk.h>
#if GTKVERSION==2
  #include <gdk/gdkkeysyms.h>
#else
  #include <gdk/gdk.h>
#endif

#include <cairo.h>
#include <cairo-ps.h>
#include <cairo-pdf.h>
#include <cairo-svg.h>

static DCL_REAL rwxold, rwyold;

#define FACTZ  0.03          /* scaling factor */

#ifndef TRUE
#define TRUE   -1             /* numeric value for true  */
#endif
#ifndef FALSE
#define FALSE  0             /* numeric value for false */
#endif

#define PAD    2.0           /* padding for workstation window */
#define LWDATR TRUE          /* line width  capability */
#define LCLATR TRUE          /* line color  capability */
#define LTNATR FALSE         /* hardfill image   capability */
#define LIMATR TRUE          /* bit image   capability */
#define LPTATR FALSE         /* mouse point capability */


#define MAXWDI 9             /* maximum number of line index */
#define MAXCLI 255           /* maximum number of line color */
#define MAXBMP 300           /* maximum number of bitmaps */

#define DOPN  1
#define DCLS  2
#define PCLS  3

#define IWS_DISP  1
#define IWS_FILE  2

#define IFL_EPS   2
#define IFL_PNG   1
#define IFL_SVG   3
#define IFL_PDF   4

#define FSFACT 26.0   /* size factor to convert DCL font size to Pango size */



//static double linewidth[MAXWDI] = { 1.0, 2.0, 2.0, 3.0, 3.0, 4.0, 4.0, 5.0, 5.0 };
static double linewidth[MAXWDI] = { 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0 };

static int iwidth,iheight;
static int iwdidz;           /* pen width */
static int iclidz;           /* pen color index */
static int iwtroz;           /* direction of frame */
static int lclatrz = TRUE;          /* type of screen */
//static int imagewrite = FALSE;          /* (Not) Use Image buffer Surface */
static int idev_type;         /* absolute value of type of device 1:Display 2:Files */
                              /*1:png 2:eps 3:SVG 4:PDF */
static int jdev_type;         /* type of device (landscape or portlait) 1:Display 2:Files */
                              /*1:png 2:eps 3:SVG 4:PDF */
static int wsxwd, wsywd, wsxmnz,wsymnz;
// wsxmxz, , wsymxz;
static int ixz, iyz, iwz, ihz, ixxz, iyyz, page; /* for image */
static int irxt,iryt,irxb,iryb,irwidth; /* for Invalidate */
static int posx, posy, wait_np, wait_op, wait_cl, key, dump, fgbg, sep;
static int nbmap, nn1[MAXBMP], nn2[MAXBMP], nx[MAXBMP], ny[MAXBMP];
static char dmpfile[1024], xtitle[80];
static char bmline[MAXBMP][260];
static int lfcmod = FALSE;

static int lfirst = TRUE;
static int ltfrst = TRUE;

static int laltz = FALSE;

static int pactive;

static GtkWidget *window = NULL;
static GtkWidget *drawing_area = NULL;

static int ldclonly = FALSE;
static int lpage = FALSE;

static int wnd;

//Name Should be change (cr(cairo surface ) to cairo cr)
static cairo_t *cr;
static cairo_surface_t *csr;

//Font
gchar     *fontfamily;
PangoFontDescription *font_desc;

static char defaultfont[]="Sans Normal 12";
//imagemode surface
////static cairo_t *cri;
static cairo_surface_t *csi;

static char imgfmt[8];
static DCL_REAL imgcmp;

#if GTKVERSION==2
static GdkColor cx[MAXCLI];
#elif GTKVERSION==3
static GdkColor cx[MAXCLI];
#else
static GdkRGBA cx[MAXCLI];
#endif

static int ifunc, next;
static int dumpz = FALSE;

/* Post Script A4 Page (Landscape) */
static int PS_PAGE_WIDTH  = 595;
static int PS_PAGE_HEIGHT = 842;

static int iPS_PAGE_WIDTH;
static int iPS_PAGE_HEIGHT;

static double ipsx=33;
static double ipsy=46;

static double ddvscale = 1.0;
static double dlnscale;
static double offx = 0.0;
static double offy = 0.0;

/* For BITMAP Image */
static unsigned char * pixels;
static int rows;

static int dmpdgt;
static int pngstdout;
static int ifl;

static cairo_status_t png2stdout(void *, const unsigned char* , unsigned int );
static void zgcatl(void);

static char fontlist[255] = { 41, 42, 43, 44, 55, 66, 77, 85, 95 };

//  Full Color index */
static double rt2,gt2,bt2,rl2,gl2,bl2;
static int ifcidx=998;
//Background color index
static int ibgcli=999;


/* For using system font. some internal variables of SGPACK*/
static int sg_lfprop, sg_lcntl, sg_isup, sg_isub, sg_irst;
static double sg_small, sg_shift;

//usage
// sg_isub=getiparm("isub");

char *zglpmname[]={
  "lfprop","lcntl"
};
char* zgipmname[]={
  "isup","isub","irst"
};
char *zgrpmname[]={
  "small","shift"
};
static int zglparm[2];
static int zgiparm[3];
static DCL_REAL zgrparm[2];

/*---------------------- parameter set --------------------*/
int getparmnumber(char pmname[],int tp){
  int num,iend;
  num=-1;
  iend=0;
    switch (tp){
    case 0:
      while(iend==0){
        num++;
        if(strcmp(zglpmname[num],pmname)==0){iend=1;};
      }
      break;
    case 1:
      while(iend==0){
        num++;
        if(strcmp(zgipmname[num],pmname)==0){iend=1;};
      }
      break;
    case 2:
      while(iend==0){
        num++;
        if(strcmp(zgrpmname[num],pmname)==0){iend=1;};
      }
      break;
    }



  return num;
}


#ifndef WINDOWS
void zglset_(char pmname[],int *pl,DCL_INT* value)
#else
void ZGLSET(char pmname[],int *pl,DCL_INT* value)
#endif
{
  int i;
  char pmn[8];
  int p,v;
  p=*pl;
  v=*value;

  pmn[*pl]='\0';
  for(i=0;i<*pl;i++){pmn[i]=pmname[i];}
  zglparm[getparmnumber(pmn,0)]=*value;

}
#ifndef WINDOWS
void zgiset_(char pmname[],int *pl,DCL_INT* value)
#else
void ZGISET(char pmname[],int *pl,DCL_INT* value)
#endif
{
  int i;
  char pmn[8];
  pmn[*pl]='\0';
  for(i=0;i<*pl;i++){pmn[i]=pmname[i];}
  zgiparm[getparmnumber(pmn,1)]=*value;
}
#ifndef WINDOWS
void zgrset_(char pmname[],int *pl,DCL_REAL *value)
#else
void ZGRSET(char pmname[],int *pl,DCL_REAL *value)
#endif
{
  int i;
  char pmn[8];
  pmn[*pl]='\0';
  for(i=0;i<*pl;i++){pmn[i]=pmname[i];}
  zgrparm[getparmnumber(pmn,2)]=*value;
}

DCL_INT getlparm(char* pmname){
  return zglparm[getparmnumber(pmname,0)];
}
DCL_INT getiparm(char* pmname){
  return zgiparm[getparmnumber(pmname,1)];
}
DCL_REAL getrparm(char* pmname){
  return zgrparm[getparmnumber(pmname,2)];
}

/*---------------------- transformation -------------------*/
#ifndef WINDOWS
void zgfint_(DCL_REAL *wx, DCL_REAL *wy, DCL_INT *iwx, DCL_INT *iwy)
#else
void ZGFINT(DCL_REAL *wx, DCL_REAL *wy, DCL_INT *iwx, DCL_INT *iwy)
#endif
{

    *iwx = *wx + 0.5;
    *iwy = wsywd - *wy + 0.5;
}

#ifndef WINDOWS
void zgfrel_(DCL_REAL *wx, DCL_REAL *wy, DCL_REAL *rwx, DCL_REAL *rwy)
#else
void ZGFREL(DCL_REAL *wx, DCL_REAL *wy, DCL_REAL *rwx, DCL_REAL *rwy)
#endif
{

  *rwx = *wx + 0.5;
  *rwy = wsywd - *wy + 0.5;

  *rwx = *rwx * ddvscale;
  *rwy = *rwy * ddvscale;

}

#ifndef WINDOWS
void zgiint_(DCL_INT *iwx, DCL_INT *iwy, DCL_REAL *wx, DCL_REAL *wy)
#else
void ZGIINT(DCL_INT *iwx, DCL_INT *iwy, DCL_REAL *wx, DCL_REAL *wy)
#endif
{
  *wx = *iwx;
  *wy = wsywd - *iwy;
}

/*------------------------- GDK 設定 ------------------------*/

#if GTKVERSION==2
void zgupdate(int flag)
#else
void zgupdate(int flag,cairo_t* crx )
#endif
{
#if GTKVERSION==2
  GdkRectangle update_rect;
  if (idev_type==IWS_DISP){
    update_rect.x = irxb-1;
    update_rect.y = iryb-1;
    update_rect.width  = irxt-irxb+1;
    update_rect.height = iryt-iryb+1;
    if (irxb == 0 && irxt == 0 && iryb == 0 && iryt == 0 && flag == 0){
      update_rect.x = 0;
      update_rect.y = 0;
      update_rect.width  = wsxwd;
      update_rect.height = wsywd;
    }
  gtk_widget_draw(drawing_area, &update_rect);
#else
  GtkAllocation update_rect;
  if (idev_type==IWS_DISP){
    update_rect.x = irxb-1;
    update_rect.y = iryb-1;
    update_rect.width  = irxt-irxb+1;
    update_rect.height = iryt-iryb+1;
    if (irxb == 0 && irxt == 0 && iryb == 0 && iryt == 0 && flag == 0){
      update_rect.x = 0;
      update_rect.x = 0;
      update_rect.width  = wsxwd-1;
      update_rect.height = wsywd-1;
    }
#endif
#if GTKVERSION==2
#else
      gtk_widget_queue_draw_area(
        drawing_area,
        update_rect.x,update_rect.y,
        update_rect.width,update_rect.height);
#endif
      irxt = 0;
      irxb = 0;
      iryt = 0;
      iryb = 0;
      while (gtk_events_pending()) gtk_main_iteration();
    }
}
/*--------------------- internal function -------------------*/

void zguprect(int ix,int iy){
	if ((ix-irwidth) < irxb || irxb == 0) irxb =ix-irwidth;
	if ((ix+irwidth) > irxt ) irxt =ix+irwidth;
	if ((iy-irwidth) < iryb || iryb == 0) iryb =iy-irwidth;
	if ((iy+irwidth) > iryt ) iryt =iy+irwidth;
}


/*-----------------------------------------------*/
#if GTKVERSION==2
gint zg_expose_event(GtkWidget *widget, GdkEventExpose *event)
{
static cairo_t *cre;
  if (idev_type==IWS_DISP && lpage){
    cre = gdk_cairo_create(widget->window);
    cairo_set_source_surface(cre,csr,0,0);
    cairo_paint(cre);
    cairo_destroy(cre);
  }
  return FALSE;
}
#else
gboolean zg_draw_event(GtkWidget *widget, cairo_t *cr)
{
  if (idev_type==IWS_DISP && lpage){
//    cre = gdk_cairo_create(gtk_widget_get_parent_window(widget));
    cairo_set_source_surface(cr,csr,0,0);
    cairo_paint(cr);
  }
  return(FALSE);
}
#endif

#if GTKVERSION==2
gint zg_key_press_event(GtkWidget *widget, GdkEventKey *event)
#elif GTKVERSION==3
gint zg_key_press_event(GtkWidget *widget, GdkEventKey *event)
#else
gint zg_key_press_event(GtkWidget *widget, GdkEvent *event)
#endif
{
  switch (ifunc){
  case DOPN:
    next = TRUE;
    break;

  case DCLS:
#if GTKVERSION==2
    switch (event->keyval) {
#elif GTKVERSION==3
    switch (event->keyval) {
#else
    switch (gdk_key_event_get_keyval(event)){
#endif

#if GTKVERSION==2
    case GDK_space:
    case GDK_Return:
#else
    case GDK_KEY_space:
    case GDK_KEY_Return:
#endif
      next = TRUE;
      break;
    default:
      next = FALSE;
    }
    break;

  case PCLS:
#if GTKVERSION==2
    switch (event->keyval) {
#elif GTKVERSION==3
    switch (event->keyval) {
#else
    switch (gdk_key_event_get_keyval(event)){
#endif
      
#if GTKVERSION==2
    case GDK_w:
#else
    case GDK_KEY_w:
#endif
      wait_np = TRUE;
      break;
#if GTKVERSION==2
    case GDK_Return:
    case GDK_space:
#else
    case GDK_KEY_Return:
    case GDK_KEY_space:
#endif
      next = TRUE;
      break;
#if GTKVERSION==2
    case GDK_d:
#else
    case GDK_KEY_d:
#endif
      next = TRUE;
      dumpz = TRUE;
      break;
#if GTKVERSION==2
    case GDK_s:
#else
    case GDK_KEY_s:
#endif
      next = TRUE;
      wait_np = FALSE;
      break;
#if GTKVERSION==2
    case GDK_q:
      gtk_exit(0);
#else
    case GDK_KEY_q:
#endif
      exit(0);
    default:
      next = FALSE;
    }
    break;

  default:
    next = FALSE;
  }
  return TRUE;
}

#if GTKVERSION==2
gint zg_button_press_event(GtkWidget *widget, GdkEventButton *event)
#elif GTKVERSION==3
gint zg_button_press_event(GtkWidget *widget, GdkEventButton *event)
#else
gint zg_button_press_event(GtkWidget *widget, GdkEvent *event)
#endif
{
  switch (ifunc){
  case DOPN:
  case DCLS:
  case PCLS:
    next = TRUE;
    break;

  default:
    next = FALSE;
  }
  return TRUE;
}

#if GTKVERSION==2
gint zg_destroy_event(GtkWidget *widget, GdkEventButton *event)
#elif GTKVERSION==3
gint zg_destroy_event(GtkWidget *widget, GdkEventButton *event)
#else
gint zg_destroy_event(GtkWidget *widget, GdkEvent *event)
#endif
{
#if GTKVERSION==2
      gtk_exit(0);
#endif
  exit(0);
  return TRUE;
}

/*-----------------------------------------------*/
#ifndef WINDOWS
static GtkWidget *zggdrw_(DCL_INT *width, DCL_INT *height)
#else
static GtkWidget *ZGGDRW(DCL_INT *width, DCL_INT *height)
#endif
{
  GtkWidget * drw;
  GtkWidget *vbox;
#if GTKVERSION==2
  gtk_init(0,NULL);
#elif GTKVERSION==3
  gtk_init(0,NULL);
#else
  gtk_init();
#endif
  
#if GTKVERSION==2
  drw=gtk_drawing_area_new();
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#elif GTKVERSION==3
  drw = (GtkWidget*)gtk_drawing_area_new();
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#else
  drw = (GtkWidget*)gtk_drawing_area_new();
  window = gtk_window_new();
#endif



#if GTKVERSION==2
  gtk_drawing_area_size(GTK_DRAWING_AREA (drw), wsxwd, wsywd);
#else
  gtk_widget_set_size_request((GtkWidget*)drw, wsxwd, wsywd);
#endif

  gtk_widget_show(drw);
  gtk_window_set_title (GTK_WINDOW (window), xtitle);

#if GTKVERSION==2
  gtk_container_add(GTK_CONTAINER (window), drw);
#else
  gtk_container_add(GTK_CONTAINER(window),drw);
#endif
  if (!wnd){
    gtk_widget_realize(drw);
  }else {
    if (key){
#if GTKVERSION==2
      gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK|GDK_KEY_PRESS_MASK);
      gtk_signal_connect(GTK_OBJECT (window), "key_press_event",
			 (GtkSignalFunc) zg_key_press_event, NULL);
#elif GTKVERSION==3
      gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK|GDK_KEY_PRESS_MASK);
      g_signal_connect(G_OBJECT(window), "button_press_event",
                          G_CALLBACK(zg_button_press_event), NULL);
#else
      gtk_widget_set_events(window, GDK_BUTTON_PRESS|GDK_KEY_PRESS);
      g_signal_connect(G_OBJECT(window), "button_press_event",
                          G_CALLBACK(zg_button_press_event), NULL);
#endif
    }

#if GTKVERSION==2
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK|GDK_KEY_PRESS_MASK);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK);
    gtk_signal_connect(GTK_OBJECT (window), "button_press_event",
  		       (GtkSignalFunc) zg_button_press_event, NULL);
    gtk_widget_set_events(drw, GDK_EXPOSURE_MASK);
    gtk_signal_connect(GTK_OBJECT (drw), "expose_event",
  		       (GtkSignalFunc) zg_expose_event, NULL);
    gtk_signal_connect(GTK_OBJECT (window), "destroy",
  		       (GtkSignalFunc) zg_destroy_event, NULL);
    /*#elif GTKVERSION==3
    //      gtk_widget_set_events(drw, GDK_EXPOSURE_MASK);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK);
    g_signal_connect(G_OBJECT(window), "key_press_event",
                      G_CALLBACK(zg_key_press_event), NULL);
    g_signal_connect (G_OBJECT(drw), "draw",
                      G_CALLBACK(zg_draw_event), NULL);
    g_signal_connect(G_OBJECT (window), "destroy",
    G_CALLBACK(zg_destroy_event), NULL);*/
#elif GTKVERSION==3
//      gtk_widget_set_events(drw, GDK_EXPOSURE_MASK);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK|GDK_KEY_PRESS_MASK);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS_MASK);
    g_signal_connect(G_OBJECT(window), "key_press_event",
                      G_CALLBACK(zg_key_press_event), NULL);
    g_signal_connect (G_OBJECT(drw), "draw",
                      G_CALLBACK(zg_draw_event), NULL);
    g_signal_connect(G_OBJECT (window), "destroy",
  	          	      G_CALLBACK(zg_destroy_event), NULL);
#else
//      gtk_widget_set_events(drw, GDK_EXPOSURE_MASK);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS|GDK_KEY_PRESS);
    gtk_widget_set_events(window, GDK_BUTTON_PRESS);
    g_signal_connect(G_OBJECT(window), "key_press_event",
                      G_CALLBACK(zg_key_press_event), NULL);
    g_signal_connect (G_OBJECT(drw), "draw",
                      G_CALLBACK(zg_draw_event), NULL);
    g_signal_connect(G_OBJECT (window), "destroy",
  	          	      G_CALLBACK(zg_destroy_event), NULL);
#endif
      gtk_widget_show(window);
  }
  return drw;
}

#ifndef WINDOWS
GtkWidget *zgqdrw_(void)
#else
GtkWidget *ZGQDRW(void)
#endif
{
  return drawing_area;
}

static cairo_t *zgcsfc(){
  cairo_t *cro;
  char cout[64];

  if (idev_type == IWS_DISP){
    csr = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,wsxwd,wsywd);
  }else if (idev_type == IWS_FILE){
    if(ifl == IFL_EPS){
      ddvscale = 1.0;
      if (page != 0){
        sprintf (cout, "%s_%0*d.eps", dmpfile,dmpdgt, page);
        csr = cairo_ps_surface_create(cout, PS_PAGE_HEIGHT * ddvscale, PS_PAGE_WIDTH * ddvscale );
        cairo_ps_surface_set_eps(csr,TRUE);
      }
      linewidth[0] =  2.0;
      linewidth[1] =  4.0;
      linewidth[2] =  6.0;
      linewidth[3] =  8.0;
      linewidth[4] = 10.0;
      linewidth[5] = 11.0;
      linewidth[6] = 12.0;
      linewidth[7] = 13.0;
      linewidth[8] = 14.0;
    }else if(ifl == IFL_PNG){
      csr = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,wsxwd,wsywd);
    }else if(ifl == IFL_SVG){
      if (page != 0){
        sprintf (cout, "%s_%0*d.svg", dmpfile,dmpdgt, page);
        csr = cairo_svg_surface_create(cout,wsxwd,wsywd);
      }
    }else if (ifl == IFL_PDF){
      ddvscale = 1.0;
      if ( !sep ){
        sprintf (cout, "%s.pdf", dmpfile);
      } else if ( page != 0 ){
        sprintf (cout, "%s_%0*d.pdf", dmpfile,dmpdgt, page);
      }
      csr = cairo_pdf_surface_create(cout, PS_PAGE_WIDTH * ddvscale, PS_PAGE_HEIGHT * ddvscale );
/*      linewidth[0] =  2.0;
      linewidth[1] =  4.0;
      linewidth[2] =  6.0;
      linewidth[3] =  8.0;
      linewidth[4] = 10.0;
      linewidth[5] = 11.0;
      linewidth[6] = 12.0;
      linewidth[7] = 13.0;
      linewidth[8] = 14.0; */
/*      linewidth[0] =  1.0;
      linewidth[1] =  2.0;
      linewidth[2] =  2.0;
      linewidth[3] =  3.0;
      linewidth[4] = 3.0;
      linewidth[5] = 4.0;
      linewidth[6] = 4.0;
      linewidth[7] = 5.0;
      linewidth[8] = 5.0;*/
    }
  }

  cro = cairo_create(csr);

  cairo_pattern_set_filter(cairo_get_source(cro), CAIRO_FILTER_NEAREST);

  cairo_set_source_rgb(cro,1.0,1.0,1.0);

  return cro;
}

/*-----------------------------------------------*/
static void zgbmcv(int *nx, int *ny, char bmline[], char bitmap[])
{
  static int n8 = 8;
  int n, nb;
  unsigned bx;

  nb = *nx * *ny / n8;

  for (n = 0; n < nb; n++){
    sscanf(&bmline[2*n], "%2x", &bx);
    bitmap[n] = bx;
  }
  bitmap[nb] = '\0';
}

/*------------------------- device ------------------------*/
#ifndef WINDOWS
void zgdopn_(DCL_INT *dev_type,
             DCL_INT *width, DCL_INT *height, DCL_INT *iposx, DCL_INT *iposy, DCL_INT *idmpdgt,
             DCL_INT *ibgpage,DCL_REAL *rlwfact,
             DCL_INT *lwait, DCL_INT *lwait0, DCL_INT *lwait1, DCL_INT *lalt , DCL_INT *lstdot,
             DCL_INT *lkey, DCL_INT *ldump, DCL_INT *lwnd, DCL_INT *lfgbg, DCL_INT *lsep, DCL_INT *ifln,
             char cimgfmt[], DCL_REAL *rimgcmp, char clrmap[], char cbmmap[], char file[], char title[]
             )
#else
void ZGDOPN(DCL_INT *dev_type,
            DCL_INT *width, DCL_INT *height, DCL_INT *iposx, DCL_INT *iposy, DCL_INT *idmpdgt,
            DCL_INT *ibgpage, DCL_REAL *rlwfact,
            DCL_INT *lwait, DCL_INT *lwait0, DCL_INT *lwait1, DCL_INT *lalt,DCL_INT *lstdot,
            DCL_INT *lkey, DCL_INT *ldump, DCL_INT *lwnd, DCL_INT *lfgbg, DCL_INT *lsep, DCL_INT *ifln,
            char cimgfmt[], DCL_REAL *rimgcmp, char clrmap[], char cbmmap[], char file[], char title[]
            )
#endif
{
  void cfnchr(char *ch1, char *ch2, int lch);

  int ncolor, n, m ,fscanret;

  guint16 rx[MAXCLI], gx[MAXCLI], bx[MAXCLI], rx1, gx1, bx1;
  char c[80], cmapz[80], bmapz[80];

  FILE *stream;

  //  GdkVisual *vis;

  GdkRectangle update_rect;
  GdkEvent *ev;

  double rt1,gt1,bt1;
  
  fontfamily=defaultfont;
  font_desc = pango_font_description_from_string ("Sans Normal 12");

  sg_lfprop = getlparm("lfprop");
  sg_lcntl  = getlparm("lcntl");
  sg_isup   = getiparm("isup");
  sg_isub   = getiparm("isub");
  sg_irst   = getiparm("irst");
  sg_small  = getrparm("small");
  sg_shift  = getrparm("shift");
  
  posx      = *iposx;
  posy      = *iposy;
  wait_np   = *lwait;
  wait_op   = *lwait0;
  wait_cl   = *lwait1;
  key       = *lkey;
  dump      = *ldump;
  fgbg      = *lfgbg;
  sep       = *lsep;
  laltz     = *lalt;
  idev_type = abs(*dev_type);
  jdev_type = *dev_type;
  wnd       = *lwnd;
  page      = *ibgpage - 1;

  cfnchr(imgfmt, cimgfmt, 7);
  imgcmp = *rimgcmp;
  dmpdgt = *idmpdgt;
  pngstdout  = *lstdot;
  ifl  = *ifln;

  iwidth = *width;
  iheight = *height;

  dlnscale = *rlwfact;

  if ((idev_type == IWS_FILE) && ( ifl == IFL_EPS || ifl == IFL_PDF)){
    if (((PS_PAGE_HEIGHT - ipsy *2) / iwidth) > ((PS_PAGE_WIDTH - ipsx *2 )/ iheight)){
      if((PS_PAGE_HEIGHT < iwidth + ipsx * 2) || (PS_PAGE_WIDTH < iheight + ipsy * 2)){
        PS_PAGE_WIDTH=iheight + ipsy * 2;
        PS_PAGE_HEIGHT=iwidth + ipsx * 2;
      }
      iPS_PAGE_WIDTH   = PS_PAGE_WIDTH - ipsx * 2;
      iPS_PAGE_HEIGHT  = (PS_PAGE_WIDTH - ipsx * 2) * iwidth / iheight;
      PS_PAGE_WIDTH=iPS_PAGE_WIDTH + ipsx *2;
      PS_PAGE_HEIGHT=PS_PAGE_WIDTH * 842 / 595;
      offx = ipsx;
      offy = ipsy + (PS_PAGE_HEIGHT - ipsy *2 - iPS_PAGE_HEIGHT )/2;
      if(dlnscale==999.){
        dlnscale = (DCL_REAL)iPS_PAGE_WIDTH / iwidth ;
      }
    }else{
      if((PS_PAGE_HEIGHT < iwidth + ipsx * 2) || (PS_PAGE_WIDTH < iheight + ipsy * 2)){
        PS_PAGE_WIDTH=iheight + ipsy * 2;
        PS_PAGE_HEIGHT=iwidth + ipsx * 2;
      }
      iPS_PAGE_WIDTH   = (PS_PAGE_HEIGHT -ipsy*2) * iheight / iwidth;
      iPS_PAGE_HEIGHT  = PS_PAGE_HEIGHT - ipsy*2;
      PS_PAGE_HEIGHT=iPS_PAGE_HEIGHT + ipsy *2;
      PS_PAGE_WIDTH=PS_PAGE_HEIGHT * 595 / 842;
      offx = ipsx + (PS_PAGE_WIDTH  - ipsx *2 - iPS_PAGE_WIDTH)/2;
      offy = ipsy;
      if(dlnscale==999.){
        dlnscale = (DCL_REAL)iPS_PAGE_HEIGHT/iheight;
      }
    }
    if( ifl == IFL_EPS ){
      dlnscale=0.1;
    }
  }else{
    dlnscale = 1.0;
  }

  if (!wnd) {
    wait_np = FALSE;
    wait_op = FALSE;
    wait_cl = FALSE;
    dump    = TRUE;
  }

  cfnchr(dmpfile, file, 1023);
  cfnchr(xtitle, title, 79);

  /* check drawing_area, if not set, stop */

  if (idev_type == IWS_DISP){
    if (drawing_area == NULL) {
      ldclonly = TRUE;
      wsxwd  = iwidth  + 2 * PAD;  /* window width */
      wsywd  = iheight + 2 * PAD;  /* window height */
      wsxmnz = PAD + offx;                /* lower-left  corner */
      wsymnz = PAD + offy;                /* lower-left  corner */
#ifndef WINDOWS
      drawing_area = zggdrw_(width,height);
#else
      drawing_area = ZGGDRW(width,height);
#endif
    }
  }else if (idev_type == IWS_FILE){
    if(ifl == IFL_EPS || ifl == IFL_PDF){
    wsywd = iPS_PAGE_WIDTH * ddvscale;
    wsxwd = iPS_PAGE_HEIGHT * ddvscale;
    wsymnz = offx * ddvscale;
    wsxmnz = offy * ddvscale;
    }else if(ifl == IFL_PNG || ifl == IFL_SVG ){
    wsxwd  = iwidth  + 2 * PAD;  /* window width */
    wsywd  = iheight + 2 * PAD;  /* window height */
    wsxmnz = PAD + offx;                /* lower-left  corner */
    wsymnz = PAD + offy;                /* lower-left  corner */
    }
  }
#ifdef WINDOWS
 if (pngstdout){
   _setmode(_fileno(stdout),_O_BINARY);
 }
#endif

  /* read colormap file */

  cfnchr(cmapz, clrmap, 79);
  if ((stream = fopen(cmapz, "r")) == NULL) {
    fprintf(stderr, "*** Error in zgdopn : ");
    fprintf(stderr,
	    "Allocation failed for colormap (%s).\n", cmapz);
    exit (1);
  }

  fscanret=fscanf(stream, "%d : %s", &ncolor, c);
  for (n = 0; n < ncolor; n++)
    fscanret=fscanf(stream, "%6hd%6hd%6hd : %s", &rx[n], &gx[n], &bx[n], c);
  fclose(stream);

  if (fgbg) {
    rx1 = rx[0];
    gx1 = gx[0];
    bx1 = bx[0];
    rx[0] = rx[1];
    gx[0] = gx[1];
    bx[0] = bx[1];
    rx[1] = rx1;
    gx[1] = gx1;
    bx[1] = bx1;
  }

  /* read bitmap file */

  cfnchr (bmapz, cbmmap, 79);

  if ((stream = fopen(bmapz, "r")) == NULL) {
    fprintf(stderr, "*** Error in zgdopn : ");
    fprintf(stderr,
	     "Allocation failed for bitmap (%s).\n", bmapz);
    exit (1);
  }

  fscanret=fscanf(stream, "%d", &nbmap);
  for (n = 0; n < nbmap; n++)
    fscanret=fscanf(stream, "%4d%4d%3d%3d%s",
	   &nn1[n], &nn2[n], &nx[n], &ny[n], bmline[n]);
  fclose(stream);

  /* set colormap */
  for (n = 0; n < MAXCLI; n++) {

      m = n % ncolor;

      cx[n].red   = rx[m];
      cx[n].green = gx[m];
      cx[n].blue  = bx[m];
  }

  if (ldclonly) {

    cr =zgcsfc();
#if GTKVERSION==2
    zgupdate(0);
#else
    zgupdate(0,cr);
#endif
    if (wait_op) {
      next = FALSE;
      ifunc = DOPN;
      while (1) {
        gtk_main_iteration();
      	if (next)
	      break;
      }
    }

  }else{
     cr =zgcsfc();
  }

  if (idev_type == IWS_FILE && ifl == IFL_PDF){
    zgcatl();
}

  rt1 = (double) cx[0].red   / 65535 ;
  gt1 = (double) cx[0].green / 65535 ;
  bt1 = (double) cx[0].blue  / 65535 ;
  cairo_set_source_rgb(cr,rt1,gt1,bt1);

  if (idev_type == IWS_DISP){
    cairo_destroy(cr);
    cairo_surface_destroy (csr);
  }else if (idev_type == IWS_FILE){
    if(ifl==IFL_PNG ){
      cairo_destroy(cr);
      cairo_surface_destroy (csr);
    }
  }

  return;
}

#ifndef WINDOWS
void zgdcls_(void)
#else
void ZGDCLS(void)
#endif
{
  /* device closing proc. */

  GdkEvent *ev;
  if (ldclonly) {
    if (!wait_np && wait_cl) {
      next = FALSE;
      ifunc = DCLS;
      while (1) {
        gtk_main_iteration();
        if (next) break;
      }
    }
  }
  if (idev_type == IWS_FILE){
    if(ifl==IFL_PNG || ifl==IFL_EPS || ifl == IFL_SVG ){
    }else if (ifl == IFL_PDF){
      if(!sep){
        cairo_destroy(cr);
        cairo_surface_finish (csr);
        cairo_surface_destroy (csr);
      }
    }
 }

}

/*------------------------- page --------------------------*/

#ifndef WINDOWS
void zgpopn_(void)
#else
void ZGPOPN(void)
#endif
{
  cairo_t *cro;
  double rt1,gt1,bt1;
  char cout[64];

  /* background drawing proc. */
  ++page;
  lpage=TRUE;

  pactive=1;

  iwdidz = 1;
  iclidz = 1;

   if (idev_type == IWS_DISP){
     cr=zgcsfc();
     cro = cairo_create(csr);
   }else if (idev_type == IWS_FILE){
     if(ifl==IFL_EPS){
       cr=zgcsfc();
       cro = cairo_create(csr);
     }else if(ifl ==IFL_PNG){
       cr=zgcsfc();
       cro = cairo_create(csr);
     }else if(ifl ==IFL_SVG){
       cr=zgcsfc();
       cro = cairo_create(csr);
     }else if (ifl == IFL_PDF){
       if(sep){
         cr=zgcsfc();
         zgcatl();
       }
       cro = cairo_create(csr);
     }
  }

  rt1 =(double) cx[0].red   / 65535;
  gt1 =(double) cx[0].green / 65535;
  bt1 =(double) cx[0].blue  / 65535;

  cairo_set_source_rgb(cro,rt1,gt1,bt1);

  if (idev_type == IWS_DISP || ( idev_type == IWS_FILE && ifl == IFL_PNG)){
     cairo_rectangle(cro,0.0,0.0,wsxwd,wsywd);
     cairo_fill(cro);
     if(!laltz){
#if GTKVERSION==2
    zgupdate(0);
#else
    zgupdate(0,cro);
#endif
    }
  }

  cairo_destroy(cro);

}

#ifndef WINDOWS
void zgpcls_(void)
#else
void ZGPCLS(void)
#endif
{

  /* event loop */

  char cout[64];

  char* opt_key[2];
  char* opt_val[2];

  char cnum[4];

  if (ldclonly) {
    if(lpage){
#if GTKVERSION==2
      zgupdate(0);
#else
      zgupdate(0,cr);
      gtk_widget_queue_draw(drawing_area);
      gtk_main_iteration();
#endif
    }
    if (wait_np) {
      dumpz = FALSE;
      next = FALSE;
      ifunc = PCLS;
      while (1) {
    	gtk_main_iteration();
      	if (next)
	       break;
        }
      }
      if (dump || dumpz) {
        sprintf (cout, "%s_%0*d.%s", dmpfile,dmpdgt, page, imgfmt);
        opt_key[0] = NULL;
        opt_key[1] = NULL;
        if (imgcmp>=0.0 && imgcmp<=1.0) {
	        if (strcmp(imgfmt, "png")==0) {
	           opt_key[0] = "compression";
             sprintf(cnum, "%d", (int)(imgcmp*9));
	          opt_val[0] = cnum;
	         } else if (strcmp(imgfmt, "jpeg")==0) {
	            opt_key[0] = "quality";
	            sprintf(cnum, "%d", (int)((1-imgcmp)*100));
	            opt_val[0] = cnum;
	           }
         } else if (imgcmp>1.0) {
	            fprintf(stderr, " *** Error in zgdopn : ");
	            fprintf(stderr,	"Image compression must be 0-1.\n");
         }
        cairo_surface_write_to_png(csr,cout);
      }
      if(lpage){
        cairo_destroy(cr);
        cairo_surface_destroy(csr);
      }
      lpage=FALSE;
    }
  if ( idev_type == IWS_FILE && pactive){
    if(ifl==IFL_EPS || ifl == IFL_SVG){
      cairo_surface_show_page (csr);
      cairo_destroy(cr);
      cairo_surface_destroy(csr);

    }else if(ifl==IFL_PNG){
      if(pngstdout){
        cairo_surface_write_to_png_stream(csr,png2stdout,stdout);
      }else{
        sprintf (cout, "%s_%0*d.%s", dmpfile,dmpdgt, page, imgfmt);
        opt_key[0] = NULL;
        opt_key[1] = NULL;
        if (imgcmp>=0.0 && imgcmp<=1.0) {
          if (strcmp(imgfmt, "png")==0) {
            opt_key[0] = "compression";
            sprintf(cnum, "%d", (int)(imgcmp*9));
            opt_val[0] = cnum;
          }else if (strcmp(imgfmt, "jpeg")==0){
            opt_key[0] = "quality";
            sprintf(cnum, "%d", (int)((1-imgcmp)*100));
            opt_val[0] = cnum;
          }
        }else if (imgcmp>1.0) {
          fprintf(stderr, " *** Error in zgdopn : ");
          fprintf(stderr,"Image compression must be 0-1.\n");
        }
        cairo_surface_write_to_png(csr,cout);
      }
      cairo_destroy(cr);
      cairo_surface_destroy(csr);
    }else if ( ifl == IFL_PDF){
        cairo_show_page (cr);
        if( sep ){
          cairo_destroy(cr);
          cairo_surface_destroy(csr);
        }
    }
  }
  pactive=0;
}

#ifndef WINDOWS
void zgflash_()
#else
void ZGFLASH()
#endif
{
    irxt=0;
    irxb=0;
    iryt=0;
    iryb=0;
#if GTKVERSION==2
    zgupdate(0);
#else
    zgupdate(0,cr);
#endif

}

/*------------------------- object ------------------------*/

#ifndef WINDOWS
void zgoopn_(char *objname, char *comment)
#else
void ZGOOPN(char *objname, char *comment)
#endif
{
  /* for long-type message? */
}

#ifndef WINDOWS
void zgocls_(char *objname)
#else
void ZGOCLS(char *objname)
#endif
{
  if (!laltz){
#if GTKVERSION==2
    zgupdate(1);
#else
    zgupdate(1,cr);
#endif

}

  /* for long-type message? */
}

/*------------------------- line --------------------------*/

#ifndef WINDOWS
void zgswdi_(DCL_INT *iwdidx)
#else
void ZGSWDI(DCL_INT *iwdidx)
#endif
{

  /* set line width index */

  iwdidz = *iwdidx % 10;
  if (iwdidz == 0) iwdidz = 1;

  irwidth = iwdidz;
}

#ifndef WINDOWS
void zgscli_(DCL_INT *iclidx)
#else
void ZGSCLI(DCL_INT *iclidx)
#endif
{
  /* set line color index */
  double rt1,gt1,bt1;

  if (!lfcmod){

  if (*iclidx == ibgcli) {
    iclidz=0;
  }else{
    iclidz = *iclidx % MAXCLI;
  }

  if(*iclidx==ifcidx){
    rt1=rl2;
    gt1=gl2;
    bt1=bl2;
  }else{
    rt1 = (double) cx[iclidz].red   / 65535;
    gt1 = (double) cx[iclidz].green / 65535;
    bt1 = (double) cx[iclidz].blue  / 65535;
  }
  cairo_set_source_rgb(cr,rt1,gt1,bt1);
  }
/*if (iclidz == 0)
    iclidz = 1; */
}

#ifndef WINDOWS
void zggopn_(void)
#else
void ZGGOPN(void)
#endif
{

  /* open graphic segment */

  cairo_set_line_width(cr,linewidth[iwdidz-1]*dlnscale);
  cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);
  cairo_set_line_join(cr,CAIRO_LINE_JOIN_BEVEL);
}

#ifndef WINDOWS
void zggmov_(DCL_REAL *wx, DCL_REAL *wy)
#else
void ZGGMOV(DCL_REAL *wx, DCL_REAL *wy)
#endif
{
  DCL_REAL rwx, rwy;

#ifndef WINDOWS
  zgfrel_( wx, wy, &rwx, &rwy );
#else
  ZGFREL( wx, wy, &rwx, &rwy );
#endif

  /* pen-up move */
  cairo_move_to(cr,(double)rwx,(double)rwy);

  rwxold = *wx;
  rwyold = *wy;
  zguprect(rwx,rwy);
}


int utf8_char_byte(char* s){
  if ((s[0] & 0x80)==0) { /* 1 byte char */
    return 1;
  }else if((s[0] & 0xe0)==0xc0 && /* 2 byte char */
           (s[1] & 0xc0)==0x80 ){
    return 2;
  }else if((s[0] & 0xf0)==0xe0 && /* 3 byte char */
           (s[1] & 0xc0)==0x80 &&
           (s[2] & 0xc0)==0x80 ){
    return  3;
  }else if((s[0] & 0xf8)==0xf0 && /* 4 byte char */
           (s[1] & 0xc0)==0x80 &&
           (s[2] & 0xc0)==0x80 &&
           (s[3] & 0xc0)==0x80 ){
    return 4;
  }else{
    return 0;
  }
}

int char_width(char* string, int len){
	PangoLayout *layout;
	PangoRectangle ink_rect, logical_rect;

	layout = pango_cairo_create_layout(cr);
  pango_layout_set_text(layout, string, len);
	pango_layout_set_font_description(layout, font_desc);
	pango_cairo_update_layout(cr, layout);
  pango_layout_get_extents (layout, &ink_rect, &logical_rect);
	g_object_unref(layout);
  return logical_rect.width;
}

int char_height(char* string, int len){
	PangoLayout *layout;
	PangoRectangle ink_rect, logical_rect;

	layout = pango_cairo_create_layout(cr);
  pango_layout_set_text(layout, string, len);
	pango_layout_set_font_description(layout, font_desc);
	pango_cairo_update_layout(cr, layout);
  pango_layout_get_extents (layout, &ink_rect, &logical_rect);
	g_object_unref(layout);
  return ink_rect.height;
}



void get_pangostring_width_height(cairo_t *cr, char* string, double *width, double *height){
	PangoLayout *layout;
	PangoRectangle ink_rect, logical_rect;
	double w0, w1;
	int len, i;

	layout = pango_cairo_create_layout(cr);
  pango_layout_set_markup(layout, string, -1); /* interpret markup */
  //pango_layout_set_text(layout, string, -1); /* ignore markup */

	pango_layout_set_font_description(layout, font_desc);
	pango_cairo_update_layout(cr, layout);

  pango_layout_get_extents (layout, &ink_rect, &logical_rect);
  *width = (double)logical_rect.width / (double)PANGO_SCALE ;

  /* height を以下のどちらで取る方が見た目が良いかは、フォントに依存する */
  *height = (double)logical_rect.height / (double)PANGO_SCALE ;
//  *height = (double)pango_layout_get_baseline(layout) / (double)PANGO_SCALE;


	g_object_unref(layout);
}


void dcltext2pangomarkup(char* text, int textlength, char* string, double fontsize){
  int i, j, k, l, b, ii ;
  int length = 0;
  int char_byte;
  int sub_rise, sup_rise;
  char sub_span[128] = {0}, sup_span[128]={0};
  char over_span[128]={0};
  char dclextchar[2048];
  int sw, cw0, cw1, wdiff, height, weight;
  int prev_byte = 0, prev_pos = 0;
  int flag_close = -1, flag_allow_user_pangomarkup = 0, flag_inspan = 0;
  int flag_dclextchar = 0;

  sg_small = getrparm("small");
  sg_shift = getrparm("shift");
/*  sg_isup = getiparm("isup");
  sg_isub = getiparm("isub");
  sg_irst = getiparm("irst");*/
  sg_isup = 29;
  sg_isub = 30;
  sg_irst = 31;
  sg_lcntl = getlparm("lcntl");

/* calculate rise amount for super-/sub-script from fontsize that in PangoUnits
   and set as a part of markup text */
  sup_rise = (int) (fontsize*(0.5 + sg_shift - 0.5*sg_small));
  sub_rise = (int) (fontsize*(0.5 - sg_shift - 0.5*sg_small));

  sprintf(sup_span,"<span size='%d' rise='%d'>", (int)(sg_small*fontsize), sup_rise );
  sprintf(sub_span,"<span size='%d' rise='%d'>", (int)(sg_small*fontsize), sub_rise );

  j=0;
  for (i=0;i<textlength;i++){
    if (text[i] == 92){
      if(text[i+1] == 120){
        flag_dclextchar=1;
        i=i+2;
      }else{
        flag_dclextchar=0;
      }
    }else{
      flag_dclextchar=0;
    }
    if(flag_dclextchar){


              /* マーカーの処理 */
              if ( (0 < text[i] && text[i] < 32) ||
                   (226 < text[i]+256 && text[i]+256 < 231)){ /* for Marker */
                //strcpy(&dclextchar[j], "\\s"); j += strlen("\\s");
                weight = pango_font_description_get_weight (font_desc);
                if (weight <= 200){
                  strcpy(&dclextchar[j], "\\L"); j += strlen("\\L");
                }else if (weight <= 400){
                  strcpy(&dclextchar[j], "\\R"); j += strlen("\\R");
                }else if(weight <= 600){
                  strcpy(&dclextchar[j], "\\B"); j += strlen("\\B");
                }else{
                  strcpy(&dclextchar[j], "\\K"); j += strlen("\\K");
                }
//                strcpy(&dclextchar[j], "\\E"); j += strlen("\\E");

                switch(text[i]){
                  case 1:
                    strcpy(&dclextchar[j], "・"); j += strlen("・"); break;
                  case 2:
                    strcpy(&dclextchar[j], "＋"); j += strlen("＋"); break;
                  case 3:
                    strcpy(&dclextchar[j], "＊"); j += strlen("＊"); break;
                  case 4:
                    strcpy(&dclextchar[j], "○"); j += strlen("○"); break;
                  case 5:
                    strcpy(&dclextchar[j], "×"); j += strlen("×"); break;
                  case 6:
                    strcpy(&dclextchar[j], "□"); j += strlen("□"); break;
                  case 7:
                    strcpy(&dclextchar[j], "△"); j += strlen("△"); break;
                  case 8:
                    strcpy(&dclextchar[j], "◇"); j += strlen("◇"); break;
                  case 9:
                    strcpy(&dclextchar[j], "☆"); j += strlen("☆"); break;
                  case 10:
                    strcpy(&dclextchar[j], "●"); j += strlen("●"); break;
                  case 11:
                    strcpy(&dclextchar[j], "■"); j += strlen("■"); break;
                  case 12:
                    strcpy(&dclextchar[j], "▲"); j += strlen("▲"); break;
                  case 13:
                    strcpy(&dclextchar[j], "◀"); j += strlen("◀"); break;
                  case 14:
                    strcpy(&dclextchar[j], "▼"); j += strlen("▼"); break;
                  case 15:
                    strcpy(&dclextchar[j], "▶"); j += strlen("▶"); break;
                  case 16:
                    strcpy(&dclextchar[j], "★"); j += strlen("★"); break;
                  case 17:
                    strcpy(&dclextchar[j], "⚑"); j += strlen("⚑"); break;
                  case 18:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 19:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 20:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 21:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 22:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 23:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 24:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 25:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 26:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 27:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 28:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 29:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 30:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                  case 31:
                    strcpy(&dclextchar[j], " "); j += strlen(" "); break;
                }
                switch(text[i]+256){
                  case 227:
                    strcpy(&dclextchar[j], "②"); j += strlen("②"); break;
                  case 228:
                    strcpy(&dclextchar[j], "○"); j += strlen("○"); break;
                  case 229:
                    strcpy(&dclextchar[j], "③"); j += strlen("③"); break;
                  case 230:
                    strcpy(&dclextchar[j], "①"); j += strlen("①"); break;
                  }

//                strcpy(&dclextchar[j], "\\e"); j += strlen("\\e");
                continue;
              }








      switch(text[i]+256){
      case 128:
        strcpy(&dclextchar[j], "Α"); j += strlen("Α"); break;
      case 129:
        strcpy(&dclextchar[j], "Β"); j += strlen("Β"); break;
      case 130:
        strcpy(&dclextchar[j], "Γ"); j += strlen("Γ"); break;
      case 131:
        strcpy(&dclextchar[j], "Δ"); j += strlen("Δ"); break;
      case 132:
        strcpy(&dclextchar[j], "Ε"); j += strlen("Ε"); break;
      case 133:
        strcpy(&dclextchar[j], "Ζ"); j += strlen("Ζ"); break;
      case 134:
        strcpy(&dclextchar[j], "Η"); j += strlen("Η"); break;
      case 135:
        strcpy(&dclextchar[j], "Θ"); j += strlen("Θ"); break;
      case 136:
        strcpy(&dclextchar[j], "Ι"); j += strlen("Ι"); break;
      case 137:
        strcpy(&dclextchar[j], "Κ"); j += strlen("Κ"); break;
      case 138:
        strcpy(&dclextchar[j], "Λ"); j += strlen("Λ"); break;
      case 139:
        strcpy(&dclextchar[j], "Μ"); j += strlen("Μ"); break;
      case 140:
        strcpy(&dclextchar[j], "Ν"); j += strlen("Ν"); break;
      case 141:
        strcpy(&dclextchar[j], "Ξ"); j += strlen("Ξ"); break;
      case 142:
        strcpy(&dclextchar[j], "Ο"); j += strlen("Ο"); break;
      case 143:
        strcpy(&dclextchar[j], "Π"); j += strlen("Π"); break;
      case 144:
        strcpy(&dclextchar[j], "Ρ"); j += strlen("Ρ"); break;
      case 145:
        strcpy(&dclextchar[j], "Σ"); j += strlen("Σ"); break;
      case 146:
        strcpy(&dclextchar[j], "Τ"); j += strlen("Τ"); break;
      case 147:
        strcpy(&dclextchar[j], "Υ"); j += strlen("Υ"); break;
      case 148:
        strcpy(&dclextchar[j], "Φ"); j += strlen("Φ"); break;
      case 149:
        strcpy(&dclextchar[j], "Χ"); j += strlen("Χ"); break;
      case 150:
        strcpy(&dclextchar[j], "Ψ"); j += strlen("Ψ"); break;
      case 151:
        strcpy(&dclextchar[j], "Ω"); j += strlen("Ω"); break;
      case 152:
        strcpy(&dclextchar[j], "α"); j += strlen("α"); break;
      case 153:
        strcpy(&dclextchar[j], "β"); j += strlen("β"); break;
      case 154:
        strcpy(&dclextchar[j], "γ"); j += strlen("γ"); break;
      case 155:
        strcpy(&dclextchar[j], "δ"); j += strlen("δ"); break;
      case 156:
        strcpy(&dclextchar[j], "ε"); j += strlen("ε"); break;
      case 157:
        strcpy(&dclextchar[j], "ζ"); j += strlen("ζ"); break;
      case 158:
        strcpy(&dclextchar[j], "η"); j += strlen("η"); break;
      case 159:
        strcpy(&dclextchar[j], "θ"); j += strlen("θ"); break;
      case 160:
        strcpy(&dclextchar[j], "ι"); j += strlen("ι"); break;
      case 161:
        strcpy(&dclextchar[j], "κ"); j += strlen("κ"); break;
      case 162:
        strcpy(&dclextchar[j], "λ"); j += strlen("λ"); break;
      case 163:
        strcpy(&dclextchar[j], "μ"); j += strlen("μ"); break;
      case 164:
        strcpy(&dclextchar[j], "ν"); j += strlen("ν"); break;
      case 165:
        strcpy(&dclextchar[j], "ξ"); j += strlen("ξ"); break;
      case 166:
        strcpy(&dclextchar[j], "ο"); j += strlen("ο"); break;
      case 167:
        strcpy(&dclextchar[j], "π"); j += strlen("π"); break;
      case 168:
        strcpy(&dclextchar[j], "ρ"); j += strlen("ρ"); break;
      case 169:
        strcpy(&dclextchar[j], "σ"); j += strlen("σ"); break;
      case 170:
        strcpy(&dclextchar[j], "τ"); j += strlen("τ"); break;
      case 171:
        strcpy(&dclextchar[j], "υ"); j += strlen("υ"); break;
      case 172:
        strcpy(&dclextchar[j], "φ"); j += strlen("φ"); break;
      case 173:
        strcpy(&dclextchar[j], "χ"); j += strlen("χ"); break;
      case 174:
        strcpy(&dclextchar[j], "ψ"); j += strlen("ψ"); break;
      case 175:
        strcpy(&dclextchar[j], "ω"); j += strlen("ω"); break;
      case 177:
        strcpy(&dclextchar[j], "‘"); j += strlen("‘"); break;
      case 178:
        strcpy(&dclextchar[j], "’"); j += strlen("’"); break;
      case 179:
        strcpy(&dclextchar[j], "→"); j += strlen("→"); break;
      case 180:
        strcpy(&dclextchar[j], "↑"); j += strlen("↑"); break;
      case 181:
        strcpy(&dclextchar[j], "←"); j += strlen("←"); break;
      case 182:
        strcpy(&dclextchar[j], "↓"); j += strlen("↓"); break;
      case 183:
        strcpy(&dclextchar[j], "‖"); j += strlen("‖"); break;
      case 184:
        strcpy(&dclextchar[j], "⊥"); j += strlen("⊥"); break;
      case 185:
        strcpy(&dclextchar[j], "∠"); j += strlen("∠"); break;
      case 186:
        strcpy(&dclextchar[j], "∴"); j += strlen("∴"); break;
      case 187:
        strcpy(&dclextchar[j], " "); j += strlen(" "); break;
      case 188:
        strcpy(&dclextchar[j], "∾"); j += strlen("∾"); break;
      case 189:
        strcpy(&dclextchar[j], "∞"); j += strlen("∞"); break;
      case 190:
        strcpy(&dclextchar[j], "−"); j += strlen("−"); break;
      case 191:
        strcpy(&dclextchar[j], "+"); j += strlen("+"); break;
      case 192:
        strcpy(&dclextchar[j], "±"); j += strlen("±"); break;
      case 193:
        strcpy(&dclextchar[j], "∓"); j += strlen("∓"); break;
      case 194:
        strcpy(&dclextchar[j], "×"); j += strlen("×"); break;
      case 195:
        strcpy(&dclextchar[j], "∙"); j += strlen("∙"); break;
      case 196:
        strcpy(&dclextchar[j], "÷"); j += strlen("÷"); break;
      case 197:
        strcpy(&dclextchar[j], "="); j += strlen("="); break;
      case 198:
        strcpy(&dclextchar[j], "≠"); j += strlen("≠"); break;
      case 199:
        strcpy(&dclextchar[j], "≡"); j += strlen("≡"); break;
      case 200:
        strcpy(&dclextchar[j], "＜"); j += strlen("＜"); break;
      case 201:
        strcpy(&dclextchar[j], "＞"); j += strlen("＞"); break;
      case 202:
        strcpy(&dclextchar[j], "≦"); j += strlen("≦"); break;
      case 203:
        strcpy(&dclextchar[j], "≧"); j += strlen("≧"); break;
      case 204:
        strcpy(&dclextchar[j], "∝"); j += strlen("∝"); break;
      case 205:
        strcpy(&dclextchar[j], "∼"); j += strlen("∼"); break;
      case 206:
        strcpy(&dclextchar[j], "^"); j += strlen("^"); break;
      case 207:
        strcpy(&dclextchar[j], "´"); j += strlen("´"); break;
      case 208:
        strcpy(&dclextchar[j], "`"); j += strlen("`"); break;
      case 209:
        strcpy(&dclextchar[j], "⏝"); j += strlen("⏝"); break;
      case 210:
        strcpy(&dclextchar[j], "√"); j += strlen("√"); break;
      case 211:
        strcpy(&dclextchar[j], "⊂"); j += strlen("⊂"); break;
      case 212:
        strcpy(&dclextchar[j], "∪"); j += strlen("∪"); break;
      case 213:
        strcpy(&dclextchar[j], "⊃"); j += strlen("⊃"); break;
      case 214:
        strcpy(&dclextchar[j], "∩"); j += strlen("∩"); break;
      case 215:
        strcpy(&dclextchar[j], "∈"); j += strlen("∈"); break;
      case 216:
        strcpy(&dclextchar[j], "∂"); j += strlen("∂"); break;
      case 217:
        strcpy(&dclextchar[j], "∇"); j += strlen("∇"); break;
      case 218:
        strcpy(&dclextchar[j], "∫"); j += strlen("∫"); break;
      case 219:
        strcpy(&dclextchar[j], "∮"); j += strlen("∮"); break;
      case 224:
        strcpy(&dclextchar[j], "‰"); j += strlen("‰"); break;
      case 225:
        strcpy(&dclextchar[j], "Å"); j += strlen("Å"); break;
      case 226:
        strcpy(&dclextchar[j], "ℏ"); j += strlen("ℏ"); break;
      case 227:
        strcpy(&dclextchar[j], " "); j += strlen(" "); break;
      case 228:
        strcpy(&dclextchar[j], "○"); j += strlen("○"); break;
      case 229:
        strcpy(&dclextchar[j], " "); j += strlen(" "); break;
      case 230:
        strcpy(&dclextchar[j], " "); j += strlen(" "); break;
      case 240:
        strcpy(&dclextchar[j], "𝜖"); j += strlen("𝜖"); break;
      case 241:
        strcpy(&dclextchar[j], "𝜗"); j += strlen("𝜗"); break;
      case 242:
        strcpy(&dclextchar[j], "𝜛"); j += strlen("𝜛"); break;
      case 243:
        strcpy(&dclextchar[j], "𝜚"); j += strlen("𝜚"); break;
      case 244:
        strcpy(&dclextchar[j], "ς"); j += strlen("ς"); break;
      case 245:
        strcpy(&dclextchar[j], "𝜙"); j += strlen("𝜙"); break;
      case 246:
        strcpy(&dclextchar[j], "‐"); j += strlen("‐"); break;
      case 247:
        strcpy(&dclextchar[j], "-"); j += strlen("–"); break;
      case 248:
        strcpy(&dclextchar[j], "—"); j += strlen("—"); break;
      default:
        dclextchar[j]=text[i];j++;
      }
    }else{ // !flag_dclextchar
      dclextchar[j]=text[i];j++;
    }
  }
  for(i=j;i<textlength;i++){
    dclextchar[i]=' ';
  }
  textlength=j;

/* store and convert chracters of texts */
  for (i=0;i<textlength;i++){

    char_byte = utf8_char_byte(&dclextchar[i]);

    if (0){ /* 従来のDCL書式 */
      /* 制御文字をmarkup tagに。 */
/*      else if(dclextchar[i] == 36){ // 暫定 $ で over を表現
        sw = char_width(" ", -1);
        cw0 = char_width(&dclextchar[prev_pos], prev_byte);
        cw1 = char_width(&dclextchar[i+1], utf8_char_byte(&dclextchar[i+1]));
        if (dclextchar[i+1]==45) {cw1 = char_width("−", -1);}
        wdiff = cw0 - cw1 ;
        height = char_height(&dclextchar[prev_pos], prev_byte);
        sprintf(over_span,"<span letter_spacing='%d'> </span><span rise='%d' letter_spacing='%d'>",
                -(cw0+sw), (int)(height*0.8), wdiff);
        strcpy(&string[length], over_span); length += strlen(over_span); continue;*/



    }else{ /* 新しい書式 */
      if (dclextchar[i] == sg_isup){ /* 上付き開始 */
        strcpy(&string[length], sup_span); length += strlen(sup_span); continue;
      }else if(dclextchar[i] == sg_isub){ /* 下付き開始 */
        strcpy(&string[length], sub_span); length += strlen(sub_span); continue;
      }else if(dclextchar[i] == sg_irst){ /* span終了 */
        strcpy(&string[length], "</span>"); length += strlen("</span>"); continue;
      }
      if (dclextchar[i] == 92){ /* 92 は バックスラッシュ（制御の始まり） */
        flag_inspan += 1;
        if (flag_close == i){ /* } がない場合の制御終了処理 */
          strcpy(&string[length], "</span>"); length += strlen("</span>");
          flag_inspan -= 1;
        }
        if (dclextchar[i+1] == 94 ){ /* 94 は ハット （上付き文字）*/
          strcpy(&string[length], sup_span); length += strlen(sup_span);
        }else if(dclextchar[i+1] == 95){ /* 95 はアンダースコア（下付き文字）*/
          strcpy(&string[length], sub_span); length += strlen(sub_span);
        }else if(dclextchar[i+1] == 76){ /* 76 は L*/
          strcpy(&string[length], "<span font_desc='DCLMarker Light'>"); length += strlen("<span font_desc='DCLMarker Light'>");
        }else if(dclextchar[i+1] == 82){ /* 82 は R*/
          strcpy(&string[length], "<span font_desc='DCLMarker Regular'>"); length += strlen("<span font_desc='DCLMarker Regular'>");
        }else if(dclextchar[i+1] == 66){ /* 66 は B*/
          strcpy(&string[length], "<span font_desc='DCLMarker Bold'>"); length += strlen("<span font_desc='DCLMarker Bold'>");
        }else if(dclextchar[i+1] == 75){ /* 75 は K*/
          strcpy(&string[length], "<span font_desc='DCLMarker Black'>"); length += strlen("<span font_desc='DCLMarker Black'>");
        }else if(dclextchar[i+1] == 111 || dclextchar[i+1] == 117){ /* 111 は o（over）, 117は u (under)*/
          sw = char_width(" ", -1);
          cw0 = char_width(&dclextchar[prev_pos], prev_byte);
          if (dclextchar[i+2]==123){
            cw1 = char_width(&dclextchar[i+3], utf8_char_byte(&dclextchar[i+3]));
            if (dclextchar[i+3]==45) {cw1 = char_width("−", -1);}
          }else{
            cw1 = char_width(&dclextchar[i+2], utf8_char_byte(&dclextchar[i+2]));
            if (dclextchar[i+2]==45) {cw1 = char_width("−", -1);}
          }
          wdiff = cw0 - cw1 ;
          height = char_height(&dclextchar[prev_pos], prev_byte);
          if (dclextchar[i+1] == 111){
            sprintf(over_span,"<span letter_spacing='%d'> </span><span rise='%d' letter_spacing='%d'>",
                    -(cw0+sw), (int)(height*0.75), wdiff);
          }else{
            sprintf(over_span,"<span letter_spacing='%d'> </span><span rise='%d' letter_spacing='%d'>",
                    -(cw0+sw), (int)(-char_height("I", 1)*0.65), wdiff);
          }
          strcpy(&string[length], over_span); length += strlen(over_span);

        }else if(dclextchar[i+1] == 112 && dclextchar[i+2] == 123){ /* 112 は p (pango markupを許可開始)*/
          flag_allow_user_pangomarkup = 1; i+= 2; continue;

        }else if(dclextchar[i+1] == 92){ /* バックスラッシュの表示 */
          strcpy(&string[length], "\\"); length += strlen("\\"); i++; flag_inspan = 0;
          continue;
        }else{ /* 制御記号に該当しない場合もバックスラッシュを表示　*/
          strcpy(&string[length], "\\"); length += strlen("\\"); flag_inspan = 0;
          continue;
        }
        if (dclextchar[i+2] == 123){ /* { が続く場合 */
          i+=2; continue;
        }else if(dclextchar[i+2] != 60 && dclextchar[i+2] != '\'') { /* { がない場合は一文字のみ対応 */
          flag_close = i+2+utf8_char_byte(&dclextchar[i+2]); /* 終了場所を示すフラグを立てる */
          i++; continue;
        }
      }else if (flag_close == i){ /* } がない場合の制御終了処理 */
        for(ii=0;ii<flag_inspan;ii++){
          strcpy(&string[length], "</span>"); length += strlen("</span>");
        }
        flag_inspan = 0;
      }else if (dclextchar[i] == 125 && !flag_allow_user_pangomarkup && flag_inspan){ /* } で制御終了処理 */
        for(ii=0;ii<flag_inspan;ii++){
          strcpy(&string[length], "</span>"); length += strlen("</span>");
        }
        flag_inspan = 0; continue;
      }else if (dclextchar[i] == 125 && flag_allow_user_pangomarkup){ /* } で制御終了処理（markup許可終了） */
        flag_allow_user_pangomarkup = 0; flag_inspan = 0; continue;

      }
    }

    if (char_byte < 2){
      /* マーカーの処理 */
      if ( (0 < dclextchar[i] && dclextchar[i] < 18) ||
           (226 < dclextchar[i]+256 && dclextchar[i]+256 < 231)){ /* for Marker */
        strcpy(&string[length], "<span font_desc='DCLMarker "); length += strlen("<span font_desc='DCLMarker ");
        weight = pango_font_description_get_weight (font_desc);
        if (weight <= 200){
          strcpy(&string[length], "Light"); length += strlen("Light");
        }else if (weight <= 400){
          strcpy(&string[length], "Regular"); length += strlen("Regular");
        }else if(weight <= 600){
          strcpy(&string[length], "Bold"); length += strlen("Bold");
        }else{
          strcpy(&string[length], "Black"); length += strlen("Black");
        }
        strcpy(&string[length], "'>"); length += strlen("'>");

        switch(dclextchar[i]){
          case 1:
            strcpy(&string[length], "・"); length += strlen("・"); break;
          case 2:
            strcpy(&string[length], "＋"); length += strlen("＋"); break;
          case 3:
            strcpy(&string[length], "＊"); length += strlen("＊"); break;
          case 4:
            strcpy(&string[length], "○"); length += strlen("○"); break;
          case 5:
            strcpy(&string[length], "×"); length += strlen("×"); break;
          case 6:
            strcpy(&string[length], "□"); length += strlen("□"); break;
          case 7:
            strcpy(&string[length], "△"); length += strlen("△"); break;
          case 8:
            strcpy(&string[length], "◇"); length += strlen("◇"); break;
          case 9:
            strcpy(&string[length], "☆"); length += strlen("☆"); break;
          case 10:
            strcpy(&string[length], "●"); length += strlen("●"); break;
          case 11:
            strcpy(&string[length], "■"); length += strlen("■"); break;
          case 12:
            strcpy(&string[length], "▲"); length += strlen("▲"); break;
          case 13:
            strcpy(&string[length], "◀"); length += strlen("◀"); break;
          case 14:
            strcpy(&string[length], "▼"); length += strlen("▼"); break;
          case 15:
            strcpy(&string[length], "▶"); length += strlen("▶"); break;
          case 16:
            strcpy(&string[length], "★"); length += strlen("★"); break;
          case 17:
            strcpy(&string[length], "⚑"); length += strlen("⚑"); break;
          }
        switch(dclextchar[i]+256){
          case 227:
            strcpy(&string[length], "②"); length += strlen("②"); break;
          case 228:
            strcpy(&string[length], "○"); length += strlen("○"); break;
          case 229:
            strcpy(&string[length], "③"); length += strlen("③"); break;
          case 230:
            strcpy(&string[length], "①"); length += strlen("①"); break;
          }

        strcpy(&string[length], "</span>"); length += strlen("</span>");
        continue;
      }

      /* マーカー以外 */
      /* replace "hyphenminus" to "minus" */
      if (dclextchar[i] == 45){
        strcpy(&string[length], "−"); length += strlen("−"); continue;
      }
      /* escape &, <, > for markup */
      if(dclextchar[i] == 38 &&  !flag_allow_user_pangomarkup){ /* & */
        strcpy(&string[length], "&amp;"); length += strlen("&amp;"); continue;
      }else if(dclextchar[i] == 60 && !flag_allow_user_pangomarkup){ /* < */
        strcpy(&string[length], "&#60;"); length += strlen("&#60;"); continue;
      }else if(dclextchar[i] == 62 && !flag_allow_user_pangomarkup){ /* > */
        strcpy(&string[length], "&#62;"); length += strlen("&#62;"); continue;
      }
    }

    /* store utf8 character */
    if (char_byte > 0){
      for (b=0;b<char_byte;b++){
        string[length+b] = dclextchar[i+b];
      }
      if (!flag_inspan) { prev_byte = char_byte; prev_pos = i; }
      i += char_byte-1; length += char_byte;
      continue;
    }

  } /* end of for loop */

  if (flag_close == textlength){
    strcpy(&string[length], "</span>"); length += strlen("</span>");
  }
}




void rendertext(cairo_t *cr, char* string) {
	PangoLayout *layout;
	PangoRectangle rect;
  PangoAttribute *att;
  PangoAttrList *att_list;

	layout = pango_cairo_create_layout(cr);

  pango_layout_set_markup(layout, string, -1); /* intepret markup */
  //pango_layout_set_text(layout, string, -1); /* ignore markup */

	pango_layout_set_font_description(layout, font_desc);

	pango_cairo_update_layout(cr, layout);
	pango_cairo_show_layout(cr, layout);

	g_object_unref(layout);
}

#ifndef WINDOWS
void zgqtxw_(char* text, DCL_INT *len, DCL_REAL *wxch, DCL_REAL *wych)
#else
void ZGQTXW(char* text, DCL_INT *len, DCL_REAL *wxch, DCL_REAL *wych)
#endif
{
  char string[32768]={0} ;
  double width, height;
  double const fact=100.0;

  dcltext2pangomarkup(text, *len, string, 1.0*PANGO_SCALE*fact);
  pango_font_description_set_size(font_desc, 1.0*PANGO_SCALE*fact);
  get_pangostring_width_height(cr, string, &width, &height);
  *wxch = width*1.0/fact; //目で見て調整しただけ。
  *wych = height*0.8/fact;
}

#ifndef WINDOWS
void zgclip_(DCL_REAL *xmin,DCL_REAL *xmax,DCL_REAL *ymin,DCL_REAL *ymax)
#else
void ZGCLIP(DCL_REAL *xmin,DCL_REAL *xmax,DCL_REAL *ymin,DCL_REAL *ymax)
#endif
{
  float rxm,rym;
  double w,h;
  w=*xmax-*xmin;
  h=*ymax-*ymin;
#ifndef WINDOWS
  zgfrel_(xmin,ymax,&rxm,&rym);
#else
  ZGFREL(xmin,ymax,&rxm,&rym);
#endif
  cairo_rectangle(cr,(double)rxm,(double) rym,w,h);
  cairo_clip(cr);
}

#ifndef WINDOWS
void zgrclp_()
#else
void ZGRCLP()
#endif
{
  cairo_reset_clip(cr);
}


#ifndef WINDOWS
void zgtxt_(DCL_REAL *wx, DCL_REAL *wy, DCL_REAL *size, char* text, DCL_INT *len, DCL_REAL *irota, DCL_INT *icentz)
#else
void ZGTXT(DCL_REAL *wx, DCL_REAL *wy, DCL_REAL *size, char* text, DCL_INT *len, DCL_REAL *irota, DCL_INT *icentz)
#endif
{
  DCL_REAL iiwx,iiwy;
  double font_size;
  char string[32768]={0};
  int char_byte;
  double rotation;
  double width, height;
  double lbx,lby,rbx,rby,ltx,lty,rtx,rty;

  /* set font size and face. calculate string's width and height */
  font_size = *size * FSFACT;
  pango_font_description_set_size(font_desc, (gint)font_size*PANGO_SCALE);

  /* convert dcl's text to pango's markup */
  dcltext2pangomarkup(text, *len, string, font_size*PANGO_SCALE);

  /* calculate string's width and height */
  get_pangostring_width_height(cr, string, &width, &height);

  /* for negative iws (90 deg rotation)*/
  if (jdev_type > 0) {
    rotation = -*irota;
  }else{
    rotation = -*irota + G_PI/2;
  }

  /* centering, left-/right-aligned*/
  if (*icentz == 0) {
    iiwx = (*wx) - width*0.5*cos(rotation) + height*0.5*sin(rotation); // center
    iiwy = (wsywd-*wy) - height*0.5*cos(rotation)- width*0.5*sin(rotation) ;
  }else if (*icentz == 1) {
    iiwx = (*wx) - width*cos(rotation) + height*0.5*sin(rotation); // right
    iiwy = (wsywd-*wy) - height*0.5*cos(rotation) - width*sin(rotation);
  }else if (*icentz == -1) {
    iiwx = (*wx) + height*0.5*sin(rotation); // left
    iiwy = (wsywd-*wy) - height*0.5*cos(rotation) ;
  }

  /* tiny modification (empirical) */
  iiwx += 0.5;  iiwy += 0.5;

  /* save present cairo coordinate */
  cairo_save(cr);

  /* shift and rotate the origin of cairo coordinate */
  cairo_translate(cr, iiwx, iiwy);
  cairo_rotate(cr, rotation);

  /* render (draw) string */
  rendertext(cr, string);

  /* restore cairo cooridinate */
  cairo_restore(cr);

  /* Drawing Rectangle*/
  lbx=iiwx;
  lby=iiwy;
  ltx=lbx + height*sin(-rotation);
  lty=lby + height*cos(-rotation);
  rbx=lbx + width*cos(-rotation);
  rby=lby - width*sin(-rotation);
  rtx=rbx + height*sin(-rotation);
  rty=rby + height*cos(-rotation);
  zguprect(lbx,lby);
  zguprect(ltx,lty);
  zguprect(rbx,rby);
  zguprect(rtx,rty);

  if(!laltz){
#if GTKVERSION==2
    zgupdate(1);
#else
    zgupdate(1,cr);
#endif
  }
}




static void font_dialog_response(
#if GTKVERSION==2
           GtkFontSelectionDialog *dialog,
#else
           GtkFontChooser *dialog,
#endif
           gint response, gpointer data){

  gchar *font;

  switch (response){
  case (GTK_RESPONSE_APPLY):
  case (GTK_RESPONSE_OK):
#if GTKVERSION==2
    font=gtk_font_selection_dialog_get_font_name(dialog);
#else
    font=gtk_font_chooser_get_font(dialog);

#endif
    font_desc = pango_font_description_from_string (font);
    printf("selected font name is  '%s'  \n",font);
    strcpy(fontfamily, font);
    fontfamily[strlen(font)] = 0;
    g_free(font);
    break;
  default:
    gtk_widget_destroy(GTK_WIDGET(dialog));
  }

  if (response==GTK_RESPONSE_OK){
    gtk_widget_destroy(GTK_WIDGET(dialog));
  }
  if (font_desc == NULL){
    font_desc = pango_font_description_from_string ("Sans Normal 12");
  }
}

#ifndef WINDOWS
void zgselectfont_(char* selected_font){
#else
void ZGSELECTFONT(char* selected_font){
#endif
  int i;
  GtkWidget *dialog;
//  static void font_dialog_response (GtkFontSelectionDialog*, gint, gpointer);

#if GTKVERSION==2
  dialog = gtk_font_selection_dialog_new("Choose a Font");
#else
  dialog = gtk_font_chooser_dialog_new("Choose a Font",(GtkWindow*)window);
#endif
  if (fontfamily == NULL){
    fontfamily = defaultfont;
  }
#if GTKVERSION==2
  gtk_font_selection_dialog_set_font_name(
           GTK_FONT_SELECTION_DIALOG(dialog),
           fontfamily);
  gtk_font_selection_dialog_set_preview_text(
           GTK_FONT_SELECTION_DIALOG(dialog),
           "GFD Dennou Common Library 電脳ライブラリ αβΣΩ");
#else
  gtk_font_chooser_set_font(
           GTK_FONT_CHOOSER(dialog),
           fontfamily);
  gtk_font_chooser_set_preview_text(
           GTK_FONT_CHOOSER(dialog),
           "GFD Dennou Common Library 電脳ライブラリ αβΣΩ");
#endif

  g_signal_connect(G_OBJECT(dialog),"response",
           G_CALLBACK(font_dialog_response),NULL);
  gtk_dialog_run(GTK_DIALOG(dialog));

  for(i=0;i<1024;i++){
    selected_font[i]=0;
  }
  strcpy(selected_font, fontfamily);

}
#ifndef WINDOWS
void zgftfc_(char* family)
#else
void ZGFTFC(char* family)
#endif
{
  font_desc = pango_font_description_from_string (family);
}

#ifndef WINDOWS
void zgsfw_(DCL_INT *weight)
#else
void ZGSFW(DCL_INT *weight)
#endif
{
  int fact, offset, w;
  if ( dlnscale > 0.5 ){
    fact = 100; offset = 200;
  }else{
    fact = 100; offset = 0;
  }
  pango_font_description_set_weight (font_desc, *weight*fact + offset);
  //w = pango_font_description_get_weight (font_desc);
  //printf("w=%d\n", w);
}
#ifndef WINDOWS
void zgnumfonts_(DCL_INT *fntnum)
#else
void ZGNUMFONTS(DCL_INT *fntnum)
#endif
{
    int i, j;
    PangoFontFamily **families;
    int n_families, n_faces;
    PangoFontMap *fontmap;

    fontmap = pango_cairo_font_map_get_default();
    pango_font_map_list_families (fontmap, &families, &n_families);

    *fntnum=n_families;
}

// cf. http://www.lemoda.net/pango/list-fonts/
#ifndef WINDOWS
void zglistfonts_()
#else
void ZGLISTFONTS()
#endif
{
    int i, j;
    PangoFontFamily **families;
    int n_families, n_faces;
    PangoFontMap *fontmap;
    PangoFontFace **faces;

    fontmap = pango_cairo_font_map_get_default();
    pango_font_map_list_families (fontmap, &families, &n_families);
    printf ("There are %d families\n", n_families);
    for (i = 0; i < n_families; i++) {
        PangoFontFamily * family = families[i];
        const char * family_name;

        family_name = pango_font_family_get_name (family);
        printf ("Family %d: %s\n", i, family_name);

        pango_font_family_list_faces(family, &faces, &n_faces);
        printf("  Faces : ");
          for (j = 0; j < n_faces; j++) {
            printf("%d) %s  ", j, pango_font_face_get_face_name(faces[j]));
          }
        printf("\n\n");
        g_free(faces);
    }
    g_free (families);
}

#ifndef WINDOWS
void zgfontname_(DCL_INT *n, char* string, DCL_INT *nmax)
#else
void ZGFONTNAME(DCL_INT *n, char* string, DCL_INT *nmax)
#endif
{
    int i;
    PangoFontFamily ** families;
    int n_families;
    PangoFontMap * fontmap;

    for (i=0;i<80;i++){
      string[i] = 0;
    }

    fontmap = pango_cairo_font_map_get_default();
    pango_font_map_list_families (fontmap, & families, & n_families);
    i = *n;
    PangoFontFamily * family = families[i];
    const char * family_name;

    family_name = pango_font_family_get_name (family);
    printf ("Family %d: %s\n", i, family_name);
    for (i=0; i<strlen(family_name);i++){
      string[i] = family_name[i];
    }
    *nmax = n_families;

    g_free (families);
}

#ifndef WINDOWS
void zggplt_(DCL_REAL *wx, DCL_REAL *wy)
#else
void ZGGPLT(DCL_REAL *wx, DCL_REAL *wy)
#endif
{
  DCL_REAL iwxold, iwyold, rwx, rwy;
//  void zgfint_();

  /* pen-down move */

#ifndef WINDOWS
  zgfrel_(&rwxold, &rwyold, &iwxold, &iwyold);
  zgfrel_( wx,      wy,     &rwx,    &rwy   );
#else
  ZGFREL(&rwxold, &rwyold, &iwxold, &iwyold);
  ZGFREL( wx,      wy,     &rwx,    &rwy   );
#endif

  cairo_line_to(cr,(double)rwx,(double)rwy);

  zguprect(rwx,rwy);
  rwxold = *wx;
  rwyold = *wy;
}

#ifndef WINDOWS
void zggcls_(void)
#else
void ZGGCLS(void)
#endif
{
    cairo_stroke(cr);
    lfcmod = FALSE;
  /* close graphic segment */
}

/*------------------------- tone --------------------------*/

#ifndef WINDOWS
void zggton_(DCL_INT *np, DCL_REAL wpx[], DCL_REAL wpy[], DCL_INT *itpat)
#else
void ZGGTON(DCL_INT *np, DCL_REAL wpx[], DCL_REAL wpy[], DCL_INT *itpat)
#endif
{
  static int ltfrst = TRUE, ibitold = -1;
  DCL_REAL rpx, rpy;
  DCL_INT iclr, ibit;
  int i,j,k,l,m, nb,nl,nm;
  char bitmap[16384];
  double rt1,gt1,bt1;
  double alpha;

  static cairo_pattern_t *pattern;
  static cairo_surface_t *csb;
  static cairo_t *crb;

  /* hard fill */

  if (ltfrst) {
    csb = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 8,8);
    crb = cairo_create(csb);
    ltfrst = FALSE;
  }

  //  ibit = *itpat % 1000;
  if (*itpat/1000 == ibgcli) {
    iclr=0;
  }else{
    iclr = (*itpat / 1000) % MAXCLI;
  }
  if ((*itpat / 1000) == ifcidx){
    rt1=rt2;
    gt1=gt2;
    bt1=bt2;
  }else{
    rt1 = (double) cx[iclr].red   / 65535;
    gt1 = (double) cx[iclr].green / 65535;
    bt1 = (double) cx[iclr].blue  / 65535;
  }

  cairo_set_source_rgb(crb,rt1,gt1,bt1);
  cairo_rectangle(crb,0.0,0.0,16.0,16.0);
  cairo_fill(crb);

  pattern = cairo_pattern_create_for_surface (csb);
  cairo_pattern_set_extend (pattern , CAIRO_EXTEND_REPEAT);
  cairo_set_source (cr , pattern);

#ifndef WINDOWS
  zgfrel_(&wpx[0],&wpy[0], &rpx, &rpy);
#else
  ZGFREL(&wpx[0],&wpy[0], &rpx, &rpy);
#endif
  cairo_move_to(cr,(double)rpx,(double)rpy);
  zguprect(rpx,rpy);
  for (i = 1; i < *np; i++) {
#ifndef WINDOWS
    zgfrel_(&wpx[i],&wpy[i], &rpx, &rpy);
#else
    ZGFREL(&wpx[i],&wpy[i], &rpx, &rpy);
#endif
    cairo_line_to(cr,(double)rpx,(double)rpy);
    zguprect(rpx,rpy);
  }

  cairo_close_path(cr);
  cairo_set_source_rgb(cr,rt1,gt1,bt1);
// Adhoc Patch for 3
  if ( idev_type == IWS_FILE && ifl == IFL_PDF ){
    cairo_fill_preserve(cr);
    cairo_set_line_width(cr,0.4);
    cairo_stroke(cr);
  }else{
    cairo_set_antialias(cr,CAIRO_ANTIALIAS_NONE);
    cairo_fill(cr);
    cairo_set_antialias(cr,CAIRO_ANTIALIAS_DEFAULT);
  }
//  cairo_surface_destroy(csb);
//  cairo_destroy(crb);
  cairo_pattern_destroy (pattern);
}

/*------------------------- image -------------------------*/

#ifndef WINDOWS
void zgiopn_(DCL_INT *iwx, DCL_INT *iwy, DCL_INT *iwidth, DCL_INT *iheight)
#else
void ZGIOPN(DCL_INT *iwx, DCL_INT *iwy, DCL_INT *iwidth, DCL_INT *iheight)
#endif
{
    ixz = *iwx ;
    iyz = *iwy ;
    iwz = *iwidth;
    ihz = *iheight;
    ixxz = ixz;
    iyyz = iyz;

    csi    = cairo_image_surface_create(CAIRO_FORMAT_RGB24, iwz, ihz);
    pixels = cairo_image_surface_get_data(csi);
    rows   = cairo_image_surface_get_stride(csi);
//    cairo_surface_flush (csi);

    fprintf (stderr, " *** image ");
}

#ifndef WINDOWS
void zgidat_(DCL_INT image[], DCL_INT *nlen)
#else
void ZGIDAT(DCL_INT image[], DCL_INT *nlen)
#endif
{
  int i,ofs;
  int e=1;
  double rt1,gt1,bt1;

  for ( i=0; i< *nlen; i++){
    ofs = (iyyz-iyz)*rows + 4*(ixxz -ixz);
    if(* (char*) &e){
    //For Little Endian
    pixels[ofs  ]=(unsigned char)(cx[image[i]].blue /256);
    pixels[ofs+1]=(unsigned char)(cx[image[i]].green/256);
    pixels[ofs+2]=(unsigned char)(cx[image[i]].red  /256);
    // pixels[ofs+3]=(unsigned char)(128);
    }else{
    //For Big Endian
    // pixels[ofs  ]=(unsigned char)(128);
    pixels[ofs+1]=(unsigned char)(cx[image[i]].red  /256);
    pixels[ofs+2]=(unsigned char)(cx[image[i]].green/256);
    pixels[ofs+3]=(unsigned char)(cx[image[i]].blue /256);
    }


    ixxz = ixxz + 1;
    if (ixxz >= ixz+iwz) {
      ixxz = ixz;
      iyyz = iyyz + 1;
      if (iyyz % 16 == 0) {
        fprintf(stderr, ".");
        fflush(stdout);
      }
    }
  }
}

#ifndef WINDOWS
void zgicls_(void)
#else
void ZGICLS(void)
#endif
{
  cairo_set_source_surface(cr, csi, (double)ixz, (double)iyz);
  cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
  cairo_paint(cr);
//  cairo_surface_flush (csi);

  if(!laltz){
    irxt=0;
    irxb=0;
    iryt=0;
    iryb=0;
#if GTKVERSION==2
    zgupdate(0);
#else
    zgupdate(0,cr);
#endif
  }
  fprintf (stderr, " end\n");
  cairo_surface_destroy(csi);
}

/*------------------------- mouse -------------------------*/

#ifndef WINDOWS
void zgqpnt_(DCL_REAL *wx, DCL_REAL *wy, DCL_INT *mb)
#else
void ZGQPNT(DCL_REAL *wx, DCL_REAL *wy, DCL_INT *mb)
#endif
{
  /* mouse pointer position info. */
}

/*------------------------- inquiry -----------------------*/

#ifndef WINDOWS
void zgqwdc_(DCL_INT *lwdatr)
#else
void ZGQWDC(DCL_INT *lwdatr)
#endif
{
  /* inquire line width capability */

  *lwdatr = LWDATR;
}

#ifndef WINDOWS
void zgqclc_(DCL_INT *lclatr)
#else
void ZGQCLC(DCL_INT *lclatr)
#endif
{
  /* inquire line color capability */
  *lclatr = lclatrz;
}

#ifndef WINDOWS
void zgqtnc_(DCL_INT *ltnatr)
#else
void ZGQTNC(DCL_INT *ltnatr)
#endif
{
  /* inquire hard fill capability */
  *ltnatr = LTNATR;
}

#ifndef WINDOWS
void zgqimc_(DCL_INT *limatr)
#else
void ZGQIMC(DCL_INT *limatr)
#endif
{
  /* inquire bit image capability */
  *limatr = LIMATR;
}

#ifndef WINDOWS
void zgqptc_(DCL_INT *lptatr)
#else
void ZGQPTC(DCL_INT *lptatr)
#endif
{
  /* inquire mouse point capability */
  *lptatr = LPTATR;
}

#ifndef WINDOWS
void zgqrct_(DCL_REAL *wsxmn, DCL_REAL *wsxmx, DCL_REAL *wsymn, DCL_REAL *wsymx, DCL_REAL *fact)
#else
void ZGQRCT(DCL_REAL *wsxmn, DCL_REAL *wsxmx, DCL_REAL *wsymn, DCL_REAL *wsymx, DCL_REAL *fact)
#endif
{
  /* inquire workstation rectangle */
// Korehakairodemawaseruyounisitekyoutuukadekiruyouni

  if (idev_type == IWS_DISP || (idev_type == IWS_FILE && (ifl == IFL_PNG || ifl == IFL_SVG))){
    *wsxmn = PAD;
    *wsxmx = wsxwd-PAD;
    *wsymn = PAD;
    *wsymx = wsywd-PAD;
    *fact  = FACTZ;
  }else if (idev_type == IWS_FILE && ( ifl == IFL_EPS || ifl == IFL_PDF)){
    *wsxmn = offy;
    *wsxmx = iPS_PAGE_HEIGHT + offy;
    *wsymn = offx;
    *wsymx = iPS_PAGE_WIDTH + offx;
    *wsxmn = 0;
    *wsxmx = iPS_PAGE_HEIGHT;
    *wsymn = 0;
    *wsymx = iPS_PAGE_WIDTH;
    *fact  = FACTZ;
  }else{
    *wsxmn = offx;
    *wsxmx = iPS_PAGE_WIDTH+offx;
    *wsymn = offy;
    *wsymx = iPS_PAGE_HEIGHT+offy;
    *wsxmn = 0;
    *wsxmx = iPS_PAGE_WIDTH;
    *wsymn = 0;
    *wsymx = iPS_PAGE_HEIGHT;
    *fact  = FACTZ;
  }
}

#ifndef WINDOWS
void zgsrot_(DCL_INT *iwtrot)
#else
void ZGSROT(DCL_INT *iwtrot)
#endif
{
  /* set frame rotation flag */

  iwtroz = *iwtrot;
}

// New function for Fullcolor
#ifndef WINDOWS
void zgsfcm_(DCL_INT *lfc)
#else
void ZGSFCM(DCL_INT *lfc)
#endif
{
  lfcmod = *lfc;
}

#ifndef WINDOWS
void zgslcl_(DCL_INT *icolor)
#else
void ZGSLCL(DCL_INT *icolor)
#endif
{
#if GTKVERSION==2
  GdkColor loccx;
#elif GTKVERSION==3
  GdkColor loccx;
#else
  GdkRGBA loccx;
#endif

//  double rt1,gt1,bt1;

  loccx.red   = ((*icolor >> 16) & 255) * 256;
  loccx.green = ((*icolor >> 8)  & 255) * 256;
  loccx.blue  = ((*icolor >> 0)  & 255) * 256;

  rl2 = (double) loccx.red   / 65535;
  gl2 = (double) loccx.green / 65535;
  bl2 = (double) loccx.blue  / 65535;

  cairo_set_source_rgb(cr,rl2,gl2,bl2);
}

#ifndef WINDOWS
void zgstcl_(DCL_INT *icolor)
#else
void ZGSTCL(DCL_INT *icolor)
#endif
{
  /*This Function is not used in uipk samples
     So, it is not tested.*/
  /* set tone color in 24 bit RGB */
#if GTKVERSION==2
  GdkColor  loccx;
#elif GTKVERSION==3
  GdkColor  loccx;
#else
  GdkRGBA  loccx;
#endif
  double rt1,gt1,bt1;

  if (ltfrst) {
    ltfrst = FALSE;
  }

  loccx.red   = ((*icolor >> 16) & 255) * 256;
  loccx.green = ((*icolor >> 8)  & 255) * 256;
  loccx.blue  = ((*icolor >> 0)  & 255) * 256;

  rt2 = (double) loccx.red   / 65535;
  gt2 = (double) loccx.green / 65535;
  bt2 = (double) loccx.blue  / 65535;

  cairo_set_source_rgb(cr,rt1,gt1,bt1);
}

#ifndef WINDOWS
void zgiclr_(DCL_INT *image,DCL_INT *nlen)
#else
void ZGICLR(DCL_INT *image,DCL_INT *nlen)
#endif
{
#if GTKVERSION==2
  GdkColor  loccx;
#elif GTKVERSION==3
  GdkColor  loccx;
#else
  GdkRGBA  loccx;
#endif

  int i,ofs;
  int e=1;
  double rt1,gt1,bt1;

  for ( i=0; i< *nlen; i++){
    ofs = (iyyz-iyz)*rows + 4*(ixxz -ixz);

    loccx.red   = ((image[i] >> 16) & 255);
    loccx.green = ((image[i] >> 8)  & 255);
    loccx.blue  = ((image[i] >> 0)  & 255);

    if(* (char*) &e){
    //For Little Endian
      pixels[ofs  ]=(unsigned char)(loccx.blue);
      pixels[ofs+1]=(unsigned char)(loccx.green);
      pixels[ofs+2]=(unsigned char)(loccx.red);
    // pixels[ofs+3]=(unsigned char)(128);
    }else{
    //For Big Endian
    // pixels[ofs  ]=(unsigned char)(128);
      pixels[ofs+1]=(unsigned char)(loccx.red);
      pixels[ofs+2]=(unsigned char)(loccx.green);
      pixels[ofs+3]=(unsigned char)(loccx.blue);
    }

    ixxz = ixxz + 1;
    if (ixxz >= ixz+iwz) {
      ixxz = ixz;
      iyyz = iyyz + 1;
      if (iyyz % 16 == 0) {
        fprintf (stderr,".");
        fflush (stdout);
      }
    }
  }
  if(!laltz){
#if GTKVERSION==2
    zgupdate(1);
#else
    zgupdate(1,cr);
#endif
  }
}

#ifndef WINDOWS
void zgclini_(char clrmap[], DCL_INT *lfgbg)
#else
void ZGCLINI(char clrmap[], DCL_INT *lfgbg)
#endif
{

  void cfnchr(char *ch1, char *ch2, int lch);

  char c[80],cmapz[80];
  FILE *stream;
  int ncolor,n,m,fscanret;
  guint16 rx[MAXCLI], gx[MAXCLI], bx[MAXCLI], rx1, gx1, bx1;
  double rt1,gt1,bt1;
  int fgbg;

  /* read colormap file */

  cfnchr(cmapz, clrmap, 79);

  if ((stream = fopen(cmapz, "r")) == NULL) {
    fprintf(stderr, "*** Error in zgdopn : ");
    fprintf(stderr,
	    "Allocation failed for colormap (%s).\n", cmapz);
    exit (1);
  }

  fscanret=fscanf(stream, "%d : %s", &ncolor, c);
  for (n = 0; n < ncolor; n++)
    fscanret=fscanf(stream, "%6hd%6hd%6hd : %s", &rx[n], &gx[n], &bx[n], c);
  fclose(stream);

  fgbg = *lfgbg;

  if (fgbg) {
    rx1 = rx[0];
    gx1 = gx[0];
    bx1 = bx[0];
    rx[0] = rx[1];
    gx[0] = gx[1];
    bx[0] = bx[1];
    rx[1] = rx1;
    gx[1] = gx1;
    bx[1] = bx1;
  }

  lclatrz = 1;
/* set colormap */
  for (n = 0; n < MAXCLI; n++) {

      m = n % ncolor;

      cx[n].red   = rx[m];
      cx[n].green = gx[m];
      cx[n].blue  = bx[m];
  }

  rt1 = (double) cx[0].red   / 65535 ;
  gt1 = (double) cx[0].green / 65535 ;
  bt1 = (double) cx[0].blue  / 65535 ;

  cairo_set_source_rgb(cr,rt1,gt1,bt1);
}


static cairo_status_t png2stdout(void *closure, const unsigned char* data, unsigned int length)
{
  if (length == fwrite(data, 1, length,closure) ){
  return  CAIRO_STATUS_SUCCESS;
  }
  return CAIRO_STATUS_WRITE_ERROR;
}


static void zgcatl(){
    cairo_translate (cr, offx+iPS_PAGE_WIDTH * ddvscale / 2.0   , offy+iPS_PAGE_HEIGHT * ddvscale / 2.0 );
    cairo_rotate(cr, -2 * 3.1415926 * 0.25 );
    cairo_translate (cr, -iPS_PAGE_HEIGHT * ddvscale / 2.0 , -iPS_PAGE_WIDTH * ddvscale / 2.0 );
}
