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


#include "stdafx.h"
#include "virtable.h"
#include "appfunc.h"

/********************************************************
* Function:	VTInit
* Purpose: 	This function is to init the virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
bounds			The bounds of the virtual table
num_rows		The total number of rows
of the virtual table
num_cols		The total number of column
of the virtual table
top_row_num		The top row number of the 
virtual table that is being
displayed
row_height		Array of height of rows
col_width		Array of width of column
ref_col			The reference column number
scrollbar_id	The ID value of the scrollbar for the 
virtual table
* Output:		None
* Return:		None
* Comment: 	the row height for each row is set to 9
when the virtual table is first initialised.
All the pointers within the structure is set to NULL
*********************************************************/
void VTInit(VirtualTable *vt, ObjectBounds bounds, USHORT num_rows, USHORT num_cols,
			USHORT top_row_num, SHORT *row_height, SHORT *col_width, SHORT ref_col, ObjectID scrollbar_id)
{
	USHORT i;
	ObjectBounds field_bounds = {0, 0, 0, 0};
	
	vt->vt_num_rows = num_rows;
	vt->vt_num_cols = num_cols;
	vt->vt_top_row_num = top_row_num;
	vt->vt_num_rows_displayed = 0;
	vt->vt_total_num_lines = 0;
	vt->vt_ref_col = ref_col;
	vt->vt_font_size = SMALL_FONT;
	vt->vt_scrollbar_id = scrollbar_id;
	vt->vt_active_row = 0;
	
	VTSetTableBounds(vt, bounds);
	vt->vt_row_height = (SHORT*)qmalloc(num_rows*sizeof(SHORT));
	for (i = 0; i < num_rows; i++)
		vt->vt_row_height[i] = row_height[i];
	
	vt->vt_col_width = (SHORT*)qmalloc(num_cols*sizeof(SHORT));
	for (i = 0; i < num_cols; i++)
		vt->vt_col_width[i] = col_width[i];
	
	vt->vt_items = (VTItems**)qmalloc(num_rows*sizeof(VTItems*));
	
	/* by Kenny */
	vt->vt_ref_col = 1;
	vt->vt_active_row = -1;
	vt->vt_top_row_num = 0;
	
	for (i = 0; i < num_rows; i++)
	{
		vt->vt_items[i] = (VTItems*)qmalloc(sizeof(VTItems));
		vt->vt_items[i]->string_text = NULL;
		vt->vt_items[i]->alarm = NO_ALARM;
		field_bounds.width = vt->vt_col_width[vt->vt_ref_col];
		field_bounds.height = row_height[i];
		vt->vt_items[i]->ptr = VTCreateVirtualFieldObject(vt, field_bounds);
	}
	
}	

/********************************************************
* Function:	VTDeleteAllRowItems
* Purpose:		This function is called to delete all row items
in a virtual table object
* Scope:		Application
* Input:		vt				The pointer of the virtual table
* Output:		None
* Return:		None
* Comment:     vt_num_rows = 0
vt_top_row_num = 0;
vt_num_row_displayed = 0;
all allocated pointer will be freed and set back to NULL
*********************************************************/
void VTDeleteAllRowItems(VirtualTable *vt)
{
    USHORT  row_num;
    BYTE    object_type;
    ObjectID    field_id;
    Field   *field_ptr;
	
	
	for (row_num = 0; row_num < vt->vt_num_rows; row_num++)
	{
		if (vt->vt_items[row_num]->string_text != NULL)
			qfree(vt->vt_items[row_num]->string_text);
		if (vt->vt_items[row_num]->ptr != NULL)
			VTDeleteVirtualFieldObject(vt->vt_items[row_num]->ptr);
		qfree(vt->vt_items[row_num]);
	}
	qfree(vt->vt_items);
	vt->vt_num_rows = 0;
	vt->vt_top_row_num = 0;
	vt->vt_num_rows_displayed = 0;
	qfree(vt->vt_row_height);
	qfree(vt->vt_col_width);
	
    for (field_id = 16; field_id <= 29; field_id ++)
	{
		FormGetObjectPointer(field_id, &object_type, (void**)&field_ptr);
		field_ptr->field_lineinfo = NULL;
	}
	
	
}

/********************************************************
* Function:	VTCreateVirtualFieldObject
* Purpose:		This fucntion is called to create a virtaul field object
* Scope:		Application
* Input:		bounds			The bounds of the virtual field object
* Output:		None
* Return:		pointer of the created virtual field objects
NULL if can't be created
* Comment:     
*********************************************************/
Field *VTCreateVirtualFieldObject(VirtualTable *vt, ObjectBounds bounds)
{
	Field *ptr;
	ptr = (Field*)qmalloc(sizeof(Field));
	ptr->identification.ui_object_id = 0;
	ptr->identification.ui_object_type = FIELD;
	ptr->identification.table_related = 0;
	ptr->bounds = bounds;
	ptr->screen_bounds = bounds;
	
	if (ptr == NULL)
		return NULL;
	ptr->field_string = (BYTE*)qmalloc(sizeof(BYTE));
	ptr->field_string[0] = '\0';
    ptr->field_style = 0;       
    ptr->field_back_line = 0; 
    ptr->field_font_id = vt->vt_font_size;
    ptr->field_font_color = COLOR_BLACK;
	ptr->field_background_color = COLOR_WHITE;
	ptr->field_max_chars = 500;
    ptr->field_current_num_chars = 0;
    ptr->field_total_num_lines = 0;
    ptr->field_top_line_num = 0;;
    ptr->field_num_lines_displayed = 0;
    ptr->field_insert_pt_char_pos = 0;
	ptr->field_insert_pt_x = 0;
	ptr->field_insert_pt_y = 0;
	ptr->field_insert_pt_movement = NO_MOVEMENT;
    ptr->field_highlight_start_char = 0;
    ptr->field_highlight_end_char = 0;
    ptr->field_highlight_length = 0;
	ptr->field_lineinfo = NULL;
	ptr->field_attr.field_drawn = FALSE;
	ptr->field_attr.field_active = FALSE;
	ptr->field_attr.field_enable = FALSE;
	ptr->field_attr.field_dirty = FALSE;
	ptr->field_attr.field_highlight = FALSE;
	ptr->field_attr.field_insert_pt_visible = FALSE;
	ptr->field_attr.field_scrollbar = FALSE;
	ptr->field_attr.field_full_size = FALSE;
	ptr->field_attr.field_visible = TRUE;
	StrAnalyzeLine(ptr);
	return ptr;
}

/********************************************************
* Function:	VTDeleteVirtualFieldObject
* Purpose:		This fucntion is called to delete a virtaul field object
* Scope:		Application
* Input:		field_ptr			The pointer of the virtual field object
* Output:		None
* Return:		None
* Comment:     the field pointer and all the related pointer within the structure 
will be freed too
*********************************************************/
void VTDeleteVirtualFieldObject(Field *field_ptr)
{
    pfree(field_ptr->field_string);
	pfree(field_ptr->field_lineinfo);
	qfree(field_ptr);
}

/********************************************************
* Function:	VTSetTableBounds
* Purpose: 	This function is to set the vitual table bounds
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
bounds			The bounds of the virtual table
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTSetTableBounds(VirtualTable *vt, ObjectBounds bounds)
{
	vt->vt_bounds = bounds;
}

/********************************************************
* Function:	VTGetTableBounds
* Purpose: 	This function is to set the vitual table bounds
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table				
* Output:		bounds			The Pointer to the bounds of the virtual table
* Return:		None
* Comment: 	None
*********************************************************/
void VTGetTableBounds(VirtualTable *vt, ObjectBounds *bounds)
{
	*bounds = vt->vt_bounds;
}

/********************************************************
* Function:	VTSetTextPointer
* Purpose: 	This function is called to get the text pointer
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
text			the pointer of the text
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
* Comment: 	after setting the text, the passed-in pointer should be 
freed by application
*********************************************************/
Err VTSetTextPointer(VirtualTable *vt, USHORT row_num, BYTE *text)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->string_text != NULL)
		qfree(vt->vt_items[row_num]->string_text);
	vt->vt_items[row_num]->string_text = (BYTE*)qmalloc((strlen(text) + 1)*sizeof(BYTE));
	strcpy(vt->vt_items[row_num]->string_text, text);
	return TRUE;
}

/********************************************************
* Function:	VTGetTextPointer
* Purpose: 	This function is called to get the text pointer
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
* Output:		text			the reference pointer of the text
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_TEXT_NOT_FOUND
if there is no text or the text pointer
is not allocated
* Comment: 	
*********************************************************/
Err VTGetTextPointer(VirtualTable *vt, USHORT row_num, BYTE **text)
{
	if (row_num >= vt->vt_num_rows)
	{
		*text = NULL;
		return ERR_VT_ROW_NUM_INVALID;
	}
	
	*text = vt->vt_items[row_num]->string_text;
	if (*text == NULL)
		return ERR_VT_TEXT_NOT_FOUND;
	return TRUE;
}

