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

#include "stdafx.h"

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

/********************************************************
* Function:	    ListConvertStyle
* Purpose:		To convert the styles of the list object
*				when black and white UI is selected
* Scope:		Internal
* Input:		list_addr		pointer to the list object
* Output:		None
* Return:		None
* Comment:      None
*********************************************************/
void ListConvertStyle(List *list_addr)
{
	if (color_mode == BLACK_AND_WHITE_MODE)
	{
		if (list_addr->list_style == 3 || list_addr->list_style == 6)
			list_addr->list_style = 1;		
		else if (list_addr->list_style == 2)
			list_addr->list_style = 4;
		else if (list_addr->list_style == 5)
			list_addr->list_style = 7;
	}
}


/********************************************************
* Function:	ListEraseList
* Purpose:		to erase the list object on the screen
* Scope:		Application
* Input:		list_id		OBJECTID of the list object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListEraseList(ObjectID list_id)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->list_attr.list_drawn)
    {
		if (addr->identification.table_related != 0xFFFF)
			LcdEraseRegion(&(addr->screen_bounds));
		else LcdEraseRegion(&(addr->bounds));
    }
    addr->list_attr.list_drawn = FALSE;
    return TRUE;
}
/********************************************************
* Function:	ListDeleteList
* Purpose:		to delete a list from memory
* Scope:		Application
* Input:		list_id		OBJECTID of the list object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListDeleteList(ObjectID list_id)
{
	List *addr;
    BYTE object_type;
    Err Error;
	WORD i;
	
	if (UISearchForAddress(list_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	i = addr->list_total_num_items;
	while (i)
	{
		i--; 
		qfree(addr->list_items[i]);
	}
	if (addr->list_items)
        qfree(addr->list_items);
	if (addr->list_related_list_id)
        qfree(addr->list_related_list_id);
	Error = UIDeleteLookupTableElement(list_id); /* delete the corresponding element in the lookup table */	if (Error !=TRUE) return Error;
    qfree(addr);
	return TRUE;
}
/********************************************************
* Function:	ListGetNumOfItems
* Purpose:		to get the number of items of a list object
* Scope:		Application
* Input:		list_id		OBJECTID of the list object
* Output:		num_items   Pointer to value of number of items
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetNumOfItems(ObjectID list_id, USHORT *num_items)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *num_items = addr->list_total_num_items;
	return TRUE;
}

/********************************************************
* Function:	ListSearchSelectedItem
* 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 ListSearchSelectedItem(List *addr, SHORT input_xcoord, SHORT input_ycoord)
{
	WORD count;
	SHORT item_height;
	ObjectBounds popup;
	
	if (addr->identification.table_related != 0xFFFF)
		popup = addr->screen_bounds;
	else popup = addr->bounds;
	
	item_height = addr->list_item_height;
	count = 0;
	while (	count < addr->list_num_items_on_display)
	{
		if (input_xcoord >= popup.xcoord &&
			input_xcoord <= popup.xcoord + popup.width-1 &&
			input_ycoord >= popup.ycoord &&
			input_ycoord <= popup.ycoord + item_height-1)
		{
			count = count + addr-> list_top_item_num;
			return (SHORT)count;
		}
		popup.ycoord = popup.ycoord + item_height;
		count++;
	}
	return -1;
}
/********************************************************
* Function:	ListSetTotalItems
* Purpose:		to set the total number of items in the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
total_num_items	the total number of items in the
list
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListSetTotalItems (ObjectID list_id,USHORT total_num_items)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    addr->list_total_num_items = total_num_items;
	return TRUE;
}
/********************************************************
* Function:	ListGetTotalItems
* Purpose:		to get the the total number of items in the list
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:		total_num_items	Pointer to the total number of items in the
list object
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetTotalItems (ObjectID list_id,USHORT *total_num_items)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *total_num_items = addr->list_total_num_items;
	return TRUE;
}
/********************************************************
* Function:	ListGetListItem
* Purpose:		to get the text of a specific list 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 ListGetListItem(ObjectID list_id,USHORT item_number,BYTE **item_text)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (item_number >= addr->list_total_num_items) return ERR_UI_ITEM_NUMBER_EXCEED;
	*item_text = addr->list_items[item_number];
	return TRUE;
}
/********************************************************
* Function:	ListGetNumItemsDisplay
* Purpose:		to get the the number of items that are displayed on the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:		num_items	    Pointer to the total number of displayed items
in the list object
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetNumItemsDisplay (ObjectID list_id,USHORT *num_items)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *num_items = addr->list_num_items_on_display;
	return TRUE;
}

/********************************************************
* Function:	ListGetMaxNumItemsDisplay
* Purpose:		to get the the max number of items that are displayed on the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:		max_num_items	    Pointer to the max number of displayed items
in the list object
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetMaxNumItemsDisplay (ObjectID list_id,USHORT *max_num_items)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *max_num_items = addr->list_max_num_items_on_display;
	return TRUE;
}

/********************************************************
* Function:	ListSetSelectedItem
* Purpose:		to set the the selected item in the list
* Scope:		Application
* Input:		list_id		    DBID of list object
item_num	    the item number of the selected item
* Output:      None
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListSetSelectedItem(ObjectID list_id,SHORT item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (item_num <= (addr->list_total_num_items - 1))
    {
		addr->list_selected_item = item_num;
		return TRUE;
    }
    return ERR_UI_ITEM_NUMBER_EXCEED;
}
/********************************************************
* Function:	ListGetSelectedItem
* Purpose:		to get the the selected item in the list
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:      item_num	    Poibnter to the item number of the selected item
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetSelectedItem(ObjectID list_id,SHORT *item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *item_num =  addr->list_selected_item;
    return TRUE;
}

/********************************************************
* Function:	ListSetHighlightedItem
* Purpose:		to set the the highlighted item in the list
* Scope:		Application
* Input:		list_id		    DBID of list object
item_num	    the item number of the highlighted item
* Output:      None
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListSetHighlightedItem(ObjectID list_id,SHORT item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (item_num <= (addr->list_total_num_items - 1))
    {
		addr->list_highlighted_item = item_num;
		addr->list_selected_item = item_num;
		return TRUE;
    }
    return ERR_UI_ITEM_NUMBER_EXCEED;
}
/********************************************************
* Function:	ListGetHighlightedItem
* Purpose:		to get the the highlighted item in the list
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:      item_num	    Poibnter to the item number of the selected item
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetHighlightedItem(ObjectID list_id,SHORT *item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *item_num =  addr->list_highlighted_item;
    return TRUE;
}

/********************************************************
* Function:	ListGetTopItemNum
* Purpose:		to get thetop item number
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:      item_num	    Pointer to the item number of the top item
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetTopItemNum(ObjectID list_id,USHORT *item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *item_num =  addr->list_top_item_num;
    return TRUE;
}

/********************************************************
* Function:	ListSetTopItemNum
* Purpose:		to set the top item number
* Scope:		Application
* Input:		list_id		    DBID of list object
item_num	    the item number of the top item
* Output:      None
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListSetTopItemNum(ObjectID list_id,USHORT item_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (item_num <= (addr->list_total_num_items - 1))
    {
		addr->list_top_item_num = item_num;
		return TRUE;
    }
    return ERR_UI_ITEM_NUMBER_EXCEED;
}
/********************************************************
* Function:	ListGetListBounds
* Purpose:		to set the bounds of the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
* Output:      bounds	        Pointer to the bounds of the list object
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetListBounds(ObjectID list_id,ObjectBounds *bounds)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->identification.table_related != 0xFFFF)
		*bounds = addr->screen_bounds;
    else *bounds = addr->bounds;
    return TRUE;
}
/********************************************************
* Function:	ListSetListBounds
* Purpose:		to set the bounds of the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
bounds	        the bounds of the list object
* Output:      None
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListSetListBounds(ObjectID list_id,ObjectBounds bounds)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->identification.table_related != 0xFFFF)
		addr->screen_bounds = bounds;
    else addr->bounds = bounds;
    return TRUE;
}
/********************************************************
* Function:	ListDeleteItem
* Purpose:		to delete an item in the list object and all the items
will be re-arranged
* Scope:		Application
* Input:		list_id	    DBID of list object
item_number	the item number that u want to delete
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListDeleteItem(ObjectID list_id,USHORT item_number)
{
	List *addr;
	BYTE object_type;
	USHORT total_number;
	WORD i;
	BYTE **new_popup;
	
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (item_number < addr->list_selected_item)
		addr->list_selected_item--;
	if (item_number < addr->list_highlighted_item)
		addr->list_highlighted_item++;
	if (item_number == addr->list_selected_item)
	{
		addr->list_selected_item = -1;
		addr->list_highlighted_item = -1;
	}
	if ((item_number) >= addr->list_total_num_items) return ERR_UI_ITEM_NUMBER_EXCEED;
	total_number = addr->list_total_num_items;
    qfree(addr->list_items[item_number]);  /* the corresponding item in the popup 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] = addr->list_items[i];
	}
	i = item_number;
	while (i<(total_number - 1))
	{
		new_popup[i] = addr->list_items[i+1];
		i++;
	}
	addr->list_total_num_items = total_number - 1;
    qfree(addr->list_items);
	addr->list_items = new_popup;
	return TRUE;
}

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

/********************************************************
* Function:	ListInsertItem
* Purpose:		to insert a new item in the list and the whole
list will be re-arranged again
* Scope:		Application
* Input:		list_id	    DBID of list 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
* Comment:     None
*********************************************************/
Err ListInsertItem(ObjectID list_id,USHORT item_number,BYTE *item_text)
{
    List    *addr;
    BYTE    object_type;
    WORD    i;
    USHORT  total_number;
    BYTE    **new_list;
    WORD    item_text_length = 0;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (item_number <= addr->list_selected_item)
		addr->list_selected_item++;
    if (item_number <= addr->list_highlighted_item)
		addr->list_highlighted_item++;
	if (item_number > addr->list_total_num_items)
		item_number = addr->list_total_num_items;
    total_number = addr->list_total_num_items;
    new_list = (BYTE **)qmalloc((total_number+1)*sizeof(BYTE *));
	
    item_text_length = strlen(item_text);
    i = 0;
	while (i <total_number)
	{
		if (i < item_number)
		{
			new_list[i] = addr->list_items[i];
		}
		else if ( i == item_number)
		{
			new_list[i] = (BYTE *)qmalloc((item_text_length+1)*sizeof(BYTE));
			strcpy (new_list[i],item_text);
			new_list[i+1] = addr->list_items[i];
		}
		else
		{
			new_list[i+1] = addr->list_items[i];
		}
		i++;
	}
	if (item_number == total_number)
	{
		new_list[item_number] = (BYTE *)qmalloc((item_text_length+1)*sizeof(BYTE));
		strcpy (new_list[item_number],item_text);
	}
	addr->list_total_num_items = (total_number + 1);
    qfree(addr->list_items);
	addr->list_items = new_list;
	return TRUE;
}
/********************************************************
* Function:	ListUpdateList
* Purpose:		to update the list object
* Scope:		Application
* Input:		list_id    	DBID of list object
new_top_num	the new top item number of the list
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     this function will draw the list object again too
*********************************************************/
Err ListUpdateList(ObjectID list_id,USHORT new_top_num)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	addr->list_top_item_num = new_top_num;
    ListDrawList(list_id);
	return TRUE;
}
/*********************************************************************
* Function	: ListClickedRegion
* Purpose	: To get the clicked region of the list object
* Scope		: Internal
* Input		: addr			Pointer to the address of the specified list object
*			  x_input
*			  y_input
* Output	: None
* Return	: return the region of the popup trigger
* Comment	: None
**********************************************************************/
USHORT ListClickedRegion(List *addr,SHORT x_input,SHORT y_input)
{
	if (x_input >= addr->list_arrow_up_bounds.xcoord &&
		x_input <  addr->list_arrow_up_bounds.xcoord+addr->list_arrow_up_bounds.width &&
		y_input >= addr->list_arrow_up_bounds.ycoord &&
		y_input <  addr->list_arrow_up_bounds.ycoord+addr->list_arrow_up_bounds.height &&
		addr->list_arrow_up == TRUE)
		return 1;
	
	if (x_input >= addr->list_arrow_down_bounds.xcoord &&
		x_input <  addr->list_arrow_down_bounds.xcoord+addr->list_arrow_down_bounds.width &&
		y_input >= addr->list_arrow_down_bounds.ycoord &&
		y_input <  addr->list_arrow_down_bounds.ycoord+addr->list_arrow_down_bounds.height &&
		addr->list_arrow_down == TRUE)
		return 2;
	
	/* default value */
	return 0;
}

