module "/pliant/language/context.pli"
module "/pliant/language/unsafe.pli"
module "/pliant/SDL/SDL_keyboard.pli"

constant sdl_library "libSDL.so"


public
 gvar Int SDL_NOEVENT         := 0  # Unused (do not remove) 
 gvar Int SDL_ACTIVEEVENT     := 1  # Application loses/gains visibility 
 gvar Int SDL_KEYDOWN         := 2  # Keys pressed 
 gvar Int SDL_KEYUP           := 3  # Keys released 
 gvar Int SDL_MOUSEMOTION     := 4  # Mouse moved 
 gvar Int SDL_MOUSEBUTTONDOWN := 5  # Mouse button pressed 
 gvar Int SDL_MOUSEBUTTONUP   := 6  # Mouse button released 
 gvar Int SDL_JOYAXISMOTION   := 7  # Joystick axis motion 
 gvar Int SDL_JOYBALLMOTION   := 8  # Joystick trackball motion 
 gvar Int SDL_JOYHATMOTION    := 9  # Joystick hat position change 
 gvar Int SDL_JOYBUTTONDOWN   := 10 # Joystick button pressed 
 gvar Int SDL_JOYBUTTONUP     := 11 # Joystick button released 
 gvar Int SDL_QUIT            := 12 # User-requested quit 
 gvar Int SDL_SYSWMEVENT      := 13 # System specific event 
 gvar Int SDL_EVENT_RESERVEDA := 14 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVEDB := 15 # Reserved for future use.. 
 gvar Int SDL_VIDEORESIZE     := 16 # User resized video mode 
 gvar Int SDL_VIDEOEXPOSE     := 17 # Screen needs to be redrawn 
 gvar Int SDL_EVENT_RESERVED2 := 18 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVED3 := 19 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVED4 := 20 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVED5 := 21 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVED6 := 22 # Reserved for future use.. 
 gvar Int SDL_EVENT_RESERVED7 := 23 # Reserved for future use.. 

 # Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use 
 gvar Int SDL_USEREVENT       := 24
 gvar Int NUM_EVENTS          := 32


 # Predefined event masks 

 function SDL_EVENTMASK X -> S
  arg Int X S
  S :=  2^X

 gvar Int SDL_ACTIVEEVENTMASK := SDL_EVENTMASK:SDL_ACTIVEEVENT
 gvar Int SDL_KEYDOWNMASK     := SDL_EVENTMASK:SDL_KEYDOWN
 gvar Int SDL_KEYUPMASK       := SDL_EVENTMASK:SDL_KEYUP
 gvar Int SDL_MOUSEMOTIONMASK := SDL_EVENTMASK:SDL_MOUSEMOTION
 gvar Int SDL_MOUSEBUTTONDOWNMASK := SDL_EVENTMASK:SDL_MOUSEBUTTONDOWN
 gvar Int SDL_MOUSEBUTTONUPMASK := SDL_EVENTMASK:SDL_MOUSEBUTTONUP
 gvar Int SDL_MOUSEEVENTMASK := SDL_MOUSEMOTIONMASK .or. SDL_MOUSEBUTTONDOWNMASK .or. SDL_MOUSEBUTTONUPMASK
 gvar Int SDL_JOYAXISMOTIONMASK := SDL_EVENTMASK:SDL_JOYAXISMOTION
 gvar Int SDL_JOYBALLMOTIONMASK := SDL_EVENTMASK:SDL_JOYBALLMOTION
 gvar Int SDL_JOYHATMOTIONMASK  := SDL_EVENTMASK:SDL_JOYHATMOTION
 gvar Int SDL_JOYBUTTONDOWNMASK := SDL_EVENTMASK:SDL_JOYBUTTONDOWN
 gvar Int SDL_JOYBUTTONUPMASK := SDL_EVENTMASK:SDL_JOYBUTTONUP
 gvar Int SDL_JOYEVENTMASK := SDL_JOYAXISMOTIONMASK .or. SDL_JOYBALLMOTIONMASK .or. SDL_JOYHATMOTIONMASK .or. SDL_JOYBUTTONDOWNMASK .or. SDL_JOYBUTTONUPMASK
 gvar Int VIDEORESIZEMASK := SDL_EVENTMASK:SDL_VIDEORESIZE
 gvar Int VIDEOEXPOSEMASK := SDL_EVENTMASK:SDL_VIDEOEXPOSE
 gvar Int SDL_QUITMASK := SDL_EVENTMASK:SDL_QUIT
 gvar Int SDL_SYSWMEVENTMASK := SDL_EVENTMASK:SDL_SYSWMEVENT
 gvar Int SDL_ALLEVENTS := 0FFFFFFFFh

 type SDL_ActiveEvent
  packed
  field uInt8 type    # SDL_ACTIVEEVENT
  field uInt8 gain    # Whether given states were gained or lost (1/0) 
  field uInt8 state   # A mask of the focus states
  field Byte padding0

 type SDL_KeyboardEvent
  packed
  field uInt8 type
  field uInt8 which
  field uInt8 state
  field Byte padding0
  field SDL_keysym keysym

 # Mouse motion event structure 
 type SDL_MouseMotionEvent
  packed
  field uInt8 type  #SDL_MOUSEMOTION
  field uInt8 which #The mouse device index
  field uInt8 state #The current button state 
  field Byte padding0
  field uInt16 x y  #The X/Y coordinates of mouse 
  field Int16 xrel  #The relative motion in X direction 
  field Int16 yrel  #The relative motion in Y direction


 # Mouse button event structure
 type SDL_MouseButtonEvent
  packed
  field uInt8 type   #SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP
  field uInt8 which  #The mouse device index
  field uInt8 button #The mouse button index
  field uInt8 state  #SDL_PRESSED or SDL_RELEASED
  field uInt16 x y   #The X/Y coordinates of the mouse at press time

 # Joystick axis motion event structure 
 type SDL_JoyAxisEvent
  packed
  field uInt8 type  #SDL_JOYAXISMOTION
  field uInt8 which #Joystick device index
  field uInt8 axis  #Joystick axis index
  field Int16 value #Axis value (-32768 to 32767)

 # Joystick trackball motion event structure 
 type SDL_JoyBallEvent
  packed
  field uInt8 type  #SDL_JOYBALLMOTION
  field uInt8 which #Joystick device index
  field uInt8 ball  #Jostick trackball index
  field Int16 xrel  #Relative motion in X direction
  field Int16 yrel  #Relative motion in Y direction

 # Joystick hat position change event structure
 type SDL_JoyHatEvent
  packed
  field uInt8 type  #SDL_JOYHATMOTION
  field uInt8 which #Joystick device index
  field uInt8 hat   #Joystick hat index
  field uInt8 value #The position value:
  #Hat postion values:
  #       8 1 2
  #       7 0 3
  #       6 5 4
  #Note that zero means the POV is centered.

 # Joystick button event structure
 type SDL_JoyButtonEvent
  packed
  field uInt8 type   #SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP
  field uInt8 which  #Joystick device index
  field uInt8 button #Joystick button index 
  field uInt8 state  #SDL_PRESSED or SDL_RELEASED

 # The "window resized" event
 # When you get this event, you are responsible for setting a new video
 # mode with the new width and height.

 type SDL_ResizeEvent
  packed
  field uInt8 type #SDL_VIDEORESIZE
  field Int w      #New width
  field Int h      #New height

 # The "screen redraw" event 
 type SDL_ExposeEvent
  field uInt8 type #SDL_VIDEOEXPOSE 

 # The "quit requested" event 
 type SDL_QuitEvent
  field uInt8 type #SDL_QUIT 

 type SDL_UserEvent
  field uInt8 type    #SDL_USEREVENT through SDL_NUMEVENTS-1
  field Int code      #User defined event code
  field Address data1 #User defined data pointer
  field Address data2 #User defined data pointer

 type SDL_Event
  packed
  field uInt8 type
  field (Array Byte 19) event_data

 #These methods cast the generic event structure to a specific event
 method event active -> active_event
  arg SDL_Event event
  arg SDL_ActiveEvent active_event
  active_event := addressof:event map SDL_ActiveEvent

 method event key -> key_event
  arg SDL_Event event
  arg SDL_KeyboardEvent key_event
  key_event := addressof:event map SDL_KeyboardEvent

 method event motion -> motion_event
  arg SDL_Event event
  arg SDL_MouseMotionEvent motion_event
  motion_event := addressof:event map SDL_MouseMotionEvent

 method event button -> button_event
  arg SDL_Event event
  arg SDL_MouseButtonEvent button_event
  button_event := addressof:event map SDL_MouseButtonEvent

 method event jaxis -> jaxis_event
  arg SDL_Event event
  arg SDL_JoyAxisEvent jaxis_event
  jaxis_event := addressof:event map SDL_JoyAxisEvent

 method event jball -> jball_event
  arg SDL_Event event
  arg SDL_JoyBallEvent jball_event
  jball_event := addressof:event map SDL_JoyBallEvent

 method event jhat -> jhat_event
  arg SDL_Event event
  arg SDL_JoyHatEvent jhat_event
  jhat_event := addressof:event map SDL_JoyHatEvent

 method event jbutton -> jbutton_event
  arg SDL_Event event
  arg SDL_JoyButtonEvent jbutton_event
  jbutton_event := addressof:event map SDL_JoyButtonEvent

 method event resize -> resize_event
  arg SDL_Event event
  arg SDL_ResizeEvent resize_event
  resize_event := addressof:event map SDL_ResizeEvent

 method event expose -> expose_event
  arg SDL_Event event
  arg SDL_ExposeEvent expose_event
  expose_event := addressof:event map SDL_ExposeEvent

 method event quit -> quit_event
  arg SDL_Event event
  arg SDL_QuitEvent quit_event
  quit_event := addressof:event map SDL_QuitEvent

 method event UserEvent -> user_event
  arg SDL_Event event
  arg SDL_UserEvent user_event
  user_event := addressof:event map SDL_UserEvent


 # Function prototypes 
 # Pumps the event loop, gathering events from the input devices.
 # This function updates the event queue and internal input device state.
 # This should only be run in the thread that sets the video mode.

 function SDL_PumpEvents
  external sdl_library "SDL_PumpEvents"

 # Checks the event queue for messages and optionally returns them.
 # If 'action' is SDL_ADDEVENT, up to 'numevents' events will be added to
 # the back of the event queue.
 # If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front
 # of the event queue, matching 'mask', will be returned and will not
 # be removed from the queue.
 # If 'action' is SDL_GETEVENT, up to 'numevents' events at the front 
 # of the event queue, matching 'mask', will be returned and will be
 # removed from the queue.
 # This function returns the number of events actually stored, or -1
 # if there was an error.  This function is thread-safe.

 gvar Int SDL_ADDEVENT := 0
 gvar Int SDL_ADDEvent := 1
 gvar Int SDL_ADDEvent := 2

 function SDL_PeepEvents events numevents action mask -> z
  arg Address events #(Array of type SDL_Event *)
  arg Int numevents action z
  arg uInt mask
  external sdl_library "SDL_PeepEvents"

 # Polls for currently pending events, and returns 1 if there are any pending
 # events, or 0 if there are none available.  If 'event' is not NULL, the next
 # event is removed from the queue and stored in that area.

 function SDL_PollEvent event -> z
  arg SDL_Event event; arg Int z
  external sdl_library "SDL_PollEvent"

 # Waits indefinitely for the next available event, returning 1, or 0 if there
 # was an error while waiting for events.  If 'event' is not NULL, the next
 # event is removed from the queue and stored in that area.

 function SDL_WaitEvent event -> z
  arg SDL_Event event; arg Int z
  external sdl_library "SDL_WaitEvent"


 # Add an event to the event queue.
 # This function returns 0 if the event queue was full, or -1
 # if there was some other error.  Returns 1 on success.

 function SDL_PushEvent event -> z
  arg SDL_Event event; arg Int z
  external sdl_library "SDL_PushEvent"