//
// 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 <windows.h>
#include <win/WSDwindraw.h>
#include <win/WSDwinFont.h>
#include <WSDfont.h>
#include <WSCfontSet.h>
#include <WSDcolor.h>
#include <WSCcolorSet.h>
#include <WSDimage.h>
#include <WSCimageSet.h>
#include <WSCstring.h>
//#include <WSDwincom.h>
#include <win/WSDwinappDev.h>
#include <WSCvarc.h>

WSMFclassInit(WSDwindraw,WSCroot);
#define HS_DOT 8
static long fgcolor = -100;
static long bgcolor = -100;
static char _fill_type = -1;
#if 0
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 HBITMAP  _hatch[9] = { 0,0,0,0,0,0,0,0,0 };
#endif

static long _clip_x = 0;
static long _clip_y = 0;
static WSCulong _clip_w = 0xffffffff;
static WSCulong _clip_h = 0xffffffff;
static HDC _printer_hdc = 0x0;

WSDwindraw::WSDwindraw(){
  _fg_color = 0;
  _bg_color = 0;
  _line_width = -1;
  _line_type = -1;
  _clipping = False;
  _dash_no = PS_SOLID;
  _printer = False;
}
WSDwindraw::~WSDwindraw(){}
WSCushort _pr_x;
WSCushort _pr_y;
WSCushort _pr_w;
WSCushort _pr_h;
double _pr_scale_x;
double _pr_scale_y;
long WSDwindraw::setValue(long kind,long val){
  if (kind == WSDEV_WORK_X){
    _pr_x = val;
    return WS_NO_ERR;
  }else
  if (kind == WSDEV_WORK_Y){
    _pr_y = val;
    return WS_NO_ERR;
  }else
  if (kind == WSDEV_WORK_WIDTH){
    _pr_w = val;
    return WS_NO_ERR;
  }else
  if (kind == WSDEV_WORK_HEIGHT){
    _pr_h = val;
    return WS_NO_ERR;
  }else
  if (kind == WSDEV_PR_PRINTER){
    if (val != 0){
      _printer = True;
      PRINTDLG pd;
      pd.lStructSize = sizeof(PRINTDLG);
      pd.hwndOwner = NULL;
      pd.hDevMode = NULL;
      pd.hDevNames = NULL;
      pd.hDC = NULL;
      pd.Flags = PD_ALLPAGES | PD_COLLATE | PD_RETURNDC;
      pd.nFromPage =0;
      pd.nToPage =0;
      pd.nMinPage =0;
      pd.nMaxPage =0;
      pd.nCopies =0;
      pd.hInstance =NULL;
      pd.lCustData =0L;
      pd.lpfnPrintHook =NULL;
      pd.lpfnSetupHook =NULL;
      pd.lpPrintTemplateName =NULL;
      pd.lpSetupTemplateName =NULL;
      pd.hPrintTemplate =NULL;
      pd.hSetupTemplate =NULL;

      BOOL ret = PrintDlg(&pd);
//    _printer_hdc = CreateDC("WINSPOOL","Acrobat PDFWriter",NULL,NULL);
      if (ret == FALSE){
//printf("err ret0\n");
        return WS_ERR;
      }

      _printer_hdc = pd.hDC;
      if (_printer_hdc == 0){
        exit(1);
      }
      int v = GetDeviceCaps(_printer_hdc,HORZSIZE);
//printf("horz=%d\n",v);
      v = GetDeviceCaps(_printer_hdc,VERTSIZE);
//printf("vert=%d\n",v);
      v = GetDeviceCaps(_printer_hdc,HORZRES);
      _pr_scale_x = (double)v/_pr_w;
//printf("hpix=%d %lf\n",v,_pr_scale_x);
      v = GetDeviceCaps(_printer_hdc,VERTRES);
      _pr_scale_y = (double)v/_pr_h;
//printf("vpix=%d %lf\n",v,_pr_scale_y);

      DOCINFO di;
      memset(&di,0,sizeof(DOCINFO));
      di.cbSize = sizeof(DOCINFO);
      di.lpszDocName = "WsDoc";
      if (StartDoc(_printer_hdc,&di) != SP_ERROR){
        StartPage(_printer_hdc);
      }else{
        DeleteDC(_printer_hdc);
        _printer_hdc = 0;
        _printer = False;
//printf("err ret1\n");
        return WS_ERR;
      }
      return WS_NO_ERR;
    }
    if (val == 0){
      _printer = False;
      if (_printer_hdc != 0){
        EndPage(_printer_hdc);
        EndDoc(_printer_hdc);
        DeleteDC(_printer_hdc);
        _printer_hdc = 0;
      }
    }
    return WS_NO_ERR;
  }
//printf("err ret2\n");
  return WS_ERR;
}

long WSDwindraw::setForeColor(short cno){
  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
  long bk = fgcolor;
  if (color != NULL){
    fgcolor = cno;
    _fg_color = (COLORREF)color->getValue1();
//printf("WSDwindraw::setForeColor cno=%d cname=%s cref=0x%x\n",cno,color->getSrc(),_fg_color);
  }
  if (bk == -1){
    bk = fgcolor;
  }
  return bk;
}
long WSDwindraw::setForeColor(WSDcolor* color){
//  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
  long bk = fgcolor;
  if (color != NULL){
    fgcolor = color->getId();
    _fg_color = (COLORREF)color->getValue1();
//printf("WSDwindraw::setForeColor cno=%d cname=%s cref=0x%x\n",cno,color->getSrc(),_fg_color);
  }
  if (bk == -1){
    bk = fgcolor;
  }
  return bk;
}

