/*
================================ COPYRIGHT ================================
The contents of this file are subject to the VTech Informations Ltd. License
of VT-OS Ver. 1.1 operating system (the "License"); you may not use this 
file except in compliance with the License.  

Software distributed under the License is distributed on an "AS IS" basis, 
WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License 
for the specific language governing rights and limitations under the License.
  
The Original Code is VT-OS Ver. 1.1 Operating System, released 
on October 1st, 1999
	
The Initial Developer of the Original Code is VTech Informations Ltd.  All 
codes are Copyright (C) VTech Informations Ltd. 1999.  All Rights Reserved.
===========================================================================
*/

/*
===========================================================================
File        :   keyboard.c
Author(s)   :   Henry Fok
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   software keyboard object functions
Revision    :   1.1
Note        :   None
===========================================================================
*/              

#include "stdafx.h"

#include "uidef.h"
#include "uifunc.h"


/********************************************************
* Function:	KeyboardInitKeyboard
* Purpose:		to load the information of the keys 
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardInitKeyboard()
{
	WORD i;
    BitmapTemplate *temp;
	
	keyboard.bounds.xcoord = 0;
	keyboard.bounds.ycoord = 99;
	keyboard.bounds.width = 160;
	keyboard.bounds.height = 61;
	
	keyboard.keyboard_num_keys = 256;
	keyboard.keyboard_num_keyboard_bitmap = 10;
	keyboard.keyboard_highlight_key = 0;
	
    keyboard.keyboard_keys_bounds = keys_bounds;
	keyboard.keyboard_bitmap_index = keyboard_bitmap_index;
    keyboard.keyboard_bitmap = (BitmapTemplate **)pmalloc(keyboard.keyboard_num_keyboard_bitmap *sizeof(BitmapTemplate*));
	
	i = (keyboard.keyboard_num_keyboard_bitmap);
	while (i)
	{
		i--;
        temp = (BitmapTemplate*)pmalloc(sizeof(BitmapTemplate));
		temp->xcoord = keyboard.bounds.xcoord;
		temp->ycoord = keyboard.bounds.ycoord;
		temp->width = keyboard.bounds.width;
		temp->height = keyboard.bounds.height;
		temp->compressed = 0;
        temp->quantisation = Q_TWO_BIT;
		temp->size = 0;
		if (i == 0)
			(const *)temp->bitmap_data = key0;
		else if (i == 1)
			(const *)temp->bitmap_data = key1;
		else if (i == 2)
			(const *)temp->bitmap_data = key2;
		else if (i == 3)
			(const *)temp->bitmap_data = key3;
		else if (i == 4)
			(const *)temp->bitmap_data = key4;
		else if (i == 5)
			(const *)temp->bitmap_data = key5;
		else if (i == 6)
			(const *)temp->bitmap_data = key6;
		else if (i == 7)
			(const *)temp->bitmap_data = key7;
		else if (i == 8)
			(const *)temp->bitmap_data = key8;
		else if (i == 9)
			(const *)temp->bitmap_data = key9;
		
		
		keyboard.keyboard_bitmap[i] = temp;
	}
	
	keyboard.keyboard_attr.keyboard_drawn = FALSE;
	keyboard.keyboard_attr.keyboard_enable = TRUE;
	keyboard.keyboard_attr.keyboard_cap = FALSE;
	keyboard.keyboard_attr.keyboard_shift = FALSE;
	keyboard.keyboard_attr.keyboard_international = FALSE;
	keyboard.keyboard_attr.keyboard_enter = FALSE;
	keyboard.save_behind.bitmap_data = NULL;
	
    keyboard.keyboard_attr.keyboard_customised = FALSE;       // <----------- new attribute
    
    KeyboardDefineKeyboard(0);
}
/********************************************************
* Function:	KeyboardDrawKeyboard
* Purpose:		to draw the first bitmap of the keyboard
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardDrawKeyboard()
{
	keyboard.keyboard_attr.keyboard_drawn = TRUE;
	keyboard.keyboard_attr.keyboard_enter = FALSE;
	keyboard_status = TRUE;
	LcdDrawBitmap(keyboard.keyboard_bitmap[(keyboard.keyboard_current_bitmap_index)], FALSE);
}
/********************************************************
* Function:	KeyboardDrawKeyboardBitmap
* Purpose:		to draw a particular selected bitmap of keyboard
* Scope:		Application
* Input:		bitmap_index	the bitmap index of the selected keyboard template
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardDrawKeyboardBitmap(BYTE bitmap_index)
{
	LcdDrawBitmap(keyboard.keyboard_bitmap[bitmap_index], FALSE);
	keyboard.keyboard_current_bitmap_index = bitmap_index;
}

/********************************************************
* Function:	KeyboardGetClickedKey
* Purpose:		to get the ascii of the pressed key
* Scope:		Application
* Input:		xcoord		current xcoord of the pen
*				ycoord		current ycoord of the pen
* Output:		None
* Return:		UBYTE		ascii code of the pressed key
* Comment:     if the return is 0, it means that not hit
*********************************************************/
UBYTE KeyboardGetClickedKey(SHORT xcoord, SHORT ycoord)
{
	WORD i;
	SHORT current_bitmap_index;
	
	if (xcoord < keyboard.bounds.xcoord || xcoord > (keyboard.bounds.xcoord + keyboard.bounds.width - 1)
		|| ycoord <(keyboard.bounds.ycoord) || ycoord > (keyboard.bounds.ycoord + keyboard.bounds.height - 1))
		return 0; /*not hit*/
	
	/* exception case */
	/* NUM */
    if (xcoord >= 0    && xcoord <= (1 - 1 + 18 + 2 - 1) &&
        ycoord >= 129  && ycoord <= (130 - 1 + 14 + 2 - 1) &&
		(keyboard.keyboard_current_bitmap_index == 9))
		return 5;
	
    if (xcoord >= 85        && xcoord <= (86 - 1 + 17 + 2 - 1) &&
        ycoord >= 144   && ycoord <= (145 - 1 + 14 + 2 - 1) &&
		(keyboard.keyboard_current_bitmap_index != 4 &&
		keyboard.keyboard_current_bitmap_index != 9))
		return 5;
	
	/* abc */
    if (xcoord >= 21    && xcoord <= (22 - 1 + 14 + 2 - 1) &&
        ycoord >= 144   && ycoord <= (145 - 1 + 14 + 2 - 1) &&
		(keyboard.keyboard_current_bitmap_index >= 5 &&
		keyboard.keyboard_current_bitmap_index <= 8))
		return 6;
	
    if (xcoord >= 85    && xcoord <= (86 - 1 + 17 + 2 - 1) &&
        ycoord >= 144   && ycoord <= (145 - 1 + 14 + 2 - 1) &&
		(keyboard.keyboard_current_bitmap_index == 4 ||
		keyboard.keyboard_current_bitmap_index == 9))
		return 6;
	
	/* $ */
    if (xcoord >= 42    && xcoord <= (43 - 1 + 13 + 2 - 1) &&
        ycoord >= 114   && ycoord <= (115 - 1 + 14 + 2 - 1) &&
		keyboard.keyboard_current_bitmap_index == 4)
		return '$';
	
    if (xcoord >= 145   && xcoord <= (146 - 1 + 13 + 2 - 1) &&
        ycoord >= 129   && ycoord <= (130 - 1 + 14 + 2 - 1) &&
		keyboard.keyboard_current_bitmap_index == 9)
		return '$';
	
	/* @ */
    if (xcoord >= 14    && xcoord <= (15 - 1 + 13 + 2 - 1) &&
        ycoord >= 114   && ycoord <= (115 - 1 + 14 + 2 - 1) &&
		keyboard.keyboard_current_bitmap_index == 4)
		return '@';
	
    if (xcoord >= 126   && xcoord <= (127 - 1 + 13 + 2 - 1) &&
        ycoord >= 114   && ycoord <= (115 - 1 + 14 + 2 - 1) &&
		keyboard.keyboard_current_bitmap_index == 9)
		return '@';
	
	i = keyboard.keyboard_num_keys;
	while (i)
	{
		i--;
        if (xcoord >= (keyboard.keyboard_keys_bounds[i].xcoord - 1) &&
            xcoord <= (keyboard.keyboard_keys_bounds[i].xcoord - 1 + keyboard.keyboard_keys_bounds[i].width + 2 - 1) &&
            ycoord >= (keyboard.keyboard_keys_bounds[i].ycoord - 1 + 99)&&
            ycoord <= (keyboard.keyboard_keys_bounds[i].ycoord - 1 + 99 + keyboard.keyboard_keys_bounds[i].height + 2 - 1))
		{
			current_bitmap_index = 1;
			current_bitmap_index <<= (keyboard.keyboard_current_bitmap_index);
			if (current_bitmap_index & keyboard.keyboard_bitmap_index[i])
				return (UBYTE)i;
		}
	}
	return 0;
}