/********************************************************
* Function:	VTSetFieldTextPointer
* Purpose: 	This function is called to set the field text pointer
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
text			the pointer of the field text
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTSetFieldTextPointer(VirtualTable *vt, USHORT row_num, BYTE *text)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	if (vt->vt_items[row_num]->ptr->field_string != NULL)
		qfree(vt->vt_items[row_num]->ptr->field_string);
	vt->vt_items[row_num]->ptr->field_string = (BYTE*)qmalloc((strlen(text) + 1)*sizeof(BYTE));
	strcpy(vt->vt_items[row_num]->ptr->field_string, text);
	StrAnalyzeLine(vt->vt_items[row_num]->ptr);
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldTextPointer
* Purpose: 	This function is called to get the field text pointer
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
* Output:		text			the reference pointer of the field text
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_TEXT_NOT_FOUND
if there is no text or the text pointer
is not allocated
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldTextPointer(VirtualTable *vt, USHORT row_num, BYTE **text)
{
	*text = NULL;
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	if (vt->vt_items[row_num]->ptr->field_string == NULL)
		return ERR_VT_TEXT_NOT_FOUND;
	
	*text = vt->vt_items[row_num]->ptr->field_string;
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldPointer
* Purpose: 	This function is called to get the field pointer
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
* Output:		field_ptr		The reference poitner of the virtaul field object 
in the virtual pointer
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldPointer(VirtualTable *vt, USHORT row_num, Field **field_ptr)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*field_ptr = vt->vt_items[row_num]->ptr;
	return TRUE;
}

/********************************************************
* Function:	VTSetFieldBounds
* Purpose: 	This function is called to set the bounds of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
bounds			The bounds of the virtual field object
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTSetFieldBounds(VirtualTable *vt, USHORT row_num, ObjectBounds bounds)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	vt->vt_items[row_num]->ptr->bounds = bounds;
	vt->vt_items[row_num]->ptr->screen_bounds = bounds;
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldBounds
* Purpose: 	This function is called to get the bounds of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
* Output:		bounds			The Pointer to bounds of the virtual field object
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldBounds(VirtualTable *vt, USHORT row_num, ObjectBounds *bounds)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*bounds = vt->vt_items[row_num]->ptr->bounds;
	return TRUE;
}

/********************************************************
* Function:	VTSetFieldFontSize
* Purpose: 	This function is called to set the font size of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
font_size		The font_size of the field object
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTSetFieldFontSize(VirtualTable *vt, USHORT row_num, BYTE font_size)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	vt->vt_items[row_num]->ptr->field_font_id = font_size;
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldFontSize
* Purpose: 	This function is called to get the font size of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 				
* Output:		font_size		The Pointer to font_size of the field object
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldFontSize(VirtualTable *vt, USHORT row_num, BYTE *font_size)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*font_size = vt->vt_items[row_num]->ptr->field_font_id;
	return TRUE;
}

/********************************************************
* Function:	VTSetTableFontSize
* Purpose: 	This function is called to set the font size of the
virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
font_size		The font_size of the virtual table
* Output:		None
* Return:		ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	All the font size of the field objects in the virtual table 
is set to the table font size correspondingly
*********************************************************/
Err VTSetTableFontSize(VirtualTable *vt, BYTE font_size)
{
	USHORT row_num = 0;
	
	if (vt->vt_num_rows <= 0) 
		return ERR_VT_FIELD_NOT_FOUND;
	if (vt->vt_items[0]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	vt->vt_font_size = font_size;
	
	for (row_num = 0; row_num < vt->vt_num_rows; row_num++)
	{
		vt->vt_items[row_num]->ptr->field_font_id = font_size;
		StrAnalyzeLine(vt->vt_items[row_num]->ptr);
	}
	return TRUE;
}

/********************************************************
* Function:	VTGetTableFontSize
* Purpose: 	This function is called to set the font size of the
virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table				
* Output:		font_size		The Pointer to font_size of the virtual table
* Return:		ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	None
*********************************************************/
void VTGetTableFontSize(VirtualTable *vt, BYTE *font_size)
{
	*font_size = vt->vt_font_size;
}

/********************************************************
* Function:	VTSetTableColumnWidth
* Purpose: 	This function is called to set the column width of the
virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
col_num			The column number
col_width		The column width of column, that contains
field objects, in the virtual object
* Output:		None
* Return:		ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	All width of the field objects in the virtual table is changed
*********************************************************/
void VTSetTableColumnWidth(VirtualTable *vt, USHORT col_num, SHORT col_width)
{
	USHORT row_num;
	
	vt->vt_col_width[col_num] = col_width;
	if (col_num != vt->vt_ref_col) return;
	
	for (row_num = 0; row_num < vt->vt_num_rows; row_num++)
	{
		vt->vt_items[row_num]->ptr->bounds.width = col_width;
		vt->vt_items[row_num]->ptr->screen_bounds.width = col_width;
		StrAnalyzeLine(vt->vt_items[row_num]->ptr);
	}
}

/********************************************************
* Function:	VTSetTableRowHeight
* Purpose: 	This function is called to set the row height of a particular
row in the virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The require drow_num
row_height		The row_height of row, that contains
field objects, in the virtual object
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	All height of the field objects in the virtual table is changed
*********************************************************/
Err VTSetTableRowHeight(VirtualTable *vt, USHORT row_num, SHORT row_height)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	vt->vt_row_height[row_num] = row_height;
	
	vt->vt_items[row_num]->ptr->bounds.height = row_height;
	vt->vt_items[row_num]->ptr->screen_bounds.height = row_height;
	StrAnalyzeLine(vt->vt_items[row_num]->ptr);
	return TRUE;
}

/********************************************************
* Function:	VTGetTableTotalNumLines
* Purpose: 	This function is called to get the total number of lines
in a virtual table object
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
* Output:		num_lines		The pointer of total num_lines in a virtual
table
* Return:		None
* Comment: 	None
*********************************************************/
void VTGetTableTotalNumLines(VirtualTable *vt, WORD *num_lines)
{
	USHORT count;
	
	*num_lines = 0;
	for (count = 0; count < vt->vt_num_rows; count ++)
		*num_lines += vt->vt_items[count]->ptr->field_total_num_lines;
	vt->vt_total_num_lines = *num_lines;
}

/********************************************************
* Function:	VTSetFieldTopLineNum
* Purpose: 	This function is called to set the top line number of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num
top_line_num	The top line number of the field object
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTSetFieldTopLineNum(VirtualTable *vt, USHORT row_num, WORD top_line_num)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	vt->vt_items[row_num]->ptr->field_top_line_num = top_line_num;
	StrAnalyzeLine(vt->vt_items[row_num]->ptr);
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldTopLineNum
* Purpose: 	This function is called to get the top line number of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 				
* Output:		top_line_num	The pointer to the top line number of
the wanted virtual field objects
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldTopLineNum(VirtualTable *vt, USHORT row_num, WORD *top_line_num)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*top_line_num = vt->vt_items[row_num]->ptr->field_top_line_num;
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldNumLinesDisplayed
* Purpose: 	This function is called to get the number of lines of a virtual field object
that are being displayed in the screen
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 				
* Output:		num_lines		The pointer to the number of lines being displayed of
the wanted virtual field objects
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldNumLinesDisplayed(VirtualTable *vt, USHORT row_num, WORD *num_lines)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*num_lines = vt->vt_items[row_num]->ptr->field_num_lines_displayed;
	return TRUE;
}

/********************************************************
* Function:	VTGetFieldTotalNumLines
* Purpose: 	This function is called to get the total number of lines of field 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 				
* Output:		num_lines		The pointer to the total number of lines of
the wanted virtual field objects
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
ERR_VT_FIELD_NOT_FOUND
if the field pointer is set to NULL
* Comment: 	
*********************************************************/
Err VTGetFieldTotalNumLines(VirtualTable *vt, USHORT row_num, WORD *num_lines)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_items[row_num]->ptr == NULL)
		return ERR_VT_FIELD_NOT_FOUND;
	
	*num_lines = vt->vt_items[row_num]->ptr->field_total_num_lines;
	return TRUE;
}


/********************************************************
* Function:	VTSetRowAlarm
* Purpose: 	This function is called to set the alarm of 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
alarm			The alarm setting
alarm_time
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
* Comment: 	
*********************************************************/
Err VTSetRowAlarm(VirtualTable *vt, USHORT row_num, BYTE alarm, BYTE alarm_time)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	vt->vt_items[row_num]->alarm = alarm;
	//	if (alarm_time != DONT_CARE)
	//		vt->vt_items[row_num]->alarm_time = alarm_time;
	return TRUE;
}