long WSDwindraw::setBackColor(short cno){
  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
  long bk = bgcolor;
  if (color != NULL){
    bgcolor = cno;
    _bg_color = (COLORREF)color->getValue1();
  }
  if (bk == -1){
    bk = bgcolor;
  }
  return bk;
}
long WSDwindraw::setBackColor(WSDcolor* color){
//  WSDcolor*  color = WSGIappColorSet()->getColor(cno);
  long bk = bgcolor;
  if (color != NULL){
    bgcolor = color->getId();
    _bg_color = (COLORREF)color->getValue1();
  }
  if (bk == -1){
    bk = bgcolor;
  }
  return bk;
}
long WSDwindraw::setLineWidth(short width){
  if (_printer_hdc != 0){
    width = (short)(width * _pr_scale_x);
  }
  if (_line_width == width){
    return _line_width;
  }
  long bk = _line_width;
  _line_width = width;
  return bk;
}
long WSDwindraw::setLineDashType(char type){
  if (_line_type == type){
    return WS_NO_ERR;
  }
  long bk = _line_type;
  _line_type = type;
  switch(type){
    case 0:
      _dash_no = PS_SOLID;
      break;
    case 1:
    case 8:
      _dash_no = PS_DOT;
      break;
    case 2:
    case 3:
      _dash_no = PS_DASH;
      break;
    case 4:
    case 6:
      _dash_no = PS_DASHDOT;
      break;
    case 5:
    case 7:
      _dash_no = PS_DASHDOTDOT;
      break;
    default:
      _dash_no = PS_SOLID;
  }
  return bk;
}
long WSDwindraw::setHatchPattern(char type){
//  if (_fill_type == type){
//    return WS_NO_ERR;
//  }
  long bk = _fill_type;
  _fill_type = type;
  _hatch_att = 1;
  _hatch = 0;
  switch(type){
    case 0: 
      _hatch_att =1;
      break;
    case 1: 
      _hatch_att =0;
      _hatch = HS_BDIAGONAL;
      break;
    case 2:
      _hatch_att =0;
      _hatch = HS_FDIAGONAL;
      break;
    case 3:
      _hatch_att =0;
      _hatch = HS_VERTICAL;
      break;
    case 4:
      _hatch_att =0;
      _hatch = HS_HORIZONTAL;
      break;
    case 5:
      _hatch_att =0;
      _hatch = HS_DIAGCROSS;
      break;
    case 6:
      _hatch_att =0;
      _hatch = HS_CROSS;
      break;
    case 7:
      _hatch_att =0;
      _hatch = HS_DOT;
    default:
      _hatch_att =1;
      break;
  }
//printf("WSDwindraw::setHatchPattern _att=%d _hatch=%d\n",_hatch_att,_hatch);
  return bk;
}
long WSDwindraw::beginDraw(WSDdev* dev,long val1,long val2,long val3){

  _dev = dev;

  _fg_color = 0;
  _bg_color = 0;
//printf("windraw::beginDraw hdc=0x%x\n",val3);
  _hdc =   (HDC)val3;
  if (_printer_hdc != 0){
    _hdc = _printer_hdc;
  }
  _palette = WSGIwinAppDev()->getPalette();
  _palette_bk = 0;
  if (_hdc == 0){
    return WS_ERR;
  }
//  HRGN rgn = CreateRectRgn(0,0,0xffffffff,0xffffffff);
//  SelectClipRgn(_hdc,rgn);
//  DeleteObject((void*)rgn);
  SelectClipRgn(_hdc,(HRGN)0);

  if (_palette != NULL ){
    _palette_bk = SelectPalette(_hdc,_palette,False);
    RealizePalette(_hdc);
  }
  setLineDashType(0);
  setLineWidth(0);
  setHatchPattern(0);

  return WS_NO_ERR;
}

long WSDwindraw::endDraw(){
//printf("windraw::endDraw hdc=0x%x\n",_hdc);
  if (_hdc == 0){
    return WS_ERR;
  }
  if (_hdc == 0 && _palette != 0){
    SelectPalette(_hdc,_palette_bk,False);
  }
  _hdc = 0;
  return WS_NO_ERR;
}

long WSDwindraw::setRegion(short x,short y,WSCushort w,WSCushort h){
  if (_hdc == (HDC)0){
    return WS_ERR;
  }
WSMFtrace("WSDwindraw::setResion %d,%d,%d,%d    XXZZ33x\n",x,y,w,h);
  if (w > 2048){
    w = 2048;
  }
  if (h > 2048){
    h = 2048;
  }
  if (_printer_hdc != 0){
    short x1 = (short)((x - _pr_x) * _pr_scale_x);
    short y1 = (short)((y - _pr_y) * _pr_scale_y);
    WSCulong x2 = (WSCulong)((x - _pr_x +w) * _pr_scale_x );
    WSCulong y2 = (WSCulong)((y - _pr_y +h) * _pr_scale_y );
    HRGN rgn = CreateRectRgn(x1,y1,x2,y2);
//    WSCushort w1 = (WSCushort)(w * _pr_scale_x);
//    WSCushort h1 = (WSCushort)(h * _pr_scale_y);
//    HRGN rgn = CreateRectRgn(x1,y1,x1 + w1,y1 + h1);
    SelectClipRgn(_hdc,rgn);
    DeleteObject((void*)rgn);
  }else{
    HRGN rgn = CreateRectRgn(x,y,x+w,y+h);
    SelectClipRgn(_hdc,rgn);
    DeleteObject((void*)rgn);
  }
  _clip_x = x;
  _clip_y = y;
  _clip_w = w;
  _clip_h = h;
  return WS_NO_ERR;
}

long WSDwindraw::drawArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2){
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    w = (WSCushort)(w * _pr_scale_x);
    h = (WSCushort)(h * _pr_scale_y);
  }
  if (_hdc == 0 ){
    return WS_ERR;
  }
  if (_line_width < 1){
    _line_width = 1;
  }
  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
  SetBkMode(_hdc,TRANSPARENT);

  double vx1 = x + w/2 + cos(3.141592 *a1/64.0/180.0)*w/2;
  double vy1 = y + h/2 - sin(3.141592 *a1/64.0/180.0)*h/2;
  double vx2 = x + w/2 + cos(3.141592 *(a1+a2)/64.0/180.0)*w/2;
  double vy2 = y + h/2 - sin(3.141592 *(a1+a2)/64.0/180.0)*h/2;
  Arc(_hdc,x,y,x+w,y+h, (int)vx1,(int)vy1,(int)vx2,(int)vy2);

  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  DeleteObject((void*)pen);

  return WS_NO_ERR;
//WSMFtrace("WSDwindraw::drawArc() is not implemented..\n");
//#if 0
//  if (_gc == 0 || _window == 0){
//    return WS_ERR;
//  }
//  XDrawArc(_display,_window,_gc,x,y,w,h,a1,a2);
//#endif
//  return WS_NO_ERR;
}
long WSDwindraw::drawFillArc(short x,short y,WSCushort w,WSCushort h,short a1,short a2,char kind){
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    w = (WSCushort)(w * _pr_scale_x);
    h = (WSCushort)(h * _pr_scale_y);
  }
  if (_hdc == 0 ){
    return WS_ERR;
  }
  if (_line_width < 1){
    _line_width = 1;
  }
  HPEN pen = CreatePen(PS_NULL,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);

  HBRUSH brush;
  if (_hatch_att == 0 && _hatch != HS_DOT ){
    brush = CreateHatchBrush(_hatch,_fg_color);
  }else{
    brush = CreateSolidBrush(_fg_color);
  }
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

  SetBkMode(_hdc,TRANSPARENT);
  double vx1 = x + w/2 + cos(3.141592 *a1/64.0/180.0)*w/2;
  double vy1 = y + h/2 - sin(3.141592 *a1/64.0/180.0)*h/2;
  double vx2 = x + w/2 + cos(3.141592 *(a1+a2)/64.0/180.0)*w/2;
  double vy2 = y + h/2 - sin(3.141592 *(a1+a2)/64.0/180.0)*h/2;
  if (kind == WS_PI){
    Pie(_hdc,x,y,x+w,y+h, (int)vx1,(int)vy1,(int)vx2,(int)vy2);
  }else{
    Chord(_hdc,x,y,x+w,y+h, (int)vx1,(int)vy1,(int)vx2,(int)vy2);
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
  DeleteObject((void*)pen);
  DeleteObject((void*)brush);

  return WS_NO_ERR;
#if 0
  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);
