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



#include "stdafx.h"

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

/********************************************************
* Function:	MenuEraseMenu
* Purpose:		to erase the popuped up menu
* Scope:		Application
* Input:		menu_id		OBJECTID of the menu object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuEraseMenu(ObjectID menu_id)
{
	Menu *addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->menu_attr.menu_drawn)
        LcdEraseRegion(&(addr->bounds));
    addr->menu_attr.menu_drawn = FALSE;
    return TRUE;
}
/********************************************************
* Function:	MenuDeleteMenu
* Purpose:		to delete a menu from memory
* Scope:		Application
* Input:		menu_id		OBJECTID of the menu object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuDeleteMenu(ObjectID menu_id)
{
	Menu *addr;
	BYTE object_type;
    Err Error;
	WORD i;
	
	if (UISearchForAddress(menu_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	i = addr->menu_num_items;
	while (i)
	{
		i--;
        qfree(addr->menu_items[i]);
	}
    qfree(addr->menu_items);
	if (addr->save_behind.bitmap_data)
        qfree(addr->save_behind.bitmap_data);
	Error = UIDeleteLookupTableElement(menu_id); /* delete the corresponding element in the lookup table */
	if (Error !=TRUE) return Error;
    qfree(addr);
	return TRUE;
}
/********************************************************
* Function:	MenuGetNoOfItems
* Purpose:		to get the number of items of a menu
* Scope:		Application
* Input:		menu_id		OBJECTID of the menu object
* Output:		num_items   Pointer to value of number of items
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuGetNumOfItems(ObjectID menu_id, USHORT *num_items)
{
	Menu *addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *num_items = addr->menu_num_items;
	return TRUE;
}
/********************************************************
* Function:	MenuSetPopupBounds
* Purpose:		to set the bounds of a popuped menu
* Scope:		Application
* Input:		menu_id		OBJECTID of the menu object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuSetPopupBounds(ObjectID menu_id)
{
	Menu *addr;
	BYTE object_type;
	ObjectBounds popuped;
	USHORT total_objects;
	WORD count;
	SHORT new_width, width_sum = 0, longest = 0;
	BOOLEAN average = FALSE;
	
	if (UISearchForAddress(menu_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	total_objects = addr->menu_num_items;
	count = total_objects;
	while (count)
	{
		count--;
		new_width = StrGetWidth(addr->menu_items[count],SMALL_FONT);
		if (new_width > 140) average = TRUE;
		else if (new_width > longest)
			longest = new_width;
		width_sum = width_sum+new_width;
	}
	if (average == TRUE) 
		new_width = (width_sum / total_objects);
	else new_width = longest;
	if (new_width > 100) new_width = 100;
	popuped.width = new_width + (4 * MENU_BORDER);
	popuped.xcoord = 4;
	popuped.height = (total_objects * (FONT_HEIGHT[0] + MENU_BORDER))+5;/* Add 5 offset */
	popuped.ycoord = 160 - popuped.height - 2;
	addr->bounds = popuped;
	return TRUE;
}
/********************************************************
* Function:	MenuSearchSelectedItem
* Purpose:		to find out which item is being clicked
* Scope:		Application
* Input:		addr	        Pointer to menu
input_xcoord    the xcoord of the pen
input_ycoord    the ycoord of the pen
* Output:		item_num        Pointer to show which item is clicked on
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
SHORT MenuSearchSelectedItem(Menu *addr, SHORT input_xcoord, SHORT input_ycoord)
{
	USHORT item_height,total_num_objects;
	ObjectBounds popup;
	WORD count;
	
	popup = addr->bounds;
	popup.ycoord += 1;
	
	item_height = FONT_HEIGHT[0] + MENU_BORDER;
	total_num_objects = addr->menu_num_items;
	count = 0;
	
	while (	count < total_num_objects)
	{
		if (input_xcoord >= popup.xcoord &&
			input_xcoord <= popup.xcoord + popup.width-1 &&
			input_ycoord >= popup.ycoord &&
			input_ycoord <= popup.ycoord + item_height + 1) return (SHORT)count;
		
		popup.ycoord += item_height;
		count++;
	}
	return -1;
}
/********************************************************
* Function:	MenuSetTotalItems
* Purpose:		to set the total number of items in the menu
* Scope:		Application
* Input:		menu_id		    DBID of menu object
total_num_items	the total number of items in the
menu
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuSetTotalItems (ObjectID menu_id,USHORT total_num_items)
{
	Menu *menu_addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	menu_addr->menu_num_items = total_num_items;
	return TRUE;
}
/********************************************************
* Function:	MenuGetTotalItems
* Purpose:		to get the the total number of items in the menu
* Scope:		Application
* Input:		menu_id		    DBID of menu object
* Output:		total_num_items	Pointer to the total number of items in the
menu list
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuGetTotalItems (ObjectID menu_id,USHORT *total_num_items)
{
	Menu *menu_addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *total_num_items = menu_addr->menu_num_items;
	return TRUE;
}
/********************************************************
* Function:	MenuDeleteItem
* Purpose:		to delete an item in the menu list and all the items
will be re-arranged
* Scope:		Application
* Input:		menu_id	    DBID of menu object
item_number	the item number that u want to add
item to
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuDeleteItem(ObjectID menu_id,USHORT item_number)
{
	Menu *menu_addr;
	BYTE object_type;
	WORD i;
	USHORT total_number;
	BYTE **new_popup;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (item_number < menu_addr->menu_selected_item)
		menu_addr->menu_selected_item--;
	if (item_number < menu_addr->menu_highlighted_item)
		menu_addr->menu_highlighted_item++;
	if (item_number == menu_addr->menu_selected_item)
	{
		menu_addr->menu_selected_item = -1;
		menu_addr->menu_highlighted_item = -1;
	}
	if (item_number >= menu_addr->menu_num_items) return ERR_UI_ITEM_NUMBER_EXCEED;
	total_number = menu_addr->menu_num_items;
    qfree(menu_addr->menu_items[item_number]);
	/* the corresponding item in the menu list is deleted and all the other items are re-arrnaged */
    new_popup = (BYTE**)qmalloc((total_number - 1)*sizeof(BYTE*));
	i = item_number;
	while (i)
	{
		i--;
		new_popup[i] = menu_addr->menu_items[i];
	}
	i = item_number;
	while (i<(total_number - 1))
	{
		new_popup[i] = menu_addr->menu_items[i+1];
		i++;
	}
	menu_addr->menu_num_items = total_number - 1;
    qfree(menu_addr->menu_items);
	menu_addr->menu_items = new_popup;
	return TRUE;
}