/********************************************************
* Function:	VTGetRowAlarm
* Purpose: 	This function is called to get the alarm setting of 
of a particular row in a virtual table
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
row_num			The required row num 
* Output:		alarm			The poitner to alarm setting
alarm_time
* Return:		ERR_VT_ROW_NUM_INVALID
if the input row number is invalid
* Comment: 	None
*********************************************************/
Err VTGetRowAlarm(VirtualTable *vt, USHORT row_num, BYTE *alarm, BYTE *alarm_time)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	*alarm = vt->vt_items[row_num]->alarm;
	//	*alarm_time = vt->vt_items[row_num]->alarm_time;
	return TRUE;
}

/********************************************************
* Function:	VTInsertRow
* Purpose:		This function is called to insert a row to the virtual table object
* Scope:		Application
* Input:		vt				The pointer to virtual table object
row_num			The wanted row number
hour			The hour
minute			The minute
alarm			alarm setting
alarm_time		alarm lasting time
appointment
dbid
recid
string_text		The string text
field_string	The text in new virtual field object
* Output:		None
* Return:		None
* Comment:     The width of the new virtual field object is set to col_width
of the virtual table object
The height of the new virtual field object is set to the height
of the (font_size + 1)
*********************************************************/
void VTInsertRow(VirtualTable *vt, USHORT row_num, BYTE *string_text, BYTE *field_string)
{
	WORD i;
	USHORT total_number;
	SHORT height = 0;
	VTItems **new_vt_items;
	SHORT *new_height;
	ObjectBounds bounds = {0, 0, 0, 0};
	
	if (vt->vt_active_row != -1 && vt->vt_active_row >= row_num)
		vt->vt_active_row ++;
	
	if (row_num >=  vt->vt_num_rows)
		row_num = vt->vt_num_rows;
    total_number = vt->vt_num_rows;
	new_vt_items = (VTItems **)qmalloc((total_number+1)*sizeof(VTItems *));
	new_height   = (SHORT*)qmalloc((total_number+1)*sizeof(SHORT *));
	i = 0;
	while (i <total_number)
	{
		if (i < row_num)
		{
			new_height[i]   = vt->vt_row_height[i];	
			new_vt_items[i] = vt->vt_items[i];
			//		if (new_vt_items[i]->appointment >= row_num)
			//			new_vt_items[i]->appointment ++;
		}
		else if( i == row_num)
		{
			height = SysGetFontHeight(vt->vt_font_size) + 1;
			new_height[i] = height;
			
			new_vt_items[i] = (VTItems *)pmalloc(sizeof(VTItems));
			//		new_vt_items[i]->hour = hour;
			//		new_vt_items[i]->minute = minute;
			new_vt_items[i]->alarm = NO_ALARM;
			//		new_vt_items[i]->alarm_time = alarm_time;
			//		new_vt_items[i]->appointment = appointment;
			//		new_vt_items[i]->dbid = dbid;
			//		new_vt_items[i]->recid = recid;
			new_vt_items[i]->string_text = (BYTE*)qmalloc((strlen(string_text) + 1) * sizeof(BYTE));
			strcpy(new_vt_items[i]->string_text, string_text);
			bounds.width = vt->vt_col_width[vt->vt_ref_col];
			bounds.height = height;
			new_vt_items[i]->ptr = VTCreateVirtualFieldObject(vt, bounds);
			if (new_vt_items[i]->ptr->field_string != NULL)
				qfree(new_vt_items[i]->ptr->field_string);
			new_vt_items[i]->ptr->field_string = (BYTE*)qmalloc((strlen(field_string) + 1) * sizeof(BYTE));
			strcpy(new_vt_items[i]->ptr->field_string, field_string);
			new_vt_items[i+1] = vt->vt_items[i];
			new_height[i+1] = vt->vt_row_height[i];
			//		if (new_vt_items[i+1]->appointment >= row_num)
			//			new_vt_items[i+1]->appointment ++;
		}
		else
		{
			new_vt_items[i+1] = vt->vt_items[i];
			new_height[i+1] = vt->vt_row_height[i];
			//		if (new_vt_items[i+1]->appointment != -1)
			//			new_vt_items[i+1]->appointment ++;
		}
		i++;
	}
	if (row_num == total_number)
	{
		height = SysGetFontHeight(vt->vt_font_size) + 1;
		new_height[row_num] = height;
		new_vt_items[row_num] = (VTItems *)pmalloc(sizeof(VTItems));
		//	  new_vt_items[i]->hour = hour;
		//	  new_vt_items[i]->minute = minute;
		new_vt_items[i]->alarm = NO_ALARM;
		//	  new_vt_items[i]->alarm_time = alarm_time;
		//	  new_vt_items[i]->appointment = appointment;
		//	  new_vt_items[i]->dbid = dbid;
		//	  new_vt_items[i]->recid = recid;
		new_vt_items[i]->string_text = (BYTE*)qmalloc((strlen(string_text) + 1) * sizeof(BYTE));
		strcpy(new_vt_items[i]->string_text, string_text);
		
		bounds.width = vt->vt_col_width[vt->vt_ref_col];
		bounds.height = height;
		new_vt_items[row_num]->ptr = VTCreateVirtualFieldObject(vt, bounds);
		if (new_vt_items[i]->ptr->field_string != NULL)
			qfree(new_vt_items[i]->ptr->field_string);
		new_vt_items[i]->ptr->field_string = (BYTE*)qmalloc((strlen(field_string) + 1) * sizeof(BYTE));
		strcpy(new_vt_items[i]->ptr->field_string, field_string);
		
	}
	vt->vt_num_rows = (total_number + 1);
	qfree(vt->vt_items);
	qfree(vt->vt_row_height);
	vt->vt_row_height = new_height;
	vt->vt_items = new_vt_items;
}

/********************************************************
* Function:	VTDeleteRow
* Purpose:		This function is called to delete a row to the virtual table object
* Scope:		Application
* Input:		vt				The pointer to virtual table object
row_num			The wanted row number
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
if the row_num is in valid
* Comment:     None
*********************************************************/
Err VTDeleteRow(VirtualTable *vt, USHORT row_num)
{
	WORD i;
	USHORT total_number;
	VTItems **new_vt_items;
	SHORT *new_height;
	
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	if (vt->vt_active_row != -1 && vt->vt_active_row == row_num)
		vt->vt_active_row = -1;
	else if (vt->vt_active_row != -1 && vt->vt_active_row > row_num)
		vt->vt_active_row  --;
	
	total_number = vt->vt_num_rows;
	/* delete a row */
	if (vt->vt_items[row_num]->string_text != NULL)
		qfree(vt->vt_items[row_num]->string_text);
	VTDeleteVirtualFieldObject(vt->vt_items[row_num]->ptr);
	qfree(vt->vt_items[row_num]);
	/* the corresponding item in the menu list is deleted and all the other items are re-arrnaged */
	new_vt_items = (VTItems**)pmalloc((total_number - 1)*sizeof(VTItems*));
	new_height = (SHORT*)pmalloc((total_number - 1)*sizeof(SHORT));
	i = row_num;
	while (i)
	{
		i--;
		new_vt_items[i] = vt->vt_items[i];
		new_height[i] = vt->vt_row_height[i];
		//		if (new_vt_items[i]->appointment > row_num)
		//			new_vt_items[i]->appointment --;
		//		else if (new_vt_items[i]->appointment == row_num)
		//			new_vt_items[i]->appointment = -1;
	}
	i = row_num;
	while (i < (total_number - 1))
	{
		new_vt_items[i] = vt->vt_items[i+1];
		new_height[i] = vt->vt_row_height[i+1];
		//	  if (new_vt_items[i]->appointment != -1)
		//		  new_vt_items[i]->appointment --;
		i++;
	}
	vt->vt_num_rows = total_number - 1;
	qfree(vt->vt_row_height);
	qfree(vt->vt_items);
	vt->vt_row_height = new_height;
	vt->vt_items = new_vt_items;	
	if (vt->vt_top_row_num == vt->vt_num_rows)
		vt->vt_top_row_num --;
	return TRUE;
}

/********************************************************
* Function:	VTGetTableMaxNumLines
* Purpose: 	This function is called to in order to get
the max num of lines that the table can 
handle
* Scope:		application
* Input:		vt					The pointer of virtual table object
* Output:		max_num_lines		The maximum number of lines
* Return:		None
* Comment: 	None
*********************************************************/
void VTGetTableMaxNumLines(VirtualTable *vt, WORD *max_num_lines)
{
	SHORT table_height;
	SHORT line_height;
	
	table_height = vt->vt_bounds.height;
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	*max_num_lines = table_height / line_height;
}

