/*
 * File:	wx_win.cc
 * Purpose:	wxWindow class implementation (X version)
 * Author:	Julian Smart
 * Created:	1993
 * Updated:	August 1994
 * RCS_ID:      $Id: wx_win.cc,v 1.5 1994/08/14 21:28:43 edz Exp $
 * Copyright:	(c) 1993, AIAI, University of Edinburgh
 */

static const char sccsid[] = "@(#)wx_win.cc	1.2 5/9/94";

#ifdef __GNUG__
#pragma implementation
#endif

#include <X11/keysym.h>
// #include <iostream.h>

#include "common.h"
#include "wx_win.h"
#include "wx_main.h"
#include "wx_utils.h"
#include "wx_privt.h"
#include "wx_gdi.h"
#include "wx_canvs.h"
#include "wx_menu.h"
#include "wx_panel.h"

#ifdef wx_motif
#include "wx_dialg.h"
#include <Xm/RowColumn.h>
#endif

#ifdef wx_xview
#include <xview/wmgr.h>
#include <xview/svrimage.h>
extern Xv_Server xview_server;
// Intercept focus events
extern "C" int win_set_kbd_focus(Xv_Window, XID);
extern void wxMenuProc (Menu x_menu, Menu_item menu_item);
#endif

// Constructor
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)

wxWindow::wxWindow(void)
{
  currentWindowCursor = 0;
#ifdef wx_motif
  wxType = 0;
  button1Pressed = FALSE;
  button2Pressed = FALSE;
  button3Pressed = FALSE;
#endif
#ifdef wx_xview
  dropSite = 0;
#endif
}

// Destructor
wxWindow::~wxWindow(void)
{
  if (window_parent)
  {
    window_parent->RemoveChild(this);

    if (wxSubType(window_parent->__type, wxTYPE_PANEL))
    {
      wxPanel *panel = (wxPanel *) GetParent ();
      // Must reset the panel since we may have dangling pointers, etc.

      panel->new_line = FALSE;
      panel->label_position = wxHORIZONTAL;

      panel->hSpacing = PANEL_HSPACING;
      panel->vSpacing = PANEL_VSPACING;
      panel->initial_hspacing = panel->hSpacing;
      panel->initial_vspacing = panel->vSpacing;
      panel->current_hspacing = panel->hSpacing;
      panel->current_vspacing = panel->vSpacing;
#ifdef wx_motif
      panel->cursor_x = PANEL_LEFT_MARGIN;
      panel->cursor_y = PANEL_TOP_MARGIN;
      panel->max_height = 0;
      panel->max_line_height = 0;
      panel->max_width = 0;
      panel->firstRowWidget = 0;
      panel->currentRow = 0;
      panel->currentCol = 0;
      panel->last_created = 0;
#endif
    }
  }
#ifdef wx_motif
  if (handle)
  {
    DestroyChildren();

    wxWidgetHashTable->Delete((long)handle);
    Widget w = (Widget)handle;
    if (w)
      XtDestroyWidget(w);

    PostDestroyChildren();

  }
#endif
#ifdef wx_xview
  if (handle)
  {
    // Reset client data
    xv_set((Xv_opaque)handle, WIN_CLIENT_DATA, NULL, NULL);
    DestroyChildren();
    xv_destroy_safe((Xv_opaque)handle);
  }
#endif
  delete children;
  children = NULL;
}

void wxWindow::SetFocus(void)
{
#ifdef wx_motif
  XmProcessTraversal((Widget)handle, XmTRAVERSE_CURRENT);
  XmProcessTraversal((Widget)handle, XmTRAVERSE_CURRENT);
#endif
#ifdef wx_xview
  Xv_opaque win = (Xv_opaque)handle;
  Xv_opaque id = xv_get(win, XV_XID);
  if (id)
    win_set_kbd_focus(win, id);
#endif
}

void wxWindow::CaptureMouse(void)
{
  if (winCaptured)
    return;
    
#ifdef wx_motif
  if (handle)
    XtAddGrab((Widget)handle, TRUE, FALSE);
#endif
#ifdef wx_xview
  if (handle)
  {
    Xv_opaque win = (Xv_opaque)handle;
    xv_set(win, WIN_GRAB_ALL_INPUT, TRUE, NULL);
  }
#endif
  winCaptured = TRUE;
}

