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


#include "stdafx.h"
#include "app.h"

//#define DEBUG
//#define DEBUG_SCROLL

/********************************************************
* Function:	EmailEditChangeFont
* Purpose: 	This function is called in order to change the font size fo the 
font in each field object
* Scope:		application
* Input:		None
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailEditChangeFont(BOOLEAN draw)
{
	Field *field_ptr;
	Table *table_ptr;
	Scrollbar *scroll_ptr;
	BYTE object_type;
	USHORT count;
	SHORT line_height;
	BYTE original_font;
	WORD acc_num_lines = 0;
	WORD num_lines_displayed = 0;
	
	if (edit_table_font_size == MEDIUM_FONT) edit_table_font_size = SMALL_FONT;
	else edit_table_font_size = MEDIUM_FONT;
	font_size = edit_table_font_size;
	FormGetObjectPointer(TABLE_EDIT, &object_type, (void**)&table_ptr);
	FormGetObjectPointer(SCROLLBAR_EDIT, &object_type, (void**)&scroll_ptr);
	FieldGetFont(FIELD_EDIT_0, &original_font);
	line_height = SysGetFontHeight(edit_table_font_size) + SPACE_LINE;
	
	switch (edit_table_font_size)
	{
	case SMALL_FONT:
		MenuDeleteItem(MENU_POPUP1, 4);
		MenuInsertItem(MENU_POPUP1, 4, EMLFONT);
		if (original_font == SMALL_FONT) return TRUE;
		for (count = 0; count < (table_ptr->table_num_row); count++)
		{
			table_ptr->table_row_height[count] = SysGetFontHeight(SMALL_FONT) + SPACE_LINE;
			FormGetObjectPointer((ObjectID)(FIELD_EDIT_0 + count), &object_type, (void**)&field_ptr);
			field_ptr->bounds.height = table_ptr->table_row_height[count];
			field_ptr->field_font_id = SMALL_FONT;
			TableUpdateObjectScreenBounds(TABLE_EDIT, (ObjectID)(FIELD_EDIT_0 + count));
			StrAnalyzeLine(field_ptr);
		}
		break;
	case MEDIUM_FONT:
		MenuDeleteItem(MENU_POPUP1, 4);
		MenuInsertItem(MENU_POPUP1, 4, EMSFONT);
		if (original_font == MEDIUM_FONT) return TRUE;
		for (count = 0; count < (table_ptr->table_num_row); count++)
		{
			table_ptr->table_row_height[count] = SysGetFontHeight(MEDIUM_FONT) + SPACE_LINE;
			FormGetObjectPointer((ObjectID)(FIELD_EDIT_0 + count), &object_type, (void**)&field_ptr);
			field_ptr->bounds.height = table_ptr->table_row_height[count];
			field_ptr->field_font_id = MEDIUM_FONT;
			TableUpdateObjectScreenBounds(TABLE_EDIT, (ObjectID)(FIELD_EDIT_0 + count));
			StrAnalyzeLine(field_ptr);
		}
		break;
	default: return FALSE;
	}
    EmailSetEditTable(FORM_EDIT, TABLE_EDIT);
	EmailEditTableSetScrollbar(TABLE_EDIT, SCROLLBAR_EDIT);
	
	if (draw == TRUE)
	{
		TableEraseTable(TABLE_EDIT);
		TableDrawTable(TABLE_EDIT);
	}
	return TRUE;
}

/********************************************************
* Function:	EmailMailListChangeFont
* Purpose: 	This function is called in order to change the font size fo the 
font in each field object
* Scope:		application
* Input:		None
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailMailListChangeFont(BOOLEAN draw)
{
	Field *field_ptr;
	Table *table_ptr;
	Scrollbar *scroll_ptr;
	BYTE object_type;
	USHORT count;
	SHORT line_height;
	BYTE original_font;
	WORD acc_num_lines = 0;
	WORD num_lines_displayed = 0;
	
	if (mail_list_table_font_size == MEDIUM_FONT) mail_list_table_font_size = SMALL_FONT;
	else mail_list_table_font_size = MEDIUM_FONT;
	
	font_size = mail_list_table_font_size;
	
	FormGetObjectPointer(TABLE_MAIL_LIST, &object_type, (void**)&table_ptr);
	FormGetObjectPointer(SCROLLBAR_MAIL_LIST, &object_type, (void**)&scroll_ptr);
	FieldGetFont(FIELD_MAIL_LIST_TO, &original_font);
	line_height = SysGetFontHeight(mail_list_table_font_size) + SPACE_LINE;
	
	switch (mail_list_table_font_size)
	{
	case SMALL_FONT:
		MenuDeleteItem(MENU_POPUP1, 4);
		MenuInsertItem(MENU_POPUP1, 4, EMLFONT);
		if (original_font == SMALL_FONT) return TRUE;
		for (count = 0; count < (table_ptr->table_num_row); count++)
		{
			table_ptr->table_row_height[count] = SysGetFontHeight(SMALL_FONT) + SPACE_LINE;
			FormGetObjectPointer((ObjectID)(FIELD_MAIL_LIST_TO + count), &object_type, (void**)&field_ptr);
			field_ptr->bounds.height = table_ptr->table_row_height[count];
			field_ptr->field_font_id = SMALL_FONT;
			TableUpdateObjectScreenBounds(TABLE_MAIL_LIST, (ObjectID)(FIELD_MAIL_LIST_TO + count));
			StrAnalyzeLine(field_ptr);
		}
		break;
	case MEDIUM_FONT:
		MenuDeleteItem(MENU_POPUP1, 4);
		MenuInsertItem(MENU_POPUP1, 4, EMSFONT);
		if (original_font == MEDIUM_FONT) return TRUE;
		for (count = 0; count < (table_ptr->table_num_row); count++)
		{
			table_ptr->table_row_height[count] = SysGetFontHeight(MEDIUM_FONT) + SPACE_LINE;
			FormGetObjectPointer((ObjectID)(FIELD_MAIL_LIST_TO + count), &object_type, (void**)&field_ptr);
			field_ptr->bounds.height = table_ptr->table_row_height[count];
			field_ptr->field_font_id = MEDIUM_FONT;
			TableUpdateObjectScreenBounds(TABLE_MAIL_LIST, (ObjectID)(FIELD_MAIL_LIST_TO + count));
			StrAnalyzeLine(field_ptr);
		}
		break;
	default: return FALSE;
	}
    EmailSetEditTable(FORM_MAIL_LIST, TABLE_MAIL_LIST);
	EmailEditTableSetScrollbar(TABLE_MAIL_LIST, SCROLLBAR_MAIL_LIST);
	if (draw == TRUE)
	{
		TableDrawTable(TABLE_MAIL_LIST);
		TableDrawTable(TABLE_MAIL_LIST);
	}
	return TRUE;
}


/********************************************************
* Function:	EmailGetTableNumLines
* Purpose: 	This function is called in order to get
the total number of lines in table a object (if 
a column is full of field objects
* Scope:		application
* Input:		table_id			The ID value of table object to be scrolled
*				ref_col				the column number of the reference row
* Output:		total_num_lines		The total number of lines
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	The reference row should consists only of field objects
*********************************************************/
BOOLEAN EmailGetTableNumLines(ObjectID table_id, USHORT ref_col, WORD *total_num_lines)
{
	Table *addr;
	BYTE object_type;
	USHORT num_rows, count;
	WORD field_num_lines;
	
	if (FormGetObjectPointer(table_id, &object_type, (void**)&addr) != TRUE)
		return FALSE;
	
	num_rows = addr->table_num_row;
	*total_num_lines = 0;
	
	for (count = ref_col; count < (addr->table_num_row * addr->table_num_column); count += addr->table_num_column)
	{
		FieldGetTotalNumOfLines((ObjectID)((addr->table_item_ptr[count])->table_item_ui_id), &field_num_lines);
		*total_num_lines += (USHORT)field_num_lines;
	}
	return TRUE;
}

