/* libke.c
 *
 * Copyright 2001, 2002 Sun Microsystems, Inc.,
 * Copyright 2001, 2002 BAUM Retec, A.G.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cspi/spi.h>
#include "libke.h"
#include "libsrconf.h"
#include "SRMessages.h"

#define XK_MISCELLANY
#include <X11/keysymdef.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>

#include <X11/XKBlib.h>

#define  USE_ALL_WINDOWS

/* Solaris specific variable types. */
#ifdef __sun
#define u_int8_t   uint8_t
#define u_int16_t  uint16_t
#define u_int32_t  uint32_t
#define u_int64_t  uint64_t
#endif

#define KE_TIME_WAIT 			5000
#define COUNT_OF_ITEM_IN_LAYER_KEYSET 	16
#define COUNT_OF_ITEM_IN_KEYECHO_KEYSET 16

#define MODIFIER(K,C) (K ? C : "")
#define LINE(X)       (X != 0 ? "-" : "")
#define STR(X)	      (X != NULL ? X : "")

#define Z_CHAR_POSITION 26

static AccessibleKeystrokeListener *ke_layer_listener;
static AccessibleKeySet 	   *ke_layer_keyset  = NULL;

static void
ke_print_register_return_value (SPIBoolean retval,
				const gchar *modifiers)
{
    fprintf  (stderr, "\nKey registry(%s): result %s", modifiers, retval ? "succeeded" : "failed");
}

void
ke_config_changed (void)
{
}




/**************************************************************/
static SPIBoolean 
ke_report_layer_key_event (const AccessibleKeystroke *key, gpointer user_data)
{
//    return TRUE;
    fprintf (stderr, "\n(Layer)Received key event:\n\tsym %ld (%c)\n\tmods %x\n\tcode %d\n\ttime %ld\n\tkeystring \"%s\"\n\ttype %d (press = %d, release = %d)",
	      (glong) key->keyID, (gchar)key->keyID,
	      (guint) key->modifiers,
	      (gint) key->keycode, 
	      (long int) key->timestamp,
	      key->keystring,
	      (gint) key->type, (gint)SPI_KEY_PRESSED, (gint)SPI_KEY_RELEASED );   

    return TRUE;
}



static gboolean
ke_layer_register_events (AccessibleKeystrokeListener *ke_layer_listener,
			  AccessibleKeySet 	      *ke_layer_keyset)
{
    gboolean retval = TRUE;
    /*
	Layer key listener. Listen key event from numpad. Listen only if a numlock 
	is active.
    */
    retval = SPI_registerAccessibleKeystrokeListener (ke_layer_listener,
				      (AccessibleKeySet *) ke_layer_keyset,
				      SPI_KEYMASK_NUMLOCK,
				      (gulong) ( SPI_KEY_PRESSED | SPI_KEY_RELEASED ),
#ifdef USE_ALL_WINDOWS
				      SPI_KEYLISTENER_ALL_WINDOWS);
#else
				      SPI_KEYLISTENER_NOSYNC | SPI_KEYLISTENER_CANCONSUME);
#endif

    ke_print_register_return_value (retval, "(NUMLOCK)");
    return retval;
}



static short*
ke_get_keypad_keycodes (void)
{
    Display *display;
    short *keycodes = (short *) g_new0 (short *, COUNT_OF_ITEM_IN_LAYER_KEYSET);	

    display = GDK_DISPLAY ();
    
    keycodes [0] = XKeysymToKeycode (display, XK_KP_0);
    keycodes [1] = XKeysymToKeycode (display, XK_KP_1);
    keycodes [2] = XKeysymToKeycode (display, XK_KP_2);
    keycodes [3] = XKeysymToKeycode (display, XK_KP_3);
    keycodes [4] = XKeysymToKeycode (display, XK_KP_4);
    keycodes [5] = XKeysymToKeycode (display, XK_KP_5);
    keycodes [6] = XKeysymToKeycode (display, XK_KP_6);
    keycodes [7] = XKeysymToKeycode (display, XK_KP_7);
    keycodes [8] = XKeysymToKeycode (display, XK_KP_8);
    keycodes [9] = XKeysymToKeycode (display, XK_KP_9);
    keycodes [10] = XKeysymToKeycode (display, XK_KP_Decimal);
    keycodes [11] = XKeysymToKeycode (display, XK_KP_Enter);
    keycodes [12] = XKeysymToKeycode (display, XK_KP_Add);
    keycodes [13] = XKeysymToKeycode (display, XK_KP_Subtract);
    keycodes [14] = XKeysymToKeycode (display, XK_KP_Multiply);
    keycodes [15] = XKeysymToKeycode (display, XK_KP_Divide);
    	
    return keycodes;
}



gboolean
ke_init (KeyboardEchoCB kecb)
{
    short *ke_layer_keycodes;
    ke_layer_listener 	 = SPI_createAccessibleKeystrokeListener (ke_report_layer_key_event, NULL);

    ke_layer_keycodes = ke_get_keypad_keycodes ();
    ke_layer_keyset   = SPI_createAccessibleKeySet (COUNT_OF_ITEM_IN_LAYER_KEYSET, NULL, ke_layer_keycodes, NULL);
    g_free (ke_layer_keycodes);

    ke_layer_register_events (ke_layer_listener,
			     (AccessibleKeySet *) ke_layer_keyset);
    return TRUE;
}
/**************************************************************/

void
ke_terminate (void)
{
}

