/* A graphic libruary for GCC, emulating BASIC like graphic instructions. */
/* (Copyright by A. Kaneko) */
/* This originates from a Graphic libruary for ProFORTRAN-77 */
/* published from the University of Tokyo Press (1991) by the author. */
/* According to the general public license agreement of GNU, */
/* this program is subject to the same rule of GNU. */
/* It calls the graphic libruary functions for XWindow (Xlib) in C language */
/* by the name of functions more familiar to BASIC users. */ 
/* The usage of each subroutine is the same as that of the original one in */
/* graphic libruary for ProFORTRAN-77, written in "Kyouyou no Suugaku-Keisanki" */
/* published from the University of Tokyo Press, 1991. */
/* There are some extensions and restrictions caused by XWindow system. */
/* Unlike the FORTRAN version of this library, most functions have arguments */
/* by value, fitting to C functions. */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "xgrc.h"
#define _IMUL 256
#define Event_Mask  ( ExposureMask | KeyPressMask | Button1MotionMask | \
                      ButtonPressMask | ButtonReleaseMask )
double dmod_(double,double);
double random_(int);
void GrLine(int,int,int,int,int);
void GrLineSub(int ,int ,int ,int ,int );
void _paint_up(int ,int ,int );
void _paint_down(int ,int ,int );
void _transkj(unsigned short *,char *,int);
void _color_(int,int,int,int);
static int _GrMaxX=799;
static int _GrMaxY=599;
static int _MODE=3;
static int _LCOLOR=15;
static int _BLCOLOR=15;
static int _GCOLOR=0;
static int _PMODE=0;
static int _PCOLOR=0;
static int _LSTYLE=1;
static int _HATCHSTYLE=1;
static int _TILESTYLE=0;
static int _BLMODE=1;
static int _BLSTYLE=1;
static int _CHCOLOR=0;
static int _LASTX=0;
static int _LASTY=0;
static float _PI=3.141592653589793;
static Display  *_DISPLAY=NULL;
static Window *_WINDOW;
static Window _WINDOWDATA[10];
static int _WINDOWNO=-1;
static GC _GCONTEXT;
static XEvent _EVENT;
static XSetWindowAttributes _ATTR;
static XImage *_XIMAGE;
static Pixmap _PIXMAP;
static unsigned long _PIXEL[256];
static Colormap _CMAP;
static _LWIDTH=1;
static char _LSTYLELIST2[]={6,2};
static char _LSTYLELIST3[]={3,5};
static char _LSTYLELIST4[]={8,3,2,3};
static char _LSTYLELIST5[]={6,2,2,2,2,2};
static Pixmap _HATCH[7];
/* */
void time_(long *ih,long *im,long *is,long *ics){
     char *p; char it[3];
     time_t t;
     it[2]=0;
     t=time(NULL);
     p=ctime(&t);
     it[0]=*(p+11);
     it[1]=*(p+12);
     *ih=atol(it);
     it[0]=*(p+14);
     it[1]=*(p+15);
     *im=atol(it);
     it[0]=*(p+17);
     it[1]=*(p+18);
     *is=atol(it);
     }