/********************************************************
* Function:	EmailGetTableMaxNumLines
* Purpose: 	This function is called to in order to get
the max num of lines that the table can 
handle
* Scope:		application
* Input:		table_id			The ID value of table object to be scrolled
*				font_id				The font type
* Output:		max_num_lines		The maximum number of lines
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailGetTableMaxNumLines(ObjectID table_id, BYTE font_id, WORD *max_num_lines)
{
	Table *addr;
	BYTE object_type;
	SHORT table_height;
	SHORT line_height;
	
	if (FormGetObjectPointer(table_id, &object_type, (void**)&addr) != TRUE)
		return FALSE;
	
	table_height = addr->bounds.height;
	line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	
	*max_num_lines = table_height / line_height;
	return TRUE;
}

/********************************************************
* Function:	EmailGetScrollBarMaxValue
* Purpose: 	This fucntion is called in order to work out the 
max value of the scrollbar
* Scope:		application
* Input:		None
* Output:		None
* Return:		max. value
* Comment: 	None
*********************************************************/
WORD EmailGetScrollbarMaxValue(ObjectID table_id, USHORT ref_col)
{
	Table *table_ptr;
	SHORT count = 0;
	WORD acc_num_lines = 0;
	WORD max_num_lines;
	BYTE object_type;
	BYTE font_id;
	WORD num_lines;
	WORD total_num_lines;
	
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	FieldGetFont(table_ptr->table_item_ptr[ref_col]->table_item_ui_id, &font_id);
	
	EmailGetTableMaxNumLines(table_id, font_id, &max_num_lines);
	EmailGetTableNumLines(table_id, 1, &total_num_lines);
	
	for (count = (table_ptr->table_num_row - 1); count >= 0; count--)
	{
		FieldGetTotalNumOfLines((ObjectID)(table_ptr->table_item_ptr[count * table_ptr->table_num_column + ref_col]->table_item_ui_id), &num_lines);
		
		acc_num_lines += num_lines;
		
		if (acc_num_lines > max_num_lines)
		{
			acc_num_lines -= num_lines;
			
            if (acc_num_lines == 0)
                acc_num_lines = max_num_lines;
			
			return (total_num_lines - acc_num_lines);
        }
    }
	
	return (total_num_lines - acc_num_lines);
}

/********************************************************
* Function:	EmailDecideTopRowNum
* Purpose:		This function is called to decide the to row number
of the table with field objects
* Scope:		application
* Input:		table_id			The ID value of table object to be scrolled
field_id			The focused field object
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	The decision is made depending on the 
*********************************************************/
BOOLEAN EmailDecideTopRowNum(ObjectID table_id, ObjectID active_id)
{
	Table *addr;
	ObjectID first_field_id;
	BYTE object_type;
	USHORT count;
	USHORT active_row;
	BYTE font_id;
	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;
	
	if (FormGetObjectPointer(table_id, &object_type, (void**)&addr) != TRUE)
		return FALSE;
	
	first_field_id = (addr->table_item_ptr[1])->table_item_ui_id;
	FieldGetFont(active_id, &font_id);	
	line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	
	for(count = 0; count < (addr->table_num_row); count++)
		if (active_id == (ObjectID)(first_field_id + count)) active_row = count;
		
		EmailGetTableMaxNumLines(table_id, font_id, &max_num_lines);
		
		row_num = addr->table_top_row_num;
		while (row_num < (addr->table_num_row))
		{
			TableUpdateObjectScreenBounds(table_id, (ObjectID)(first_field_id + row_num));
			FormGetObjectPointer((ObjectID)(first_field_id + row_num), &object_type, (void**)&field_ptr);
			StrAnalyzeLine(field_ptr);
			FieldGetTotalNumOfLines((ObjectID)(first_field_id + row_num), &field_num_lines);
			acc_num_lines += (USHORT)field_num_lines;
			if ((acc_num_lines > max_num_lines) && row_num <= active_row &&
				addr->table_top_row_num != active_row)
			{
				acc_num_lines = 0;
				addr->table_top_row_num ++;
				row_num = addr->table_top_row_num;
				field_num_lines = 0;
				return_boolean = TRUE;
			}
			else if ((acc_num_lines > max_num_lines) && row_num == active_row &&
				addr->table_top_row_num == active_row)
			{
				FormGetObjectPointer((ObjectID)(first_field_id + active_row), &object_type, (void**)&field_ptr);
				if (field_ptr->bounds.height != max_num_lines * line_height)
				{	
					field_ptr->bounds.height = field_ptr->field_total_num_lines * line_height;
					addr->table_row_height[active_row] = field_ptr->bounds.height;
					return TRUE;
				}
				else return FALSE;
			}
			else if ((acc_num_lines > max_num_lines) && addr->table_top_row_num == active_row &&
				row_num > active_row)
				return FALSE;
			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 == addr->table_num_row - 1)
			{
				if (return_boolean == FALSE) return FALSE;
				else return TRUE;
			}
			else row_num++;
		}
		return TRUE;
}