/********************************************************
* Function:	VTGetScrollbarMaxValue
* Purpose: 	This fucntion is called in order to work out the 
max value of the scrollbar of the virtual table object
* Scope:		application
* Input:		None
* Output:		None
* Return:		maximum value
* Comment: 	None
*********************************************************/
WORD VTGetScrollbarMaxValue(VirtualTable *vt)
{
	SHORT count = 0;
	WORD acc_num_lines = 0;
	WORD max_num_lines;
	WORD num_lines;
	WORD total_num_lines;
	
	VTGetTableMaxNumLines(vt, &max_num_lines);
	VTGetTableTotalNumLines(vt, &total_num_lines);
	
	for (count = (vt->vt_num_rows - 1); count >= 0; count--)
	{
		num_lines = vt->vt_items[count]->ptr->field_total_num_lines;
		acc_num_lines += num_lines;
		if (acc_num_lines > max_num_lines)
		{
			acc_num_lines -= num_lines;
			return (total_num_lines - acc_num_lines);
		}
	}
	return (total_num_lines - acc_num_lines);
}

/********************************************************
* Function:	VTSetScrollbarID
* Purpose: 	This function is to set the related scrollbar id value of 
the virtual table object
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
scrollbar_id	The ID value of the scrollbar 
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTSetScrollbarID(VirtualTable *vt, ObjectID scrollbar_id)
{
	vt->vt_scrollbar_id = scrollbar_id;
}

/********************************************************
* Function:	VTGetTableBounds
* Purpose: 	This function is to set the vitual table bounds
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table				
* Output:		bounds			The Pointer to the bounds of the virtual table
* Return:		None
* Comment: 	None
*********************************************************/
void VTGetScrollbarID(VirtualTable *vt, ObjectID *scrollbar_id)
{
	*scrollbar_id = vt->vt_scrollbar_id;
}

