//
// Copyright (C) 1999-2002 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <Carbon/Carbon.h>
#include <WSDfont.h>
#include <WSCfontSet.h>
#include <WSDcolor.h>
#include <WSCcolorSet.h>
#include <WSDimage.h>
#include <WSCimageSet.h>
#include <WSCstring.h>
#include <WSCvarc.h>
#include <WSClocaleSet.h>
//#include <x11/WSxcom.h>
#include <mac/WSDmacAppDev.h>
#include <mac/WSDmacDraw.h>
//#include <mac/WSDmacImage.h>

//#define TDBG

WSMFclassInit(WSDmacDraw,WSCroot);

#if 0 //XXZZ
static char _line_dash_type1[] = {3, 3};
static char _line_dash_type2[] = {10, 10};
static char _line_dash_type3[] = {20, 20};
static char _line_dash_type4[] = {20, 5, 5, 5};
static char _line_dash_type5[] = {20, 5, 5, 5, 5, 5};
static char _line_dash_type6[] = {40, 5, 5, 5};
static char _line_dash_type7[] = {40, 5, 5, 5, 5, 5};
static char _line_dash_type8[] = {1, 2};

static int _line_dash_type_seg1 = 2;
static int _line_dash_type_seg2 = 2;
static int _line_dash_type_seg3 = 2;
static int _line_dash_type_seg4 = 4;
static int _line_dash_type_seg5 = 6;
static int _line_dash_type_seg6 = 4;
static int _line_dash_type_seg7 = 6;
static int _line_dash_type_seg8 = 2;

static WSCuchar _hatch_pattern1[] = {0xc0, 0xc0, 0x30, 0x30, 0x0c, 0x0c, 0x03, 0x03};
static WSCuchar _hatch_pattern2[] = {0x03, 0x03, 0x0c, 0x0c, 0x30, 0x30, 0xc0, 0xc0};
static WSCuchar _hatch_pattern3[] = {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
static WSCuchar _hatch_pattern4[] = {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00};
static WSCuchar _hatch_pattern5[] = {0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33};
static WSCuchar _hatch_pattern6[] = {0xff, 0xff, 0xcc, 0xcc, 0xff, 0xff, 0xcc, 0xcc};
static WSCuchar _hatch_pattern7[] = {0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00};
static WSCuchar _hatch_pattern8[] = {0xcc, 0xaa, 0xcc, 0xaa, 0xcc, 0xaa, 0xcc, 0xaa};

static Pixmap _hatch[9] = { 0,0,0,0,0,0,0,0,0 };
#endif //XXZZ

//static short _clip_x = -1;
//static short _clip_y = -1;
//static short _clip_w = -1;
//static short _clip_h = -1;

WSDmacDraw::WSDmacDraw(){
//  _region_saved = False;
//  _save_region = 0;
  _exposed = False;
  _fg_color.red = 0xffff;
  _fg_color.green = 0xffff;
  _fg_color.blue = 0xffff;

  _bg_color.red = 0xffff;
  _bg_color.green = 0xffff;
  _bg_color.blue = 0xffff;

  _line_width = -1;
  _line_type = -1;
  _clipping = False;
  _fg_no = -1;
  _bg_no = -1;
  _pre_offset_x = 0;
  _pre_offset_y = 0;
}
WSDmacDraw::~WSDmacDraw(){
  long num = _offset_stack.getNum();
  long i;
  for(i=0; i<num; i++){
    WSCpoint* pt = (WSCpoint*)_offset_stack[i];
    if (pt != NULL){
      delete pt;
    }
  }

//  if (_save_region != NULL){
//    DisposeRgn(_save_region);
//    _save_region = NULL;
//    _region_saved = False;
//  }
}

long WSDmacDraw::setForeColor(short cno){
//  if (_window == 0){
//    return -1;
//  }
  long bk = _fg_no;
  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
//printf("WSDmacDraw::setForeColor color=0x%x\n",color);
  if (color != NULL){
    RGBColor* col = (RGBColor*)color->getValue1();
//printf("WSDmacDraw::setForeColor col=0x%x\n",col);
    if (col != NULL){
      _fg_color.red = col->red;
      _fg_color.green = col->green;
      _fg_color.blue = col->blue;
//      if (cno != _fg_no){
//printf("WSDmacDraw::setForeColor rgb= 0x%x 0x%x 0x%x\n",col->red,col->green,col->blue);
        RGBForeColor(&_fg_color);
//      }
    }
  }else{
//printf("WSDmacDraw::setForeColor null..\n");
  }
  _fg_no = cno;
  return bk;
}

long WSDmacDraw::setBackColor(short cno){
//  if (_window == 0){
//    return -1;
//  }
  long bk = _bg_no;
  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
  if (color != NULL){
    RGBColor* col = (RGBColor*)color->getValue1();
    if (col != NULL){
      _bg_color.red = col->red;
      _bg_color.green = col->green;
      _bg_color.blue = col->blue;
//      if (cno != _bg_no){
        RGBBackColor(&_bg_color);
//      }
    }
  }
  _bg_no = cno;
  return bk;
}

long WSDmacDraw::setForeColor(WSDcolor* color){
//  if (_window == 0){
//    return _fg_no;
//  }
  if (color == NULL){
    return _fg_no;
  }

  short cno = color->getId();
  long bk = _fg_no;
  if (color != NULL){
    RGBColor* col = (RGBColor*)color->getValue1();
    if (col != NULL){
      _fg_color.red = col->red;
      _fg_color.green = col->green;
      _fg_color.blue = col->blue;
//      if (cno != _fg_no){
        RGBForeColor(&_fg_color);
//      }
    }
  }
  _fg_no = cno;
  return bk;
}

long WSDmacDraw::setBackColor(WSDcolor* color){
//  if (_window == 0){
//    return _fg_no;
//  }
  if (color == NULL){
    return _bg_no;
  }

  short cno = color->getId();
  long bk = _bg_no;
  if (color != NULL){
    RGBColor* col = (RGBColor*)color->getValue1();
    if (col != NULL){
      _bg_color.red = col->red;
      _bg_color.green = col->green;
      _bg_color.blue = col->blue;
//      if (cno != _bg_no){
        RGBBackColor(&_bg_color);
//      }
    }
  }
  _bg_no = cno;
  return bk;
}

long WSDmacDraw::setLineWidth(short width){
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return -1;
  }

  if (_line_width == width){
    return _line_width;
  }
  long bk = _line_width;
  _line_width = width;

  long linet = _line_type;
  _line_type = -1; 
  setLineDashType(linet);

  return bk;
#endif //XXZZ
//printf("WSDmacDraw::setLineWidth.. not supported\n");
  return 0;
}

//#define CAPSTYLE  CapButt
#define CAPSTYLE  CapNotLast

