//
// 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 <WSCdevice.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSCbase.h>
#include <WSDmouse.h>
#include <WSCbaseList.h>
#include <mac/WSDmacFormDev.h>
#include <mac/WSDmacAppDev.h>
#include <mac/WSDmacDraw.h>
#include <mac/WSmcom.h>
#include <mac/WSDmacDragDrop.h>
//#include <form.h>
//TEST
#include <mac/WSDmacScrFrameDev.h>
//TEST

WSMFclassInit(WSDmacFormDev,WSDwindowDev);

WSDdev* _wsdmacFormdev_init_(){
  return new WSDmacFormDev();
}

class _WSDmacFormDev_init_ {
  public:_WSDmacFormDev_init_(){
     WSGIappDevice()->setCreateHandler("formDev",_wsdmacFormdev_init_);
  };
};
static _WSDmacFormDev_init_ _init_to_run_WSDmacFormDev_;

//static WSDmacDraw* draw_of_macForm = NULL;

WSDmacFormDev::WSDmacFormDev(){
  _is_win = False;
  _pwin = 0;
  _parent = NULL;
  _mouse_press_target = NULL;
  _mouse_move_target = NULL;
//  _cntl  = 0;
//  _pixmap  = 0;
//  _gc      = 0;
  _bg = -1;
  _bg_pix = -1;
  _mno = 0;

//  if (draw_of_macForm == NULL){
//      draw_of_macForm = new WSDmacDraw();
//  }
//  setDraw(draw_of_macForm);
}

WSDmacFormDev::~WSDmacFormDev(){
  destroyContext();
  destroyPixmap();
  destroyWindow();
}

pascal OSStatus WSDmacFormDev::_handle_events_(EventHandlerCallRef nh,
EventRef ev,void* d){
  WindowPtr win;
  EventRecord event;
  Boolean fl = ConvertEventRefToEventRecord(ev,&event);
printf("WSDmacFormDev::_handle_events_().. this=0x%x fl=%d\n",d,fl);
  if (fl != FALSE){
#if 0 //XXZZ
    short part = FindWindow(event.where,&win);
    Rect rect;
    long size;
printf("WSDmacFormDev::_handler_events_().. part=%d %d\n",part,inMenuBar);
    switch(part){
      case inMenuBar:
        WSDmacAppDev::handleMenuEvents(event);
        break;
      case inSysWindow:
        break;
      case inContent:
        break;
      case inDrag:
        GetRegionBounds(GetGrayRgn(),&rect);
        DragWindow(win,event.where,&rect);
        break;
      case inGrow:
        size = GrowWindow(win,event.where,NULL);
        if (size){
          GetPortBounds(GetWindowPort(win),&rect);
          InvalWindowRect(win,&rect);
        }
        break;
    }
    switch(event.what){
      case kHighLevelEvent:
        AEProcessAppleEvent(&event);
        break;
    }
#endif //XXZZ
  }
  return eventNotHandledErr;
}

WSDdev* WSDmacFormDev::getEventParentDev(){
  return this;
}
WindowRef WSDmacFormDev::getBaseWindow(){
  if (_pwin == 0){
    WSDmacFormDev* dev = getParentAreaDev();
    if (dev != NULL){
      _pwin = dev->getBaseWindow();
    }
  }
  return _pwin;
}

