// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

// This is an implementation of a virtual keyboard using the same scheme
// as Valve's Big Picture (apparently). This implementation uses only QF's
// IMT key binding system and joystick axis controls (to get buttons from
// analog inputs) and the standard id parser.
//
// At this stage, there is no support for backspace or enter. However, that
// requires only some modifications to in_type to support things like \h and
// \n.
//
// This probably could be done more elegantly using gib, and certainly using
// Ruamoko with just enough config to get the button presses into the VM.

// The dpad on my gamepad (Elecom jc-u2312fsv) is only pseudo-digital, at
// least from Linux's point of view: -32767, 0, 32767. Axis 4 is horizontal
// and axis 5 is vertical. This setup makes it so j_axis1 = up/north,
// j_axis2 = right/east, j_axis3 = down/south, j_axis4 = left/west
in_joy 4 amp 1 pre_amp 1 deadzone 0 offset 0 type button 0
in_joy 4 button add J_AXIS2 16384
in_joy 4 button add J_AXIS4 -16384
in_joy 5 amp 1 pre_amp 1 deadzone 0 offset 0 type button 0
in_joy 5 button add J_AXIS1 -16384
in_joy 5 button add J_AXIS3 16384

// create the imts
// the vkb imts form a compass rose around imt_vkb. imt_vkb0 is intended to be
// at north, imt_vkb2 at east, imt_vkb4 at south, imt_vkb6 at west, and the odd
// numbered vkb imts in between the even (eg, imt_vkb1 at NE, imt_vkb7 at NW).
imt_create key_console imt_vkb imt_console
imt_create key_console imt_vkb0 imt_vkb
imt_create key_console imt_vkb1 imt_vkb
imt_create key_console imt_vkb2 imt_vkb
imt_create key_console imt_vkb3 imt_vkb
imt_create key_console imt_vkb4 imt_vkb
imt_create key_console imt_vkb5 imt_vkb
imt_create key_console imt_vkb6 imt_vkb
imt_create key_console imt_vkb7 imt_vkb
// in case the imts already existed. clearing the tables isn't strictly
// necessary, but it means that we're always starting from a clean slate
imt_clear imt_vkb imt_vkb0 imt_vkb1 imt_vkb2 imt_vkb3 imt_vkb4 imt_vkb5 imt_vkb6 imt_vkb7
// because key_console already has (or should have) imt_console, creating
// imt_vkb won't automatically switch to it.
imt_keydest key_console imt_vkb

// Due to the way the event system works, it's not possible to jump straight
// from imt_vkb to any of the odd numbered vkb imts
in_bind imt_vkb j_axis1 "+goto_vkb0"
in_bind imt_vkb j_axis2 "+goto_vkb2"
in_bind imt_vkb j_axis3 "+goto_vkb4"
in_bind imt_vkb j_axis4 "+goto_vkb6"

// when j_axis1 is pressed, we are in vkb0 (N) and thus pressing j_axis2
// while holding j_axis1 gives NE thus vkb1 and j_axis4 gives NW thus vkb7
in_bind imt_vkb0 j_axis2 "+goto_vkb1"
in_bind imt_vkb0 j_axis4 "+goto_vkb7"

// from vkb2 (E) vkb1 (NE) and vkb3 (SE) can be reached
in_bind imt_vkb2 j_axis1 "+goto_vkb1"
in_bind imt_vkb2 j_axis3 "+goto_vkb3"

// from vkb4 (S) vkb3 (SE) and vkb5 (SW) can be reached
in_bind imt_vkb4 j_axis2 "+goto_vkb3"
in_bind imt_vkb4 j_axis4 "+goto_vkb5"

// from vkb6 (W) vkb5 (SW) and vkb7 (NW) can be reached
in_bind imt_vkb6 j_axis1 "+goto_vkb7"
in_bind imt_vkb6 j_axis3 "+goto_vkb5"

// Releasing j_axis1 while in vkb1 makes only j_axis2 active thus we return
// to vkb2. Releasing j_axis2 means only j_axis1 is active thus back to vkb0.
// The encoding in the name for goto_vkb1_2 means "we're in vkb1 but will
// return to vkb2"
in_bind imt_vkb1 j_axis1 "+goto_vkb1_2"
in_bind imt_vkb1 j_axis2 "+goto_vkb1_0"

// from vkb3, can return to either vkb4 or vkb2
in_bind imt_vkb3 j_axis2 "+goto_vkb3_4"
in_bind imt_vkb3 j_axis3 "+goto_vkb3_2"

// from vkb5, can return to either vkb6 or vkb4
in_bind imt_vkb5 j_axis4 "+goto_vkb5_4"
in_bind imt_vkb5 j_axis3 "+goto_vkb5_6"