long WSDmacDraw::setLineDashType(char type){
#if 0 //XXZZ
  if (_line_type == type){
    return type;
  }
  if (_gc == 0 || _window == 0){
    return -1;
  }
  long bk = _line_type;
  _line_type = type;
  switch(type){
    case 0:
//      XSetLineAttributes(_display,_gc,_line_width, LineSolid,CapButt,WS_JOIN);
      XSetLineAttributes(_display,_gc,_line_width, LineSolid,CAPSTYLE,WS_JOIN);
      break;

    case 1:
      XSetDashes(_display,_gc,0,_line_dash_type1,_line_dash_type_seg1);
//      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CapButt,WS_JOIN);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 2:
      XSetDashes(_display,_gc,0,_line_dash_type2,_line_dash_type_seg2);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 3:
      XSetDashes(_display,_gc,0,_line_dash_type3,_line_dash_type_seg3);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 4:
      XSetDashes(_display,_gc,0,_line_dash_type4,_line_dash_type_seg4);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 5:
      XSetDashes(_display,_gc,0,_line_dash_type5,_line_dash_type_seg5);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 6:
      XSetDashes(_display,_gc,0,_line_dash_type6,_line_dash_type_seg6);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
      break;
    case 7:
      XSetDashes(_display,_gc,0,_line_dash_type7,_line_dash_type_seg7);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
       break;
    case 8:
      XSetDashes(_display,_gc,0,_line_dash_type8,_line_dash_type_seg8);
      XSetLineAttributes(_display,_gc,_line_width, LineOnOffDash,CAPSTYLE,WS_JOIN);
       break;
    default:
      XSetLineAttributes(_display,_gc,_line_width, LineSolid,CAPSTYLE,WS_JOIN);
  }
  return bk;
#endif //XXZZ
printf("WSDmacDraw::setLineDashType.. not supported\n");
  return 0;
}
long WSDmacDraw::setHatchPattern(char type){
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return -1;
  }
  if (_fill_type == type){
    return type;
  }
  long bk = _fill_type;
  if (type == 0 ){
    XSetFillStyle(_display,_gc,FillSolid);
    _fill_type = 0;
    return bk;
  }
  _fill_type = type;
  Pixmap _htch = 0;
  WSDxappDev* app   = WSGIxwinAppDev(); 
  switch(type){
    case 1: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern1,8,8);
            };
            _htch = _hatch[type];
            break;
    case 2: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern2,8,8);
            };
            _htch = _hatch[type];
            break;
    case 3: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern3,8,8);
            };
            _htch = _hatch[type];
            break;
    case 4: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern4,8,8);
            };
            _htch = _hatch[type];
            break;
    case 5: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern5,8,8);
            };
            _htch = _hatch[type];
            break;
    case 6: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern6,8,8);
            };
            _htch = _hatch[type];
            break;
    case 7: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern7,8,8);
            };
            _htch = _hatch[type];
            break;
    case 8: if (_hatch[type] == 0){
              _hatch[type] = XCreateBitmapFromData(_display,
                       XtWindow((Widget)app->appWidget()),
                       (char*)_hatch_pattern8,8,8);
            };
            _htch = _hatch[type];
            break;
  }
  if (_htch != 0){
    XSetFillStyle(_display,_gc,FillStippled);
    XSetStipple(_display,_gc,_htch);
  }else{
    XSetFillStyle(_display,_gc,FillSolid);
  }
  return bk;
#endif //XXZZ
printf("WSDmacDraw::setHatchPattern.. not supported\n");
  return 0;
}
long WSDmacDraw::beginDraw(WSDdev* dev,long val1,long val2,long val3){
  WindowRef wbk = _window;
  _dev = dev;
  if (_window != (WindowRef)val2){
    _fg_color.red = 0xffff;
    _fg_color.green = 0xffff;
    _fg_color.blue = 0xffff;
    _bg_color.red = 0xffff;
    _bg_color.green = 0xffff;
    _bg_color.blue = 0xffff;
    _window = (WindowRef)val2;
    _fill_type = -1;
    GetQDGlobalsWhite(&_pattern);
  }
  if (_window == (WindowRef)-1 || _window == (WindowRef)0){
    return WS_ERR;
  }
  if (_window != NULL){
    RgnHandle save_region = NewRgn();
    if (save_region != NULL){
//printf("WSDmacDraw::beginDraw GetClip.. win=0x%x\n",wbk);
      if (_exposed != False){
        GetClip(save_region);
      }else{
        SetRectRgn(save_region,0,0,0x7fff,0x7fff);
      }
    }
    _clip_stack.add((void*)save_region);
//printf("WSDmacDraw::beginDraw D5 save clip win=0x%x wbk=0x%x rh=0x%x\n",_window,wbk,save_region);

    WSCpoint* pt = new WSCpoint;
    pt->x = _pre_offset_x;
    pt->y = _pre_offset_y;
    _offset_stack.add((void*)pt);

    if (_window != NULL){
      if (_window != wbk){
static WindowRef _window_pre = 0;
        if (_window_pre != _window){
//printf("WSDmacDraw::beginDraw D3 D2 D5 SetPortWindowPort(0x%x)\n",_window);
          SetPortWindowPort(_window);
          _window_pre = _window;
        }
      }
    }
    if (val3 != 0){
      WSCpoint* pt = (WSCpoint*)val3;
//printf("WSDmacDraw::beginDraw MovePortTo D2 D5 pt->x,y=%d %d\n",pt->x,pt->y);
//      MovePortTo(pt->x,pt->y);
      _pre_offset_x = pt->x;
      _pre_offset_y = pt->y;
    }else{
//printf("MOVE PORT2 D2   pt->x,y=%d %d\n",0,0);
//      MovePortTo(0,0);
    }

    RgnHandle csave_region = NewRgn();
    if (csave_region != NULL){
//printf("WSDmacDraw::beginDraw GetClip (cunnret) D5 0x%x\n",csave_region);
      GetClip(csave_region);
    }
    _current_clip_stack.add((void*)csave_region);

    _window_stack.add((void*)_window);
    _pre_window_stack.add((void*)wbk);
  }
  _clip_area.x = 0;
  _clip_area.y = 0;
  _clip_area.width = 0x7fff;
  _clip_area.height = 0x7fff;

  _line_width = 1;
  _line_type = 0;
  if (_window != NULL){

    RGBForeColor(&_fg_color);
    RGBBackColor(&_bg_color);
    return WS_NO_ERR;
  }else{
//printf("WSDmacDraw::beginDraw... err return\n");
    return WS_ERR;
  }
}

