]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/window.cpp
More Motif additions: mdi and sashtest samples now just about work!
[wxWidgets.git] / src / motif / window.cpp
index 5e8e991befc1b5c5849607f92f459539eea6b979..cbaa0704909d41e807fa6c1540011d36ee33e39c 100644 (file)
@@ -31,7 +31,7 @@
 #include "wx/menuitem.h"
 #include "wx/log.h"
 
-#if  USE_DRAG_AND_DROP
+#if  wxUSE_DRAG_AND_DROP
 #include "wx/dnd.h"
 #endif
 
@@ -52,6 +52,8 @@ void wxCanvasRepaintProc (Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
 void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
 void wxCanvasMotionEvent (Widget, XButtonEvent * event);
 void wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
+void wxScrollBarCallback(Widget widget, XtPointer clientData,
+                        XmScaleCallbackStruct *cbs);
 void wxPanelItemEventHandler (Widget    wid,
                               XtPointer client_data,
                               XEvent*   event,
@@ -99,12 +101,11 @@ wxWindow::wxWindow()
     m_caretWidth = 0; m_caretHeight = 0;
     m_caretEnabled = FALSE;
     m_caretShown = FALSE;
-    m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
+    // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
+    m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
     m_foregroundColour = *wxBLACK;
-    m_defaultForegroundColour = *wxBLACK ;
-    m_defaultBackgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
 
-#if  USE_DRAG_AND_DROP
+#if  wxUSE_DRAG_AND_DROP
     m_pDropTarget = NULL;
 #endif
 
@@ -122,8 +123,6 @@ wxWindow::wxWindow()
     m_drawingArea = (WXWidget) 0;
     m_hScroll = FALSE;
     m_vScroll = FALSE;
-    m_hScrollingEnabled = FALSE;
-    m_vScrollingEnabled = FALSE;
     m_backingPixmap = (WXPixmap) 0;
     m_pixmapWidth = 0;
     m_pixmapHeight = 0;
@@ -132,67 +131,74 @@ wxWindow::wxWindow()
     m_lastTS = 0;
     m_lastButton = 0;
     m_canAddEventHandler = FALSE;
+    m_scrollPosX = 0;
+    m_scrollPosY = 0;
+    m_paintRegion = (WXRegion) 0;
 }
 
 // Destructor
 wxWindow::~wxWindow()
 {
-  //// Motif-specific
+    //// Motif-specific
 
-  if (GetMainWidget())
-    DetachWidget(GetMainWidget()); // Removes event handlers
+    if (m_paintRegion)
+        XDestroyRegion ((Region) m_paintRegion);
+    m_paintRegion = (WXRegion) 0;
 
-  // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
-  if (m_drawingArea)
-  {
-    // Destroy children before destroying self
-    DestroyChildren();
+    if (GetMainWidget())
+        DetachWidget(GetMainWidget()); // Removes event handlers
 
-    if (m_backingPixmap)
-      XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
+    // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
+    if (m_drawingArea)
+    {
+        // Destroy children before destroying self
+        DestroyChildren();
 
-    Widget w = (Widget) m_drawingArea;
-    wxDeleteWindowFromTable(w);
+        if (m_backingPixmap)
+        XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
 
-    if (w)
-      XtDestroyWidget(w);
-    m_mainWidget = (WXWidget) 0;
+        Widget w = (Widget) m_drawingArea;
+        wxDeleteWindowFromTable(w);
 
-    // Only if we're _really_ a canvas (not a dialog box/panel)
-    if (m_scrolledWindow)
-    {
-      wxDeleteWindowFromTable((Widget) m_scrolledWindow);
-    }
+        if (w)
+            XtDestroyWidget(w);
+        m_mainWidget = (WXWidget) 0;
 
-    if (m_hScrollBar)
-    {
-      XtUnmanageChild ((Widget) m_hScrollBar);
-      XtDestroyWidget ((Widget) m_hScrollBar);
-    }
-    if (m_vScrollBar)
-    {
-      XtUnmanageChild ((Widget) m_vScrollBar);
-      XtDestroyWidget ((Widget) m_vScrollBar);
-    }
-    if (m_scrolledWindow)
-    {
-      XtUnmanageChild ((Widget) m_scrolledWindow);
-      XtDestroyWidget ((Widget) m_scrolledWindow);
-    }
+        // Only if we're _really_ a canvas (not a dialog box/panel)
+        if (m_scrolledWindow)
+        {
+            wxDeleteWindowFromTable((Widget) m_scrolledWindow);
+        }
 
-    if (m_borderWidget)
-    {
-      XtDestroyWidget ((Widget) m_borderWidget);
-      m_borderWidget = (WXWidget) 0;
+        if (m_hScrollBar)
+        {
+            XtUnmanageChild ((Widget) m_hScrollBar);
+            XtDestroyWidget ((Widget) m_hScrollBar);
+        }
+        if (m_vScrollBar)
+        {
+            XtUnmanageChild ((Widget) m_vScrollBar);
+            XtDestroyWidget ((Widget) m_vScrollBar);
+        }
+        if (m_scrolledWindow)
+        {
+            XtUnmanageChild ((Widget) m_scrolledWindow);
+            XtDestroyWidget ((Widget) m_scrolledWindow);
+        }
+
+        if (m_borderWidget)
+        {
+            XtDestroyWidget ((Widget) m_borderWidget);
+            m_borderWidget = (WXWidget) 0;
+        }
     }
-  }
 
-  //// Generic stuff
+    //// Generic stuff
 
        // Have to delete constraints/sizer FIRST otherwise
        // sizers may try to look at deleted windows as they
        // delete themselves.
-#if USE_CONSTRAINTS
+#if wxUSE_CONSTRAINTS
     DeleteRelatedConstraints();
     if (m_constraints)
     {
@@ -264,7 +270,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     m_sizerParent = NULL;
     m_autoLayout = FALSE;
     m_windowValidator = NULL;
-#if USE_DRAG_AND_DROP
+#if wxUSE_DRAG_AND_DROP
     m_pDropTarget = NULL;
 #endif
     m_caretWidth = 0; m_caretHeight = 0;
@@ -292,13 +298,14 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     m_drawingArea = (WXWidget) 0;
     m_hScroll = FALSE;
     m_vScroll = FALSE;
-    m_hScrollingEnabled = FALSE;
-    m_vScrollingEnabled = FALSE;
     m_backingPixmap = (WXPixmap) 0;
     m_pixmapWidth = 0;
     m_pixmapHeight = 0;
     m_pixmapOffsetX = 0;
     m_pixmapOffsetY = 0;
+    m_scrollPosX = 0;
+    m_scrollPosY = 0;
+    m_paintRegion = (WXRegion) 0;
 
     if (!parent)
         return FALSE;
@@ -314,10 +321,9 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     else
        m_windowId = id;
 
-    m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
+    // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
+    m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
     m_foregroundColour = *wxBLACK;
-    m_defaultForegroundColour = *wxBLACK ;
-    m_defaultBackgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
 
     m_windowStyle = style;
 
@@ -413,7 +419,68 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
   XtAddEventHandler ((Widget) m_drawingArea, PointerMotionHintMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask,
     False, (XtEventHandler) wxCanvasEnterLeave, (XtPointer) this);
 
-    return TRUE;
+  // Add scrollbars if required
+  if (m_windowStyle & wxHSCROLL)
+  {
+      Widget hScrollBar = XtVaCreateManagedWidget ("hsb",
+                                    xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
+                                               XmNorientation, XmHORIZONTAL,
+                                               NULL);
+      //         XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+         XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL);
+
+      XtVaSetValues (hScrollBar,
+                    XmNincrement, 1,
+                    XmNvalue, 0,
+                    NULL);
+
+      m_hScrollBar = (WXWidget) hScrollBar;
+      m_hScroll = TRUE;
+  }
+  if (m_windowStyle & wxVSCROLL)
+  {
+      Widget vScrollBar = XtVaCreateManagedWidget ("vsb",
+                                    xmScrollBarWidgetClass, (Widget) m_scrolledWindow,
+                                               XmNorientation, XmVERTICAL,
+                                               NULL);
+      //         XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+         XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL);
+
+      XtVaSetValues (vScrollBar,
+                    XmNincrement, 1,
+                    XmNvalue, 0,
+                    NULL);
+
+      m_vScrollBar = (WXWidget) vScrollBar;
+      m_vScroll = TRUE;
+  }
+
+  if (m_hScrollBar || m_vScrollBar)
+    XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea);
+
+  if (m_hScrollBar)
+       XtRealizeWidget ((Widget) m_hScrollBar);
+  if (m_vScrollBar)
+       XtRealizeWidget ((Widget) m_vScrollBar);
+
+  // Without this, the cursor may not be restored properly
+  // (e.g. in splitter sample).
+  SetCursor(*wxSTANDARD_CURSOR);
+  SetSize(pos.x, pos.y, size.x, size.y);
+
+  return TRUE;
 }
 
 void wxWindow::SetFocus()
@@ -480,7 +547,7 @@ wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
                return NULL;
 }
 
-#if    USE_DRAG_AND_DROP
+#if    wxUSE_DRAG_AND_DROP
 
 void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
 {
@@ -520,20 +587,39 @@ void wxWindow::GetSize(int *x, int *y) const
 
 void wxWindow::GetPosition(int *x, int *y) const
 {
-  if (m_drawingArea)
-  {
-    CanvasGetPosition(x, y);
-    return;
-  }
-  Widget widget = (Widget) GetTopWidget();
-  Position xx, yy;
-  XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
-  *x = xx; *y = yy;
+    if (m_drawingArea)
+    {
+        CanvasGetPosition(x, y);
+        return;
+    }
+    Widget widget = (Widget) GetTopWidget();
+    Position xx, yy;
+    XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
+
+    // We may be faking the client origin.
+    // So a window that's really at (0, 30) may appear
+    // (to wxWin apps) to be at (0, 0).
+    if (GetParent())
+    {
+        wxPoint pt(GetParent()->GetClientAreaOrigin());
+        xx -= pt.x;
+        yy -= pt.y;
+    }
+
+    *x = xx; *y = yy;
 }
 
 void wxWindow::ScreenToClient(int *x, int *y) const
 {
-    // TODO
+  Widget widget = (Widget) GetClientWidget();
+  Display *display = XtDisplay((Widget) GetMainWidget());
+  Window rootWindow = RootWindowOfScreen(XtScreen(widget));
+  Window thisWindow = XtWindow(widget);
+
+  Window childWindow;
+  int xx = *x;
+  int yy = *y;
+  XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
 }
 
 void wxWindow::ClientToScreen(int *x, int *y) const
@@ -541,15 +627,7 @@ void wxWindow::ClientToScreen(int *x, int *y) const
   Widget widget = (Widget) GetClientWidget();
   Display *display = XtDisplay(widget);
   Window rootWindow = RootWindowOfScreen(XtScreen(widget));
-  Window thisWindow;
-  if (this->IsKindOf(CLASSINFO(wxFrame)))
-  {
-    wxFrame *fr = (wxFrame *)this;
-    // TODO
-    //    thisWindow = XtWindow(fr->m_clientArea);
-  }
-  else
-    thisWindow = XtWindow((Widget)widget);
+  Window thisWindow = XtWindow(widget);
 
   Window childWindow;
   int xx = *x;
@@ -562,14 +640,12 @@ void wxWindow::SetCursor(const wxCursor& cursor)
   m_windowCursor = cursor;
   if (m_windowCursor.Ok())
   {
-    /* TODO when wxCursor implemented
     WXDisplay *dpy = GetXDisplay();
-    Cursor x_cursor = cursor.GetXCursor(dpy);
+    WXCursor x_cursor = ((wxCursor&)cursor).GetXCursor(dpy);
 
     Widget w = (Widget) GetMainWidget();
     Window win = XtWindow(w);
-    XDefineCursor((Display*) dpy, win, x_cursor);
-    */
+    XDefineCursor((Display*) dpy, win, (Cursor) x_cursor);
   }
 }
 
@@ -577,7 +653,7 @@ void wxWindow::SetCursor(const wxCursor& cursor)
 // Get size *available for subwindows* i.e. excluding menu bar etc.
 void wxWindow::GetClientSize(int *x, int *y) const
 {
-  Widget widget = (Widget) GetTopWidget();
+  Widget widget = (Widget) GetClientWidget();
   Dimension xx, yy;
   XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
   *x = xx; *y = yy;
@@ -598,10 +674,13 @@ void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
   if (managed)
     XtUnmanageChild(widget);
 
+  int xx = x; int yy = y;
+  AdjustForParentClientOrigin(xx, yy, sizeFlags);
+
   if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-    XtVaSetValues(widget, XmNx, x, NULL);
+    XtVaSetValues(widget, XmNx, xx, NULL);
   if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-    XtVaSetValues(widget, XmNy, y, NULL);
+    XtVaSetValues(widget, XmNy, yy, NULL);
   if (width > -1)
     XtVaSetValues(widget, XmNwidth, width, NULL);
   if (height > -1)
@@ -701,24 +780,77 @@ bool wxWindow::IsShown() const
 
 int wxWindow::GetCharHeight() const
 {
-    // TODO
+  if (!m_windowFont.Ok())
     return 0;
+
+  WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
+
+  int direction, ascent, descent;
+  XCharStruct overall;
+  XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
+        &descent, &overall);
+//  return (overall.ascent + overall.descent);
+  return (ascent + descent);
 }
 
 int wxWindow::GetCharWidth() const
 {
-    // TODO
+  if (!m_windowFont.Ok())
     return 0;
+
+  WXFontStructPtr pFontStruct = m_windowFont.GetFontStruct(1.0, GetXDisplay());
+
+  int direction, ascent, descent;
+  XCharStruct overall;
+  XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
+        &descent, &overall);
+  return overall.width;
+}
+
+/* Helper function for 16-bit fonts */
+static int str16len(const char *s)
+{
+  int count = 0;
+
+  while (s[0] && s[1]) {
+    count++;
+    s += 2;
+  }
+
+  return count;
 }
 
 void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