// from vkb7, can return to either vkb0 or vkb6
in_bind imt_vkb7 j_axis4 "+goto_vkb7_0"
in_bind imt_vkb7 j_axis1 "+goto_vkb7_6"

// the buttons on my gamepad are arranged:
//    2         b
//  1   4  -> a   c
//    3         d
in_bind imt_vkb0 j_button1 in_type a
in_bind imt_vkb0 j_button2 in_type b
in_bind imt_vkb0 j_button4 in_type c
in_bind imt_vkb0 j_button3 in_type d

//    f
//  e   g
//    h
in_bind imt_vkb1 j_button1 in_type e
in_bind imt_vkb1 j_button2 in_type f
in_bind imt_vkb1 j_button4 in_type g
in_bind imt_vkb1 j_button3 in_type h

//    j
//  i   k
//    l
in_bind imt_vkb2 j_button1 in_type i
in_bind imt_vkb2 j_button2 in_type j
in_bind imt_vkb2 j_button4 in_type k
in_bind imt_vkb2 j_button3 in_type l

//    n
//  m   o
//    p
in_bind imt_vkb3 j_button1 in_type m
in_bind imt_vkb3 j_button2 in_type n
in_bind imt_vkb3 j_button4 in_type o
in_bind imt_vkb3 j_button3 in_type p

//    r
//  q   s
//    t
in_bind imt_vkb4 j_button1 in_type q
in_bind imt_vkb4 j_button2 in_type r
in_bind imt_vkb4 j_button4 in_type s
in_bind imt_vkb4 j_button3 in_type t

//    v
//  u   w
//    x
in_bind imt_vkb5 j_button1 in_type u
in_bind imt_vkb5 j_button2 in_type v
in_bind imt_vkb5 j_button4 in_type w
in_bind imt_vkb5 j_button3 in_type x

//    z
//  y   ,
//    .
in_bind imt_vkb6 j_button1 in_type y
in_bind imt_vkb6 j_button2 in_type z
in_bind imt_vkb6 j_button4 in_type ,
in_bind imt_vkb6 j_button3 in_type .

//    /
//  :   @
//    _
in_bind imt_vkb7 j_button1 in_type :
in_bind imt_vkb7 j_button2 in_type /
in_bind imt_vkb7 j_button4 in_type @
in_bind imt_vkb7 j_button3 in_type _

// some aliases to clear up the code (and, for now, display which vkb has
// been entered)
alias enter_vkb "imt_keydest key_console imt_vkb; echo vkb"
alias enter_vkb0 "imt_keydest key_console imt_vkb0; echo vkb0"
alias enter_vkb1 "imt_keydest key_console imt_vkb1; echo vkb1"
alias enter_vkb2 "imt_keydest key_console imt_vkb2; echo vkb2"
alias enter_vkb3 "imt_keydest key_console imt_vkb3; echo vkb3"
alias enter_vkb4 "imt_keydest key_console imt_vkb4; echo vkb4"
alias enter_vkb5 "imt_keydest key_console imt_vkb5; echo vkb5"
alias enter_vkb6 "imt_keydest key_console imt_vkb6; echo vkb6"
alias enter_vkb7 "imt_keydest key_console imt_vkb7; echo vkb7"

// The real implementation of the compass rose. the + version of
// goto_vkbN_R is not expected to execute (as repeat is not yet supported),
// but just in case, make them an effective no-op. Probably don't really need
// to define them as everthing seems to work without devinitions for
// -goto_vkbN for odd N.
alias +goto_vkb0 enter_vkb0
alias +goto_vkb1 enter_vkb1
alias +goto_vkb1_0 enter_vkb1
alias +goto_vkb1_2 enter_vkb1
alias +goto_vkb2 enter_vkb2
alias +goto_vkb3 enter_vkb3
alias +goto_vkb3_2 enter_vkb3
alias +goto_vkb3_4 enter_vkb3
alias +goto_vkb4 enter_vkb4
alias +goto_vkb5 enter_vkb5
alias +goto_vkb5_4 enter_vkb5
alias +goto_vkb5_6 enter_vkb5
alias +goto_vkb6 enter_vkb6
alias +goto_vkb7 enter_vkb7
alias +goto_vkb7_4 enter_vkb7
alias +goto_vkb7_6 enter_vkb7

alias -goto_vkb0 enter_vkb
alias -goto_vkb1_0 enter_vkb0
alias -goto_vkb1_2 enter_vkb2
alias -goto_vkb2 enter_vkb
alias -goto_vkb3_2 enter_vkb2
alias -goto_vkb3_4 enter_vkb4
alias -goto_vkb4 enter_vkb
alias -goto_vkb5_4 enter_vkb4
alias -goto_vkb5_6 enter_vkb6
alias -goto_vkb6 enter_vkb
alias -goto_vkb7_0 enter_vkb0
alias -goto_vkb7_6 enter_vkb6