void init_(int ix,int iy,int ix2,int iy2,int ind,char *name){
     XColor xcolor, c;
     XEvent event;
     XSetWindowAttributes at;
     int i;
     char wname[12]="My Window X";
     _GrMaxX=ix2-ix+1;
     _GrMaxY=iy2-iy+1;
     if (_DISPLAY==NULL) {
         _DISPLAY = XOpenDisplay ( NULL );
     }
     if (ind>=0) {
         _WINDOW=&_WINDOWDATA[ind];
         return;
     }
     _WINDOWNO++;
     _WINDOW=&_WINDOWDATA[_WINDOWNO];
     *_WINDOW = XCreateSimpleWindow (_DISPLAY, RootWindow(_DISPLAY,0),
                                     0,0,_GrMaxX+1,_GrMaxY+1,1,0,1);
     at.backing_store=Always;
     XChangeWindowAttributes(_DISPLAY,*_WINDOW,CWBackingStore,&at);
     XSelectInput(_DISPLAY,*_WINDOW, Event_Mask); //added
     XMapWindow(_DISPLAY,*_WINDOW);
/* naming of the opened window */
     if (name==NULL){
         wname[10]='0'+_WINDOWNO;
         XStoreName(_DISPLAY,*_WINDOW,wname);
     } else {
         XStoreName(_DISPLAY,*_WINDOW,name);
     }
     _PIXMAP=XCreatePixmap(_DISPLAY,*_WINDOW,800,600,DefaultDepth(_DISPLAY,0));
     _CMAP=DefaultColormap(_DISPLAY,0);
     _GCONTEXT = XCreateGC (_DISPLAY,_PIXMAP,0,0);
     _color_(0,0,0,0);
     _color_(1,1,1,1);
     _color_(2,0,0,128);
     _color_(3,0,0,255);
     _color_(4,128,0,0);
     _color_(5,255,0,0);
     _color_(6,128,0,128);
     _color_(7,255,0,255);
     _color_(8,0,128,0);
     _color_(9,0,255,0);
     _color_(10,0,128,128);
     _color_(11,0,255,255);
     _color_(12,128,128,0);
     _color_(13,255,255,0);
     _color_(14,192,192,192);
     _color_(15,255,255,255);
     _color_(16,64,64,64);
     _color_(17,128,128,128);
     _color_(18,0,64,128);
     _color_(19,0,128,255);
     _color_(20,128,64,0);
     _color_(21,255,128,0);
     _color_(22,128,0,64);
     _color_(23,255,0,128);
     _color_(24,64,128,0);
     _color_(25,128,255,0);
     _color_(26,0,128,64);
     _color_(27,0,255,128);
     _color_(28,64,0,128);
     _color_(29,128,0,255);
     _color_(30,128,128,64);
     _color_(31,255,255,128);
     _MODE=3;
     _LCOLOR=15;
     _BLCOLOR=15;
     _GCOLOR=0;
     _PMODE=0;
     _PCOLOR=0;
     _LSTYLE=1;
     _HATCHSTYLE=1;
     _TILESTYLE=0;
     _BLMODE=1;
     _BLSTYLE=1;
     _CHCOLOR=15;
     _LASTX=0;
     _LASTY=0;
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_GCOLOR]);
     for (i=1;i<=6;i++){
         _HATCH[i]=XCreatePixmap(_DISPLAY,*_WINDOW,4,4,DefaultDepth(_DISPLAY,0));
         XFillRectangle(_DISPLAY,_HATCH[i],_GCONTEXT,0,0,4,4);
         }
/*     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[15]);
     XSetBackground(_DISPLAY,_GCONTEXT,_PIXEL[0]);
     XClearWindow(_DISPLAY,*_WINDOW); */
     XFlush(_DISPLAY); 
     }
void cls_(void){
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_GCOLOR]);
     XFillRectangle(_DISPLAY,*_WINDOW,_GCONTEXT,0,0,_GrMaxX,_GrMaxY);
     XFlush(_DISPLAY);
     }
void cls2_(int ix,int iy,int ix2,int iy2,int ip){int iyc,iy2c;
     iyc=iy;
     iy2c=iy2;
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_GCOLOR]);
     XFillRectangle(_DISPLAY,*_WINDOW,_GCONTEXT,ix,iyc,ix2-ix,iy2c-iyc);
     XFlush(_DISPLAY);
     }
void xflush_(void){
     XFlush(_DISPLAY); 
     }
/* _MODE is written in /usr/X11R6/include/X11/X.h */
/* and is the same as FMR original definition of mode */
/* e.g. 1...and, 3...copy,  6...xor, 7...or  */ 
void mode_(int m){
     _MODE=m;
     XSetFunction(_DISPLAY,_GCONTEXT,_MODE);
     }
void color_(int ic,int ir,int ig,int ib){
     XColor xcolor;
     xcolor.red=ir*_IMUL+_IMUL-1;
     xcolor.green=ig*_IMUL+_IMUL-1;
     xcolor.blue=ib*_IMUL+_IMUL-1;
     XAllocColor(_DISPLAY,_CMAP,&xcolor);
     _PIXEL[ic]=xcolor.pixel;
     }
void _color_(int ic,int ir,int ig,int ib){
     XColor xcolor;
     xcolor.red=ir*_IMUL+_IMUL-1;
     xcolor.green=ig*_IMUL+_IMUL-1;
     xcolor.blue=ib*_IMUL+_IMUL-1;
     XAllocColor(_DISPLAY,_CMAP,&xcolor);
     _PIXEL[ic]=xcolor.pixel;
     }
int color_rvalue_(int ic){
    return (_PIXEL[ic]>>4)&0xff;
}
int color_gvalue_(int ic){
     return (_PIXEL[ic]>>2)&0xff;
}
int color_bvalue_(int ic){
     return _PIXEL[ic] &0xff;
}
void gcolor_(int ic){
     _GCOLOR=ic;
     XSetBackground(_DISPLAY,_GCONTEXT, _PIXEL[_GCOLOR]);
     }
void lcolor_(int ic){
     _LCOLOR=ic;
     }
void lwidth_(int iw){
     int cap,join,style;
     _LWIDTH=iw;
     switch(_LSTYLE){
            case 1: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineSolid,CapButt,JoinMiter);
                    break;
            case 2: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST2,2); 
                    break;
            case 3: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST3,2); 
                    break;
            case 4: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST4,4); 
                    break;
            case 5: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST5,6); 
                    break;
            } 
     XFlush(_DISPLAY);
     }