/*********************************************************************
* Function	: ListSetScrollList
* Purpose	: To set the top item num of list object
* Scope		: Internal
* Input		: addr			Pointer to the address of the specified list
*			  up_down
* Output	: None
* Return	: None
* Comment	: Calculate the new top item number of the list object
**********************************************************************/
Err ListSetScrollList(ObjectID list_id,BYTE up_down)
{
	List *addr;
	SHORT top_item;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (up_down == MOVE_UP)
	{
		top_item = addr->list_top_item_num - addr->list_num_items_on_display;
		if (top_item < 0)
			top_item = 0;
		addr->list_top_item_num = top_item;
	}
	
	if (up_down == MOVE_DOWN)
	{
		top_item = addr->list_top_item_num + addr->list_num_items_on_display;
		if (top_item > addr->list_total_num_items - addr->list_num_items_on_display)
			addr->list_top_item_num = addr->list_total_num_items - addr->list_num_items_on_display;
        else addr->list_top_item_num = top_item;
	}
	return TRUE;
}

/*********************************************************************
* Function	: ListDrawBackgroundBox
* Purpose	: 
* Scope		: Internal
* Input		: object_id - DBID of the UI object
* Output	: None
* Return	: Return True if no error
*			  ERR_UI_RES_NOT_FOUND - Invalid object ID
**********************************************************************/
void ListDrawBackgroundBox (List *addr,ObjectBounds bounds,USHORT list_border)
{
	SHORT	draw_xcoord, draw_ycoord, draw_end_xcoord, draw_end_ycoord;
	ObjectBounds box;
	
    ListConvertStyle(addr);
	LcdEraseRegion(&bounds);
	/* The following draw the style of the particular List Box */
	if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
		LcdDrawBox(&bounds,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],DRAW_NOT_FILL);
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
	{
		/* Draw the upper horizontal line */
		draw_xcoord = bounds.xcoord+LIST_FIXED_CORNER;
		draw_ycoord = bounds.ycoord;
		draw_end_xcoord = bounds.xcoord+(bounds.width-1)-LIST_FIXED_CORNER;
		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]);
		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]);
		/* Draw the lower horizontal line */
		draw_xcoord = bounds.xcoord+LIST_FIXED_CORNER;
		draw_ycoord = bounds.ycoord+bounds.height-1;
		draw_end_xcoord = bounds.xcoord+bounds.width-1-LIST_FIXED_CORNER;
		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]);
		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+LIST_FIXED_CORNER;
		draw_end_xcoord = bounds.xcoord;
		draw_end_ycoord = bounds.ycoord+bounds.height-1-LIST_FIXED_CORNER;
		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]);
		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]);
		/* Draw the right vertical line */
		draw_xcoord = bounds.xcoord+bounds.width-1;
		draw_ycoord = bounds.ycoord+LIST_FIXED_CORNER;
		draw_end_xcoord = bounds.xcoord+bounds.width-1;
		draw_end_ycoord = bounds.ycoord+bounds.height-1-LIST_FIXED_CORNER;
		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]);
		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]);
		
		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_GREY1_COLOR],color_level[COLOR_GREY1_COLOR],DRAW_FILL);
		ControlDrawArc(&bounds,DRAW_NOT_FILL,LIST_FIXED_CORNER,color_level[COLOR_WHITE_COLOR]);
	}
	else if (addr->list_style == LIST_STYLE_6)
	{
		//		if (color_mode == GREYSCALE_MODE)
		LcdDrawBox(&bounds,addr->list_bg_color,addr->list_bg_color,DRAW_NOT_FILL);
		//		else LcdDrawBox(&bounds,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],DRAW_NOT_FILL);
	}		
}
/*********************************************************************
* Function	: ListDrawUpDownArrow
* Purpose	: To save the bounds of the specified popup trigger
* Scope		: Internal
* Input		: object_id - DBID of the UI object
* Output	: None
* Return	: Return True if no error
*			  ERR_UI_RES_NOT_FOUND - Invalid object ID
**********************************************************************/
void ListDrawUpDownArrow(List *addr,ObjectBounds *list_bounds)
{
	BitmapTemplate list_up_bitmap,list_down_bitmap;
	
	
	ListConvertStyle(addr);
	
	addr->list_arrow_up = FALSE;
	addr->list_arrow_down = FALSE;
	
	/* Assign the upper arrow */
	if (addr->list_top_item_num != 0)
	{
		list_up_bitmap.xcoord = list_bounds->xcoord+(list_bounds->width-1)-POPUP_SCROLL_ARROW_SIZE-LIST_BORDER;
		list_up_bitmap.ycoord = list_bounds->ycoord+LIST_SEPARATOR+1;
		list_up_bitmap.width  = POPUP_SCROLL_ARROW_SIZE;
		list_up_bitmap.height = POPUP_SCROLL_ARROW_SIZE;
		list_up_bitmap.compressed = FALSE;
        list_up_bitmap.quantisation = Q_FOUR_BIT;
		list_up_bitmap.size = FALSE;
		
		if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
			list_up_bitmap.bitmap_data = list_34_arrow_up;
		else
            list_up_bitmap.bitmap_data = arrow_up;
		
		addr->list_arrow_up = TRUE;
		/* If highlight And enter1 then Not Invert */
		if (addr->list_highlighted_item == addr->list_top_item_num && addr->list_attr.list_enter1 == TRUE)
			LcdDrawBitmap(&list_up_bitmap,NOT_INVERT);
		/* If highlight Or enter1 then Invert */
		else if (addr->list_highlighted_item == addr->list_top_item_num || addr->list_attr.list_enter1 == TRUE)
			LcdDrawBitmap(&list_up_bitmap,INVERT);
		/* Otherwise Not Invert */
		else
			LcdDrawBitmap(&list_up_bitmap,NOT_INVERT);
	}
	/* Assign the lower arrow */
	if ( addr->list_top_item_num + addr->list_num_items_on_display < addr->list_total_num_items)
	{
		list_down_bitmap.xcoord = list_bounds->xcoord+(list_bounds->width-1)-POPUP_SCROLL_ARROW_SIZE-LIST_BORDER;
		list_down_bitmap.ycoord = list_bounds->ycoord+(list_bounds->height-1)-POPUP_SCROLL_ARROW_SIZE-LIST_SEPARATOR-1;
		list_down_bitmap.width  = POPUP_SCROLL_ARROW_SIZE;
		list_down_bitmap.height = POPUP_SCROLL_ARROW_SIZE;
		list_down_bitmap.compressed = FALSE;
        list_down_bitmap.quantisation = Q_FOUR_BIT;
		list_down_bitmap.size = FALSE;
		
		if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
			list_down_bitmap.bitmap_data = list_34_arrow_down;
		else
            list_down_bitmap.bitmap_data = arrow_down;
		
		addr->list_arrow_down = TRUE;
		/* If highlight And enter2 then Not Invert */
		if ( addr->list_top_item_num + addr->list_num_items_on_display-1 ==
			addr->list_highlighted_item && addr->list_attr.list_enter2 == TRUE)
			LcdDrawBitmap(&list_down_bitmap,NOT_INVERT);
		/* If highlight Or enter2 then Invert */
		else if ( addr->list_top_item_num + addr->list_num_items_on_display-1 ==
			addr->list_highlighted_item || addr->list_attr.list_enter2 == TRUE)
			LcdDrawBitmap(&list_down_bitmap,INVERT);
		/* Otherwise Not Invert */
		else
			LcdDrawBitmap(&list_down_bitmap,NOT_INVERT);
	}
	addr->list_arrow_up_bounds.xcoord = list_up_bitmap.xcoord;
	addr->list_arrow_up_bounds.ycoord = list_up_bitmap.ycoord;
	addr->list_arrow_down_bounds.xcoord = list_down_bitmap.xcoord;
	addr->list_arrow_down_bounds.ycoord = list_down_bitmap.ycoord;
	addr->list_arrow_up_bounds.width = addr->list_arrow_up_bounds.height = POPUP_SCROLL_ARROW_SIZE;
	addr->list_arrow_down_bounds.width = addr->list_arrow_down_bounds.height = POPUP_SCROLL_ARROW_SIZE;
}
/********************************************************
* Function:	ListGetAttr
* Purpose:		to get all the attributes of a list object
* Scope:		Application
* Input:		list_id		DBID of list object
* Output:		enable_attr		Pointer to Boolean varaible to
show whether the cotnrol object is
enabled or not
drawn_attr		Pointer to Boolean variable to show
whether the cotnrol object is drawn
or not
active_attr		Pointer to Boolean variable to show
whether the list object is active or not
currently
visible_attr	Pointer to Boolean variable to show whether 
the object should be drawn on the screen or not
set_scroll_attr Pointer to Boolean variable to show whether 
arrow is displayed or not
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListGetAttribute(ObjectID list_id, BOOLEAN *enable_attr,
					 BOOLEAN *drawn_attr, BOOLEAN *active_attr, 
					 BOOLEAN *visible_attr, BOOLEAN *set_scroll_attr)
{
	List *list_addr;
	BYTE object_type;
	
	/* to find out the address of the specific list structure */
	/* if it can't find out the corresponding list object, then
	ErrResNotFound is returned */
	if (UISearchForAddress(list_id,&object_type,(void**)&list_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*enable_attr = (list_addr->list_attr).list_enable;
	*drawn_attr = (list_addr->list_attr).list_drawn;
	*active_attr = (list_addr->list_attr).list_active;
	*visible_attr = (list_addr->list_attr).list_visible;
	*set_scroll_attr = (list_addr->list_attr).list_set_scroll;
	return TRUE;
}
/*********************************************************************
* Function	: listSetAttribute
* Purpose	: Used to set the attribute of the list object
* Scope		: Application
* Input		: list_id - DBID of the list object
*			  att_drawn - Set the state of the list_drawn attribute
*			  att_enable - Set the state of the list_enable attribute
*		      att_active - Set the state of the schine_active attribute
*			  att_visible - Set the state of the list_visible attribute 	
*			  att_set_scroll - Set the state of the list_set_scroll	
* Output	: None
* Return	: Return True if no error or return ErrResNotFound if
*		  	  Invalid object ID
* Comment	: None
**********************************************************************/
Err ListSetAttribute(ObjectID list_id,BOOLEAN att_enable,BOOLEAN att_drawn,
					 BOOLEAN att_active, BOOLEAN att_visible, BOOLEAN att_set_scroll)
{
	List *addr;
	BYTE object_type;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) == TRUE)
	{
		addr->list_attr.list_drawn = att_drawn;
		addr->list_attr.list_enable = att_enable;
		addr->list_attr.list_active = att_active;
		addr->list_attr.list_visible = att_visible;
		addr->list_attr.list_set_scroll = att_set_scroll;
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}