/********************************************************
* Function:	MenuDeleteAllItems
* Purpose:		to delete all items in a menu
* Scope:		Application
* Input:		menu_id	    DBID of menu object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuDeleteAllItems(ObjectID menu_id)
{
	Menu *addr;
	BYTE object_type;
	WORD i;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	i = addr->menu_num_items;
	while (i)
	{	
		i--;
        qfree(addr->menu_items[i]);
	}
    qfree(addr->menu_items);
	addr->menu_items = NULL;
	addr->menu_num_items = 0;
	return TRUE;
}

/********************************************************
* Function:	MenuInsertItem
* Purpose:		to insert a new item in the menu list and the whole
list will be re-arranged again
* Scope:		Application
* Input:		menu_id	    DBID of menu object
item_number	the item number that u want to add
item to
item_text	Pointer to the char array of item text
* Output:		None
* Return:		TRUE if no error
ErrUIObjectNotMatch
ERR_UI_NUM__MENU_ITEMS_EXCEED
* Comment:     None
*********************************************************/
Err MenuInsertItem(ObjectID menu_id,USHORT item_number,BYTE *item_text)
{
	Menu *menu_addr;
	BYTE object_type;
	WORD i;
	USHORT total_number;
	BYTE **new_popup;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    menu_addr->menu_max_num_items = 160/(2 * MENU_BORDER + FONT_HEIGHT[0]) - 1;
    if (item_number <= menu_addr->menu_selected_item)
		menu_addr->menu_selected_item++;
    if (item_number <= menu_addr->menu_highlighted_item)
		menu_addr->menu_highlighted_item++;
	if (item_number > menu_addr->menu_num_items)
		item_number = menu_addr->menu_num_items;
    if (menu_addr->menu_num_items >= menu_addr->menu_max_num_items)
		return ERR_UI_NUM__MENU_ITEMS_EXCEED;
    total_number = menu_addr->menu_num_items;
    new_popup = (BYTE **)qmalloc((total_number+1)*sizeof(BYTE *));
	i = 0;
	while (i <total_number)
	{
		if (i < item_number)
		{
			new_popup[i] = menu_addr->menu_items[i];
		}
		else if( i == item_number)
		{
			new_popup[i] = (BYTE *)qmalloc((strlen(item_text)+1)*sizeof(BYTE));
			strcpy (new_popup[i],item_text);
			new_popup[i+1] = menu_addr->menu_items[i];
		}
		else
		{
			new_popup[i+1] = menu_addr->menu_items[i];
		}
		i++;
	}
	if (item_number == total_number)
	{
		new_popup[item_number] = (BYTE *)qmalloc((strlen(item_text) + 1)*sizeof(BYTE));
		strcpy (new_popup[item_number],item_text);
	}
	menu_addr->menu_num_items = (total_number + 1);
    qfree(menu_addr->menu_items);
	menu_addr->menu_items = new_popup;
	return TRUE;
}
/********************************************************
* Function:	MenuGetMenuItem
* Purpose:		to get the text of a specific popup item
* Scope:		Application
* Input:		menu_id	    DBID of menu object
item_number	the item number that u want to add
item to
* Output:		item_text	Pointer to the char array of item text
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuGetMenuItem(ObjectID menu_id,USHORT item_number,BYTE **item_text)
{
	Menu *menu_addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (item_number >= menu_addr->menu_num_items) return ERR_UI_ITEM_NUMBER_EXCEED;
	*item_text = menu_addr->menu_items[item_number];
	return TRUE;
}
/********************************************************
* Function:	MenuDrawMenu
* Purpose:		to draw the menu on the screen
* Scope:		Application
* Input:		menu_id	    DBID of menu object
* Output:		None
* Return:		TRUE if no error
ErrUIObjectNotMatch
* Comment:     None
*********************************************************/
Err MenuDrawMenu (ObjectID menu_id)
{
    Menu *addr;
    BYTE object_type;
    ObjectBounds highlight, display_bounds;
	WORD count=0;
	
    if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    addr->menu_max_num_items = 160/(2 * MENU_BORDER + FONT_HEIGHT[0]) - 1;
	
    MenuSetPopupBounds(menu_id);
	
    display_bounds.xcoord = addr->bounds.xcoord + MENU_BORDER;
    display_bounds.ycoord = addr->bounds.ycoord + MENU_BORDER + 1;
    display_bounds.width  = addr->bounds.width - (MENU_BORDER * 2);
    display_bounds.height = FONT_HEIGHT[0];
	
	ControlDrawEmptyButton(&addr->bounds,BUTTON_FIXED_CORNER,color_level[COLOR_WHITE_COLOR]);
	ControlDrawArc(&addr->bounds,DRAW_NOT_FILL,BUTTON_FIXED_CORNER,color_level[COLOR_WHITE_COLOR]);
	
	highlight = display_bounds;
    highlight.height = display_bounds.height + 1;
	
	while (count< addr->menu_num_items)
	{
		if (addr->menu_highlighted_item == count)
		{        
			LcdDrawBox(&highlight,color_level[COLOR_GREY2_COLOR],color_level[COLOR_GREY2_COLOR],DRAW_FILL);
			
			LcdDrawFixedString(&display_bounds,addr->menu_items[count],color_level[COLOR_WHITE_COLOR],color_level[COLOR_GREY2_COLOR],SMALL_FONT,DOTDOT,MARGIN_0);
			
			LcdDrawLine(highlight.xcoord+1,highlight.ycoord-1,highlight.xcoord+highlight.width-1,
				highlight.ycoord-1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);								
			
			if (color_mode == GREYSCALE_MODE)
			{
				LcdDrawLine(highlight.xcoord+1,highlight.ycoord+highlight.height,highlight.xcoord+highlight.width-1,
					highlight.ycoord+highlight.height,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
				
				LcdDrawLine(highlight.xcoord,highlight.ycoord-1,highlight.xcoord,highlight.ycoord+highlight.height,
					SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
			}							
			else							
				LcdDrawLine(highlight.xcoord,highlight.ycoord-1,highlight.xcoord,highlight.ycoord + highlight.height - 1,
				SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
			
			LcdDrawLine(highlight.xcoord+highlight.width-1,highlight.ycoord-1,highlight.xcoord+highlight.width-1,
				highlight.ycoord+highlight.height,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);																
		}
		else
			LcdDrawFixedString(&display_bounds,addr->menu_items[count],color_level[COLOR_BLACK_COLOR],color_level[COLOR_GREY1_COLOR],SMALL_FONT,DOTDOT,MARGIN_0);
		
		display_bounds.ycoord += display_bounds.height + MENU_BORDER;
		highlight.ycoord = display_bounds.ycoord;
		count ++;
    }
    addr->menu_attr.menu_drawn = TRUE;
    return TRUE;
}
/********************************************************
* Function:	MenuRestoreBehindBits
* Purpose:		to restore the bitmap of the image that is covered
BY THE POPUPED MENU
* Scope:		Application
* Input:		menu_id	    DBID of menu object
* Output:		None
* Return:		TRUE if no error
ErrUIObjectNotMatch
* Comment:     None
*********************************************************/
Err MenuRestoreBehindBits(ObjectID menu_id)
{
	Menu *menu_addr;
	BYTE object_type;
	
	if (UISearchForAddress(menu_id,&object_type,(void**)&menu_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	/* to check whether save_behind is TRUE */
	LcdDrawBitmap(&(menu_addr->save_behind),0);
    qfree(menu_addr->save_behind.bitmap_data);
	menu_addr->save_behind.bitmap_data = NULL;
	return TRUE;
}
/********************************************************
* Function:	MenuSaveBehindBits
* Purpose:		to save the the bitmap of the image that is covered
BY THE POPUPED MENU
* Scope:		Application
* Input:		menu_id	    DBID of menu object
* Output:		None
* Return:		TRUE if no error
ErrUIObjectNotMatch
* Comment:     None
*********************************************************/
Err MenuSaveBehindBits(ObjectID menu_id)
{
    Menu *addr;
    BYTE object_type;
    BitmapTemplate save_behind;
	
	/* Get the bounds to save */
    if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    MenuSetPopupBounds(addr->identification.ui_object_id);
	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));
    return TRUE;
}

/********************************************************
* Function:	MenuSetAttrVisible
* Purpose:		to set the attribute visible in menu object
* Scope:		Application
* Input:		menu_id			DBID of menu object
menu_visible	the attribute value
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuSetAttrVisible(ObjectID menu_id, BOOLEAN menu_visible)
{
    Menu *addr;
    BYTE object_type;
    
	
	/* Get the bounds to save */
    if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	addr->menu_attr.menu_visible = menu_visible;
    return TRUE;
}

/********************************************************
* Function:	MenuGetAttrVisible
* Purpose:		to set the attribute visible in menu object
* Scope:		Application
* Input:		menu_id			DBID of menu object
* Output:		menu_visible	pointer to the attribute value
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err MenuGetAttrVisible(ObjectID menu_id, BOOLEAN *menu_visible)
{
    Menu *addr;
    BYTE object_type;
    
	/* Get the bounds to save */
    if (UISearchForAddress(menu_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*menu_visible = addr->menu_attr.menu_visible;
    return TRUE;
}

/********************************************************
* Function:	MenuInitMenu
* Purpose:		1) to initialise the list object
2) to read the resource file
3) to create a corresponding list structure
in RAM
* Scope:		Application
* Input:		menu_id	DBID of the menu object
* Output:		None
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err MenuInitMenu(ObjectID menu_id)
{
	BYTE *buffer,*temp_buffer;
	UWORD byte_return;
	void *temp;
	Menu *addr;
	Err Error;
	BYTE object_type;
	BYTE **temp_menu;
	WORD i;
	
	object_type = MENU;
	Error = UIAddressToLookupTable(menu_id,object_type,&temp); /*put the pointer to the DBID											  lookup table */
	if (Error != TRUE) return Error;
	addr = (Menu *)temp;
    Error = ResOpen(menu_id);
    if (Error != TRUE) return Error;
	
	addr->identification.ui_object_id = menu_id;
	/* Field 0 */
	addr->identification.ui_object_type = MENU;
	addr->identification.table_related = 0xFFFF;
	/* Field 1 */
	ResReadField(menu_id,1,0,2,&buffer,&byte_return);
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(menu_id,1,2,2,&buffer,&byte_return);
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(menu_id,1,4,2,&buffer,&byte_return);
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(menu_id,1,6,2,&buffer,&byte_return);
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	/* Field 2 */
	ResGetField(menu_id,2,&buffer,&byte_return);
	addr->menu_num_items = *(USHORT*)buffer;
    qfree(buffer);
	/* Field 3 */
	ResGetField(menu_id,3,&buffer,&byte_return);
	addr->menu_selected_item = *(USHORT*)buffer;
    qfree(buffer);
	addr->menu_highlighted_item = -1;
	/* Field 4 */
	ResGetField(menu_id,4,&buffer,&byte_return);
	temp_buffer = buffer;
	if (addr->menu_num_items > 0)
        temp_menu = (BYTE**)qmalloc(sizeof(BYTE*)*(addr->menu_num_items));
	else temp_menu = NULL;
	i = 0;
	while (i<addr->menu_num_items)
	{
		temp_menu[i] = (BYTE*)qmalloc(sizeof(BYTE)*(strlen(buffer)+1));
		strcpy(temp_menu[i],buffer);
		buffer = buffer + strlen(buffer) + 1;
		i++;
	}
	addr->menu_items = temp_menu;
    qfree(temp_buffer);
	/* Field 5 */
	ResGetField(menu_id,5,&buffer,&byte_return);
	addr->menu_attr.menu_visible = *(BOOLEAN*)buffer;
    qfree(buffer);
	addr->menu_attr.menu_drawn = FALSE;
	addr->save_behind.bitmap_data = NULL;
	ResClose(menu_id);
	return TRUE;
}

/********************************************************
* Function:    MenuCloseMenu
* Purpose:     This function is called to close the menu
* Scope:		Application
* Input:       None
* Output:		None
* Return:      None
* Comment:     None
*********************************************************/
Err MenuCloseMenu()
{
    Menu        *addr;
    ObjectID    menu_id, form_id;
    BYTE        object_type;
    BYTE        temp_undo_action;
	
    if (FormGetActiveFormID(&form_id) != TRUE)
        return FALSE;
    if (FormGetMenuID(form_id, &menu_id) != TRUE)
        return FALSE;
	
    if (UISearchForAddress(menu_id, &object_type, (void**)&addr) != TRUE)
        return  ERR_UI_RES_NOT_FOUND;
    if (object_type != MENU)
        return ERR_UI_OBJECT_NOT_MATCH;
	
    if (menu_status == FALSE)
        return FALSE;
    menu_status = FALSE;
    old_event.eventType = NULL_EVENT;
    addr->menu_attr.menu_drawn = FALSE;
    MenuRestoreBehindBits(menu_id);
    temp_undo_action = undo_action;
    FormObjectRestoreFocus();
    undo_action = temp_undo_action;
}

/********************************************************
* Function:    MenuKeyboardHandleMenu
* Purpose:     This fucntion is called to provide support to change menu by keyboard keys
* Scope:		Application
* Input:       None
* Output:		None
* Return:      None
* Comment:     None
*********************************************************/
Err MenuKeyboardHandleMenu(EvtType *Event)
{
	ObjectID						active_control_id;
	BYTE							object_type;
	Menu							*menu_ptr;
    void                            *addr;
	ControlTemplatePopupTrigger		*control_template;	
	BOOLEAN							draw = FALSE;
	BYTE                            temp_undo_action;
	
	if (!menu_status)
		return FALSE;
	
	if (old_event.eventType != EVT_MENU_SELECT)
		return FALSE;
	
    if (FormGetObjectPointer(old_event.eventID, &object_type, (void**)&addr) != TRUE)
		return FALSE;
	
    if (object_type == MENU)
        menu_ptr = (Menu*)addr;
    else return FALSE;                
	
	
    switch (Event->eventType)
	{
	case EVT_KEY:
		if (Event->eventID == SOFT_KEY)
		{
			Event->para2 = Event->para2 & 0x000000FF;
			switch (Event->para2)
			{
			case KEY_HOME:
				menu_ptr->menu_highlighted_item = 0;
				MenuDrawMenu(old_event.eventID);
				return TRUE;
			case KEY_END:
				menu_ptr->menu_highlighted_item = menu_ptr->menu_num_items - 1;
				MenuDrawMenu(old_event.eventID);
				return TRUE;
			case KEY_UP:
				if (menu_ptr->menu_highlighted_item == -1)
					menu_ptr->menu_highlighted_item = menu_ptr->menu_num_items - 1;   			 		        
				else if (menu_ptr->menu_highlighted_item > 0 &&
					(menu_ptr->menu_highlighted_item <= (menu_ptr->menu_num_items - 1)))
					menu_ptr->menu_highlighted_item --;                           
				MenuDrawMenu(old_event.eventID);                            
				return TRUE;
			case KEY_DOWN:
				if (menu_ptr->menu_highlighted_item == -1)
					menu_ptr->menu_highlighted_item = 0;
				else if (menu_ptr->menu_highlighted_item >= 0 &&
					(menu_ptr->menu_highlighted_item < (menu_ptr->menu_num_items - 1)))
					menu_ptr->menu_highlighted_item ++;                           
				MenuDrawMenu(old_event.eventID);                            
				return TRUE;
			default:
				if (Event->para1 == '\r')
				{
					if (menu_ptr->menu_highlighted_item == -1)
					{	
						menu_status = FALSE;	
						old_event.eventType = NULL_EVENT;
						menu_ptr->menu_attr.menu_drawn = FALSE;
						MenuRestoreBehindBits(old_event.eventID);
						temp_undo_action = undo_action;
						FormObjectRestoreFocus();
						undo_action = temp_undo_action;
						
					}
					else
					{
						menu_status = FALSE;	
						menu_ptr->menu_selected_item = menu_ptr->menu_highlighted_item;
						EvtAppendEvt(EVT_MENU_SELECT_ITEM, old_event.eventID,  menu_ptr->menu_selected_item, 0, (void*)menu_ptr);
						menu_ptr->menu_selected_item = -1;
						menu_ptr->menu_highlighted_item = -1;
						menu_ptr->menu_attr.menu_drawn = FALSE;
						MenuRestoreBehindBits(old_event.eventID);
						old_event.eventType = NULL_EVENT;
						temp_undo_action = undo_action;
						FormObjectRestoreFocus();
						undo_action = temp_undo_action;
					}     			
					return TRUE;							
				}
				else
					return FALSE;
			}						
		}
		return FALSE;
	default: return FALSE;
	}					
	return FALSE;	
}