void lstyle_(int is){
     int cap,join,style;
     _LSTYLE=is;
     switch(_LSTYLE){
            case 1: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineSolid,CapButt,JoinMiter);
                    break;
            case 2: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST2,2); 
                    break;
            case 3: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST3,2); 
                    break;
            case 4: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST4,4); 
                    break;
            case 5: XSetLineAttributes(_DISPLAY,_GCONTEXT,_LWIDTH,LineOnOffDash,CapButt,JoinMiter);
                    XSetDashes(_DISPLAY,_GCONTEXT,0,_LSTYLELIST5,6); 
                    break;
            } 
     XFlush(_DISPLAY);
     }
void line_(int ix,int iy,int ix2,int iy2){
     GrLineSub(ix,_GrMaxY-(iy),ix2,_GrMaxY-(iy2),_LCOLOR);
     _LASTX=ix2;                /* last ref data should not be scissored */
     _LASTY=_GrMaxY-(iy2);
     XFlush(_DISPLAY);
     }
void line2_(int ix,int iy,int ix2,int iy2,int ic,int is){
     GrLineSub(ix,_GrMaxY-iy,ix2,_GrMaxY-iy2,ic);
     _LASTX=ix2;
     _LASTY=_GrMaxY-(iy2);
     XFlush(_DISPLAY);
     }
/* draw segment with arrow; ind=0...arrow at the head, ind=1...at the midst */
void arrow_(int ix,int iy,int ix2,int iy2,int length,int ind)
{
    float u,v,r;
    int yax1,yay1,yax2,yay2;
    int ix3,iy3;
    float ROOT3=1.7320508;
    line_(ix,iy,ix2,iy2);
    u=ix2-ix; v=iy2-iy; r=sqrt(u*u+v*v);
    yax1=(int)((-ROOT3*u/2-v/2)/r*length);
    yay1=(int)((u/2-ROOT3*v/2)/r*length);
    yax2=(int)((-ROOT3*u/2+v/2)/r*length);
    yay2=(int)((-u/2-ROOT3*v/2)/r*length);
    switch(ind){
    case 0:{ ix3=ix2; iy3=iy2; break;}
    case 1:{ ix3=ix+2*u/3; iy3=iy+2*v/3; break; }
    }
    line_(ix3,iy3,ix3+yax1,iy3+yay1);
    line_(ix3,iy3,ix3+yax2,iy3+yay2);
}
void move_(int ix,int iy){
     _LASTX=ix;
     _LASTY=_GrMaxY-(iy);
     }
void lineto_(int ix,int iy){
     GrLineSub(_LASTX,_LASTY,ix,_GrMaxY-(iy),_LCOLOR);
     _LASTX=(ix);
     _LASTY=_GrMaxY-(iy);
     XFlush(_DISPLAY);
     }
void arc_(int ix,int iy,int ix1,int iy1,int ix2,int iy2,int ir){
     int r,it1,it2;
     r=2*(ir);
     it1=atan2(iy1,ix1)*180/_PI*64;
     it2=atan2(iy2,ix2)*180/_PI*64;
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_LCOLOR]);
     XDrawArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-iy,r,r,it1,it2);
     XFlush(_DISPLAY);
     }
void sector_(int ix,int iy,int ix1,int iy1,int ix2,int iy2,int ir){
     int r,it1,it2;
     r=2*(ir);
     it1=atan2(iy1,ix1)*180/_PI*64;
     it2=atan2(iy2,ix2)*180/_PI*64;
     if (_PMODE!=0){
        XSetArcMode(_DISPLAY,_GCONTEXT,ArcPieSlice);
        XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
        XFillArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-iy,r,r,it1,it2);
        }
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_BLCOLOR]);
     XDrawArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-iy,r,r,it1,it2);
     XFlush(_DISPLAY);
     }
void polygon_(int n,short *id){int i,ix,iy,ix2,iy2;
     XPoint d_data[n];
     ix=*id;
     iy=_GrMaxY-*(id+1);
     for (i=0;i<n;i++) {
        d_data[i].x=*(id+i+i);
        d_data[i].y=_GrMaxY-*(id+i+i+1);
        }
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
     XFillPolygon(_DISPLAY,*_WINDOW,_GCONTEXT,d_data,n,Convex,CoordModeOrigin);
     XFlush(_DISPLAY);
     }
void zigzag_(int n,short *id){int i,ix,iy,ix2,iy2;
     XPoint d_data[n+1];
     ix=*id;
     iy=_GrMaxY-*(id+1);
     for (i=0;i<=n;i++) {
        d_data[i].x=*(id+i+i);
        d_data[i].y=_GrMaxY-*(id+i+i+1);
        }
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_LCOLOR]);
     XDrawLines(_DISPLAY,*_WINDOW,_GCONTEXT,d_data,n+1,CoordModeOrigin);
     _LASTX=*(id+2*n+1);
     _LASTY=*(id+2*n+2);
     XFlush(_DISPLAY);
     }