void wxWindow::ReleaseMouse(void)
{
  if (!winCaptured)
    return;
    
#ifdef wx_motif
  if (handle)
    XtRemoveGrab((Widget)handle);
#endif
#ifdef wx_xview
  if (handle)
  {
    Xv_opaque win = (Xv_opaque)handle;
    xv_set(win, WIN_GRAB_ALL_INPUT, FALSE, NULL);
  }
#endif
  winCaptured = FALSE;
}

void wxWindow::Enable(Bool enable)
{
#ifdef wx_motif
  if (handle)
  {
    XtSetSensitive((Widget)handle, enable);
    XmUpdateDisplay((Widget)handle);
  }
#endif
#ifdef wx_xview
#endif
}

Window wxWindow::GetXWindow(void)
{
#ifdef wx_motif
  return XtWindow((Widget)handle);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;
  Window thisWindow = 0;
  if (wxSubType(__type, wxTYPE_CANVAS))
  {
    Xv_Window win = xv_get(x_win, CANVAS_NTH_PAINT_WINDOW, 0);
    thisWindow = xv_get(win, XV_XID);
  }
  else
  {
    thisWindow = xv_get(x_win, XV_XID);
  }
  return thisWindow;
#endif
}

Display *wxWindow::GetXDisplay(void)
{
#ifdef wx_motif
  return XtDisplay((Widget)handle);
#endif
#ifdef wx_xview
  return wxGetDisplay();
#endif
}

void wxWindow::Refresh(void)
{
#ifdef wx_motif
  Display *display = XtDisplay((Widget)handle);
  Window thisWindow = XtWindow((Widget)handle);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;
  wmgr_refreshwindow(x_win); // Refresh Window manager
  Xv_Window win = 0;
  Display *display = wxGetDisplay();
  Window thisWindow = 0;
  if (wxSubType(__type, wxTYPE_CANVAS) && !wxSubType(__type, wxTYPE_PANEL))
  {
    win = xv_get(x_win, CANVAS_NTH_PAINT_WINDOW, 0);
    thisWindow = xv_get(win, XV_XID);
  }
  else
  {
    thisWindow = xv_get(x_win, XV_XID);
  }
#endif
  XExposeEvent dummyEvent;
  int width, height;
  GetSize(&width, &height);

  dummyEvent.type = Expose;
  dummyEvent.display = display;
  dummyEvent.send_event = True;
  dummyEvent.window = thisWindow;
  dummyEvent.x = 0;
  dummyEvent.y = 0;
  dummyEvent.width = width;
  dummyEvent.height = height;
  dummyEvent.count = 0;

  XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent);
}

void wxWindow::DragAcceptFiles(Bool accept)
{
}

// Get total size
void wxWindow::GetSize(int *x, int *y)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;
  Dimension xx, yy;
  XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
  *x = xx; *y = yy;
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;

  *x = (int)xv_get(x_win, XV_WIDTH);
  *y = (int)xv_get(x_win, XV_HEIGHT);
#endif
}

void wxWindow::GetPosition(int *x, int *y)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;
  Dimension xx, yy;
  XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
  *x = xx; *y = yy;
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;

  *x = (int)xv_get(x_win, XV_X);
  *y = (int)xv_get(x_win, XV_Y);
#endif
}

void wxWindow::ClientToScreen(int *x, int *y)
{
#ifdef wx_motif
  Display *display = XtDisplay((Widget)handle);
  Window rootWindow = RootWindowOfScreen(XtScreen((Widget)handle));
  Window thisWindow;
  if (wxSubType(__type, wxTYPE_FRAME))
  {
    wxFrame *fr = (wxFrame *)this;
    thisWindow = XtWindow(fr->clientArea);
  }
  else
    thisWindow = XtWindow((Widget)handle);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;
  Xv_Window win = 0;
  Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  Xv_Window root_window = xv_get(screen, XV_ROOT);
  Display *display = (Display *)xv_get(root_window, XV_DISPLAY);
  Window rootWindow = xv_get(root_window, XV_XID);
  Window thisWindow = 0;
  if (wxSubType(__type, wxTYPE_CANVAS))
  {
    win = xv_get(x_win, CANVAS_NTH_PAINT_WINDOW, 0);
    thisWindow = xv_get(win, XV_XID);
  }
  else if (wxSubType(__type, wxTYPE_FRAME))
  {
    int xp, yp;
    GetPosition(&xp, &yp);
    *x = *x + xp;
    *y = *y + yp;
    return;
  }
  else
  {
    thisWindow = xv_get(x_win, XV_XID);
  }
#endif
  Window childWindow;
  int xx = *x;
  int yy = *y;
  XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow);
}

