    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.HGL.Key
    -- Copyright   :  (c) Alastair Reid, 1999-2003
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  libraries@haskell.org
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- Abstract representation of keys.
    --
    -----------------------------------------------------------------------------

    module Graphics.HGL.Key
    	( Key			-- Abstract!
    	, keyToChar		-- :: Key -> Char
    	, isCharKey		-- :: Key -> Bool
    	, isBackSpaceKey	-- :: Key -> Bool
    	, isTabKey		-- :: Key -> Bool
    	-- , isLineFeedKey		-- :: Key -> Bool
    	, isClearKey		-- :: Key -> Bool
    	, isReturnKey		-- :: Key -> Bool
    	, isEscapeKey		-- :: Key -> Bool
    	, isDeleteKey		-- :: Key -> Bool
    	-- , isMultiKeyKey		-- :: Key -> Bool
    	, isHomeKey		-- :: Key -> Bool
    	, isLeftKey		-- :: Key -> Bool
    	, isUpKey		-- :: Key -> Bool
    	, isRightKey		-- :: Key -> Bool
    	, isDownKey		-- :: Key -> Bool
    	, isPriorKey		-- :: Key -> Bool
    	, isPageUpKey		-- :: Key -> Bool
    	, isNextKey		-- :: Key -> Bool
    	, isPageDownKey		-- :: Key -> Bool
    	, isEndKey		-- :: Key -> Bool
    	-- , isBeginKey		-- :: Key -> Bool
    	, isShiftLKey		-- :: Key -> Bool
    	, isShiftRKey		-- :: Key -> Bool
    	, isControlLKey		-- :: Key -> Bool
    	, isControlRKey		-- :: Key -> Bool
    	-- , isCapsLockKey		-- :: Key -> Bool
    	-- , isShiftLockKey		-- :: Key -> Bool
    	-- , isMetaLKey		-- :: Key -> Bool
    	-- , isMetaRKey		-- :: Key -> Bool
    	-- , isAltLKey		-- :: Key -> Bool
    	-- , isAltRKey		-- :: Key -> Bool
    	) where

    import Data.Maybe (isJust)

    #if !X_DISPLAY_MISSING
    import Graphics.HGL.X11.Types(Key(MkKey))
    import Graphics.X11.Xlib
    #else
    import Graphics.HGL.Win32.Types(Key(MkKey))
    import Graphics.Win32
    #endif

    ----------------------------------------------------------------
    -- Interface
    ----------------------------------------------------------------

    -- | Converts a character key to a character.
    keyToChar          :: Key -> Char
    isCharKey          :: Key -> Bool -- Is it a "real" character?
    isBackSpaceKey     :: Key -> Bool
    isTabKey           :: Key -> Bool
    --isLineFeedKey      :: Key -> Bool
    isClearKey         :: Key -> Bool
    isReturnKey        :: Key -> Bool
    isEscapeKey        :: Key -> Bool
    isDeleteKey        :: Key -> Bool
    --isMultiKeyKey      :: Key -> Bool -- Multi-key character compose.
    isHomeKey          :: Key -> Bool -- Cursor home.
    isLeftKey          :: Key -> Bool -- Cursor left, left arrow.
    isUpKey            :: Key -> Bool -- Cursor up, up arrow.
    isRightKey         :: Key -> Bool -- Cursor right, right arrow.
    isDownKey          :: Key -> Bool -- Cursor down, down arrow.
    isPriorKey         :: Key -> Bool -- Prior, previous page. Same as page up.
    isPageUpKey        :: Key -> Bool -- Page up, previous page. Same as prior.
    isNextKey          :: Key -> Bool -- Next, next page. Same as page down.
    isPageDownKey      :: Key -> Bool -- Page down, next page. Same as next.
    isEndKey           :: Key -> Bool -- End of line.
    --isBeginKey         :: Key -> Bool -- Beginning of line.
    isShiftLKey        :: Key -> Bool -- Left shift.
    isShiftRKey        :: Key -> Bool -- Right shift.
    isControlLKey      :: Key -> Bool -- Left control.
    isControlRKey      :: Key -> Bool -- Right control.
    --isCapsLockKey      :: Key -> Bool -- Caps lock.
    --isShiftLockKey     :: Key -> Bool -- Shift lock.
    --isMetaLKey         :: Key -> Bool -- Left meta.
    --isMetaRKey         :: Key -> Bool -- Right meta.
    --isAltLKey          :: Key -> Bool -- Left alt.
    --isAltRKey          :: Key -> Bool -- Right alt.

    ----------------------------------------------------------------
    -- Implementation
    ----------------------------------------------------------------

    keyToChar (MkKey ks) =
        case (keySymToChar ks) of
            Just c  -> c
    	Nothing -> error "keyToChar: Not a character key!"

    isCharKey      (MkKey ks) = isJust (keySymToChar ks)

    #if !X_DISPLAY_MISSING

    -- Converts an X KeySym representing an ISO 8859-1 (Latin 1) character or one
    -- of a few control characters to a Char.
    -- Note! It is assumed that the KeySym encoding for Latin 1 characters agrees
    -- with the Haskell character encoding!
    keySymToChar :: KeySym -> Maybe Char
    keySymToChar ks
        | xK_space <= ks && ks <= xK_ydiaeresis = Just (toEnum (fromIntegral ks))
        | ks == xK_BackSpace                    = Just '\BS'
        | ks == xK_Tab                          = Just '\HT'
        | ks == xK_Linefeed                     = Just '\LF'
        | ks == xK_Clear                        = Just '\FF'
        | ks == xK_Return                       = Just '\CR'
        | ks == xK_Escape                       = Just '\ESC'
        | ks == xK_Delete                       = Just '\DEL'
        | otherwise                             = Nothing

    isBackSpaceKey (MkKey ks) = ks == xK_BackSpace
    isTabKey       (MkKey ks) = ks == xK_Tab
    --isLineFeedKey  (MkKey ks) = ks == xK_Linefeed
    isClearKey     (MkKey ks) = ks == xK_Clear
    isReturnKey    (MkKey ks) = ks == xK_Return
    isEscapeKey    (MkKey ks) = ks == xK_Escape
    isDeleteKey    (MkKey ks) = ks == xK_Delete
    --isMultiKeyKey  (MkKey ks) = ks == xK_Multi_key
    isHomeKey      (MkKey ks) = ks == xK_Home
    isLeftKey      (MkKey ks) = ks == xK_Left
    isUpKey        (MkKey ks) = ks == xK_Up
    isRightKey     (MkKey ks) = ks == xK_Right
    isDownKey      (MkKey ks) = ks == xK_Down
    isPriorKey     (MkKey ks) = ks == xK_Prior
    isPageUpKey    (MkKey ks) = ks == xK_Page_Up
    isNextKey      (MkKey ks) = ks == xK_Next
    isPageDownKey  (MkKey ks) = ks == xK_Page_Down
    isEndKey       (MkKey ks) = ks == xK_End
    --isBeginKey     (MkKey ks) = ks == xK_Begin
    isShiftLKey    (MkKey ks) = ks == xK_Shift_L
    isShiftRKey    (MkKey ks) = ks == xK_Shift_R
    isControlLKey  (MkKey ks) = ks == xK_Control_L
    isControlRKey  (MkKey ks) = ks == xK_Control_R
    --isCapsLockKey  (MkKey ks) = ks == xK_Caps_Lock
    --isShiftLockKey (MkKey ks) = ks == xK_Shift_Lock
    --isMetaLKey     (MkKey ks) = ks == xK_Meta_L
    --isMetaRKey     (MkKey ks) = ks == xK_Meta_R
    --isAltLKey      (MkKey ks) = ks == xK_Alt_L
    --isAltRKey      (MkKey ks) = ks == xK_Alt_R

    #else /* X_DISPLAY_MISSING */

    -- Converts a VKey representing an ISO 8859-1 (Latin 1) character or one
    -- of a few control characters to a Char.
    -- Note! It is assumed that the VKey encoding for Latin 1 characters agrees
    -- with the Haskell character encoding!
    keySymToChar :: VKey -> Maybe Char
    keySymToChar ks
        | space <= ks && ks <= ydiaresis = Just (toEnum (fromIntegral ks))
        | ks == vK_BACK                  = Just '\BS'
        | ks == vK_TAB                   = Just '\HT'
    --    | ks == vK_LINEFEED              = Just '\LF'
        | ks == vK_CLEAR                 = Just '\FF'
        | ks == vK_RETURN                = Just '\CR'
        | ks == vK_ESCAPE                = Just '\ESC'
        | ks == vK_DELETE                = Just '\DEL'
        | otherwise                      = Nothing
     where
      space, ydiaresis :: VKey
      space     = fromIntegral (fromEnum ' ')
      ydiaresis = fromIntegral 255        -- is this right?

    isBackSpaceKey (MkKey ks) = ks == vK_BACK
    isTabKey       (MkKey ks) = ks == vK_TAB
    --isLineFeedKey  (MkKey ks) = ks == vK_LINEFEED
    isClearKey     (MkKey ks) = ks == vK_CLEAR
    isReturnKey    (MkKey ks) = ks == vK_RETURN
    isEscapeKey    (MkKey ks) = ks == vK_ESCAPE
    isDeleteKey    (MkKey ks) = ks == vK_DELETE
    --isMultiKeyKey  (MkKey ks) = ks == vK_MULTI_KEY
    isHomeKey      (MkKey ks) = ks == vK_HOME
    isLeftKey      (MkKey ks) = ks == vK_LEFT
    isUpKey        (MkKey ks) = ks == vK_UP
    isRightKey     (MkKey ks) = ks == vK_RIGHT
    isDownKey      (MkKey ks) = ks == vK_DOWN
    isPriorKey     (MkKey ks) = ks == vK_PRIOR
    isPageUpKey    (MkKey ks) = ks == vK_PRIOR  -- same as isPriorKey
    isNextKey      (MkKey ks) = ks == vK_NEXT
    isPageDownKey  (MkKey ks) = ks == vK_NEXT   -- same as isNextKey
    isEndKey       (MkKey ks) = ks == vK_END
    --isBeginKey     (MkKey ks) = ks == vK_Begin
    isShiftLKey    (MkKey ks) = ks == vK_SHIFT  -- can't distinguish left and right
    isShiftRKey    (MkKey ks) = ks == vK_SHIFT
    isControlLKey  (MkKey ks) = ks == vK_CONTROL -- ambidextrous
    isControlRKey  (MkKey ks) = ks == vK_CONTROL
    --isCapsLockKey  (MkKey ks) = ks == vK_Caps_Lock
    --isShiftLockKey (MkKey ks) = ks == vK_Shift_Lock
    --isMetaLKey     (MkKey ks) = ks == vK_Meta_L
    --isMetaRKey     (MkKey ks) = ks == vK_Meta_R
    --isAltLKey      (MkKey ks) = ks == vK_Alt_L
    --isAltRKey      (MkKey ks) = ks == vK_Alt_R

    #endif /* X_DISPLAY_MISSING */

    ----------------------------------------------------------------
    -- End
    ----------------------------------------------------------------