/*
================================ 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        :   uiglobal.c
Author(s)   :   Henry Fok
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   UI Global functions
Revision    :   1.1
Note        :   None
===========================================================================
*/              



#include "stdafx.h"

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

#ifdef DEBUG
extern int totala, totalf, counta, countf;
#endif

/* ==================================================================== */
/* ========================= Global Variables ========================= */
/* ==================================================================== */
LinkListForm    *main_pointer = NULL;
LookupTable     *lookup_table_ptr = NULL;
BOOLEAN         insert = TRUE;
BYTE            undo_action = UNDO_EMPTY;
Clipboard       clipboard;
Clipboard       undo_buffer;
BOOLEAN         keyboard_status = FALSE;
BOOLEAN         menu_status = FALSE;
BOOLEAN         popup_status = FALSE;
Keyboard        keyboard;
BackspaceUndo   backspace_undo;
TypingUndo 		typing_undo;
EvtType         old_event;
EvtType         inlay_event;
BYTE            form_loaded_once = 0;
SHORT           stored_bitmap_index = -1;
BOOLEAN         by_pass_scrollbar_event = FALSE;

void (*InsertTextFunction)(ObjectID id, BYTE object_type, void* addr, BYTE key);
void (*BackspaceFunction)(ObjectID id, BYTE object_type, void* addr);


/* ==================================================================== */
/* ==================================================================== */
/* ========================= Global Functions ========================= */
/* ==================================================================== */
/********************************************************
* Function:	UIInit
* Purpose:	    This function should be called in the Main() to initialise
the UI Mgr before the program goes to EventLoop
* Scope:       Application/internal
* Input:	    None
* Output:		None
* Return:      None
* Comment:     None
*********************************************************/
void UIInit()
{
	WORD count;
	
	main_pointer = NULL;
	lookup_table_ptr = NULL;
    inlay_status = 1;
	insert = TRUE;
	undo_action = UNDO_EMPTY;
	keyboard_status = FALSE;
	menu_status = FALSE;
	popup_status = FALSE;
    form_loaded_once = 0;
    by_pass_scrollbar_event = FALSE;
	
	keyboard.keyboard_attr.keyboard_visible = TRUE;
	
    stored_bitmap_index = -1;
	
	KeyboardInitKeyboard();
	
	old_event.eventType = NULL_EVENT;
	inlay_event.eventType = NULL_EVENT;
	
	clipboard.clipboard_type = CLIP_EMPTY;
	clipboard.clipboard_size = 0;
	clipboard.clipboard_data = NULL;
	
	undo_buffer.clipboard_type = CLIP_EMPTY;
	undo_buffer.clipboard_size = 0;
	undo_buffer.clipboard_data = NULL;
	
	backspace_undo.current_object_id = 0;
	count = 256;
	while (count)
	{	
		count--;
		backspace_undo.key[count] = 0;
	}
	backspace_undo.index = -1;
	
	typing_undo.focus_object_id = 0;
	typing_undo.start_char = -1;
	typing_undo.length = -1;
	
    SysFontRestoreFont();
	SysSetCustomInsertFunction(NULL);
	SysSetCustomBackspaceFunction(NULL);
}

/********************************************************
* Function:	UIApplicationInit
* Purpose:	    This function should be called in each application
* Scope:       Application/internal
* Input:	    None
* Output:		None
* Return:      None
* Comment:     None
*********************************************************/
void UIApplicationInit()
{
	WORD count;
	
	main_pointer = NULL;
	lookup_table_ptr = NULL;
    inlay_status = 1;
	insert = TRUE;
	undo_action = UNDO_EMPTY;
	keyboard_status = FALSE;
	menu_status = FALSE;
	popup_status = FALSE;
    form_loaded_once = 0;
    by_pass_scrollbar_event = FALSE;
	keyboard.keyboard_attr.keyboard_visible = TRUE;
	
	old_event.eventType = NULL_EVENT;
	inlay_event.eventType = NULL_EVENT;
	
    keyboard.keyboard_attr.keyboard_save_behind = FALSE;
    keyboard.save_behind.bitmap_data = NULL;
	
	/*
    if (keyboard.keyboard_attr.keyboard_save_behind &&
	keyboard.save_behind.bitmap_data)
	{
	qfree(keyboard.save_behind.bitmap_data);
	keyboard.keyboard_attr.keyboard_save_behind = FALSE;
	keyboard.save_behind.bitmap_data = NULL;
	}
	*/
	
	undo_buffer.clipboard_type = CLIP_EMPTY;
	undo_buffer.clipboard_size = 0;
    undo_buffer.clipboard_data = NULL;
	backspace_undo.current_object_id = 0;
	count = 256;
	while (count)
	{	
		count--;
		backspace_undo.key[count] = 0;
	}
	backspace_undo.index = -1;
	
	typing_undo.focus_object_id = 0;
	typing_undo.start_char = -1;
	typing_undo.length = -1;
	
    gf_popup = FALSE;
	gf_error = GF_NO_ERROR;
	gf_num_items = 0;
	if (gf_link != NULL)
		GlobalFindDeleteAllItems();
	gf_old_event.eventType = NULL_EVENT;
}