void wxWindow::ScreenToClient(int *x, int *y)
{
#ifdef wx_motif
  Display *display = XtDisplay((Widget)handle);
  Window rootWindow = RootWindowOfScreen(XtScreen((Widget)handle));
  Window thisWindow;
  if (wxSubType(__type, wxTYPE_FRAME))
  {
    wxFrame *fr = (wxFrame *)this;
    thisWindow = XtWindow(fr->clientArea);
  }
  else
    thisWindow = XtWindow((Widget)handle);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;
  Xv_Window win = 0;
  Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  Xv_Window root_window = xv_get(screen, XV_ROOT);
  Display *display = (Display *)xv_get(root_window, XV_DISPLAY);
  Window rootWindow = xv_get(root_window, XV_XID);
  Window thisWindow = 0;

  if (wxSubType(__type, wxTYPE_CANVAS))
  {
    win = xv_get(x_win, CANVAS_NTH_PAINT_WINDOW, 0);
    thisWindow = xv_get(win, XV_XID);
  }
  else if (wxSubType(__type, wxTYPE_FRAME))
  {
    int xp, yp;
    GetPosition(&xp, &yp);
    *x = *x - xp;
    *y = *y - yp;
    return;
  }
  else
  {
    thisWindow = xv_get(x_win, XV_XID);
  }
#endif
  Window childWindow;
  int xx = *x;
  int yy = *y;
  XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow);
}

wxCursor *wxWindow::SetCursor(wxCursor *cursor)
{
  wxCursor *old_cursor = wx_cursor;
  wx_cursor = cursor;
#ifdef wx_motif
  if (cursor && cursor->x_cursor)
  {
    Widget w = (Widget)handle;
    Window win = XtWindow(w);
    Display *dpy = XtDisplay(wxTheApp->topLevel);
    XDefineCursor(dpy, win, cursor->x_cursor);
  }
#endif
#ifdef wx_xview
  if (cursor && cursor->x_cursor)
  {
    if (cursor->use_raw_x_cursor)
    {
      Display *dpy = GetXDisplay();
      Window win2 = GetXWindow();

      XDefineCursor(dpy, win2, cursor->x_cursor);
    }
    else
    {
      if (wxSubType(__type, wxTYPE_CANVAS))
      {
        Xv_opaque x_win = (Xv_opaque)handle;
        Xv_Window win2 = xv_get(x_win, CANVAS_NTH_PAINT_WINDOW, 0);

        xv_set(win2, WIN_CURSOR, cursor->x_cursor, NULL);
      }
      else
        xv_set((Xv_opaque)handle, WIN_CURSOR, cursor->x_cursor, NULL);
    }
  }
#endif
  // Removed, because this causes a lot of unexpected effects
  // if cursor are changed dynamicaly into ::OnMouseEvent() method...
  // [receiving OnMouseEvent() calls before current call is completed!]
  //wxFlushEvents();
 
  return old_cursor;
}

void wxWindow::SetColourMap(wxColourMap *cmap)
{
  Display *display = GetXDisplay();
  Window win = GetXWindow();
  XSetWindowColormap(display, win, cmap->cmap);
}

// Get size *available for subwindows* i.e. excluding menu bar etc.
// For XView, this is the same as GetSize
void wxWindow::GetClientSize(int *x, int *y)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;
  Dimension xx, yy;
  XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
  *x = xx; *y = yy;
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;

  *x = (int)xv_get(x_win, XV_WIDTH);
  *y = (int)xv_get(x_win, XV_HEIGHT);
#endif
}