#endif
}
static void _draw_dot(short x1,short y1,short x2,short y2,HDC _hdc){
  if (x1 == x2){
    long val1 ,val2;
    if (y1 > y2){
      val1 = y2;
      val2 = y1;
    }else{
      val1 = y1;
      val2 = y2;
    }
    long i;
    for(i = val1; i< val2; i+= 2){
      MoveToEx(_hdc,x1,i,NULL);
      LineTo(_hdc,x1,i+1);
    }
  }else{
    long val1 ,val2;
    if (x1 > x2){
      val1 = x2;
      val2 = x1;
    }else{
      val1 = x1;
      val2 = x2;
    }
    long i;
    for(i = val1; i< val2; i+= 2){
      MoveToEx(_hdc,i,y1,NULL);
      LineTo(_hdc,i+1,y1);
    }
  }
}
long WSDwindraw::drawLine(short x1,short y1,short x2,short y2){
  if (_printer_hdc != 0){
    x1 = (short)((x1 - _pr_x) * _pr_scale_x);
    y1 = (short)((y1 - _pr_y) * _pr_scale_y);
    x2 = (short)((x2 - _pr_x) * _pr_scale_x);
    y2 = (short)((y2 - _pr_y) * _pr_scale_y);
  }
  if (_hdc == 0 ){
    return WS_ERR;
  }
  if (_line_width < 1){
    _line_width = 1;
  }
WSMFtrace("WSDwindraw::drawLine %d,%d,%d,%d  hdc=0x%x\n",x1,y1,x2,y2,_hdc);
  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
  SetBkMode(_hdc,TRANSPARENT);
  if ( _line_type == 8 && ( (x1 == x2) || (y1 == y2)) && _line_width < 2 ){
    _draw_dot(x1,y1,x2,y2,_hdc);
  }else{
    MoveToEx(_hdc,x1,y1,NULL);
    LineTo(_hdc,x2,y2);
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  DeleteObject((void*)pen);

  return WS_NO_ERR;
}
long WSDwindraw::drawLines(WSCpoint* points,long num){
  if (_hdc == 0 ){
    return WS_ERR;
  }
  if (num <2){
    return WS_NO_ERR;
  }
  if (_line_width < 1){
    _line_width = 1;
  }
  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
  SetBkMode(_hdc,TRANSPARENT);
  if (_printer_hdc != 0){
    long x = (short)((points[0].x - _pr_x) * _pr_scale_x);
    long y = (short)((points[0].y - _pr_y) * _pr_scale_y);
    MoveToEx(_hdc,x,y,NULL);
    int i;
    for(i=1; i<num; i++){
      x = (short)((points[i].x - _pr_x) * _pr_scale_x);
      y = (short)((points[i].y - _pr_y) * _pr_scale_y);
      LineTo(_hdc,x,y);
    }
  }else{
    int i;
    MoveToEx(_hdc,points[0].x,points[0].y,NULL);
    for(i=1; i<num; i++){
      LineTo(_hdc,points[i].x,points[i].y);
    }
  }

  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  DeleteObject((void*)pen);

  return WS_NO_ERR;
}
long WSDwindraw::drawRect(short x,short y,WSCushort w,WSCushort h){
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    w = (WSCushort)(w * _pr_scale_x);
    h = (WSCushort)(h * _pr_scale_y);
  }

  if (_hdc == 0 ){
    return WS_ERR;
  }
//printf("WSDwindraw::drawRect %d,%d,%d,%d\n",x,y,w,h);
  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);

  LOGBRUSH lb;
  lb.lbStyle = BS_NULL;
  lb.lbColor = _bg_color;
  lb.lbHatch = _hatch;
  HBRUSH brush = CreateBrushIndirect(&lb);
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

  SetBkMode(_hdc,TRANSPARENT);
  if ( _line_type == 8 && _line_width < 2 ){
    _draw_dot(x,y,x,y+h-1,_hdc);
    _draw_dot(x,y,x+w-1,y,_hdc);
    _draw_dot(x,y+h-1,x+w-1,y+h-1,_hdc);
    _draw_dot(x+w-1,y,x+w-1,y+h-1,_hdc);
  }else{
    Rectangle(_hdc,x,y,x+w,y+h);
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
  DeleteObject((void*)pen);
  DeleteObject((void*)brush);

  return WS_NO_ERR;
}
long WSDwindraw::drawFillRect(short x,short y,WSCushort w,WSCushort h){
  if (_hdc == 0 ){
    return WS_ERR;
  }

//  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen = CreatePen(PS_NULL,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
//  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)NULL_PEN);

  HBRUSH brush;
  if (_hatch_att == 0 && _hatch != HS_DOT ){
    brush = CreateHatchBrush(_hatch,_fg_color);
  }else{
    brush = CreateSolidBrush(_fg_color);
  }
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

  SetBkMode(_hdc,TRANSPARENT);
#if 0
  RECT r;
  r.left = x;
  r.top = y;
  r.right = x+w+1;
  r.bottom = y+h+1;
  FillRect(_hdc,&r,brush);
#endif
  if (_hatch != HS_DOT){
    if (_printer_hdc != 0){
      x = (short)((x - _pr_x) * _pr_scale_x);
      y = (short)((y - _pr_y) * _pr_scale_y);
      w = (WSCushort)(w * _pr_scale_x);
      h = (WSCushort)(h * _pr_scale_y);
    }
    Rectangle(_hdc,x,y,x+w+1,y+h+1);
  }else{
    HPEN pen = CreatePen(PS_SOLID,1,_fg_color);
    HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
    long cx = _clip_x;
    long cy = _clip_y;
    long cw = _clip_w;
    long ch = _clip_h;
    setRegion(x,y,w,h);
    int i,x1,y2;
    int x2 = x;
    int y1 = y;
    for(i=1; i<w+h;i+=2){
      x1 = x + i;
      y2 = y + i;
      if (_printer_hdc != 0){
        x1 = (short)((x1 - _pr_x) * _pr_scale_x);
        y1 = (short)((y1 - _pr_y) * _pr_scale_y);
        x2 = (short)((x2 - _pr_x) * _pr_scale_x);
        y2 = (short)((y2 - _pr_y) * _pr_scale_y);
        MoveToEx(_hdc,x1,y1,NULL);
        LineTo(_hdc,x2,y2);
      }else{
        MoveToEx(_hdc,x1,y1,NULL);
        LineTo(_hdc,x2,y2);
      }
    }
    SelectObject(_hdc,(void*)pen_bk);
    DeleteObject((void*)pen);
    setRegion(cx,cy,cw,ch);
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
  DeleteObject((void*)pen);
  DeleteObject((void*)brush);

  return WS_NO_ERR;
}
long WSDwindraw::drawRects(WSCrect* rects,long num){
  if (_hdc == 0 ){
    return WS_ERR;
  }

  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);

  LOGBRUSH lb;
  lb.lbStyle = BS_NULL;
  lb.lbColor = _bg_color;
  lb.lbHatch = _hatch;
  HBRUSH brush = CreateBrushIndirect(&lb);
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);
//  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)NULL_BRUSH);

  SetBkMode(_hdc,TRANSPARENT);
  if (_printer_hdc != 0){
    int i;
    for(i=0; i<num; i++){
      long x = (short)((rects[i].x - _pr_x) * _pr_scale_x);
      long y = (short)((rects[i].y - _pr_y) * _pr_scale_y);
      long w = (WSCushort)(rects[i].width * _pr_scale_x);
      long h = (WSCushort)(rects[i].height * _pr_scale_y);
      if ( _line_type == 9 && _line_width < 2 ){
        _draw_dot(x,y,x,y+h,_hdc);
        _draw_dot(x,y,x+w,y,_hdc);
        _draw_dot(x,y+h,x+w,y+h,_hdc);
        _draw_dot(x+w,y,x+w,y+h,_hdc);
      }else{
        Rectangle(_hdc,x,y, x+w+1,y+h+1);
      }
    }
  }else{
    int i;
    for(i=0; i<num; i++){
      if ( _line_type == 9 && _line_width < 2 ){
        long x = rects[i].x;
        long y = rects[i].y;
        long w = rects[i].width;
        long h = rects[i].height;
        _draw_dot(x,y,x,y+h,_hdc);
        _draw_dot(x,y,x+w,y,_hdc);
        _draw_dot(x,y+h,x+w,y+h,_hdc);
        _draw_dot(x+w,y,x+w,y+h,_hdc);
      }else{
        Rectangle(_hdc,rects[i].x,rects[i].y,
              (rects[i].x+rects[i].width+1),(rects[i].y+rects[i].height+1));
      }
    }
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
  DeleteObject((void*)pen);
  DeleteObject((void*)brush);

  return WS_NO_ERR;
}
long WSDwindraw::drawFillRects(WSCrect* rects,long num){
  if (_hdc == 0 ){
    return WS_ERR;
  }

//  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
//  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)NULL_PEN);

  HBRUSH brush;
  if (_hatch_att == 0){
    brush = CreateHatchBrush(_hatch,_fg_color);
  }else{
    brush = CreateSolidBrush(_fg_color);
  }
//  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)NULL_BRUSH);
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

  SetBkMode(_hdc,TRANSPARENT);
  if (_printer_hdc != 0){
    int i;
    for(i=0; i<num; i++){
      long x = (short)((rects[i].x - _pr_x) * _pr_scale_x);
      long y = (short)((rects[i].y - _pr_y) * _pr_scale_y);
      long w = (WSCushort)(rects[i].width * _pr_scale_x);
      long h = (WSCushort)(rects[i].height * _pr_scale_y);
      Rectangle(_hdc,x,y, x+w+1,y+h+1);
    }
  }else{
    int i;
    for(i=0; i<num; i++){
      Rectangle(_hdc,rects[i].x,rects[i].y,
              (rects[i].x+rects[i].width+1),(rects[i].y+rects[i].height+1));
    }
  }
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
 // DeleteObject((void*)pen);
  DeleteObject((void*)brush);

  return WS_NO_ERR;
}
long WSDwindraw::drawPoly(WSCpoint* points,long num){
  if (_hdc == 0 ){
    return WS_ERR;
  }

  HPEN pen = CreatePen(_dash_no,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
  SetBkMode(_hdc,TRANSPARENT);
  POINT* pt = new POINT[num+1];
  if (_printer_hdc != 0){
    int i;
    for(i=0; i<num; i++){
      pt[i].x = (short)((points[i].x - _pr_x) * _pr_scale_x);
      pt[i].y = (short)((points[i].y - _pr_y) * _pr_scale_y);
    }
    pt[num].x = (short)((points[0].x - _pr_x) * _pr_scale_x);
    pt[num].y = (short)((points[0].y - _pr_y) * _pr_scale_y);
  }else{
    int i;
    for(i=0; i<num; i++){
      pt[i].x = points[i].x;
      pt[i].y = points[i].y;
    }
    pt[num].x = points[0].x;
    pt[num].y = points[0].y;
  }
  Polyline(_hdc,pt,num+1);
  delete pt;
  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  DeleteObject((void*)pen);

  return WS_NO_ERR;
}

long WSDwindraw::drawFillPoly(WSCpoint* points,long num){
  if (_hdc == 0 ){
    return WS_ERR;
  }

  HPEN pen = CreatePen(PS_NULL,_line_width,_fg_color);
  HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);

  HBRUSH brush;
  if (_hatch_att == 0){
    brush = CreateHatchBrush(_hatch,_fg_color);
  }else{
    brush = CreateSolidBrush(_fg_color);
  }
  HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

  SetBkMode(_hdc,TRANSPARENT);


  POINT* pt = new POINT[num];
  if (_printer_hdc != 0){
    int i;
    for(i=0; i<num; i++){
      pt[i].x = (short)((points[i].x - _pr_x) * _pr_scale_x);
      pt[i].y = (short)((points[i].y - _pr_y) * _pr_scale_y);
    }
  }else{
    int i;
    for(i=0; i<num; i++){
      pt[i].x = points[i].x;
      pt[i].y = points[i].y;
    }
  }
  Polygon(_hdc,pt,num);
  delete pt;

  SetBkMode(_hdc,OPAQUE);
  SelectObject(_hdc,(void*)pen_bk);
  SelectObject(_hdc,(void*)brush_bk);
  DeleteObject((void*)brush);
  DeleteObject((void*)pen);

  return WS_NO_ERR;
}