long WSDmacDraw::endDraw(){
//  if (_save_region != NULL){
  long num = _clip_stack.getNum();
  if (num > 0){
    WindowRef w = (WindowRef)_window_stack[num -1];
    WindowRef wbk = (WindowRef)_pre_window_stack[num -1];
    RgnHandle rh = (RgnHandle)_clip_stack[num -1];
    RgnHandle crh = (RgnHandle)_current_clip_stack[num -1];
    WSCpoint* pt = (WSCpoint*)_offset_stack[num -1];
    DisposeRgn(crh);

    _window_stack.delPos(num -1);
    _pre_window_stack.delPos(num -1);
    _clip_stack.delPos(num -1);
    _current_clip_stack.delPos(num -1);
    _offset_stack.delPos(num -1);
    if (_window != wbk){
      if (wbk != NULL){
//printf("WSDmacDraw::endDraw D3 D5 SetPortWindowPort(0x%x)\n",wbk);
        SetPortWindowPort(wbk);
      }
    }
    if (wbk != NULL){
      _window = wbk;
      if (pt != NULL){
        if (pt->x != -1 && pt->y != -1){
//          MovePortTo(pt->x,pt->y);
//printf("WSDmacDraw::endDraw...  D5 MovePortTo.. %d %d\n",pt->x,pt->y);
        }
        _pre_offset_x = pt->x;
        _pre_offset_y = pt->y;
      }
//printf("WSDmacDraw::endDraw D3 D5 win=0x%x SetClip(0x%x)\n",_window,rh);
      SetClip(rh);
    }else{
#if 0
//      Rect tr;
//      GetWindowBounds(_window,kWindowContentRgn,&tr);
//      Rect tr2;
//      GetWindowBounds(_window,kWindowStructureRgn,&tr2);
//printf("D5 tr=%d,%d %d,%d\n",tr.left,tr.top,tr2.left,tr2.top);
//      short diff_x = tr.left - tr2.left;
//      short diff_y = tr.top - tr2.top;
//      MovePortTo(diff_x,diff_y);
//printf("WSDmacDraw::endDraw...xx  D5 MovePortTo.. %d %d\n",diff_x,diff_y);
#endif
      SetClip(rh);
      _pre_offset_x = -1;
      _pre_offset_y = -1;
      _window = wbk;
    }
    DisposeRgn(rh);
 


    if (pt != NULL){
      delete pt;
    }

  }else{
#if 0 //TEST
printf("WSDmacDraw::endDraw  D3 EndUpdate(0x%x)\n",_window);
    EndUpdate(_window);
#endif //TEST
  }
//  }
//  EndUpdate(_window);
#if 0
  if (_window == 0){
printf("WSDmacDraw::endDraw... err return.\n");
    return WS_ERR;
  }
#endif
//printf("WSDmacDraw::endDraw...\n");
  return WS_NO_ERR;
}

long WSDmacDraw::setRegion(short x,short y,WSCushort w,WSCushort h){
  if (_window == 0){
    return WS_ERR;
  }
//  if (_clip_x != x || _clip_y != y || _clip_w != w || _clip_h != h){
//printf("WSDmacDraw::setRegion D5 win=0x%x %d %d %d %d\n",_window,x,y,w,h);
  long cx;
  long cy;
  WSCulong cw;
  WSCulong ch;

  long num = _current_clip_stack.getNum();
  RgnHandle crh = (RgnHandle)_current_clip_stack[num -1];
//printf("WSDmacDraw::setRegion restore D5 0x%x\n",crh);
//  long num = _current_clip_stack.getNum();
//  WSCrect* current_clip = NULL;
//  if (num > 0){
//    current_clip = (WSCrect*)_current_clip_stack[num -1];
//  }
//  if (current_clip != NULL){
//    long dx = current_clip->x;
//    long dy = current_clip->y;
//    WSCulong dw = current_clip->width;
//    WSCulong dh = current_clip->height;
//printf("WSDmacDraw::setRegion D1 d=%d %d %d %d\n",dx,dy,dw,dh);
//    WSGFandArea(dx,dy,dw,dh,x,y,w,h,&cx,&cy,&cw,&ch);
//  }else{
//    WSGFandArea(_clip_x,_clip_y,_clip_w,_clip_h,x,y,w,h,&cx,&cy,&cw,&ch);
//  }
#if 0
    WSGFandArea(_clip_area.x,_clip_area.y,_clip_area.width,_clip_area.height,
                x,y,w,h,&cx,&cy,&cw,&ch);
//printf("WSDmacDraw::setRegion D1 %d %d %d %d -> %d %d %d %d\n",x,y,w,h,cx,cy,cw,ch);
  _clip_area.x = cx;
  _clip_area.y = cy;
  _clip_area.width = cw;
  _clip_area.height = ch;
#endif

  RgnHandle rh1 = NewRgn();
  RgnHandle rh2 = NewRgn();
  SetRectRgn(rh1,x+_pre_offset_x,y+_pre_offset_y,
                 x+_pre_offset_x+w,y+_pre_offset_y+h);
  SectRgn(rh1,crh,rh2);
  SetClip(rh2);
  DisposeRgn(rh1);
  DisposeRgn(rh2);
  _clipping = True;
  return WS_NO_ERR;
}

long WSDmacDraw::drawArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2){
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return WS_ERR;
  }
  XDrawArc(_display,_window,_gc,x,y,w,h,a1,a2);
  return WS_NO_ERR;
#endif //XXZZ
  return WS_ERR;
}
long WSDmacDraw::drawFillArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2,char kind){
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return WS_ERR;
  }
  if (kind == WS_PI){
    XSetArcMode(_display,_gc,ArcPieSlice);
  }else{
    XSetArcMode(_display,_gc,ArcChord);
  }
  XFillArc(_display,_window,_gc,x,y,w,h,a1,a2);
  return WS_NO_ERR;
#endif //XXZZ
  return WS_ERR;;
}
long WSDmacDraw::drawLine(short x1,short y1,short x2,short y2){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawLine..  \n");
  MoveTo(x1 + _pre_offset_x,y1 + _pre_offset_y);
  LineTo(x2 + _pre_offset_x,y2 + _pre_offset_y);
  return WS_NO_ERR;
}

long WSDmacDraw::drawLines(WSCpoint* points,long num){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawLines..  \n");
  MoveTo(points[0].x,points[0].y);

  long i; 
  for(i=1; i<num; i++){
    LineTo((int)points[i].x + _pre_offset_x,(int)points[i].y + _pre_offset_y);
  }
  return WS_NO_ERR;
}
long WSDmacDraw::drawRect(short x,short y,WSCushort w,WSCushort h){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawRect..  \n");
  Rect r;
  SetRect(&r,x + _pre_offset_x,y + _pre_offset_y,
             x + _pre_offset_x+w,y + _pre_offset_y+h);
  FrameRect(&r);
  return WS_NO_ERR;
}
long WSDmacDraw::drawFillRect(short x,short y,WSCushort w,WSCushort h){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawFillRect.. D11  xywh=%d %d %d %d\n",x,y,w,h);
//TEST
//  GetQDGlobalsWhite(&_pattern);

//  RGBBackColor(&_fg_color);

  Rect r;
  SetRect(&r,x + _pre_offset_x,y + _pre_offset_y,
             x + _pre_offset_x+w,y + _pre_offset_y+h);

  PaintRect(&r);
//  FrameRect(&r);

//  RGBBackColor(&_bg_color);
  return WS_NO_ERR;
}
long WSDmacDraw::drawRects(WSCrect* rects,long num){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawRects..  \n");
  long i;
  for(i=0; i<num; i++){
    drawRect(rects[i].x,rects[i].y, rects[i].width,rects[i].height); 
  }
  return WS_NO_ERR;
}