void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;

  if (x > -1)
    XtVaSetValues(widget, XmNx, x, NULL);
  if (y > -1)
    XtVaSetValues(widget, XmNy, y, NULL);
  if (width > -1)
    XtVaSetValues(widget, XmNwidth, width, NULL);
  if (height > -1)
    XtVaSetValues(widget, XmNheight, height, NULL);
  GetEventHandler()->OnSize(width, height);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;

  if (x == -1 || y == -1)
  {
    int xx,yy ;
    GetPosition(&xx, &yy);
    if (x == -1) x = xx ;
    if (y == -1) y = yy ;
  }

  if (width == -1 || height == -1)
  {
    int ww,hh ;
    GetSize(&ww, &hh);
    if (width == -1) width = ww ;
    if (height == -1) height = hh ;
  }

  // The reason we set these all at once (and not for each dimension
  // ignoring -1's) is that XView requires to do it all in one call, for optimum
  // results.
  (void)xv_set(x_win, XV_X, x, XV_Y, y, XV_WIDTH, width, XV_HEIGHT, height, NULL);

  GetEventHandler()->OnSize(width, height);
#endif
}

void wxWindow::SetClientSize(int width, int height)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;

  if (width > -1)
    XtVaSetValues(widget, XmNwidth, width, NULL);
  if (height > -1)
    XtVaSetValues(widget, XmNheight, height, NULL);
  GetEventHandler()->OnSize(width, height);
#endif
#ifdef wx_xview
  Xv_opaque x_win = (Xv_opaque)handle;

  if (width > -1 && height > -1)
    (void)xv_set(x_win, XV_WIDTH, width, XV_HEIGHT, height, NULL);

  GetEventHandler()->OnSize(width, height);
#endif
}

Bool wxWindow::Show(Bool show)
{
#ifdef wx_motif
  Window xwin=GetXWindow();        //*** all this part
  Display *xdisp=GetXDisplay();    //*** added by
  if(show)                         //*** chubraev
          XMapWindow(xdisp,xwin);  //***
  else                             //***
          XUnmapWindow(xdisp,xwin);//***
#endif
#ifdef wx_xview
  Xv_opaque window = (Xv_opaque)handle;
  xv_set(window, XV_SHOW, show, NULL);
#endif
  return TRUE;
}
float wxWindow::GetCharHeight(void)
{
#ifdef wx_motif
  return 0.0;
#endif
#ifdef wx_xview
  Xv_Font the_font;

  if (!(font && font->x_font))
  {
    Xv_opaque thing = (Xv_opaque)handle;
    the_font = (Xv_Font)xv_get(thing, XV_FONT);
  }
  else the_font = font->x_font;

  return (float)xv_get(the_font, FONT_DEFAULT_CHAR_HEIGHT);
#endif
}

float wxWindow::GetCharWidth(void)
{
#ifdef wx_motif
  return 0.0;
#endif
#ifdef wx_xview
  Xv_Font the_font;

  if (!(font && font->x_font))
  {
    Xv_opaque thing = (Xv_opaque)handle;
    the_font = (Xv_Font)xv_get(thing, XV_FONT);
  }
  else the_font = font->x_font;

  return (float)xv_get(the_font, FONT_DEFAULT_CHAR_WIDTH);
#endif
}

void wxWindow::GetTextExtent(const char *string, float *x, float *y,
                              float *descent, float *externalLeading, wxFont *theFont)
{
  wxFont *fontToUse = theFont;
  if (!fontToUse)
    fontToUse = font;
#ifdef wx_motif
  if (!(fontToUse && fontToUse->xFont))
#endif
#ifdef wx_xview
  if (!(fontToUse && fontToUse->x_font))
#endif
  {
    cerr << "wxWindows warning - set a font before calling GetTextExtent!\n";
    *x = -1;
    *y = -1;
    return;
  }
#ifdef wx_motif
  XFontStruct *fontStruct = fontToUse->xFont;
#endif
#ifdef wx_xview
  XFontStruct *fontStruct = (XFontStruct *)xv_get(fontToUse->x_font, FONT_INFO);
#endif
  int direction, ascent, descent2;
  XCharStruct overall;
  XTextExtents(fontStruct, string, strlen(string), &direction, &ascent,
               &descent2, &overall);
  *x = overall.width;
  *y = ascent + descent2;
  if (descent)
    *descent = (float)descent2;
  if (externalLeading)
    *externalLeading = 0.0;
}