/********************************************************
* Function:	EmailSetEditTable
* Purpose: 	This function is called in order to 
set up the table in the Email Edit screen 
when the data is first put to table or the ekyboard is popuped 
up and down
* Scope:		application
* Input:		form_id				The ID value of the form that the table is on
table_id			The ID value of table object to be scrolled
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailSetEditTable(ObjectID form_id, ObjectID table_id)
{
	ObjectID first_field_id;	/*the field object id in the first row of the table */
	ObjectID active_id;			/*The ID value of the field object in the table */
	WORD count = 0;				/* another temperatory variable */
	BYTE object_type;
	Table *table_ptr;
	Field *field_ptr;
	USHORT table_num_rows;
	WORD table_max_num_lines, total_num_lines;
	BYTE font_id;
	SHORT field_height;
	SHORT line_height;			/* line_height = SysGetFontHeight(font_id) + SPACE_LINE;*/
	BOOLEAN insert_pt_on = FALSE;
	BOOLEAN highlight_pt_on = FALSE;
	USHORT table_top_row_num, table_num_row_displayed;
	SHORT acc_height = 0;
	WORD first_visible_char, last_visible_char;
	WORD line_num, temp;
	
	/*The bounds of the table should be set outside this function according
	to the keyboard status */
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	first_field_id = (table_ptr->table_item_ptr[1])->table_item_ui_id;
	table_num_rows = table_ptr->table_num_row;
	
	FieldGetFont(first_field_id, &font_id);
	EmailGetTableMaxNumLines(table_id, font_id, &table_max_num_lines);
	EmailGetTableNumLines(table_id, 1, &total_num_lines);
	line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	FormGetActiveObject(form_id, &active_id);
	if (active_id < first_field_id || active_id > (table_num_rows - 1 + first_field_id))
		active_id = (ObjectID)(table_ptr->table_top_row_num + first_field_id);
	else
	{
		FormGetObjectPointer(active_id, &object_type, (void**)&field_ptr);		
		insert_pt_on = field_ptr->field_attr.field_insert_pt_visible;
		highlight_pt_on = field_ptr->field_attr.field_highlight;
	}
	
	/* 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)
		TableSetTopRowNum(table_id, 0);
	
	
	/*set up the bounds of the field object*/
	for (count = 0; count < table_num_rows; count++)
	{
		FormGetObjectPointer((ObjectID)(count + first_field_id), &object_type, (void**)&field_ptr);		
		field_height = field_ptr->field_total_num_lines * line_height;
		if (field_height >= table_ptr->bounds.height)
		{
			table_ptr->table_row_height[count] = table_ptr->bounds.height;
			field_ptr->bounds.height = table_ptr->bounds.height;
		}
		else
		{
			table_ptr->table_row_height[count] = field_height;
			field_ptr->bounds.height = field_height;
		}
	}
	EmailDecideTopRowNum(table_id, active_id);         /*decide the top row num*/
	table_top_row_num = table_ptr->table_top_row_num;
	table_num_row_displayed  = 0;
	acc_height = 0;
	for (count = table_top_row_num; count < table_num_rows; count++)
	{
		acc_height += table_ptr->table_row_height[count];
		if (acc_height <= table_ptr->bounds.height)
		{
			table_num_row_displayed ++;
			TableUpdateObjectScreenBounds(table_id, (table_ptr->table_item_ptr[count * 2 + 1])->table_item_ui_id);
			FormGetObjectPointer((table_ptr->table_item_ptr[count * 2 + 1])->table_item_ui_id, &object_type, (void**)&field_ptr);		
			StrAnalyzeLine(field_ptr);
			if (acc_height >= (table_max_num_lines * line_height)) break;
		}
		else 
		{
			acc_height -= table_ptr->table_row_height[count];
			FormGetObjectPointer((ObjectID)(count + first_field_id), &object_type, (void**)&field_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;
			table_ptr->table_row_height[count] = field_ptr->bounds.height;
			field_ptr->field_top_line_num = 0;
			TableUpdateObjectScreenBounds(table_id, (ObjectID)(count + first_field_id));
			StrAnalyzeLine(field_ptr);
			break;
		}
	}
	if (insert_pt_on == TRUE || highlight_pt_on)
	{
		FormGetObjectPointer(active_id, &object_type, (void**)&field_ptr);
		StrAnalyzeLine(field_ptr);
		FieldGetFirstVisibleChar(active_id, &first_visible_char);
		FieldGetLastVisibleChar(active_id, &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 (insert_pt_on)
		{
			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)));
			}
		}
		else
		{
			temp = field_ptr->field_highlight_start_char;
			if (temp < field_ptr->field_highlight_end_char)
				temp = field_ptr->field_highlight_end_char;
			if (temp >= last_visible_char)
			{
				FieldCharPosToLineNum(field_ptr, temp, &line_num);
				if ((line_num - (field_ptr->bounds.height/(line_height)) + 1) < 0)
					field_ptr->field_top_line_num = 0;
				else
					field_ptr->field_top_line_num = line_num - (field_ptr->bounds.height/(line_height)) + 1;
			}
			else
			{
				temp = field_ptr->field_current_num_chars;
				FieldCharPosToLineNum(field_ptr, temp, &line_num);
				if ((field_ptr->field_top_line_num + (field_ptr->bounds.height/(line_height))) >= line_num)
					if ((line_num - (field_ptr->bounds.height/(line_height)) + 1) < 0)
						field_ptr->field_top_line_num = 0;
					else
						field_ptr->field_top_line_num = line_num - (field_ptr->bounds.height/(line_height)) + 1;
			}
		}
		
		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));
	}
	return TRUE;
}