/********************************************************
* Function:	ListInitList
* 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:		field_id	DBID of the list object
* Output:		None
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err ListInitList(ObjectID list_id)
{
	BYTE *buffer,*temp_buffer;
	UWORD byte_return;
	void *temp;
	List *addr;
	Err Error;
	BYTE object_type;
	BYTE **temp_list;
	WORD i;
	
	object_type = LIST;
	Error = UIAddressToLookupTable(list_id,object_type,&temp); /*put the pointer to the DBID											  lookup table */
	if (Error != TRUE) return Error;
	addr = (List *)temp;
    Error = ResOpen(list_id);
    if (Error != TRUE) return Error;
	addr->identification.ui_object_id = list_id;
	/* Field 0 */
	addr->identification.ui_object_type = LIST;
	/* Field 1 */
	ResGetField(list_id,1,&buffer,&byte_return);
	addr->identification.table_related = *(ObjectID*)buffer;
    qfree(buffer);
	/* Field 2 */
	ResReadField(list_id,2,0,2,&buffer,&byte_return);
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(list_id,2,2,2,&buffer,&byte_return);
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(list_id,2,4,2,&buffer,&byte_return);
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(list_id,2,6,2,&buffer,&byte_return);
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	/* Field 3 */
	ResGetField(list_id,3,&buffer,&byte_return);
	addr->list_num_related_list = *(USHORT*)buffer;
    qfree(buffer);
	/* Field 4 */
    addr->list_related_list_id = (ObjectID *)qmalloc(addr->list_num_related_list * sizeof(ObjectID));
	i = 0;
	while (i< addr->list_num_related_list)
	{
		ResReadField(list_id,4,(i * 2),2,&buffer,&byte_return);
		addr->list_related_list_id[i] = *(ObjectID *)buffer;
        qfree(buffer);
		i++;
	}
	/* Field 5 */
	ResGetField(list_id,5,&buffer,&byte_return);
	addr->list_total_num_items = *(USHORT*)buffer;
    qfree(buffer);
	
	/* Field 6 */
	ResGetField(list_id,6,&buffer,&byte_return);
	addr->list_num_items_on_display = *(USHORT*)buffer;
    qfree(buffer);
	
	/* Field 7 */
	ResGetField(list_id,7,&buffer,&byte_return);
	addr->list_top_item_num = *(USHORT*)buffer;
    qfree(buffer);
	
	/* Field 8 */
	ResGetField(list_id,8,&buffer,&byte_return);
	addr->list_text_alignment = *buffer;
    qfree(buffer);
	
	/* Field 9 */
	ResGetField(list_id,9,&buffer,&byte_return);
	addr->list_selected_item = *(USHORT*)buffer;
    qfree(buffer);
	
	addr->list_highlighted_item = -1;
	
	/* Field 10 */
	ResGetField(list_id,10,&buffer,&byte_return);
	addr->list_style = *buffer;
    qfree(buffer);
	
	/* Field 11 */
	ResGetField(list_id,11,&buffer,&byte_return);
	addr->list_text_color = UIColorConversion(*buffer);
    qfree(buffer);
	
	/* Field 12 */
	ResGetField(list_id,12,&buffer,&byte_return);
	addr->list_bg_color = UIColorConversion(*buffer);
    qfree(buffer);
	
	addr->list_arrow_up = FALSE;
	addr->list_arrow_down = FALSE;
	
	/* Field 13 */
	ResGetField(list_id,13,&buffer,&byte_return);
	temp_buffer = buffer;
    if (addr->list_total_num_items > 0)
        temp_list = (BYTE**)qmalloc(sizeof(BYTE*)*(addr->list_total_num_items));
	else temp_list = NULL;
	i = 0;
	while (i<addr->list_total_num_items)
	{
		temp_list[i] = (BYTE*)qmalloc(sizeof(BYTE)*(strlen(buffer)+1));
		strcpy(temp_list[i],buffer);
		buffer = buffer + strlen(buffer) + 1;
		i++;
	}
    qfree(temp_buffer);
	addr->list_items = temp_list;
    
	/* Field 14 */
	ResReadField(list_id,14,0,2,&buffer, &byte_return);
	addr->list_attr.list_enable = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(list_id,14,2,2,&buffer, &byte_return);
	addr->list_attr.list_visible = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(list_id,14,4,2,&buffer, &byte_return);
	addr->list_attr.list_active = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(list_id,14,6,2,&buffer, &byte_return);
	addr->list_attr.list_set_scroll = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(list_id,14,8,2,&buffer, &byte_return);
	addr->list_attr.list_synchronous = *(BOOLEAN*)buffer;
    qfree(buffer);
	/* Set up List variable */
	addr->list_text_font = SMALL_FONT;
	addr->list_item_height = FONT_HEIGHT[addr->list_text_font]+LIST_SEPARATOR*2;
	ListRecalculateMaxNumItemsDisplay(list_id);
	
	addr->list_attr.list_drawn = FALSE;
	addr->list_attr.list_enter1 = FALSE;
	addr->list_attr.list_enter2 = FALSE;
	
	ListConvertStyle(addr);
	
	ResClose(list_id);
	return TRUE;
}