long WSDwindraw::drawStretchedImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image){
//long XXZZXXZZ;
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    w = (WSCushort)(w * _pr_scale_x);
    h = (WSCushort)(h * _pr_scale_y);
  }
  if (_hdc == NULL || image == NULL){
    return WS_ERR;
  }
  HBITMAP pix = (HBITMAP)image->getValue1();
  HBITMAP pix2 = (HBITMAP)image->getValue3();
  if (pix == 0){
    return WS_NO_ERR;
  }
  long icon = (long)image->getValue2();
  if (icon == 0){
    HDC mdc = CreateCompatibleDC(_hdc);
    HDC mdc2 = 0;
    
    HPALETTE pl = WSGIwinAppDev()->getPalette();
    HPALETTE plbk = 0;
    HPALETTE plbk2 = 0;
    if (pl != 0){
      plbk = SelectPalette(mdc,pl,FALSE);
      RealizePalette(mdc);
      if (pix2 != 0){
        plbk2 = SelectPalette(mdc2,pl,FALSE);
        RealizePalette(mdc2);
      }
    }
    HBITMAP pxbk = (HBITMAP)SelectObject(mdc,(void*)pix);
    SetMapMode(mdc,GetMapMode(_hdc));

    HBITMAP pxbk2 = (HBITMAP)0;
    if (pix2 != 0){
      pxbk2 = (HBITMAP)SelectObject(mdc2,(void*)pix2);
      SetMapMode(mdc2,GetMapMode(_hdc));
    }

    WSCulong iw = image->getImageWidth();
    WSCulong ih = image->getImageHeight();
    SetStretchBltMode(_hdc,STRETCH_DELETESCANS);
    if (pix2 == 0){
      StretchBlt(_hdc,x,y,w,h,mdc,0,0,iw,ih,SRCCOPY);
    }else{
      StretchBlt(_hdc,x,y,w,h,mdc2,0,0,iw,ih,SRCAND);
      StretchBlt(_hdc,x,y,w,h,mdc,0,0,iw,ih,SRCPAINT);
    }
    if (pl != 0){
      SelectPalette(mdc,plbk,FALSE);
      if (pix2 != 0){
        SelectPalette(mdc2,plbk2,FALSE);
      }
    }
    SelectObject(mdc,pxbk);
    DeleteDC(mdc);
    if (pix2 != 0){
      SelectObject(mdc2,pxbk2);
      DeleteDC(mdc2);
    }
  }else{
    DrawIconEx(_hdc,x,y,(HICON)pix,w,h,0,NULL,DI_NORMAL);
  }

  return WS_NO_ERR;
}
long WSDwindraw::drawImage(short x,short y,WSCushort w,WSCushort h,WSDimage* image,char align){
  if (_hdc == NULL || image == NULL){
    return WS_ERR;
  }
  HBITMAP pix = (HBITMAP)image->getValue1();
  HBITMAP pix2 = (HBITMAP)image->getValue3();
  if (pix == 0){
    return WS_NO_ERR;
  }
  if (pix2 == (HBITMAP)-1){
    pix2 = 0;
  }
  long icon = (long)image->getValue2();

  POINT p;
  p.x = image->getImageWidth();
  p.y = image->getImageHeight();
  DPtoLP(_hdc,&p,1);

  WSCushort pw = p.x;
  WSCushort ph = p.y;

  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 (icon == 0){
    long dx1,dy1;
    WSCulong dw1,dh1;
    long dx,dy;
    WSCulong dw,dh;

    WSGFandArea(x,y,w,h,_clip_x,_clip_y,_clip_w,_clip_h,&dx1,&dy1,&dw1,&dh1);
    WSGFandArea(dx1,dy1,dw1,dh1,x+xoff,y+yoff,pw,ph,&dx,&dy,&dw,&dh);

    HDC mdc = CreateCompatibleDC(_hdc);
    HDC mdc2 = 0;
    if (pix2 != 0){
      mdc2 = CreateCompatibleDC(_hdc);
    }
    HPALETTE pl = WSGIwinAppDev()->getPalette();
    HPALETTE plbk = 0;
    HPALETTE plbk2 = 0;
    if (pl != 0){
      plbk = SelectPalette(mdc,pl,FALSE);
      RealizePalette(mdc);
      if (mdc2 != 0){
        plbk2 = SelectPalette(mdc2,pl,FALSE);
        RealizePalette(mdc2);
      }
    }
    HBITMAP pxbk = (HBITMAP)SelectObject(mdc,(void*)pix);
    HBITMAP pxbk2 = (HBITMAP)0;
    SetMapMode(mdc,GetMapMode(_hdc));
    if (pix2 != 0){
      pxbk2 = (HBITMAP)SelectObject(mdc2,(void*)pix2);
      SetMapMode(mdc2,GetMapMode(_hdc));
    }
    if (_printer_hdc != 0){
      x = (short)((x - _pr_x) * _pr_scale_x);
      y = (short)((y - _pr_y) * _pr_scale_y);
      xoff = (short)((xoff - _pr_x) * _pr_scale_x);
      yoff = (short)((yoff - _pr_y) * _pr_scale_y);
      dx = (short)((dx - _pr_x) * _pr_scale_x);
      dy = (short)((dy - _pr_y) * _pr_scale_y);
      dw = (WSCushort)(dw * _pr_scale_x);
      dh = (WSCushort)(dh * _pr_scale_y);
      SetStretchBltMode(_hdc,STRETCH_DELETESCANS);
      WSCulong iw = image->getImageWidth();
      WSCulong ih = image->getImageHeight();
      if (pix2 == 0){
        StretchBlt(_hdc,dx,dy,dw,dh,mdc,dx -x -xoff,dy-y-yoff,iw,ih,SRCCOPY);
      }else{
        StretchBlt(_hdc,dx,dy,dw,dh,mdc2,dx -x -xoff,dy-y-yoff,iw,ih,SRCAND);
        BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
        BitBlt(mdc,0,0,iw,ih,mdc2,0,0,SRCAND);
        StretchBlt(_hdc,dx,dy,dw,dh,mdc,dx -x -xoff,dy-y-yoff,iw,ih,SRCPAINT);
        BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
      }
    }else{
      if (pix2 == 0){
        BitBlt(_hdc,dx,dy,dw,dh,mdc,dx -x -xoff,dy -y -yoff,SRCCOPY);
      }else{
        BitBlt(_hdc,dx,dy,dw,dh,mdc2,dx -x -xoff,dy -y -yoff,SRCAND);
        WSCulong iw = image->getImageWidth();
        WSCulong ih = image->getImageHeight();
        BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
        BitBlt(mdc,0,0,iw,ih,mdc2,0,0,SRCAND);
        BitBlt(_hdc,dx,dy,dw,dh,mdc,dx -x -xoff,dy -y -yoff,SRCPAINT);
        BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
      }
    }
    if (pl != 0){
      SelectPalette(mdc,plbk,FALSE);
      if (pix2 != 0){
        SelectPalette(mdc2,plbk2,FALSE);
      }
    }
    SelectObject(mdc,pxbk);
    DeleteDC(mdc);
    if (pix2 != 0){
      SelectObject(mdc2,pxbk2);
      DeleteDC(mdc2);
    }

  }else{
    short clx_bk = _clip_x;
    short cly_bk = _clip_y;
    WSCushort clw_bk = _clip_w;
    WSCushort clh_bk = _clip_h;
    long clx,cly;
    WSCulong clw,clh;
    WSGFandArea(x,y,w,h,_clip_x,_clip_y,_clip_w,_clip_h,&clx,&cly,&clw,&clh);
    setRegion(clx,cly,clw,clh);
    if (_printer_hdc != 0){
      x = (short)((x - _pr_x) * _pr_scale_x);
      y = (short)((y - _pr_y) * _pr_scale_y);
      xoff = (short)((xoff - _pr_x) * _pr_scale_x);
      yoff = (short)((yoff - _pr_y) * _pr_scale_y);
      pw = (WSCushort)(pw * _pr_scale_x);
      ph = (WSCushort)(ph * _pr_scale_y);
    } 
    DrawIconEx(_hdc,x+xoff,y+yoff,(HICON)pix,pw,ph,0,NULL,DI_NORMAL);
    setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
  }
//printf("windraw::drawImage dx,dy=%d,%d xoff,yoff=%d,%d\n",dx,dy,xoff,yoff);  
//printf("windraw::drawImage %d %d %d %d 0x%x\n",dx -x -xoff,dy -y -yoff,dw,dh,pix);  
  
//  XCopyArea(_display,pix1,_window,_gc, dx -x -xoff,dy -y -yoff, dw,dh,dx,dy);

  return WS_NO_ERR;
}

