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


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

//#define DEBUG
//#define DEBUG_PB

extern  int totala, totalf;
void StrCharPosToXYForTable(Field *field_ptr, WORD char_pos, SHORT *xcoord, SHORT *ycoord);

/*********************************************************************
* Function	: TableDeleteTable
* Purpose	: To delete a table object from the memory
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
* Output	: None
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment	: The display will not be updated or erased accordingly
**********************************************************************/
Err TableDeleteTable(ObjectID table_id)
{
	Table *table_addr;
	BYTE object_type;
	USHORT num_of_cells;
	Err Error;
	USHORT i;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    num_of_cells = (table_addr->table_num_row) * (table_addr->table_num_column);
    for (i = 0;i<num_of_cells;i++)
	{
		qfree(((TableItems*)(table_addr->table_item_ptr[i]))->table_text); 
		qfree(table_addr->table_item_ptr[i]);
	}
    qfree(table_addr->table_item_ptr);
    qfree(table_addr->table_column_width);
    qfree(table_addr->table_row_height);
	Error = UIDeleteLookupTableElement(table_id); /* delete the corresponding element in the lookup table */
	if (Error !=TRUE) return Error;
    qfree(table_addr);
	return TRUE;
}
/*********************************************************************
* Function	: TableEnableTable
* Purpose	: To set the attribute table_enable of the table object
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
enable_attr   Boolean value of table_enable
* Output	: None
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment	: None
**********************************************************************/
Err TableEnableTable(ObjectID table_id, BOOLEAN enable_attr)
{
    Table *table_addr;
    BYTE object_type;
	
    if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    table_addr->table_attr.table_enable = enable_attr;
    return TRUE;
}
/*********************************************************************
* Function	: TableGetColumnWidth
* Purpose	: To return the width of a particular column in a table object
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
column_number the number for the column that we want
* Output	: column_width  pointer to value of the column width
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidColumnNo
* Comment	: None
**********************************************************************/
Err TableGetColumnWidth(ObjectID table_id, USHORT column_number, SHORT *column_width)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (column_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	*column_width = table_addr->table_column_width[column_number];
    return TRUE;
}
/*********************************************************************
* Function	: TableGetCellBounds
* Purpose	: To get the bounds of a particular cell in a table
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
row_number    the number for the row that we want
column_number the number for the column that we want
* Output	: cell_bounds   pointer to ObjectBounds structure
The x and y coordinates in the cell_bounds
are relative to the top-left corner of the table
Therefore, it is table relative
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidRowNo
ErrUIInvalidColumnNo
* Comment	: None
**********************************************************************/
Err TableGetCellBounds(ObjectID table_id, USHORT row_number,
					   USHORT column_number, ObjectBounds *cell_bounds)
{
	Table *table_addr;
	BYTE object_type;
	SHORT acc_width = 0;
	SHORT acc_height = 0;
	USHORT i;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_number >= table_addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (column_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	for (i = 0;i < row_number;i++)
		acc_height = acc_height + table_addr->table_row_height[i];
	for (i = 0;i <column_number;i++)
		acc_width = acc_width + table_addr->table_column_width[i];
	cell_bounds->xcoord = acc_width + table_addr->bounds.xcoord;
	cell_bounds->ycoord = acc_height + table_addr->bounds.ycoord;
	cell_bounds->width  = table_addr->table_column_width[column_number];
	cell_bounds->height = table_addr->table_row_height[row_number];
	return TRUE;
}
/*********************************************************************
* Function	: TableGetItemText
* Purpose	: To get the text in a particular cell of a table
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
row_number    the number for the row that we want
column_number the number for the column that we want
* Output	: item_text     Pointer to null-terminated string
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidRowNo
ErrUIInvalidColumnNo
* Comment	: None
**********************************************************************/
Err TableGetItemText (ObjectID table_id, USHORT row_number,
					  USHORT column_number, BYTE **item_text)
{
	Table *table_addr;
	BYTE object_type;
	USHORT cell_number;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_number >= table_addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (column_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	cell_number = (row_number * table_addr->table_num_column) + column_number;
	*item_text = ((TableItems*)(table_addr->table_item_ptr[cell_number]))->table_text;
	return TRUE;
}

/*********************************************************************
* Function	: TableGetTableBounds
* Purpose	: To get the bounds of a table object
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
* Output	: table_bounds  The bounds of a table object
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment	: None
**********************************************************************/
Err TableGetTableBounds (ObjectID table_id, ObjectBounds *table_bounds)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*table_bounds = table_addr->bounds;
	return TRUE;
}

/*********************************************************************
* Function	: TableGetNumOfColumns
* Purpose	: To get the number of columns of the table object
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
* Output	: num_columns   Pointer to value of the number of columns in
the table object
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment	: None
**********************************************************************/
Err TableGetNumOfColumns(ObjectID table_id, USHORT *num_columns)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*num_columns = table_addr->table_num_column;
	return TRUE;
}
/*********************************************************************
* Function	: TableGetRowColOfSelection
* Purpose	: To get the row number and column number of the selection
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
* Output	: row_number    Pointer to value of the row number of the selected cell
col_number    Pointer to value of the col number of the selected cell
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment	: None
**********************************************************************/
Err TableGetRowColOfSelection(ObjectID table_id, USHORT *row_number, USHORT *col_number)
{
    Table *table_addr;
    BYTE object_type;
	
    if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *row_number = table_addr->table_current_row;
    *col_number = table_addr->table_current_col;
    return TRUE;
}
/*********************************************************************
* Function	: TableSetColumnWidth
* Purpose	: To set the width of a particular column
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
col_number    the column number of the wanted column
new_width     the new width of the column
* Output	: None
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidColumnNo
* Comment	: None
**********************************************************************/
Err TableSetColumnWidth(ObjectID table_id, USHORT col_number, SHORT new_width)
{
    Table *table_addr;
    BYTE object_type;
	
    if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (col_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
    table_addr->table_column_width[col_number] = new_width;
    return TRUE;
	
}
/*********************************************************************
* Function	: TableSetItemValue
* Purpose	: To set teh value of a particular cell in a table
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
col_number    the column number of the wanted column
row_number    the row number of the wanted  row
new_value     the new value of the cell
* Output	: None
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidColumnNo
ErrUIInvalidRowNo
* Comment	: None
**********************************************************************/
Err TableSetItemValue(ObjectID table_id, USHORT col_number,
					  USHORT row_number,WORD new_value)
{
    Table *table_addr;
    BYTE object_type;
	USHORT cell_number;
	
    if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (col_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
    if (row_number >= table_addr->table_num_row) return ERR_UI_INVALID_COLUMN_NO;
    cell_number = (row_number * table_addr->table_num_column) + col_number;
    ((TableItems*)(table_addr->table_item_ptr[cell_number]))->table_value = new_value;
    return TRUE;
}
/*********************************************************************
* Function	: TableSetItemType
* Purpose	: To set the type of the item in a particular cell in a table
* Scope		: Application/Internal
* Input		: table_id	    ID of the table object
col_number    the column number of the wanted column
row_number    the row number of the wanted  row
new_type      the new item type of the cell
* Output	: None
* Return	: TRUE if no error
ERR_UI_RES_NOT_FOUND
ErrUIInvalidColumnNo
ErrUIInvalidRowNo
* Comment	: None
**********************************************************************/
Err TableSetItemType (ObjectID table_id, USHORT row_number,
					  USHORT col_number, BYTE new_type)
{
    Table *table_addr;
    BYTE object_type;
	USHORT cell_number;
	
    if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (col_number >= table_addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
    if (row_number >= table_addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
    cell_number = (row_number * table_addr->table_num_column) + col_number;
    ((TableItems*)(table_addr->table_item_ptr[cell_number]))->table_data_type = new_type;
    return TRUE;
}
/********************************************************
* Function:	TableEraseTable
* Purpose:	    to erase the drawn table object on the display
* Scope:		Application
* Input:		table_id		DBID of the table object
* Output:		None
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:		None
*********************************************************/
Err TableEraseTable(ObjectID table_id)
{
	Table *table_addr;
    void *temp;
	BYTE object_type;
	WORD i;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
#ifdef DEBUG
	printf("\n TableEraseTable");
#endif
	
	/* if the required table is active and drawn on the display */
	if (table_addr->table_attr.table_drawn == TRUE)
	{
		LcdEraseRegion(&(table_addr->bounds)); /* erase the bounds area */
		table_addr->table_attr.table_drawn = FALSE;
	}
	i = ((table_addr->table_num_column) * (table_addr->table_num_row));
    while (i)
    {
		i--;  
		if (((TableItems*)(table_addr->table_item_ptr[i]))->table_data_type == 2)
		{
			if (UISearchForAddress(((TableItems*)(table_addr->table_item_ptr[i]))->table_item_ui_id,
				&object_type,&temp) != TRUE) return ERR_UI_RES_NOT_FOUND;
			switch (object_type)
			{
			case CONTROL:
				((Control*)temp)->control_attr.control_drawn = FALSE;
				break;
			case FIELD:
				((Field*)temp)->field_attr.field_drawn = FALSE;
				break;
			case LIST:
				((List*)temp)->list_attr.list_drawn = FALSE;
				break;
			case STRING:
				((String*)temp)->string_attr.string_drawn = FALSE;
				break;
			case BITMAP:
				((Bitmap*)temp)->bitmap_attr.bitmap_drawn = FALSE;
				break;
			case TEXTBOX:
				((Textbox*)temp)->textbox_attr.textbox_drawn = FALSE;
				break;
			default: break;
			}
		}
    }
	return TRUE;
}
/********************************************************
* Function:	TableGetItemType
* Purpose:		To get the type of the specified item in a table
* Scope:		Application
* Input:		table_id			DBID of table object
*				row					the row number
*				column				the column number
* Output:		table_data_type		0=text,1=value/number,2=UI object
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetItemType(ObjectID table_id,USHORT row,USHORT column,BYTE *table_data_type)
{
	Table *table_addr;
	BYTE object_type;
	USHORT selected_cell;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	selected_cell = column+(row*table_addr->table_num_column);
	*table_data_type = ((TableItems *)(table_addr->table_item_ptr[selected_cell]))->table_data_type;
	return TRUE;
}
/********************************************************
* Function:	TableGetItemValue
* Purpose:		To get the value of the specified item in a table
* Scope:		Application
* Input:		table_id			DBID of table object
*				row					the row number
*				column				the column number
* Output:		table_value			the value/number of the item
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetItemValue(ObjectID table_id,USHORT row,USHORT column,WORD *table_value)
{
	Table *table_addr;
	BYTE object_type;
	USHORT selected_cell;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	selected_cell = column+(row*table_addr->table_num_column);
	*table_value = ((TableItems *)(table_addr->table_item_ptr[selected_cell]))->table_value;
	return TRUE;
}
/********************************************************
* Function:	TableGetNumOfRows
* Purpose:		To get the total number of rows in a table
* Scope:		Application
* Input:		table_id			DBID of table object
* Output:		table_num_row		the total number of rows in a table
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetNumOfRows(ObjectID table_id,USHORT *table_num_row)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	/* Return total num of row */
	*table_num_row = table_addr->table_num_row;
	return TRUE;
}
/********************************************************
* Function:	TableGetRowHeight
* Purpose:		To get the height of a particular row in the table
* Scope:		Application
* Input:		table_id			DBID of table object
*				row_num				the row number
* Output:		row_height			the height of a particular row
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetRowHeight(ObjectID table_id,USHORT row_num,SHORT *row_height)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	*row_height = table_addr->table_row_height[row_num];
	return TRUE;
}
/********************************************************
* Function:	TableSetBounds
* Purpose:		To set the bounds of the table
* Scope:		Application
* Input:		table_id			DBID of table object
*				table_bounds        the new bounds of the table
* Output:		None
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetBounds(ObjectID table_id,ObjectBounds table_bounds)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	table_addr->bounds = table_bounds;
	return TRUE;
}
/********************************************************
* Function:	TableSetRowHeight
* Purpose:		To set the height of a particular row in the table
* Scope:		Application
* Input:		table_id			DBID of table object
*				row_num				the row number
* 				row_height			the height of a particular row
* Output:		None
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetRowHeight(ObjectID table_id,USHORT row_num,SHORT row_height)
{
	Table *table_addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
    if (row_num >= table_addr->table_num_row) 
		return ERR_UI_INVALID_ROW_NO;
	table_addr->table_row_height[row_num] = row_height;
	return TRUE;
}
/********************************************************
* Function:	TableSetItemText
* Purpose:		To set the text string of the item
* Scope:		Application
* Input:		table_id			DBID of table object
*				row					the row number
*				column				the column number
*				text_string			Pointer to the string of
*									the specified item
* Output:		None
* Return:		TRUE if no error
*				ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetItemText(ObjectID table_id,USHORT row,USHORT column,BYTE *text_string)
{
	Table *table_addr;
	BYTE object_type;
	USHORT selected_cell;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&table_addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
    if (column >= table_addr->table_num_column) 
		return ERR_UI_INVALID_COLUMN_NO;
    if (row >= table_addr->table_num_row) 
		return ERR_UI_INVALID_ROW_NO;
	
	selected_cell = column+(row*table_addr->table_num_column);
    qfree(((TableItems *)(table_addr->table_item_ptr[selected_cell]))->table_text);
	((TableItems *)(table_addr->table_item_ptr[selected_cell]))->table_text
        = (BYTE*)qmalloc((strlen(text_string)+1)*sizeof(BYTE));
	strcpy(((TableItems *)(table_addr->table_item_ptr[selected_cell]))->table_text,text_string);
	return TRUE;
}
/********************************************************
* Function:	TableGetClickedCell
* Purpose:		To get the row, column & cell number of the
*				particular position
* Scope:		Application
* Input:		table_id			DBID of table object
*				x_coord				pen x-coordinate
*				y_coord				pen y-coordinate
* Output:		row_number			the row number
*				col_number			the column number
*				cell_number			the cell number
* Output:		None
* Return:		TRUE if no error
*				ErrUIResNotFound
* Comment:     None
*********************************************************/
Err TableGetClickedCell(ObjectID table_id,SHORT x_coord,SHORT y_coord,
						USHORT *row_number,USHORT *col_number,USHORT *cell_number)
{
	Table *addr;
	BYTE object_type;
	USHORT temp_height = 0,top_row,count=0,draw_height=0;
	WORD i,j;
	ObjectBounds temp;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (addr->table_attr.table_drawn == FALSE) return FALSE;
	if (addr->table_attr.table_enable == FALSE) return FALSE;
	count = (addr->table_top_row_num*addr->table_num_column);
	i = (addr->table_num_row-addr->table_top_row_num);
	while (i)
	{
		i--;
		draw_height += addr->table_row_height[i+addr->table_top_row_num];
	}
	if (addr->table_num_row_display == 1)
	{
		if (x_coord >= addr->bounds.xcoord && x_coord < addr->bounds.xcoord+addr->bounds.width &&
			y_coord >= addr->bounds.ycoord && y_coord < addr->bounds.ycoord+addr->bounds.height)
		{
			i = addr->table_top_row_num;
			temp.xcoord = addr->bounds.xcoord;
			temp.ycoord = addr->bounds.ycoord;
			j = 0;
			while (j < addr->table_num_column)
			{
				if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j])
				{
					if (((TableItems *)(addr->table_item_ptr[count]))->table_data_type < 2)
					{
						*row_number = (USHORT)i;
						*col_number = (USHORT)j;
						*cell_number = count;
						return TRUE;
					}
				}
				temp.xcoord = temp.xcoord+addr->table_column_width[j];
				count++;
				j++;
			}
		}
		return ERR_UI_INV_INPUT_COORD;
	}
	/* If table fully display on screen */
	if (draw_height < addr->bounds.height)
	{
		if (x_coord >= addr->bounds.xcoord && x_coord < addr->bounds.xcoord+addr->bounds.width &&
			y_coord >= addr->bounds.ycoord && y_coord < addr->bounds.ycoord+addr->bounds.height)
		{
			temp.xcoord = addr->bounds.xcoord;
			temp.ycoord = addr->bounds.ycoord;
			
			i = addr->table_top_row_num;
			while (i< addr->table_num_row)
			{
				j = 0;
				while (j< addr->table_num_column)
				{
					/* When clicked on the last row, check the column only */
					if (addr->table_top_row_num == (addr->table_num_row - 1))
					{
						if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j])
						{
							if (((TableItems *)(addr->table_item_ptr[count]))->table_data_type < 2)
							{
								*row_number = (USHORT)i;
								*col_number = (USHORT)j;
								*cell_number = count;
								return TRUE;
							}
						}
					}
					else
					{
						if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j] &&
							y_coord >= temp.ycoord && y_coord <= temp.ycoord+addr->table_row_height[i])
						{
							if (((TableItems *)(addr->table_item_ptr[count]))->table_data_type < 2)
							{
								*row_number = (USHORT)i;
								*col_number = (USHORT)j;
								*cell_number = count;
								return TRUE;
							}
						}
					}
					temp.xcoord = temp.xcoord+addr->table_column_width[j];
					count++;
					j++;
				}
				temp.xcoord = addr->bounds.xcoord;
				temp.ycoord = temp.ycoord+addr->table_row_height[i];
				i++;
			}
		}
		else
			return ERR_UI_INV_INPUT_COORD;
	}
	/* The table cannot fully display on screen */
	else
	{
		/* Get the top row of the display table */
		top_row = addr->table_top_row_num;
		
		i = addr->table_num_row_display;
		while (i)
		{	
			i--;
			temp_height = temp_height+addr->table_row_height[i+top_row];
		}
		/* Pen within the display region */
		if (x_coord >= addr->bounds.xcoord && x_coord < addr->bounds.xcoord+addr->bounds.width &&
			y_coord >= addr->bounds.ycoord && y_coord < addr->bounds.ycoord+temp_height)
		{
			temp.xcoord = addr->bounds.xcoord;
			temp.ycoord = addr->bounds.ycoord;
			
			i = addr->table_top_row_num;
			while (i< addr->table_num_row)
			{
				j = 0;
				while (j< addr->table_num_column)
				{
					if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j] &&
						y_coord >= temp.ycoord && y_coord <= temp.ycoord+addr->table_row_height[i])
					{
						if (((TableItems *)(addr->table_item_ptr[count]))->table_data_type < 2)
						{
							*row_number = (USHORT)i;
							*col_number = (USHORT)j;
							*cell_number = count;
							return TRUE;
						}
					}
					count++;
					temp.xcoord = temp.xcoord+addr->table_column_width[j];
					j++;
				}
				temp.xcoord = addr->bounds.xcoord;
				temp.ycoord = temp.ycoord+addr->table_row_height[i];
				i++;
			}
		}
		else
			return ERR_UI_INV_INPUT_COORD;
	}
	return FALSE;
}
/*********************************************************************
* Function	: TableEraseNotUIRegion
* Purpose	: To draw the specified table object on the display
* Scope		: Application
* Input		: DBID of the Table object
* Output	: None
* Return	: TRUE if no error
*			  ErrUiResNotFound
* Comment	: None
**********************************************************************/
Err TableEraseNotUIRegion(ObjectID table_item_id, ObjectBounds table_cell)
{
	void *addr;
	BYTE object_type;
	BOOLEAN	erase_whole_region = TRUE;
	ObjectBounds ui_object_bounds, clear_cell_bounds;
	
	if (UISearchForAddress(table_item_id,&object_type,&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	switch(object_type)
	{
	case BITMAP:	if (((Bitmap *)addr)->bitmap_attr.bitmap_visible == TRUE)
					{
						ui_object_bounds = ((Bitmap *)addr)->bounds;
						/* Keep the height & width but update x & y coordinate */
						ui_object_bounds.xcoord = ui_object_bounds.xcoord + table_cell.xcoord;
						ui_object_bounds.ycoord = ui_object_bounds.ycoord + table_cell.ycoord;
						erase_whole_region = FALSE;
					}
		break;
		
	case CONTROL:	if (((Control *)addr)->control_attr.control_visible == TRUE)
					{
						ui_object_bounds = ((Control *)addr)->bounds;
						ui_object_bounds.xcoord += table_cell.xcoord;
						ui_object_bounds.ycoord += table_cell.ycoord;						
						erase_whole_region = FALSE;
					}
		break;
		
	case FIELD:	if (((Field *)addr)->field_attr.field_visible == TRUE)
				{
					if (((Field *)addr)->field_attr.field_full_size == FALSE)
					{
						ui_object_bounds = ((Field *)addr)->bounds;
						ui_object_bounds.xcoord += table_cell.xcoord;
						ui_object_bounds.ycoord += table_cell.ycoord;						
					}
					else
						ui_object_bounds = clear_cell_bounds;
					
					erase_whole_region = FALSE;
				}
		break;		  
		
	case LIST:	if (((List *)addr)->list_attr.list_visible == TRUE)
				{
					ui_object_bounds = ((List *)addr)->bounds;
					ui_object_bounds.xcoord += table_cell.xcoord;
					ui_object_bounds.ycoord += table_cell.ycoord;
					erase_whole_region = FALSE;
				}
		break;
	case STRING:	if (((String *)addr)->string_attr.string_visible == TRUE)
					{
						ui_object_bounds = ((String *)addr)->bounds;
						ui_object_bounds.xcoord += table_cell.xcoord;
						ui_object_bounds.ycoord += table_cell.ycoord;
						erase_whole_region = FALSE;
					}
		break;
		
	case TEXTBOX:	if (((Textbox *)addr)->textbox_attr.textbox_visible == TRUE)
					{
						ui_object_bounds = ((Textbox *)addr)->bounds;
						ui_object_bounds.xcoord += table_cell.xcoord;
						ui_object_bounds.ycoord += table_cell.ycoord;
						erase_whole_region = FALSE;
					}
		break;
	}
	
	if (erase_whole_region == FALSE)
	{
		/* Clear the upper region of the cooresponding cell area */
		clear_cell_bounds = table_cell;
		clear_cell_bounds.height = ui_object_bounds.ycoord - clear_cell_bounds.ycoord;
		
		if (clear_cell_bounds.height)
			LcdEraseRegion(&clear_cell_bounds);
		
		/* Clear the lower region of the cooresponding cell area */
		clear_cell_bounds = table_cell;
		clear_cell_bounds.ycoord = ui_object_bounds.ycoord + ui_object_bounds.height;
		clear_cell_bounds.height = (table_cell.ycoord + table_cell.height) - clear_cell_bounds.ycoord;
		if (clear_cell_bounds.height)
			LcdEraseRegion(&clear_cell_bounds);
		
		/* Clear the left region of the cooresponding cell area */
		clear_cell_bounds = table_cell;
		clear_cell_bounds.width = ui_object_bounds.xcoord - clear_cell_bounds.xcoord;
		if (clear_cell_bounds.width)
			LcdEraseRegion(&clear_cell_bounds);
		
		/* Clear the right region of the cooresponding cell area */
		clear_cell_bounds = table_cell;
		clear_cell_bounds.xcoord = ui_object_bounds.xcoord + ui_object_bounds.width;
		clear_cell_bounds.width = (table_cell.xcoord + table_cell.width) - clear_cell_bounds.xcoord;
		if (clear_cell_bounds.width)
			LcdEraseRegion(&clear_cell_bounds);
	}
	else
        LcdEraseRegion(&table_cell);
	return TRUE;
}


/*********************************************************************
* Function	: TableDrawTable
* Purpose	: To draw the specified table object on the display
* Scope		: Application
* Input		: DBID of the Table object
* Output	: None
* Return	: TRUE if no error
*			  ErrUiResNotFound
* Comment	: None
**********************************************************************/
Err TableDrawTable(ObjectID table_id)
{
    ObjectID        table_item_id,active_form,active_object_id;
    ObjectBounds    cell,table,clear;
    Table           *addr;
    USHORT          i, j, cell_num=0, selected_cell=0;
    SHORT           draw_height=0, xcoord, ycoord;
    BYTE            object_type,cell_color=COLOR_WHITE_COLOR,clear_flag=0;
    Err             Error;
    void            *temp;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE)
        return ERR_UI_RES_NOT_FOUND;
    if (addr->table_attr.table_visible == FALSE)
        return FALSE;
	
#ifdef DEBUG
    printf("\n TableDrawTable");
#endif
	
    FormGetActiveFormID(&active_form);
	
	/* Initialize the table & cell */
	table = cell = addr->bounds;
	addr->table_num_row_display = addr->table_num_row - addr->table_top_row_num;
	addr->table_num_col_display = addr->table_num_column;
	
	/* Calculate the cell number in the upper left corner */
	cell_num = addr->table_num_column * (addr->table_top_row_num);
	selected_cell = addr->table_current_col+(addr->table_current_row*addr->table_num_column);
	
	/* Calculate the total height */
	for (i=0; i< (addr->table_num_row-addr->table_top_row_num); i++)
	{
		draw_height = draw_height + addr->table_row_height[i+addr->table_top_row_num];
		
		if (draw_height > addr->bounds.height)
		{
			draw_height -= addr->table_row_height[i+addr->table_top_row_num];
			addr->table_num_row_display = i;
			break;
		}
		else
			addr->table_num_row_display = i + 1;
	}
	
	/* Clear all UI's draw attribute */
    for (i = 0;i < ((addr->table_num_column) * (addr->table_num_row));i++)
    {
		if (((TableItems*)(addr->table_item_ptr[i]))->table_data_type == TABLE_UI_OBJECT)
		{
			if (UISearchForAddress(((TableItems*)(addr->table_item_ptr[i]))->table_item_ui_id,
				&object_type,&temp) != TRUE)
				return ERR_UI_RES_NOT_FOUND;
			switch (object_type)
			{
			case CONTROL:
				((Control*)temp)->control_attr.control_drawn = FALSE;
				break;
			case FIELD:
				((Field*)temp)->field_attr.field_drawn = FALSE;
				break;
			case LIST:
				((List*)temp)->list_attr.list_drawn = FALSE;
				break;
			case STRING:
				((String*)temp)->string_attr.string_drawn = FALSE;
				break;
			case BITMAP:
				((Bitmap*)temp)->bitmap_attr.bitmap_drawn = FALSE;
				break;
			case TEXTBOX:
				((Textbox*)temp)->textbox_attr.textbox_drawn = FALSE;
				break;
			default: break;
			}
		}
    }
	
	
	/* If table cannot fully display on screen */
	for (i=0; i< addr->table_num_row_display; i++)
	{
		for (j=0; j< addr->table_num_col_display; j++)
		{
			cell.width = addr->table_column_width[j]-1;
			cell.height = addr->table_row_height[i+addr->table_top_row_num]-1;
			
			if ((i == addr->table_num_row_display-1) && (addr->bounds.ycoord+addr->bounds.height > cell.ycoord+cell.height))
			{
				cell.height = cell.height+((addr->bounds.ycoord+addr->bounds.height)-(cell.ycoord+cell.height));
				
				if (clear_flag == 0)
				{
					clear = addr->bounds;;
					clear.ycoord = cell.ycoord;
					clear.height = table.ycoord + table.height - clear.ycoord;
					clear_flag = TRUE;
					LcdEraseRegion(&clear);
				}
			}
			
			if ( ((TableItems *)(addr->table_item_ptr[cell_num]))->table_data_type == TABLE_UI_OBJECT )
			{
				table_item_id =	((TableItems *)(addr->table_item_ptr[cell_num]))->table_item_ui_id;
				FormGetActiveObject(active_form,&active_object_id);
				TableUpdateObjectScreenBounds(table_id, table_item_id);
				if (active_object_id == table_item_id)
				{
					UISearchForAddress(table_item_id, &object_type, (void**)&temp);
					switch (object_type)
					{
					case FIELD:
						((Field*)temp)->field_attr.field_active = TRUE;
						if (((Field*)temp)->field_attr.field_insert_pt_visible)
						{
							StrAnalyzeLine((Field*)temp);
							StrCharPosToXYForTable((Field*)temp, ((Field*)temp)->field_insert_pt_char_pos,
								&((Field*)temp)->field_insert_pt_x, &((Field*)temp)->field_insert_pt_y);
							((Field*)temp)->field_attr.field_insert_pt_visible = TRUE;
						} 
						break;
					case TEXTBOX:
						((Textbox*)temp)->textbox_attr.textbox_active = TRUE;
						if (((Textbox*)temp)->textbox_attr.textbox_insert_pt_visible)
						{
							StrTextboxAnalyze((Textbox*)temp);
							StrTextboxCharPosToXY((Textbox*)temp, ((Textbox*)temp)->textbox_insert_pt_char_pos, 
								&((Textbox*)temp)->textbox_insert_pt_x, &((Textbox*)temp)->textbox_insert_pt_y);
							TextboxSetInsertPointPositionByXY(((Textbox*)temp)->identification.ui_object_id,
								((Textbox*)temp)->textbox_insert_pt_x,
								((Textbox*)temp)->textbox_insert_pt_y);
							((Textbox*)temp)->textbox_attr.textbox_insert_pt_visible = TRUE;
						}   
						break;
					default: FormObjectSetFocus(table_item_id);
					}
				}
				/* Clear the cooresponding cell's region */
				clear = cell;
				clear.width = addr->table_column_width[j];
				clear.height = addr->table_row_height[i+addr->table_top_row_num];
                if (table_item_id != table_id)
                {
                    TableEraseNotUIRegion(table_item_id, clear);
                    TableDrawUIObject(table_id,table_item_id,table,cell);
                }
                else
                    LcdEraseRegion(&clear);
			}
			else
			{				
				if (((TableItems *)(addr->table_item_ptr[cell_num]))->table_cell_highlight == TRUE ||
					(cell_num == selected_cell && addr->table_attr.table_enter == TRUE))
				{
					if (((TableItems *)(addr->table_item_ptr[cell_num]))->table_cell_highlight == TRUE &&
						(cell_num == selected_cell && addr->table_attr.table_enter == TRUE))
						cell_color = NOT_INVERT;
					else
						cell_color = INVERT;
				}
				else
					cell_color = NOT_INVERT;
				
				TableDrawDisplay(table_id,cell,cell_num,cell_color);
			}
			cell.xcoord = cell.xcoord+addr->table_column_width[j];
			cell_num++;
		}
		cell.xcoord = addr->bounds.xcoord;
		cell.ycoord = cell.ycoord+addr->table_row_height[i+addr->table_top_row_num];
	}
	
	if (addr->table_style == TABLE_STYLE_1 || addr->table_style == TABLE_STYLE_2)
		TableDrawTableBounds(table_id);
	addr->table_attr.table_drawn = TRUE;
	return TRUE;
}

/*********************************************************************
* Function	: TableDrawDisplay
* Purpose	: To draw a value, number or text in the table object
* Scope		: Internal
* Input		:
* Output	: None
* Return	: None
* Comment	: None
**********************************************************************/
Err TableDrawDisplay(ObjectID table_id,ObjectBounds cell,USHORT count,BYTE cell_color)
{
	Table *addr;
	ObjectBounds draw;
	BYTE *table_text,object_type,text_color,text_bg_color;
	SHORT text_width=0, bitmap_width=0;
	WORD table_value;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	if ( ((TableItems *)(addr->table_item_ptr[count]))->table_data_type == TABLE_TEXT )
	{
        table_text = (BYTE*)qmalloc((strlen(((TableItems *)(addr->table_item_ptr[count]))->table_text) + 1)*sizeof(BYTE));
		strcpy(table_text,((TableItems *)(addr->table_item_ptr[count]))->table_text);
	}
	else if ( ((TableItems *)(addr->table_item_ptr[count]))->table_data_type == TABLE_VALUE )
	{
        table_text = (BYTE*)qmalloc(10 * sizeof(BYTE));
		table_value = ((TableItems *)(addr->table_item_ptr[count]))->table_value;
		ltoa(table_value,(char*)table_text,10);
	}
	
	if (((TableItems *)(addr->table_item_ptr[count]))->table_cell_has_bitmap == TRUE)
	{
		addr->table_cell_bitmap.xcoord = cell.xcoord + cell.width-1 - 
			addr->table_cell_bitmap.width;
		addr->table_cell_bitmap.ycoord = cell.ycoord + (cell.height-addr->table_cell_bitmap.height)/2;
		LcdDrawBitmap(&(addr->table_cell_bitmap),NOT_INVERT);
		bitmap_width = addr->table_cell_bitmap.width + 1; /* Add one space */
	}
	
	switch (((TableItems *)(addr->table_item_ptr[count]))->table_display_alignment)
	{
	case 0: if (addr->table_style == TABLE_STYLE_0)				
				draw.xcoord = cell.xcoord;
		else
			draw.xcoord = cell.xcoord+1;
		
		draw.ycoord = cell.ycoord+(cell.height-FONT_HEIGHT[0])/2;
		draw.width  = cell.width-bitmap_width;
		draw.height = FONT_HEIGHT[0];
		break;
		
	case 1: text_width = StrGetWidth(table_text,SMALL_FONT)-2;
		draw.xcoord = cell.xcoord+(cell.width-text_width)/2;
		draw.ycoord = cell.ycoord+(cell.height-FONT_HEIGHT[0])/2;
		//draw.width  = cell.width-bitmap_width;
		draw.width = cell.xcoord + cell.width - draw.xcoord - bitmap_width;
		draw.height = FONT_HEIGHT[0];
		break;
		
	case 2: text_width = StrGetWidth(table_text,SMALL_FONT)-2;
		draw.xcoord = cell.xcoord+cell.width-text_width/*-TABLE_BORDER*/-1-bitmap_width;
		draw.ycoord = cell.ycoord+(cell.height-FONT_HEIGHT[0])/2;
		draw.width  = cell.width-bitmap_width;
		draw.height = FONT_HEIGHT[0];
		break;
	}
	
	text_color = ((TableItems *)(addr->table_item_ptr[count]))->table_text_color;
	text_bg_color = ((TableItems *)(addr->table_item_ptr[count]))->table_text_bg_color;
	
    if (cell_color == INVERT && text_width >= 0)
	{
		text_color = ColorInvert(text_color);
		text_bg_color = ColorInvert(text_bg_color);
	}
    if (cell.height != 0 && text_width >= 0 && strlen(table_text))
		LcdDrawFixedString(&draw,table_text,text_color,text_bg_color,SMALL_FONT,DOTDOT,MARGIN_0);
    qfree(table_text);
	return TRUE;
}
/*********************************************************************
* Function	: TableDrawTableBounds
* Purpose	:
* Scope		: Internal
* Input		:
* Output	: None
* Return	: None
* Comment	: None
**********************************************************************/
Err TableDrawTableBounds(ObjectID table_id)
{
	Table *addr;
	BYTE object_type;
	WORD i,j;
	SHORT start_x,start_y,end_x,end_y;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	/* Draw Horizontal lines */
	start_x = addr->bounds.xcoord;
	end_x = addr->bounds.xcoord+addr->bounds.width-1;
	start_y = end_y = addr->bounds.ycoord;
	
	if (addr->table_style == TABLE_STYLE_1)
		LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR], color_level[COLOR_BLACK_COLOR]);	
	else
	{
		i = 0;
		while (i< addr->table_num_row_display)
		{
			LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
			end_y = start_y = start_y+addr->table_row_height[i+addr->table_top_row_num];
			i++;
		}
	}
	
	/* Draw the bottom Horizontal line */
	start_y = end_y = addr->bounds.ycoord + addr->bounds.height -1;
	LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	/* Draw Vertical lines */
	start_y = addr->bounds.ycoord;
	end_y = addr->bounds.ycoord+addr->bounds.height-1;
	start_x = end_x = addr->bounds.xcoord;
	
	/*	j = addr->table_num_col_display;
	while (j)
	{
	j--;
	LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	end_x = start_x = start_x+addr->table_column_width[j];
	}
	*/	
	
	j = 0;
	do
	{
		LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
		end_x = start_x = start_x+addr->table_column_width[j];
		j++;
	}while (j < addr->table_num_col_display);
	
	
	
	/* Draw the last Vertical line */
	start_x = end_x = addr->bounds.xcoord + addr->bounds.width -1;
	LcdDrawLine(start_x,start_y,end_x,end_y,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	return TRUE;
}
/********************************************************
* Function:	TableUpdateTable
* Purpose:		To set the top_row_num and re-draw the table
* Scope:		Application
* Input:		table_id	DBID of the table object
top_row_num the top_row_num of the table
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableUpdateTable(ObjectID table_id, USHORT top_row_num)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	addr->table_top_row_num = top_row_num;
	TableDrawTable(table_id);
	return TRUE;
}
/*********************************************************************
* Function	: TableDrawUIObject
* Purpose	: To draw the specified table object on the display
* Scope		: Application
* Input		: DBID of the Table object
* Output	: None
* Return	: TRUE if no error
*			  ErrUiResNotFound
* Comment	: None
**********************************************************************/
Err TableDrawUIObject(ObjectID table_id,ObjectID table_item_id,ObjectBounds table, ObjectBounds cell)
{
	void *addr;
	Table *table_temp;
	BYTE object_type;
	SHORT height_sum = 0;
	Field *temp;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&table_temp) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (UISearchForAddress(table_item_id,&object_type,&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
	
	switch(object_type)
	{
	case CONTROL: /* Control Object */
		((Control *)addr)->screen_bounds = ((Control *)addr)->bounds;
		/* Keep the height & width  but change x & y coordinate */
		((Control *)addr)->screen_bounds.xcoord = ((Control *)addr)->bounds.xcoord+cell.xcoord;
		((Control *)addr)->screen_bounds.ycoord = ((Control *)addr)->bounds.ycoord+cell.ycoord;
		ControlDrawControl(table_item_id);
		break;
		
	case FIELD: /* Field Object */
		temp = (Field*)addr;
		if (((Field *)addr)->field_attr.field_full_size == FALSE)
		{
			((Field *)addr)->screen_bounds = ((Field *)addr)->bounds;
			((Field *)addr)->screen_bounds.xcoord = ((Field *)addr)->bounds.xcoord+cell.xcoord;
			((Field *)addr)->screen_bounds.ycoord = ((Field *)addr)->bounds.ycoord+cell.ycoord;
		}
		else
			((Field *)addr)->screen_bounds = cell;
		FieldDrawField(table_item_id);
		break;		  
		
	case LIST: /* List Object */
		((List *)addr)->screen_bounds = ((List *)addr)->bounds;
		((List *)addr)->screen_bounds.xcoord = ((List *)addr)->bounds.xcoord+cell.xcoord;
		((List *)addr)->screen_bounds.ycoord = ((List *)addr)->bounds.ycoord+cell.ycoord;
		ListDrawList(table_item_id);
		break;
		
	case STRING: /* String Object */
		((String *)addr)->screen_bounds = ((String *)addr)->bounds;
		((String *)addr)->screen_bounds.xcoord = ((String *)addr)->bounds.xcoord+cell.xcoord;
		((String *)addr)->screen_bounds.ycoord = ((String *)addr)->bounds.ycoord+cell.ycoord;
		StringDrawString(table_item_id);
		break;
		
	case BITMAP: /* Bitmap Object */
		((Bitmap *)addr)->screen_bounds = ((Bitmap *)addr)->bounds;
		((Bitmap *)addr)->screen_bounds.xcoord = ((Bitmap *)addr)->bounds.xcoord+cell.xcoord;
		((Bitmap *)addr)->screen_bounds.ycoord = ((Bitmap *)addr)->bounds.ycoord+cell.ycoord;
		BitmapDrawBitmap(table_item_id);
		break;
		
	case TEXTBOX:
		((Textbox *)addr)->screen_bounds = ((Textbox *)addr)->bounds;
		((Textbox *)addr)->screen_bounds.xcoord = ((Textbox *)addr)->bounds.xcoord+cell.xcoord;
		((Textbox *)addr)->screen_bounds.ycoord = ((Textbox *)addr)->bounds.ycoord+cell.ycoord;
		TextboxDrawTextbox(table_item_id);
		break;
	}
	return TRUE;
}
/********************************************************
* Function:	TableGetAttr
* Purpose:		to get all the attributes of a table object
* Scope:		Application
* Input:		control_id		DBID of control object
* Output:		enable_attr		Pointer to Boolean varaible to
show whether the table object is
enabled or not
drawn_attr		Pointer to Boolean variable to show
whether the table object is drawn
or not
active_attr		Pointer to Boolean variable to show
whether the control 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
scrollbar_attr	Pointer to Boolean variable to show whether 
the scrollbar related to that object 
is drawn or not
* Return:		TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetAttributes(ObjectID table_id, BOOLEAN *enable_attr,
					   BOOLEAN *drawn_attr, BOOLEAN *active_attr,
					   BOOLEAN *visible_attr, BOOLEAN *scrollbar_attr)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*enable_attr = addr->table_attr.table_enable;
	*drawn_attr = addr->table_attr.table_drawn;
	*active_attr = addr->table_attr.table_active;
	*visible_attr = addr->table_attr.table_visible;
	*scrollbar_attr = addr->table_attr.table_scrollbar;
	return TRUE;
}
/*********************************************************************
* Function	: TableSetAttribute
* Purpose	: Used to set the attribute of the table object
* Scope		: Application
* Input		: table_id - DBID of the table object
*			  att_drawn - Set the state of the table_drawn attribute
*			  att_enable - Set the state of the table_enable attribute
*		      att_active - Set the state of the schine_active attribute
*		      att_scrollbar - Set the state of the table_scrollbar
*								  attribute
*			  attr_visible	- Set the state of the table_visible attribute
* Output	: None
* Return	: Return True if no error or return ErrResNotFound if
*		  	  Invalid object ID
* Comment	: None
**********************************************************************/
Err TableSetAttributes(ObjectID table_id,BOOLEAN att_enable,BOOLEAN att_drawn,
					   BOOLEAN att_active, BOOLEAN att_visible, BOOLEAN att_scrollbar)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) == TRUE)
	{
		addr->table_attr.table_drawn = att_drawn;
		addr->table_attr.table_enable = att_enable;
		addr->table_attr.table_active = att_active;
		addr->table_attr.table_scrollbar = att_scrollbar;
		addr->table_attr.table_visible = att_visible;
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	TableDrawFieldFullSize
* Purpose:		To Draw a table if field is assigned to be full size
* Scope:		Application
* Input:		addr	Pointer to table object
* Output:		None
* Return:      TRUE if talbe is drawn while field (in full size) is found
FALSE if no table with full-size field object
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableDrawFieldFullSize(Table *addr)
{
	ObjectID table_item_id;
	ObjectBounds cell;
	USHORT cell_num=0,selected_cell;
	WORD i;
	BYTE object_type, cell_color;
	BOOLEAN found = FALSE;
	void *temp;
	
	
	cell_num = addr->table_num_column * (addr->table_top_row_num);
	selected_cell = addr->table_current_col+(addr->table_current_row*addr->table_num_column);
	i = cell_num;
	while (i<(addr->table_num_column + cell_num))
	{
		if ((addr->table_item_ptr[i])->table_data_type !=2)
		{
			i++;
			continue;
		}
		table_item_id = (addr->table_item_ptr[i])->table_item_ui_id; 	
		if (UISearchForAddress(table_item_id,&object_type,(void **)&temp) != TRUE) return ERR_UI_RES_NOT_FOUND;
		if (object_type != FIELD)
		{
			i++;
			continue;
		}
		if (((Field*)temp)->field_attr.field_full_size)
		{
			found = TRUE;
			break;
		}
		i++;
	}
	if (!found) return FALSE;
	addr->table_num_row_display = 1;
	addr->table_num_col_display = addr->table_num_column;
	
	/* initialise the cell bounds */
	i = 0;
	while (i< addr->table_num_column)
	{ 
		if (i == 0)
		{	
			cell.xcoord = addr->bounds.xcoord;
			cell.ycoord = addr->bounds.ycoord;
			cell.height = addr->bounds.height;
			cell.width =  addr->table_column_width[i];
		}
		else 
		{
			cell.xcoord += (cell.width -1);
			cell.width = addr->table_column_width[i];
		}
		if (((TableItems *)(addr->table_item_ptr[cell_num]))->table_cell_highlight == TRUE ||
			(cell_num == selected_cell && addr->table_attr.table_enter == TRUE))
		{
			if (((TableItems *)(addr->table_item_ptr[cell_num]))->table_cell_highlight == TRUE &&
				(cell_num == selected_cell && addr->table_attr.table_enter == TRUE))
				cell_color = NOT_INVERT;
			else
				cell_color = INVERT;
		}
		else
			cell_color = NOT_INVERT;
		
		if ((addr->table_item_ptr[cell_num + i])->table_data_type <2)
			TableDrawDisplay(addr->identification.ui_object_id, cell, (USHORT)(cell_num + i), cell_color);
		else TableDrawUIObject(addr->identification.ui_object_id,
	 					     (addr->table_item_ptr[cell_num + i])->table_item_ui_id, 	
							 addr->bounds,cell);
		i++;
	}
	addr->table_attr.table_drawn = TRUE;
	TableDrawTableBounds(addr->identification.ui_object_id);
	return TRUE;
}
/********************************************************
* Function:	TableGetTopRowNum
* Purpose:		To get the top row num of the table
* Scope:		Application
* Input:		table_id	    DBID of the table object
* Output:		top_num			Pointer to value of top_num
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetTopRowNum(ObjectID table_id, USHORT *top_num)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*top_num = addr->table_top_row_num;
	return TRUE;
}
/********************************************************
* Function:	TableSetTopRowNum
* Purpose:		To get the top row num of the table
* Scope:		Application
* Input:		table_id	    DBID of the table object
top_num			top row number
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetTopRowNum(ObjectID table_id, USHORT top_num)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) 
		return ERR_UI_RES_NOT_FOUND;
    
	if (top_num >= addr->table_num_row) 
		return ERR_UI_INVALID_ROW_NO;
	
	addr->table_top_row_num = top_num;
	return TRUE;
}
/********************************************************
* Function:	TableGetNumOfRowsDisplayed
* Purpose:		To get the the number of rows displayed
* Scope:		Application
* Input:		table_id	    DBID of the table object
* Output:		num_row			Pointer to that value
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableGetNumOfRowsDisplayed(ObjectID table_id, USHORT *num_row)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*num_row = addr->table_num_row_display;
	return TRUE;
}
/********************************************************
* Function:	TableSetHighlightCell
* Purpose:		to set or clear the highlight attribute of a particular 
*				cell of a table
* Scope:		Application
* Input:		table_id		DBID of the table object
*				row_num			the row number of wanted cell
*				col_num			the column number of the wanted cell
*				highlight_on	Boolean variable to set or clear the attr
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetHighlightCell(ObjectID table_id, USHORT row_num, 
						  USHORT col_num, BOOLEAN highlight_on)
{
	Table *addr;
	BYTE object_type;
	USHORT cell_number;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_num >= addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (col_num >= addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	cell_number = row_num * addr->table_num_column + col_num;
	addr->table_item_ptr[cell_number]->table_cell_highlight = highlight_on;
	return TRUE;
}
/********************************************************
* Function:	TableCheckCellHighlight
* Purpose:		to check whether the cell is set to highlight or not
*				cell of a table
* Scope:		Application
* Input:		table_id		DBID of the table object
*				row_num			the row number of wanted cell
*				col_num			the column number of the wanted cell
* Output:		cell_highlight	Pointer to Boolean variable to set or clear the attr
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableCheckCellHighlight(ObjectID table_id, USHORT row_num, 
							USHORT col_num, BOOLEAN *cell_highlight)
{
	Table *addr;
	BYTE object_type;
	USHORT cell_number;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_num >= addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (col_num >= addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	cell_number = row_num * addr->table_num_column + col_num;
	*cell_highlight = addr->table_item_ptr[cell_number]->table_cell_highlight;
	return TRUE;
}
/********************************************************
* Function:	TableSetCellHasBitmap
* Purpose:		to set or clear whether there is a bitmap in the cell
* Scope:		Application
* Input:		table_id		DBID of the table object
*				row_num			the row number of wanted cell
*				col_num			the column number of the wanted cell
*				bitmap_on		Boolean variable to set or clear the attr
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetCellHasBitmap(ObjectID table_id, USHORT row_num, 
						  USHORT col_num, BOOLEAN bitmap_on)
{
	Table *addr;
	BYTE object_type;
	USHORT cell_number;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_num >= addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (col_num >= addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	cell_number = row_num * addr->table_num_column + col_num;
	addr->table_item_ptr[cell_number]->table_cell_has_bitmap = bitmap_on;
	return TRUE;
}
/********************************************************
* Function:	TableCheckCellHasBitmap
* Purpose:		to check whether the cell is has bitmap or not
* Scope:		Application
* Input:		table_id		DBID of the table object
*				row_num			the row number of wanted cell
*				col_num			the column number of the wanted cell
* Output:		cell_bitmap		Pointer to Boolean variable to set or clear the attr
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableCheckCellHasBitmap(ObjectID table_id, USHORT row_num, 
							USHORT col_num, BOOLEAN *cell_bitmap)
{
	Table *addr;
	BYTE object_type;
	USHORT cell_number;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (row_num >= addr->table_num_row) return ERR_UI_INVALID_ROW_NO;
	if (col_num >= addr->table_num_column) return ERR_UI_INVALID_COLUMN_NO;
	cell_number = row_num * addr->table_num_column + col_num;
	*cell_bitmap = addr->table_item_ptr[cell_number]->table_cell_has_bitmap;
	return TRUE;
}
/********************************************************
* Function:	TableSetHighlightEnable
* Purpose:		to 
* Scope:		Application
* Input:		table_id			DBID of the table object
*				highlight_enable	Boolean variable to set or clear the attr
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableSetHighlightEnable(ObjectID table_id, BOOLEAN highlight_enable)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	addr->table_attr.table_highlight_enable = highlight_enable;
	return TRUE;
}
/********************************************************
* Function:	TableCheckHighlightEnable
* Purpose:		to check whether the cell is has bitmap or not
* Scope:		Application
* Input:		table_id			DBID of the table object
* Output:		highlight_enable	Pointer to Boolean variable to set or clear the attr
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableCheckHighlightEnable(ObjectID table_id, BOOLEAN *highlight_enable)
{
	Table *addr;
	BYTE object_type;
	
	if (UISearchForAddress(table_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*highlight_enable = addr->table_attr.table_highlight_enable;
	return TRUE;
}

/*********************************************************************
* Function	: TableUpdateObjectScreenObjects
* Purpose	: This function is called to update the screen bounds of an object
within the table when the bounds is chagned before drawing
* Scope		: Internal
* Input		: table_id
object_id
row_num
cell_num
* Output	: None
* Return	: None
* Comment	: None
**********************************************************************/
BOOLEAN TableUpdateObjectScreenBounds(ObjectID table_id, ObjectID object_id/*, USHORT row_num, USHORT col_num*/)
{
	Table *table_ptr;
	void *addr;
	BYTE object_type;
	USHORT cell_num;
	USHORT y_margin = 0;
	USHORT x_margin = 0;
	WORD i;
	WORD count;
	BOOLEAN found = FALSE;
	USHORT row_num;
	USHORT col_num;
	
	
	if (UISearchForAddress(table_id, &object_type, (void**)&table_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
#ifdef DEBUG_PB
	printf("\n Table Update 1");
	printf("\n Table Update 1a = %ld %ld", table_ptr->table_num_row, table_ptr->table_num_column);
#endif		
	
	count = (table_ptr->table_num_row * table_ptr->table_num_column);
	while (count)
	{
		count--;
#ifdef DEBUG_PB
		printf("\n Table Update 1b = %ld", ((TableItems*)(table_ptr->table_item_ptr[count]))->table_item_ui_id);
#endif		
		if (object_id == ((TableItems*)(table_ptr->table_item_ptr[count]))->table_item_ui_id)
		{
			
			cell_num = (USHORT)count;
			col_num = (cell_num) % (table_ptr->table_num_column);
			row_num = (cell_num - col_num) / (table_ptr->table_num_column);
			found = TRUE;
			break;
		}
	}
	if (found == FALSE) return ERR_UI_RES_NOT_FOUND;
	
#ifdef DEBUG_PB
	printf("\n Table Update 1");
#endif		
	
	
	
	if (UISearchForAddress(object_id, &object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	
#ifdef DEBUG_PB
	printf("\n Table Update 3");
#endif		
	
	
	i = table_ptr->table_top_row_num;
	while (i<row_num)
	{	
		y_margin += table_ptr->table_row_height[i];
		i++;
	}
	y_margin += table_ptr->bounds.ycoord;
	
	i = col_num;
	while (i)
	{	
		i--;
		x_margin += table_ptr->table_column_width[i];
	}
	x_margin += table_ptr->bounds.xcoord;
	
	switch(object_type)
	{
	case CONTROL: ((Control*)addr)->screen_bounds = ((Control*)addr)->bounds;
		((Control*)addr)->screen_bounds.xcoord = ((Control*)addr)->bounds.xcoord + x_margin;
		((Control*)addr)->screen_bounds.ycoord = ((Control*)addr)->bounds.ycoord + y_margin;
		break;
	case FIELD:   
		
#ifdef	DEBUG_PB
		printf("\n TableUpdateObjectScreenBounds = %ld", object_id);
		printf("\n OLD screen_bounds.width = %ld screen_bounds.height = %ld", ((Field*)addr)->screen_bounds.width, ((Field*)addr)->screen_bounds.height);
#endif					  
		((Field*)addr)->screen_bounds = ((Field*)addr)->bounds;
		((Field*)addr)->screen_bounds.xcoord = ((Field*)addr)->bounds.xcoord + x_margin;
		((Field*)addr)->screen_bounds.ycoord = ((Field*)addr)->bounds.ycoord + y_margin;
#ifdef DEBUG_PB
		printf("\n NEW screen_bounds.width = %ld screen_bounds.height = %ld", ((Field*)addr)->screen_bounds.width, ((Field*)addr)->screen_bounds.height);					  
#endif					  
		break;
	case LIST:    ((List*)addr)->screen_bounds = ((List*)addr)->bounds;
		((List*)addr)->screen_bounds.xcoord = ((List*)addr)->bounds.xcoord + x_margin;
		((List*)addr)->screen_bounds.ycoord = ((List*)addr)->bounds.ycoord + y_margin;
		break;
	case STRING:   ((String*)addr)->screen_bounds = ((String*)addr)->bounds;
		((String*)addr)->screen_bounds.xcoord = ((String*)addr)->bounds.xcoord + x_margin;
		((String*)addr)->screen_bounds.ycoord = ((String*)addr)->bounds.ycoord + y_margin;
		break;
	case TEXTBOX:   ((Textbox*)addr)->screen_bounds = ((Textbox*)addr)->bounds;
		((Textbox*)addr)->screen_bounds.xcoord = ((Textbox*)addr)->bounds.xcoord + x_margin;
		((Textbox*)addr)->screen_bounds.ycoord = ((Textbox*)addr)->bounds.ycoord + y_margin;
		break;
	case BITMAP:   ((Bitmap*)addr)->screen_bounds = ((Bitmap*)addr)->bounds;
		((Bitmap*)addr)->screen_bounds.xcoord = ((Bitmap*)addr)->bounds.xcoord + x_margin;
		((Bitmap*)addr)->screen_bounds.ycoord = ((Bitmap*)addr)->bounds.ycoord + y_margin;
		break;
	default: return TRUE;
	}
	
#ifdef DEUBG_PB
	printf("\n Table Update 4");
#endif		
	
	return TRUE;
}

/*********************************************************************
* Function	: TableUpdateNumRowDisplay
* Purpose	: This function is called to update the num of row that will be 
displayed in the table
* Scope		: Application/Internal
* Input		: table_id
ref_col
* Output	: None
* Return	: None
* Comment	: Assume that there is teh reference column is full of field objects
**********************************************************************/
BOOLEAN TableUpdateNumRowDisplay(ObjectID table_id, USHORT ref_col)
{
	USHORT field_id;
	BYTE object_type;
	Field *field_ptr;
	Table *addr;
	WORD count;
	SHORT line_height;
	BYTE font;
	WORD table_max_num_lines;
	WORD acc_num_lines = 0;
	
	if (UISearchForAddress(table_id, &object_type, (void**)&addr) == FALSE)
		return ERR_UI_RES_NOT_FOUND;
	field_id = addr->table_item_ptr[ref_col]->table_item_ui_id;
	FieldGetFont(field_id, &font);
	line_height = FONT_HEIGHT[font] + SPACE_LINE;
	table_max_num_lines = addr->bounds.height/line_height;
	count = addr->table_top_row_num;
	while (count < addr->table_num_row)
	{
		field_id = addr->table_item_ptr[addr->table_num_column * count + ref_col]->table_item_ui_id;
		if (UISearchForAddress(field_id, &object_type, (void**)&field_ptr) == FALSE)
			return ERR_UI_RES_NOT_FOUND;
		acc_num_lines += field_ptr->bounds.height/line_height;
		if (acc_num_lines > table_max_num_lines)
		{
			addr->table_num_row_display = count - addr->table_top_row_num;
			return TRUE;
		}
		count++;
	}
	addr->table_num_row_display = addr->table_num_row - addr->table_top_row_num; 
	return TRUE;
}

/********************************************************
* Function:	TableInitTable
* Purpose:		1) to initialise the table object
2) to read the resource file
3) to create a corresponding line structure
in RAM
* Scope:		Application
* Input:		table_id	DBID of the table object
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     None
*********************************************************/
Err TableInitTable(ObjectID table_id)
{
	BYTE *buffer;
	UWORD byte_return;
	void *temp;
	Table *addr;
	Err Error;
	BYTE object_type;
    USHORT total_num_cells;
	WORD i;
    USHORT acc_length = 0;
    UWORD field_size, length = 0;
	
    object_type = TABLE;
	/*put the pointer to the DBID lookup table */
	Error = UIAddressToLookupTable(table_id,object_type,&temp);
	if (Error != TRUE) return Error;
	addr = (Table *)temp;
	/*check whether the resource file	is opened */
    Error = ResOpen(table_id);
    if (Error != TRUE) return Error;
	
	addr->identification.ui_object_id = table_id;
	/* Field 0 */
	ResGetField(table_id,0,&buffer,&byte_return);
	addr->identification.ui_object_type = *buffer;
    qfree(buffer);
	/* Field 1 */
	ResReadField(table_id,1,0,2,&buffer,&byte_return);
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(table_id,1,2,2,&buffer,&byte_return);
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(table_id,1,4,2,&buffer,&byte_return);
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(table_id,1,6,2,&buffer,&byte_return);
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	/* Field 2 */
	ResGetField(table_id,2,&buffer,&byte_return);
	addr->table_num_column = *(USHORT*)buffer;
    qfree(buffer);
	/* Field 3 */
	ResGetField(table_id,3,&buffer,&byte_return);
	addr->table_num_row = *(USHORT*)buffer;
    qfree(buffer);
	/* Field 4 */
    addr->table_column_width = (SHORT*)qmalloc(addr->table_num_column*sizeof(SHORT));
	i = 0;
	while (i <(addr->table_num_column))
	{
		ResReadField(table_id,4,(i*2),2,&buffer,&byte_return);
		addr->table_column_width[i] = *(SHORT*)buffer;
		qfree(buffer);
		i++;
    }
	/* Field 5 */
    addr->table_row_height = (SHORT*)qmalloc(addr->table_num_row*sizeof(SHORT));
	i = 0;
    while (i <(addr->table_num_row))
    {
		ResReadField(table_id,5,(i*2),2,&buffer,&byte_return);
		addr->table_row_height[i] = *(SHORT*)buffer;
		qfree(buffer);
		i++;
	}
    /* Field 6 */
	ResGetField(table_id,6,&buffer,&byte_return);
	addr->table_top_row_num = *(USHORT*)buffer;
    qfree(buffer);
    /* Field 7 */
	ResGetField(table_id,7,&buffer,&byte_return);
	addr->table_left_col_num = *(USHORT*)buffer;
    qfree(buffer);
    /* Field 8 */
	ResGetField(table_id,8,&buffer,&byte_return);
	addr->table_style = *buffer;
    qfree(buffer);
	/* Field 9 */
	ResGetField(table_id,9,&buffer,&byte_return);
	addr->table_bg_color = UIColorConversion(*buffer);
    qfree(buffer);
	/* Field 10 */
	ResFieldSize(table_id,10,&field_size);
	if (field_size > 8)
	{
		ResReadField(table_id,10,0,2,&buffer,&byte_return);
		addr->table_cell_bitmap.xcoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(table_id,10,2,2,&buffer,&byte_return);
		addr->table_cell_bitmap.ycoord = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(table_id,10,4,2,&buffer,&byte_return);
		addr->table_cell_bitmap.width = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(table_id,10,6,2,&buffer,&byte_return);
		addr->table_cell_bitmap.height = *(SHORT*)buffer;
		qfree(buffer);
		ResReadField(table_id,10,8,1,&buffer,&byte_return);
		addr->table_cell_bitmap.compressed = *buffer;
		qfree(buffer);
		ResReadField(table_id,10,9,1,&buffer,&byte_return);
		addr->table_cell_bitmap.quantisation = *buffer;
		qfree(buffer);
		ResReadField(table_id,10,10,2,&buffer,&byte_return);
		addr->table_cell_bitmap.size = *(USHORT*)buffer;
		qfree(buffer);
		ResGetPointer(table_id,10,12,(void**)&buffer);
		addr->table_cell_bitmap.bitmap_data = (UWORD*)buffer;
	}
    /* Field 11 */
    total_num_cells = addr->table_num_column * addr->table_num_row;
    addr->table_item_ptr = (TableItems**)qmalloc(total_num_cells * sizeof(TableItems*));
	i = 0;
    while (i <total_num_cells)
    {
        length = 0;
        addr->table_item_ptr[i] = (TableItems*)qmalloc(sizeof(TableItems));
        ResReadField(table_id,11,((i*15) + acc_length),1,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_data_type = *buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 1),2,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_item_ui_id = *(ObjectID*)buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 3),1,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_font = *(BYTE*)buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 4),4,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_value = *(WORD*)buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 8),1,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_display_alignment = *(BYTE*)buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 9),1,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_text_color = UIColorConversion(*buffer);
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 10),1,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_text_bg_color = UIColorConversion(*buffer);
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 11),2,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_cell_highlight = *(BOOLEAN*)buffer;
        qfree(buffer);
        ResReadField(table_id,11,((i*15) + acc_length + 13),2,&buffer,&byte_return);
        ((TableItems*)(addr->table_item_ptr[i]))->table_cell_has_bitmap = *(BOOLEAN*)buffer;
        qfree(buffer);
		/* Table Text */
        ResReadField(table_id,11,((i*15) + acc_length + 15),READ_TO_END,&buffer,&byte_return);
        length = strlen(buffer) + 1;
        acc_length = acc_length + length;
        ((TableItems*)(addr->table_item_ptr[i]))->table_text = (BYTE*)qmalloc(length * sizeof(BYTE));
		strcpy(((TableItems*)(addr->table_item_ptr[i]))->table_text,buffer);
        qfree(buffer);
		i++;
	}
    /* Field 12 */
    ResReadField(table_id,12,0,2,&buffer,&byte_return);
	addr->table_attr.table_enable = *(BOOLEAN*)buffer;
    qfree(buffer);
    ResReadField(table_id,12,2,2,&buffer,&byte_return);
    addr->table_attr.table_scrollbar = *(BOOLEAN*)buffer;
    qfree(buffer);
    ResReadField(table_id,12,4,2,&buffer,&byte_return);
    addr->table_attr.table_active = *(BOOLEAN*)buffer;
    qfree(buffer);
    ResReadField(table_id,12,6,2,&buffer,&byte_return);
    addr->table_attr.table_highlight_enable = *(BOOLEAN*)buffer;
    qfree(buffer);
    ResReadField(table_id,12,8,2,&buffer,&byte_return);
    addr->table_attr.table_visible = *(BOOLEAN*)buffer;
    qfree(buffer);
	addr->table_attr.table_enter = FALSE;
    addr->table_attr.table_drawn = FALSE;
	ResClose(table_id);
	return TRUE;
}