void linep_(int n,int id){
     }
void pcolor_(int ic){
     _PCOLOR=ic;
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
     XDrawLine(_DISPLAY,_HATCH[1],_GCONTEXT,0,2,4,2);
     XDrawLine(_DISPLAY,_HATCH[5],_GCONTEXT,0,2,4,2);
     XDrawLine(_DISPLAY,_HATCH[2],_GCONTEXT,2,0,2,4);
     XDrawLine(_DISPLAY,_HATCH[5],_GCONTEXT,2,0,2,4);
     XDrawLine(_DISPLAY,_HATCH[3],_GCONTEXT,0,4,4,0);
     XDrawLine(_DISPLAY,_HATCH[6],_GCONTEXT,0,4,4,0);
     XDrawLine(_DISPLAY,_HATCH[4],_GCONTEXT,0,0,4,4);
     XDrawLine(_DISPLAY,_HATCH[6],_GCONTEXT,0,0,4,4);
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_LCOLOR]);
     }
void pmode_(int m){
     _PMODE=m;
     if (_PMODE==1) XSetFillStyle(_DISPLAY,_GCONTEXT,FillSolid);
     else if (_PMODE>1) XSetFillStyle(_DISPLAY,_GCONTEXT,FillTiled);
     }
/* accelerates GrPixel by utilizing already prepared _XIMAGE */
int _POINT_COLOR(int ix){
     int i;
     long pixel;
     pixel=_XIMAGE->data[_XIMAGE->xoffset+ix];
     for (i=0;i<16;i++) {
          if (_PIXEL[i]==pixel) break;
          }
     return i;
     }
void paint_(int ix,int iy,int ibc){
     int iyw;
     if (_PMODE==0) return;
     iyw=_GrMaxY-(iy);
     _paint_up(ix,iyw,ibc);
     _paint_down(ix,iyw-1,ibc);
     XFlush(_DISPLAY);
     }
void paint2_(int ix,int iy,int ibc,int m,int ic){
     }
void _paint_up(int ix,int iy,int ibc){
     int ixwl,ixwr,iyw,ixwls,ixwrs,ixwlc,ixwrc,color;
     iyw=iy;
     ixwls=ix; ixwlc=ix;
     _XIMAGE=XGetImage(_DISPLAY,*_WINDOW,0,iyw,_GrMaxX,1,AllPlanes,ZPixmap);
     while(_POINT_COLOR(ixwls)!=ibc && ixwls>=0) ixwls--;
     while(_POINT_COLOR(ixwlc)==_PCOLOR && ixwlc>=0) ixwlc--;
     ixwrs=ix; ixwrc=ix;
     while(_POINT_COLOR(ixwrs)!=ibc && ixwrs<=_GrMaxX) ixwrs++;
/* determines if already painted by the concordance of the total interval */
/* of the painting color with the interval found between the pair of points */
/* with the border color */
     while(_POINT_COLOR(ixwrc)==_PCOLOR && ixwrc<=_GrMaxX) ixwrc++;
     XDestroyImage(_XIMAGE);
     if (ixwrs<ixwls+2 || ixwls==ixwlc && ixwrs==ixwrc) return;
     GrLine(ixwls+1,iyw,ixwrs-1,iyw,_PCOLOR);
     while(iyw<_GrMaxY) {
        iyw++;
        ixwl=ix; ixwlc=ix;
        _XIMAGE=XGetImage(_DISPLAY,*_WINDOW,0,iyw,_GrMaxX,1,AllPlanes,ZPixmap);
        while(_POINT_COLOR(ixwl)!=ibc && ixwl>=0) ixwl--;
        while(_POINT_COLOR(ixwlc)==_PCOLOR && ixwlc>=0) ixwlc--;
        ixwr=ix; ixwrc=ix;
        while(_POINT_COLOR(ixwr)!=ibc && ixwr<=_GrMaxX) ixwr++;
        while(_POINT_COLOR(ixwrc)==_PCOLOR && ixwrc<=_GrMaxX) ixwrc++;
        XDestroyImage(_XIMAGE);
        if (ixwl<ixwls-1) {
            ixwlc=ixwls-1;
            while(ixwlc>ixwl){
                 while(((color=GrPixel(ixwlc,iyw-1))==ibc || color==_PCOLOR ) && ixwlc>ixwl+1) ixwlc--;
                 if (ixwlc>ixwl+1) _paint_down(ixwlc,iyw-1,ibc);
                 ixwlc--;
                 }
            }
        else if (ixwl>ixwls+1) {
            ixwlc=ixwl-1;
            while(ixwlc>ixwls){
                 while(((color=GrPixel(ixwlc,iyw))==ibc || color==_PCOLOR ) && ixwlc>ixwls+1) ixwlc--;
                 if (ixwlc>ixwls+1) _paint_up(ixwlc,iyw,ibc);
                 ixwlc--;
                 }
            }
        if (ixwr<ixwrs-1) {
            ixwrc=ixwr+1;
            while(ixwrc<ixwrs){
                 while(((color=GrPixel(ixwrc,iyw))==ibc || color==_PCOLOR ) && ixwrc<ixwrs-1) ixwrc++;
                 if (ixwrc<ixwrs-1) _paint_up(ixwrc,iyw,ibc);
                 ixwrc++;
                 }
            }
        else if (ixwr>ixwrs+1) {
            ixwrc=ixwrs+1;
            while(ixwrc<ixwr){
                 while(((color=GrPixel(ixwrc,iyw-1))==ibc || color==_PCOLOR ) && ixwrc<ixwr-1) ixwrc++;
                 if (ixwrc<ixwr-1) _paint_down(ixwrc,iyw-1,ibc);
                 ixwrc++;
                 }
            }
        if (ixwr<ixwl+2 || ixwl==ixwlc && ixwr==ixwrc) return;
        GrLine(ixwl+1,iyw,ixwr-1,iyw,_PCOLOR);
        ixwls=ixwl; ixwrs=ixwr;
        }
     }