long WSDmacDraw::drawFillRects(WSCrect* rects,long num){
  if (_window == 0){
    return WS_ERR;
  }
//printf("WSDmacDraw::drawFillRects..  \n");
  long i;
  for(i=0; i<num; i++){
    drawFillRect(rects[i].x,rects[i].y, rects[i].width,rects[i].height); 
  }
  return WS_NO_ERR;
}

long WSDmacDraw::drawPoly(WSCpoint* points,long num){
  if (_window == 0){
    return WS_ERR;
  }
  PolyHandle ph = OpenPoly();
  MoveTo(points[num-1].x + _pre_offset_x,points[num -1].y + _pre_offset_y);
  long i;
  for(i=0; i<num; i++){
    LineTo(points[i].x + _pre_offset_x,points[i].y + _pre_offset_y);
  }
  ClosePoly(); 
  FramePoly(ph);
  KillPoly(ph); 

  return WS_NO_ERR;
}

long WSDmacDraw::drawFillPoly(WSCpoint* points,long num){
  if (_window == 0){
    return WS_ERR;
  }
  PolyHandle ph = OpenPoly();
  MoveTo(points[num-1].x + _pre_offset_x,points[num -1].y + _pre_offset_y);
  long i;
  for(i=0; i<num; i++){
    LineTo(points[i].x + _pre_offset_x,points[i].y + _pre_offset_y);
  }
  ClosePoly(); 
  PaintPoly(ph);
  KillPoly(ph); 

  return WS_NO_ERR;
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return WS_ERR;
  }
  XPoint* pts = new XPoint[num];
  long i;
  for(i=0; i<num; i++){
    pts[i].x = points[i].x;
    pts[i].y = points[i].y;
  }
  XFillPolygon(_display,_window,_gc,pts,num,Nonconvex,CoordModeOrigin);
  delete pts;
  return WS_NO_ERR;
#endif //XXZZ
}