long WSDwindraw::drawImage(short x,short y,short sx,short sy,WSCushort w,WSCushort h,WSDimage* image){
//printf("WSDwindraw::drawImage...\n");
  if (_hdc == 0){
    return WS_ERR;
  }
  HBITMAP pix = (HBITMAP)image->getValue1();
  HBITMAP pix2 = (HBITMAP)image->getValue3();

  if (pix == (HBITMAP)-1 || pix == (HBITMAP)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);

  HDC mdc = CreateCompatibleDC(_hdc);
  HDC mdc2 = 0;
  HPALETTE plbk2 = 0;
  if (pix2 != 0){
    mdc2 = CreateCompatibleDC(_hdc);
  }

  HPALETTE pl = WSGIwinAppDev()->getPalette();
  HPALETTE plbk = 0;
  if (pl != 0){
    plbk = SelectPalette(mdc,pl,FALSE);
    RealizePalette(mdc);
    if (pix2 != 0){
      plbk2 = SelectPalette(mdc2,pl,FALSE);
      RealizePalette(mdc2);
    }
  }


  HBITMAP pxbk = (HBITMAP)SelectObject(mdc,(void*)pix);
  SetMapMode(mdc,GetMapMode(_hdc));
  HBITMAP pxbk2 = (HBITMAP)0;
  if (pix2 !=0){
    pxbk2 = (HBITMAP)SelectObject(mdc2,(void*)pix2);
    SetMapMode(mdc2,GetMapMode(_hdc));
  } 
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    sx = (short)((sx - _pr_x) * _pr_scale_x);
    sy = (short)((sy - _pr_y) * _pr_scale_y);
    dx = (short)((dx - _pr_x) * _pr_scale_x);
    dy = (short)((dy - _pr_y) * _pr_scale_y);
    dw = (WSCushort)(dw * _pr_scale_x);
    dh = (WSCushort)(dh * _pr_scale_y);
    SetStretchBltMode(_hdc,STRETCH_DELETESCANS);
    WSCulong iw = image->getImageWidth();
    WSCulong ih = image->getImageHeight();
    if (pix2 == 0){
      StretchBlt(_hdc,dx,dy,dw,dh,mdc,dx -x +sx,dy -y +sy,iw,ih,SRCCOPY);
    }else{
      StretchBlt(_hdc,dx,dy,dw,dh,mdc2,dx -x +sx,dy -y +sy,iw,ih,SRCAND);
      BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
      BitBlt(mdc,0,0,iw,ih,mdc2,0,0,SRCAND);
      StretchBlt(_hdc,dx,dy,dw,dh,mdc,dx -x +sx,dy -y +sy,iw,ih,SRCPAINT);
      BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
    }
  }else{
    if (pix2 == 0){
      BitBlt(_hdc,dx,dy,dw,dh,mdc,dx -x +sx,dy -y +sy,SRCCOPY);
    }else{
      BitBlt(_hdc,dx,dy,dw,dh,mdc2,dx -x +sx,dy -y +sy,SRCAND);
      WSCulong iw = image->getImageWidth();
      WSCulong ih = image->getImageHeight();
      BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
      BitBlt(mdc,0,0,iw,ih,mdc2,0,0,SRCAND);
      BitBlt(_hdc,dx,dy,dw,dh,mdc,dx -x +sx,dy -y +sy,SRCPAINT);
      BitBlt(mdc2,0,0,iw,ih,mdc2,0,0,DSTINVERT);
    }
  }