/********************************************************
* Function:	EmailEditSetScreen
* Purpose: 	This function is called in order to set the layout of the 
Edit screen
* Scope:		application
* Input:		None
* Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailEditSetScreen()
{
	BYTE object_type;
	Table *table_ptr;
	Control *control_ptr;
	Scrollbar *scroll_ptr;
	String *string_ptr;
	BYTE email_box = 123;
	ObjectID count_id;
	Field *field_ptr;
	
	if (edit_entry_status.new_record == FALSE)
		DataRecordInfo(emess_dbid, edit_entry_status.rec_id, NULL, (UBYTE*)&email_box, NULL, NULL, NULL);
	
	/* initialise STRING_EDIT */
	FormGetObjectPointer(STRING_EDIT, &object_type, (void**)&string_ptr);
	if (rf_action == REPLY_TO_ALL || rf_action == REPLY_TO_SENDER)
		StringSetText(STRING_EDIT, EMREPLY);
	else if (rf_action == FORWARD)
		StringSetText(STRING_EDIT, EMFWD);
	else if (edit_entry_status.email_box == DRAFT)
		StringSetText(STRING_EDIT, EMDRAFT);
	else if (edit_entry_status.email_box == INBOX)
		StringSetText(STRING_EDIT, EMINBOX);
	else if (edit_entry_status.email_box == DRAFT)
		StringSetText(STRING_EDIT, EMDRAFT);
	else if (edit_entry_status.email_box == SENT)
		StringSetText(STRING_EDIT, EMSENT);
	else if (edit_entry_status.email_box == OUTBOX)
		StringSetText(STRING_EDIT, EMOUTBOX);
	
	/* initialise BUTTON_EDIT_REPLY */
	FormGetObjectPointer(BUTTON_EDIT_REPLY, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == FALSE && email_box == INBOX)
		control_ptr->control_attr.control_visible = TRUE;
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_FORWARD */
	FormGetObjectPointer(BUTTON_EDIT_FORWARD, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == FALSE && email_box == INBOX)
		control_ptr->control_attr.control_visible = TRUE;
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_CONNECT */
	FormGetObjectPointer(BUTTON_EDIT_CONNECT, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == FALSE && email_box != DRAFT)
	{
		control_ptr->control_attr.control_visible = TRUE;
		if (email_box == INBOX)
			control_ptr->bounds.xcoord = EEDIT_XCOORD1;
		else if (email_box == OUTBOX)
		{
			if (edit_entry_status.status == VIEW)
				control_ptr->bounds.xcoord = EEDIT_XCOORD2;
            else 
                control_ptr->control_attr.control_visible = FALSE;                		        
        }                
		else control_ptr->bounds.xcoord = EEDIT_XCOORD3;
	}
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_SEND */
	FormGetObjectPointer(BUTTON_EDIT_SEND, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == TRUE ||
		(edit_entry_status.new_record == FALSE && email_box == DRAFT))
		control_ptr->control_attr.control_visible = TRUE;
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_SAVE */
	FormGetObjectPointer(BUTTON_EDIT_SAVE, &object_type, (void**)&control_ptr);
	if ((edit_entry_status.new_record == TRUE || email_box == DRAFT) && email_box != OUTBOX)
		control_ptr->control_attr.control_visible = TRUE;
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_DEL */
	FormGetObjectPointer(BUTTON_EDIT_DEL, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == FALSE)
	{
		control_ptr->control_attr.control_visible = TRUE;
		if (email_box == INBOX)
			control_ptr->bounds.xcoord = EEDIT_XCOORD4;
		else if (email_box == OUTBOX)
		{
			if (edit_entry_status.status == VIEW)
				control_ptr->bounds.xcoord = EEDIT_XCOORD5;
            else 
				control_ptr->bounds.xcoord = EEDIT_XCOORD6;
        }    			
		else if (email_box == SENT)
			control_ptr->bounds.xcoord = EEDIT_XCOORD7;
		else if (email_box == DRAFT)
			control_ptr->bounds.xcoord = EEDIT_XCOORD8;
	}
	else control_ptr->control_attr.control_visible = FALSE;
	
	/* initialise BUTTON_EDIT_RESEND */
	FormGetObjectPointer(BUTTON_EDIT_RESEND, &object_type, (void**)&control_ptr);
	if (edit_entry_status.new_record == FALSE && email_box == SENT)
		control_ptr->control_attr.control_visible = TRUE;
	else control_ptr->control_attr.control_visible = FALSE;
	
	/*Setup Table*/
	FormGetObjectPointer(TABLE_EDIT, &object_type, (void**)&table_ptr);
	FormGetObjectPointer(SCROLLBAR_EDIT, &object_type, (void**)&scroll_ptr);
	if (KeyboardCheckKeyboardStatus())
	{
		scroll_ptr->bounds.height = 80;
		table_ptr->bounds.height = 80;
	}
	else
	{
		scroll_ptr->bounds.height = 124;
		table_ptr->bounds.height = 124;
	}
	
	if (edit_entry_status.status == VIEW)
	{
		table_ptr->table_attr.table_enable = FALSE;
		table_ptr->table_item_ptr[0]->table_item_ui_id = STRING_EDIT_0;
	}
	else
	{	
		table_ptr->table_attr.table_enable = TRUE;
		table_ptr->table_item_ptr[0]->table_item_ui_id = BITMAP_EDIT_TO;
	}
	if (email_box == INBOX)
		table_ptr->table_num_row = 5;
	else table_ptr->table_num_row = 3;
	
	/*Setup the STRING collection */
	if (email_box == INBOX)
	{
		StringSetText(STRING_EDIT_1, EMFROM1);
		StringSetText(STRING_EDIT_2, EMSUBJ1);
		StringSetText(STRING_EDIT_3, EMDATE1);
		StringSetText(STRING_EDIT_4, EMBODY1);
	}
	else
	{
		StringSetText(STRING_EDIT_1, EMSUBJ1);
		StringSetText(STRING_EDIT_2, EMBODY1);
	}
	
    /* initialisation of Field's num of characters */
    FieldSetMaxNumChars(FIELD_EDIT_0, 5000);
	if (email_box == INBOX)
	{
        FieldSetMaxNumChars(FIELD_EDIT_1, 100);
        FieldSetMaxNumChars(FIELD_EDIT_2, 2048);
        FieldSetMaxNumChars(FIELD_EDIT_3, 100);
        FieldSetMaxNumChars(FIELD_EDIT_4, 32768);
	}
	else
	{
        FieldSetMaxNumChars(FIELD_EDIT_1, 2048);
        FieldSetMaxNumChars(FIELD_EDIT_2, 32768);
	}
	
	
	/*initialisation of Field's backline */
	for (count_id = FIELD_EDIT_0; count_id <= FIELD_EDIT_3; count_id++)
		//    for (count_id = FIELD_EDIT_1; count_id <= FIELD_EDIT_3; count_id++)
	{
		FormGetObjectPointer(count_id, &object_type, (void**)&field_ptr);
        if (edit_entry_status.status == EDIT)
			field_ptr->field_back_line = GREY_LINE;
		else field_ptr->field_back_line = NO_LINE;
	}
	
	// ============================================================
	// modified at 01072000
	if (edit_table_font_size == MEDIUM_FONT)
	{
		MenuDeleteItem(MENU_POPUP1, 4);
		MenuInsertItem(MENU_POPUP1, 4, EMSFONT);
	}
	// ============================================================
    return TRUE;
}