-                           int *descent, int *externalLeading, const wxFont *theFont, bool) const
+                           int *descent, int *externalLeading, const wxFont *theFont, bool use16) const
 {
   wxFont *fontToUse = (wxFont *)theFont;
   if (!fontToUse)
     fontToUse = (wxFont *) & m_windowFont;
 
-    // TODO
+  if (!fontToUse->Ok())
+    return;
+
+  WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay());
+
+  int direction, ascent, descent2;
+  XCharStruct overall;
+  int slen;
+  
+  if (use16) slen = str16len(string); else slen = strlen(string);
+
+  if (use16)
+    XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
+           &ascent, &descent2, &overall);
+  else
+     XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
+         &ascent, &descent2, &overall);
+
+  *x = (overall.width);
+  *y = (ascent + descent2);
+  if (descent)
+    *descent = descent2;
+  if (externalLeading)
+    *externalLeading = 0;
 }
 
 void wxWindow::Refresh(bool eraseBack, const wxRectangle *rect)
@@ -753,6 +885,8 @@ void wxWindow::Refresh(bool eraseBack, const wxRectangle *rect)
     if (eraseBack)
     {
         wxClientDC dc(this);
+        wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID);
+        dc.SetBackground(backgroundBrush);
         dc.Clear();
     }
 
