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

#include "stdafx.h"

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

extern int totala, totalf;
extern BOOLEAN gf_popup, battery_popup;

/*********************************************************************
* Function: FormPointInObject
* Purpose: 	To check whether the coordinates that passed to the
*			function is within the boundary of the object or not
* Scope: 	OS
* Input: 	object_id 		DBID of the UI object
*			x_coord 		the window relative x-coordinate
*			y_coord 		the window relative y-coordinate
* Output: 	None
* Return: 	Return True if no error
*			ERR_UI_RES_NOT_FOUND - Invalid object ID
*			ErrUIInvInputCoord - Invalid input coordinate
* Comment: 	None
**********************************************************************/
Err FormPointInObject(ObjectID object_id, SHORT x_coord, SHORT y_coord)
{
	void *addr;
    Table *table_ptr;
	BYTE object_type;
	ObjectBounds bounds;
	USHORT row_number, col_number, cell_number;
	
	if (UISearchForAddress(object_id,&object_type,&addr) != TRUE) return	ERR_UI_RES_NOT_FOUND;
	if (FormGetObjectBounds(object_id,&bounds) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	switch (object_type)
	{
	case CONTROL: /* Control object */
		if (((Control *)addr)->control_attr.control_drawn == FALSE) return FALSE;
		/* General Control Case */
		if (((Control *)addr)->identification.table_related == 0xFFFF)
			bounds = ((Control *)addr)->bounds;
		else
		{	/* Check if the relative window is enabled & drawn on screen */
			if (UISearchForAddress(((Control *)addr)->identification.table_related,&object_type,(void**)&table_ptr) !=TRUE) return ERR_UI_RES_NOT_FOUND;
			if (((Table *)table_ptr)->table_attr.table_drawn == FALSE) return FALSE;
			if (((Table *)table_ptr)->table_attr.table_enable == FALSE) return FALSE;
			bounds = ((Control *)addr)->screen_bounds;
		}
		if (((Control *)addr)->control_style == 4 && ((ControlTemplatePopupTrigger * )(((Control *)addr)->control_template))->control_value)
		{
			ControlSavePopupBounds(((Control*)addr)->identification.ui_object_id);
			bounds = ((ControlTemplatePopupTrigger*)(((Control*)addr)->control_template))->popuped;
			bounds.height = POPUP_HIGHLIGHT_BORDER + ((FONT_HEIGHT[0]+2) * ((ControlTemplatePopupTrigger * )(((Control *)addr)->control_template))->popup_num_objects) -1;
		}
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case FIELD:
		if (((Field*)addr)->identification.table_related == 0xFFFF) bounds = ((Field*)addr)->bounds;
		else
		{
			/* Check if the relative window is enabled & drawn on screen */
			if (UISearchForAddress(((Table *)addr)->identification.table_related,&object_type,(void**)&table_ptr) !=TRUE) return ERR_UI_RES_NOT_FOUND;
			if (((Table *)table_ptr)->table_attr.table_drawn == FALSE) return FALSE;
			if (((Table *)table_ptr)->table_attr.table_enable == FALSE) return FALSE;
			bounds = ((Field*)addr)->screen_bounds;
		}
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case LIST:
		if (ListClickedRegion((List*)addr,x_coord, y_coord) == 1 ||
			ListClickedRegion((List*)addr,x_coord, y_coord) == 2 ||
			ListSearchSelectedItem((List*)addr,x_coord, y_coord) >= 0)
			return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case TABLE:	/* Table object */
		return TableGetClickedCell(object_id,x_coord,y_coord,&row_number,&col_number,&cell_number);
	case BITMAP: /* Bitmap object */
		if (((Bitmap*)addr)->identification.table_related == 0xFFFF) bounds = ((Bitmap*)addr)->bounds;
		else
		{
			/* Check if the relative window is enabled & drawn on screen */
			if (UISearchForAddress(((Table *)addr)->identification.table_related,&object_type,(void**)&table_ptr) !=TRUE) return ERR_UI_RES_NOT_FOUND;
			if (((Table *)table_ptr)->table_attr.table_drawn == FALSE) return FALSE;
			if (((Table *)table_ptr)->table_attr.table_enable == FALSE) return FALSE;
			bounds = ((Bitmap *)addr)->screen_bounds;
		}
		
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case MENU:
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case SCHLINE:
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case SCROLLBAR:
		bounds = ((Scrollbar*)addr)->bounds;
		if (((Scrollbar *)addr)->scrollbar_clicked_region == SCROLLCAR_REGION)
		{
			bounds.xcoord -= SCROLL_EXT_WIDTH;
			bounds.width += (SCROLL_EXT_WIDTH *2);
		}
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	case TEXTBOX:
		if (((Textbox*)addr)->identification.table_related == 0xFFFF) bounds = ((Textbox*)addr)->bounds;
		else
		{
			/* Check if the relative window is enabled & drawn on screen */
			if (UISearchForAddress(((Table *)addr)->identification.table_related,&object_type,(void**)&table_ptr) !=TRUE) return ERR_UI_RES_NOT_FOUND;
			if (((Table *)table_ptr)->table_attr.table_drawn == FALSE) return FALSE;
			if (((Table *)table_ptr)->table_attr.table_enable == FALSE) return FALSE;
			bounds = ((Textbox*)addr)->screen_bounds;
		}
		if (x_coord >= bounds.xcoord && x_coord < bounds.xcoord+bounds.width &&
			y_coord >= bounds.ycoord && y_coord < bounds.ycoord+bounds.height) return TRUE;
		else return ERR_UI_INV_INPUT_COORD;
	}
	return FALSE;
}
/*********************************************************************
* Function: 	FormGetObjectBounds
* Purpose: 		This function is used to find out the bounds of the
* 			  	specified UI object
* Scope: 		Application/OS
* Input: 		object_id - DBID of the UI object
* Output: 		bounds - Pointer to the bounds structure
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		None
**********************************************************************/
Err FormGetObjectBounds(ObjectID object_id, ObjectBounds *bounds)
{
	void *addr;
	BYTE object_type;
	
	if (UISearchForAddress(object_id,&object_type,&addr) == TRUE)
	{	/* Search for the correct type */
		switch (object_type)
		{
		case FORM: *bounds = ((Form*)addr)->bounds;break;
		case CONTROL: *bounds = ((Control*)addr)->bounds;break;
		case FIELD: *bounds = ((Field*)addr)->bounds;break;
		case LIST: *bounds = ((List*)addr)->bounds;break;
		case MENU: *bounds = ((Menu*)addr)->bounds;break;
		case SCROLLBAR: *bounds = ((Scrollbar*)addr)->bounds;break;
		case TABLE: *bounds = ((Table*)addr)->bounds;break;
		case SCHLINE: *bounds = ((Schline*)addr)->bounds;break;
		case STRING: *bounds = ((String*)addr)->bounds;break;
		case BITMAP: *bounds = ((Bitmap*)addr)->bounds;break;
		case LINE: *bounds = ((Line*)addr)->bounds;break;
		}
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	FormDispatchEvent
* Purpose: 	this function is a callback function for all
application event handler functions
* Scope:		Application/Internal
* Input:		Event		received event
* Output:		None
* Return:		Return TRUE if no error
FALSE if error
* Comment:     None
*********************************************************/
BOOLEAN (*FormDispatchEvent)(EvtType *Event);

/********************************************************
* Function:	FormPopupForm
* Purpose: 	this function is called to switch the current
form to other specific form and draw it on the screen
* Scope:		Application/Internal
* Input:		form_id		DBID of the new form object
* Output:		None
* Return:		Return TRUE if no error
ERR_UI_RES_NOT_FOUND  - Invalid object ID
* Comment: 	It is assumed that the data of the form is
*				already loaded in the memory
*********************************************************/
Err FormPopupForm(ObjectID form_id)
{
    Err         Error;
    ObjectID    form_org_id;    
	
    Error = FormGetActiveFormID(&form_org_id);
	
	LcdEnableInsertPt(FALSE,0,0,0);
    old_event.eventType = NULL_EVENT;
	
	menu_status = FALSE;
	popup_status = FALSE;
	
    if (!gf_popup && !battery_popup && keyboard_status == TRUE) 
    {
        EvtAppendEvt(EVT_KEYBOARD_STATUS, 0, 0, 0, NULL);
        keyboard_status = FALSE;
        KeyboardRestoreBitBehind();
    }
	
	/*to check whether the form is already put in the Lookup Table */
    if (Error == TRUE)
        EvtAppendEvt(EVT_FORM_INACTIVE, form_org_id, 0, 0, NULL);
	EvtAppendEvt(EVT_FORM_LOAD, form_id, 0, 0, NULL);
	EvtAppendEvt(EVT_FORM_OPEN, form_id, 0, 0, NULL);
    EvtAppendEvt(EVT_FORM_ACTIVE, form_id, 0, 0, NULL);
	return TRUE;
}
/*********************************************************************
* Function: 	FormDrawForm
* Purpose: 		The form and all the objects of the form are drawn on
*			  	the display
* Scope: 		Application
* Input: 		form_id		DBID of the UI object
* Output: 		None
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment:      If form_save_behind attribute is set, then the region
*			    behind the form will be store by calling FormSaveBehindBits
***********************************************************************/
Err FormDrawForm(ObjectID form_id)
{
	Form *addr;
	void *pointer;
	BYTE object_type,ui_object_type;
	USHORT num_of_objects;
	WORD count;
	ObjectID ui_object_id;
	BOOLEAN found = FALSE;
    BOOLEAN table_found = FALSE;
	BYTE num_table_objects = 0;
	ObjectID table_id[100];
	WORD i = 0;
	
	/* Get the number of object in the specified form */
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	addr->form_attr.form_drawn = TRUE;
	FormEraseForm(form_id);
	addr->form_attr.form_drawn = TRUE;
	num_of_objects = addr->form_num_objects;
	
	switch (addr->form_style)
	{
	case BACKGROUND: break;
	case NORMAL_FORM: FormDrawNormalForm(addr); break;
	default : FormDrawDialog(addr); break;
	}
	/* for loop is used in order to initialise each objects in a form*/
	count = 0;
	while (count < num_of_objects)
	{
		found = FALSE;
		ui_object_id = addr->form_objects_list[count].object_id;
		ui_object_type = addr->form_objects_list[count].object_type;
		if (UISearchForAddress(ui_object_id,&object_type,&pointer) == TRUE) found = TRUE;
		switch (ui_object_type)
		{
		case CONTROL:
			if (found == FALSE)
				ControlInitControl(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Control*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((Control*)pointer)->control_attr.control_visible == TRUE)
					ControlDrawControl(ui_object_id);
				if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case FIELD:
			if (found == FALSE)
				FieldInitField(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Field*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((Field*)pointer)->field_attr.field_visible == TRUE)
					FieldDrawField(ui_object_id);
				if (((Field*)pointer)->field_attr.field_insert_pt_visible)
					LcdEnableInsertPt(TRUE,((Field*)pointer)->field_insert_pt_x,((Field*)pointer)->field_insert_pt_y, ((Field*)pointer)->field_font_id);
				
				if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case LIST:
			if (found == FALSE)
				ListInitList(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((List*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((List*)pointer)->list_attr.list_visible == TRUE)
				{  				  
					((List*)pointer)->list_highlighted_item = ((List*)pointer)->list_selected_item;
					ListDrawList(ui_object_id);
				}
				if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case MENU:
			if (found == FALSE)
			{
				MenuInitMenu(ui_object_id);
			}
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			((Menu*)pointer)->menu_attr.menu_drawn = FALSE;
			break;
		case SCROLLBAR:
			if (found == FALSE)
				ScrollbarInitScrollbar(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Scrollbar*)pointer)->scrollbar_attr.scrollbar_visible == TRUE)
				ScrollbarDrawScrollbar(ui_object_id);
			if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);		  
			break;
		case TABLE:
			if (found == FALSE)
				TableInitTable(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Table*)pointer)->table_attr.table_visible == TRUE)
				table_found = TRUE;
			table_id[num_table_objects] = ((Table*)pointer)->identification.ui_object_id;
			num_table_objects ++;
			break;
		case SCHLINE:
			if (found == FALSE)
                SchlineInitSchline(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Schline*)pointer)->schline_attr.schline_visible == TRUE)				
                SchlineDrawSchline(ui_object_id);
			if (addr->form_focus == ui_object_id) 
                FormObjectSetFocus(ui_object_id);
			break;
		case STRING:
			if (found == FALSE)
                StringInitString(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((String*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((String*)pointer)->string_attr.string_visible == TRUE)
					StringDrawString(ui_object_id);
				if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case BITMAP:
			if (found == FALSE)
				BitmapInitBitmap(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Bitmap*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((Bitmap*)pointer)->bitmap_attr.bitmap_visible == TRUE)
					BitmapDrawBitmap(ui_object_id);
				if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case LINE:
			if (found == FALSE)
				LineInitLine(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Line*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((Line*)pointer)->line_attr.line_visible == TRUE)
					LineDrawLine(ui_object_id);
                if (addr->form_focus == ui_object_id) FormObjectSetFocus(ui_object_id);
			}
			break;
		case TEXTBOX:
			if (found == FALSE)
				TextboxInitTextbox(ui_object_id);
			UISearchForAddress(ui_object_id,&object_type,&pointer);
			if (((Textbox*)pointer)->identification.table_related == 0xFFFF)
			{
				if (((Textbox*)pointer)->textbox_attr.textbox_visible == TRUE)
                    TextboxDrawTextbox(ui_object_id);
				if (((Textbox*)pointer)->textbox_attr.textbox_insert_pt_visible)
                    LcdEnableInsertPt(TRUE,((Textbox*)pointer)->textbox_insert_pt_x,((Textbox*)pointer)->textbox_insert_pt_y, ((Textbox*)pointer)->textbox_font_id);
				if (addr->form_focus == ui_object_id)
                    FormObjectSetFocus(ui_object_id);
			}
			break;
       	}
		count++;
	}
    if (table_found)
    {
		i = num_table_objects;
		while (i)
		{
			i--;
			TableEraseTable(table_id[i]);
			TableDrawTable(table_id[i]);
		}
		if (addr->form_focus == ui_object_id)
			FormObjectSetFocus(ui_object_id);
    }
	return TRUE;
}
/********************************************************
* Function:	FormSetEventHandler
* Purpose:		to set the event handler callback routine for
the spcecified form
* Scope:		Application
* Input:		form_id		the DBID of the form
function	the address of the function
* Output:		None
* Return:		Error Code
* Comment:		None
*********************************************************/
Err FormSetEventHandler(ObjectID form_id, void **src_func, void *func)
{
	Form *form_addr;
	BYTE object_type;
	if (UISearchForAddress(form_id,&object_type,(void **)&form_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*src_func = func;
    form_loaded_once = 1;
	return TRUE;
}
/********************************************************
* Function:	FormGetActiveFormID
* Purpose:		to get the DBID of the current active form
* Scope:		Application
* Input:		void
* Output:		form_id 	Pointer to DBID of the active form
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormGetActiveFormID(ObjectID * form_id)
{
	LinkListForm *temp;
	temp = main_pointer;
	while (temp !=NULL)
	{
		if (temp->current_form->form_attr.form_active == 1)
		{
			*form_id = temp->current_form->identification.ui_object_id;
			return TRUE;
		}
		else
			temp = temp->next;
	}
	return ERR_UI_OBJECT_ID_NOT_FOUND;
}
/********************************************************
* Function:	FormSetActiveForm
* Purpose:	    This function is called in order to
set the specific form to be active and update the
LinkList
* Scope:		Application/Internal
* Input:		form_id  the DBID of the form object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
ERR_UI_OBJECT_NOT_FOUND
* Comment:		None
*********************************************************/
Err FormSetActiveForm(ObjectID form_id)
{
    ObjectID active_form_id = 0;
	BYTE object_type;
	Form *form_ptr;
	LinkListForm *temp = main_pointer;
	LookupTable *temp1 = lookup_table_ptr;
	
	/*Firstly, the current active form is set to be inactive*/
    if (FormGetActiveFormID(&active_form_id) == TRUE)
    {
        if (UISearchForAddress(active_form_id,&object_type,(void**)&form_ptr) == TRUE)
        {
            if (object_type == FORM)
                form_ptr->form_attr.form_active = FALSE;
        }
        else return ERR_UI_OBJECT_NOT_FOUND;
    }
	
	if (UISearchForAddress(form_id, &object_type,(void**)&form_ptr) != TRUE) return ERR_UI_OBJECT_NOT_FOUND;
	while (temp != NULL)
	{
		if (temp->form_id == form_id)
		{
			((Form*)(temp->current_form))->form_attr.form_active = TRUE;
			return TRUE;
		}
		else temp = temp->next;
	}
	return ERR_UI_OBJECT_NOT_FOUND;
}
/********************************************************
* Function:	FormEraseForm
* Purpose:	    to erase the drawn form object on the display
* Scope:		Application
* Input:		form_id		DBID of the form object
* Output:		None
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormEraseForm(ObjectID form_id)
{
	Form *addr;
    void *pointer;
	ObjectBounds temp;
	BYTE object_type;
	USHORT count = 0;
    ObjectID ui_object_id;
    BYTE ui_object_type;
	
	if (UISearchForAddress (form_id,&object_type,(void**)&addr)==TRUE)
	{
		/* if the required form is active and drawn on the display */
		if (addr->form_attr.form_drawn == TRUE)
		{
			temp = addr->bounds; /* get the bounds of the form */
			LcdEraseRegion(&temp); /* erase the bounds area */
			addr->form_attr.form_drawn = FALSE;
			/* the following loop is to set the drawn attribute of
			all different objects to FALSE */
			for(count=0;count<addr->form_num_objects;count++)
			{
				ui_object_id = addr->form_objects_list[count].object_id;
				ui_object_type = addr->form_objects_list[count].object_type;
				if (UISearchForAddress(ui_object_id,&object_type,&pointer) != TRUE) return ERR_UI_RES_NOT_FOUND;
				switch (ui_object_type)
				{
				case CONTROL:
					((Control*)pointer)->control_attr.control_drawn = FALSE;
					break;
				case FIELD:
					((Field*)pointer)->field_attr.field_drawn = FALSE;
					break;
				case LIST:
					((List*)pointer)->list_attr.list_drawn = FALSE;
					break;
				case MENU:
					((Menu*)pointer)->menu_attr.menu_drawn = FALSE;
					break;
				case SCROLLBAR:
					((Scrollbar*)pointer)->scrollbar_attr.scrollbar_drawn = FALSE;
					break;
				case TABLE:
					TableEraseTable(ui_object_id);
					break;
				case SCHLINE:
					((Schline*)pointer)->schline_attr.schline_drawn = FALSE;
					break;
				case STRING:
					((String*)pointer)->string_attr.string_drawn = FALSE;
					break;
				case BITMAP:
					((Bitmap*)pointer)->bitmap_attr.bitmap_drawn = FALSE;
					break;
				case LINE:
					((Line*)pointer)->line_attr.line_drawn = FALSE;
					break;
				}
			}
		}
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	FormSetControlGroupSelection
* Purpose:		to check or push the checkbox or pushbutton
* Scope:		Application
* Input:		form_id		the DBID of the form object
object_id	the DBID of the checkbox or pushbutton
object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:		By using this function to select a particular
control object, then other objects having the same group
number are cleared and the display will be updated correspondingly
too
*********************************************************/
Err FormSetControlGroupSelection(ObjectID form_id,ObjectID object_id)
{
	Form *form_ptr;
	Control *control_ptr;
	Control *object_ptr;
	BYTE target_object_style;
	USHORT target_object_groupid;
	WORD i;
	USHORT num_of_objects = 0;
	BOOLEAN original_value;
	BYTE object_type;
	
	/*check whether the passed-in form_id and object_id is valid or not*/
	if (UISearchForAddress(form_id,&object_type,(void**)&form_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (UISearchForAddress(object_id,&object_type,(void**)&object_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	target_object_style = object_ptr->control_style;
	switch (target_object_style)
	{
	/* get the group id of the passed-in object and the control value of
		the object */
	case PUSH_BUTTON:
		target_object_groupid = ((ControlTemplatePushButton*)((object_ptr)->control_template))->push_button_group_id;
		original_value = ((ControlTemplatePushButton*)((object_ptr)->control_template))->control_value;
		break;
	case CHECKBOX:
		target_object_groupid = ((ControlTemplateCheckBox*)(object_ptr->control_template))->checkbox_group_id;
		original_value = ((ControlTemplateCheckBox*)((object_ptr)->control_template))->control_value;
		break;
	}
	i = form_ptr->form_num_objects;
	while (i)
	{
		i--;
		if (form_ptr->form_objects_list[i].object_type != CONTROL)
			continue;
		if (UISearchForAddress(form_ptr->form_objects_list[i].object_id,&object_type,(void**)&control_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
		if (control_ptr->control_style != object_ptr->control_style)
			continue;
		/* to set all the push button and checkboxes which has the same group id to FALSE */
		/* and redraw the button */
		switch (control_ptr->control_style)
		{
		case PUSH_BUTTON:
			if (((ControlTemplatePushButton*)(control_ptr->control_template))->push_button_group_id == target_object_groupid)
			{
				((ControlTemplatePushButton*)(control_ptr->control_template))->control_value = FALSE;
				if (form_ptr->form_attr.form_active == TRUE) ControlDrawControl(control_ptr->identification.ui_object_id);
				num_of_objects++;
			}
			break;
		case CHECKBOX:
			if (((ControlTemplateCheckBox*)(control_ptr->control_template))->checkbox_group_id == target_object_groupid)
			{
				((ControlTemplateCheckBox*)(control_ptr->control_template))->control_value = FALSE;
				if (form_ptr->form_attr.form_active == TRUE)
					ControlDrawControl(control_ptr->identification.ui_object_id);
				num_of_objects++;
			}
			break;
		}
	}
	/* if there is mroe than one push button or check box that have the same group id
	then the control value of the passed-in object is set to TRUE*/
	if (num_of_objects > 1)
	{
		switch (object_ptr->control_style)
		{
		case PUSH_BUTTON:
			((ControlTemplatePushButton*)((object_ptr)->control_template))->control_value = TRUE;
			break;
		case CHECKBOX:
			((ControlTemplateCheckBox*)((object_ptr)->control_template))->control_value = TRUE;
			break;
		}
	}
	else /*if there is only one push button or checkbox that has unique group id
		/*then the control value of the control object is toggled */
	{
		switch (object_ptr->control_style)
		{
		case PUSH_BUTTON:
			((ControlTemplatePushButton*)((object_ptr)->control_template))->control_value = !original_value;
			break;
		case CHECKBOX:
			((ControlTemplateCheckBox*)((object_ptr)->control_template))->control_value = !original_value;
			break;
		}
	}
	/*finally the passed-in object is redrawn on the display if the current form is on */
	if (form_ptr->form_attr.form_active == TRUE)
		ControlDrawControl(object_ptr->identification.ui_object_id);
	return TRUE;
}
/********************************************************
* Function:	FormGetNumberOfObjects
* Purpose:		to get the number of objects in the specified form
* Scope:		Application/Internal
* Input:		form_id		the DBID of the form object
* Output:		num_objects	Pointer to value of the number
of objects
* Return:  	Error code
* Comment:		None
*********************************************************/
Err FormGetNumberOfObjects(ObjectID form_id,USHORT *num_objects)
{
	Form *addr;
	BYTE object_type;
	if (UISearchForAddress (form_id,&object_type, (void**)&addr)==TRUE)
	{
		*num_objects = addr->form_num_objects;
		return TRUE;
	}
	else return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	FormGetObjectPointer
* Purpose:	  	to get pointer to the structure of the
object in the form
* Scope:		Application
* Input:		object_id	the DBID of the object
* Output:		address		Pointer to the data structure
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err FormGetObjectPointer(ObjectID object_id, BYTE *type, void **address)
{
	void *addr;
	BYTE object_type;
    if (UISearchForAddress (object_id,&object_type, (void**)&addr) == TRUE)
	{
		*address = addr;
		*type = object_type;
		/* The pointer of the object is passed out */
		return TRUE;
	}
	*address = NULL;
	return ERR_UI_RES_NOT_FOUND;
}
/*********************************************************************
* Function: 	FormGotoForm
* Purpose: 		This function is used to erase and delete a orginial
*			  	form, and then initial and draw a new form on screen
* Scope: 		Application
* Input: 		form_id  	DBID of the new form object
* Output: 		None
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		Call this function if application needs to close the
*			  	current form and then load and draw a new form on display.
*			  	The from_active attribute in the new form should be
*			  	checked before the FormGotoForm is called. If the wanted
*			  	form is already loaded and initialised, then
*			  	FormPopupForm function should be called insteaded.
**********************************************************************/
Err FormGotoForm(ObjectID form_id)
{
	ObjectID form_org_id;
	
	LcdEnableInsertPt(FALSE,0,0,0);
	menu_status = FALSE;
	keyboard_status = FALSE;
	popup_status = FALSE;
	
	/* Get the orginial form ID */
	FormGetActiveFormID(&form_org_id);
	/* Append a form close event to the event quene */
	EvtAppendEvt(EVT_FORM_CLOSE, form_org_id, 0, 0, NULL);
	EvtAppendEvt(EVT_FORM_LOAD, form_id, 1, 0, NULL);
	
	/* Append a form open event to the event quene */
	EvtAppendEvt(EVT_FORM_OPEN, form_id, 0, 0, NULL);
	return TRUE;
}

/********************************************************
* Function:	FormSetFormActiveObject
* Purpose:		to set the active form object
* Scope:		Application
* Input:		form_id		the DBID of the form
object_id   the DBID of the object
* Output:	None
* Return:	TRUE
ERR_UI_OBJECT_NOT_MATCH
ERR_UI_RES_NOT_FOUND
* Comment:	None
*********************************************************/
Err FormSetFormActiveObject(ObjectID form_id, ObjectID object_id)
{
	BYTE object_type;
	Form *addr;
	USHORT i;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	for (i = 0; i<addr->form_num_objects; i++)
	{
		if (addr->form_objects_list[i].object_id == object_id)
			addr->form_focus = object_id;
	}
	return ERR_UI_OBJECT_NOT_MATCH;
}

/********************************************************
* Function:	FormSetObjectPosition
* Purpose:		to set the position of the specified object
* Scope:		Application
* Input:		object_id	the DBID of the object
x			the
* Output:
* Return:	Error Code
* Comment:	None
*********************************************************/
Err FormSetObjectPosition(ObjectID object_id, SHORT x, SHORT y)
{
	void *addr;
	BYTE object_type;
	
	if (UISearchForAddress(object_id,&object_type,&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	switch (object_type)
	{
	case FORM:
		((Form*)addr)->bounds.xcoord = x;
		((Form*)addr)->bounds.ycoord = y;
		break;
	case CONTROL:
		((Control*)addr)->bounds.xcoord = x;
		((Control*)addr)->bounds.ycoord = y;
		break;
	case FIELD:
		((Field*)addr)->bounds.xcoord = x;
		((Field*)addr)->bounds.ycoord = y;
		break;
	case LIST:
		((List*)addr)->bounds.xcoord = x;
		((List*)addr)->bounds.ycoord = y;
		break;
	case MENU:
		((Menu*)addr)->bounds.xcoord = x;
		((Menu*)addr)->bounds.ycoord = y;
		break;
	case SCROLLBAR:
		((Scrollbar*)addr)->bounds.xcoord = x;
		((Scrollbar*)addr)->bounds.ycoord = y;
		break;
	case TABLE:
		((Table*)addr)->bounds.xcoord = x;
		((Table*)addr)->bounds.ycoord = y;
		break;
	case SCHLINE:
		((Schline*)addr)->bounds.xcoord = x;
		((Schline*)addr)->bounds.ycoord = y;
		break;
	case STRING:
		((String*)addr)->bounds.xcoord = x;
		((String*)addr)->bounds.ycoord = y;
		break;
	case BITMAP:
		((Bitmap*)addr)->bounds.xcoord = x;
		((Bitmap*)addr)->bounds.ycoord = y;
		break;
	case LINE:
		((Line*)addr)->bounds.xcoord = x;
		((Line*)addr)->bounds.ycoord = y;
		break;
	}
	return TRUE;
}
/*********************************************************************
* Function: 	FormCheckStyle
* Purpose: 		To find out the style of the specified form
* Scope: 		Application
* Input: 		form_id  	DBID of the specified form object
* Output: 		form_style  the type of the form object
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		The type of the form can be 0 -normal form,
*			  	1 -Information dialog, 2 -confirm dialog or
*			  	3 -warning dialog
**********************************************************************/
Err FormCheckStyle(ObjectID form_id, BYTE *form_style)
{
	Form *addr;
	BYTE object_type;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*form_style = addr->form_style;
	return TRUE;
}
/********************************************************
* Function:	FormSetDialogTitle
* Purpose:     send the title of the dialog box if the
form type is dialog
* Scope:		Application
* Input:       form_id 	DBID of the spceified form
title_text	Pointer to null terminated char string
* Output:		None
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormSetDialogTitle (ObjectID form_id,BYTE *title_text)
{
	Form *form_ptr;
	BYTE object_type;
	USHORT text_length;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&form_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	text_length = strlen(title_text);
    if (form_ptr->form_dialog_title)
		qfree(form_ptr->form_dialog_title);
    form_ptr->form_dialog_title = (BYTE*)qmalloc((text_length+1)*sizeof(BYTE));
	strcpy(form_ptr->form_dialog_title,title_text);
	return TRUE;
}
/********************************************************
* Function:	FormSaveAllForms
* Purpose:		to send out a EvtFormSaveEvent to all open forms
* Scope:		Application
* Input:       None
* Output:		None
* Return:		None
* Comment:		None
*********************************************************/
void FormSaveAllForms()
{
	EvtAppendEvt(EVT_FORM_SAVE, 0, 0, 0, NULL);
}
/*********************************************************************
* Function: 	FormGetControlValue
* Purpose: 		To get the control value of the specify control object
* Scope: 		Application
* Input: 		control_id   DBID of the control object
* Output: 		ctl_value    Pointer to BOOLEAN value that shows
the control value of the control object
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		None
**********************************************************************/
Err FormGetControlValue(ObjectID control_id, BOOLEAN *ctl_value)
{
	Control *control_addr;
	BYTE object_type;
	
	if (UISearchForAddress(control_id,&object_type,(void**)&control_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	switch (control_addr->control_style)
	{
	case 0: *ctl_value = ((ControlTemplateButton *)(control_addr->control_template))->control_value;
		return TRUE;
	case 1: *ctl_value = ((ControlTemplatePushButton *)(control_addr->control_template))->control_value;
		return TRUE;
	case 3: *ctl_value = ((ControlTemplateCheckBox *)(control_addr->control_template))->control_value;
		return TRUE;
	case 4: *ctl_value = ((ControlTemplatePopupTrigger *)(control_addr->control_template))->control_value;
		return TRUE;
	default:return ERR_UI_OBJECT_NOT_MATCH;
	}
}
/*********************************************************************
* Function: 	FormGetActiveObject
* Purpose: 		To find out the ID of the UI object that has the focus
* Scope: 		Application
* Input: 		form_id 	DBID of the specified form object
* Output: 		active_id  	DBID of the active object
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		This function will return the ID of the UI object that
*			  	has the focus. If there is no object that has focus,
*			  	then -1 will be turned instead.
**********************************************************************/
Err FormGetActiveObject(ObjectID form_id, ObjectID *active_id)
{
	Form *addr;
	BYTE object_type;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) == TRUE)
	{
		*active_id = addr->form_focus;
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/*********************************************************************
* Function: 	FormSetFormActiveAtt
* Purpose: 		This function is used to set or reset the form_update
*			  	attribute of a specified form
* Scope: 		Application
* Input: 		form_id    DBID of the form object
*			  	set_value  TRUE when the specified form is set to active
*						   FALSE when the specified form is reset to
*						   inactive
* Output: 		None
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		None
**********************************************************************/
Err FormSetFormUpdateAtt(ObjectID form_id, BOOLEAN set_value)
{
	Form *addr;
	BYTE object_type;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) == TRUE)
	{
		addr->form_attr.form_updated = set_value;
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/*********************************************************************
* Function: 	FormSetObjectBounds
* Purpose: 		This function is used to set up the bounds of the
* 			  	specified UI object
* Scope: 		Application/Internal
* Input: 		object_id 	DBID of the UI object
* 			  	bounds 		Bounds structure
* Output: 		None
* Return: 		Return True if no error
*			  	ERR_UI_RES_NOT_FOUND - Invalid object ID
* Comment: 		The object with the new bounds will not be updated
*			  	automatically. FormDrawForm should then be called to
*			  	redraw the form.
**********************************************************************/
Err FormSetObjectBounds(ObjectID object_id, ObjectBounds bounds)
{
	void *addr;
	BYTE object_type;
	
	if (UISearchForAddress(object_id,&object_type,&addr) == TRUE)
	{	/* Search for the correct type */
		switch (object_type)
		{
		case FORM: ((Form*)addr)->bounds = bounds;break;
		case CONTROL: ((Control*)addr)->bounds = bounds;break;
		case FIELD:	((Field*)addr)->bounds = bounds;break;
		case LIST: ((List*)addr)->bounds = bounds;break;
		case MENU: ((Menu*)addr)->bounds = bounds;break;
		case SCROLLBAR: ((Scrollbar*)addr)->bounds = bounds;break;
		case TABLE: ((Table*)addr)->bounds = bounds;break;
		case SCHLINE: ((Schline*)addr)->bounds = bounds;break;
		case STRING: ((String*)addr)->bounds = bounds;break;
		case BITMAP: ((Bitmap*)addr)->bounds = bounds;break;
		case LINE: ((Line*)addr)->bounds = bounds;break;
		}
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	FormDeleteForm
* Purpose:		to free the memory that is allocated to
the form object. This function will be called after
receiving the EvtFormCloseEvent
* Scope:		Application
* Input:		form_id		DBID of the form object
* Output:		None
* Return:		Error code in UIErr.h
* Comment:     FormEraseForm function should be called before
calling FormDeleteForm
*********************************************************/
Err FormDeleteForm (ObjectID form_id)
{
	Form *addr;
	BYTE object_type;
	Err Error;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) == TRUE)
	{
		qfree(addr->form_objects_list);
		if (addr->save_behind.bitmap_data)
			qfree(addr->save_behind.bitmap_data);
		if (addr->form_dialog_title)
			qfree(addr->form_dialog_title);
		Error = UIDeleteLookupTableElement(form_id);
		if (Error !=TRUE) return Error;
		Error = UIDeleteLinkListFormElement(form_id);
		if (Error !=TRUE) return Error;
		qfree(addr);
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}

/********************************************************
* Function:	FormDeleteAllformObjects
* Purpose:		to free the memory that are allocated to the objects 
(including the form itself) in the the form object. 
* Scope:		Application
* Input:		form_id		DBID of the form object
* Output:		None
* Return:		Error code in UIErr.h
* Comment:     None
*********************************************************/
Err FormDeleteAllFormObjects(ObjectID form_id)
{
	Form *addr;
	BYTE object_type;
	WORD count;
	
	if (UISearchForAddress(form_id,&object_type,(void**)&addr) == TRUE)
	{
		count = addr->form_num_objects;
		while (count)
		{
			count--;
			switch(addr->form_objects_list[count].object_type)
			{
			case CONTROL: ControlDeleteControl(addr->form_objects_list[count].object_id);
				break;
			case FIELD: FieldDeleteField(addr->form_objects_list[count].object_id);
				break;
			case LIST: ListDeleteList(addr->form_objects_list[count].object_id);
				break;	
			case MENU: MenuDeleteMenu(addr->form_objects_list[count].object_id);
				break;
			case SCROLLBAR: ScrollbarDeleteScrollbar(addr->form_objects_list[count].object_id);
				break;
			case TABLE: TableDeleteTable(addr->form_objects_list[count].object_id);
				break;
			case SCHLINE: SchlineDeleteSchline(addr->form_objects_list[count].object_id);
				break;
			case STRING: StringDeleteString(addr->form_objects_list[count].object_id);
				break; 
			case BITMAP: BitmapDeleteBitmap(addr->form_objects_list[count].object_id);
				break;
			case TEXTBOX: TextboxDeleteTextbox(addr->form_objects_list[count].object_id);
				break;
			case LINE: LineDeleteLine(addr->form_objects_list[count].object_id);
				break;
			default: break;
			}
		}
		FormDeleteForm(form_id);
	}
	return ERR_UI_RES_NOT_FOUND;
}

/********************************************************
* Function:	FormObjectSetFocus
* Purpose:     To set the object that get the focus
* Scope:		Internal
* Input:       object_id   the DBID of the new object that will get the focus
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:		None
*********************************************************/
Err FormObjectSetFocus(ObjectID object_id)
{
    ObjectID form_id;
	ObjectID previous_active_id;
    Form *form_ptr;
	void *ptr1;
    void *ptr;
    BYTE object_type, previous_object_type;
	WORD i;
	
	FormGetActiveFormID(&form_id);
	
    if (UISearchForAddress(form_id,&object_type,(void**)&form_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	previous_active_id = form_ptr->form_focus;
	if (UISearchForAddress(previous_active_id,&previous_object_type,(void**)&ptr1) != TRUE) return ERR_UI_RES_NOT_FOUND;
	i = form_ptr->form_num_objects;
	while (i)
    {
		i--;
		if (form_ptr->form_objects_list[i].object_id == object_id)
		{
			if (UISearchForAddress(object_id,&object_type,(void**)&ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
			switch (object_type)
			{
			case CONTROL:
				undo_action = FALSE; 	
				backspace_undo.index = -1;
				((Control*)ptr)->control_attr.control_active = TRUE;
				form_ptr->form_focus = ((Control*)ptr)->identification.ui_object_id;
				return TRUE;
			case FIELD:
				undo_action = FALSE;
				backspace_undo.index = -1;
				((Field*)ptr)->field_attr.field_active = TRUE;
				form_ptr->form_focus = ((Field*)ptr)->identification.ui_object_id;
				if (((Field*)ptr)->field_attr.field_insert_pt_visible)
				{
					FieldSetInsertPointPositionByXY(((Field*)ptr)->identification.ui_object_id,
						((Field*)ptr)->field_insert_pt_x,
						((Field*)ptr)->field_insert_pt_y);
					LcdEnableInsertPt(TRUE,((Field*)ptr)->field_insert_pt_x,((Field*)ptr)->field_insert_pt_y,((Field*)ptr)->field_font_id );
				}   
				return TRUE;
			case LIST:
				undo_action = FALSE;
				backspace_undo.index = -1;
				((List*)ptr)->list_attr.list_active = TRUE;
				form_ptr->form_focus = ((List*)ptr)->identification.ui_object_id;
				return TRUE;
			case SCROLLBAR: 
				undo_action = FALSE;
				backspace_undo.index = -1;
				((Scrollbar*)ptr)->scrollbar_attr.scrollbar_active = TRUE;
				form_ptr->form_focus = ((Scrollbar*)ptr)->identification.ui_object_id;
				return TRUE;
			case TABLE:
				undo_action = FALSE;
				backspace_undo.index = -1;
				((Table*)ptr)->table_attr.table_active = TRUE;
				form_ptr->form_focus = ((Table*)ptr)->identification.ui_object_id;
				return TRUE;
			case SCHLINE:
				undo_action = FALSE;
				backspace_undo.index = -1;
				((Schline*)ptr)->schline_attr.schline_active = TRUE;
				form_ptr->form_focus = ((Schline*)ptr)->identification.ui_object_id;
				return TRUE;
			case BITMAP:
				undo_action = FALSE;               
				backspace_undo.index = -1;
				((Bitmap*)ptr)->bitmap_attr.bitmap_active = TRUE;
				form_ptr->form_focus = ((Bitmap*)ptr)->identification.ui_object_id;
				return TRUE;
			case TEXTBOX:
				undo_action = FALSE;
				backspace_undo.index = -1;
				((Textbox*)ptr)->textbox_attr.textbox_active = TRUE;
				form_ptr->form_focus = ((Textbox*)ptr)->identification.ui_object_id;
				if (((Textbox*)ptr)->textbox_attr.textbox_insert_pt_visible)
				{
					TextboxSetInsertPointPositionByXY(((Textbox*)ptr)->identification.ui_object_id,
						((Textbox*)ptr)->textbox_insert_pt_x,
						((Textbox*)ptr)->textbox_insert_pt_y);
					LcdEnableInsertPt(TRUE,((Textbox*)ptr)->textbox_insert_pt_x,((Textbox*)ptr)->textbox_insert_pt_y, ((Textbox*)ptr)->textbox_font_id);
				}   
				return TRUE;
			default: return TRUE;
			}
		}
    }
    return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	FormObjectReleaseFocus
* Purpose:     To release the focus of the object that is currently has the focus
* Scope:		Internal
* Input:       None
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:		None
*********************************************************/
Err FormObjectReleaseFocus(BYTE current_pressed_object_type)
{
    ObjectID form_id;
	Form *form_ptr;
    ObjectID previous_active_id;
    void *ptr;
    BYTE object_type;
	
    FormGetActiveFormID(&form_id);
    if (UISearchForAddress(form_id,&object_type,(void**)&form_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	previous_active_id = form_ptr->form_focus;
	if (UISearchForAddress(previous_active_id,&object_type,&ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	switch (object_type)
	{
	case CONTROL: undo_action = FALSE;
		((Control*)ptr)->control_attr.control_active = FALSE;
		break;
	case FIELD:   undo_action = FALSE;
		((Field*)ptr)->field_attr.field_active = FALSE;
		((Field*)ptr)->field_attr.field_insert_pt_visible = FALSE;
		LcdEnableInsertPt(FALSE,0,0,0);
		if (current_pressed_object_type == FIELD ||
			current_pressed_object_type == TEXTBOX)
		{
			((Field*)ptr)->field_attr.field_highlight = FALSE;
			((Field*)ptr)->field_highlight_length = 0;
			if (((Field*)ptr)->field_attr.field_drawn)
				FieldDrawField(previous_active_id);
			if (((Field*)ptr)->field_attr.field_insert_pt_visible)
				LcdEnableInsertPt(TRUE, ((Field*)ptr)->field_insert_pt_x, ((Field*)ptr)->field_insert_pt_y, ((Field*)ptr)->field_font_id);                            
			else LcdEnableInsertPt(FALSE,0,0,0);
		}
		break;
	case LIST:	undo_action = FALSE;
		((List*)ptr)->list_attr.list_active = FALSE;
		break;
	case SCROLLBAR: 
		undo_action = FALSE;
		((Scrollbar*)ptr)->scrollbar_attr.scrollbar_active = FALSE;
		break;
	case TABLE:	undo_action = FALSE;
		((Table*)ptr)->table_attr.table_active = FALSE;
		break;
	case SCHLINE: undo_action = FALSE;
		((Schline*)ptr)->schline_attr.schline_active = FALSE;
		break;
	case BITMAP:	undo_action = FALSE;
		((Bitmap*)ptr)->bitmap_attr.bitmap_active = FALSE;
		break;
	case TEXTBOX: undo_action = FALSE;
		((Textbox*)ptr)->textbox_attr.textbox_active = FALSE;
		((Textbox*)ptr)->textbox_attr.textbox_insert_pt_visible = FALSE;
		LcdEnableInsertPt(FALSE,0,0,0);
		if (current_pressed_object_type == FIELD ||
			current_pressed_object_type == TEXTBOX)
		{
			((Textbox*)ptr)->textbox_attr.textbox_highlight = FALSE;
			((Textbox*)ptr)->textbox_highlight_length = 0;
			if (((Textbox*)ptr)->textbox_attr.textbox_drawn)
				TextboxDrawTextbox(previous_active_id);
			if (((Textbox*)ptr)->textbox_attr.textbox_insert_pt_visible)
				LcdEnableInsertPt(TRUE, ((Textbox*)ptr)->textbox_insert_pt_x, ((Textbox*)ptr)->textbox_insert_pt_y, ((Textbox*)ptr)->textbox_font_id);                            
			else LcdEnableInsertPt(FALSE,0,0,0);
		}                 
		break;
	}
    return TRUE;
}
/********************************************************
* Function:	FormObjectRestoreFocus
* Purpose:     To restore the focus of the object that already has the focus
* Scope:		Internal
* Input:       None
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:		None
*********************************************************/
Err FormObjectRestoreFocus()
{
	ObjectID form_id;
	Form *form_ptr;
	void *ptr;
	BYTE object_type;
	
	FormGetActiveFormID(&form_id);
	if (UISearchForAddress(form_id,&object_type,(void**)&form_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (UISearchForAddress(form_ptr->form_focus, &object_type, &ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	switch (object_type)
	{
	case CONTROL:	undo_action = FALSE;
		((Control*)ptr)->control_attr.control_active = TRUE;
		break;
	case FIELD:   undo_action = FALSE;
		((Field*)ptr)->field_attr.field_active = TRUE;
		if (((Field*)ptr)->field_attr.field_drawn == TRUE)
			FieldDrawField(((Field*)ptr)->identification.ui_object_id);
		if (((Field*)ptr)->field_attr.field_insert_pt_visible)
		{
			FieldSetInsertPointPositionByXY(((Field*)ptr)->identification.ui_object_id,
				((Field*)ptr)->field_insert_pt_x,
				((Field*)ptr)->field_insert_pt_y);
			LcdEnableInsertPt(TRUE,((Field*)ptr)->field_insert_pt_x,((Field*)ptr)->field_insert_pt_y, ((Field*)ptr)->field_font_id);
		}
		break;
	case LIST:	undo_action = FALSE;
		((List*)ptr)->list_attr.list_active = TRUE;
		break;
	case SCROLLBAR:
		undo_action = FALSE;
		((Scrollbar*)ptr)->scrollbar_attr.scrollbar_active = TRUE;
		break;		  
	case TABLE:	undo_action = FALSE;
		((Table*)ptr)->table_attr.table_active = TRUE;
		break;
	case SCHLINE: undo_action = FALSE;
		((Schline*)ptr)->schline_attr.schline_active = TRUE;
		break;
	case BITMAP:	undo_action = FALSE;
		((Bitmap*)ptr)->bitmap_attr.bitmap_active = TRUE;
		break;
	case TEXTBOX: undo_action = FALSE;
		((Textbox*)ptr)->textbox_attr.textbox_active = TRUE;
		if (((Textbox*)ptr)->textbox_attr.textbox_drawn == TRUE)
			TextboxDrawTextbox(((Textbox*)ptr)->identification.ui_object_id);
		if (((Textbox*)ptr)->textbox_attr.textbox_insert_pt_visible)
		{
			TextboxSetInsertPointPositionByXY(((Textbox*)ptr)->identification.ui_object_id,
				((Textbox*)ptr)->textbox_insert_pt_x,
				((Textbox*)ptr)->textbox_insert_pt_y);
			LcdEnableInsertPt(TRUE,((Textbox*)ptr)->textbox_insert_pt_x,((Textbox*)ptr)->textbox_insert_pt_y, ((Textbox*)ptr)->textbox_font_id);
		}
		break;
	}
	return TRUE;
	}/********************************************************
	 * Function:	FormGetMenuID
	 * Purpose:     to get the menu ID of the current active form
	 * Scope:		Application
	 * Input:       form_id 	DBID of the spceified form
	 menu_id     Pointer to the menu ID
	 * Output:		None
	 * Return:		Error code
	 * Comment:		None
*********************************************************/
Err FormGetMenuID(ObjectID form_id,ObjectID *menu_id)
{
    BYTE object_type;
	USHORT count = 0;
	Form *addr;
	
    if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    for (count = 0; count <addr->form_num_objects;count++)
    {
        if ((addr->form_objects_list[count]).object_type == MENU)
        {
			*menu_id = (addr->form_objects_list[count]).object_id;
			return TRUE;
        }
    }
    return ERR_UI_OBJECT_NOT_FOUND;
}
/********************************************************
* Function:	FormDrawDialogBackground
* Purpose:  
* Scope:	OS
* Input:    None
* Output:	None
* Return:	Error code
* Comment:	None
*********************************************************/
void FormDrawDialogBackground(ObjectBounds *bounds, BYTE bg_color)
{
	SHORT draw_xcoord, draw_ycoord, draw_end_xcoord, draw_end_ycoord;
	ObjectBounds box;
	
	/* Draw the upper horizontal line */
	draw_xcoord = bounds->xcoord+DIALOG_RADIUS;
	draw_ycoord = bounds->ycoord;
	draw_end_xcoord = bounds->xcoord+bounds->width-DIALOG_RADIUS-1;
	draw_end_ycoord = bounds->ycoord;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	if (color_mode == GREYSCALE_MODE)
		LcdDrawLine(draw_xcoord,draw_ycoord+1,draw_end_xcoord,draw_end_ycoord+1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
	else	
		LcdDrawLine(draw_xcoord,draw_ycoord+1,draw_end_xcoord,draw_end_ycoord+1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);	
	
	
	/* Draw the lower horizontal line */
	draw_xcoord = bounds->xcoord+DIALOG_RADIUS;
	draw_ycoord = bounds->ycoord+bounds->height-1;
	draw_end_xcoord = bounds->xcoord+bounds->width-DIALOG_RADIUS-1;
	draw_end_ycoord = bounds->ycoord+bounds->height-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	if (color_mode == GREYSCALE_MODE)
		LcdDrawLine(draw_xcoord,draw_ycoord-1,draw_end_xcoord,draw_end_ycoord-1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
	
	/* Draw the left vertical line */
	draw_xcoord = bounds->xcoord;
	draw_ycoord = bounds->ycoord+DIALOG_RADIUS;
	draw_end_xcoord = bounds->xcoord;
	draw_end_ycoord = bounds->ycoord+bounds->height-DIALOG_RADIUS-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	if (color_mode == GREYSCALE_MODE)
		LcdDrawLine(draw_xcoord+1,draw_ycoord,draw_end_xcoord+1,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
	else
		LcdDrawLine(draw_xcoord+1,draw_ycoord,draw_end_xcoord+1,(draw_ycoord + 2 + bounds->height - 4 - 1),SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	
	
	/* Draw the right vertical line */
	draw_xcoord = bounds->xcoord+bounds->width-1;
	draw_ycoord = bounds->ycoord+DIALOG_RADIUS;
	draw_end_xcoord = bounds->xcoord+bounds->width-1;
	draw_end_ycoord = bounds->ycoord+bounds->height-DIALOG_RADIUS-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	if (color_mode == GREYSCALE_MODE)
		LcdDrawLine(draw_xcoord-1,draw_ycoord,draw_end_xcoord-1,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
	else
		LcdDrawLine(draw_xcoord-1,draw_ycoord,draw_end_xcoord-1,(draw_ycoord + 2 + bounds->height - 4 - 1),SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR], color_level[COLOR_GREY2_COLOR]);		
	
	box = *bounds;
	box.xcoord = bounds->xcoord+2;
	box.ycoord = bounds->ycoord+2;
	box.width  = bounds->width-4;
	box.height = bounds->height-4;
	LcdDrawBox(&box,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR],DRAW_FILL);
	if (color_mode == BLACK_AND_WHITE_MODE)
		LcdDrawLine((bounds->xcoord + DIALOG_RADIUS), (bounds->ycoord + bounds->height - DIALOG_RADIUS - 1), (bounds->xcoord + bounds->width - 1 - DIALOG_RADIUS),(bounds->ycoord + bounds->height - DIALOG_RADIUS - 1),SINGLE_LINE,NON_DOTTED_LINE, color_level[COLOR_WHITE_COLOR], color_level[COLOR_WHITE_COLOR]);
}

/*********************************************************************
* Function:	FormDrawDialog
* Purpose: 	To draw the outline of the dialog
* Scope: 	Application
* Input: 	addr	Pointer of the Form
* Output: 	None
* Return: 	None
*		   	None
* Comment:
***********************************************************************/
void FormDrawDialog(Form *addr)
{
	ObjectBounds bounds;
	SHORT draw_width;
	USHORT header;
	BitmapTemplate	bitmap;
	
	bounds = addr->bounds;
	FormDrawDialogBackground(&bounds, color_level[COLOR_GREY2_COLOR]);
	ControlDrawArc(&bounds,DRAW_NOT_FILL,DIALOG_RADIUS,color_level[COLOR_BLACK_COLOR]);
	
	if (addr->form_style == NON_BITMAP_DIALOG)
		header = NON_BITMAP_DIALOG_HEADER;
	else 
		header = BITMAP_DIALOG_HEADER;
	
	/* Draw the Horizontal box */
	if (color_mode == GREYSCALE_MODE)
	{
		bounds.xcoord += 3;	
		bounds.width  -= 6;
	}
	else
	{
		bounds.xcoord += 1;	
		bounds.width  -= 2;
	}				
	bounds.ycoord += header;	
	bounds.height -= (header + 3);
	LcdDrawBox(&bounds,color_level[COLOR_WHITE_COLOR], color_level[COLOR_WHITE_COLOR],FILL_EMPTY);
	
    if (color_mode == GREYSCALE_MODE)
    {
        bounds = addr->bounds;
        bounds.xcoord += 3;
        bounds.ycoord += header;
        bounds.width  -= 7;
        bounds.height -= (header + 4);
        LcdDrawBox(&bounds,color_level[COLOR_BLACK_COLOR], color_level[COLOR_WHITE_COLOR],FILL_EMPTY);
        LcdDrawLine(bounds.xcoord+bounds.width-1,bounds.ycoord,
			bounds.xcoord+bounds.width-1,bounds.ycoord+bounds.height-1,
			SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
        LcdDrawLine(bounds.xcoord+1,bounds.ycoord+bounds.height-1,
			bounds.xcoord+bounds.width-2,bounds.ycoord+bounds.height-1,
			SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
    }
	
	if (addr->form_style == NON_BITMAP_DIALOG)
	{
		/* Draw the Title of the dialog */		
		draw_width = StrGetWidth(addr->form_dialog_title,SMALL_FONT);
		bounds = addr->bounds;
		bounds.xcoord = addr->bounds.xcoord+(addr->bounds.width-draw_width)/2;
        bounds.ycoord += 3;
		bounds.width  = addr->bounds.width - (15*2);
		bounds.height = FONT_HEIGHT[0];
		LcdDrawFixedString(&bounds,addr->form_dialog_title,color_level[COLOR_WHITE_COLOR],color_level[COLOR_GREY2_COLOR],SMALL_FONT,DOTDOT,MARGIN_0);
	}
	else
	{
		bounds = addr->bounds;
		bitmap = addr->form_bitmap;
		bitmap.xcoord = bounds.xcoord+DIALOG_BORDER+2;
		bitmap.ycoord = bounds.ycoord+DIALOG_TOP_BORDER;
		LcdDrawBitmap(&bitmap,NOT_INVERT);
		bounds.xcoord = bitmap.xcoord+bitmap.width+DIALOG_TEXT_SEPARATOR-1;
		bounds.ycoord = bitmap.ycoord;
		bounds.width  -= (addr->form_bitmap.width + DIALOG_TEXT_SEPARATOR + DIALOG_BORDER*2 +12);
		bounds.height = FONT_HEIGHT[0];
		LcdDrawFixedString(&bounds,addr->form_dialog_title,color_level[COLOR_WHITE_COLOR],color_level[COLOR_GREY2_COLOR],SMALL_FONT,DOTDOT,MARGIN_0);
	}
}

/*********************************************************************
* Function:	FormDrawNormalForm
* Purpose: 	To draw the outline of the dialog
* Scope: 	Application
* Input: 	addr	Pointer of the Form
* Output: 	None
* Return: 	None
*		   	None
* Comment:
***********************************************************************/
void FormDrawNormalForm(Form *addr)
{
	ObjectBounds bg_form;
	BitmapTemplate	bitmap;
	
    bg_form = addr->bounds;
	
    if (color_mode == GREYSCALE_MODE)
    {
        LcdDrawBox(&bg_form, color_level[COLOR_BLACK_COLOR], color_level[COLOR_WHITE_COLOR], DRAW_NOT_FILL);   
        LcdDrawLine(bg_form.xcoord+1,bg_form.ycoord+bg_form.height-2,bg_form.xcoord+bg_form.width-2,
			bg_form.ycoord+bg_form.height-2,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR]);
        LcdDrawLine(bg_form.xcoord+bg_form.width-2,bg_form.ycoord+1,bg_form.xcoord+bg_form.width-2,
			bg_form.ycoord+bg_form.height-2,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR]);
        LcdDrawLine(bg_form.xcoord+2,bg_form.ycoord+FORM_TOP_HEIGHT+2,bg_form.xcoord+2,bg_form.ycoord+bg_form.height-4,
			SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
    }
	
    if (color_mode == GREYSCALE_MODE)
    {
        bg_form = addr->bounds;
        bg_form.xcoord += 2;
        bg_form.ycoord += 2;
        bg_form.width -= 4;
        bg_form.height = FORM_TOP_HEIGHT;
        LcdDrawBox(&bg_form, color_level[COLOR_GREY2_COLOR], color_level[COLOR_GREY2_COLOR], DRAW_FILL);
        LcdDrawLine(bg_form.xcoord,bg_form.ycoord+bg_form.height,bg_form.xcoord+bg_form.width-1,
			bg_form.ycoord+bg_form.height,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR]);
        LcdDrawLine(bg_form.xcoord,bg_form.ycoord+bg_form.height+1,bg_form.xcoord+bg_form.width-2,
			bg_form.ycoord+bg_form.height+1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR]);
    }
    else
    {
        bg_form.xcoord = 0;
        bg_form.ycoord = 0;
        bg_form.width = 160;
        bg_form.height = FORM_TOP_HEIGHT + 2;
        LcdDrawBox(&bg_form, color_level[COLOR_BLACK_COLOR], color_level[COLOR_BLACK_COLOR],DRAW_FILL);
    }
	
	/* Draw the specified Text and Bitmap diagram */
	bg_form = addr->bounds;
	bitmap = addr->form_bitmap;
    if (color_mode == GREYSCALE_MODE)
    {
        bitmap.xcoord = bg_form.xcoord+FORM_BITMAP_LEFT_BORDER;
        bitmap.ycoord = bg_form.ycoord+FORM_BITMAP_TOP_BORDER;
    }
    else
    {
        bitmap.xcoord = bg_form.xcoord + 2;
        bitmap.ycoord = bg_form.ycoord + 2;
    }
	LcdDrawBitmap(&bitmap,NOT_INVERT);
	
	bg_form.xcoord = bitmap.xcoord+bitmap.width+DIALOG_TEXT_SEPARATOR-1;
	bg_form.ycoord = bitmap.ycoord+1;
	bg_form.width  -= (addr->form_bitmap.width + DIALOG_TEXT_SEPARATOR + DIALOG_BORDER*2 +12);
	bg_form.height = FONT_HEIGHT[0];
	LcdDrawFixedString(&bg_form,addr->form_dialog_title,color_level[COLOR_WHITE_COLOR],color_level[COLOR_GREY2_COLOR],SMALL_FONT,DOTDOT,MARGIN_0);
}

/*********************************************************************
* Function: 	FormSaveBehindBits
* Purpose: 		This function is used to set the save_behind
*		      	attribute and to store the image that is being covered
*			  	by the specified form object.
* Scope: 		Application
* Input: 		None
* Output: 		None
* Return: 		None
* Comment: 		None
**********************************************************************/
Err FormSaveBehindBits(ObjectID form_id)
{
    BYTE object_type;
	Form *addr;
	BitmapTemplate save_behind;
	
    if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	/* Get the bounds to save */
	save_behind.xcoord = addr->bounds.xcoord;
    save_behind.ycoord = addr->bounds.ycoord;
	save_behind.width  = addr->bounds.width;
	save_behind.height = addr->bounds.height;
    addr->save_behind = save_behind;
    LcdGetBitmap(&(addr->save_behind));
	addr->form_attr.form_save_behind = TRUE;
	return TRUE;
}
/********************************************************
* Function:	FormRestoreBitBehind
* 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
*********************************************************/
Err FormRestoreBitBehind(ObjectID form_id)
{
    BYTE object_type;
	Form *addr;
	
    if (UISearchForAddress(form_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	/* to check whether save_behind is TRUE */
	if (addr->form_attr.form_save_behind == TRUE)
	{
		LcdDrawBitmap(&(addr->save_behind), FALSE);
		qfree(addr->save_behind.bitmap_data);
		addr->form_attr.form_save_behind = FALSE;
	}
	return TRUE;
}

/********************************************************
* Function:	FormCheckObjectExists
* Purpose:     to check whether the object is loaded or not
* Scope:		Application/Internal
* Input:       object_id		The ID value of the object
* Output:		None
* Return:		TRUE			exist
FALSE			non_exist
* Comment:		None
*********************************************************/
BOOLEAN FormCheckObjectExists(ObjectID object_id)
{
	BYTE object_type;
	void *addr;
	
    if (UISearchForAddress(object_id,&object_type,(void**)&addr) != TRUE) return FALSE;
	else return TRUE;
}
/********************************************************
* Function:	FormInitForm
* Purpose:     to load the data from resource file to
to memory
* Scope:		Application
* Input:       form_id 	DBID of the spceified form
* Output:		None
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormInitForm(ObjectID form_id)
{
	BYTE *buffer;
	UWORD byte_return;
	Form *addr;
	Err Error;
	BYTE object_type;
	WORD i;
	
	object_type = FORM;
	Error = UIAddLinkListFormElement(form_id,&addr);
	if (Error != TRUE) return Error;
    Error = ResOpen(form_id);
    if (Error != TRUE) return Error;
	addr->identification.ui_object_id = form_id;
	/* Field 0 */
	addr->identification.ui_object_type = FORM;
	addr->identification.table_related = 0xFFFF;
	/* Field 1 */
	ResReadField(form_id,1,0,2,&buffer,&byte_return);
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,2,2,&buffer,&byte_return);
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,4,2,&buffer,&byte_return);
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,6,2,&buffer,&byte_return);
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	/* Field 2 */
	ResGetField(form_id, 2, &buffer, &byte_return);
	addr->form_focus = *(ObjectID*)buffer;
    qfree(buffer);
	/* Field 3 */
	ResGetField(form_id, 3, &buffer, &byte_return);
	addr->form_style = *buffer;
    qfree(buffer);
	/* Field 4 */
	ResGetField(form_id, 4, &buffer, &byte_return);
    addr->form_dialog_title = (BYTE*)qmalloc((strlen(buffer) + 1)*sizeof(BYTE));
    strcpy(addr->form_dialog_title, buffer);
    qfree(buffer);
	/* Field 5 */
	if (addr->form_style == 1 || addr->form_style == 2)
	{
		ResReadField(form_id,5,0,2,&buffer,&byte_return);
		addr->form_bitmap.xcoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,2,2,&buffer,&byte_return);
		addr->form_bitmap.ycoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,4,2,&buffer,&byte_return);
		addr->form_bitmap.width = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,6,2,&buffer,&byte_return);
		addr->form_bitmap.height = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,8,1,&buffer,&byte_return);
		addr->form_bitmap.compressed = *buffer;
		qfree(buffer);
		ResReadField(form_id,5,9,1,&buffer,&byte_return);
		addr->form_bitmap.quantisation = *buffer;
		qfree(buffer);
		ResReadField(form_id,5,10,2,&buffer,&byte_return);
		addr->form_bitmap.size = *(USHORT*)buffer;
		qfree(buffer);
		ResGetPointer(form_id,5,12,(void**)&buffer);
		addr->form_bitmap.bitmap_data = (UWORD*)buffer;
	}
	/* Field 6 */
	ResGetField(form_id, 6, &buffer, &byte_return);
	addr->form_num_objects = *(USHORT*)buffer;
    qfree(buffer);
	/* Field 7 */
    addr->form_objects_list = (FormObjectsList*)qmalloc(addr->form_num_objects*sizeof(FormObjectsList));
	
	i = 0;
	while (i<addr->form_num_objects)
	{
		ResReadField(form_id,7,(i * 3),2,&buffer,&byte_return);
		addr->form_objects_list[i].object_id = *(ObjectID*)buffer;
		qfree(buffer);
		ResReadField(form_id,7,((i * 3) + 2),1,&buffer,&byte_return);
		addr->form_objects_list[i].object_type = *buffer;
		qfree(buffer);
		i++;
	}
    /* Field 8 */
	addr->form_attr.form_drawn = FALSE;
	addr->form_attr.form_active = FALSE;
	addr->form_attr.form_updated = FALSE;
	addr->form_attr.form_save_behind = FALSE;
	addr->save_behind.bitmap_data = NULL;
	ResClose(form_id);
	return TRUE;
}

/********************************************************
* Function:	FormInitAllFormObjects
* Purpose:     to initialise all objects of a particular form
* Scope:		Application
* Input:       form_id 	DBID of the spceified form
* Output:		None
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormInitAllFormObjects(ObjectID form_id)
{
	BYTE *buffer;
	UWORD byte_return;
	Form *addr;
	Err Error;
	BYTE object_type;
	WORD i;
	
	
	object_type = FORM;
	Error = UIAddLinkListFormElement(form_id,&addr);
	if (Error != TRUE) return Error;
	
    Error = ResOpen(form_id);
	
    if (Error != TRUE) return Error;
	
	addr->identification.ui_object_id = form_id;
	/* Field 0 */
	addr->identification.ui_object_type = FORM;
	addr->identification.table_related = 0xFFFF;
	
	/* Field 1 */
	ResReadField(form_id,1,0,2,&buffer,&byte_return);
	
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,2,2,&buffer,&byte_return);
	
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,4,2,&buffer,&byte_return);
	
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(form_id,1,6,2,&buffer,&byte_return);
	
	
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	
	/* Field 2 */
	ResGetField(form_id, 2, &buffer, &byte_return);
	
	
	
	addr->form_focus = *(ObjectID*)buffer;
    qfree(buffer);
	
	
	/* Field 3 */
	ResGetField(form_id, 3, &buffer, &byte_return);
	addr->form_style = *buffer;
    qfree(buffer);
	
	
	/* Field 4 */
	ResGetField(form_id, 4, &buffer, &byte_return);
    addr->form_dialog_title = (BYTE*)qmalloc((strlen(buffer) + 1)*sizeof(BYTE));
    strcpy(addr->form_dialog_title, buffer);
    qfree(buffer);  
	
	
	/* Field 5 */
	if (addr->form_style == 1 || addr->form_style == 2)
	{
		ResReadField(form_id,5,0,2,&buffer,&byte_return);
		addr->form_bitmap.xcoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,2,2,&buffer,&byte_return);
		addr->form_bitmap.ycoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,4,2,&buffer,&byte_return);
		addr->form_bitmap.width = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,6,2,&buffer,&byte_return);
		addr->form_bitmap.height = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(form_id,5,8,1,&buffer,&byte_return);
		
		addr->form_bitmap.compressed = *buffer;
		qfree(buffer);
		ResReadField(form_id,5,9,1,&buffer,&byte_return);
		addr->form_bitmap.quantisation = *buffer;
		qfree(buffer);
		ResReadField(form_id,5,10,2,&buffer,&byte_return);
		addr->form_bitmap.size = *(USHORT*)buffer;
		qfree(buffer);
		ResGetPointer(form_id,5,12,(void**)&buffer);
		addr->form_bitmap.bitmap_data = (UWORD*)buffer;
	}
	
	/* Field 6 */
	ResGetField(form_id, 6, &buffer, &byte_return);
    addr->form_num_objects = *(USHORT*)buffer;
    qfree(buffer);
	
	
	/* Field 7 */
    addr->form_objects_list = (FormObjectsList*)qmalloc(addr->form_num_objects*sizeof(FormObjectsList));
	
	
	i = 0;
	while (i<addr->form_num_objects)
	{
		ResReadField(form_id,7,(i * 3),2,&buffer,&byte_return);
		
		addr->form_objects_list[i].object_id = *(ObjectID*)buffer;
		qfree(buffer);
		ResReadField(form_id,7,((i * 3) + 2),1,&buffer,&byte_return);
		
		addr->form_objects_list[i].object_type = *buffer;
		qfree(buffer);
		switch (addr->form_objects_list[i].object_type)
		{
		case CONTROL: ControlInitControl(addr->form_objects_list[i].object_id);
			break;
        case FIELD: FieldInitField(addr->form_objects_list[i].object_id);
			break;
		case LIST: ListInitList(addr->form_objects_list[i].object_id);
			break;	
		case MENU: MenuInitMenu(addr->form_objects_list[i].object_id);
			break;
		case SCROLLBAR: ScrollbarInitScrollbar(addr->form_objects_list[i].object_id);
			break;
		case TABLE: TableInitTable(addr->form_objects_list[i].object_id);
			break;
		case SCHLINE: SchlineInitSchline(addr->form_objects_list[i].object_id);
			break;
		case STRING: StringInitString(addr->form_objects_list[i].object_id);
			         break; 
		case BITMAP: BitmapInitBitmap(addr->form_objects_list[i].object_id);
			break;
		case TEXTBOX: TextboxInitTextbox(addr->form_objects_list[i].object_id);
			break;
		case LINE: LineInitLine(addr->form_objects_list[i].object_id);
			break;
		default: break;
		}
		
		i++;
	}
	
    /* Field 8 */
	addr->form_attr.form_drawn = FALSE;
	addr->form_attr.form_active = FALSE;
	addr->form_attr.form_updated = FALSE;
	addr->form_attr.form_save_behind = FALSE;
	addr->save_behind.bitmap_data = NULL;
	ResClose(form_id);
	return TRUE;
}

/********************************************************
* Function:    FormAddOneObject
* Purpose:     This function is called to add an object into a form
* Scope:		Application
* Input:       form_id 	DBID of the spceified form
object_id
object_type
nth_object
* Output:		None
* Return:		Error code
* Comment:		None
*********************************************************/
Err FormAddOneObject(ObjectID form_id, ObjectID object_id, BYTE object_type)
{
    BYTE                form_object_type;
    Form                *addr;
    FormObjectsList     *new_objects_list;
    USHORT              i;
	
    if (UISearchForAddress(form_id, &form_object_type, (void**)&addr) != TRUE)
        return ERR_UI_RES_NOT_FOUND;
	
    new_objects_list = (FormObjectsList*)qmalloc((addr->form_num_objects + 1)*sizeof(FormObjectsList));
    i = 0;
    while (i<addr->form_num_objects)
    {
        new_objects_list[i].object_id = addr->form_objects_list[i].object_id;
        new_objects_list[i].object_type = addr->form_objects_list[i].object_type;
		i ++;    
    }
	
    new_objects_list[addr->form_num_objects].object_id    = object_id;
    new_objects_list[addr->form_num_objects].object_type  = object_type;
	
    addr->form_num_objects ++;
	
    qfree(addr->form_objects_list);
	
    addr->form_objects_list = new_objects_list;
    
    return TRUE;
	
}