Bool wxWindow:: PopupMenu (wxMenu * menu, float x, float y)
{
#ifdef wx_motif
  Widget widget = (Widget)handle;

//  if (!menu->handle)
//    menu->CreateMenu (NULL, wxTheApp->topLevel, menu);
  menu->DestroyMenu();
  menu->CreateMenu (NULL, widget, menu);

  Widget menuWidget = (Widget) menu->handle;

  int rootX = 0;
  int rootY = 0;

  int deviceX = (int) x;
  int deviceY = (int) y;

  if (wxSubType (__type, wxTYPE_CANVAS))
    {
      wxCanvas *canvas = (wxCanvas *) this;
/*
   int vs_x, vs_y;
   canvas->ViewStart(&vs_x, &vs_y);
   if (canvas->horiz_units > 0)
   scrollOffsetX = (int)(- vs_x*canvas->horiz_units);
   if (canvas->vert_units > 0)
   scrollOffsetY = (int)(- vs_y*canvas->vert_units);
 */
      deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
      deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
    }

  Display *display = XtDisplay ((Widget) handle);
  Window rootWindow = RootWindowOfScreen (XtScreen ((Widget) handle));
  Window thisWindow = XtWindow ((Widget) handle);
  Window childWindow;
  XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
			 &rootX, &rootY, &childWindow);

  XButtonPressedEvent event;
  event.type = ButtonPress;
  event.button = 1;

  event.x = (int) deviceX;
  event.y = (int) deviceY;

//  event.x_root = rootX;
  //  event.y_root = rootY;
  event.x_root = rootX;
  event.y_root = rootY;

  XmMenuPosition (menuWidget, &event);
  XtManageChild (menuWidget);

  return TRUE;
#endif
#ifdef wx_xview
  int deviceX = (int) x;
  int deviceY = (int) y;

  if (wxSubType (__type, wxTYPE_CANVAS))
    {
      wxCanvas *canvas = (wxCanvas *) this;
      int vs_x, vs_y;
      canvas->ViewStart (&vs_x, &vs_y);

      // Under XView, LogicalToDevice doesn't deal with scroll position
      deviceX = canvas->GetDC ()->LogicalToDeviceX (x) - vs_x * canvas->horiz_units;
      deviceY = canvas->GetDC ()->LogicalToDeviceY (y) - vs_y * canvas->vert_units;
    }

  xv_set ((Menu) this->handle,
	  MENU_NOTIFY_PROC, wxMenuProc,
	  NULL);

  Event event;
  event.ie_locx = (int) deviceX;
  event.ie_locy = (int) deviceY;
  event.ie_xevent = NULL;
  event.ie_win = (Xv_opaque) handle;
  event.ie_string = NULL;
  event.ie_code = 0;
  event.ie_flags = 0;
  event.ie_shiftmask = 0;
  event.action = 0;

  menu_show ((Menu) menu->handle,
	     (Xv_opaque) handle,
	     &event, NULL);

  return TRUE;
#endif
}

#ifdef wx_motif
// Sometimes in Motif there are problems popping up a menu
// (for unknown reasons); use this instead when this happens.
// Works for one-level popups only (ignores submenus).
Bool wxWindow::FakePopupMenu(wxMenu *menu, float x, float y)
{
  // Find true dialog box parent
  wxWindow *trueParent = NULL;
  if (wxSubType(__type, wxTYPE_CANVAS) ||
      wxSubType(__type, wxTYPE_PANEL) ||
      wxSubType(__type, wxTYPE_TEXT_WINDOW))
    trueParent = GetParent();
  else
    trueParent = this;

  // Find true screen x and y position
  int trueX = (int)x;
  int trueY = (int)y;

  ClientToScreen(&trueX, &trueY);

  // Create array of strings to pass to choose dialog
  int noStrings = menu->menuItems.Number();
  char **theStrings = new char *[noStrings];
  // Have an array of menu ids so can map position in
  // chooser list to menu id
  int *menuIds = new int[noStrings];

  int i = 0;
  
  for (wxNode * node = menu->menuItems.First (); node; node = node->Next ())
    {
      wxMenuItem *item = (wxMenuItem *) node->Data ();
      if ((item->itemId != -2) && (item->itemName && !item->subMenu) &&
          (item->isEnabled))
      {
        theStrings[i] = item->itemName;
        menuIds[i] = item->itemId;
        i ++;
      }
    }
  int stringIndex = wxGetSingleChoiceIndex("Please choose an option",
   "Menu", i, theStrings, trueParent, trueX, trueY);

  int menuId = 0;
  if (stringIndex > -1)
    menuId = menuIds[stringIndex];

  delete[] theStrings;
  delete[] menuIds;
  if (stringIndex > -1)
  {
    wxCommandEvent event (wxEVENT_TYPE_MENU_COMMAND);
    event.eventObject = menu;
    event.commandInt = menuId;
    menu->ProcessCommand (event);
  }
  return TRUE;
}
#endif