void _paint_down(int ix,int iy,int ibc){
     int ixwl,ixwr,iyw,ixwls,ixwrs,ixwlc,ixwrc,color;
     iyw=iy;
     ixwls=ix; ixwlc=ix;
     _XIMAGE=XGetImage(_DISPLAY,*_WINDOW,0,iyw,_GrMaxX,1,AllPlanes,ZPixmap);
     while(_POINT_COLOR(ixwls)!=ibc && ixwls>=0) ixwls--;
     while(_POINT_COLOR(ixwlc)==_PCOLOR && ixwlc>=0) ixwlc--;
     ixwrs=ix; ixwrc=ix;
     while(_POINT_COLOR(ixwrs)!=ibc && ixwrs<=_GrMaxX) ixwrs++;
     while(_POINT_COLOR(ixwrc)==_PCOLOR && ixwrc<=_GrMaxX) ixwrc++;
     XDestroyImage(_XIMAGE);
     if (ixwrs<ixwls+2 || ixwls==ixwlc && ixwrs==ixwrc) return;
     GrLine(ixwls+1,iyw,ixwrs-1,iyw,_PCOLOR);
     while(iyw>0) {
        iyw--;
        ixwl=ix; ixwlc=ix;
        _XIMAGE=XGetImage(_DISPLAY,*_WINDOW,0,iyw,_GrMaxX,1,AllPlanes,ZPixmap);
        while(_POINT_COLOR(ixwl)!=ibc && ixwl>=0) ixwl--;
        while(_POINT_COLOR(ixwlc)==_PCOLOR && ixwlc>=0) ixwlc--;
        ixwr=ix; ixwrc=ix;
        while(_POINT_COLOR(ixwr)!=ibc && ixwr<=_GrMaxX) ixwr++;
        while(_POINT_COLOR(ixwrc)==_PCOLOR && ixwrc<=_GrMaxX) ixwrc++;
        XDestroyImage(_XIMAGE);
        if (ixwl<ixwls-1) {
            ixwlc=ixwls-1; ixwrc=ixwls;
            while(ixwrc>ixwl){
                 while(((color=GrPixel(ixwlc,iyw+1))==ibc || color==_PCOLOR ) && ixwlc>ixwl+1) ixwlc--;
                 if (ixwlc>ixwl+1) _paint_up(ixwlc,iyw+1,ibc);
                 ixwrc=ixwlc; ixwlc--;
                 }
            }
        else if (ixwl>ixwls+1) {
            ixwlc=ixwl-1; ixwrc=ixwl;
            while(ixwlc>ixwls){
                 while(((color=GrPixel(ixwlc,iyw))==ibc || color==_PCOLOR ) && ixwlc>ixwls+1) ixwlc--;
                 if (ixwlc>ixwls+1) _paint_down(ixwlc,iyw,ibc);
                 ixwrc=ixwlc; ixwlc--;
                 }
            }
        if (ixwr<ixwrs-1) {
            ixwrc=ixwr+1; ixwlc=ixwr;
            while(ixwrc<ixwrs){
                 while(((color=GrPixel(ixwrc,iyw))==ibc || color==_PCOLOR ) && ixwrc<ixwrs-1) ixwrc++;
                 if (ixwrc<ixwrs-1) _paint_down(ixwrc,iyw,ibc);
                 ixwlc=ixwrc; ixwrc++;
                 }
            }
        else if (ixwr>ixwrs+1) {
            ixwrc=ixwrs+1; ixwlc=ixwrs;
            while(ixwrc<ixwr){
                 while(((color=GrPixel(ixwrc,iyw+1))==ibc || color==_PCOLOR ) && ixwrc<ixwr-1) ixwrc++;
                 if (ixwrc<ixwr-1) _paint_up(ixwrc,iyw+1,ibc);
                 ixwlc=ixwrc; ixwrc++;
                 }
            }
        if (ixwr<ixwl+2 || ixwl==ixwlc && ixwr==ixwrc) return;
        GrLine(ixwl+1,iyw,ixwr-1,iyw,_PCOLOR);
        ixwls=ixwl; ixwrs=ixwr;
        }
     }