//printf("windraw::drawImage sx,sy=%d,%d dx,dy=%d,%d\n",sx,sy,dx,dy);
//printf("windraw::drawImage %d,%d %d,%d 0x%x\n",dx -x +sx,dy -y +sy,dw,dh,pix);  
//  XCopyArea(_display,pix1,_window,_gc, dx -x +sx,dy -y +sy, dw,dh,dx,dy);

  if (pl != 0){
    SelectPalette(mdc,plbk,FALSE);
    if (pix2 != 0){
      SelectPalette(mdc2,plbk2,FALSE);
    }
  }
  SelectObject(mdc,pxbk);
  DeleteDC(mdc);

  if (pix2 != 0){
    SelectObject(mdc2,pxbk2);
    DeleteDC(mdc2);
  }
  return WS_NO_ERR;
}

long WSDwindraw::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 WSDwindraw::drawString(long x,long y,WSCulong w,WSCulong h,
         WSCstring* str,char font,char align,long cur,WSCbool inter_cur,
         long scur1,long scur2){
  if (_hdc == 0){
    return WS_ERR;
  }
//printf("drawString _hdc=0x%x\n",_hdc);
  short clx_bk = _clip_x;
  short cly_bk = _clip_y;
  WSCushort clw_bk = _clip_w;
  WSCushort clh_bk = _clip_h;
  long clx,cly;
  WSCulong clw,clh;
  WSGFandArea(x,y,w,h,_clip_x,_clip_y,_clip_w,_clip_h,&clx,&cly,&clw,&clh);

//  if (_printer_hdc == 0){//TEST
  setRegion(clx,cly,clw,clh);
//  }
WSMFtrace("XXZZr1 setRegion %d,%d,%d,%d bk %d,%d,%d,%d\n",clx,cly,clw,clh,clx_bk,cly_bk,clw_bk,clh_bk);
  WSDfont* fn = WSGIappFontSet()->getFont(font);
  if (fn == NULL){
    fn = WSGIappFontSet()->getDefaultFont();
    if (fn == NULL){
//      if (_printer_hdc == 0){ //TEST
      setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
//      }
      return WS_ERR;
    }
  }
  HFONT f = (HFONT)fn->getValue1();
  if (_printer_hdc != 0){
    WSDwinfont* wfn = (WSDwinfont*)fn->cast("WSDwinfont");
    if (wfn != NULL){
      HFONT f1 = wfn->getScaledFont(_pr_scale_x,_pr_scale_y);
      if (f1 != 0){
        f = f1;
      }
//printf("sfont=0x%x font=0x%x\n",f1,f);
    }
  }

  HFONT fontbk = (HFONT)SelectObject(_hdc,(void*)f);

//printf("WSDwindraw::drawStr font=%d fn=0x%x f=0x%x bk=0x%x hdc=0x%x XXZZr1\n",font,fn,f,fontbk,_hdc);
  SetTextColor(_hdc,_fg_color);
  SetBkMode(_hdc,TRANSPARENT);

  long num = 0;
  long i;
  WSCpoint* points = NULL;
  long fheight = fn->getFontHeight();
  WSCpoint  point;
  if (str->isExist("\n") == -1){
    WSCrect   area;
    area.setRect(x,y,w,h);
    WSGFcalcOneLineStringAddr(str,&area,align,fn,&point);
    char* tstrUTF8 = str->getString(WS_EN_UTF8);
    WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8);
    long tlen = WSGFstrlenUCS2(tstr);
    WSCushort* tstr2 = new WSCushort[WSGFstrlenUCS2(tstr) + 8];
    memcpy(tstr2,tstr,sizeof(WSCushort)*tlen);
    delete tstr;
    tstr2[tlen] = ' ';
    long slen = tlen+1;
    tstr2[slen] = 0;
    if (_printer_hdc != 0){
      short x1 = (short)((point.x - _pr_x) * _pr_scale_x);
      short y1 = (short)((point.y - _pr_y) * _pr_scale_y);
      TextOutW(_hdc,x1,y1,(WCHAR*)tstr2,slen);
    }else{
      TextOutW(_hdc,point.x,point.y,(WCHAR*)tstr2,slen);
    }
    if (inter_cur != False){
      if (cur > -1){
        WSCstring str2(*str);
        str2.cutString(cur);
        long cx = fn->getStringWidth(&str2);
WSMFtrace("XXZZif1 drawstring cur=%d width=%d #%s#\n",cur,cx,str2.getString(WS_EN_SJIS));
        drawFillRect(x + cx, point.y-2,2,fheight);
        SetBkMode(_hdc,TRANSPARENT);
      }
    }else{
      if (cur > -1){
        WSCstring str2(*str);
        str2.cutString(cur);
        long cx = fn->getStringWidth(&str2);
        str2 = *str;
        str2.deleteChars(0,cur); //changed
        str2.cutString(1);
        SetTextColor(_hdc,_bg_color);
        SetBkColor(_hdc,_fg_color);
        SetBkMode(_hdc,OPAQUE);
        char* tstrUTF8 = str2.getString(WS_EN_UTF8);
        WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8);
        long tlen = WSGFstrlenUCS2(tstr);
        if (_printer_hdc != 0){
          short x1 = (short)(((cx + point.x) - _pr_x) * _pr_scale_x);
          short y1 = (short)((point.y - _pr_y) * _pr_scale_y);
          TextOutW(_hdc,x1,y1,(WCHAR*)tstr,tlen);
        }else{
          TextOutW(_hdc,cx + point.x,point.y,(WCHAR*)tstr,tlen);
        }
        delete tstr;
        SetBkMode(_hdc,TRANSPARENT);
        SetTextColor(_hdc,_fg_color);
      }
    }
    if (scur1 < 0){
      scur1 =0;
    }
    if (scur2 < 0){
      scur2 =0;
    }
    if (scur1 > -1 && scur1 != scur2){
      if (scur1 > scur2){
        long bk = scur1;
        scur1 = scur2;
        scur2 = bk;
      }
      WSCstring str2(*str);
      str2.cutString(scur1); // changed
      long cx = fn->getStringWidth(&str2);
      str2 = *str;
      str2.deleteChars(0,scur1); //changed
      str2.cutString(scur2 - scur1); //changed
      SetTextColor(_hdc,_bg_color);
      SetBkColor(_hdc,_fg_color);
      SetBkMode(_hdc,OPAQUE);
      char* tstrUTF8 = str2.getString(WS_EN_UTF8);
      WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8);
      long tlen = WSGFstrlenUCS2(tstr);
      if (_printer_hdc != 0){
        short x1 = (short)((cx + point.x - _pr_x) * _pr_scale_x);
        short y1 = (short)((point.y - _pr_y) * _pr_scale_y);
        TextOutW(_hdc,x1,y1,(WCHAR*)tstr,tlen);
      }else{
        TextOutW(_hdc,cx + point.x,point.y,(WCHAR*)tstr,tlen);
      }
      delete tstr;
      SetBkMode(_hdc,TRANSPARENT);
      SetTextColor(_hdc,_fg_color);
    }
    delete tstr2;
  }else{
    WSCrect area;
    area.setRect(x,y,w,h);
    WSGFcalcStringAddr(str,&area,align,fn,&points,&num);
    str->seek(0);
    long lpos =0;
    long prelpos =0;
    if (scur1 > scur2){
      long bk = scur1;
      scur1 = scur2;
      scur2 = bk;
    }
    for(i=0; i < num; i++){
      WSCstring lstr = str->gets();
      lpos += prelpos;
      prelpos = lstr.getChars() +1;
      if ((signed)(points[i].y + (signed)fheight)< (signed)cly
          || (signed)(cly + clh)< points[i].y){
//WSMFtrace("XXZZ windraw::drawString mln=%d c hdc=0x%x points[i].y=%d fheight=%d cly=%d clh=%d\n",i,_hdc,points[i].y,fheight,cly,clh);
        continue;
      }
//      long slen = strlen(lstr.getSjisString());
      char* tstrUTF8 = lstr.getString(WS_EN_UTF8); 
      WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8); 
      if (_printer_hdc != 0){
        short x1 = (short)((points[i].x - _pr_x) * _pr_scale_x);
        short y1 = (short)((points[i].y - _pr_y) * _pr_scale_y);
        TextOutW(_hdc,x1,y1,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
      }else{
        TextOutW(_hdc,points[i].x,points[i].y,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
      }
      delete tstr;
WSMFtrace("XXZZ windraw::drawString mline=%d hdc=0x%x points[i].y=%d fheight=%d cly=%d clh=%d\n",i,_hdc,points[i].y,fheight,cly,clh);
      if (inter_cur != False && lpos <= cur && cur < lpos + prelpos){
        WSCstring str2(lstr);
        str2.cutString(cur - lpos);
        long cx = fn->getStringWidth(&str2);
        drawFillRect(points[i].x + cx,points[i].y-2,2,fheight);
        SetBkMode(_hdc,TRANSPARENT);
        cur = -1;
      }else if (inter_cur == False && lpos <= cur && cur < lpos + prelpos){
        WSCstring str2(lstr);
        str2.cutString(cur);
        long cx = fn->getStringWidth(&str2);
        str2 = *str;
        str2.deleteChars(0,cur); // changed
        str2.cutString(1);
        SetTextColor(_hdc,_bg_color);
        SetBkColor(_hdc,_fg_color);
        SetBkMode(_hdc,OPAQUE);
        char* tstrUTF8 = str2.getString(WS_EN_UTF8); 
        WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8); 
        if (_printer_hdc != 0){
          short x1 = (short)((cx + points[i].x - _pr_x) * _pr_scale_x);
          short y1 = (short)((points[i].y - _pr_y) * _pr_scale_y);
          TextOutW(_hdc,x1,y1,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
        }else{
          TextOutW(_hdc,cx + points[i].x,points[i].y,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
        }
        delete tstr;
        SetBkMode(_hdc,TRANSPARENT);
        SetTextColor(_hdc,_fg_color);
      }
      if (scur1 > -1 && scur1 != scur2 && !(scur2 < lpos ||  lpos + prelpos < scur1)){
        long startpos = scur1;
        if (lpos >scur1){
          startpos = lpos;
        }
        long endpos = scur2;
        if (lpos+ prelpos < scur2){
          endpos = lpos + prelpos;
        }

        WSCstring str2(*str);
        str2.cutString(startpos); // changed
        str2.deleteChars(0,lpos); // changed
        long cx = fn->getStringWidth(&str2);
        str2 = *str;
        str2.deleteChars(0,startpos);
        str2.cutString(endpos - startpos); // changed
        str2.replaceString("\n","",0);
        SetTextColor(_hdc,_bg_color);
        SetBkColor(_hdc,_fg_color);
        SetBkMode(_hdc,OPAQUE);
        char* tstrUTF8 = str2.getString(WS_EN_UTF8); 
        WSCushort* tstr = WSGFgetUCS2(tstrUTF8,WS_EN_UTF8); 
        if (_printer_hdc != 0){
          short x1 = (short)((cx + points[i].x - _pr_x) * _pr_scale_x);
          short y1 = (short)((points[i].y - _pr_y) * _pr_scale_y);
          TextOutW(_hdc,x1,y1,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
        }else{
          TextOutW(_hdc,cx + points[i].x,points[i].y,(WCHAR*)tstr,WSGFstrlenUCS2(tstr));
        }
        delete tstr;
        SetBkMode(_hdc,TRANSPARENT);
        SetTextColor(_hdc,_fg_color);
      }
    }
    str->seek(0);
  }
  SetBkMode(_hdc,OPAQUE);
//  char* tstr = (char*)str; 
//  long slen = strlen(tstr);
//  long swidth = fn->getStringWidth(str);
//  long sheight = fn->getStringHeight(str);

  SelectObject(_hdc,fontbk);

  if (num != 0){
    delete points;
  }
  setRegion(clx_bk,cly_bk,clw_bk,clh_bk);

  return WS_NO_ERR;
}

long WSDwindraw::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 WSDwindraw::drawFillString(long x,long y,WSCulong w,WSCulong h,
           WSCstring* str,char font,char align,short cur,WSCbool inter_cur){
  COLORREF bk1 = _fg_color;
  COLORREF bk2 = _bg_color;
  _fg_color = bk2;
  _bg_color = bk1;
  drawFillRect(x,y,w,h);
  _fg_color = bk1;
  _bg_color = bk2;
  drawString(x,y,w,h,str,font,align,cur,inter_cur);

  return WS_NO_ERR;
}

long WSDwindraw::drawGradation(long type,short c1,short c2,short c3,
                  short x,short y,WSCushort w,WSCushort h,WSCuchar gradm){
  if (_printer_hdc != 0){
    x = (short)((x - _pr_x) * _pr_scale_x);
    y = (short)((y - _pr_y) * _pr_scale_y);
    w = (WSCushort)(w * _pr_scale_x);
    h = (WSCushort)(h * _pr_scale_y);
  }

static WSDcolor* color = NULL;
  if (_hdc == 0){
    return WS_ERR;
  }

  short clx_bk = _clip_x;
  short cly_bk = _clip_y;
  WSCushort clw_bk = _clip_w;
  WSCushort clh_bk = _clip_h;
  long clx,cly;
  WSCulong clw,clh;
  WSGFandArea(x,y,w,h,_clip_x,_clip_y,_clip_w,_clip_h,&clx,&cly,&clw,&clh);

  setForeColor(c2);
  drawFillRect(x,y,w,h);

  WSDcolor* col1 = WSGIappColorSet()->getColor(c1);
  WSDcolor* col2 = WSGIappColorSet()->getColor(c2);
  WSDcolor* col3 = WSGIappColorSet()->getColor(c3);
  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;
  }
  setRegion(clx,cly,clw,clh);
  fgcolor = -100;
  bgcolor = -100;
  _fg_color = 0;
  _bg_color = 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);
  }