/********************************************************
* Function:	UISearchForAddress
* Purpose:	    This function is used to search the address pointer
of different object by inputting the databaseID
of an object
* Scope:       internal
* Input:	    object_id	DBID of the object
* Output:		type		Pointer to a BYTE to show the type of the
object with DBID form_id
address		Pointer to the address of the object structure
in the lookup table
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND - Invalid DBID
* Comment:     None
*********************************************************/
Err UISearchForAddress(ObjectID object_id, BYTE *type, void **address)
{
    volatile LookupTable *temp = lookup_table_ptr;
    BOOLEAN error = FALSE;
	
	
	while (temp !=NULL)
	{
	if (temp->object_id == object_id) /*if the object Id can be found
		in the lookup table */
	{
		/* the address and type of the object are extracted */
		switch (temp->object_type)
		{
		case FORM:
			if (((Form*)(temp->object_struct_add))->identification.ui_object_type != FORM)
				error = TRUE;
			break;
		case CONTROL:
			if (((Control*)(temp->object_struct_add))->identification.ui_object_type != CONTROL)
				error = TRUE;
			break;
		case FIELD:
			
			if (((Field*)(temp->object_struct_add))->identification.ui_object_type != FIELD)
				error = TRUE;
			break;
		case LIST:
			if (((List*)(temp->object_struct_add))->identification.ui_object_type != LIST)
				error = TRUE;
			break;
		case MENU:
			if (((Menu*)(temp->object_struct_add))->identification.ui_object_type != MENU)
				error = TRUE;
			break;
		case SCROLLBAR:
			if (((Scrollbar*)(temp->object_struct_add))->identification.ui_object_type != SCROLLBAR)
				error = TRUE;
			break;
		case TABLE:
			if (((Table*)(temp->object_struct_add))->identification.ui_object_type != TABLE)
				error = TRUE;
			break;
		case SCHLINE:
			if (((Schline*)(temp->object_struct_add))->identification.ui_object_type != SCHLINE)
				error = TRUE;
			break;
		case STRING:
			if (((String*)(temp->object_struct_add))->identification.ui_object_type != STRING)
				error = TRUE;
			break;
		case BITMAP:
			if (((Bitmap*)(temp->object_struct_add))->identification.ui_object_type != BITMAP)
				error = TRUE;
			break;
		case TEXTBOX:
			if (((Textbox*)(temp->object_struct_add))->identification.ui_object_type != TEXTBOX)
				error = TRUE;
			break;
		case LINE:
			if (((Line*)(temp->object_struct_add))->identification.ui_object_type != LINE)
				error = TRUE;
			break;
		default: break;
		}
		if (error == FALSE)
		{
			*address = temp->object_struct_add;
			*type = temp->object_type;
			return TRUE;
		}
		else break;
	}
	temp = temp->next;
	}
	/*if no match*/
    *address = NULL;
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	UIAddressToLookupTable
* Purpose:	    This function is used to add the address
pointer to the LookupTable
* Scope:       internal
* Input:		object_id		DBID of the object
object type		object type of the object
* Output:		address			Pointer to address of the object
* Return:      TRUE if no error
ErrUICantCreateLookupTable
ErrUICantCreatePointer
* Comment:     None
*********************************************************/
Err UIAddressToLookupTable(ObjectID object_id,BYTE type,void **address)
{
	LookupTable *tmp;
	LookupTable * temp = lookup_table_ptr;
	while (temp !=NULL)
	{
	if (temp->object_id == object_id) /* that object is already in
						  the lookup table */
	{
		if (temp->object_type != type) return ERR_UI_TYPE_MISMATCH;
		switch (temp->object_type)
		{
		case FORM:		FormDeleteForm(temp->object_id);
			break;
		case CONTROL:	ControlDeleteControl(temp->object_id);break;
		case FIELD:		FieldDeleteField(temp->object_id);break;
		case LIST:		ListDeleteList(temp->object_id);break;
		case MENU:		MenuDeleteMenu(temp->object_id);break;
		case SCROLLBAR:	ScrollbarDeleteScrollbar(temp->object_id);break;
		case TABLE:		TableDeleteTable(temp->object_id);break;
		case SCHLINE:	SchlineDeleteSchline(temp->object_id);break;
		case STRING:	StringDeleteString(temp->object_id);break;
		case BITMAP:	BitmapDeleteBitmap(temp->object_id);break;
		case LINE:		LineDeleteLine(temp->object_id);break;
		case TEXTBOX:	TextboxDeleteTextbox(temp->object_id);break;
		default: break;
		}
		break;
	}
	temp = temp->next;
	}
	/* the object is not in the lookup table */
	temp = NULL;
    tmp = (LookupTable *) qmalloc(sizeof(LookupTable));
	if (tmp == NULL)
	{
		return ERR_UI_CANT_CREATE_LOOKUP_TABLE;
	}
	tmp->object_id = object_id;
	tmp->object_type = type;
	switch (type)
	{
	case FORM:        *address = qmalloc(sizeof(Form));
		break;
	case CONTROL:     *address = qmalloc(sizeof(Control));
		break;
	case FIELD:
		*address = qmalloc(sizeof(Field));
		break;
	case LIST:        *address = qmalloc(sizeof(List));
		break;
	case MENU:        *address = qmalloc(sizeof(Menu));
		break;
	case SCROLLBAR:   *address = qmalloc(sizeof(Scrollbar));
		break;
	case TABLE:       *address = qmalloc(sizeof(Table));
		break;
	case SCHLINE:     *address = qmalloc(sizeof(Schline));
		break;
	case STRING:      *address = qmalloc(sizeof(String));
		break;
	case BITMAP:      *address = qmalloc(sizeof(Bitmap));
		break;
	case LINE:        *address = qmalloc(sizeof(Line));
		break;
	case TEXTBOX:     *address = qmalloc(sizeof(Textbox));
		break;
	default: break;
	}
	if (!address) return ERR_UI_CANT_CREATE_POINTER;
	tmp->object_struct_add = *address;
	tmp->next = lookup_table_ptr;
	lookup_table_ptr = tmp;
	return TRUE;
}
/********************************************************
* Function:	UIDeleteLookupTableElement
* Purpose:	 	This function is used to delete an element
in the lookup table and free the corresponding
pointer to the data structure
* Scope:       internal
* Input:      	object_id		DBID of the object
* Output:     	None
* Return:      TRUE if no error
ErrUICantCreatePointer
* Comment:     None
*********************************************************/
Err UIDeleteLookupTableElement(ObjectID object_id)
{
	LookupTable *temp = lookup_table_ptr;
	LookupTable *temp1;
	
	while (temp != NULL)
	{
	/* if the the specified DBID can be found in the top of
		the lookup table */
		if (temp->object_id == object_id && temp == lookup_table_ptr)
		{
			lookup_table_ptr = temp->next;
			qfree(temp);
			return TRUE;
		}
		/* if the specified DBID is no at the top of the lookup
		table */
		if (temp->object_id == object_id && temp != lookup_table_ptr)
		{
			temp1->next = temp->next;
			qfree(temp);
			return TRUE;
		}
		/* if the specified DBID does not match with the
		current checking element in the lookup table */
		if (temp->object_id != object_id)
		{
			temp1 = temp;
			temp = temp->next;
		}
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	UIDeleteLinkLiskFormElement
* Purpose:		This function is used to delete an element in
the link list of the form objects
* Scope:       internal
* Input:       form_id		DBID of the form object
* Output:      None
* Return:		TRUE if no error
ErrUINoActiveFormFound
* Comment:     None
*********************************************************/
Err UIDeleteLinkListFormElement (ObjectID form_id)
{
	LinkListForm *temp = main_pointer;
	LinkListForm *temp1;
	while (temp != NULL)
	{
	/* if the the specified DBID can be found in the top of
		the list link structure */
		if (temp->form_id == form_id && temp == main_pointer)
		{
			main_pointer = temp->next;
			qfree(temp);
			return TRUE;
		}
		/* if the specified DBID is not at the top of the list link
		structure */
		if (temp->form_id == form_id && temp != main_pointer)
		{
			temp1->next = temp->next;
			qfree(temp);
			return TRUE;
		}
		/* if the specified DBID does not match with the
		current checking element in the list link table */
		if (temp->form_id != form_id)
		{
			temp1 = temp;
			temp = temp->next;
		}
	}
	return ERR_UI_NO_ACTIVE_FORM_FOUND;
}
/********************************************************
* Function:	UIDeleteLinkLiskFormElement
* Purpose:		This function is used to add an element to
the link list of the form objects
* Scope:       internal
* Input:       form_id		DBID of the form object
* Output:      None
* Return:		TRUE if no error
* Comment:     None
*********************************************************/
Err UIAddLinkListFormElement(ObjectID form_id,Form **form_pointer)
{
	Form *form_ptr;
	Err Error;
	LinkListForm *temp4 = main_pointer;
	BOOLEAN found = FALSE;
	
	/*put the form structure to lookup table */
	/*put the pointer to the DBID lookup table */
	Error = UIAddressToLookupTable(form_id,0,(void**)&form_ptr);
	if (Error != TRUE) return Error;
	else temp4 = main_pointer;
	/* inser the form object to the LinkListForm structure */
	while (temp4 != NULL)
	{
	/* if the form is already in the LinkListForm structure
	the address of the form is put in the corresponding LinkListForm
		record */
		if (temp4->form_id == form_id)
		{
			found = TRUE;
			temp4->current_form = form_ptr;
			break;
		}
		temp4 = temp4->next;
	}
	/* if the form object is not already put in the LinkListForm structure */
	/* new record is added to the LinkListForm structure */
	if (found == FALSE)
	{
		temp4 = (LinkListForm*)qmalloc(sizeof(LinkListForm));
		if (temp4 == NULL) return ERR_UI_CANT_CREATE_POINTER;
		temp4->next = main_pointer;
		temp4->form_id = form_id;
		temp4->current_form = form_ptr;
		main_pointer = temp4;
	}
	*form_pointer = form_ptr;
	return TRUE;
}
/********************************************************
* Function:	UIColorConversion
* Purpose:		This function is called to convert the color from
*				resource file to RAM
* Scope:       internal
* Input:       color_in	color input
* Output:      None
* Return:		color output
* Comment:     None
*********************************************************/
BYTE UIColorConversion(BYTE color_in)
{
	switch(color_in)
	{
	case COLOR_WHITE_COLOR:
		return color_level[COLOR_WHITE_COLOR];
	case COLOR_GREY1_COLOR:
		return color_level[COLOR_GREY1_COLOR];
	case COLOR_GREY2_COLOR:
		return color_level[COLOR_GREY2_COLOR];
	case COLOR_BLACK_COLOR:
		return color_level[COLOR_BLACK_COLOR];
	default:
		return color_level[COLOR_WHITE_COLOR];
	}
}

/********************************************************
* Function:	UIDeleteAllAppObjects
* Purpose:		This function is called to delete all objects of a
Application
* Scope:       Application
* Input:       None
* Output:      None
* Return:		None
* Comment:     None
*********************************************************/
void UIDeleteAllAppObjects()
{
	LinkListForm *temp = main_pointer;
	
	while (temp != NULL)
	{
		FormDeleteAllFormObjects(temp->form_id);
		temp = main_pointer;
	}
}

/********************************************************
* Function:	UIGetUndoStatus
* Purpose:		This function is called to get the undo status
Application
* Scope:       Application
* Input:       None
* Output:      None
* Return:		undo_action		
* Comment:     None
*********************************************************/
BYTE UIGetUndoStatus()
{
	return undo_action;
}


/********************************************************
* Function:    UICheckObjectPopupStatus
* Purpose:     This function is called to check the popup status
of Menu object and Popup Trigger object
* Scope:       Application
* Input:       None
* Output:      menu_status
popup_status
* Return:      None
* Comment:     None
*********************************************************/
Err UICheckObjectPopupStatus(BOOLEAN *menu_popup_status, BOOLEAN *popup_popup_status)
{
	if (menu_popup_status)
		*menu_popup_status = menu_status;
	if (popup_popup_status)
		*popup_popup_status = popup_status;
	return TRUE;
}


void GetUIVariable(BOOLEAN **menu_s, EvtType **old_e, Keyboard **key, BOOLEAN **gf_p, BYTE **inlay_s, BOOLEAN **popup_s)
{
	*menu_s = &menu_status;
	*old_e = &old_event;
	*key = &keyboard;
	*gf_p = &gf_popup;
	*inlay_s = &inlay_status;
	*popup_s = &popup_status;
	
}

void SysSetCustomInsertFunction(void* func_ptr)
{
	void** pInsertTextFunction = (void**) &InsertTextFunction;
	*pInsertTextFunction = func_ptr;
}

void SysSetCustomBackspaceFunction(void* func_ptr)
{
	void** pBackspaceFunction = (void**) &BackspaceFunction;
	*pBackspaceFunction = func_ptr;
}

void UIPrintMallocCounter()
{
    return;
}

void UIResetMallocCounter()
{
    return;
}

void DummyDummy()
{
    return;
}