/*********************************************************************
* Function	: ListDrawList
* Purpose	: Draw the list object on the display
* Scope		: Application
* Input		: DBID of the Control object
* Output	: None
* Return	: TRUE if no error
ErrUiResNotFound
* Comment	: None
**********************************************************************/
Err ListDrawList (ObjectID list_id)
{
	List *addr;
	USHORT 	list_border;
	WORD count;
	SHORT	text_length,draw_width;
	BYTE object_type,*draw_text;
	BOOLEAN last_flag = FALSE;
	SHORT draw_xcoord, draw_ycoord, draw_end_xcoord, draw_end_ycoord;
	ObjectBounds bounds,text,highlight;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (addr->list_attr.list_visible == FALSE) return FALSE;
	
	ListConvertStyle(addr);
	
	if (addr->identification.table_related == 0xFFFF) bounds = addr->bounds;
	else bounds = addr->screen_bounds;
	
	if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
		list_border = LIST_STYLE_12_BORDER;
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
		list_border = LIST_STYLE_34_BORDER;
	else
		list_border = 0;
	/* Call the following function to erase the region in any way */
	ListDrawBackgroundBox (addr,bounds,list_border);
	
	if ((addr->list_total_num_items - addr->list_top_item_num) >= addr->list_max_num_items_on_display)
		addr->list_num_items_on_display = addr->list_max_num_items_on_display;
	else
		addr->list_num_items_on_display = (addr->list_total_num_items - addr->list_top_item_num);
	
	addr->list_item_height = FONT_HEIGHT[addr->list_text_font]+LIST_SEPARATOR*2;
	
	if( addr->list_style == LIST_STYLE_0 || addr->list_style == LIST_STYLE_5 || addr->list_style == LIST_STYLE_7)
	{
		text.ycoord = bounds.ycoord+1;
		addr->list_max_num_items_on_display = (bounds.height - 1) / addr->list_item_height;
	}
	else if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
	{
		text.ycoord = bounds.ycoord+2;
		addr->list_max_num_items_on_display = (bounds.height - 2) / addr->list_item_height;
	}
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
	{
		text.ycoord = bounds.ycoord+3;
		addr->list_max_num_items_on_display = (bounds.height - 3) / addr->list_item_height;
	}
	text.width  = bounds.width - (list_border*2) - 1;
	
	if (addr->list_attr.list_set_scroll == TRUE)
		text.width -= POPUP_SCROLL_ARROW_SIZE;
	
	text.height = FONT_HEIGHT[addr->list_text_font];
	count = addr->list_top_item_num;
	
	while (count<= (addr->list_top_item_num + addr->list_num_items_on_display - 1))
	{
		text_length = strlen(addr->list_items[count]);
        draw_text = (BYTE*)qmalloc((text_length + 1)*sizeof(BYTE));
		strcpy(draw_text,(addr->list_items[count]));
		draw_width = StrGetWidth(draw_text,addr->list_text_font);
		
		if (addr->list_style != LIST_STYLE_7)
		{
			if (addr->list_text_alignment == LEFT_ALIGN)
				text.xcoord = bounds.xcoord+LIST_BORDER;
			else if (addr->list_text_alignment == CENTRE_ALIGN)
				text.xcoord = bounds.xcoord+(bounds.width-draw_width-POPUP_SCROLL_ARROW_SIZE)/2;
			else
				text.xcoord = bounds.xcoord+(bounds.width-1)-draw_width-LIST_BORDER-POPUP_SCROLL_ARROW_SIZE;
		}
		else
			text.xcoord = bounds.xcoord;
		
		if (addr->list_highlighted_item == count)
		{
			highlight.ycoord = text.ycoord-(addr->list_item_height-FONT_HEIGHT[addr->list_text_font])/2;
			highlight.height = addr->list_item_height+1;
			/* Set up the region to highlight the specified text */
			if(addr->list_style == LIST_STYLE_2 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_5)
			{
				if(addr->list_style != LIST_STYLE_2)
					highlight.xcoord = bounds.xcoord + list_border;
				else
					highlight.xcoord = bounds.xcoord + list_border + 1;
				
				highlight.width = StrGetWidth(draw_text,addr->list_text_font)+2;
				
				if ( highlight.width > bounds.width)
					highlight.width = bounds.width - list_border*2;
			}
			else if(addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_6)
			{
				if(addr->list_style != LIST_STYLE_1)
				{
					highlight.xcoord = bounds.xcoord + list_border;
					highlight.width = bounds.width - list_border*2;
				}
				else
				{
					highlight.xcoord = bounds.xcoord + list_border + 1;
					highlight.width = bounds.width - list_border*2 - 2;
				}
			}
			else if (addr->list_style == LIST_STYLE_7)
			{
				highlight.xcoord = bounds.xcoord;
				highlight.width = StrGetWidth(draw_text,addr->list_text_font);
				if ( highlight.width > bounds.width)
					highlight.width = bounds.width;
			}
			else
			{
				highlight.xcoord = bounds.xcoord;
				highlight.width = bounds.width;
			}
			
			if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
			{
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_GREY2_COLOR],FILL_EMPTY);
				//				else LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],FILL_EMPTY);
				/* Draw the right vertical line */
				draw_xcoord = highlight.xcoord + highlight.width-1;
				draw_ycoord = highlight.ycoord;
				draw_end_xcoord = highlight.xcoord + highlight.width-1;
				draw_end_ycoord = highlight.ycoord + highlight.height-1;
				LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
				/* Draw the bottom line */
				draw_xcoord = highlight.xcoord;
				draw_ycoord = highlight.ycoord + highlight.height-1;
				draw_end_xcoord = highlight.xcoord + highlight.width-1;
				draw_end_ycoord = highlight.ycoord + highlight.height-1;
				LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
				/* Draw Text */
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR], color_level[COLOR_GREY2_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
				//				else LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR], color_level[COLOR_BLACK_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
				/* Draw the left vertical line */
				draw_xcoord = highlight.xcoord;
				draw_ycoord = highlight.ycoord;
				draw_end_xcoord = highlight.xcoord;
				draw_end_ycoord = highlight.ycoord + highlight.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]);
			}
			else
			{
				LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],DRAW_FILL);				
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR],color_level[COLOR_BLACK_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
			}
		}
		else
		{
			if( addr->list_style == LIST_STYLE_6)
			{
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],addr->list_bg_color,addr->list_text_font,DOTDOT,MARGIN_0);
				//				else					
				//					LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);				
			}					
			else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_GREY1_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
			else
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
		}
		text.ycoord += addr->list_item_height;
        qfree(draw_text);
		count++;
	}
	
	if ( addr->list_attr.list_set_scroll == TRUE)
		ListDrawUpDownArrow(addr,&bounds);
	addr->list_attr.list_drawn = TRUE;
	return TRUE;
}