int CharCodeXToWX(KeySym keySym)
{
  int id;
  switch (keySym) {
    case XK_Shift_L:
    case XK_Shift_R:
      id = WXK_SHIFT; break;
    case XK_Control_L:
    case XK_Control_R:
      id = WXK_CONTROL; break;
    case XK_BackSpace:
      id = WXK_BACK; break;
    case XK_Delete:
      id = WXK_DELETE; break;
    case XK_Clear:
      id = WXK_CLEAR; break;
    case XK_Tab:
      id = WXK_TAB; break;
    case XK_numbersign:
      id = '#'; break;
    case XK_Return:
      id = WXK_RETURN; break;
    case XK_Escape:
      id = WXK_ESCAPE; break;
    case XK_Pause:
    case XK_Break:
      id = WXK_PAUSE; break;
    case XK_Num_Lock:
      id = WXK_NUMLOCK; break;
    case XK_Scroll_Lock:
      id = WXK_SCROLL; break;

    case XK_Home:
      id = WXK_HOME; break;
    case XK_End:
      id = WXK_END; break;
    case XK_Left:
      id = WXK_LEFT; break;
    case XK_Right:
      id = WXK_RIGHT; break;
    case XK_Up:
      id = WXK_UP; break;
    case XK_Down:
      id = WXK_DOWN; break;
    case XK_Next:
      id = WXK_NEXT; break;
    case XK_Prior:
      id = WXK_PRIOR; break;
    case XK_Menu:
      id = WXK_MENU; break;
    case XK_Select:
      id = WXK_SELECT; break;
    case XK_Cancel:
      id = WXK_CANCEL; break;
    case XK_Print:
      id = WXK_PRINT; break;
    case XK_Execute:
      id = WXK_EXECUTE; break;
    case XK_Insert:
      id = WXK_INSERT; break;
    case XK_Help:
      id = WXK_HELP; break;

    case XK_KP_Multiply:
      id = WXK_MULTIPLY; break;
    case XK_KP_Add:
      id = WXK_ADD; break;
    case XK_KP_Subtract:
      id = WXK_SUBTRACT; break;
    case XK_KP_Divide:
      id = WXK_DIVIDE; break;
    case XK_KP_Decimal:
      id = WXK_DECIMAL; break;
    case XK_KP_Equal:
      id = '='; break;
    case XK_KP_Space:
      id = ' '; break;
    case XK_KP_Tab:
      id = WXK_TAB; break;
    case XK_KP_Enter:
      id = WXK_RETURN; break;
    case XK_KP_0:
      id = WXK_NUMPAD0; break;
    case XK_KP_1:
      id = WXK_NUMPAD1; break;
    case XK_KP_2:
      id = WXK_NUMPAD2; break;
    case XK_KP_3:
      id = WXK_NUMPAD3; break;
    case XK_KP_4:
      id = WXK_NUMPAD4; break;
    case XK_KP_5:
      id = WXK_NUMPAD5; break;
    case XK_KP_6:
      id = WXK_NUMPAD6; break;
    case XK_KP_7:
      id = WXK_NUMPAD7; break;
    case XK_KP_8:
      id = WXK_NUMPAD8; break;
    case XK_KP_9:
      id = WXK_NUMPAD9; break;
    case XK_F1:
      id = WXK_F1; break;
    case XK_F2:
      id = WXK_F2; break;
    case XK_F3:
      id = WXK_F3; break;
    case XK_F4:
      id = WXK_F4; break;
    case XK_F5:
      id = WXK_F5; break;
    case XK_F6:
      id = WXK_F6; break;
    case XK_F7:
      id = WXK_F7; break;
    case XK_F8:
      id = WXK_F8; break;
    case XK_F9:
      id = WXK_F9; break;
    case XK_F10:
      id = WXK_F10; break;
    case XK_F11:
      id = WXK_F11; break;
    case XK_F12:
      id = WXK_F12; break;
    case XK_F13:
      id = WXK_F13; break;
    case XK_F14:
      id = WXK_F14; break;
    case XK_F15:
      id = WXK_F15; break;
    case XK_F16:
      id = WXK_F16; break;
    case XK_F17:
      id = WXK_F17; break;
    case XK_F18:
      id = WXK_F18; break;
    case XK_F19:
      id = WXK_F19; break;
    case XK_F20:
      id = WXK_F20; break;
    case XK_F21:
      id = WXK_F21; break;
    case XK_F22:
      id = WXK_F22; break;
    case XK_F23:
      id = WXK_F23; break;
    case XK_F24:
      id = WXK_F24; break;
    default:
      id = (keySym <= 255) ? (int)keySym : -1;
  } // switch
  return id;
}