/*********************************************************************
* Function: 	KeyboardSaveBehindBits
* Purpose: 		This function is used to set the keyboard_save_behind
*		      	attribute and to store the image that is being covered
*			  	by the specified keyboard object.
* Scope: 		Application
* Input: 		None
* Output: 		None
* Return: 		None
* Comment: 		None
**********************************************************************/
void KeyboardSaveBehindBits()
{
	/* Get the bounds to save */
	keyboard.save_behind.xcoord = keyboard.bounds.xcoord;
    keyboard.save_behind.ycoord = keyboard.bounds.ycoord;
	keyboard.save_behind.width  = keyboard.bounds.width;
	keyboard.save_behind.height = keyboard.bounds.height;
    LcdGetBitmap(&(keyboard.save_behind));
	keyboard.keyboard_attr.keyboard_save_behind = TRUE;
}
/********************************************************
* Function:	KeyboardRestoreBitBehind
* Purpose:		to re-drawn the covered and saved image that is
behind the specific object
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardRestoreBitBehind()
{
	/* to check whether save_behind is TRUE */
	if (keyboard.keyboard_attr.keyboard_save_behind == TRUE)
	{
		LcdDrawBitmap(&(keyboard.save_behind), FALSE);
		qfree(keyboard.save_behind.bitmap_data);
		keyboard.keyboard_attr.keyboard_save_behind = FALSE;
		keyboard.save_behind.bitmap_data = NULL;
	}
}