/********************************************************
* Function:	EmailKeyInChangeEditTable
* Purpose: 	This function is called when the content in table changed,
then both table
* Scope:		application
* Input:		table_id			The ID value of table object to be scrolled
*				scroll_id			The ID value of scrollbar object
*				field_id			The ID value of active field
*				active_field		whether there is active field or not
* Output:		None
* Return:		TRUE		The table layout is changed
FALSE		The table layout is not changed
* Comment: 	None
*********************************************************/
BOOLEAN EmailKeyInChangeEditTable(ObjectID form_id, ObjectID table_id, ObjectID scrollbar_id)
{
	ObjectID first_field_id;	/*the field object id in the first row of the table */
	ObjectID active_id;			/*The ID value of the field object in the table */
	WORD count = 0;				/* another temperatory variable */
	BYTE object_type;
	Table *table_ptr;
	Field *field_ptr, *field_ptr1;
	USHORT table_num_rows;
	WORD table_max_num_lines;
	BYTE font_id;
	SHORT line_height;			/* line_height = SysGetFontHeight(font_id) + SPACE_LINE;*/
	BOOLEAN insert_pt_on = FALSE;
	SHORT acc_height = 0;
	BOOLEAN return_boolean = FALSE;
	WORD field_total_num_lines, num_lines_displayed, acc_num_lines = 0, num_lines, table_total_num_lines, row_num;
	
	/*The bounds of the table should be set outside this function according
	to the keyboard status */
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	first_field_id = (table_ptr->table_item_ptr[1])->table_item_ui_id;
	table_num_rows = table_ptr->table_num_row;
	
	FieldGetFont(first_field_id, &font_id);
	EmailGetTableMaxNumLines(table_id, font_id, &table_max_num_lines);
	EmailGetTableNumLines(table_id, 1, &table_total_num_lines);
	line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	FormGetActiveObject(form_id, &active_id);
	if (active_id < first_field_id || active_id > (table_num_rows - 1 + first_field_id))
		active_id = (ObjectID)(table_ptr->table_top_row_num + first_field_id);
	else
	{
		FormGetObjectPointer(active_id, &object_type, (void**)&field_ptr);		
		insert_pt_on = field_ptr->field_attr.field_insert_pt_visible;
	}
	
	FieldGetTotalNumOfLines(active_id, &field_total_num_lines);
	FieldGetNumOfLinesDisplayed(active_id, &num_lines_displayed);
	FormGetObjectPointer(active_id, &object_type, (void**)&field_ptr);
	if (table_total_num_lines <= table_max_num_lines && table_ptr->table_top_row_num > 0)
	{
		return_boolean = TRUE;
		table_ptr->table_top_row_num = 0;
		for (row_num = 0;row_num < table_ptr->table_num_row; row_num++)
		{
			FormGetObjectPointer((ObjectID)(first_field_id +  row_num), &object_type, (void**)&field_ptr1);
			field_ptr1->bounds.height = field_ptr1->field_total_num_lines * line_height;
			field_ptr1->field_top_line_num = 0;
			table_ptr->table_row_height[row_num] = field_ptr1->bounds.height;
			if ((ObjectID)(first_field_id + row_num) == active_id && insert_pt_on)
				FieldSetInsertPointPositionByCharPos((ObjectID)(first_field_id + row_num), field_ptr1->field_insert_pt_char_pos);							
		}
	}
	else if (field_total_num_lines >= table_max_num_lines &&
		field_ptr->bounds.height != table_max_num_lines * line_height)
	{
		field_ptr->bounds.height = table_max_num_lines * line_height;
		table_ptr->table_row_height[(USHORT)(active_id - first_field_id)] = field_ptr->bounds.height;
		if (field_total_num_lines <= field_ptr->bounds.height/line_height)
			field_ptr->field_top_line_num = 0;
		else 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);
		
		return_boolean = TRUE;
	}
	else if (field_total_num_lines < (field_ptr->screen_bounds.height/line_height))
	{
		field_ptr->bounds.height = field_total_num_lines * line_height;
		TableUpdateObjectScreenBounds(table_id, active_id);
		if (field_total_num_lines <= field_ptr->bounds.height/line_height)
			field_ptr->field_top_line_num = 0;
		else 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));
		table_ptr->table_row_height[(USHORT)(active_id - first_field_id)] = field_ptr->bounds.height;
		return_boolean = TRUE;
	}			
	else if (num_lines_displayed < field_total_num_lines && 
		field_total_num_lines <= table_max_num_lines)
	{
		field_ptr->bounds.height = field_total_num_lines * line_height;
		TableUpdateObjectScreenBounds(table_id, active_id);
		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;
		else 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));
		table_ptr->table_row_height[(USHORT)(active_id - first_field_id)] = field_ptr->bounds.height;
		return_boolean = TRUE;
	}
	if (EmailDecideTopRowNum(table_id, active_id) == TRUE) return_boolean = TRUE;
	if (insert_pt_on)
	{
		TableUpdateObjectScreenBounds(table_id, active_id);		
		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 = table_ptr->table_top_row_num; count < table_ptr->table_num_row; count++)
	{
		FieldGetTotalNumOfLines((ObjectID)(table_ptr->table_item_ptr[count * table_ptr->table_num_column + 1]->table_item_ui_id), &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;
			FormGetObjectPointer((ObjectID)(table_ptr->table_item_ptr[count * table_ptr->table_num_column + 1]->table_item_ui_id), &object_type, (void**)&field_ptr);
			if (field_ptr->bounds.height != (table_max_num_lines - acc_num_lines) * line_height)
			{	
				field_ptr->bounds.height = (table_max_num_lines - acc_num_lines) * line_height;
				table_ptr->table_row_height[count] = field_ptr->bounds.height;
				return_boolean = TRUE;
			}
			break;
		}
	}
	
	EmailEditTableSetScrollbar(table_id, scrollbar_id);
	if (return_boolean == TRUE)
		return TRUE;
	else return FALSE;
}