KeySym CharCodeWXToX(int id)
{
  KeySym keySym;

  switch (id) {
    case WXK_CANCEL:            keySym = XK_Cancel; break;
    case WXK_BACK:              keySym = XK_BackSpace; break;
    case WXK_TAB:	        keySym = XK_Tab; break;
    case WXK_CLEAR:		keySym = XK_Clear; break;
    case WXK_RETURN:		keySym = XK_Return; break;
    case WXK_SHIFT:		keySym = XK_Shift_L; break;
    case WXK_CONTROL:		keySym = XK_Control_L; break;
    case WXK_MENU :		keySym = XK_Menu; break;
    case WXK_PAUSE:		keySym = XK_Pause; break;
    case WXK_ESCAPE:		keySym = XK_Escape; break;
    case WXK_SPACE:		keySym = ' '; break;
    case WXK_PRIOR:		keySym = XK_Prior; break;
    case WXK_NEXT :		keySym = XK_Next; break;
    case WXK_END:		keySym = XK_End; break;
    case WXK_HOME :		keySym = XK_Home; break;
    case WXK_LEFT :		keySym = XK_Left; break;
    case WXK_UP:		keySym = XK_Up; break;
    case WXK_RIGHT:		keySym = XK_Right; break;
    case WXK_DOWN :		keySym = XK_Down; break;
    case WXK_SELECT:		keySym = XK_Select; break;
    case WXK_PRINT:		keySym = XK_Print; break;
    case WXK_EXECUTE:		keySym = XK_Execute; break;
    case WXK_INSERT:		keySym = XK_Insert; break;
    case WXK_DELETE:		keySym = XK_Delete; break;
    case WXK_HELP :		keySym = XK_Help; break;
    case WXK_NUMPAD0:		keySym = XK_KP_0; break;
    case WXK_NUMPAD1:		keySym = XK_KP_1; break;
    case WXK_NUMPAD2:		keySym = XK_KP_2; break;
    case WXK_NUMPAD3:		keySym = XK_KP_3; break;
    case WXK_NUMPAD4:		keySym = XK_KP_4; break;
    case WXK_NUMPAD5:		keySym = XK_KP_5; break;
    case WXK_NUMPAD6:		keySym = XK_KP_6; break;
    case WXK_NUMPAD7:		keySym = XK_KP_7; break;
    case WXK_NUMPAD8:		keySym = XK_KP_8; break;
    case WXK_NUMPAD9:		keySym = XK_KP_9; break;
    case WXK_MULTIPLY:		keySym = XK_KP_Multiply; break;
    case WXK_ADD:		keySym = XK_KP_Add; break;
    case WXK_SUBTRACT:		keySym = XK_KP_Subtract; break;
    case WXK_DECIMAL:		keySym = XK_KP_Decimal; break;
    case WXK_DIVIDE:		keySym = XK_KP_Divide; break;
    case WXK_F1:		keySym = XK_F1; break;
    case WXK_F2:		keySym = XK_F2; break;
    case WXK_F3:		keySym = XK_F3; break;
    case WXK_F4:		keySym = XK_F4; break;
    case WXK_F5:		keySym = XK_F5; break;
    case WXK_F6:		keySym = XK_F6; break;
    case WXK_F7:		keySym = XK_F7; break;
    case WXK_F8:		keySym = XK_F8; break;
    case WXK_F9:		keySym = XK_F9; break;
    case WXK_F10:		keySym = XK_F10; break;
    case WXK_F11:		keySym = XK_F11; break;
    case WXK_F12:		keySym = XK_F12; break;
    case WXK_F13:		keySym = XK_F13; break;
    case WXK_F14:		keySym = XK_F14; break;
    case WXK_F15:		keySym = XK_F15; break;
    case WXK_F16:		keySym = XK_F16; break;
    case WXK_F17:		keySym = XK_F17; break;
    case WXK_F18:		keySym = XK_F18; break;
    case WXK_F19:		keySym = XK_F19; break;
    case WXK_F20:		keySym = XK_F20; break;
    case WXK_F21:		keySym = XK_F21; break;
    case WXK_F22:		keySym = XK_F22; break;
    case WXK_F23:		keySym = XK_F23; break;
    case WXK_F24:		keySym = XK_F24; break;
    case WXK_NUMLOCK:		keySym = XK_Num_Lock; break;
    case WXK_SCROLL:		keySym = XK_Scroll_Lock; break;
    default:                    keySym = id <= 255 ? (KeySym)id : 0;
  } // switch
  return keySym;
}