@@ -850,21 +984,20 @@ void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, in
       return;
 
     wxFrame *frame = (wxFrame *)this;
+    Widget widget = (Widget) frame->GetShellWidget();
 
-    /* Uncomment when wxFrame implemented
     if (minW > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNminWidth, minW, NULL);
+      XtVaSetValues(widget, XmNminWidth, minW, NULL);
     if (minH > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNminHeight, minH, NULL);
+      XtVaSetValues(widget, XmNminHeight, minH, NULL);
     if (maxW > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNmaxWidth, maxW, NULL);
+      XtVaSetValues(widget, XmNmaxWidth, maxW, NULL);
     if (maxH > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNmaxHeight, maxH, NULL);
+      XtVaSetValues(widget, XmNmaxHeight, maxH, NULL);
     if (incW > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNwidthInc, incW, NULL);
+      XtVaSetValues(widget, XmNwidthInc, incW, NULL);
     if (incH > -1)
-      XtVaSetValues((Widget) frame->m_frameShell, XmNheightInc, incH, NULL);
-      */
+      XtVaSetValues(widget, XmNheightInc, incH, NULL);
 }
 
 void wxWindow::Centre(int direction)
@@ -906,51 +1039,272 @@ void wxWindow::OnEraseBackground(wxEraseEvent& event)
 
 int wxWindow::GetScrollPos(int orient) const
 {
-    // TODO
-    return 0;
+    if (orient == wxHORIZONTAL)
+        return m_scrollPosX;
+    else
+        return m_scrollPosY;
+/*
+       Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
+       if (scrollBar)
+       {
+        int pos;
+        XtVaGetValues(scrollBar,
+            XmNvalue, &pos, NULL);
+        return pos;
+    }
+    else
+        return 0;
+*/
 }
 
 // This now returns the whole range, not just the number
 // of positions that we can scroll.
 int wxWindow::GetScrollRange(int orient) const
 {
-    // TODO
-    return 0;
+       Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
+       if (scrollBar)
+       {
+        int range;
+        XtVaGetValues(scrollBar,
+            XmNmaximum, &range, NULL);
+        return range;
+    }
+    else
+        return 0;
 }
 
 int wxWindow::GetScrollThumb(int orient) const
 {
-    // TODO
-    return 0;
+       Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
+       if (scrollBar)
+       {
+        int thumb;
+        XtVaGetValues(scrollBar,
+            XmNsliderSize, &thumb, NULL);
+        return thumb;
+    }
+    else
+        return 0;
 }
 