/********************************************************
* Function:	KeyboardRemvoeKeyboard
* Purpose:		This function is called in order to erase
keyboard and free pointer of save behind
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardRemoveKeyboard()
{
	/* to check whether save_behind is TRUE */
	if (keyboard.keyboard_attr.keyboard_save_behind == TRUE)
	{ 
		LcdEraseRegion(&(keyboard.bounds));
		if (keyboard.save_behind.bitmap_data != NULL)
			pfree(keyboard.save_behind.bitmap_data);
		keyboard.keyboard_attr.keyboard_save_behind = FALSE;
		keyboard_status = FALSE;
		keyboard.save_behind.bitmap_data = NULL;
	}
}

/********************************************************
* Function:	KeyboardSendEvent
* Purpose:		to send event if only caps, international and shift keys 
is pressed
* Scope:		Application
* Input:		key
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardSendEvent(UBYTE key, BOOLEAN cap, BOOLEAN shift, BOOLEAN international)
{
	EvtType new_event;
	
	new_event.eventType = EVT_KEY;
	new_event.eventID = SOFT_KEY;
	
	if ((key >= 32 && key <= 255) || key == 8 || key == 9 
		|| key == 13 || key == 27)
	{
		new_event.para1 = key;
		new_event.para2 = 0;
	}
	else
	{
		new_event.para1 = 0;
		new_event.para2 = key;
	}
	
	if (cap == TRUE)
		new_event.para2 += 0x0800;
	if (shift == TRUE)
		new_event.para2 += 0x0400;
	if (international == TRUE)
		new_event.para2 += 0x1000;
	
	new_event.evtPBP = NULL;
	EvtAppend(new_event,&evtQueue);
}
/********************************************************
* Function:	KeyboardDrawInvertKey
* Purpose:		to invert a particular key
* Scope:		Application
* Input:		key		the ascii of the key
* Output:		None
* Return:		TRUE means the drawing is successful
*				ERR_UI_CANT_FIND_KEY means can't draw			
* Comment:     None
*********************************************************/
Err KeyboardDrawInvertKey(UBYTE key)
{
	ObjectBounds bounds;
	SHORT bitmap_index;
	BitmapTemplate temp;
	SHORT current_bitmap_index = 1;
	
    bounds = keyboard.keyboard_keys_bounds[key];
	bitmap_index = keyboard.keyboard_bitmap_index[key];
	
	/* exception case */
	/* NUM */
	switch (key)
	{
	case 5:	
		if (keyboard.keyboard_current_bitmap_index == 9)
		{
			bounds.xcoord = 1;
			bounds.ycoord = 31;
			bounds.width = 18;
			bounds.height = 14;
		}
		else if (keyboard.keyboard_current_bitmap_index != 4 &&
			keyboard.keyboard_current_bitmap_index != 9)
		{
			bounds.xcoord = 86;
			bounds.ycoord = 46;
			bounds.width = 17;
			bounds.height = 14;
		}
		break;
	case 6:
		if (keyboard.keyboard_current_bitmap_index >= 5 &&
			keyboard.keyboard_current_bitmap_index <= 8)
		{
			bounds.xcoord = 22;
			bounds.ycoord = 46;
			bounds.width = 14;
			bounds.height = 14;
		}
		else if (keyboard.keyboard_current_bitmap_index == 9)
		{
			bounds.xcoord = 86;
			bounds.ycoord = 46;
			bounds.width = 17;
			bounds.height = 14;
		}
		break;
	case '$':
		if (keyboard.keyboard_current_bitmap_index == 4)
		{
			bounds.xcoord = 43;
			bounds.ycoord = 16;
			bounds.width = 13;
			bounds.height = 14;
		}
		else if (keyboard.keyboard_current_bitmap_index == 9)
		{
			bounds.xcoord = 146;
			bounds.ycoord = 31;
			bounds.width = 13;
			bounds.height = 14;
		}
		break;
	case '@':
		if (keyboard.keyboard_current_bitmap_index == 4)
		{
			bounds.xcoord = 15;
			bounds.ycoord = 16;
			bounds.width = 13;
			bounds.height = 14;
		}
		else if (keyboard.keyboard_current_bitmap_index == 9)
		{
			bounds.xcoord = 127;
			bounds.ycoord = 16;
			bounds.width = 13;
			bounds.height = 14;
		}
		break;
	}	
	
	current_bitmap_index <<= keyboard.keyboard_current_bitmap_index;
	
	if (bitmap_index & current_bitmap_index)
	{
		temp.xcoord = bounds.xcoord;
		temp.ycoord = bounds.ycoord + 99;
		temp.width = bounds.width;
		temp.height = bounds.height;
		temp.quantisation = Q_TWO_BIT;
		temp.compressed = 1;
		
		LcdGetBitmap(&temp);
		LcdDrawBitmap(&temp, TRUE);
		qfree(temp.bitmap_data);
		return TRUE;
	}
	else return ERR_UI_CANT_FIND_KEY;
}