/*********************************************************************
* Function  : ListHighlightOneItem
* Purpose	: HightLight / DeHightLight a item on the list object
* Scope		: Application
* Input		: addr
* Output	: None
* Return	: TRUE if no error
*			  ErrUiResNotFound
* Comment	: None
**********************************************************************/
Err ListHighlightOneItem (List *addr, SHORT item_num, BOOLEAN item_onoff)
{
	BYTE	*draw_text;
	ObjectBounds bounds,text,highlight;
	SHORT	text_length,draw_width;
	SHORT	draw_xcoord, draw_ycoord, draw_end_xcoord, draw_end_ycoord;
	USHORT 	list_border;
	
	if (addr->list_attr.list_visible == FALSE) return FALSE;
	
	ListConvertStyle(addr);
	
	if (item_num >= addr->list_top_item_num && item_num < addr->list_top_item_num + addr->list_num_items_on_display)
	{
		if (addr->identification.table_related == 0xFFFF) 
			bounds = addr->bounds;
		else 
			bounds = addr->screen_bounds;
		
		if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
			list_border = LIST_STYLE_12_BORDER;
		else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
			list_border = LIST_STYLE_34_BORDER;
		else
			list_border =0;
		
		if( addr->list_style == LIST_STYLE_0 || addr->list_style == LIST_STYLE_5 || addr->list_style == LIST_STYLE_7)
			text.ycoord = bounds.ycoord+1;
		else if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
			text.ycoord = bounds.ycoord+2;
		else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
			text.ycoord = bounds.ycoord+3;
		
		text.ycoord += (item_num - addr->list_top_item_num) * addr->list_item_height;
		text.height = FONT_HEIGHT[addr->list_text_font];
		text.width  = bounds.width - (list_border*2) - 1;
		
		if (addr->list_attr.list_set_scroll == TRUE)
			text.width -= POPUP_SCROLL_ARROW_SIZE;
		
		text_length = strlen(addr->list_items[item_num]);
       	draw_text = (BYTE*)qmalloc((text_length + 1)*sizeof(BYTE));
		strcpy(draw_text,(addr->list_items[item_num]));
		draw_width = StrGetWidth(draw_text,addr->list_text_font);
		
		if (addr->list_style != LIST_STYLE_7)
		{
			if (addr->list_text_alignment == LEFT_ALIGN)
				text.xcoord = bounds.xcoord+LIST_BORDER;
			else if (addr->list_text_alignment == CENTRE_ALIGN)
				text.xcoord = bounds.xcoord+(bounds.width-draw_width-POPUP_SCROLL_ARROW_SIZE)/2;
			else
				text.xcoord = bounds.xcoord+(bounds.width-1)-draw_width-LIST_BORDER-POPUP_SCROLL_ARROW_SIZE;
		}
		else
			text.xcoord = bounds.xcoord;
		
		highlight.ycoord = text.ycoord-(addr->list_item_height-FONT_HEIGHT[addr->list_text_font])/2;
		highlight.height = addr->list_item_height+1;
		/* Set up the region to highlight the specified text */
		if(addr->list_style == LIST_STYLE_2 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_5)
		{
			if(addr->list_style != LIST_STYLE_2)
				highlight.xcoord = bounds.xcoord + list_border;
			else
				highlight.xcoord = bounds.xcoord + list_border + 1;
			
			highlight.width = StrGetWidth(draw_text,addr->list_text_font)+2;
			
			if ( highlight.width > bounds.width)
				highlight.width = bounds.width - list_border*2;
		}
		else if(addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_6)
		{
			if(addr->list_style != LIST_STYLE_1)
			{
				highlight.xcoord = bounds.xcoord + list_border;
				highlight.width = bounds.width - list_border*2;
			}
			else
			{
				highlight.xcoord = bounds.xcoord + list_border + 1;
				highlight.width = bounds.width - list_border*2 - 2;
			}
		}
		else if (addr->list_style == LIST_STYLE_7)
        {
			highlight.xcoord = bounds.xcoord;
			highlight.width = StrGetWidth(draw_text,addr->list_text_font);
			if ( highlight.width > bounds.width)
				highlight.width = bounds.width;
		}
		else
		{
			highlight.xcoord = bounds.xcoord;
			highlight.width = bounds.width;
		}
		
		if (item_onoff == TRUE)
		{			 
			if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
			{
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_GREY2_COLOR],FILL_EMPTY);
				//				else
				//					LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],FILL_EMPTY);										
				/* Draw the right vertical line */
				draw_xcoord = highlight.xcoord + highlight.width-1;
				draw_ycoord = highlight.ycoord;
				draw_end_xcoord = highlight.xcoord + highlight.width-1;
				draw_end_ycoord = highlight.ycoord + highlight.height-1;
				LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
				/* Draw the bottom line */
				draw_xcoord = highlight.xcoord;
				draw_ycoord = highlight.ycoord + highlight.height-1;
				draw_end_xcoord = highlight.xcoord + highlight.width-1;
				draw_end_ycoord = highlight.ycoord + highlight.height-1;
				LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
				/* Draw Text */
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR],color_level[COLOR_GREY2_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
				//				else
				//					LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR],color_level[COLOR_BLACK_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);									
				/* Draw the left vertical line */
				draw_xcoord = highlight.xcoord;
				draw_ycoord = highlight.ycoord;
				draw_end_xcoord = highlight.xcoord;
				draw_end_ycoord = highlight.ycoord + highlight.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]);
			}
			else
			{
				LcdDrawBox(&highlight,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],DRAW_FILL);
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_WHITE_COLOR],color_level[COLOR_BLACK_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
			}
		}
		else /* Item Off */
		{
           	if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
				LcdDrawBox(&highlight,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR],FILL_EMPTY);
			else if (addr->list_style == LIST_STYLE_6)
				LcdDrawBox(&highlight,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR],DRAW_FILL);
			else
				LcdDrawBox(&highlight,color_level[COLOR_WHITE_COLOR],color_level[COLOR_BLACK_COLOR],DRAW_FILL);
			
			
			if( addr->list_style == LIST_STYLE_6)
			{
				//				if (color_mode == GREYSCALE_MODE)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],addr->list_bg_color,addr->list_text_font,DOTDOT,MARGIN_0);
				//				else
				//					LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);										
			}					
			else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4)
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_GREY1_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
			else
				LcdDrawFixedString(&text,draw_text,color_level[COLOR_BLACK_COLOR],color_level[COLOR_WHITE_COLOR],addr->list_text_font,DOTDOT,MARGIN_0);
		}
        qfree(draw_text);
		
		if ( addr->list_attr.list_set_scroll == TRUE)
			ListDrawUpDownArrow(addr,&bounds);
		
		return TRUE;
	}
	return ERR_UI_INV_INPUT_VALUE;
}