/********************************************************
* Function:	VTUpdateFieldScreenBounds
* Purpose: 	This function is called to update the screen bounds
of the corresponding virtual field object
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table				
row_num			The row number of field object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTUpdateFieldScreenBounds(VirtualTable *vt, USHORT row_num)
{
	USHORT y_margin = 0;
	USHORT x_margin = 0;
	WORD i;
	BOOLEAN found = FALSE;
	
	i = vt->vt_top_row_num;
	while (i < row_num)
	{	
		y_margin += vt->vt_row_height[i];
		i++;
	}
	y_margin += vt->vt_bounds.ycoord;
	
	i = vt->vt_ref_col;
	while (i)
	{	
		i--;
		x_margin += vt->vt_col_width[i];
	}
	x_margin += vt->vt_bounds.xcoord;
	
    vt->vt_items[row_num]->ptr->screen_bounds = vt->vt_items[row_num]->ptr->bounds;
	vt->vt_items[row_num]->ptr->screen_bounds.xcoord = vt->vt_items[row_num]->ptr->bounds.xcoord + x_margin;
	vt->vt_items[row_num]->ptr->screen_bounds.ycoord = vt->vt_items[row_num]->ptr->bounds.ycoord + y_margin;
}	

/********************************************************
* Function:	VTFieldGetFirstVisibleChar
* Purpose:	Get the first visible character
* Scope:	Application
* Input:	field_ptr		The pointer to a field object
* Output:	char_pos		Character position
* Return:	None
* Comment:	None
**********************************************************/
void VTFieldGetFirstVisibleChar (Field *field_ptr, WORD *char_pos)
{
	StrAnalyzeLine(field_ptr);
	StrXYToCharPos(field_ptr,field_ptr->screen_bounds.xcoord,field_ptr->screen_bounds.ycoord,char_pos);
}
/********************************************************
* Function:	FieldGetLastVisibleChar
* Purpose:	Get the last visible character
* Scope:	Application
* Input:	field_id		DBID of the spceified field object
* Output:	char_pos		Character position
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
void VTFieldGetLastVisibleChar (Field *field_ptr, WORD *char_pos)
{
	ObjectBounds bounds = field_ptr->screen_bounds;
	SHORT xcoord, ycoord;
	
	StrAnalyzeLine(field_ptr);
	if ((field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed) == field_ptr->field_total_num_lines)
		StrGetInsertPtPos(field_ptr,(bounds.xcoord+bounds.width-1),(bounds.ycoord+bounds.height-1),char_pos,
		&xcoord,&ycoord);
	else StrXYToCharPos(field_ptr,(bounds.xcoord+bounds.width-1),(bounds.ycoord+bounds.height-1),char_pos);
}

/********************************************************
* Function:	VTSetActiveRow
* Purpose: 	This function is to set the active row number of the
virtual table object
* Scope:		application/internal
* Input:		vt				The pointer of the virtual table
active_row		The row number of the active row
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
* Comment: 	None
*********************************************************/
Err VTSetActiveRow(VirtualTable *vt, USHORT active_row)
{
	if (active_row >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	vt->vt_active_row = active_row;
	return TRUE;
}


/********************************************************
* Function:	VTSetVirtualTableLayout
* Purpose: 	This function is called in order to set up the virtual table
the table when the data is first put to table or the keyboard is popuped 
up and down
* Scope:		application
* Input:		vt					The pointer to virtual table object
* Output:		None
* Return:		TRUE		Success
FALSE		not handled
* Comment: 	None
*********************************************************/
BOOLEAN VTSetVirtualTableLayout(VirtualTable *vt)
{
	USHORT active_row;			
	BOOLEAN insert_pt_on = FALSE;
	
	WORD table_max_num_lines, total_num_lines;
	
	SHORT field_height;
	USHORT table_top_row_num, table_num_row_displayed;
	
	WORD first_visible_char, last_visible_char;
	
	WORD count = 0;
	SHORT acc_height = 0;
	SHORT line_height;			/* line_height = SysGetFontHeight(font_id) + SPACE_LINE;*/
	
	Field *field_ptr;
	
	
	/*The bounds of the table should be set outside this function according
	to the keyboard status */
	VTGetTableMaxNumLines(vt, &table_max_num_lines);
	VTGetTableTotalNumLines(vt, &total_num_lines);
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	
	
	if (vt->vt_active_row >= 0)
	{
		active_row	= (USHORT)(vt->vt_active_row); 
		insert_pt_on = vt->vt_items[vt->vt_active_row]->ptr->field_attr.field_insert_pt_visible;
	}
	else active_row = vt->vt_top_row_num;
	
	/* restore the top row nubmer of the table to 0, if the 
	   table_max_num_lines >= total_num_lines of the table*/
	if (table_max_num_lines >= total_num_lines)
		vt->vt_top_row_num = 0;
	
	
	/*set up the bounds of the field object*/
	for (count = 0; count < vt->vt_num_rows; count++)
	{
		
		field_ptr = vt->vt_items[count]->ptr;
		StrAnalyzeLine(field_ptr);
		field_height = field_ptr->field_total_num_lines * line_height;
		if (field_height >= vt->vt_bounds.height)
		{
			vt->vt_row_height[count] = vt->vt_bounds.height;
			field_ptr->bounds.height = vt->vt_bounds.height;
		}
		else
		{
			vt->vt_row_height[count] = field_height;
			field_ptr->bounds.height = field_height;
		}
	}
	VTDecideTopRowNum(vt, active_row);         /*decide the top row num*/
	table_top_row_num = vt->vt_top_row_num;
	table_num_row_displayed  = 0;
	acc_height = 0;
	for (count = table_top_row_num; count < vt->vt_num_rows; count++)
	{
		acc_height += vt->vt_row_height[count];
		if (acc_height <= vt->vt_bounds.height)
		{
			table_num_row_displayed ++;
			VTUpdateFieldScreenBounds(vt, (USHORT)count);
			StrAnalyzeLine(vt->vt_items[count]->ptr);
			if (acc_height >= (table_max_num_lines * line_height)) break;
		}
		else 
		{
			acc_height -= vt->vt_row_height[count];
			field_ptr = vt->vt_items[count]->ptr;
			if (acc_height == (table_max_num_lines * line_height)) break;
			field_ptr->bounds.height = (table_max_num_lines - acc_height/line_height) * line_height;
			vt->vt_row_height[count] = field_ptr->bounds.height;
			field_ptr->field_top_line_num = 0;
			VTUpdateFieldScreenBounds(vt, (USHORT)count);
			StrAnalyzeLine(field_ptr);
			break;
		}
	}
	if (insert_pt_on == TRUE)
	{
		field_ptr = vt->vt_items[active_row]->ptr;
		StrAnalyzeLine(field_ptr);
		VTFieldGetFirstVisibleChar(field_ptr, &first_visible_char);
		VTFieldGetLastVisibleChar(field_ptr, &last_visible_char);
		for (count = 0; count < field_ptr->field_total_num_lines; count++)
		{
			if (field_ptr->field_insert_pt_char_pos >= field_ptr->field_lineinfo[count].start &&
				field_ptr->field_insert_pt_char_pos < field_ptr->field_lineinfo[count].start + field_ptr->field_lineinfo[count].length)
				break;
		}
		if (field_ptr->field_insert_pt_char_pos < first_visible_char)
			field_ptr->field_top_line_num = count;
		else if (field_ptr->field_insert_pt_char_pos > last_visible_char)
			field_ptr->field_top_line_num = count - field_ptr->field_num_lines_displayed;
		
		if (field_ptr->field_num_lines_displayed < (field_ptr->bounds.height/(line_height)))
		{
			if (field_ptr->field_top_line_num > (field_ptr->field_total_num_lines - (field_ptr->bounds.height/(line_height))))
				field_ptr->field_top_line_num = (field_ptr->field_total_num_lines - (field_ptr->bounds.height/(line_height)));
		}
		StrAnalyzeLine(field_ptr);
		StrCharPosToXY(field_ptr, field_ptr->field_insert_pt_char_pos, 
			&(field_ptr->field_insert_pt_x), &(field_ptr->field_insert_pt_y));
	}
	VTUpdateNumRowsDisplayed(vt);
	return TRUE;
}

/********************************************************
* Function:	VTDecideTopRowNum
* Purpose:		This function is called to decide the to row number
of the table with field objects
* Scope:		application
* Input:		vt				The pointer to a virtual table object
active_row		The active row 
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN VTDecideTopRowNum(VirtualTable *vt, USHORT active_row)
{
	WORD max_num_lines;
	USHORT acc_num_lines = 0;
	USHORT row_num;
	WORD field_num_lines;
	Field *field_ptr;
	SHORT line_height;
	BOOLEAN return_boolean = FALSE;
	
	
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	VTGetTableMaxNumLines(vt, &max_num_lines);
	
	row_num = vt->vt_top_row_num;
	while (row_num < (vt->vt_num_rows))
	{
		VTUpdateFieldScreenBounds(vt, row_num);
		field_ptr = vt->vt_items[row_num]->ptr;
		StrAnalyzeLine(field_ptr);
		VTGetFieldTotalNumLines(vt, row_num, &field_num_lines);
		acc_num_lines += (USHORT)field_num_lines;
		if ((acc_num_lines > max_num_lines) && row_num <= active_row &&
			vt->vt_top_row_num != active_row)
		{
			acc_num_lines = 0;
			vt->vt_top_row_num ++;
			row_num = vt->vt_top_row_num;
			field_num_lines = 0;
			return_boolean = TRUE;
		}
		else if ((acc_num_lines > max_num_lines) && row_num == active_row &&
			vt->vt_top_row_num == active_row)
		{
			vt->vt_top_row_num = active_row;
			vt->vt_row_height[active_row] = vt->vt_bounds.height;
			field_ptr = vt->vt_items[active_row]->ptr;
			field_ptr->bounds.height = vt->vt_bounds.height;
			vt->vt_row_height[row_num] = vt->vt_bounds.height;
			return TRUE;
		}
		else if ((acc_num_lines > max_num_lines) && vt->vt_top_row_num == active_row &&
			row_num > active_row)
		{
			vt->vt_top_row_num = active_row;
			return TRUE;
		}
		else if (acc_num_lines == max_num_lines && row_num >= active_row)
		{
			if (return_boolean == FALSE) return FALSE;
			else return TRUE;
		}
		else if (acc_num_lines < max_num_lines && row_num == vt->vt_top_row_num - 1)
		{
			if (return_boolean == FALSE) return FALSE;
			else return TRUE;
		}
		else row_num++;
	}
	return TRUE;
}

/********************************************************
* Function:	VTKeyInChangeVirtualTable
* Purpose: 	This function is called when the content in table changed,
then both table
* Scope:		application
* Input:		vt			The pointer to virtual table object
* Output:		None
* Return:		TRUE		The table layout is changed
FALSE		The table layout is not changed
* Comment: 	None
*********************************************************/
BOOLEAN VTKeyInChangeVirtualTable(VirtualTable *vt)
{
	WORD count = 0;				/* another temperatory variable */
	Field *field_ptr;
	WORD table_max_num_lines;
	SHORT line_height;			/* line_height = SysGetFontHeight(font_id) + SPACE_LINE;*/
	BOOLEAN insert_pt_on = FALSE;
	SHORT acc_height = 0;
	BOOLEAN return_boolean = FALSE;
	USHORT active_row;
	WORD field_total_num_lines, num_lines_displayed, acc_num_lines = 0, num_lines;
	
	
	/*The bounds of the table should be set outside this function according
	to the keyboard status */
	
	VTGetTableMaxNumLines(vt, &table_max_num_lines);
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	
	if (vt->vt_active_row >= 0)
	{
		active_row	= (USHORT)(vt->vt_active_row); 
		insert_pt_on = vt->vt_items[vt->vt_active_row]->ptr->field_attr.field_insert_pt_visible;
	}
	else active_row = vt->vt_top_row_num;
	
	VTGetFieldTotalNumLines(vt, active_row, &field_total_num_lines);
	VTGetFieldNumLinesDisplayed(vt, active_row, &num_lines_displayed);
	field_ptr = vt->vt_items[active_row]->ptr;
	if (field_total_num_lines >= table_max_num_lines)
	{
		field_ptr->bounds.height = vt->vt_bounds.height;
		vt->vt_row_height[active_row] = vt->vt_bounds.height;
		if (field_total_num_lines <= field_ptr->bounds.height/line_height)
			field_ptr->field_top_line_num = 0;
		return_boolean = TRUE;
	}
	else if (field_total_num_lines < (field_ptr->screen_bounds.height/(SysGetFontHeight(vt->vt_font_size) + SPACE_LINE)))
	{
		field_ptr->bounds.height = (field_total_num_lines)*(SysGetFontHeight(vt->vt_font_size) + SPACE_LINE);
		VTUpdateFieldScreenBounds(vt, active_row);
		if (field_total_num_lines <= field_ptr->bounds.height/line_height)
			field_ptr->field_top_line_num = 0;
		StrAnalyzeLine(field_ptr);
		StrCharPosToXY(field_ptr, field_ptr->field_insert_pt_char_pos, 
			&(field_ptr->field_insert_pt_x), &(field_ptr->field_insert_pt_y));
		vt->vt_row_height[active_row] = field_ptr->bounds.height;
		return_boolean = TRUE;
	}			
	else if (num_lines_displayed < field_total_num_lines) 
	{
		field_ptr->bounds.height = (field_total_num_lines)*(SysGetFontHeight(vt->vt_font_size) + SPACE_LINE);
		VTUpdateFieldScreenBounds(vt, active_row);
		if (field_ptr->field_top_line_num >0) field_ptr->field_top_line_num--;
		if (field_total_num_lines <= field_ptr->bounds.height/line_height)
			field_ptr->field_top_line_num = 0;
		StrAnalyzeLine(field_ptr);
		StrCharPosToXY(field_ptr, field_ptr->field_insert_pt_char_pos, 
			&(field_ptr->field_insert_pt_x), &(field_ptr->field_insert_pt_y));
		vt->vt_row_height[active_row] = field_ptr->bounds.height;
		return_boolean = TRUE;
	}
	if (VTDecideTopRowNum(vt, active_row) == TRUE) return_boolean = TRUE;
	if (insert_pt_on)
	{
		VTUpdateFieldScreenBounds(vt, active_row);		
		StrAnalyzeLine(field_ptr);
		StrCharPosToXY(field_ptr, field_ptr->field_insert_pt_char_pos, 
			&(field_ptr->field_insert_pt_x), &(field_ptr->field_insert_pt_y));
	}
	acc_num_lines = 0;
	for (count = vt->vt_top_row_num; count < vt->vt_num_rows; count++)
	{
		VTGetFieldTotalNumLines(vt, (USHORT)count, &num_lines);
		acc_num_lines += num_lines;
		if (acc_num_lines == table_max_num_lines)
			break;
		else if (acc_num_lines > table_max_num_lines)
		{
			acc_num_lines -= num_lines;
			field_ptr = vt->vt_items[count]->ptr;
			field_ptr->bounds.height = (table_max_num_lines - acc_num_lines) * line_height;
			vt->vt_row_height[count] = field_ptr->bounds.height;
			return_boolean = TRUE;
			break;
		}
	}
	VTUpdateNumRowsDisplayed(vt);
	if (return_boolean == TRUE)
	{
		VTVirtualTableSetScrollbar(vt);
		return TRUE;
	}
	else return FALSE;
}

/********************************************************
* Function:	VTVirtualTableSetScrollbar
* Purpose: 	This function is to set the scrollbar beside the table
* Scope:		application
* Input:		vt			The pointer to virtual table object
* Output:		None
* Return:		TRUE		The table layout is changed
FALSE		The table layout is not changed
* Comment: 	None
*********************************************************/
BOOLEAN VTVirtualTableSetScrollbar(VirtualTable *vt)
{
	BYTE object_type;
	Scrollbar *scroll_ptr;
	Field *field_ptr;
	WORD table_max_num_lines, table_total_num_lines;
	WORD value, max_value, min_value, pagesize, scrollbar_total_num_lines;
	WORD count, field_total_num_lines, acc_num_lines = 0, acc_num_lines1 = 0, top_line_num;
	WORD acc_num_lines2 = 0;
	SHORT line_height = 0;
	BOOLEAN set = FALSE;
	
	/*The bounds of the table should be set outside this function according
	to the keyboard status */
	
	FormGetObjectPointer(vt->vt_scrollbar_id, &object_type, (void**)&scroll_ptr);
	
	VTGetTableMaxNumLines(vt, &table_max_num_lines);
	VTGetTableTotalNumLines(vt, &table_total_num_lines);
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	
	if ((table_total_num_lines > table_max_num_lines))
		scroll_ptr->scrollbar_attr.scrollbar_visible = TRUE;
	else
	{
		scroll_ptr->scrollbar_attr.scrollbar_visible = FALSE;
		if (scroll_ptr->scrollbar_attr.scrollbar_drawn == TRUE)
			ScrollbarEraseScrollbar(vt->vt_scrollbar_id);
		return TRUE;
	}
	
	ScrollbarGetScrollbar(vt->vt_scrollbar_id, &value, &max_value, &min_value, &pagesize, &scrollbar_total_num_lines);
	for (count = 0; count < vt->vt_top_row_num; count++)
	{
		VTGetFieldTotalNumLines(vt, (USHORT)count, &field_total_num_lines);
		acc_num_lines += field_total_num_lines;
	}
	VTGetFieldTopLineNum(vt, vt->vt_top_row_num, &top_line_num);
	for (count = vt->vt_top_row_num; count < vt->vt_num_rows; count++)
	{
		field_ptr = vt->vt_items[count]->ptr;
		acc_num_lines2 += field_ptr->bounds.height/line_height; 
		if (acc_num_lines2 > table_max_num_lines)
		{
			vt->vt_num_rows_displayed = count - vt->vt_top_row_num;
			set = TRUE;
			break;
		}
	}
	if (set == FALSE)
		vt->vt_num_rows_displayed = vt->vt_num_rows - vt->vt_top_row_num; 
	acc_num_lines += top_line_num;
	for (count = vt->vt_top_row_num; count < (vt->vt_top_row_num + vt->vt_num_rows_displayed);count++)
	{
		field_ptr = vt->vt_items[count]->ptr;
		acc_num_lines1 += (field_ptr->bounds.height/line_height);
	}
	
	ScrollbarSetScrollbar(vt->vt_scrollbar_id, acc_num_lines, VTGetScrollbarMaxValue(vt), 0, acc_num_lines1, table_total_num_lines);
	scroll_ptr->scrollbar_draw_pagesize = table_max_num_lines;
	ScrollbarDrawScrollbar(vt->vt_scrollbar_id);
	return TRUE;
}

/********************************************************
* Function:	VTScrollbarSetVirtualTable
* Purpose: 	This function is called in order to change the content 
of a table when a scrollbar is being moved
* Scope:		application
* Input:		None
* Output:		row_to_be_drawn			if a particular field object is required to be drawn
* Return:		VT_TABLE_CHANGED
VT_TABLE_NOT_CHANGED
VT_FIELD_CHANGED
* Comment: 	None
*********************************************************/
BYTE VTScrollbarSetVirtualTable(VirtualTable* vt, EvtType *Event, USHORT *row_to_be_drawn)
{
	BYTE object_type;
	WORD *row_num_lines;		/* The numbers of lines of different field objects in the table*/
	USHORT table_current_row;
	USHORT table_largest_top_row_num;
	WORD temp;
	Field *field_ptr;
	Scrollbar *scroll_ptr;
	WORD table_max_num_lines, table_total_num_lines;
	WORD value, max_value, min_value, pagesize, scrollbar_total_num_lines;
	WORD count, acc_num_lines = 0, acc_num_lines1 = 0, field_current_line_num;
	WORD num_lines;
	SHORT line_height = 0;
	BYTE change_status = VT_TABLE_NOT_CHANGED;
	BOOLEAN done = FALSE;
	
	*row_to_be_drawn = 0;
	FormGetObjectPointer(vt->vt_scrollbar_id, &object_type, (void**)&scroll_ptr);
	VTGetTableMaxNumLines(vt, &table_max_num_lines);
	VTGetTableTotalNumLines(vt, &table_total_num_lines);
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	
	row_num_lines = (WORD*)qmalloc(vt->vt_num_rows*sizeof(WORD));
	
	for (count = 0; count < (vt->vt_num_rows); count++)
	{
		StrAnalyzeLine(vt->vt_items[count]->ptr);
		VTGetFieldTotalNumLines(vt, (USHORT)count, &temp);
		row_num_lines[count] = temp;
	}
	
	for (count = 0; count < (vt->vt_num_rows); count++)
	{
		acc_num_lines += row_num_lines[count];
		if ((WORD)(Event->para2) < acc_num_lines)
		{
			table_current_row = (USHORT)count;
			acc_num_lines -= row_num_lines[count];
			field_current_line_num = (WORD)((WORD)(Event->para2) - (WORD)(acc_num_lines));
			break;
		}
	}
	
	for (count = (vt->vt_num_rows - 1); count >=0; count--)
	{
		acc_num_lines1 += row_num_lines[count];
		if (acc_num_lines1 > table_max_num_lines)
		{
			table_largest_top_row_num = count + 1;
			break;
		}
	}
	
	ScrollbarGetScrollbar(vt->vt_scrollbar_id, &value, &max_value, &min_value, &pagesize, &scrollbar_total_num_lines);
	if (vt->vt_top_row_num != table_current_row)
	{	
		vt->vt_top_row_num = table_current_row;
		change_status = VT_TABLE_CHANGED;
	}
	if (vt->vt_top_row_num > table_largest_top_row_num)
	{
		vt->vt_top_row_num = table_largest_top_row_num;
		change_status = VT_TABLE_CHANGED;
	}
	
	for (count = vt->vt_top_row_num; count < vt->vt_num_rows; count++)
	{
		if (vt->vt_items[count]->ptr->field_total_num_lines <= table_max_num_lines)
			vt->vt_items[count]->ptr->bounds.height = vt->vt_items[count]->ptr->field_total_num_lines * line_height;
		else vt->vt_items[count]->ptr->bounds.height = table_max_num_lines * line_height;
		vt->vt_items[count]->ptr->screen_bounds.height = vt->vt_items[count]->ptr->bounds.height;
		vt->vt_row_height[count] = vt->vt_items[count]->ptr->bounds.height;
		StrAnalyzeLine(vt->vt_items[count]->ptr);
	}
	field_ptr = vt->vt_items[vt->vt_top_row_num]->ptr;
	if (field_current_line_num > (field_ptr->field_total_num_lines - field_ptr->field_num_lines_displayed))
	{
		if ((Event->para2 - Event->para1) > 0)
		{
			if (vt->vt_top_row_num != vt->vt_num_rows - 1)
			{
				vt->vt_top_row_num ++;
				(WORD)(Event->para2) += (field_ptr->field_total_num_lines - field_current_line_num);
				change_status = VT_TABLE_CHANGED;
			}
			else
			{
				(WORD)(Event->para2) -= (field_ptr->field_num_lines_displayed - (field_ptr->field_total_num_lines - field_current_line_num));
			}
		}
		else if ((Event->para2 - Event->para1) < 0)
		{
			(WORD)(Event->para2) -= (field_ptr->field_num_lines_displayed - (field_ptr->field_total_num_lines - field_current_line_num));
		}
	}
	else
	{	
		field_ptr->field_top_line_num = field_current_line_num;
		if (change_status != VT_TABLE_CHANGED) 
		{
			*row_to_be_drawn = vt->vt_top_row_num;
			change_status = VT_FIELD_CHANGED;
		}
	}
	
	acc_num_lines = 0;
	for (count = vt->vt_top_row_num; count < vt->vt_num_rows; count++)
	{
		VTGetFieldTotalNumLines(vt, (USHORT)count, &num_lines);
		acc_num_lines += num_lines;
		field_ptr = vt->vt_items[count]->ptr;
		if (acc_num_lines <= table_max_num_lines)
		{
			if (field_ptr->bounds.height != field_ptr->field_total_num_lines * line_height)
			{	
				field_ptr->bounds.height = field_ptr->field_total_num_lines * line_height;
				vt->vt_row_height[count] = field_ptr->bounds.height;
				change_status = VT_TABLE_CHANGED;
			}
			if (acc_num_lines == table_max_num_lines) break;
		}
		else if (acc_num_lines > table_max_num_lines)
		{
			acc_num_lines -= num_lines;
			field_ptr = vt->vt_items[count]->ptr;
			if ((field_ptr->bounds.height != (table_max_num_lines - acc_num_lines) * line_height) ||
				(vt->vt_row_height[count] != (table_max_num_lines - acc_num_lines) * line_height))
			{	
				field_ptr->bounds.height = (table_max_num_lines - acc_num_lines) * line_height;
				vt->vt_row_height[count] = field_ptr->bounds.height;
				change_status = VT_TABLE_CHANGED;
			}
			break;
		}
	}
	
	VTUpdateNumRowsDisplayed(vt);	
	ScrollbarSetScrollbar(vt->vt_scrollbar_id, (WORD)(Event->para2), max_value, 0, pagesize, scrollbar_total_num_lines);
	ScrollbarDrawScrollbar(vt->vt_scrollbar_id);
	
	acc_num_lines = 0;
	for (count = vt->vt_top_row_num; count < vt->vt_num_rows_displayed; count++)
	{
		field_ptr = vt->vt_items[count]->ptr;
		acc_num_lines += field_ptr->field_total_num_lines;
		if (acc_num_lines <= table_max_num_lines)
		{
			if (field_ptr->bounds.height != field_ptr->field_total_num_lines * line_height)
			{	
				field_ptr->bounds.height = field_ptr->field_total_num_lines * line_height;
				vt->vt_row_height[count] = field_ptr->bounds.height;
				change_status = VT_TABLE_CHANGED;
			}
			field_ptr->field_top_line_num = 0;
			if (acc_num_lines == table_max_num_lines) break;
		}
		else
		{
			acc_num_lines -= field_ptr->field_total_num_lines;
			if ((field_ptr->bounds.height != (table_max_num_lines - acc_num_lines) * line_height) ||
				(vt->vt_row_height[count] != (table_max_num_lines - acc_num_lines) * line_height))
			{
				field_ptr->bounds.height = (table_max_num_lines - acc_num_lines)*line_height;
				vt->vt_row_height[count] = field_ptr->bounds.height;
				StrAnalyzeLine(field_ptr);
				change_status = VT_TABLE_CHANGED;
			}
		}
	}	
	qfree(row_num_lines);
	VTUpdateNumRowsDisplayed(vt);
	return change_status;
}

/*********************************************************************
* Function	: VTUpdateNumRowsDisplayed
* Purpose	: This function is called to update the num of row that will be 
displayed in the table
* Scope		: Application/Internal
* Input		: vt					The pointer to virtual table object
* Output	: None
* Return	: None
* Comment	: Assume that there is teh reference column is full of field objects
**********************************************************************/
void VTUpdateNumRowsDisplayed(VirtualTable *vt)
{
	Field *field_ptr;
	WORD count;
	SHORT line_height;
	WORD table_max_num_lines;
	WORD acc_num_lines = 0;
	
	line_height = SysGetFontHeight(vt->vt_font_size) + SPACE_LINE;
	table_max_num_lines = vt->vt_bounds.height/line_height;
	count = vt->vt_top_row_num;
	while (count < vt->vt_num_rows)
	{
		field_ptr = vt->vt_items[count]->ptr;	
		acc_num_lines += field_ptr->bounds.height/line_height; 
		if (acc_num_lines > table_max_num_lines)
		{
			vt->vt_num_rows_displayed = count - vt->vt_top_row_num;
			return;
		}
		count++;
	}
	vt->vt_num_rows_displayed = vt->vt_num_rows - vt->vt_top_row_num; 
	return;
}

/********************************************************
* Function:	VTSetRowAppointment
* Purpose: 	This function is called in order to set the row appointment
* Scope:		application
* Input:		vt					The Pointer to virtual table object
row_num				The required row number
appointment			appointment row number
* Output:		None
* Return:		ERR_VT_ROW_NUM_INVALID
* Comment: 	None
*********************************************************/
Err VTSetRowAppointment(VirtualTable *vt, USHORT row_num, WORD appointment)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	//	vt->vt_items[row_num]->appointment = appointment;
	return TRUE;
}