long WSDmacFormDev::setValue(long kind,void* data){
  short bx,by;
  WSCushort bw,bh;
  if (kind == WSDEV_X && *(short*)data == _w_x){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_Y && *(short*)data == _w_y){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_WIDTH && *(WSCushort*)data == _w_w){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_HEIGHT && *(WSCushort*)data == _w_h){
    return WS_NO_ERR;
  }
  switch(kind){
    case WSDEV_BACKCOLOR:{
      _bg = *(short*)data;
       WSDcolor* color = WSGIappColorSet()->getColor(*(short*)data);
       if (color != NULL){
         RGBColor* col = (RGBColor*)color->getValue1();
         if (col != NULL){
           _bgc.red = col->red;
           _bgc.green = col->green;
           _bgc.blue = col->blue;
printf("%s %d color=%x %x %x\n",__FILE__,__LINE__,_bgc.red,_bgc.green,_bgc.blue)
;
         }
       }
       break;
    }

  }

  WSDwindowDev::setValue(kind,data);
  switch(kind){
    case WSDEV_X: 
    case WSDEV_Y: 
    case WSDEV_WIDTH: 
    case WSDEV_HEIGHT: 
//printf("WSDmacFormDev::setValue D12 %s x,y,w,h=%d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),0,0,_w_w,_w_h);
//      resize_execute(_w_w,_w_h);
      _clear_area(0,0,_w_w,_w_h);
      break;
    default:
      break;
  }

#if 0 //XXZZ
  Arg args[4];
  WSDcolor* color;
  WSDimage* image;
  WSCbool unmanaged = False;
  WSCbool fl;
  switch(kind){
    case WSDEV_X: 
             if (_widget == NULL){
               break;
             }
             if (getVisible() == True){
                WSDmacFormDev* pdev = getParentAreaDev();
                XtSetArg(args[0],XtNx,&bx);
                XtSetArg(args[1],XtNwidth,&bw);
                XtGetValues((Widget)_widget,args,2);
                if (pdev != NULL &&
                    (pdev->getWidth()-1  < *(short*)data + bw 
                     || pdev->getWidth()-1  < bx + bw  
                     || pdev->getHeight()-1 < _w_y + _w_h) ){
                  unmanaged = True;
                  XtUnmanageChild((Widget)_widget);
                }
             }

             XtSetArg(args[0],XtNx,*(short*)data);
             XtSetValues((Widget)_widget,args,1);
             if (unmanaged == True){
               XtManageChild((Widget)_widget);
             }
             break;
    case WSDEV_Y:
             if (_widget == NULL){
               break;
             }
             if (getVisible() == True){
                WSDmacFormDev* pdev = getParentAreaDev();
                XtSetArg(args[0],XtNy,&by);
                XtSetArg(args[1],XtNheight,&bh);
                XtGetValues((Widget)_widget,args,2);
                if (pdev != NULL &&
                    (pdev->getHeight() -1 < *(short*)data + bh
                     || pdev->getHeight() -1  < by + bh
                     || pdev->getWidth() -1 < _w_x + _w_w )){
                  XtUnmanageChild((Widget)_widget);
                  unmanaged = True;
                }
             }

             XtSetArg(args[0],XtNy,*(short*)data);
             XtSetValues((Widget)_widget,args,1);
             if (unmanaged == True){
               XtManageChild((Widget)_widget);
             }
             break;
    case WSDEV_WIDTH:
             if (_widget == NULL){
               break;
             }
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               destroyPixmap();
             }
             if (*(WSCushort*)data > 0){
               XtSetArg(args[0],XtNwidth,*(WSCushort*)data);
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_HEIGHT:
             if (_widget == NULL){
               break;
             }
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               destroyPixmap();
             }
             if (*(WSCushort*)data > 0){
               XtSetArg(args[0],XtNheight,*(WSCushort*)data);
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_BACKCOLOR:
             color = WSGIappColorSet()->getColor(*(short*)data);
             _bg = *(short*)data;
             if (_widget == NULL){
               break;
             }
             if (color != NULL){
               XtSetArg(args[0],XtNbackground,color->getValue1());
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_BACK_PIXMAP:
             _bg_pix = *(short*)data;
             if (_widget == NULL){
               break;
             }
             if (*(short*)data == -2 ){
               XtSetArg(args[0],XtNbackgroundPixmap,0);
               XtSetValues((Widget)_widget,args,1);
             }else
             if (*(short*)data == -1){
               XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
               XtSetValues((Widget)_widget,args,1);
             }else{
               image = WSGIappImageSet()->getImage(*(short*)data);
               if (image != NULL){
                 if (image->getValue1() == -1){
                   XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
                 }else{
                   Pixmap pid = (Pixmap)image->getValue1();
                   XtSetArg(args[0],XtNbackgroundPixmap,pid);
                 }
                 XtSetValues((Widget)_widget,args,1);
               }
             }
             break;
    case WSDEV_GRAB_POINTER:
             if (_widget == NULL){
               break;
             }
             fl = *(WSCbool*)data;
             if (fl != False){
               XGrabPointer(XtDisplay(_widget),XtWindow(_widget),False,
                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
                  GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
               XGrabKeyboard(XtDisplay(_widget),XtWindow(_widget),False,
                  GrabModeAsync,GrabModeAsync,CurrentTime);
             }else{
               XUngrabPointer(XtDisplay(_widget),CurrentTime);
               XUngrabKeyboard(XtDisplay(_widget),CurrentTime);
             }
             break;
     case WSDEV_MOUSE_NO:
             _mno = *(WSCushort*)data;
             if (_widget != NULL && XtWindow(_widget) != 0){
               long val = WSGIappMouse()->getMouseCursor(_mouse_no);
               if (val != 0){
                 XDefineCursor(XtDisplay(_widget),XtWindow(_widget),val);
               }
             }
             break;
     default:
      return WS_NO_ERR;
  }
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_NO_ERR;
}
WSCushort WSDmacFormDev::getMouseNo(){
  return _mno;
}
void WSDmacFormDev::_copy_area(long x,long y,WSCulong w,WSCulong h,long dx,long dy,WSCuchar fl){
#if 0 //XXZZ
  if (_widget == NULL){
    return;
  }
  Display* disp = WSGIxwinAppDev()->display();
  GC gc = getGC();
  if (fl == WS_PIXMAP_TO_WINDOW){
     Pixmap pix = getPixmap();
     if (pix == 0 || gc  == 0){
        return;
     }
     XCopyArea( disp,pix,XtWindow(_widget),gc,
          (int)x, (int)y, (WSCuint)w, (WSCuint)h, (int)dx, (int)dy);
  }else{
     XCopyArea( disp,XtWindow(_widget),XtWindow(_widget),gc,
          (int)x, (int)y, (WSCuint)w, (WSCuint)h, (int)dx, (int)dy);
     while(1){
       XFlush(XtDisplay(_widget));
       XEvent e;
       Bool fl =  XCheckTypedWindowEvent(disp,XtWindow(_widget),
                   GraphicsExpose,&e);
       if (fl == 1){
         e.type = Expose;
         XtDispatchEvent(&e);
         WSGIappObjectList()->execInitialize();
         WSGIappObjectList()->execUpdate();
         break;
       }
       fl =  XCheckTypedWindowEvent(disp,XtWindow(_widget),
                   NoExpose,&e);
       if (fl == 1){
         break;
       }
     }
  }
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
printf("WSDmacFormDev::_copy_area  not implemented...\n");
  return;
}

void WSDmacFormDev::_clear_area(long x,long y,WSCulong w,WSCulong h){
#if 0
  if (getVisible() == False){
    return;
  }
#endif
//  Rect r;
//  SetRect(&r,_w_x + x,_w_y + y,_w_x + xw,h);
  WSCpoint* cpt = (WSCpoint*)getContextResource();
  RgnHandle rh1 = NewRgn();
  RgnHandle rh2 = NewRgn();
  RgnHandle rh3 = NewRgn();
  SetRectRgn(rh1, cpt->x, cpt->y, cpt->x + _w_w, cpt->y + _w_h);
  SetRectRgn(rh2, cpt->x + x, cpt->y + y, cpt->x + x + w, cpt->y + y + h);
printf("WSDmacFormDev::_clear_area D14 target=%s %d,%d,%d,%d %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),cpt->x,cpt->y,_w_w,_w_h,cpt->x+x,cpt->y+y,w,h);
  SectRgn(rh1,rh2,rh3);
  CopyRgn(rh3,rh1);

  RgnHandle rh4 = NewRgn();
  SetRectRgn(rh4, 0, 0, 0x7fff,  0x7fff);
  WSDmacFormDev* parent = getParentAreaDev();
  while(1){
    if (parent == NULL){
      break;
    }
    long cx,cy,cw,ch;
    parent->getAbsoluteGeometry(&cx,&cy,&cw,&ch);

    SetRectRgn(rh2, cx, cy, cx + cw, cy + ch);
    SectRgn(rh1,rh2,rh3);
    CopyRgn(rh3,rh1);
    
    parent = parent->getParentAreaDev();
  }
  WSCbool vis = getVisible();
  if (vis != False){
    long num = _child_list.getNum();
    long i;
    for(i=0; i<num; i++){
      WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
      if (child->getVisible() == False){
        continue;
      }
      long cx,cy,cw,ch;
      child->getAbsoluteGeometry(&cx,&cy,&cw,&ch);
      SetRectRgn(rh2, cx, cy, cx + cw, cy + ch);
printf("WSDmacFormDev::_clear_area D14 child=%s clip out %d,%d,%d,%d\n",child->getAttachedClient()->getInstanceName(),cx,cy,cw,ch);
#if 0
    RGBColor col;
    col.red = 0;
    col.green = 0;
    col.blue = 0xffff;
    RGBForeColor(&col);
    SetClip(rh2);
    Rect r;
    SetRect(&r,0,0,0x7fff,0x7fff);
    PaintRect(&r);
#endif
      XorRgn(rh2,rh4,rh3);
      CopyRgn(rh3,rh2);
      SectRgn(rh1,rh2,rh3);
      CopyRgn(rh3,rh1);
    }
  }

  WindowRef bw = getBaseWindow(); 
  if (bw != NULL){
//    InvalWindowRect(bw,&r);
//    SetPortWindowPort(bw);
//    MovePortTo(0,0);
//TEST
    InvalWindowRgn(bw,rh1);
printf("WSDmacFormDev::_clear_area D14 cleared.. %s\n",getAttachedClient()->getInstanceName());
#if 0
    SetPortWindowPort(bw);
    SetClip(rh1);
    RGBColor col;
    col.red = 0;
    col.green = 0xffff;
    col.blue = 0;
    RGBForeColor(&col);
    Rect r;
//    SetRect(&r,cpt->x, cpt->y, cpt->x + _w_w, cpt->y + _w_h);
    SetRect(&r,0,0,0x7fff,0x7fff);
    PaintRect(&r);
#endif
  }
  DisposeRgn(rh1);
  DisposeRgn(rh2);
  DisposeRgn(rh3);
  DisposeRgn(rh4);
  return;
}
WSDmacFormDev* WSDmacFormDev::getParentAreaDev(){
  WSDdev*      pdev = WSDmacFormDev::getParentDev();
  if (pdev == NULL){
    return NULL;
  }

  WSDmacFormDev* mdev = (WSDmacFormDev*)pdev->cast("WSDmacFormDev");
  if (mdev == NULL){
    while(mdev == NULL){
      pdev = pdev->getParentDev();
      if (pdev == NULL){
        return NULL;
      }
      mdev = (WSDmacFormDev*)pdev->cast("WSDmacFormDev");
    }
  }
  return mdev;
}

void WSDmacFormDev::_setup_pixmap(short x,short y,WSCushort w,WSCushort h,short bg,short img_no){
  WSDcolor*  color = WSGIappColorSet()->getColor(bg);

#if 0 //XXZZ
  GC gc = WSGIxwinAppDev()->appGC2();
  if (gc == 0){
      return;
  }
  Display* disp = WSGIxwinAppDev()->display();
  if (color != NULL){
      WSCulong  pixel = (WSCulong )color->getValue1();
      XSetForeground(disp,gc,pixel);
  }

  Pixmap pix = getPixmap();
  if (getPixmap() != 0){
    if (img_no != -1 && img_no != 0){
      WSDimage* image = WSGIappImageSet()->getImage(img_no);
      if (image != NULL && image->getValue1() != -1){
         WSCushort pw = image->getImageWidth();
         WSCushort ph = image->getImageHeight();
         Pixmap pid = (Pixmap)image->getValue1();
         short cw = 0;
         while(1){
             short ch = 0;
             while(1){
               XCopyArea( disp,pid,pix,gc,
                         (int)0, (int)0, (WSCuint)pw, (WSCuint)ph,
                         (int)cw, (int)ch);
               ch += ph;
               if (ch > h) break;
             }
             cw += pw;
             if (cw > w) break;
         }

      }else{
        XFillRectangle(disp,pix, gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h);
      }
    }else{
      XFillRectangle(disp,pix, gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h);
    }
  }
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return;
}

long WSDmacFormDev::createWindow(){
  WSDmacFormDev* mdev = getParentAreaDev();
  if (_parent != NULL && mdev != _parent){
    _parent->delChild(this);
  }

  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w == 0){
    w = 1;
  }
  if (h == 0){
    h = 1;
  }

  _parent = getParentAreaDev();

  if (_parent == NULL){
    return WS_ERR;
  }
  _parent->addChild(this);
  return WS_NO_ERR;
}

#if 0 //XXZZ
long WSDmacFormDev::setPixmap(WindowRef pixmap){
   if ( _pixmap != 0){
     WSGFxReleasePixmap(_pixmap);
   }
   _pixmap = pixmap;
   return WS_NO_ERR;
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}
#endif //XXZZ

long WSDmacFormDev::getDeviceResource(){
#if 0 //XXZZ
   if (_widget == 0 || XtDisplay(_widget) == 0){
     return -1;
   }
   return (long)XtDisplay(_widget);
#endif //XXZZ
//printf("WSDmacFormDev::getDeviceResource not support %s %d\n",__FILE__,__LINE__);
  return 0;
}

long WSDmacFormDev::createPixmap(){
#if 0 //XXZZ
  if (getGC() == 0){
     return WS_ERR;
  }

  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }

  Pixmap pix = WSGFxGetPixmap(w,h);

  setPixmap(pix);
  _setup_pixmap(0,0,w,h,_bg_no,_bp_no);
  exposeExecute(0,0,w,h);
  return WS_NO_ERR;
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}

long WSDmacFormDev::getContextResource(){
  _top_left.x = 0;
  _top_left.y = 0;
  if (_parent != NULL){
    WSCpoint* pt = (WSCpoint*)_parent->getContextResource();
    _top_left.x = pt->x;
    _top_left.y = pt->y;
  }
  _top_left.x += _w_x;
  _top_left.y += _w_y;
  return (long)&_top_left;
}

long WSDmacFormDev::getSpecialResource(){
#if 0//XXZZ
   return (long)_widget;
#endif //XXZZ
//printf("not support %s %d\n",__FILE__,__LINE__);
  return 0;
}

long WSDmacFormDev::createContext(){
#if 0 //XXZZ
  destroyContext();  
  WSDmacAppDev* app   = WSGIxwinAppDev();
  GC gc = app->appGC();
  setGC(gc);
  return WS_NO_ERR;
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}

long WSDmacFormDev::getWindowResource(){
  return (long)getBaseWindow();
}

#if 0 //XXZZ
GC WSDmacFormDev::getGC(){
  return _gc;
}
WindowRef WSDmacFormDev::getPixmap(){
  return 0;
//  return _pixm;
}
#endif //XXZZ

#if 0 //XXZZ
WindowRef WSDmacFormDev::getWindow(){
  if (getPixmapStyle() != WS_DIRECT_WINDOW ){
    if ( getPixmap() != 0 ){
      return getPixmap();
    }else{
        return (WindowRef)-1;
    }
  }
  if (_win == 0){
    return (WindowRef)-1;
  }
  return _win;
}
#endif //

long WSDmacFormDev::destroyWindow(){
  _pwin = 0;
  if (_parent != NULL){
    _parent->delChild(this);
    _parent = NULL;
  }
  long i;
  long num = _child_list.getNum();
  for(i=0; i<num; i++){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
    child->_parent = NULL;
    child->destroyWindow();
  }
  _child_list.clear();

  setInitialized(False);
  return WS_NO_ERR;
}

long WSDmacFormDev::destroyPixmap(){
#if 0 //XXZZ
  setPixmap(0);
  WSDwindowDev::destroyPixmap();
#endif //XXZZ
  return WS_NO_ERR;
}
#if 0 //XXZZ
long WSDmacFormDev::setGC(GC gc){
  _gc = gc;
  return WS_NO_ERR;
}
#endif //XXZZ

long WSDmacFormDev::setBaseWindow(WindowRef w){
  _pwin = w;
  return WS_NO_ERR;
}
long WSDmacFormDev::destroyContext(){
#if 0//XXZZ
  setGC(0);
  return WS_NO_ERR;
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}
long WSDmacFormDev::setVisible(WSCbool fl){
  WSCbool bk = getVisible();
printf("WSDmacFormDev::setVisible(%d) D11 bk=%d %s\n",fl,bk,getAttachedClient()->getInstanceName());
  WSDdev::setVisible(fl);
  WSCbool update_rgn = False;
  if (fl == False){
    if (bk != False){
      update_rgn = True;
    }
  }else{
    if (bk == False){
      update_rgn = True;
      long num = _child_list.getNum();
      long i;
      for(i=0; i<num; i++){
        WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
        if (child->getAttachedClient() != NULL){
          WSCbool vis = child->getAttachedClient()->getVisible();
printf("WSDmacFormDev::setVisible(%d) D11 %s i=%d child=%s vis=%d\n",getAttachedClient()->getInstanceName(),i,child->getAttachedClient()->getInstanceName(),vis);
          if (vis != False && child->getVisible() == False){
            child->setVisible(True);
          }
        }
      }
    }
  }
  if (update_rgn != False){
printf("WSDmacFormDev::setVisible(%d) D11 %s cleared..\n",fl,getAttachedClient()->getInstanceName());
    _clear_area(0,0,_w_w,_w_h);
  }
  return WS_ERR;
}
#if 0 //XXZZ
void WSDmacFormDev::_evh_mouse_in(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  WSGIxwinAppDev()->setXEvent(ev);
  WSDmacFormDev* dev = (WSDmacFormDev*)ptr;

  WSCpoint point;
  point.setPoint( ev->xcrossing.x, ev->xcrossing.y );

  long val = WSGIappMouse()->getMouseCursor(dev->_mouse_no);
  if (val != 0){
    XDefineCursor(XtDisplay((Widget)dev->_widget),XtWindow((Widget)dev->_widget),val);
  }

  dev->onMouseIn(&point);
  WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDmacFormDev::_evh_mouse_out(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
   if (ev->xcrossing.mode != NotifyNormal){
     return;
   }
   WSGIxwinAppDev()->setXEvent(ev);
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;

  dev->onMouseOut();
  WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDmacFormDev::_evh_mouse_move(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
   WSGIxwinAppDev()->setXEvent(ev);
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;

   WSCpoint point;
   point.setPoint( ev->xmotion.x, ev->xmotion.y );

   WSCbool b1 =  (ev->xmotion.state & Button1Mask) != 0 ? True:False;
   WSCbool b2 =  (ev->xmotion.state & Button2Mask) != 0 ? True:False;
   WSCbool b3 =  (ev->xmotion.state & Button3Mask) != 0 ? True:False;

   long state = WSGIappMouse()->getStatus();
   if (b1){
     state |= WS_MOUSE_BTN1;
   }
   if (b2){
     state |= WS_MOUSE_BTN2;
   }
   if (b3){
     state |= WS_MOUSE_BTN3;
   }
   WSGIappMouse()->setStatus(state);

   dev->onMouseMove(&point);
   WSGIxwinAppDev()->setXEvent(NULL);

}


void WSDmacFormDev::_evh_expose(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
   WSGIxwinAppDev()->setXEvent(ev);

   if (dev->getAttachedClient() == NULL){
      dev->setVisible(False);
      return;
   }else if (dev->getAttachedClient()->getVisible() == False){
      dev->setVisible(False);
      return;
   }

   if (dev->getGC() == 0){
      dev->createContext();
   }

   WSCrect area;
   area.setRect( (short)ev->xexpose.x, (short)ev->xexpose.y,
             (WSCushort)ev->xexpose.width, (WSCushort)ev->xexpose.height);
   dev->onExpose(&area);
   WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDmacFormDev::_evh_resize(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  WSGIxwinAppDev()->setXEvent(ev);
  WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
  if (ev->type == ConfigureNotify){
    Arg args[4];
    Position x,y;
    Dimension w,h;
    XtSetArg(args[0],XtNx,&x);
    XtSetArg(args[1],XtNy,&y);
    XtSetArg(args[2],XtNwidth,&w);
    XtSetArg(args[3],XtNheight,&h);
    XtGetValues(dev->_widget,args,4);

    WSCrect area;
    area.setRect(x,y,w,h);
    dev->onResize(&area);
    WSGIxwinAppDev()->setXEvent(NULL);
  }
}

void WSDmacFormDev::_evh_btn_press(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
   WSGIxwinAppDev()->setXEvent(ev);
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
   WSCpoint point;
   point.setPoint( ev->xbutton.x,ev->xbutton.y );
#if 0
   long state = WSGIappMouse()->getStatus();
   if (ev->xbutton.button == 1){
     state |= WS_MOUSE_BTN1;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
   }else if (ev->xbutton.button == 2){
     state |= WS_MOUSE_BTN2;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN2);
   }else if (ev->xbutton.button == 3){
     state |= WS_MOUSE_BTN3;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
   }
   WSGIappMouse()->setStatus(state);
#endif

   dev->onMousePress(&point);
   WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDmacFormDev::_evh_btn_release(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
   WSGIxwinAppDev()->setXEvent(ev);
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
   WSDmacDragDrop* xdd = WSGImacAppDragDrop();
   if (xdd != NULL){
     if (xdd->getDragState() != 0){
       xdd->executeDrop();
	   return;
	 }
   }
   WSCpoint point;
   point.setPoint( ev->xbutton.x, ev->xbutton.y );
#if 0
   long state = WSGIappMouse()->getStatus();
   if (ev->xbutton.button == 1){
     state &= ~WS_MOUSE_BTN1;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
   }else if (ev->xbutton.button == 2){
     state &= ~WS_MOUSE_BTN2;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN2);
   }else if (ev->xbutton.button == 3){
     state &= ~WS_MOUSE_BTN3;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
   }
   WSGIappMouse()->setStatus(state);
#endif
   dev->onMouseRelease(&point);
   WSGIxwinAppDev()->setXEvent(NULL);
}


void WSDmacFormDev::_evh_delete(Widget w,XtPointer ptr,XEvent* ev,WSCbool*){
  if (ev->type == ClientMessage){
    if (ev->xclient.message_type ==  XInternAtom(XtDisplay(w),"WM_PROTOCOLS",False) &&
        (WSCulong)ev->xclient.data.l[0] == XInternAtom(XtDisplay(w),"WM_DELETE_WINDOW",False)){
      WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
      dev->onUnmap();
    }
  }
}


void WSDmacFormDev::_evh_delete2(Widget w,void* ptr,void*){
   WSDmacFormDev* dev = (WSDmacFormDev*)ptr;
   if (dev->_widget != w){
     return;
   }
   dev->_pwidget = 0;
   dev->_widget = 0;
   dev->setInitialized(False);
}

void WSDmacFormDev::_evh_dummy(Widget ,XtPointer ,XEvent* ,WSCbool*){
}
#endif //XXZZ

long WSDmacFormDev::raise(){
#if 0//XXZZ
  if ( _widget == 0){
    return WS_ERR;
  }
  if ( XtWindow(_widget) != 0){
    XRaiseWindow(XtDisplay(_widget),XtWindow(_widget));
    return WS_NO_ERR;
  }
#endif  //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}
long WSDmacFormDev::lower(){
#if 0 //XXZZ
  if ( _widget == 0){
    return WS_ERR;
  }
  if ( XtWindow(_widget) != 0){
    XLowerWindow(XtDisplay(_widget),XtWindow(_widget));
    return WS_NO_ERR;
  }
#endif //XXZZ
printf("not support %s %d\n",__FILE__,__LINE__);
  return WS_ERR;
}
long WSDmacFormDev::resize_execute(long,long){
printf("WSDmacFormDev:resize_execute not supported.\n");
  return WS_NO_ERR;
}
long WSDmacFormDev::move_execute(long,long){
printf("WSDmacFormDev:move_execute not supported.\n");
  return WS_NO_ERR;
}
long WSDmacFormDev::addChild(WSDmacFormDev* new_child){
  _child_list.add((void*)new_child);
}
long WSDmacFormDev::delChild(WSDmacFormDev* new_child){
  _child_list.del((void*)new_child);
}
void WSDmacFormDev::getGeometry(long* x,long* y,long* w,long* h){
  *x = _w_x;
  *y = _w_y;
  *w = _w_w;
  *h = _w_h;
}
void WSDmacFormDev::getAbsoluteGeometry(long* x,long* y,long* w,long* h){
  WSCpoint* cpt = (WSCpoint*)getContextResource();
  if (cpt == NULL){
    *x = _w_x;
    *y = _w_y;
  }else{
    *x = cpt->x;
    *y = cpt->y;
  }
  *w = _w_w;
  *h = _w_h;
}

long WSDmacFormDev::expose_execute(WSCrect* rt){
printf("WSDmacFormDev::expose_exec D11   %s %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),rt->x,rt->y,rt->width,rt->height);
  long cx,cy,cw,ch;
  getAbsoluteGeometry(&cx,&cy,&cw,&ch);
  RGBForeColor(&_bgc);
  Rect rect;
  SetRect(&rect,cx+rt->x,cy+rt->y,
                cx+rt->x + rt->width,cy+rt->y + rt->height);
  PaintRect(&rect);

  onExpose(rt);
//XXZZ
// parent's area is invalid..
//  may clear child's area..
printf("WSDmacFormDev::expose_exec D11-2 %s %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),rt->x,rt->y,rt->width,rt->height);
  long i;
  long num = _child_list.getNum();
  for(i=0; i<num; i++){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
printf("WSDmacFormDev::expose_exec D11 %s child=%s %d %d\n",getAttachedClient()->getInstanceName(),child->getAttachedClient()->getInstanceName(),child->getAttachedClient()->getVisible(),child->getVisible());
    if (child->getAttachedClient() == NULL){
      continue;
    }
    WSCbool vis = child->getAttachedClient()->getVisible();
    if (vis == False){
      continue;
    }
    if (child->getVisible() == False){
      child->setVisible(True);
    }
    long dx,dy,dw,dh;
    long cx,cy,cw,ch;
    child->getGeometry(&cx,&cy,&cw,&ch);
    WSGFandArea(rt->x,rt->y,rt->width,rt->height,cx,cy,cw,ch,&dx,&dy,&dw,&dh);

    long vx,vy,vw,vh;
    child->getVaridArea(&vx,&vy,&vw,&vh);
    WSGFandArea(dx,dy,dw,dh,vx,vy,vw,vh,&dx,&dy,&dw,&dh);
printf("WSDmacFormDev::expose_exec D16 %s %s %d,%d,%d,%d %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),child->getAttachedClient()->getInstanceName(),cx,cy,cw,ch,vx,vy,vw,vh );
    if (dw>0 && dh > 0){
      WSCrect r;
      r.setRect(dx - cx,dy - cy, dw,dh);
printf("WSDmacFormDev::expose_exec D16 %s expose=%d,%d,%d,%d\n",child->getAttachedClient()->getInstanceName(),dx-cx,dy-cy,dw,dh );
      child->expose_execute(&r);
    }
  }
  return WS_NO_ERR;
}
long WSDmacFormDev::mouse_press_execute(WSCpoint* pt){
  _mouse_press_target = this;
  long i;
  long num = _child_list.getNum();
  for(i=num-1; i> -1; i--){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
    long cx,cy,cw,ch;
    child->getGeometry(&cx,&cy,&cw,&ch);
printf("search:mouse press=%d %s\n",i,child->getAttachedClient()->getInstanceName());
    if (cx < pt->x && pt->x <= cx + cw &&
        cy < pt->y && pt->y <= cy + ch){
printf("hit mouse pressed target=%d %d,%d %s XXZZms1\n",i,pt->x,pt->y,child->getAttachedClient()->getInstanceName());
      _mouse_press_target = child;
      pt->x -= cx;
      pt->y -= cy;
      break;
    }
  }

  if (_mouse_press_target != NULL){
    if (this != _mouse_press_target){
      _mouse_press_target->mouse_press_execute(pt);
    }else{
      onMousePress(pt);
    }
  }else{
    onMousePress(pt);
  }

  return WS_NO_ERR;
}

long WSDmacFormDev::mouse_release_execute(WSCpoint* pt){
  if (_mouse_press_target != NULL){
    if (_mouse_press_target != this){
      long cx,cy,cw,ch;
      _mouse_press_target->getGeometry(&cx,&cy,&cw,&ch);
      pt->x -= cx;
      pt->y -= cy;
      _mouse_press_target->mouse_release_execute(pt);
    }else{
printf("hit mouse released target=%d,%d %s XXZZms21\n",pt->x,pt->y,getAttachedClient()->getInstanceName());
      onMouseRelease(pt);
    }
    _mouse_press_target = NULL;
  }else{
printf("hit mouse released2 target=%d,%d %s XXZZms21\n",pt->x,pt->y,getAttachedClient()->getInstanceName());
    onMouseRelease(pt);
  }

  return WS_NO_ERR;
}
long WSDmacFormDev::mouse_entered_execute(WSCpoint* pt){
  _mouse_move_target = this;
  long i;
  long num = _child_list.getNum();
  for(i=num-1; i> -1; i--){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
    long cx,cy,cw,ch;
    child->getGeometry(&cx,&cy,&cw,&ch);

    if (cx < pt->x && pt->x <= cx + cw &&
        cy < pt->y && pt->y <= cy + ch){
      _mouse_move_target = child;
      pt->x -= cx;
      pt->y -= cy;
      break;
    }
  }
  if (_mouse_move_target != NULL){
    if (this != _mouse_move_target){
      _mouse_move_target->mouse_entered_execute(pt);
    }else{
      onMouseIn(pt);
    }
  }else{
    onMouseIn(pt);
  }
  return WS_NO_ERR;
}
long WSDmacFormDev::mouse_leaved_execute(){
  if (_mouse_move_target != NULL){
    if (this != _mouse_move_target){
      _mouse_move_target->mouse_leaved_execute();
    }else{
      onMouseOut();
    }
    _mouse_move_target = NULL;
  }else{
    onMouseOut();
  }
  return WS_NO_ERR;
}
long WSDmacFormDev::mouse_moved_execute(WSCpoint* pt){
  WSDmacFormDev* bk = _mouse_move_target;
  long i;
  long num = _child_list.getNum();
  for(i=num-1; i> -1; i--){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
    long cx,cy,cw,ch;
    child->getGeometry(&cx,&cy,&cw,&ch);

    if (cx < pt->x && pt->x <= cx + cw &&
        cy < pt->y && pt->y <= cy + ch){
      _mouse_move_target = child;
      pt->x -= cx;
      pt->y -= cy;
      break;
    }
  }
  if (_mouse_move_target != bk){
    if (bk != NULL){
      bk->onMouseOut();
    }
  }
  if (_mouse_move_target != NULL){
    if (_mouse_move_target != bk){
      if (this != _mouse_move_target){
        _mouse_move_target->mouse_entered_execute(pt);
      }else{
        onMouseIn(pt);
      }
    }else{
      if (this != _mouse_move_target){
        _mouse_move_target->mouse_moved_execute(pt);
      }else{
        _mouse_move_target->onMouseMove(pt);
      }
    }
  }else{
    onMouseMove(pt);
  }

  return WS_NO_ERR;
}

long WSDmacFormDev::mouse_dragged_execute(WSCpoint* pt){
  if (_mouse_press_target != NULL){
    if (_mouse_press_target != this){
      long cx,cy,cw,ch;
      _mouse_press_target->getGeometry(&cx,&cy,&cw,&ch);
      pt->x -= cx;
      pt->y -= cy;
    }
    if (_mouse_press_target != this){
      _mouse_press_target->mouse_dragged_execute(pt);
    }else{
printf("WSDmacFormDev::mouse_dragged_execute target=%s pt=%d,%d XXZZm1\n",this->getAttachedClient()->getInstanceName(),pt->x,pt->y);
      onMouseMove(pt);
    }
  }else{
printf("WSDmacFormDev::mouse_dragged_execute target2=%s pt=%d,%d XXZZm1\n",this->getAttachedClient()->getInstanceName(),pt->x,pt->y);
    onMouseMove(pt);
  }
  return WS_NO_ERR;
}

void WSDmacFormDev::getVaridArea(long* x,long* y, long* w,long* h){
  if (_parent != NULL){
    long px,py,pw,ph;
    _parent->getVaridArea(&px,&py,&pw,&ph);
    long cx,cy,cw,ch;
    _parent->getGeometry(&cx,&cy,&cw,&ch);
    long dx,dy,dw,dh;
printf("D8 %s getVariArea %d,%d,%d,%d %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),px,py,pw,ph,cx,cy,cw,ch);
    WSGFandArea(px - cx,py - cy,pw,ph,_w_x,_w_y,_w_w,_w_h,&dx,&dy,&dw,&dh);
    *x = dx;
    *y = dy;
    *w = dw;
    *h = dh;
    return;
  }
  *x = 0;
  *y = 0;
  *w = _w_w;
  *h = _w_h;
}
void WSDmacFormDev::getAbsoluteVaridArea(long* x,long* y, long* w,long* h){
  if (_parent != NULL){
    long px,py,pw,ph;
    _parent->getAbsoluteVaridArea(&px,&py,&pw,&ph);
    long cx,cy,cw,ch;
    _parent->getAbsoluteGeometry(&cx,&cy,&cw,&ch);
    long dx,dy,dw,dh;
printf("D8 %s getVariArea %d,%d,%d,%d %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),px,py,pw,ph,cx,cy,cw,ch);
    WSGFandArea(px - cx,py - cy,pw,ph,_w_x,_w_y,_w_w,_w_h,&dx,&dy,&dw,&dh);
    getAbsoluteGeometry(&cx,&cy,&cw,&ch);
    *x = dx+cx;
    *y = dy+cy;
    *w = dw;
    *h = dh;
    return;
  }
  *x = 0;
  *y = 0;
  *w = _w_w;
  *h = _w_h;
}



long WSDmacFormDev::beginDraw(short x,short y,WSCushort w,WSCushort h,   
                         WSCbool absolute,WSCbool scaling){
if (getVisible() == False){
  return WS_ERR;
}

if (getAttachedClient() != NULL){
printf("WSDmacFormDev::beginDraw D2 inst=%s\n",getAttachedClient()->getInstanceName());
}
  long ret = WSDwindowDev::beginDraw(x,y,w,h,absolute,scaling);
  if (ret != WS_NO_ERR){
    return ret;
  }

  long wx = _w_x;
  long wy = _w_y;
  if (_is_win != False){
    wx = 0;
    wy = 0;
  }
printf("WSDmacFormDev::beginDraw D15 %s xywh=%d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),x,y,w,h);
printf("WSDmacFormDev::beginDraw D7 %s wx,wy=%d,%d\n",getAttachedClient()->getInstanceName(),wx,wy);
  long px,py;
  WSCulong pw,ph;
  long cx,cy;
  WSCulong cw,ch;
  getVaridArea(&px,&py,&pw,&ph);
//  WSGFandArea(wx,wy,_w_w,_w_h,px + wx,py + wy,pw,ph,&cx,&cy,&cw,&ch);
//XXZZXXZZ
  WSGFandArea(wx,wy,_w_w,_w_h,px,py,pw,ph,&cx,&cy,&cw,&ch);
  px = cx - wx;
  py = cy - wy;
  pw = cw;
  ph = ch;
  WSGFandArea(x,y,w,h,px,py,pw,ph,&cx,&cy,&cw,&ch);
printf("WSDmacFormDev::beginDraw D15 %s %d,%d,%d,%d varid=%d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),wx,wy,_w_w,_w_h,px,py,pw,ph);
  RgnHandle rh1 = NewRgn();
  RgnHandle rh2 = NewRgn();
  RgnHandle rh3 = NewRgn();
  RgnHandle rh4 = NewRgn();
  GetClip(rh1);
  getAbsoluteGeometry(&px,&py,&pw,&ph);
  
  SetRectRgn(rh2,cx+px,cy+py,cx+px+cw,cy+py+ch);
  SectRgn(rh1,rh2,rh3);

  CopyRgn(rh3,rh1);

  SetRectRgn(rh4,0,0,0x7fff,0x7fff);

  long num = _child_list.getNum();
  if (num > 0){
    long i;
    long set = False;
    for(i=0; i<num; i++){
      WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
      if (child->getVisible() == False){
        continue;
      }
      long cx,cy,cw,ch;
      child->getAbsoluteGeometry(&cx,&cy,&cw,&ch);
      SetRectRgn(rh2,cx,cy,cx+cw,cy+ch);
printf(" WSDmacFormDev::beginDraw D15 clip out child=%s %d,%d,%d,%d\n",child->getAttachedClient()->getInstanceName(),cx,cy,cw,ch);
      XorRgn(rh2,rh4,rh3);
      CopyRgn(rh3,rh2);
      SectRgn(rh1,rh2,rh3);
      CopyRgn(rh3,rh1);
//      set = True;
    }
//    if (set != False){
//      SetClip(rh1);
//    }
  }
  SetClip(rh1);
#if 0
  RGBForeColor(&_bgc);
//  Pattern whitept;
//  GetQDGlobalsWhite(&whitept);   
  Rect rect;
  SetRect(&rect,wx,wy,wx+_w_w,wy+_w_h);
  PaintRect(&rect);
#endif

  DisposeRgn(rh1);
  DisposeRgn(rh2);
  DisposeRgn(rh3);
  DisposeRgn(rh4);

  return ret;
}
WSDmacFormDev* WSDmacFormDev::getChildByPoint(short x,short y){
  long i;
  long num = _child_list.getNum();       
  for(i=num-1; i> -1; i--){
    WSDmacFormDev* child = (WSDmacFormDev*)_child_list[i];
printf("WSDmacWinDev::getChildByPoint D21 child=%s vis=%d\n",child->getAttachedClient()->getInstanceName(),child->getVisible());
    if (child->getVisible() == False){
      continue;
    }
    long cx,cy,cw,ch;
    child->getGeometry(&cx,&cy,&cw,&ch);
    WSCpoint* basept = (WSCpoint*)child->getContextResource();
    cx = basept->x + _diff_x;
    cy = basept->y + _diff_y;
printf(" mouse pressed D21 cx,cy=%d,%d,%d,%d x,y=%d,%d\n",cx,cy,cx+cw,cy+ch,x,y);
    if (cx < x && x <= cx + cw &&
        cy < y && y <= cy + ch){
      return child->getChildByPoint(x,y);
    }
  }
printf("WSDmacWinDev::getChildByPoint D21 return=%s num=%d\n",getAttachedClient()->getInstanceName(),num);
  return this;
}