/********************************************************
* Function:	KeyboardCheckKeyboardStatus
* Purpose:		This function is used in order to get the 
variable keyboard_status
* Scope:		Application
* Input:		None
* Output:		None
* Return:		TRUE		when keyboard is popup
FALSE		when keyboard is not popup
* Comment:     None
*********************************************************/
BOOLEAN KeyboardCheckKeyboardStatus()
{
	return keyboard_status;
}

/********************************************************
* Function:	KeyboardSetKeyboardStatus
* Purpose:		This function is called in order to set 
the keyboard_status parameter
* Scope:		Application
* Input:		status		BOOLEAN variable
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardSetKeyboardStatus(BOOLEAN status)
{
	keyboard_status = status;
}

/********************************************************
* Function:	KeyboardSetKeyboardVisible
* Purpose:		This function is to set the keyboard to be visible
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardSetKeyboardVisible()
{
	keyboard.keyboard_attr.keyboard_visible = TRUE;
}

/********************************************************
* Function:	KeyboardSetKeyboardInvisible
* Purpose:		This function is to set the keyboard to be invisible
* Scope:		Application
* Input:		status		BOOLEAN variable
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardSetKeyboardInvisible()
{
	keyboard.keyboard_attr.keyboard_visible = FALSE;
}

/********************************************************
* Function:	KeyboardGetCurrentKeyboardNumber
* Purpose:		to get the current keyboard number
* Scope:		Application/System
* Input:		WORD keyboard_number 0...9
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
WORD KeyboardGetCurrentKeyboardNumber()
{
	return keyboard.keyboard_current_bitmap_index;
}

/********************************************************
* Function:	KeyboardRestoreKeyboard
* Purpose:		Restore the original keyboard from flash
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardRestoreKeyboard()
{
	WORD i;
	BitmapTemplate *temp;
	
    if (!(keyboard.keyboard_attr.keyboard_customised))
		return;
	
	keyboard.bounds.xcoord = 0;
	keyboard.bounds.ycoord = 99;
	keyboard.bounds.width = 160;
	keyboard.bounds.height = 61;
	
	keyboard.keyboard_num_keys = 256;
	keyboard.keyboard_num_keyboard_bitmap = 10;
	keyboard.keyboard_highlight_key = 0;
	
	keyboard.keyboard_keys_bounds = keys_bounds;
	keyboard.keyboard_bitmap_index = keyboard_bitmap_index;
	
	i = (keyboard.keyboard_num_keyboard_bitmap);
	while (i)
	{
		i--;
		temp = keyboard.keyboard_bitmap[i];
		temp->xcoord = keyboard.bounds.xcoord;
		temp->ycoord = keyboard.bounds.ycoord;
		temp->width = keyboard.bounds.width;
		temp->height = keyboard.bounds.height;
		temp->compressed = 0;
        temp->quantisation = Q_TWO_BIT;
		temp->size = 0;
		if (i == 0)
			(const *) temp->bitmap_data = key0;
		else if (i == 1)
			(const *) temp->bitmap_data = key1;
		else if (i == 2)
			(const *) temp->bitmap_data = key2;
		else if (i == 3)
			(const *) temp->bitmap_data = key3;
		else if (i == 4)
			(const *) temp->bitmap_data = key4;
		else if (i == 5)
			(const *) temp->bitmap_data = key5;
		else if (i == 6)
			(const *) temp->bitmap_data = key6;
		else if (i == 7)
			(const *) temp->bitmap_data = key7;
		else if (i == 8)
			(const *) temp->bitmap_data = key8;
		else if (i == 9)
			(const *) temp->bitmap_data = key9;
	}
	
	keyboard.keyboard_attr.keyboard_drawn = FALSE;
	keyboard.keyboard_attr.keyboard_enable = TRUE;
	keyboard.keyboard_attr.keyboard_cap = FALSE;
	keyboard.keyboard_attr.keyboard_shift = FALSE;
	keyboard.keyboard_attr.keyboard_international = FALSE;
	keyboard.keyboard_attr.keyboard_enter = FALSE;
	keyboard.save_behind.bitmap_data = NULL;
}


/********************************************************
* Function:	KeyboardSetCustomKeyboard
* Purpose:		Set custom keyboard
* Scope:		Application
* Input:		New keyboards data (see KeyApi.cpp for reference)
*				ObjectBounds new_keys_bounds[]
*				UWORD* new_keyboards[]
*				SHORT* keyb_bitmap_index
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardSetCustomKeyboard(const ObjectBounds *new_keys_bounds, const UWORD **new_keyboards, const short *keyb_bitmap_index)
{
	WORD i;
	BitmapTemplate *temp;
	
    keyboard.keyboard_attr.keyboard_customised = TRUE;
	
	keyboard.bounds.xcoord = 0;
	keyboard.bounds.ycoord = 99;
	keyboard.bounds.width = 160;
	keyboard.bounds.height = 61;
	
	keyboard.keyboard_num_keys = 256;
	keyboard.keyboard_num_keyboard_bitmap = 10;
	keyboard.keyboard_highlight_key = 0;
	
	keyboard.keyboard_keys_bounds = (ObjectBounds*) new_keys_bounds;
	keyboard.keyboard_bitmap_index = keyb_bitmap_index;
	
	i = (keyboard.keyboard_num_keyboard_bitmap);
	while (i)
	{
		i--;
		temp = keyboard.keyboard_bitmap[i];
		temp->xcoord = keyboard.bounds.xcoord;
		temp->ycoord = keyboard.bounds.ycoord;
		temp->width = keyboard.bounds.width;
		temp->height = keyboard.bounds.height;
		temp->compressed = 0;
        temp->quantisation = Q_TWO_BIT;
		temp->size = 0;
		if( new_keyboards[i] != 0)
			(const*) temp->bitmap_data = new_keyboards[i];
	}
	
	keyboard.keyboard_attr.keyboard_drawn = FALSE;
	keyboard.keyboard_attr.keyboard_enable = TRUE;
	keyboard.keyboard_attr.keyboard_cap = FALSE;
	keyboard.keyboard_attr.keyboard_shift = FALSE;
	keyboard.keyboard_attr.keyboard_international = FALSE;
	keyboard.keyboard_attr.keyboard_enter = FALSE;
	keyboard.save_behind.bitmap_data = NULL;
}

/********************************************************
* Function:	KeyboardDefineKeyboard
* Purpose:		to draw the defined bitmap of the keyboard
* Scope:		Application
* Input:		WORD keyboard_number 0...9
* Output:		None
* Return:		None
* Comment:     None
*********************************************************/
void KeyboardDefineKeyboard(WORD keyboard_number)
{
	keyboard.keyboard_attr.keyboard_enter = FALSE;
	
	if(keyboard_number == 2 || keyboard_number == 3
		|| keyboard_number == 7 || keyboard_number == 8)
		keyboard.keyboard_attr.keyboard_cap = TRUE;
	else
		keyboard.keyboard_attr.keyboard_cap = FALSE;
	
	if(keyboard_number == 1 || keyboard_number == 3
		|| keyboard_number == 6 || keyboard_number == 8)
		keyboard.keyboard_attr.keyboard_shift = TRUE;
	else
		keyboard.keyboard_attr.keyboard_shift = FALSE;
	
	if(keyboard_number < 5 || keyboard_number == 9)
		keyboard.keyboard_attr.keyboard_international = FALSE;
	else
		keyboard.keyboard_attr.keyboard_international = TRUE;
	
	keyboard.keyboard_current_bitmap_index = keyboard_number;
}