/********************************************************
* Function:	VTGetRowAppointment
* Purpose: 	This function is called in order to set the row appointment
* Scope:		application
* Input:		vt					The Pointer to virtual table object
row_num				The required row number
* Output:		appointment			pointer to appointment attribute
* Return:		ERR_VT_ROW_NUM_INVALID
* Comment: 	None
*********************************************************/
Err VTGetRowAppointment(VirtualTable *vt, USHORT row_num, WORD *appointment)
{
	if (row_num >= vt->vt_num_rows)
		return ERR_VT_ROW_NUM_INVALID;
	
	//	*appointment = vt->vt_items[row_num]->appointment;
	return TRUE;
}

/********************************************************
* Function:	VTTransferStringToVT
* Purpose: 	This function is called in order to copy the content of string objects 
in the real table to virtual table 
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferStringToVT(VirtualTable *vt, ObjectID table_id)
{
	BYTE *string_text;
	
	USHORT table_top_row_num = 0;
	USHORT table_num_rows_displaying = 0, count = 0;
	
	TableGetTopRowNum(table_id, &table_top_row_num);
	TableGetNumOfRowsDisplayed(table_id, &table_num_rows_displaying);
	
	/*for (count = 0; count < table_num_rows_displaying; count++)
	{
	//StringGetText((ObjectID)(count + STRING_SCH_DAY_VIEW_0 + table_top_row_num), &string_text);
	//	VTSetTextPointer(vt, (USHORT)(vt->vt_top_row_num + count), string_text);
}*/
}