void hatchs_(int is){
     _HATCHSTYLE=is;
     XSetTile(_DISPLAY,_GCONTEXT,_HATCH[is]);
     }
void tiles_(int is){
     _TILESTYLE=is;
     }
void blmode_(int m){
     _BLMODE=m;
     }
void blstyl_(int is){
     _BLSTYLE=is;
     }
void blcolr_(int ic){
     _BLCOLOR=ic;
     }
void box_(int ix1,int iy1,int ix2,int iy2){
     int iy,iy0,i;
     iy0=_GrMaxY-(iy1);
     iy=_GrMaxY-(iy2);
     if (_PMODE!=0) {
          XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
          XFillRectangle(_DISPLAY,*_WINDOW,_GCONTEXT,ix1,iy,ix2-ix1,iy0-iy);
          XFlush(_DISPLAY);
          }
/*     lstyle_(_BLSTYLE); */
     GrLineSub(ix1,iy0,ix2,iy0,_BLCOLOR);
     GrLineSub(ix1,iy,ix2,iy,_BLCOLOR);
     GrLineSub(ix1,iy0,ix1,iy,_BLCOLOR);
     GrLineSub(ix2,iy0,ix2,iy,_BLCOLOR);
/*     lstyle_(_LSTYLE);  */
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_LCOLOR]);
     XFlush(_DISPLAY);
     }
void circle_(int ix,int iy,int ir){char c;
     int r;
     r=2*(ir);
     if (_PMODE!=0){
        XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
        XFillArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix-ir,_GrMaxY-iy-ir,r,r,0,360*64);
        }
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_BLCOLOR]);
     XDrawArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix-ir,_GrMaxY-iy-ir,r,r,0,360*64);
     XFlush(_DISPLAY);
     }
void ellips_(int ix,int iy,int irx,int iry){
     int r1,r2;
     r1=2*(irx);
     r2=2*(iry);
     if (_PMODE!=0){
        XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_PCOLOR]);
        XFillArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix-irx,_GrMaxY-iy-iry,r1,r2,0,360*64);
        }
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[_BLCOLOR]);
     XDrawArc(_DISPLAY,*_WINDOW,_GCONTEXT,ix-irx,_GrMaxY-iy-iry,r1,r2,0,360*64);
     XFlush(_DISPLAY);
     }
void pset_(int ix,int iy,int ic){
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[ic]);
     XDrawPoint(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-(iy));
/*     XFlush(_DISPLAY); */
     }
void psethline_(int ix,int iy,int n,unsigned short *idata){
     struct _XImage image;
     int i;
     image.width=n;
     image.height=1;
     image.xoffset=0;
     for (i=0;i<n;i++) *(idata+i)=_PIXEL[*(idata+i)];
     image.data=(char *)idata;
     image.format=XYPixmap;
     image.depth=16;
     XPutImage(_DISPLAY,*_WINDOW,_GCONTEXT,&image,0,0,ix,_GrMaxY-(iy),n,0);
     XFlush(_DISPLAY);
     }
void chcolr_(int ic){
     _CHCOLOR=ic;
     }
void charac_(int ix,int iy,char *moji){
     unsigned short jis[100];
     Font ft;
     XSetForeground(_DISPLAY,_GCONTEXT, _PIXEL[_CHCOLOR]);
     if ((unsigned)(*moji)<0x80) {
         ft=XLoadFont(_DISPLAY,"12x24");
         XSetFont(_DISPLAY,_GCONTEXT,ft);
         XDrawString(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-iy,moji,strlen(moji));
         }
     else {
         ft=XLoadFont(_DISPLAY,"kanji24");
         XSetFont(_DISPLAY,_GCONTEXT,ft);
         XFlush(_DISPLAY);
         _transkj(jis,moji,0);
         XDrawString16(_DISPLAY,*_WINDOW,_GCONTEXT,ix,_GrMaxY-iy,(XChar2b *)moji,strlen(moji)/2);
         XDrawString16(_DISPLAY,*_WINDOW,_GCONTEXT,ix+100,_GrMaxY-iy,(XChar2b *)jis,strlen(moji));
         }
     XFlush(_DISPLAY);
     } 