long WSDmacDraw::drawImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image,char align){
//TEST
//return WS_NO_ERR;


  if (_window == 0){
//printf("WSDmacDraw::drawImage D17 err return..1\n");
    return WS_ERR;
  }
  PicHandle pix1 = (PicHandle)image->getValue1();
  PicHandle pix2 = (PicHandle)image->getValue2();
//printf("WSDmacDraw::drawImage D17 %s 0x%x %d,%d,%d,%d\n",image->getSrc(),pix1,x,y,w,h);

  WSCushort pw = image->getImageWidth();
  WSCushort ph = image->getImageHeight();
  short xoff = 0;
  short yoff = 0;
  if (align == WS_CENTER){
    xoff = ((short)w - (short)pw)/2;
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_LEFT){
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_LEFT_TOP){
    xoff = 0;
    yoff = 0;
  }else
  if (align == WS_TOP){
    xoff = ((short)w - (short)pw)/2;
    yoff = 0;
  }else
  if (align == WS_RIGHT){
    xoff = ((short)w - (short)pw);
    yoff = ((short)h - (short)ph)/2;
  }else
  if (align == WS_BOTTOM){
    xoff = ((short)w - (short)pw)/2;
    yoff = ((short)h - (short)ph);
  }else
  if (align == WS_LEFT_BOTTOM){
    xoff = 0;
    yoff = ((short)h - (short)ph);
  }else
  if (align == WS_RIGHT_TOP){
    xoff = ((short)w - (short)pw);
    yoff = 0;
  }else
  if (align == WS_RIGHT_BOTTOM){
    xoff = ((short)w - (short)pw);
    yoff = ((short)h - (short)ph);
  }
  if ((long)pix1 == -1 && pix1 != 0){
//printf("WSDmacDraw::drawImage D17 err return..\n");
    return WS_NO_ERR;
  }
#if 0 //XXZZ
  if ((long)pix2 != -1 && pix2 != 0){
    XSetClipMask(_display,_gc,pix2);
    XSetClipOrigin(_display,_gc,x+xoff,y+yoff);
  }
#endif

  long dx,dy;
  long dw,dh;

  WSGFandArea(x,y,w,h,x+xoff,y+yoff,pw,ph,&dx,&dy,(WSCulong*)&dw,(WSCulong*)&dh);
#if 0
  MoveTo(_pre_offset_x + dx,_pre_offset_y + dy);
  Rect r;
  SetRect(&r, _pre_offset_x + dx -x -xoff,_pre_offset_y + dy -y -yoff,
              _pre_offset_x + dx -x -xoff +dw,_pre_offset_y + dy -y -yoff +dh);

  DrawPicture(pix1,&r);
#endif

  char* buf = (char*)pix1;
  char* buf2 = (char*)pix2;
  RGBColor col;
  long x1,y1;
  long p,p2;
//printf("WSDmacDraw::drawImage D17 wh=%d,%d draw=%d,%d,%d,%d buf=0x%x\n",pw,ph,xoff,yoff,dw,dh,buf);
  for(y1 = -yoff;y1 < -yoff+dh; y1++){
    for(x1 = -xoff;x1 < -xoff+dw; x1++){
      if (y1 < 0){
        continue;
      }
      if (x1 < 0){
        continue;
      }
      p2 = y1 * ph + x1;
      p = p2*3;
//printf("WSDmacDraw::drawImage D20 ptr=0x%x xy=%d,%d rgb=0x%x,0x%x,0x%x 0x%x\n",p2,x1,y1,(WSCuchar)buf[p],(WSCuchar)buf[p+1],(WSCuchar)buf[p+2],(WSCuchar)buf2[p2]);
      if (buf2 != NULL && buf2[p2] != 0){
        continue;
      }
      col.red = (unsigned short)(buf[p++])<<8;
      col.green = (unsigned short)(buf[p++])<<8;
      col.blue = (unsigned short)(buf[p])<<8;
//printf("WSDmacDraw::drawImage D20 xy=%d,%d rgb=0x%x,0x%x,0x%x\n",x1,y1,col.red,col.green,col.blue);
//      RGBForeColor(&col);
//      MoveTo(_pre_offset_x +x1,_pre_offset_y +y1);
//      LineTo(_pre_offset_x +x1+1,_pre_offset_y +y1);
      SetCPixel(_pre_offset_x+x+x1+xoff,_pre_offset_y+y+y1+yoff,&col);
    }
  }
  return WS_NO_ERR;
}
long WSDmacDraw::drawStretchedImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image){
#if 0 //XXZZ
  if (_gc == 0 || _window == 0){
    return WS_ERR;
  }
  Pixmap pix1 = (Pixmap)image->getValue1();
//  Pixmap pix2 = (Pixmap)image->getValue2();

//  WSCushort pw = image->getImageWidth();
//  WSCushort ph = image->getImageHeight();

  if ((long)pix1 == -1 || (long)pix1 == 0){
    return WS_NO_ERR;
  }
  long dx,dy;
  WSCulong dw,dh;
  WSGFandArea(x,y,w,h,_clip_x,_clip_y,_clip_w,_clip_h,&dx,&dy,&dw,&dh);
  if (dw == 0 || dh == 0){
    return WS_NO_ERR;
  }

  XImage* img = (XImage*)image->getValue3();
  if ((long)img == 0 ||
      (long)img == -1 ){
    WSDximage* ximage = (WSDximage*)image->cast("WSDximage");
    if (ximage == NULL){
      return WS_ERR;
    }
    ximage->createImage();
    img = (XImage*)image->getValue3();
    if (img == NULL ||(long)img == -1){
      return WS_ERR;
    }
  }

  if ((long)pix1 != -1 && (long)pix1 != 0){
    XSetClipMask(_display,_gc,0);
  }

  long display_depth = XDefaultDepth(_display,
                                     XDefaultScreen(_display));
//printf("display_depth=%d\n",display_depth);
  long bit_pad = 32;
  if (display_depth == 32){
     bit_pad = 32;
  }else
  if (display_depth == 24){
     bit_pad = 32; 
  }else
  if (display_depth == 16){
     bit_pad = 16;
  }else{ 
     bit_pad = 8;
  }
  Visual* visual = XDefaultVisual(_display,XDefaultScreen(_display));
  XVisualInfo vinf;

  XImage* img2 = XCreateImage(_display, visual,
                       display_depth,
                       ZPixmap,0,0,
                       dw, dh, bit_pad,0);
  XInitImage(img2);
  WSCulong iw = image->getImageWidth();
  WSCulong ih = image->getImageHeight();
  img2->data = new char[img2->bytes_per_line * dh ];
  long bit = img2->bits_per_pixel;


//  if ((long)pix2 != -1 && pix2 != 0){
//    XSetClipMask(_display,_gc,pix2);
//    XSetClipOrigin(_display,_gc,x,y);
//  }

  long i=0;
  long j=0;
  long ptr = 0;
  long pt = 0;
  for(i=dy-y; i<dy-y +dh; i++){
    for(j=dx-x; j<dx -x +dw; j++){
//      long pt = (long)((double)j*iw/w + 0.5 + (int)((double)i*ih/h+0.5)*iw);
//      long pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*(iw + iw%2);
      if (display_depth == 32){
        pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*iw;
        pt = pt *4;
        ptr = ((j -dx +x)+(i -dy +y)*dw)*4;
        img2->data[ptr++] = img->data[pt];
        img2->data[ptr++] = img->data[pt+1];
        img2->data[ptr++] = img->data[pt+2];
        img2->data[ptr++] = img->data[pt+3];
      }else
      if (display_depth == 24){
        if (bit == 32){
          pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*iw;
          pt = pt *4;
          ptr = ((j -dx +x)+(i -dy +y)*dw)*4;
          img2->data[ptr++] = img->data[pt];
          img2->data[ptr++] = img->data[pt+1];
          img2->data[ptr++] = img->data[pt+2];
          img2->data[ptr++] = img->data[pt+3];
        }else if (bit == 24){
          pt = (long)((double)j*iw/w)*3 + (long)((double)i*ih/h)*img->bytes_per_line;
          ptr = (j -dx +x)*3+(i -dy +y)*img2->bytes_per_line;
          img2->data[ptr++] = img->data[pt];
          img2->data[ptr++] = img->data[pt+1];
          img2->data[ptr++] = img->data[pt+2];
        }
      }else
      if (display_depth == 16 || display_depth == 15){
        pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*(iw + iw%2);
        pt = pt *2;
        ptr = ((j -dx +x)+(i -dy +y)*dw)*2;
        img2->data[ptr++] = img->data[pt];
        img2->data[ptr++] = img->data[pt+1];
      }else
      if (display_depth == 12){
        if (bit == 24){
          pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*iw;
          pt = pt *3;
          ptr = ((j -dx +x)+(i -dy +y)*dw)*3;
          img2->data[ptr++] = img->data[pt];
          img2->data[ptr++] = img->data[pt+1];
          img2->data[ptr++] = img->data[pt+2];
        }
      }else
      if (display_depth == 8){
        pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*img->bytes_per_line;
        ptr = ((j -dx +x)+(i -dy +y)*img2->bytes_per_line);
        img2->data[ptr++] = img->data[pt];
      }else
      if (display_depth == 4){
        pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*img->bytes_per_line;
        ptr = ((j -dx +x)+(i -dy +y)*img2->bytes_per_line);
        img2->data[ptr++] = img->data[pt];
      }else{
        pt = (long)((double)j*iw/w) + (long)((double)i*ih/h)*img->bytes_per_line;
        ptr = ((j -dx +x)+(i -dy +y)*img2->bytes_per_line);
        img2->data[ptr++] = img->data[pt];
      }
    }
  }
  Pixmap newpix = WSGFxGetPixmap(dw,dh);
//  XPutImage(_display,newpix,_gc,img2,dx-x,dy-y,0,0,dw,dh);
  XPutImage(_display,newpix,_gc,img2,0,0,0,0,dw,dh);

//  XCopyArea(_display,newpix,_window,_gc, dx -x,dy -y, dw,dh,dx,dy);
  XCopyArea(_display,newpix,_window,_gc, 0,0, dw,dh,dx,dy);

  WSGFxReleasePixmap(newpix);
  if (img2->data != NULL){
    delete img2->data;
    img2->data = NULL;
  }
  XDestroyImage(img2);
//  if ((long)pix2 != -1 && pix2 != 0){
//    short clx = _clip_x;
//    _clip_x = -1;
//    setRegion(clx,_clip_y,_clip_w,_clip_h);
//  }
  if ((long)pix1 != -1 && (long)pix1 != 0){
    short clx = _clip_x;
    _clip_x = -1;
    setRegion(clx,_clip_y,_clip_w,_clip_h);
  }
  return WS_NO_ERR;
#endif //XXZZ
//printf("WSDmacDraw::drawStretchedImage.. not supported \n");
  return WS_NO_ERR;
}