-void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
+void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
-    // TODO
-    return;
+       Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar);
+       if (scrollBar)
+       {
+               XtVaSetValues (scrollBar,
+                               XmNvalue, pos,
+                               NULL);
+       }
+        if (orient == wxHORIZONTAL)
+          m_scrollPosX = pos;
+        else
+          m_scrollPosY = pos;
+
 }
 
 // New function that will replace some of the above.
 void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
-    int range, bool refresh)
+    int range, bool WXUNUSED(refresh))
 {
-    // TODO
+    Widget scrollBar = (Widget) ((orient == wxHORIZONTAL) ? m_hScrollBar : m_vScrollBar );
+    if (!scrollBar)
+        return;
+
+    if (range == 0)
+      range = 1;
+    if (thumbVisible == 0)
+      thumbVisible = 1;
+
+    XtVaSetValues(scrollBar,
+         XmNvalue, pos,
+         XmNminimum, 0,
+         XmNmaximum, range,
+         XmNsliderSize, thumbVisible,
+         NULL);
+
+    if (orient == wxHORIZONTAL)
+        m_scrollPosX = pos;
+    else
+        m_scrollPosY = pos;
 }
 
 // Does a physical scroll
 void wxWindow::ScrollWindow(int dx, int dy, const wxRectangle *rect)
 {
-    // TODO
-    return;
+//  cerr << "Scrolling. delta = " << dx << ", " << dy << endl;
+  int x, y, w, h;
+  if (rect)
+  {
+    // Use specified rectangle
+    x = rect->x; y = rect->y; w = rect->width; h = rect->height;
+  }
+  else
+  {
+    // Use whole client area
+    x = 0; y = 0;
+    GetClientSize(& w, & h);
+  }
+
+  int x1 = (dx >= 0) ? x : x - dx ;
+  int y1 = (dy >= 0) ? y : y - dy;
+  int w1 = w - abs(dx);
+  int h1 = h - abs(dy);
+  int x2 = (dx >= 0) ? x + dx : x;
+  int y2 = (dy >= 0) ? y + dy : y;
+
+  wxClientDC dc(this);
+
+  dc.SetLogicalFunction (wxCOPY);
+
+  Widget widget = (Widget) GetMainWidget();
+  Window window = XtWindow(widget);
+  Display* display = XtDisplay(widget);
+
+  XCopyArea(display, window,
+    window, (GC) dc.GetGC(),
+    x1, y1,
+    w1, h1,
+    x2, y2);
+
+  dc.SetAutoSetting(TRUE);
+  wxBrush brush(GetBackgroundColour(), wxSOLID);
+  dc.SetBrush(brush); // ??
+
+  // We'll add rectangles to the list of update rectangles
+  // according to which bits we've exposed.
+  wxList updateRects;
+       
+  if (dx > 0)
+  {
+    wxRect *rect = new wxRect;
+    rect->x = x;
+    rect->y = y;
+    rect->width = dx;
+    rect->height = h;
+
+    XFillRectangle(display, window,
+      (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
+
+    rect->x = rect->x;
+    rect->y = rect->y;
+    rect->width = rect->width;
+    rect->height = rect->height;
+
+    updateRects.Append((wxObject*) rect);
+  }
+  else if (dx < 0)
+  {
+    wxRect *rect = new wxRect;
+
+    rect->x = x + w + dx;
+    rect->y = y;
+    rect->width = -dx;
+    rect->height = h;
+
+    XFillRectangle(display, window,
+      (GC) dc.GetGC(), rect->x, rect->y, rect->width,
+      rect->height);
+
+    rect->x = rect->x;
+    rect->y = rect->y;
+    rect->width = rect->width;
+    rect->height = rect->height;
+
+    updateRects.Append((wxObject*) rect);
+  }
+  if (dy > 0)
+  {
+    wxRect *rect = new wxRect;
+
+    rect->x = x;
+    rect->y = y;
+    rect->width = w;
+    rect->height = dy;
+
+    XFillRectangle(display, window,
+      (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
+
+    rect->x = rect->x;
+    rect->y = rect->y;
+    rect->width = rect->width;
+    rect->height = rect->height;
+
+    updateRects.Append((wxObject*) rect);
+  }
+  else if (dy < 0)
+  {
+    wxRect *rect = new wxRect;
+
+    rect->x = x;
+    rect->y = y + h + dy;
+    rect->width = w;
+    rect->height = -dy;
+
+    XFillRectangle(display, window,
+      (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height);
+
+    rect->x = rect->x;
+    rect->y = rect->y;
+    rect->width = rect->width;
+    rect->height = rect->height;
+
+    updateRects.Append((wxObject*) rect);
+  }
+  dc.SetBrush(wxNullBrush);
+
+  // Now send expose events
+
+  wxNode* node = updateRects.First();
+  while (node)
+  {
+    wxRect* rect = (wxRect*) node->Data();
+    XExposeEvent event;
+
+    event.type = Expose;
+    event.display = display;
+    event.send_event = True;
+    event.window = window;
+
+    event.x = rect->x;
+    event.y = rect->y;
+    event.width = rect->width;
+    event.height = rect->height;
+
+    event.count = 0;
+
+    XSendEvent(display, window, False, ExposureMask, (XEvent *)&event);
+
+    node = node->Next();
+
+  }
 }
 
 void wxWindow::SetFont(const wxFont& font)
 {
     m_windowFont = font;
 
-    if (!m_windowFont.Ok())
-           return;
-    // TODO
+    // Note that this causes the widget to be resized back
+    // to its original size! We therefore have to set the size
+    // back again. TODO: a better way in Motif?
+    /*
+    Widget w = (Widget) GetLabelWidget(); // Usually the main widget
+    if (w && m_windowFont.Ok())
+    {
+        int width, height, width1, height1;
+        GetSize(& width, & height);
+
+        XtVaSetValues (w,
+                  XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay(w)),
+                  NULL);
+
+        GetSize(& width1, & height1);
+        if (width != width1 || height != height1)
+        {
+            SetSize(-1, -1, width, height);
+        }
+    }
+    */
 }
 
 void wxWindow::OnChar(wxKeyEvent& event)
@@ -972,7 +1326,8 @@ void wxWindow::OnPaint(wxPaintEvent& event)
 
 bool wxWindow::IsEnabled() const
 {
-    // TODO
+    // TODO. Is this right?
+    // return XtGetSensitive((Widget) GetMainWidget());
     return FALSE;
 }
 
@@ -1547,7 +1902,7 @@ void wxWindow::OnDefaultAction(wxControl *initiatingItem)
 
 void wxWindow::Clear()
 {
-       wxClientDC dc(this);
+    wxClientDC dc(this);
     wxBrush brush(GetBackgroundColour(), wxSOLID);
     dc.SetBackground(brush);
     dc.Clear();
@@ -2052,6 +2407,8 @@ void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallba
 
         wxevent.SetId(canvas->GetId());
         wxevent.SetEventObject(canvas);
+        wxevent.m_x = local_event.xbutton.x;
+        wxevent.m_y = local_event.xbutton.y;
        canvas->GetEventHandler()->ProcessEvent (wxevent);
        /*
        if (eventType == wxEVT_ENTER_WINDOW ||
@@ -2166,16 +2523,19 @@ void wxWindow::CanvasSetSize (int x, int y, int w, int h, int sizeFlags)
     XtUnmanageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
   XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
 
+  int xx = x; int yy = y;
+  AdjustForParentClientOrigin(xx, yy, sizeFlags);
+
   if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
     {
       XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
-                    XmNx, x, NULL);
+                    XmNx, xx, NULL);
     }
 
   if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
     {
       XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
-                    XmNy, y, NULL);
+                    XmNy, yy, NULL);
     }
 
   if (w > -1)
@@ -2313,10 +2673,21 @@ void wxWindow::CanvasGetSize (int *w, int *h) const
 
 void wxWindow::CanvasGetPosition (int *x, int *y) const
 {
-  Position xx, yy;
-  XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
-  *x = xx;
-  *y = yy;
+    Position xx, yy;
+    XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
+
+    // We may be faking the client origin.
+    // So a window that's really at (0, 30) may appear
+    // (to wxWin apps) to be at (0, 0).
+    if (GetParent())
+    {
+        wxPoint pt(GetParent()->GetClientAreaOrigin());
+        xx -= pt.x;
+        yy -= pt.y;
+    }
+
+    *x = xx;
+    *y = yy;
 }
 
 // Add to hash table, add event handler
@@ -2407,6 +2778,74 @@ void wxPanelItemEventHandler (Widget    wid,
   *continueToDispatch = True;
 }
 
+void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
+                        XmScaleCallbackStruct *cbs)
+{
+    Widget scrolledWindow = XtParent (scrollbar);
+    wxWindow *win = (wxWindow *) wxWidgetHashTable->Get ((long) scrolledWindow);
+    int orientation = (int) clientData;
+
+    wxEventType eventType = wxEVT_NULL;
+    switch (cbs->reason)
+    {
+        case XmCR_INCREMENT:
+        {
+            eventType = wxEVT_SCROLL_LINEDOWN;
+            break;
+        }
+        case XmCR_DECREMENT:
+        {
+            eventType = wxEVT_SCROLL_LINEUP;
+            break;
+        }
+        case XmCR_DRAG:
+        {
+            eventType = wxEVT_SCROLL_THUMBTRACK;
+            break;
+        }
+        case XmCR_VALUE_CHANGED:
+        {
+            // TODO: Should this be intercepted too, or will it cause
+            // duplicate events?
+            eventType = wxEVT_SCROLL_THUMBTRACK;
+            break;
+        }
+        case XmCR_PAGE_INCREMENT:
+        {
+            eventType = wxEVT_SCROLL_PAGEDOWN;
+            break;
+        }
+        case XmCR_PAGE_DECREMENT:
+        {
+            eventType = wxEVT_SCROLL_PAGEUP;
+            break;
+        }
+        case XmCR_TO_TOP:
+        {
+            eventType = wxEVT_SCROLL_TOP;
+            break;
+        }
+        case XmCR_TO_BOTTOM:
+        {
+            eventType = wxEVT_SCROLL_BOTTOM;
+            break;
+        }
+        default:
+        {
+            // Should never get here
+            wxFAIL_MSG("Unknown scroll event.");
+            break;
+        }
+    }
+
+    wxScrollEvent event(eventType, win->GetId());
+    event.SetEventObject(win);
+    event.SetPosition(cbs->value);
+    event.SetOrientation( (orientation == XmHORIZONTAL) ? wxHORIZONTAL : wxVERTICAL );
+
+    win->GetEventHandler()->ProcessEvent(event);
+}
+
 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
 {
   switch (xevent->xany.type)
@@ -2657,10 +3096,14 @@ void wxWindow::ChangeColour(WXWidget widget)
 
 void wxWindow::ChangeFont(WXWidget widget)
 {
-  /* TODO
-  if (widget && GetFont() && GetFont()->IsOk())
-    XtVaSetValues ((Widget) widget,
-                  XmNfontList, GetFont()->GetInternalFont (),
+  /*
+  if (widget && GetFont() && GetFont()->Ok())
+  {
+    XmFontList fontList = (XmFontList) GetFont()->GetFontList(1.0, GetXDisplay());
+    if (fontList)
+        XtVaSetValues ((Widget) widget,
+                  XmNfontList, fontList,
                   NULL);
+  }
   */
 }