void GrLineSub(int ix,int iy,int ix2,int iy2,int ic){
     int igx1,igy1,igx2,igy2; int c;
     if(scissor(ix,iy,ix2,iy2,&igx1,&igy1,&igx2,&igy2) != 0) return;
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[ic]);
     XDrawLine(_DISPLAY,*_WINDOW,_GCONTEXT,igx1,igy1,igx2,igy2);
     }
void GrLine(int ix,int iy,int ix2,int iy2,int ic){
     XSetForeground(_DISPLAY,_GCONTEXT,_PIXEL[ic]);
     XDrawLine(_DISPLAY,*_WINDOW,_GCONTEXT,ix,iy,ix2,iy2);
     }
int scissor(int ix,int iy,int ix2,int iy2,\
            int *igx1,int *igy1,int *igx2,int *igy2){
     float xdif,ydif,yoverx,xovery;
     if(ix>ix2){*igx1=ix2;*igy1=iy2;*igx2=ix;*igy2=iy;}
     else {*igx1=ix;*igy1=iy;*igx2=ix2;*igy2=iy2;}
     if(*igx1>=0 && *igx2>=0 && *igx1<=_GrMaxX && *igx2<=_GrMaxX && \
        *igy1>=0 && *igy2>=0 && *igy1<=_GrMaxY && *igy2<=_GrMaxY) return 0;
     if(*igx2<0 || *igx1>_GrMaxX) return -1;
     xdif=*igx2-*igx1; ydif=*igy2-*igy1;
     if(xdif!=0) yoverx=ydif/xdif;
     if(ydif!=0) xovery=xdif/ydif;
     if(*igx1<0){*igy1=*igy1+yoverx*(-*igx1);*igx1=0;}
     if(*igx2>_GrMaxX){*igy2=*igy1+yoverx*(_GrMaxX-*igx1);*igx2=_GrMaxX;}
     if(*igy1<0 && *igy2<0 || *igy1>_GrMaxY && *igy2>_GrMaxY) return -1;
     if(*igy1<0) {*igx1=*igx1+xovery*(-*igy1);*igy1=0;}
     if(*igy2<0) {*igx2=*igx2+xovery*(-*igy2);*igy2=0;}
     if(*igy1>_GrMaxY) {*igx1=*igx1+xovery*(_GrMaxY-*igy1);*igy1=_GrMaxY;}
     if(*igy2>_GrMaxY) {*igx2=*igx2+xovery*(_GrMaxY-*igy2);*igy2=_GrMaxY;}
     return 0;
     }
int max(int i,int j){
    if (i>=j) return i;
    else return j;
    }
int min(int i,int j){
    if (i<=j) return i;
    else return j;
    }
double random_(int i){
static long INI_=123456789;    /* detarame na kazu */
static long LAML_=63149;
static long LAMH_=12867;
static long MUL_=45429;
static long MUH_=6924;
static long POWER0_=65536;
static double POWER2_=65536.0;
static long RANL_;
static long RANH_;
      double X,Y; double RANDOM;
      if (i>0) {RANL_=dmod_((double)i,(double)POWER0_);
		RANH_=i/POWER0_;}
      else if (INI_!=0) {INI_=0;
                       RANL_=0;
                       RANH_=0;}
      X=RANL_;
      Y=RANH_;
      Y=dmod_(Y*LAML_+X*LAMH_+MUH_,POWER2_);
      X=X*LAML_+MUL_;
      RANL_=dmod_(X,POWER2_);
      RANH_=dmod_(Y+(long)(X/POWER2_),POWER2_);
      RANDOM=((float)RANH_)/POWER2_+((float)RANL_)/POWER2_/POWER2_;
      return RANDOM;
      }
double dmod_(double x,double y){
     return x-(long)(x/y)*y;
     }
int GrPixel(int ix,int iy) {
     int i;
     long pixel;
     XImage *image;
     if (ix<0 || iy<0 || ix>_GrMaxX ||iy>_GrMaxY) return -1;
     image=XGetImage(_DISPLAY,*_WINDOW,ix,iy,1,1,AllPlanes,ZPixmap);
     pixel=image->data[image->xoffset];
     for (i=0;i<16;i++) {
          if (_PIXEL[i]==pixel) break;
          }
     XDestroyImage(image);
     return i;
     }
void _transkj(unsigned short *jis,char *euc,int ind){
     int i;
     for (i=0;i<strlen(euc);i++){
          *(jis+i)=*(euc+i) & 0x7f;
          }
     *(jis+i)=0;
     }