long WSDmacDraw::drawImage(short x,short y,short sx,short sy,WSCushort w,WSCushort h,WSDimage* image){
//TEST
//return WS_NO_ERR;
//printf("WSDmacDraw::drawImage D17 0x%x %d,%d,%d,%d\n",_window,x,y,w,h);
  if ( _window == 0){
    return WS_ERR;
  }
  PicHandle pix1 = (PicHandle)image->getValue1();
  PicHandle pix2 = (PicHandle)image->getValue2();
  if ((long)pix1 == -1 && pix1 != 0){
    return WS_NO_ERR;
  }
#if 0
  MoveTo(_pre_offset_x + x,_pre_offset_y + y);
  Rect r;
  SetRect(&r, 0,0,w,h);

  DrawPicture(pix1,&r);
#endif
  RGBColor col;
  long x1,y1;
  long p,p2;
  long width = image->getImageWidth();
  long height = image->getImageHeight();

  char* buf = (char*)pix1;
  char* buf2 = (char*)pix2;

  for(y1 = 0;y1 < height; y1++){
    for(x1 = 0;x1 < width; x1++){
      p2 = y1 * width + x1;
      p = p2*3;
      if (buf2 != NULL && buf2[p2] != 0){
        continue;
      }
      col.red = (unsigned short)(buf[p++])<<8;
      col.green = (unsigned short)(buf[p++])<<8;
      col.blue = (unsigned short)(buf[p])<<8;
      SetCPixel(_pre_offset_x+x + x1,_pre_offset_y+y+y1,&col);
    }
  }
  return WS_NO_ERR;
}
long WSDmacDraw::_draw_string( long x,long y,char* st,
                            long fheight,int cur,
                            WSCbool inter_cur,long lw,long scur1,long scur2){
  y = y + fheight;
  if (st == NULL){
    return WS_ERR;
  }
#if 0
{
  MoveTo(x + _pre_offset_x,y + _pre_offset_y);
//  WSCushort* str = WSGFgetUCS2(st,WS_EN_UTF8);
  Str255 tbuf;
//  c2pstrcpy(tbuf,(char*)str);
  c2pstrcpy(tbuf,st);
  //TEST
//XXZZ
  DrawString(tbuf);
//  delete str;
return WS_NO_ERR;
}
#endif
  WSCushort* str = WSGFgetUCS2(st,WS_EN_UTF8);
  long dx = x;
  long i=0;
  while(str[i]){
    MoveTo(dx + _pre_offset_x,y + _pre_offset_y);
    long dw = CharWidth(str[i]);
    if (inter_cur == True){
      if (i == cur){
        drawRect(dx - lw/2, y- fheight,dx+lw/2,y);
        MoveTo(x+_pre_offset_x,y+_pre_offset_y);
      }
      DrawChar(str[i]);
    }else{
      if (i == cur){
        drawRect(dx, y- fheight,dx +dw,y);
        RGBForeColor(&_bg_color);
        MoveTo(x+_pre_offset_x,y+_pre_offset_y);
        DrawChar(str[i]);
        RGBForeColor(&_fg_color);
      }else{
        DrawChar(str[i]);
      }
    }
    dx += dw;
    i++;
  }
  delete str;
  return WS_NO_ERR;
}

long WSDmacDraw::drawUString(long x,long y,WSCulong w,WSCulong h,
         WSCushort* str,char font,char align,long cur,WSCbool inter_cur,
         long scur1,long scur2){
  char* str1 = WSGFgetString(str,WS_EN_UTF8);
  WSCstring str2(str1,WS_EN_UTF8);
  long ret = drawString(x,y,w,h,&str2,font,align,cur,inter_cur,scur1,scur2);
  delete str1;
  return ret;
}
long WSDmacDraw::drawFillUString(long x,long y,WSCulong w,WSCulong h,
           WSCushort* str,char font,char align,short cur,WSCbool inter_cur){
  char* str1 = WSGFgetString(str,WS_EN_UTF8);
  WSCstring str2(str1,WS_EN_UTF8);
  long ret = drawFillString(x,y,w,h,&str2,font,align,cur,inter_cur);
  delete str1;
  return ret;
}
long WSDmacDraw::drawString(long x,long y,WSCulong w,WSCulong h,
         WSCstring* str,char font,char align,long cur,WSCbool inter_cur,
         long scur1,long scur2){
//printf("WSDmacDraw::drawString.... not supported 1\n");
#ifdef TDBG
printf("WSDmacDraw::drawString start %d\n",WSGFclocktime());
#endif

  if (scur1 == scur2){
    scur1 = scur2 = 0;
  }
  if (scur1 > scur2){
    long bk = scur1;
    scur1 = scur2;
    scur2 = bk;
  }
  if (_window == 0){
    return WS_ERR;
  }
  short clx_bk = _clip_area.x;
  short cly_bk = _clip_area.y;
  WSCushort clw_bk = _clip_area.width;
  WSCushort clh_bk = _clip_area.height;
  long clx,cly;
  WSCulong clw,clh;
  WSGFandArea(x,y,w,h,
              _clip_area.x,_clip_area.y,_clip_area.width,_clip_area.height,
              &clx,&cly,&clw,&clh);
  setRegion(clx,cly,clw,clh);

  WSDfont* fn = WSGIappFontSet()->getFont(font);
  if (fn == NULL){
    fn = WSGIappFontSet()->getDefaultFont();
    if (fn == NULL){
//printf("WSDmacDraw::drawString err return...\n");
      return WS_ERR;
    }
  }
#if 0
  XFontStruct* efs = (XFontStruct*)fn->getValue1();
  XFontStruct* kfs = (XFontStruct*)fn->getValue2();
  XFontStruct* gfs = (XFontStruct*)fn->getValue3();
  long efontWidth = 14;
  long kfontWidth = 14;
  Font efid;
  if (efs == NULL || efs == (void*)-1){
    return WS_ERR;
  }else{
    efid = efs->fid;
    efontWidth = (long)efs->max_bounds.rbearing;
  }
  Font kfid;
  if (kfs == NULL || kfs == (void*)-1){
    kfid = efid;
    kfontWidth = efontWidth;
  }else{
    kfid = kfs->fid;
    kfontWidth = (long)kfs->max_bounds.rbearing;
  }
  Font gfid;
  if (gfs == NULL || gfs == (void*)-1){
    gfid = efid;
  }else{
    gfid = gfs->fid;
  }

  long fheight = (long)efs->max_bounds.ascent;
  long fheight2 = (long)kfs->max_bounds.ascent;
#endif
  FontInfo finf;
  GetFontInfo(&finf);
  long fontWidth = finf.widMax;
  long fheight = (long)finf.ascent;

  if (str->isExist("\n") == -1){
    WSCrect   area;
    area.setRect(x,y,w,h);
    WSCpoint  point;
    WSGFcalcOneLineStringAddr(str,&area,align,fn,&point);
    char* tstr;
    tstr = str->getString(WS_EN_UTF8);
    char* tstr2 = new char[strlen(tstr) + 8];
    strcpy(tstr2,tstr);
    strcat(tstr2," ");
    _draw_string( point.x, point.y,
      tstr2, fheight,cur, inter_cur,_line_width,scur1,scur2);
    delete tstr2;
    setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
    return WS_NO_ERR;
  }

  long num;
  WSCrect area;
  area.setRect(x,y,w,h);
  WSCpoint* points;

  WSGFcalcStringAddr(str,&area,align,fn,&points,&num);
  long i;
  str->seek(0);
  long lpos =0;
  long prelpos =0;
  for(i=0; i < num; i++){

    if (points[i].y + fheight < cly){
      lpos += prelpos;
      prelpos = str->_seek_next_line() +1;
//printf("lpos=%d prelpos=%d\n",lpos,prelpos);
      continue;
    }
//printf("multiline.in=#%s#\n",str->getString());
//printf("XXXXXXXXXXXXXXXXXXZZZZZZZZZZ start\n");
    WSCstring lstr;
    lstr = str->gets();
//printf("XXXXXXXXXXXXXXXXXXZZZZZZZZZZ done\n");
//printf("WSDmacDraw::drawUString:\n%s\n",lstr.getString(WS_EN_EUCJP));

//printf("multiline lstr=#%s#\n",lstr.getString(WS_EN_EUCJP));
    lpos += prelpos;
    prelpos = lstr.getChars() +1;
    if ((long)(cly + clh) < points[i].y){
      break;
    }
    char* tstr;
    tstr = lstr.getString(WS_EN_UTF8);

    if (cur == -1){
      _draw_string(points[i].x, points[i].y, tstr, fheight, -1,
                   inter_cur,_line_width, scur1 - lpos,scur2 - lpos);
//printf("cur=%d c1=%d c2=%d  lpos=%d pre=%d\n",-1,scur1-lpos,scur2-lpos,lpos,prelpos);
    }else{
      _draw_string( points[i].x, points[i].y, tstr, fheight,cur - lpos,
                       inter_cur,_line_width, scur1 - lpos,scur2 - lpos);
//printf("cur=%d c1=%d c2=%d  lpos=%d pre=%d\n",cur-lpos,scur1-lpos,scur2-lpos,lpos,prelpos);
    }
  }
  str->seek(0);
  if (num != 0){
    delete points;
  }
  setRegion(clx_bk,cly_bk,clw_bk,clh_bk);

#ifdef TDBG
printf("WSDmacDraw::drawString done %d\n",WSGFclocktime());
#endif

  return WS_NO_ERR;
}

