/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

#include "nsKeyCode.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>

#include "nsGUIEvent.h" // For NS_VK

struct nsKeyConverter 
{
  int          vkCode; // Platform independent key code
  unsigned int keysym; // XK keysym key code
};

struct nsKeyConverter nsKeycodes[] =
{
  { NS_VK_CANCEL,        XK_Cancel},
  { NS_VK_BACK,          XK_BackSpace},
  { NS_VK_TAB,           XK_Tab},
#ifdef XK_ISO_Left_Tab
  { NS_VK_TAB,           XK_ISO_Left_Tab }, // SunOS 5.5.1 doesn't have it.
#endif
  { NS_VK_CLEAR,         XK_Clear},
  { NS_VK_RETURN,        XK_Return},
  { NS_VK_ENTER,         XK_KP_Enter},
  { NS_VK_SHIFT,         XK_Shift_L},
  { NS_VK_SHIFT,         XK_Shift_R},
  { NS_VK_CONTROL,       XK_Control_L},
  { NS_VK_CONTROL,       XK_Control_R},
  { NS_VK_ALT,           XK_Alt_L},
  { NS_VK_ALT,           XK_Alt_R},
  { NS_VK_PAUSE,         XK_Pause},
  { NS_VK_CAPS_LOCK,     XK_Caps_Lock},
  { NS_VK_ESCAPE,        XK_Escape},
  { NS_VK_SPACE,         XK_KP_Space},
  { NS_VK_PAGE_UP,       XK_KP_Page_Up},
  { NS_VK_PAGE_DOWN,     XK_KP_Page_Down},
  { NS_VK_END,           XK_KP_End},
  { NS_VK_HOME,          XK_Home},
  { NS_VK_LEFT,          XK_Left},
  { NS_VK_UP,            XK_Up},
  { NS_VK_RIGHT,         XK_Right},
  { NS_VK_DOWN,          XK_Down},
  { NS_VK_PRINTSCREEN,   XK_Print},
  { NS_VK_INSERT,        XK_Insert},
  { NS_VK_DELETE,        XK_Delete},
  { NS_VK_0,             XK_0},
  { NS_VK_1,             XK_1},
  { NS_VK_2,             XK_2},
  { NS_VK_3,             XK_3},
  { NS_VK_4,             XK_4},
  { NS_VK_5,             XK_5},
  { NS_VK_6,             XK_6},
  { NS_VK_7,             XK_7},
  { NS_VK_8,             XK_8},
  { NS_VK_9,             XK_9},
  { NS_VK_SEMICOLON,     XK_semicolon},
  { NS_VK_EQUALS,        XK_equal},
  { NS_VK_NUMPAD0,       XK_KP_0},
  { NS_VK_NUMPAD1,       XK_KP_1},
  { NS_VK_NUMPAD2,       XK_KP_2},
  { NS_VK_NUMPAD3,       XK_KP_3},
  { NS_VK_NUMPAD4,       XK_KP_4},
  { NS_VK_NUMPAD5,       XK_KP_5},
  { NS_VK_NUMPAD6,       XK_KP_6},
  { NS_VK_NUMPAD7,       XK_KP_7},
  { NS_VK_NUMPAD8,       XK_KP_8},
  { NS_VK_NUMPAD9,       XK_KP_9},
  { NS_VK_MULTIPLY,      XK_KP_Multiply},
  { NS_VK_ADD,           XK_KP_Add},
  { NS_VK_SEPARATOR,     XK_KP_Separator},
  { NS_VK_SUBTRACT,      XK_KP_Subtract},
  { NS_VK_DECIMAL,       XK_KP_Decimal},
  { NS_VK_DIVIDE,        XK_KP_Divide},
  { NS_VK_F1,            XK_F1},
  { NS_VK_F2,            XK_F2},
  { NS_VK_F3,            XK_F3},
  { NS_VK_F4,            XK_F4},
  { NS_VK_F5,            XK_F5},
  { NS_VK_F6,            XK_F6},
  { NS_VK_F7,            XK_F7},
  { NS_VK_F8,            XK_F8},
  { NS_VK_F9,            XK_F9},
  { NS_VK_F10,           XK_F10},
  { NS_VK_F11,           XK_F11},
  { NS_VK_F12,           XK_F12},
  { NS_VK_F13,           XK_F13},
  { NS_VK_F14,           XK_F14},
  { NS_VK_F15,           XK_F15},
  { NS_VK_F16,           XK_F16},
  { NS_VK_F17,           XK_F17},
  { NS_VK_F18,           XK_F18},
  { NS_VK_F19,           XK_F19},
  { NS_VK_F20,           XK_F20},
  { NS_VK_F21,           XK_F21},
  { NS_VK_F22,           XK_F22},
  { NS_VK_F23,           XK_F23},
  { NS_VK_F24,           XK_F24},
  { NS_VK_NUM_LOCK,      XK_Num_Lock},
  { NS_VK_SCROLL_LOCK,   XK_Scroll_Lock},
  { NS_VK_COMMA,         XK_comma},
  { NS_VK_PERIOD,        XK_period},
  { NS_VK_SLASH,         XK_slash},
  { NS_VK_BACK_QUOTE,    XK_grave},
  { NS_VK_OPEN_BRACKET,  XK_bracketleft},
  { NS_VK_BACK_SLASH,    XK_backslash},
  { NS_VK_CLOSE_BRACKET, XK_bracketright},
  { NS_VK_QUOTE,         XK_apostrophe}
};

PRInt32
nsKeyCode::ConvertKeySymToVirtualKey(KeySym keysym)
{
  unsigned int i;
  unsigned int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);

  if (keysym >= XK_a && keysym <= XK_z)
    return keysym - XK_a + NS_VK_A;
  if (keysym >= XK_A && keysym <= XK_Z)
    return keysym - XK_A + NS_VK_A;

  for (i = 0; i < length; i++) 
  {
    if (nsKeycodes[i].keysym == keysym)
    {
      return(nsKeycodes[i].vkCode);
    }
  }
  
  return((int)0);
}

//////////////////////////////////////////////////////////////////////////
/* static */ PRBool
nsKeyCode::KeyCodeIsModifier(KeyCode aKeyCode)
{
  if (aKeyCode == XK_Shift_L ||
	  aKeyCode == XK_Shift_R ||
	  aKeyCode == XK_Control_L ||
	  aKeyCode == XK_Control_R ||
	  aKeyCode == XK_Caps_Lock ||
	  aKeyCode == XK_Shift_Lock ||
	  aKeyCode == XK_Meta_L ||
	  aKeyCode == XK_Meta_R ||
	  aKeyCode == XK_Alt_L ||
	  aKeyCode == XK_Alt_R)
  {
	return PR_TRUE;
  }

  return PR_FALSE;
}
//////////////////////////////////////////////////////////////////////////
/* static */ KeySym
nsKeyCode::ConvertKeyCodeToKeySym(Display * aDisplay,
								  KeyCode   aKeyCode)
{
  KeySym keysym = 0;

  keysym = XKeycodeToKeysym(aDisplay, aKeyCode, 0);

  return keysym;
}
//////////////////////////////////////////////////////////////////////////