//WSMFtrace("WSDwindraw::drawGradation here0\n");

  if (gradm != 0){
    WSCulong cval1 = (WSCulong )col2->getValue1();
//    COLORREF cval1 = PALETTERGB(r2,g2,b2);
    HPEN pen = CreatePen(PS_NULL,0,cval1);
    HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
//    HBRUSH brush = CreateSolidBrush(_fg_color);
    HBRUSH brush = CreateSolidBrush(cval1);
    HBRUSH brush_bk = (HBRUSH)SelectObject(_hdc,(void*)brush);

    SetBkMode(_hdc,TRANSPARENT);
    Rectangle(_hdc,x,y,x+w+1,y+h+1);
    SetBkMode(_hdc,OPAQUE);

    SelectObject(_hdc,(void*)pen_bk);
    SelectObject(_hdc,(void*)brush_bk);
    DeleteObject((void*)pen);
    DeleteObject((void*)brush);

  }
//WSMFtrace("WSDwindraw::drawGradation here0.1\n");
  long i;
  if (type == WS_GR_LT_RB || type == WS_GR_RB_LT){
    long max = (w+h)* (100 -gradm)/100;
    long wval = max/128+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;
        }
      }
//WSMFtrace("drawGradation rgb=%x %x %x \n",val1,val2,val3);
      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;
      }
      
      COLORREF cval = PALETTERGB(val1,val2,val3);
      SetBkMode(_hdc,TRANSPARENT);

      if (wval > 7){
        HPEN pen = CreatePen(PS_SOLID,1,cval);
        HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
        if (type == WS_GR_LT_RB){
          MoveToEx(_hdc,x1-wval -5,y,NULL);
          LineTo(_hdc,x,y1-wval -5);
        }else{
          MoveToEx(_hdc,x1+wval+5,y,NULL);
          LineTo(_hdc,x,y1+wval+5);
        }
        SelectObject(_hdc,(void*)pen_bk);
        DeleteObject((void*)pen);
      }
       if (wval > 3){
        HPEN pen = CreatePen(PS_SOLID,1,cval);
        HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
        if (type == WS_GR_LT_RB){
          MoveToEx(_hdc,x1-wval-1,y,NULL);
          LineTo(_hdc,x,y1-wval-1);
        }else{
          MoveToEx(_hdc,x1+wval+1,y,NULL);
          LineTo(_hdc,x,y1+wval+1);
        }
        SelectObject(_hdc,(void*)pen_bk);
        DeleteObject((void*)pen);
      }
      HPEN pen = CreatePen(PS_SOLID,wval+1,cval);
      HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
      MoveToEx(_hdc,x1,y,NULL);
      LineTo(_hdc,x,y1);
      SelectObject(_hdc,(void*)pen_bk);
      DeleteObject((void*)pen);

      SetBkMode(_hdc,OPAQUE);