long WSDmacDraw::drawFillString(long x,long y,WSCulong w,WSCulong h,
           WSCstring* str,char font,char align,short cur,WSCbool inter_cur){
  if (_window == 0){
    return WS_ERR;
  }
  RGBForeColor(&_bg_color);
  RGBBackColor(&_fg_color);

  drawFillRect(x,y,w,h);

  RGBForeColor(&_fg_color);
  RGBBackColor(&_bg_color);

  drawString(x,y,w,h,str,font,align,cur,inter_cur);

  return WS_NO_ERR;
}

extern WSCulong WSGFxcolorval(WSDcolor*,WSCuchar,WSCuchar,WSCuchar);

long WSDmacDraw::drawGradation(long type,short c1,short c2,short c3,
                  short x,short y,WSCushort w,WSCushort h,WSCuchar gradm){
//static WSDcolor* color = NULL;
//printf("WSDmacDraw::drwaGradation.. not supported.\n");
  if (_window == 0){
    return WS_ERR;
  }
  short clx_bk = _clip_area.x;
  short cly_bk = _clip_area.y;
  WSCushort clw_bk = _clip_area.width;
  WSCushort clh_bk = _clip_area.height;
  long clx,cly;
  WSCulong clw,clh;
  WSGFandArea(x,y,w,h,
              _clip_area.x,_clip_area.y,_clip_area.width,_clip_area.height,
              &clx,&cly,&clw,&clh);
  setRegion(clx,cly,clw,clh);

  WSDcolor* col1 = WSGIappColorSet()->getColor(c1);
  WSDcolor* col2 = WSGIappColorSet()->getColor(c2);
  WSDcolor* col3 = WSGIappColorSet()->getColor(c3);
#if 0
  long r1,g1,b1;
  long r2,g2,b2;
  long r3,g3,b3;
  if (col1 == NULL || col2 == NULL || col3 == NULL){
    setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
    return WS_ERR;
  }
  fgcolor = -100;
  bgcolor = -100;
  _fg_color = 0;
  _bg_color = 0;
  _fg_color_no = 0xffffffff;
  _bg_color_no = 0xffffffff;

  long display_depth = XDefaultDepth(_display,XDefaultScreen(_display));
  if (display_depth < 9){
    WSCulong cval1 = (WSCulong )col2->getValue1();
    XSetForeground(_display,_gc,cval1);
    XFillRectangle(_display,_window,_gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h); 
    setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
    return WS_NO_ERR;
  }
#endif

#if 0
  col1->getRGB(&r1,&g1,&b1);
  col2->getRGB(&r2,&g2,&b2);
  col3->getRGB(&r3,&g3,&b3);
  color = WSGIappColorSet()->getColor((short)0);
  if (color == NULL){
    color = WSGIappColorSet()->getNewColor();
    color->setId(0);
    color->setUsePrivateCell(True);
    WSGIappColorSet()->addColor(color);
  }
#endif
  RGBColor* cval1 = (RGBColor*)col1->getValue1();
  RGBColor* cval2 = (RGBColor*)col2->getValue1();
  RGBColor* cval3 = (RGBColor*)col3->getValue1();
  RGBColor fg = _fg_color;
  RGBColor bg = _bg_color;

  if (gradm != 0){
    _fg_color = *cval2;
    drawFillRect(x,y,w,h);
#if 0
    WSCulong cval1 = (WSCulong )col2->getValue1();
    XSetForeground(_display,_gc,cval1);
    XFillRectangle(_display,_window,_gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h); 
#endif
  }

//DUMMY....
  _fg_color = *cval2;
  drawFillRect(x,y,w,h);
//DUMMY....

  _fg_color = bg;

#if 0 //XXZZ
  long i;
  if (type == WS_GR_LT_RB || type == WS_GR_RB_LT){
    long max = (w+h)* (100 -gradm)/100;
    long wval = max/64+1;
    XSetLineAttributes(_display,_gc,wval+1,LineSolid,CapProjecting,WS_JOIN);
    for(i=0; i<max;i+=wval){
      long x1 = x +i;
      long y1 = y +i;
      if (i > max/2){ 
        x1 = x + (w+h)*gradm/100 + i;
        y1 = y + (w+h)*gradm/100 + i;
      }
      if (_clip_y != -1){
        if (_clip_y > -_clip_x + y1 + x || _clip_y + _clip_h < -_clip_x - _clip_w + y1 + x){
//          continue;
        }
      }
      long val1,val2,val3;
      if (type == WS_GR_LT_RB){
        if (i < max/2){ 
          val1 = (r1 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g1 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b1 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max *2 -i*2)  + r3 * (i *2 -max)) /max;
          val2 = (g2 * (max *2 -i*2)  + g3 * (i *2 -max)) /max;
          val3 = (b2 * (max *2 -i*2)  + b3 * (i *2 -max)) /max;
        }
      }else{
        if (i < max/2){ 
          val1 = (r3 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g3 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b3 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max *2 -i*2)  + r1 * (i *2 -max)) /max;
          val2 = (g2 * (max *2 -i*2)  + g1 * (i *2 -max)) /max;
          val3 = (b2 * (max *2 -i*2)  + b1 * (i *2 -max)) /max;
        }
      }
      if (val1 < 0){
        val1 = 0;
      }
      if (val2 < 0){
        val2 = 0;
      }
      if (val3 < 0){
        val3 = 0;
      }
      if (val1 > 0xff){
        val1 = 0xff;
      }
      if (val2 > 0xff){
        val2 = 0xff;
      }
      if (val3 > 0xff){
        val3 = 0xff;
      }
      
      WSCulong cval = WSGFxcolorval(color,val1,val2,val3);
      XSetForeground(_display,_gc,cval);
      XDrawLine(_display,_window,_gc,(int)x1,(int)y,(int)x,(int)y1); 
    }
  }else
  if (type == WS_GR_LB_RT || type == WS_GR_RT_LB){
    long max = (w+h)* (100 -gradm)/100;
    long wval = max/64+1;
    XSetLineAttributes(_display,_gc,wval+1,LineSolid,CapProjecting,WS_JOIN);
    for(i=0; i<max;i+=wval){
      long x1 = x +i;
      long y1 = y +h -i;
      if (i >= max/2){
        x1 = x +i + (w+h) * gradm/100;
        y1 = y +h -i - (w+h) * gradm/100;
      }
      if (_clip_y != -1){
        if (_clip_y > _clip_x + _clip_w + y1 - x || _clip_y + _clip_h < _clip_x + y1 - x){
//          continue;
        }
      }
      long val1,val2,val3;
      if (type == WS_GR_LB_RT){
        if (i < max/2){ 
          val1 = (r1 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g1 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b1 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max *2 -i*2)  + r3 * (i *2 -max)) /max;
          val2 = (g2 * (max *2 -i*2)  + g3 * (i *2 -max)) /max;
          val3 = (b2 * (max *2 -i*2)  + b3 * (i *2 -max)) /max;
        }
      }else{
        if (i < max/2){ 
          val1 = (r3 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g3 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b3 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max *2 -i*2)  + r1 * (i *2 -max)) /max;
          val2 = (g2 * (max *2 -i*2)  + g1 * (i *2 -max)) /max;
          val3 = (b2 * (max *2 -i*2)  + b1 * (i *2 -max)) /max;
        }
      }
      if (val1 < 0){
        val1 = 0;
      }
      if (val2 < 0){
        val2 = 0;
      }
      if (val3 < 0){
        val3 = 0;
      }
      if (val1 > 0xff){
        val1 = 0xfff;
      }
      if (val2 > 0xff){
        val2 = 0xff;
      }
      if (val3 > 0xff){
        val3 = 0xff;
      }
      WSCulong cval = WSGFxcolorval(color,val1,val2,val3);
      XSetForeground(_display,_gc,cval);
      XDrawLine(_display,_window,_gc,(int)x,(int)y1,(int)x1,(int)(y+h)); 
    }
  }else
  if (type == WS_GR_T_B || type == WS_GR_B_T){
    long max = h* (100 -gradm)/100;
    long wval = max/64+1;
    XSetLineAttributes(_display,_gc,wval+1,LineSolid,CapProjecting,WS_JOIN);
    for(i=0; i<max;i+=wval){
      long h1 = i;
      if (h1 >= max/2){
        h1 = i+ h * gradm/100;
      }
      if (_clip_x != -1){
        if (_clip_y > h1+y || _clip_y + _clip_h < h1+y){
//          continue;
        }
      }
      long val1,val2,val3;
      if (type == WS_GR_T_B){
        if (i < max/2){ 
          val1 = (r1 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g1 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b1 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max*2 -i*2)  + r3 * (i *2 -max)) /max;
          val2 = (g2 * (max*2 -i*2)  + g3 * (i *2 -max)) /max;
          val3 = (b2 * (max*2 -i*2)  + b3 * (i *2 -max)) /max;
        }
      }else{
        if (i < max/2){ 
          val1 = (r3 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g3 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b3 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max*2 -i*2)  + r1 * (i *2 -max)) /max;
          val2 = (g2 * (max*2 -i*2)  + g1 * (i *2 -max)) /max;
          val3 = (b2 * (max*2 -i*2)  + b1 * (i *2 -max)) /max;
        }
      }
      if (val1 < 0){
        val1 = 0;
      }
      if (val2 < 0){
        val2 = 0;
      }
      if (val3 < 0){
        val3 = 0;
      }
      if (val1 > 0xff){
        val1 = 0xff;
      }
      if (val2 > 0xff){
        val2 = 0xff;
      }
      if (val3 > 0xff){
        val3 = 0xff;
      }
      WSCulong cval = WSGFxcolorval(color,val1,val2,val3);
      XSetForeground(_display,_gc,cval);
      XDrawLine(_display,_window,_gc,(int)x,(int)(y+h1),(int)(x+w),(int)(y+h1)); 
    }
  }else{
    long max = w* (100 -gradm)/100;
    long wval = max/64+1;
    XSetLineAttributes(_display,_gc,wval+1,LineSolid,CapProjecting,WS_JOIN);
    for(i=0; i<max; i+=wval){
      long w1 = i;
      if (w1 >= max/2){
        w1 = i+ w * gradm/100;
      }
      if (_clip_x != -1){
        if (_clip_x > w1+x || _clip_x + _clip_w < w1+x){
//          continue;
        }
      }
      long val1,val2,val3;
      if (type == WS_GR_L_R){
        if (i < max/2){ 
          val1 = (r1 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g1 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b1 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max*2 -i*2)  + r3 * (i *2 -max)) /max;
          val2 = (g2 * (max*2 -i*2)  + g3 * (i *2 -max)) /max;
          val3 = (b2 * (max*2 -i*2)  + b3 * (i *2 -max)) /max;
        }
      }else{
        if (i < max/2){ 
          val1 = (r3 * (max -i*2)  + r2 * i *2) /max;
          val2 = (g3 * (max -i*2)  + g2 * i *2) /max;
          val3 = (b3 * (max -i*2)  + b2 * i *2) /max;
        }else{ 
          val1 = (r2 * (max*2 -i*2)  + r1 * (i *2 -max)) /max;
          val2 = (g2 * (max*2 -i*2)  + g1 * (i *2 -max)) /max;
          val3 = (b2 * (max*2 -i*2)  + b1 * (i *2 -max)) /max;
        }
      }
      if (val1 < 0){
        val1 = 0;
      }
      if (val2 < 0){
        val2 = 0;
      }
      if (val3 < 0){
        val3 = 0;
      }
      if (val1 > 0xff){
        val1 = 0xff;
      }
      if (val2 > 0xff){
        val2 = 0xff;
      }
      if (val3 > 0xff){
        val3 = 0xff;
      }
      WSCulong cval = WSGFxcolorval(color,val1,val2,val3);
      XSetForeground(_display,_gc,cval);
      XDrawLine(_display,_window,_gc,(int)(w1+x),(int)y,(int)(w1+x),(int)y+h); 
    }
  }
  long linet = _line_type;
  _line_type = -1;
  setLineDashType(linet);
  setRegion(clx_bk,cly_bk,clw_bk,clh_bk);

  return WS_NO_ERR;
#endif //XXZZ
printf("WSDmacDraw::drawGradation.. not supported\n");
  return WS_NO_ERR;
}
void WSDmacDraw::setExposed(WSCbool fl){
  _exposed = fl;
}