/********************************************************
* Function:	EmailEditTableSetScrollbar
* Purpose: 	This function is to set the scrollbar beside the table
* Scope:		application
* Input:		table_id			The ID value of table object to be scrolled
*				scroll_id			The ID value of scrollbar object
* Output:		None
* Return:		TRUE		The table layout is changed
FALSE		The table layout is not changed
* Comment: 	None
*********************************************************/
BOOLEAN EmailEditTableSetScrollbar(ObjectID table_id, ObjectID scrollbar_id)
{
	ObjectID first_field_id;
	BYTE object_type;
	Table *table_ptr;
	Scrollbar *scroll_ptr;
	Field *field_ptr;
	BYTE font_id;
	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(table_id, &object_type, (void**)&table_ptr);
	FormGetObjectPointer(scrollbar_id, &object_type, (void**)&scroll_ptr);
	first_field_id = (table_ptr->table_item_ptr[1])->table_item_ui_id;
	
	FieldGetFont(first_field_id, &font_id);
	EmailGetTableMaxNumLines(table_id, font_id, &table_max_num_lines);
	EmailGetTableNumLines(table_id, 1, &table_total_num_lines);
	line_height = SysGetFontHeight(font_id) + 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 (draw_scrollbar)
            ScrollbarEraseScrollbar(scrollbar_id);
		return TRUE;
	}
	
	ScrollbarGetScrollbar(scrollbar_id, &value, &max_value, &min_value, &pagesize, &scrollbar_total_num_lines);
	for (count = 0; count < table_ptr->table_top_row_num; count++)
	{
		FieldGetTotalNumOfLines((count + first_field_id), &field_total_num_lines);
		acc_num_lines += field_total_num_lines;
	}
	FieldGetTopLineNum((ObjectID)(table_ptr->table_top_row_num + first_field_id), &top_line_num);
	for (count = table_ptr->table_top_row_num; count < table_ptr->table_num_row; count++)
	{
		FormGetObjectPointer((ObjectID)(count + first_field_id), &object_type, (void**)&field_ptr);
		acc_num_lines2 += field_ptr->bounds.height/line_height; 
		if (acc_num_lines2 > table_max_num_lines)
		{
			table_ptr->table_num_row_display = count - table_ptr->table_top_row_num;
			set = TRUE;
			break;
		}
	}
	if (set == FALSE)
		table_ptr->table_num_row_display = table_ptr->table_num_row - table_ptr->table_top_row_num; 
	acc_num_lines += top_line_num;
	for (count = table_ptr->table_top_row_num; count < (table_ptr->table_top_row_num + table_ptr->table_num_row_display);count++)
	{
		FormGetObjectPointer((ObjectID)(count + first_field_id), &object_type, (void**)&field_ptr);		
		acc_num_lines1 += (field_ptr->bounds.height/line_height);
	}
	
	ScrollbarSetScrollbar(scrollbar_id, acc_num_lines, EmailGetScrollbarMaxValue(table_id, 1), 0, acc_num_lines1, table_total_num_lines);
	scroll_ptr->scrollbar_draw_pagesize = table_max_num_lines;
    if (draw_scrollbar)
        ScrollbarDrawScrollbar(scrollbar_id);
	return TRUE;
}