//WSMFtrace("WSDwindraw::drawGradation here1 wval+1=%d cval=0x%x\n",wval+1,cval);
    }
  }else
  if (type == WS_GR_LB_RT || type == WS_GR_RT_LB){
    long max = (w+h)* (100 -gradm)/100;
    long wval = max/128+1;
    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 > (long)(_clip_x + _clip_w + y1 - x) || (long)(_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;
      }

      COLORREF cval = PALETTERGB(val1,val2,val3);
      HPEN pen = CreatePen(PS_SOLID,wval+1,cval);
      HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
      SetBkMode(_hdc,TRANSPARENT);
      MoveToEx(_hdc,x,y1,NULL);
      LineTo(_hdc,x1,y+h);
      SetBkMode(_hdc,OPAQUE);

      SelectObject(_hdc,(void*)pen_bk);
      DeleteObject((void*)pen);
//WSMFtrace("WSDwindraw::drawGradation here2\n");
    }
  }else
  if (type == WS_GR_T_B || type == WS_GR_B_T){
    long max = h* (100 -gradm)/100;
    long wval = max/128+1;
    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 > (long)(h1+y) || (long)(_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;
      }

      COLORREF cval = PALETTERGB(val1,val2,val3);
      HPEN pen = CreatePen(PS_SOLID,wval+1,cval);
      HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
      SetBkMode(_hdc,TRANSPARENT);
      MoveToEx(_hdc,x,y+h1,NULL);
      LineTo(_hdc,x+w,y+h1);
      SetBkMode(_hdc,OPAQUE);

      SelectObject(_hdc,(void*)pen_bk);
      DeleteObject((void*)pen);
//WSMFtrace("WSDwindraw::drawGradation here3\n");

    }
  }else{
    long max = w* (100 -gradm)/100;
    long wval = max/128+1;
    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 > (long)(w1+x) || (long)(_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;
      }

      COLORREF cval = PALETTERGB(val1,val2,val3);
      HPEN pen = CreatePen(PS_SOLID,wval+1,cval);
      HPEN pen_bk = (HPEN)SelectObject(_hdc,(void*)pen);
      SetBkMode(_hdc,TRANSPARENT);
      MoveToEx(_hdc,x+w1,y,NULL);
      LineTo(_hdc,x+w1,y+h);
      SetBkMode(_hdc,OPAQUE);

      SelectObject(_hdc,(void*)pen_bk);
      DeleteObject((void*)pen);
//WSMFtrace("WSDwindraw::drawGradation here4\n");
    }
  }
  setRegion(clx_bk,cly_bk,clw_bk,clh_bk);
  return WS_NO_ERR;
}