/********************************************************
* Function:	ListSetNumItemsDisplay
* Purpose:		to set the the number of items that are displayed on the list object
* Scope:		Application
* Input:		list_id		    DBID of list object
num_items	    total number of displayed items in the list object
* Output:      None
* Return:		True if no error
ERR_UI_RES_NOT_FOUND
* Comment:     if the number is too large, then it will automatically set to maximum
*********************************************************/
Err ListSetNumItemsDisplay (ObjectID list_id,USHORT num_items)
{
	List *addr;
	BYTE object_type;
	USHORT max_num_items_displayed;
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	
	///    max_num_items_displayed = (addr->bounds.height-1)/(SysGetFontHeight(addr->list_text_font) + (2 * LIST_BORDER)) - 1;
	
	ListConvertStyle(addr);
	
	if( addr->list_style == LIST_STYLE_0 || addr->list_style == LIST_STYLE_5 || addr->list_style == LIST_STYLE_7)
		max_num_items_displayed = (addr->bounds.height-1)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
		max_num_items_displayed = (addr->bounds.height-2)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
		max_num_items_displayed = (addr->bounds.height-3)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	
    if (num_items > max_num_items_displayed) 
		addr->list_max_num_items_on_display = max_num_items_displayed;
    else 
		addr->list_max_num_items_on_display = num_items;
	return TRUE;
}