/********************************************************
* Function:	VTTransferFieldToVT 
* Purpose: 	This function is called to copy the field 
content from real table to virtual table object
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferFieldToVT(VirtualTable *vt, ObjectID table_id)
{
	BYTE *field_text;
	Field *field_ptr;
	BYTE object_type;
	
	USHORT table_top_row_num = 0;
	USHORT table_num_rows_displaying = 0, count = 0;
	
	TableGetTopRowNum(table_id, &table_top_row_num);
	TableGetNumOfRowsDisplayed(table_id, &table_num_rows_displaying);
	
	for (count = 0; count < table_num_rows_displaying; count++)
	{
		FieldGetTextPointer((ObjectID)(count + FIELD_ALARMPP_0 + table_top_row_num), &field_text);
		FormGetObjectPointer((ObjectID)(count + FIELD_ALARMPP_0 + table_top_row_num), &object_type, (void**)&field_ptr);
		if (vt->vt_items[count + vt->vt_top_row_num]->ptr->field_string != NULL)
			qfree(vt->vt_items[count + vt->vt_top_row_num]->ptr->field_string);
		vt->vt_items[count + vt->vt_top_row_num]->ptr->field_string = NULL;
		*(vt->vt_items[count + vt->vt_top_row_num]->ptr) = *field_ptr;
		vt->vt_items[count + vt->vt_top_row_num]->ptr->field_string = NULL;
		VTSetFieldTextPointer(vt, (USHORT)(vt->vt_top_row_num + count), field_text);
		if (field_ptr->field_attr.field_insert_pt_visible == TRUE)
			vt->vt_active_row = count + vt->vt_top_row_num;
	}
	
}

/********************************************************
* Function:	VTTransferAlarmToVT 
* Purpose: 	This function is called to copy the alarm settings
content from real table to virtual table object
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferAlarmToVT(VirtualTable *vt, ObjectID table_id)
{
	Bitmap *bitmap_ptr;
	BYTE object_type;
	
	USHORT table_top_row_num = 0;
	USHORT table_num_rows_displaying = 0, count = 0;
	
	TableGetTopRowNum(table_id, &table_top_row_num);
	TableGetNumOfRowsDisplayed(table_id, &table_num_rows_displaying);
	
	for (count = 0; count < table_num_rows_displaying; count++)
	{
		FormGetObjectPointer((ObjectID)(count + table_top_row_num + BITMAP_ALARMPP_0), &object_type, (void**)&bitmap_ptr);
		if (bitmap_ptr->bitmap_attr.bitmap_drawn)
		{
			if (bitmap_ptr->bitmap_attr.bitmap_enter)
				VTSetRowAlarm(vt, (USHORT)(count + vt->vt_top_row_num), TONE_ALARM, DONT_CARE);
			else VTSetRowAlarm(vt, (USHORT)(count + vt->vt_top_row_num), VOICE_ALARM, DONT_CARE);
		}
		else VTSetRowAlarm(vt, (USHORT)(count + vt->vt_top_row_num), NO_ALARM, NO_ALARM);
	}
}

/********************************************************
* Function:	VTTransferTableToVT 
* Purpose: 	This function is called to copy the table settings
content from real table to virtual table object
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferTableToVT(VirtualTable *vt, ObjectID table_id)
{
	BYTE object_type;
	Table *table_ptr;
	BYTE font_size;
	USHORT count;
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	
	FieldGetFont((ObjectID)(FIELD_ALARMPP_0 + table_ptr->table_top_row_num), &font_size);
	
	vt->vt_bounds = table_ptr->bounds;
	vt->vt_font_size = font_size;
	vt->vt_num_rows_displayed = table_ptr->table_num_row_display;
	table_ptr->table_top_row_num = 0;
	
	for (count = 0; count < vt->vt_num_rows_displayed; count++)
		table_ptr->table_row_height[count] = vt->vt_row_height[count + vt->vt_top_row_num];
	
	for (count = 0; count < vt->vt_num_cols; count++)
		table_ptr->table_row_height[count] = vt->vt_row_height[count];		
}

/********************************************************
* Function:	VTTransferAllToVT 
* Purpose: 	This function is called to copy the table settings
content from real table to virtual table object
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferAllToVT(VirtualTable *vt, ObjectID table_id)
{
	VTTransferFieldToVT(vt, table_id);
	VTTransferAlarmToVT(vt, table_id);
	VTTransferTableToVT(vt, table_id);
}


/********************************************************
* Function:	VTTransferFieldToRT
* Purpose: 	This function is called to copy the field content in virtual
table object to Real Table
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferFieldToRT(VirtualTable *vt, ObjectID table_id)
{
	Field *field_ptr;
	BYTE object_type;
	ObjectID field_id;
	BYTE *old_text;
	WORD first_char_pos, last_char_pos;
	
	USHORT count = 0;
	
	for (count = 0; count < 14; count++)
	{
		FormGetObjectPointer((ObjectID)(count + FIELD_ALARMPP_0), &object_type, (void**)&field_ptr);
		if (count >= vt->vt_num_rows_displayed)
		{
			field_ptr->field_attr.field_drawn = FALSE;
			field_ptr->field_attr.field_visible = FALSE;
			continue;
		}		
		field_id = field_ptr->identification.ui_object_id;
		old_text = field_ptr->field_string;
		*field_ptr = *(vt->vt_items[count + vt->vt_top_row_num]->ptr);
		field_ptr->field_string = old_text;
		field_ptr->identification.ui_object_id = field_id;
		field_ptr->identification.table_related = table_id;
		FieldSetText((ObjectID)(count + FIELD_ALARMPP_0), vt->vt_items[count + vt->vt_top_row_num]->ptr->field_string);
		field_ptr->field_font_id = vt->vt_font_size;
		TableUpdateObjectScreenBounds(table_id, field_id);
		StrAnalyzeLine(field_ptr);
		VTFieldGetFirstVisibleChar (field_ptr, &first_char_pos);
		VTFieldGetLastVisibleChar (field_ptr, &last_char_pos);
		vt->vt_items[count + vt->vt_top_row_num]->ptr->field_num_lines_displayed = field_ptr->field_num_lines_displayed;
		vt->vt_items[count + vt->vt_top_row_num]->ptr->screen_bounds = field_ptr->screen_bounds;
		
   	    LcdEnableInsertPt(FALSE, 0, 0, vt->vt_font_size);
		field_ptr->field_attr.field_insert_pt_visible = FALSE;
	}
	
}				


/********************************************************
* Function:	VTTransferAlarmToRT
* Purpose: 	This function is called to copy the alarm settings in virtual
table object to Real Table
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferAlarmToRT(VirtualTable *vt, ObjectID table_id)
{
	USHORT count = 0;
	BYTE object_type;
	Bitmap *bitmap_ptr;
	
	for (count = 0; count < vt->vt_num_rows_displayed; count++)
	{
		FormGetObjectPointer((ObjectID)(count + BITMAP_ALARMPP_0), &object_type, (void**)&bitmap_ptr);
		switch(vt->vt_items[count + vt->vt_top_row_num]->alarm)
		{
		case NO_ALARM:
			printf("\n ALARM -----> NO_ALARM_ALARM");
			bitmap_ptr->bitmap_attr.bitmap_visible = FALSE;
			break;
		case VOICE_ALARM:
			bitmap_ptr->bitmap_attr.bitmap_visible = TRUE;
			bitmap_ptr->bitmap_attr.bitmap_enter = FALSE;
			bitmap_ptr->bitmap_style = 0;
			bitmap_ptr->bitmap_attr.bitmap_enable = TRUE;
			printf("\n ALARM -----> VOICE_ALARM");
			break;
		case TONE_ALARM:
			printf("\n ALARM -----> TONE_ALARM");
			bitmap_ptr->bitmap_attr.bitmap_visible = TRUE;
			bitmap_ptr->bitmap_attr.bitmap_enter = TRUE;
			bitmap_ptr->bitmap_style = 1;
			bitmap_ptr->bitmap_attr.bitmap_enable = FALSE;
			break;
		default: break;
		}
	}
}		

/********************************************************
* Function:	VTTransferTableToRT
* Purpose: 	This function is called to copy the table settings in virtual
table object to Real Table
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferTableToRT(VirtualTable *vt, ObjectID table_id)
{
	USHORT count = 0;
	BYTE object_type;
	Table *table_ptr;
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	table_ptr->table_top_row_num = 0;
	table_ptr->table_num_row_display = 0;
	for (count = 0; count < vt->vt_num_rows_displayed; count++)
		table_ptr->table_row_height[count] = vt->vt_row_height[count + vt->vt_top_row_num];
	for(count = 0; count < vt->vt_num_cols; count++)
		table_ptr->table_column_width[count] = vt->vt_col_width[count];
	table_ptr->table_num_column = vt->vt_num_cols;
	table_ptr->table_num_row = vt->vt_num_rows_displayed;
	table_ptr->table_num_row_display = vt->vt_num_rows_displayed;
}	

/********************************************************
* Function:	VTTransferAllToRT
* Purpose: 	This function is called to copy the All settings in virtual
table object to Real Table
* Scope:		application
* Input:		vt					The Pointer to virtual table object
table_id			The ID value of table object
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTTransferAllToRT(VirtualTable *vt, ObjectID table_id)
{
	VTTransferTableToRT(vt, table_id);
	VTTransferFieldToRT(vt, table_id);
    printf("\n All To RT");
	VTTransferAlarmToRT(vt, table_id);
}


/********************************************************
* Function:    VTChangeFont
* Purpose:     This function is called to change the font of the display
* Scope:		application
* Input:		vt					The Pointer to virtual table object                
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void VTChangeFont(VirtualTable *vt)
{
	
#if 0
    if (virtual_table.vt_font_size == SMALL_FONT)
        VTSetTableFontSize(&virtual_table, MEDIUM_FONT);
    else VTSetTableFontSize(&virtual_table, SMALL_FONT);
	
    for (count = 0; count < virtual_table.vt_num_rows; count++)
    {
        virtual_table.vt_items[count]->ptr->bounds.height = 9;
        virtual_table.vt_items[count]->ptr->screen_bounds.height = 9;
        virtual_table.vt_row_height[count] = 9; 
    }
	
    VTSetVirtualTableLayout(&virtual_table);
    VTVirtualTableSetScrollbar(&virtual_table);
    VTTransferAllToRT(&virtual_table, TABLE_SCH_DAY_VIEW);       
	
    TableDrawTable(TABLE_SCH_DAY_VIEW);
    ScrollbarDrawScrollbar(SCROLLBAR_SCH_DAY_VIEW);
    SchedulerDayViewDrawAppointmentColumn(&virtual_table, TABLE_SCH_DAY_VIEW);
    if (virtual_table.vt_font_size == SMALL_FONT)
        ControlSet
		
    {
		MenuDeleteItem(MENU_SCH_DAY_VIEW, 4);
		MenuInsertItem(MENU_SCH_DAY_VIEW, 4, ALMLFONT);
	}
	else
	{
		MenuDeleteItem(MENU_SCH_DAY_VIEW, 4);
		MenuInsertItem(MENU_SCH_DAY_VIEW, 4, ALMSFONT);
	}
#endif
}