#ifdef wx_motif
Bool wxWindow::PreResize(void)
{
  return TRUE;
}

// All widgets should have this as their resize proc.
// OnSize sent to wxWindow via client data.
void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args)
{
  wxWindow *win = (wxWindow *)wxWidgetHashTable->Get((long)w);
  if (!win)
    return;
  if (win->PreResize()) {
    int width, height;
    win->GetSize(&width, &height);
    win->GetEventHandler()->OnSize(width, height);
  }
}
#endif

void wxWindow::SetFont(wxFont *f)
{
#ifdef wx_motif
  if (f) 
    XtVaSetValues ((Widget)handle,
		   XmNfontList, f->GetInternalFont (),
		   NULL);
#endif
#ifdef wx_xview
#endif
}

#ifdef wx_motif
Bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, XEvent *xevent)
{
  switch (xevent->xany.type)
  {
    case EnterNotify:
    case LeaveNotify:
    case ButtonPress:
    case ButtonRelease:
    case MotionNotify:
      {
	WXTYPE eventType = 0;

        if (xevent->xany.type == LeaveNotify)
	{
          win->button1Pressed = FALSE;
          win->button2Pressed = FALSE;
          win->button3Pressed = FALSE;
          return FALSE;
	}
	else if (xevent->xany.type == MotionNotify)
	  {
	    eventType = wxEVENT_TYPE_MOTION;
	  }
	else if (xevent->xany.type == ButtonPress)
	  {
//            cout << "Button press\n";
	    if (xevent->xbutton.button == Button1)
	      {
		eventType = wxEVENT_TYPE_LEFT_DOWN;
		win->button1Pressed = TRUE;
//                cout << "Left button press\n";
	      }
	    else if (xevent->xbutton.button == Button2)
	      {
		eventType = wxEVENT_TYPE_MIDDLE_DOWN;
		win->button2Pressed = TRUE;
	      }
	    else if (xevent->xbutton.button == Button3)
	      {
		eventType = wxEVENT_TYPE_RIGHT_DOWN;
		win->button3Pressed = TRUE;
	      }
	  }
	else if (xevent->xany.type == ButtonRelease)
	  {
//            cout << "Button release\n";
	    if (xevent->xbutton.button == Button1)
	      {
		eventType = wxEVENT_TYPE_LEFT_UP;
		win->button1Pressed = FALSE;
//                cout << "Left button release\n";
	      }
	    else if (xevent->xbutton.button == Button2)
	      {
		eventType = wxEVENT_TYPE_MIDDLE_UP;
		win->button2Pressed = FALSE;
	      }
	    else if (xevent->xbutton.button == Button3)
	      {
		eventType = wxEVENT_TYPE_RIGHT_UP;
		win->button3Pressed = FALSE;
	      }
            else return FALSE;
	  }
          else return FALSE;

	wxevent.eventHandle = (char *)xevent;
        wxevent.eventType = eventType;

        wxevent.x = xevent->xbutton.x;
	wxevent.y = xevent->xbutton.y;

	wxevent.leftDown = win->button1Pressed;
	wxevent.middleDown = win->button2Pressed;
	wxevent.rightDown = win->button3Pressed;

	wxevent.shiftDown = xevent->xbutton.state & ShiftMask;
	wxevent.controlDown = xevent->xbutton.state & ControlMask;
        return TRUE;
    }
  }
  return FALSE;
}
#endif