/********************************************************
* Function:	ListRecalculateMaxNumItemsDisplay
* Purpose:		to update the maximum number of items display
* Scope:		Application
* Input:		list_id    	DBID of list object
* Output:		None
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err ListRecalculateMaxNumItemsDisplay(ObjectID list_id)
{
	List *addr;
	BYTE object_type;
	ObjectBounds bounds;
	
	
	if (UISearchForAddress(list_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	ListConvertStyle(addr);
	
	if (addr->identification.table_related == 0xFFFF)
		bounds = addr->bounds;
	else bounds = addr->screen_bounds;
	
	if( addr->list_style == LIST_STYLE_0 || addr->list_style == LIST_STYLE_5 || addr->list_style == LIST_STYLE_7)
		addr->list_max_num_items_on_display = (bounds.height-1)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
		addr->list_max_num_items_on_display = (bounds.height-2)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
		addr->list_max_num_items_on_display = (bounds.height-3)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	
	return TRUE;
}

/********************************************************
* Function:	FieldSetFont
* Purpose:     to set the font of the field object
* Scope:		Application
* Input:       field_id 	        DBID of the spceified field object
font                font type for the field object
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err ListSetFont(ObjectID list_id, BYTE font)
{
	List	*addr;
	BYTE	object_type;
	ObjectBounds	bounds;
	
	
	if (UISearchForAddress(list_id,&object_type, (void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	ListConvertStyle(addr);
	
	if (addr->identification.table_related == 0xFFFF)
		bounds = addr->bounds;
	else 
		bounds = addr->screen_bounds;
	
	addr->list_text_font = font;
	
	if( addr->list_style == LIST_STYLE_0 || addr->list_style == LIST_STYLE_5 || addr->list_style == LIST_STYLE_7)
		addr->list_max_num_items_on_display = (bounds.height-1)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_1 || addr->list_style == LIST_STYLE_2)
		addr->list_max_num_items_on_display = (bounds.height-2)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	else if( addr->list_style == LIST_STYLE_3 || addr->list_style == LIST_STYLE_4 || addr->list_style == LIST_STYLE_6)
		addr->list_max_num_items_on_display = (bounds.height-3)/(LIST_SEPARATOR*2+FONT_HEIGHT[addr->list_text_font]);
	
	if (addr->identification.table_related != 0xFFFF)
		TableUpdateObjectScreenBounds(addr->identification.table_related, list_id);
	
    return TRUE;
}