/********************************************************
* Function:	EmailScrollbarSetEditTable
* 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:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN EmailScrollbarSetEditTable(ObjectID table_id, ObjectID scrollbar_id, EvtType *Event)
{
	Table       *table_ptr;
	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, *ptr;
	ObjectID    first_field_id;
	Scrollbar   *scroll_ptr;
	BYTE        font_id;
	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;
    BOOLEAN     table_change = FALSE, field_change = FALSE;
    ObjectID    field_change_id, last_field_id;
    USHORT      cell_number;
	
	FormGetObjectPointer(table_id, &object_type, (void**)&table_ptr);
	FormGetObjectPointer(scrollbar_id, &object_type, (void**)&scroll_ptr);
	first_field_id = (table_ptr->table_item_ptr[1])->table_item_ui_id;
	
	FieldGetFont(first_field_id, &font_id);
	EmailGetTableMaxNumLines(table_id, font_id, &table_max_num_lines);
	EmailGetTableNumLines(table_id, 1, &table_total_num_lines);
	line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	
#ifdef DEBUG_SCROLL
    printf("\n MAX = %ld VALUE = %ld", scroll_ptr->scrollbar_max , scroll_ptr->scrollbar_value);
    printf("\n top_row_num = %ld", table_ptr->table_top_row_num);
    printf("\n top_num_row = %ld", table_ptr->table_num_row);
    printf("\n top_num_row_display = %ld", table_ptr->table_num_row_display);
#endif
	
	
    if (scroll_ptr->scrollbar_max == scroll_ptr->scrollbar_value)
    {
		if ((table_ptr->table_top_row_num <= (table_ptr->table_num_row - 1)) &&
			((table_ptr->table_top_row_num + table_ptr->table_num_row_display) >= (table_ptr->table_num_row)))
		{
			cell_number = ((table_ptr->table_top_row_num + table_ptr->table_num_row_display - 1) * table_ptr->table_num_column) + 1;
			last_field_id = ((TableItems*)(table_ptr->table_item_ptr[cell_number]))->table_item_ui_id;
			FormGetObjectPointer(last_field_id, &object_type, (void**)&ptr);
			if (ptr->field_top_line_num == (ptr->field_total_num_lines - ptr->field_num_lines_displayed))
				return TRUE;
		}
    }       
	
	
	row_num_lines = (WORD*)qmalloc(table_ptr->table_num_row*sizeof(WORD));
	for (count = 0; count < (table_ptr->table_num_row); count++)
	{
		FieldGetTotalNumOfLines((ObjectID)(count + first_field_id), &temp);
		row_num_lines[count] = temp;
	}
	
	for (count = 0; count < (table_ptr->table_num_row); 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;
		}
	}
	
	/* find out the table's largest top_row_number */
	for (count = table_ptr->table_num_row - 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(scrollbar_id, &value, &max_value, &min_value, &pagesize, &scrollbar_total_num_lines);
	if (table_ptr->table_top_row_num != table_current_row)
	{	
		table_ptr->table_top_row_num = table_current_row;
		table_change = TRUE;
	}
	
	if (table_ptr->table_top_row_num > table_largest_top_row_num)
	{
		table_ptr->table_top_row_num = table_largest_top_row_num;
		table_change = TRUE;
	}
	
	FormGetObjectPointer((first_field_id + table_ptr->table_top_row_num), &object_type, (void**)&field_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 (table_ptr->table_top_row_num != table_ptr->table_num_row - 1)
			{
				table_ptr->table_top_row_num++;
				(WORD)(Event->para2) += (field_ptr->field_total_num_lines - field_current_line_num);
				table_change = TRUE;
			}
			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 (table_change == FALSE)
        {
            field_change = TRUE;
            field_change_id = field_ptr->identification.ui_object_id;
            StrAnalyzeLine(field_ptr);
        }
	}
	
	acc_num_lines = 0;
	for (count = table_ptr->table_top_row_num; count < table_ptr->table_num_row; count++)
	{
		FieldGetTotalNumOfLines((ObjectID)(table_ptr->table_item_ptr[count * table_ptr->table_num_column + 1]->table_item_ui_id), &num_lines);
		acc_num_lines += num_lines;
		FormGetObjectPointer((ObjectID)(count +  first_field_id), &object_type, (void**)&field_ptr);
		if (acc_num_lines <= table_max_num_lines)
		{
			if (field_ptr->bounds.height != field_ptr->field_total_num_lines * line_height)
			{	
                if ((field_ptr->bounds.height != (field_ptr->field_total_num_lines * line_height)) ||
                    (table_ptr->table_row_height[count] != (field_ptr->field_total_num_lines * line_height)))
                {
                    field_ptr->bounds.height = field_ptr->field_total_num_lines * line_height;
                    table_ptr->table_row_height[count] = field_ptr->bounds.height;
                    table_change = TRUE;
                }
			}
			if (acc_num_lines == table_max_num_lines) break;
		}
		else if (acc_num_lines > table_max_num_lines)
		{
			acc_num_lines -= num_lines;
			FormGetObjectPointer((ObjectID)(table_ptr->table_item_ptr[count * table_ptr->table_num_column + 1]->table_item_ui_id), &object_type, (void**)&field_ptr);
            if ((field_ptr->bounds.height != ((table_max_num_lines - acc_num_lines) * line_height)) ||
                (table_ptr->table_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;
                table_ptr->table_row_height[count] = field_ptr->bounds.height;
                table_change = TRUE;
            }
			break;
		}
	}
	
	if (table_ptr->table_top_row_num == (table_ptr->table_num_row - 1))
	{
		FormGetObjectPointer((ObjectID)(table_ptr->table_item_ptr[table_ptr->table_top_row_num * table_ptr->table_num_column + 1]->table_item_ui_id), &object_type, (void**)&field_ptr);
        if ((field_ptr->bounds.height != table_max_num_lines * line_height) ||
            (table_ptr->table_row_height[table_ptr->table_top_row_num] != table_max_num_lines * line_height))
        {
            field_ptr->bounds.height = table_max_num_lines * line_height;
            table_ptr->table_row_height[table_ptr->table_top_row_num] = field_ptr->bounds.height;
            table_change = TRUE;
        }
	}
	
	ScrollbarSetScrollbar(scrollbar_id, (WORD)(Event->para2), max_value, 0, pagesize, scrollbar_total_num_lines);
    if (draw_scrollbar)
    {
#ifdef DEBUG
        printf("\n Scrollbar Draw Scrollbar");
#endif
        ScrollbarDrawScrollbar(scrollbar_id);
    }
	acc_num_lines = 0;
	
    TableUpdateNumRowDisplay(table_id, 1);
	
#ifdef DEBUG
    printf("\n A)   top_row_num = %ld", table_ptr->table_top_row_num);
    printf("\n B)   num_row     = %ld", table_ptr->table_num_row);
#endif
	
    for (count = table_ptr->table_top_row_num; count < table_ptr->table_num_row; count++)
		//    for (count = table_ptr->table_top_row_num; count < table_ptr->table_num_row_display; count++)
	{
		FormGetObjectPointer((ObjectID)(count +  first_field_id), &object_type, (void**)&field_ptr);
		acc_num_lines += field_ptr->field_total_num_lines;
		
#ifdef DEBUG
        printf("\n C)   Field_id        = %ld", (count + first_field_id));
        printf("\n D)   field_total     = %ld", field_ptr->field_total_num_lines);
        printf("\n E)   acc_num_lines   = %ld", acc_num_lines);
#endif
		
        if (acc_num_lines <= table_max_num_lines)
		{
#ifdef DEBUG
            printf("\n F)   acc_num_lines <= table_max_num_lines");
#endif
            if (field_ptr->bounds.height != field_ptr->field_total_num_lines * line_height)
			{
#ifdef DEBUG
                printf("\n G)");
#endif
				field_ptr->bounds.height = field_ptr->field_total_num_lines * line_height;
				table_ptr->table_row_height[count] = field_ptr->bounds.height;
				table_change = TRUE;
			}
			if (acc_num_lines == table_max_num_lines) break;
		}
		else
		{
#ifdef DEBUG
            printf("\n H)");
#endif
			
            if (count == table_ptr->table_top_row_num)
            {
                if ((field_ptr->bounds.height != (table_max_num_lines *line_height)) ||
                    (table_ptr->table_row_height[count] != (table_max_num_lines - acc_num_lines)*line_height))
                {
                    field_ptr->bounds.height = table_max_num_lines *line_height;
                    table_ptr->table_row_height[count] = field_ptr->bounds.height;
                    table_change = TRUE;
                }
                break;
            }                              
#ifdef DEBUG
            printf("\n I)");
#endif
			
			acc_num_lines -= field_ptr->field_total_num_lines;
            if (field_ptr->field_top_line_num != 0)
            {
                field_ptr->field_top_line_num = 0;
                field_change = TRUE;
            }
            if ((field_ptr->bounds.height != (table_max_num_lines - acc_num_lines)*line_height) ||
                (table_ptr->table_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;
                table_ptr->table_row_height[count] = field_ptr->bounds.height;
                StrAnalyzeLine(field_ptr);
                table_change = TRUE;
            }
		}
	}
	
	if (table_change == TRUE)
	{
        if (Event->eventType == EVT_SCROLLBAR_SELECT ||
            (Event->eventType == EVT_SCROLLBAR_REPEAT))
        {
            LcdEnableInsertPt(FALSE, 0, 0, SMALL_FONT);            
            TableDrawTable(table_id);
        }            
	}
    else if (field_change)
        FieldDrawField(field_change_id);
	
	qfree(row_num_lines);
	return TRUE;
}

/********************************************************
* Function:	EmailMessageResend
* Purpose: 	Thsi function is called to resend the opened message				
* Scope:		application
* Input:		original_rec_id			The Record ID of the recorded message
Output:		None
* Return:		TRUE		Success
FALSE		NotHandled
* Comment: 	The resend message will be COPIED to the draft and the original
copy will be left in the original email box
*********************************************************/
BOOLEAN EmailMessageResend(RecordID *top_rec_id)
{
	BYTE *buffer;
	RecordID rec_id;
	UWORD time_index;
	UWORD byte_read;
	
    DataNewRecord(emess_dbid, OUTBOX, 8, &rec_id);
	DataWriteField(emess_dbid, rec_id, DATE, 1, (BYTE*)(""));
	
	DataGetField(emess_dbid, TIME_INDEX_RECID, (OUTBOX - 1), &buffer, &byte_read);
	time_index = EL32((*(UWORD*)buffer));
	qfree(buffer);
	DataWriteField(emess_dbid, rec_id, TIME_INDEX, 4, (BYTE*)&(time_index));
	time_index ++;
	time_index = EL32(time_index);
	DataWriteField(emess_dbid, TIME_INDEX_RECID, (OUTBOX - 1), 4, (BYTE*)&time_index);
	
	DataWriteField(emess_dbid, rec_id, FROM, 1, (BYTE*)(""));	
	FieldGetTextPointer(FIELD_MAIL_LIST_TO, &buffer);
	DataWriteField(emess_dbid, rec_id, TO, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_MAIL_LIST_CC, &buffer);
	DataWriteField(emess_dbid, rec_id, CC, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_MAIL_LIST_BCC, &buffer);
	DataWriteField(emess_dbid, rec_id, BCC, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_EDIT_1, &buffer);
	DataWriteField(emess_dbid, rec_id, SUBJECT, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_EDIT_2, &buffer);
	DataWriteField(emess_dbid, rec_id, BODY, (strlen(buffer) + 1), buffer);
	DataCloseRecord(emess_dbid, rec_id);
	*top_rec_id = rec_id;
	return TRUE;
}

/********************************************************
* Function:	EmailMessageSave
* Purpose: 	This function is called in order to save message
to DRAFT or draft
* Scope:		application
* Input:		None
Output:		None
* Return:		None
* Comment: 	the function will check the edit_entry_status to 
know where the save message should put into
*********************************************************/
BOOLEAN EmailMessageSave(UBYTE *email_box, RecordID *top_rec_id)
{
	BYTE *buffer;
	RecordID rec_id;
	UWORD rec_num;
	UWORD byte_read, time_index;
	
	if (edit_entry_status.new_record == TRUE || rf_action != 0)
	{
        DataNewRecord(emess_dbid, DRAFT, 8, &rec_id);
		*email_box = DRAFT;
	}
	else
	{
		DataRecIDtoNum(emess_dbid, edit_entry_status.rec_id, &rec_num);
		DataOpenRecord(emess_dbid, rec_num, &rec_id, NULL);
		DataRecordInfo(emess_dbid, rec_id, NULL, email_box, NULL, NULL, NULL);
	}
	DataWriteField(emess_dbid, rec_id, DATE, 1, (BYTE*)(""));
	if (*email_box == DRAFT && edit_entry_status.new_record == TRUE)
	{
		DataGetField(emess_dbid, TIME_INDEX_RECID, (DRAFT - 1), &buffer, &byte_read);
		time_index = EL32((*(UWORD*)buffer));
		qfree(buffer);
		DataWriteField(emess_dbid, rec_id, TIME_INDEX, 4, (BYTE*)&(time_index));
		time_index ++;
		time_index = EL32(time_index);
		DataWriteField(emess_dbid, TIME_INDEX_RECID, (DRAFT - 1), 4, (BYTE*)&time_index);
	}
	DataWriteField(emess_dbid, rec_id, FROM, 1, (BYTE*)(""));	
	FieldGetTextPointer(FIELD_MAIL_LIST_TO, &buffer);
	DataWriteField(emess_dbid, rec_id, TO, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_MAIL_LIST_CC, &buffer);
	DataWriteField(emess_dbid, rec_id, CC, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_MAIL_LIST_BCC, &buffer);
	DataWriteField(emess_dbid, rec_id, BCC, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_EDIT_1, &buffer);
	DataWriteField(emess_dbid, rec_id, SUBJECT, (strlen(buffer) + 1), buffer);
	FieldGetTextPointer(FIELD_EDIT_2, &buffer);
	DataWriteField(emess_dbid, rec_id, BODY, (strlen(buffer) + 1), buffer);
	DataCloseRecord(emess_dbid, rec_id);
	*top_rec_id = rec_id;
	return TRUE;
}

/********************************************************
* Function:	EmailMessageCheckTOFieldEmpty
* Purpose: 	This function is called to check whether the TO field is empty or not
* Scope:		application
* Input:		None
Output:		None
* Return:		TRUE		FOUND
FALSE		NO EMAIL ADDR
* Comment: 	None
*********************************************************/
BOOLEAN EmailMessageCheckTOFieldEmpty()
{
	BYTE *buffer;
	
	if (FieldGetTextPointer(FIELD_MAIL_LIST_TO, &buffer) != TRUE)
		return TRUE;
	if (strlen(buffer))
		return FALSE;
    else return TRUE;
}