int mouse_(int *ix, int *iy){
     XEvent _EVENT;
     while (1){
         XNextEvent(_DISPLAY,&_EVENT);
         switch(_EVENT.type){
             case ButtonPress :
                  break;
             case ButtonRelease:
                  *ix=_EVENT.xbutton.x; *iy=_GrMaxY-_EVENT.xbutton.y;
                  return _EVENT.xbutton.button;
             }
         }
    }
void mboxsub_(X1,Y1,X2,Y2){
    int ix,iy,idx,idy;
    if (X1>X2){
        ix=X2; idx=X1-X2+1;
    } else {
        ix=X1; idx=X2-X1+1;
    }
    if (Y1>Y2){
        iy=_GrMaxY-Y1; idy=Y1-Y2+1;
    } else {
        iy=_GrMaxY-Y2; idy=Y2-Y1;
    }
    XDrawRectangle(_DISPLAY,*_WINDOW,_GCONTEXT,ix,iy,idx,idy);
}
int mbox_(int *ix, int *iy, int *ix2, int *iy2){
     XEvent _EVENT;
     int X1,Y1,X2,Y2,X,Y,LEFT,ICC,IPC;
     LEFT=0;
     XSetFunction(_DISPLAY,_GCONTEXT,GXxor);
     XSetForeground(_DISPLAY,_GCONTEXT,0xffffffff);
     while (1){
         XCheckWindowEvent(_DISPLAY,*_WINDOW,Event_Mask,&_EVENT);
         switch(_EVENT.type){
             case ButtonPress :
                  if (_EVENT.xbutton.button==1) {
                        if (LEFT==2) {
                           mboxsub_(X1,Y1,X2,Y2);
                           XFlush(_DISPLAY);
                        } 
                        LEFT=1; /* start of region capture */
                        X1=_EVENT.xbutton.x; Y1=_GrMaxY-_EVENT.xbutton.y;
                        X2=X1; Y2=Y1;
                  }
                  break;
             case ButtonRelease:
                  if (_EVENT.xbutton.button==1) {
                       mboxsub_(X1,Y1,X2,Y2);
                       X2=_EVENT.xbutton.x; Y2=_GrMaxY-_EVENT.xbutton.y;
                       mboxsub_(X1,Y1,X2,Y2);
                       XFlush(_DISPLAY);
                       LEFT=2; /* end of region capture */
                  } else if (_EVENT.xbutton.button==2) {
                       XSetFunction(_DISPLAY,_GCONTEXT,_MODE);
                       *ix=X1; *ix2=X2;
                       if (X1>X2) {
                           *ix=X2; *ix2=X1;
                       }
                       *iy=Y1; *iy2=Y2;
                       if (Y1>Y2) {
                           *iy=Y2; *iy2=Y1;
                       }
                       return _EVENT.xbutton.button;
                  } else if (_EVENT.xbutton.button==3) {
                       XSetFunction(_DISPLAY,_GCONTEXT,_MODE);
                       *ix=X1; *ix2=X2;
                       if (X1>X2) {
                           *ix=X2; *ix2=X1;
                       }
                       *iy=Y1; *iy2=Y2;
                       if (Y1>Y2) {
                           *iy=Y2; *iy2=Y1;
                       }
                       return _EVENT.xbutton.button;
                  }
                  break;
             case MotionNotify:
                  if (LEFT==0) break;
                  mboxsub_(X1,Y1,X2,Y2);
                  X2=_EVENT.xbutton.x;
                  Y2=_GrMaxY-_EVENT.xbutton.y;
                  mboxsub_(X1,Y1,X2,Y2);
                  XFlush(_DISPLAY);
                  break;
             case 0: break;
             default: break;
             }
         }
    }
/* ic>0 のとき, 最後に開いたウインドウから元に ic 個のウインドウを閉じる,
   ic=0 のとき, すべてのウインドウを閉じ，Display も破壊し終了する.   */
void closex_(int ic){
    int i;
    if (ic>0) {
        for (i=0;i<ic;i++){
            _WINDOW=&_WINDOWDATA[_WINDOWNO-i];
            XDestroyWindow(_DISPLAY,*_WINDOW);
        }
        _WINDOW=&_WINDOWDATA[_WINDOWNO-i];
        return;
    } else {
        XFreeGC(_DISPLAY,_GCONTEXT);
        XDestroyWindow(_DISPLAY,*_WINDOW);
        XCloseDisplay(_DISPLAY);
        _DISPLAY=NULL;
    }
}
#if 0
void closex_(void){
    XFreeGC(_DISPLAY,_GCONTEXT);
    XDestroyWindow(_DISPLAY,*_WINDOW);
    XCloseDisplay(_DISPLAY);
    _DISPLAY=NULL;
}
#endif
