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



#include "stdafx.h"
#include "MemoFunc.h"
#include "SySetup.h"
//#define       DEBUG
//#define DEBUG_H

extern BYTE	old_cate[];

/*****************************************************************
********************** Global Variables **************************
*****************************************************************/
/********************************************************
* Function:	AnnSetTableTopRowNum
* Purpose: 	This function is called to set the top row number
*			of the table object
* Scope:	application
* Input:	BYTE				the starting_char
* Output:	None
* Return:	TRUE			display of table is on
*			FALSE			display of table is off
* Comment: 	The top row number of the table objects are set
*********************************************************/
BOOLEAN MemoSetTableTopRowNum(UWORD top_record)
{
	USHORT	total_num_rows;
	BOOLEAN	enable,drawn, active,visible, set_scroll;
	
	
	total_num_rows = memo_list.total_num_rows;
	memo_list.top_row_num = (USHORT)top_record;
	MemoTableDisplayDraw(&memo_list);
	TableGetAttributes(TABLE_MEMO_LIST, &enable, &drawn, &active, &visible, &set_scroll);
	TableSetAttributes(TABLE_MEMO_LIST, enable, drawn, active, TRUE, set_scroll);
	MemoSetScrollbar();
	return TRUE;
}

/********************************************************
* Function:	ToDoListSetScrollbar
* Purpose: 	This function is called in order to set the values for a scrollbar		
* Scope:	application
* Input:	BYTE				the starting_char
* Output:	None
* Return:	TRUE		scrollbar is erased
*			FALSE		scrollbar is drawn
* Comment: 	If a scrollbar is not required, then the scrollbar will be erased 
*			If a scrollbar is required, the scrollbar will be displayed accordingly 
*********************************************************/
BOOLEAN MemoSetScrollbar()
{
	Scrollbar *scroll_ptr;
	BYTE object_type;
	USHORT max_num_rows_display;
	USHORT top_row_num;
	WORD max_value, min_value, pagesize, total_num_rows;
	
	
	
	max_num_rows_display = memo_list.num_rows_displayed;
	total_num_rows = memo_list.total_num_rows;
	top_row_num = memo_list.top_row_num;
	pagesize = max_num_rows_display;
	min_value = 0;
	max_value = total_num_rows - pagesize;	
	
	if (total_num_rows > max_num_rows_display)
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,TRUE);
	else
	{
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,FALSE);
		ScrollbarEraseScrollbar(SCROLLBAR_MEMO_LIST);
		return FALSE;
	}
	
	if (top_row_num > (total_num_rows - max_num_rows_display))
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, max_value, max_value, min_value,
		pagesize, total_num_rows);
	else
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, top_row_num, max_value, min_value,
		pagesize, total_num_rows);
	
	FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_ptr);
	scroll_ptr->scrollbar_draw_pagesize = pagesize;
	
	ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);
	return TRUE;
}

/********************************************************
* Function:	AnnGetClickedCell
* Purpose:	To get the row, column & cell number of the
*			particular position
* Scope:	Application
* Input:	table_id			DBID of table object
*			x_coord				pen x-coordinate
*			y_coord				pen y-coordinate
* Output:	row_number			the row number
*			col_number			the column number
*			cell_number			the cell number
* Output:	None
* Return:	TRUE if no error
*			ErrUIResNotFound
* Comment:    None
*********************************************************/
Err MemoGetClickedCell(ObjectID table_id,SHORT x_coord,SHORT y_coord,USHORT *row_number,
					   USHORT *col_number,USHORT *cell_number)
{
	Table	*addr;
	BYTE	object_type;
	USHORT	i,j,temp_height = 0,top_row,count=0,draw_height=0;
	ObjectBounds temp;
	
	if (UISearchForAddress(table_id,&object_type,(void **)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (addr->table_attr.table_drawn == FALSE) return FALSE;
	if (addr->table_attr.table_enable == FALSE) return FALSE;
	
	count = (addr->table_top_row_num*addr->table_num_column);
	
	for (i=0; i< (addr->table_num_row-addr->table_top_row_num); i++)
		draw_height += addr->table_row_height[i+addr->table_top_row_num];
	/* If table fully display on screen */
	if (draw_height < addr->bounds.height)
	{
		if (x_coord >= addr->bounds.xcoord && x_coord < addr->bounds.xcoord+addr->bounds.width &&
			y_coord >= addr->bounds.ycoord && y_coord < addr->bounds.ycoord+addr->bounds.height)
		{
			temp.xcoord = addr->bounds.xcoord;
			temp.ycoord = addr->bounds.ycoord;
			
			for (i=addr->table_top_row_num; i< addr->table_num_row; i++)
			{
				for (j=0; j< addr->table_num_column; j++)
				{
					if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j] &&
						y_coord >= temp.ycoord && y_coord <= temp.ycoord+addr->table_row_height[i])
					{
						*row_number = i;
						*col_number = j;
						*cell_number = count;
						return TRUE;
					}
					temp.xcoord = temp.xcoord+addr->table_column_width[j];
					count++;
				}
				temp.xcoord = addr->bounds.xcoord;
				temp.ycoord = temp.ycoord+addr->table_row_height[i];
			}
		}
		else
			return ERR_UI_INV_INPUT_COORD;
	}
	/* The table cannot fully display on screen */
	else
	{
		/* Get the top row of the display table */
		top_row = addr->table_top_row_num;
		
		for (i=0; i< addr->table_num_row_display; i++)
			temp_height = temp_height+addr->table_row_height[i+top_row];
		/* Pen within the display region */
		if (x_coord >= addr->bounds.xcoord && x_coord < addr->bounds.xcoord+addr->bounds.width &&
			y_coord >= addr->bounds.ycoord && y_coord < addr->bounds.ycoord+temp_height)
		{
			temp.xcoord = addr->bounds.xcoord;
			temp.ycoord = addr->bounds.ycoord;
			
			for (i=addr->table_top_row_num; i< addr->table_num_row; i++)
			{
				for (j=0; j< addr->table_num_column; j++)
				{
					if (x_coord >= temp.xcoord && x_coord <= temp.xcoord+addr->table_column_width[j] &&
						y_coord >= temp.ycoord && y_coord <= temp.ycoord+addr->table_row_height[i])
					{
						*row_number = i;
						*col_number = j;
						*cell_number = count;
						return TRUE;
					}
					count++;
					temp.xcoord = temp.xcoord+addr->table_column_width[j];
				}
				temp.xcoord = addr->bounds.xcoord;
				temp.ycoord = temp.ycoord+addr->table_row_height[i];
			}
		}
		else
			return ERR_UI_INV_INPUT_COORD;
	}
	return FALSE;
}

/******************************************************************
* Function:	AnnScrollbarSetTable
* Purpose: 	This function is called to set the To Do List
*			when the scrollbar is moved.
* Scope:	application
* Input:	Event		
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoScrollbarSetTable(EvtType *Event)
{
	WORD		max,min,value,pagesize;
	WORD		scroll_total_lines;
	BYTE		object_type;
	Scrollbar*	scroll_ptr;
	
	ScrollbarGetScrollbar(SCROLLBAR_MEMO_LIST, &value, &max, &min, &pagesize, &scroll_total_lines);
	
	if ((Event->para2 - Event->para1) >= pagesize)
	{
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, (Event->para2 - 1), max, min, pagesize, scroll_total_lines);
		memo_list.top_row_num = (USHORT)(Event->para2) - 1;
	}
	else if ((Event->para1 - Event->para2) >= pagesize)
	{
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, (Event->para2 + 1), max, min, pagesize, scroll_total_lines);
		memo_list.top_row_num = (USHORT)(Event->para2) + 1;
	}
	else
	{	
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, Event->para2, max, min, pagesize, scroll_total_lines);
		memo_list.top_row_num = (USHORT)(Event->para2);
	}	
	
	if (Event->para2 != Event->para1)
	{
		MemoTableDisplayDraw(&memo_list);
		TableDrawTable(TABLE_MEMO_LIST);
	}
	
    FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_ptr);
    scroll_ptr->scrollbar_draw_pagesize = pagesize;
    ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);
}

/********************************************************
* Function:	AnnDisplayGetRecordID
* Purpose: 	This function is called in order to get the record ID 
*			of a particular table item in the Table object
* Scope:	application
* Input:	table_display	table-display structure
*			item_num		item number
* Output:	rec_id			Pointer to record ID of the list object
* Return:	TRUE    handled
*			FALSE   not-handled
* Comment: 	None
*********************************************************/
BOOLEAN MemoDisplayGetRecordID(TableDisplay *table_display, USHORT row_num, RecordID *rec_id, DatabaseID *dbid)
{
	RecordIDBlock *temp = table_display->record_id_block;
	USHORT count = 0;
	
	if (row_num >= table_display->total_num_rows) return FALSE;
	if (table_display->record_id_block == NULL) return FALSE;
	
	while (temp != NULL)
	{
		if ((row_num >= count) && (row_num < (count + 20)))
		{
			*rec_id = temp->record_id[row_num - count];
			*dbid = temp->dbid[row_num - count];
			return TRUE;
		}
		else
		{
			count += 20;
			temp = temp->next;
		}
	}
	return FALSE;
}

/********************************************************
* Function:	AnnSetUpFieldScreen
* Purpose: 	This function is called in order to set the layout of the 
*			To Do New screen
* Scope:	application
* Input:	None
* Output:	None
* Return:	TRUE		Success
*			FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN MemoSetUpFieldScreen(ObjectID form_id)
{
	BYTE		object_type;
	Field		*field_ptr;
	Scrollbar	*scroll_ptr;
	
	if (form_id == FORM_MEMO_NEW || form_id == FORM_MEMO_VIEWING)
	{
		if (form_id == FORM_MEMO_NEW)
			FormGetObjectPointer(FIELD_MEMO_NEW, &object_type, (void**)&field_ptr);
		else
			FormGetObjectPointer(FIELD_MEMO_VIEWING, &object_type, (void**)&field_ptr);
		
		FormGetObjectPointer(SCROLLBAR_MEMO_VIEWING, &object_type, (void**)&scroll_ptr);
		
		if (KeyboardCheckKeyboardStatus())
		{
			field_ptr->bounds.height = FIELD_HEIGHT_KEYBOARD_ON;
#ifdef DEBUG
			printf("\n Keyboard status = TRUE");
			printf("\n field height = %ld", field_ptr->bounds.height);
#endif
			
			scroll_ptr->bounds.height = SCROLLBAR_HEIGHT_KEYBOARD_ON;
		}
		else
		{
			field_ptr->bounds.height = FIELD_HEIGHT_KEYBOARD_OFF;
#ifdef DEBUG
			printf("\n Keyboard status = FALSE");
			printf("\n field height = %ld", field_ptr->bounds.height);
#endif
			
			scroll_ptr->bounds.height = SCROLLBAR_HEIGHT_KEYBOARD_OFF;
		}
		return TRUE;
	}		
	return FALSE;	
}

/********************************************************
* Function:	AnnFieldSetScrollbar
* Purpose: 	This function is called in order to set the 
*			values for a scrollbar		
* Scope:	application
* Input:	None
* Output:	None
* Return:	TRUE				scrollbar is erased
*			FALSE				scrollbar is drawn
* Comment: 	If a scrollbar is not required, then the scrollbar will be erased 
*			If a scrollbar is required, the scrollbar will be displayed accordingly 
*********************************************************/
BOOLEAN MemoFieldSetScrollbar(ObjectID field_id, ObjectID scrollbar_id)
{
	Field		*field_ptr;
	Scrollbar	*scroll_ptr;
	BYTE		font_id;
	BYTE		object_type;
	WORD		max_num_lines;
	WORD		max_value, min_value, pagesize;
	
	
	FormGetObjectPointer(field_id, &object_type, (void**)&field_ptr);
	
	FieldGetFont(field_id, &font_id);
    max_num_lines = field_ptr->bounds.height/(SysGetFontHeight(font_id) + SPACE_LINE);
	
	pagesize = max_num_lines  - 1;
	min_value = 0;	
	max_value = field_ptr->field_total_num_lines - pagesize - 1;	
	
	if (field_ptr->field_total_num_lines > max_num_lines)
		ScrollbarSetScrollbarVisible(scrollbar_id, TRUE);
	else
	{
		ScrollbarSetScrollbarVisible(scrollbar_id, FALSE);
		ScrollbarEraseScrollbar(scrollbar_id);
		return FALSE;
	}
	
	FormGetObjectPointer(scrollbar_id, &object_type, (void**)&scroll_ptr);
	scroll_ptr->scrollbar_draw_pagesize = max_num_lines;
	
	if (field_ptr->field_top_line_num > (field_ptr->field_total_num_lines - max_num_lines))
		ScrollbarSetScrollbar(scrollbar_id, max_value, max_value, min_value, pagesize, field_ptr->field_total_num_lines);
	else
		ScrollbarSetScrollbar(scrollbar_id, field_ptr->field_top_line_num, max_value, min_value, pagesize, field_ptr->field_total_num_lines);
	
	ScrollbarDrawScrollbar(scrollbar_id);
	return TRUE;
}

/******************************************************************
* Function:	AnnViewingSetUpScreen
* Purpose: 	
* Scope:	application/internal
* Input:	Event		received event
* Output:	None
* Return:	TRUE if handled
*			FALSE if not handled
* Comment: 	None
*******************************************************************/
void MemoViewingSetUpScreen()
{
	Bitmap	*bmp_addr;
	UBYTE	cate_num;
	BYTE	object_type, *cate_name;
	String	*string_addr;
	
	/* Set up category label */
	MemoCateNameToPopupTrigger(memo_dbid);
	ControlPopupDeleteItem(POPUP_TRIGGER_CATEGORY, 0);
	
	DataRecordInfo(memo_dbid, app_status.rec_id, NULL, &cate_num, NULL, NULL, NULL);
	cate_name = (BYTE*)qmalloc(30*sizeof(BYTE));
	DataCategoryName(memo_dbid, cate_num, cate_name);
	ControlSetLabel(POPUP_TRIGGER_CATEGORY, cate_name);
	strcpy(current_cate, cate_name);
	qfree(cate_name);
	/* Set up Field contents */
	FieldSetText(FIELD_MEMO_VIEWING, memo_field_buffer[0]);
	/* Set up Sketch status */
	FormGetObjectPointer(BITMAP_MEMO_SKETCH, &object_type, (void **)&bmp_addr);
	if (app_status.sketch_status == MEMO_SKETCH)
	{
		bmp_addr->bitmap_attr.bitmap_visible = TRUE;
		bmp_addr->bitmap_attr.bitmap_enable = TRUE;
	}
	else
	{
		bmp_addr->bitmap_attr.bitmap_visible = FALSE;
		bmp_addr->bitmap_attr.bitmap_enable = FALSE;
	}
	/* Set up Field Size */
	FieldSetFont(FIELD_MEMO_VIEWING, table_font);
}

/******************************************************************
* Function:	ToDoRecordToVariable
* Purpose: 	
* Scope:	application/internal
* Input:	Event		received event
* Output:	None
* Return:	TRUE if handled
*			FALSE if not handled
* Comment: 	None
*******************************************************************/
void MemoRecordToVariable()
{
	UWORD	rec_num, byte_read;
	BYTE	*buffer;
	Err	result;
	
	result = DataRecIDtoNum(memo_dbid, app_status.rec_id, &rec_num);
	result = DataOpenRecord(memo_dbid, rec_num, &app_status.rec_id, NULL);
	/* Get Field 0 of To Do List Record */
	result = DataGetField(memo_dbid, app_status.rec_id, 0, &buffer, &byte_read);
	app_status.sketch_status = *buffer;
	qfree(buffer);
	/* Get Field 1 of To Do List Record */
	DataGetField(memo_dbid, app_status.rec_id, 1, &buffer, &byte_read);
	
#ifdef DEBUG_H
    printf("\n RecordToVariable = %ld %ld", strlen(buffer), byte_read);
#endif    
	
	
	if (memo_field_buffer[0] != NULL)
		qfree(memo_field_buffer[0]);
	
	memo_field_buffer[0] = (BYTE*)qmalloc((strlen(buffer) + 1)*sizeof(BYTE));
	strcpy(memo_field_buffer[0], buffer);
	qfree(buffer);
	/* Get Field 2 of To Do List Record */
	DataGetField(memo_dbid, app_status.rec_id, 2, &buffer, &byte_read);
	strcpy(app_status.create_time, buffer);
	qfree(buffer);
	
	app_status.field_change = FALSE;		
	DataCloseRecord(memo_dbid,app_status.rec_id);
}

/********************************************************
* Function:	AnnEditSetField
* Purpose: 	This function is called in order to set up 
*			the field in the To DO New screen when the 
*			data is first put to Field or the keyboard 
*			is popuped up and down
* Scope:	application
* Input:	form_id		ID value of the form that the field is on
*			field_id	ID value of field object to be scrolled
* Output:	None
* Return:	TRUE		Success
*			FALSE		NotHandled
* Comment: 	None
*********************************************************/
BOOLEAN	MemoEditSetField(ObjectID form_id, ObjectID field_id)
{
	Field	*field_ptr;
	BOOLEAN insert_pt_on = FALSE;
	BOOLEAN highlight_pt_on = FALSE;
	BYTE	object_type, font_id;
	SHORT	line_height, acc_height = 0;
	WORD	first_visible_char, last_visible_char, count = 0;
	WORD	line_num, insert_pos;
	WORD	temp;
	
	
	FormGetObjectPointer(field_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;
	
#ifdef DEBUG
	printf("\n insert_pt_on = %ld", insert_pt_on);
	printf("\n highlight_pt_on = %ld", highlight_pt_on);
#endif
	
	FieldGetFont(field_id, &font_id);
    line_height = SysGetFontHeight(font_id) + SPACE_LINE;
	
	//modified at 13042000
	
	StrAnalyzeLine(field_ptr);
	FieldGetFirstVisibleChar(field_id, &first_visible_char);
	FieldGetLastVisibleChar(field_id, &last_visible_char);
	
	if (insert_pt_on == TRUE || highlight_pt_on == TRUE)
	{
#ifdef	DEBUG
		printf("\n MemoEditSetField 1 First Char %d ",first_visible_char);
		printf("\n MemoEditSetField 1 Last Char %d ",last_visible_char);
		printf("\n MemoEditSetField 1 Total Lines %d ",field_ptr->field_total_num_lines);
		printf("\n MemoEditSetField 1 Insert Pt Char Pos %d ",field_ptr->field_insert_pt_char_pos);
		printf("\n MemoEditSetField 1 Top line num = %ld", field_ptr->field_top_line_num);
#endif
		if (insert_pt_on)
		{
			
			for (count = 0; count < field_ptr->field_total_num_lines; count++)
			{
#ifdef	DEBUG
				printf("\n Field 1-1 Line Info Start %d, Line Info End %d ",field_ptr->field_lineinfo[count].start, field_ptr->field_lineinfo[count].start + field_ptr->field_lineinfo[count].length);
#endif	
				
				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)));
				
				if (field_ptr->field_top_line_num < 0)
					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));
		/* Set up the correct insert pt position when keyboard on */
		FieldGetInsertPointPosition(field_id, &insert_pos);
		FieldGetFirstVisibleChar (field_id, &first_visible_char);
		FieldGetLastVisibleChar (field_id, &last_visible_char);
		
		if (insert_pt_on)
		{
			if(insert_pos > last_visible_char)
			{
				FieldCharPosToLineNum (field_ptr, insert_pos, &line_num);
				FieldSetTopLineNum(field_id, line_num - (field_ptr->bounds.height/(line_height)) + 1);
			}
			FieldSetInsertPointPositionByCharPos(field_id, insert_pos);
		}
		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)
					FieldSetTopLineNum(field_id, 0);
				else
					FieldSetTopLineNum(field_id, line_num - (field_ptr->bounds.height/(line_height)) + 1);
			}
			// ------------------------------------------------------------
			// ------------- add at 19052000 ------------------------------
			else
			{
				FieldGetNumOfChars(field_id, &temp);
				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)
						FieldSetTopLineNum(field_id, 0);
					else
						FieldSetTopLineNum(field_id, line_num - (field_ptr->bounds.height/(line_height)) + 1);
			}
			// ------------------------------------------------------------
		}
	}
	else
	{
		FieldCharPosToLineNum(field_ptr, last_visible_char, &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)
				FieldSetTopLineNum(field_id, 0);
			else
				FieldSetTopLineNum(field_id, line_num - (field_ptr->bounds.height/(line_height)) + 1);
	}
	
#ifdef DEBUG
	printf("\n Point 2) field top line num = %ld", field_ptr->field_top_line_num);
#endif
	return TRUE;
}

/********************************************************
* Function:	AnnScrollbarSetField
* Purpose: 	This function is called to set up the field
*			object when the scrollbar is moved.
* Scope:	application
* Input:	Event		
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoScrollbarSetField(ObjectID field_id, ObjectID scrollbar_id, EvtType *Event)
{
	WORD max,min,value,pagesize;
	WORD scroll_total_lines;
	
	ScrollbarGetScrollbar(scrollbar_id, &value, &max, &min, &pagesize, &scroll_total_lines);
	ScrollbarSetScrollbar(scrollbar_id, Event->para2, max, min, pagesize, scroll_total_lines);
	
	FieldSetTopLineNum(field_id, (USHORT)(Event->para2));
	FieldDrawField(field_id);
	ScrollbarDrawScrollbar(scrollbar_id);		
	return;
}

/********************************************************
* Function:	AnnFieldtoFieldBuffer
* Purpose: 	This function is called in order to put the data
*			in the field object to field buffer
* Scope:	application
* Input:	dbid			The ID of the database
*			record_id		The ID of the record that is required to be 
*							put in the field objects
* Output:	None
* Return:	TRUE			Success
*			FALSE			FALSE
* Comment: 	None
*********************************************************/
void MemoFieldToFieldBuffer()
{
	BYTE *temp;
	
	if (memo_field_buffer[0] != NULL)
		qfree(memo_field_buffer[0]);
	
	if (app_status.edit_mode == MEMO_NEW)
		FieldGetTextPointer(FIELD_MEMO_NEW, &temp);
	else
		FieldGetTextPointer(FIELD_MEMO_VIEWING, &temp);
	
	memo_field_buffer[0] = (BYTE*)qmalloc((strlen(temp) + 1)*sizeof(BYTE));
	strcpy(memo_field_buffer[0],temp);
}

/********************************************************
* Function:	AnnFieldBufferToField
* Purpose: 	This function is called to send data from field buffer to 
*			corresponding FIELD objects
* Scope:	application
* Input:	None
* Output:	None
* Return:	TRUE			success
*			FALSE			error occure
* Comment: 	
*********************************************************/
void MemoFieldBufferToField()
{	
	if (app_status.edit_mode == MEMO_NEW)
		FieldSetText(FIELD_MEMO_NEW, memo_field_buffer[0]);
	else
		FieldSetText(FIELD_MEMO_VIEWING, memo_field_buffer[0]);
}

/********************************************************
* Function:	AnnClearFieldBuffer
* Purpose: 	This function is used to clear the field 
*			buffer of the To Do List Application
* Scope:	application
* Input:	None
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoClearFieldBuffer()
{
	if (memo_field_buffer[0] !=NULL)
	{
		qfree(memo_field_buffer[0]);
		memo_field_buffer[0] = NULL;
	}
}

/********************************************************
* Function:	AnnFieldUpdateRecord
* Purpose: 	This function is called in order to save the edited record
*			back into database.
* Scope:	application
* Input:	dbid			The ID of the database
*			record_id		The ID of the record that is required to be 
*							put in the field object
*			new_record		BOOLENA variable to show whether new record or 
*							old record 
* Output:	None
* Return:	TRUE			Success
*			FALSE			FALSE
* Comment: 	None
*********************************************************/
BOOLEAN MemoFieldUpdateRecord()
{
	UWORD	rec_num;
	UBYTE	cate_num;
	BYTE	read_status = FALSE;
	BYTE	*temp_cate;
	
	if (app_status.edit_mode == MEMO_NEW || app_status.edit_mode == MEMO_VIEWING)
	{
		/* Update current_cate */
		ControlGetLabel(POPUP_TRIGGER_CATEGORY, &temp_cate);
		strcpy(current_cate, temp_cate);
		MemoCateNameToNum(current_cate, &cate_num);
		MemoCateNameToPopupTrigger(memo_dbid);
		
		DataRecIDtoNum(memo_dbid, app_status.rec_id, &rec_num);
		DataOpenRecord(memo_dbid, rec_num, &app_status.rec_id, NULL);
		DataSetRecordAttribute(memo_dbid, app_status.rec_id, ATTR_UNCHG, ATTR_UNCHG, cate_num);
		DataWriteField(memo_dbid, app_status.rec_id, 1, (strlen(memo_field_buffer[0]) + 1), memo_field_buffer[0]);
		DataCloseRecord(memo_dbid, app_status.rec_id);
	}
	/* Clear the field buffer and the corresponding Field object */
	strcpy(memo_field_buffer[0],(BYTE*)(""));
	MemoFieldBufferToField();
	MemoClearFieldBuffer();
	return TRUE;
}

/********************************************************
* Function:	AnnInitFieldBuffer
* Purpose: 	This function is used to init the field buffer
*			of the To Do List Application
* Scope:	application
* Input:	None
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoInitFieldBuffer()
{
	if (memo_field_buffer[0] !=NULL)
		qfree(memo_field_buffer[0]);
	memo_field_buffer[0] = (BYTE*)qmalloc(sizeof(BYTE));
	strcpy(memo_field_buffer[0],(BYTE*)(""));
}

/********************************************************
* Function:	AnnMenuSelectedAction
* Purpose: 	This fucntion is to do an action when 
*			an item in a menu is selected
* Scope:	application/internal
* Input:	item_num	The item number of the selectd menu item
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoMenuSelectedAction(USHORT item_num)
{
	ObjectID active_form_id;
	ObjectID active_object_id;
	BOOLEAN highlighted = FALSE, insert_pt = FALSE;
	BYTE object_type;
	void *addr;
	Field *field_ptr;
	Textbox *textbox_ptr;
	
	
	FormGetActiveFormID(&active_form_id);
	FormGetActiveObject(active_form_id, &active_object_id);
	if (FormGetObjectPointer(active_object_id, &object_type, (void**)&addr) == FALSE)
		return;
	if (object_type != FIELD && object_type != TEXTBOX && item_num != MENU_ITEM_ZOOM)
		return;
	else if (object_type == FIELD)
	{
		field_ptr = (Field*)addr;
		highlighted = field_ptr->field_attr.field_highlight;
		insert_pt = field_ptr->field_attr.field_insert_pt_visible;
	}
	else if (object_type == TEXTBOX)
	{
		textbox_ptr = (Textbox*)addr;
		highlighted = textbox_ptr->textbox_attr.textbox_highlight;
		insert_pt = textbox_ptr->textbox_attr.textbox_insert_pt_visible;
	}
	
	switch(item_num)
	{
	case	MENU_ITEM_COPY:
		KeyboardSendEvent(KEY_COPY, FALSE, FALSE, FALSE);
		break;
		
	case	MENU_ITEM_CUT:
		KeyboardSendEvent(KEY_CUT, FALSE, FALSE, FALSE);
		break;
		
	case	MENU_ITEM_PASTE:
		KeyboardSendEvent(KEY_PASTE, FALSE, FALSE, FALSE);
		break;
		
	case	MENU_ITEM_UNDO:
		if (UIGetUndoStatus() != UNDO_EMPTY)
			KeyboardSendEvent(KEY_UNDO, FALSE, FALSE, FALSE);
		break;
		
	case	MENU_ITEM_ZOOM:
		MemoChangeFont();
		break;
		
	default: break;
	}
}

/********************************************************
* Function:	AnnChangeFont
* 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 MemoChangeFont()
{
	ObjectID	fld_id, scrollbar_id, form_id;	
	BYTE		original_font;
	BYTE		object_type;
	Field		*fld_addr;
	
	
	if (app_status.edit_mode == MEMO_VIEWING)
	{
		FormGetObjectPointer(FIELD_MEMO_VIEWING, &object_type, (void **)&fld_addr);
		FieldGetFont(FIELD_MEMO_VIEWING, &original_font);
		scrollbar_id = SCROLLBAR_MEMO_VIEWING;
		fld_id = FIELD_MEMO_VIEWING;
		form_id = FORM_MEMO_VIEWING;
	}
	else if (app_status.edit_mode == MEMO_NEW)
	{
		FormGetObjectPointer(FIELD_MEMO_NEW, &object_type, (void **)&fld_addr);
		FieldGetFont(FIELD_MEMO_NEW, &original_font);
		scrollbar_id = SCROLLBAR_MEMO_VIEWING;
		fld_id = FIELD_MEMO_NEW;
	}
	
	switch (original_font)
	{
	case	SMALL_FONT:
		MenuDeleteItem(MEMO_MENU, 4);
		MenuInsertItem(MEMO_MENU, 4, MEMOSFONT);
		original_font = MEDIUM_FONT;
		break;
		
	case	MEDIUM_FONT:
		MenuDeleteItem(MEMO_MENU, 4);
		MenuInsertItem(MEMO_MENU, 4, MEMOLFONT);
		original_font = SMALL_FONT;
		break;
		
	default: 
		return FALSE;
	}
	
	FieldSetFont(FIELD_MEMO_VIEWING, original_font);
	FieldSetFont(FIELD_MEMO_NEW, original_font);
	table_font = original_font;
	
	if (show_line == TRUE)
	{
		if (fld_addr->field_attr.field_highlight == TRUE && 
			fld_addr->field_attr.field_insert_pt_visible == FALSE)
			FieldSetInsertPointOff(fld_id);
		else
			FieldSetInsertPointOn(fld_id);
	}
	else
		FieldSetInsertPointOff(fld_id);
	
	MemoEditSetField(form_id, fld_id);
	FieldEraseField(fld_id);
	FieldDrawField(fld_id);
	/* Field update scrollbar */
	MemoFieldSetScrollbar(fld_id, scrollbar_id);
	return TRUE;
}

/********************************************************
* Function:	MemoScrollbarSetEditCate
* Purpose: 	This function is called to set the edit cate list object
*			when the scrollbar is moved.
* Scope:	application
* Input:	Event		
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoScrollbarSetEditCate(EvtType *Event)
{
	WORD max, min, value, pagesize;
	WORD scroll_total_lines;
	
	
	
	if (Event->para1 == Event->para2)
		return;
	
	ScrollbarGetScrollbar(SCROLLBAR_MEMO_LIST, &value, &max, &min, &pagesize, &scroll_total_lines);
	
	if ((Event->para2 - Event->para1) >= pagesize)
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, (Event->para2 - 1), max, min, pagesize, scroll_total_lines);
	else if ((Event->para1 - Event->para2) >= pagesize)
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, (Event->para2 + 1), max, min, pagesize, scroll_total_lines);
	else
		ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, Event->para2, max, min, pagesize, scroll_total_lines);
	
	ListSetTopItemNum(LIST_CATE,(USHORT)(Event->para2));
	ListDrawList(LIST_CATE);
	
	ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);
}

/********************************************************
* Function:	MemoEditCateSetScrollbar
* Purpose: 	This function is called in order to set the 
*			values for a scrollbar		
* Scope:	application
* Input:	None
* Output:	None
* Return:	TRUE		scrollbar is drawn
*			FALSE		scrollbar is erased
* Comment: 	None
*********************************************************/
BOOLEAN MemoEditCateSetScrollbar()
{
	Scrollbar *scroll_ptr;
	BYTE	object_type;
	USHORT	max_num_rows_display;
	USHORT	top_row_num ,total_num_rows;
	WORD	max_value, min_value, pagesize;
	
	
	
	ListRecalculateMaxNumItemsDisplay(LIST_CATE);
	ListGetMaxNumItemsDisplay(LIST_CATE, &max_num_rows_display);
	ListGetTotalItems(LIST_CATE, &total_num_rows);
	ListGetTopItemNum(LIST_CATE, &top_row_num);
	
	pagesize = max_num_rows_display;
	min_value = 0;
	max_value = total_num_rows - pagesize;	
	
	if (total_num_rows > max_num_rows_display)
	{
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,TRUE);
		
		if (top_row_num > (total_num_rows - max_num_rows_display))
			ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, max_value, max_value, min_value,
			pagesize, total_num_rows);
		else
			ScrollbarSetScrollbar(SCROLLBAR_MEMO_LIST, top_row_num, max_value, min_value,
			pagesize, total_num_rows);
		
		FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_ptr);
		scroll_ptr->scrollbar_draw_pagesize = pagesize;
		
		ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);
		return TRUE;
	}
	else
	{
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,FALSE);
		ScrollbarEraseScrollbar(SCROLLBAR_MEMO_LIST);
		return FALSE;
	}
}

/********************************************************
* Function:	DeleteCateCheck
* Purpose: 	This function is used to check the deleting category mode
*			1) the category being deleted has records attached
*			2) there is no record attached to the category
* Scope:	application/internal
* Input:	selected_item		the item number in the list object
* Output:	None
* Return:	TRUE if handled
*			FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN DeleteCateCheck(SHORT selected_item)
{
	RecordID rec_id;
	BYTE	*list_text, *cate_name;
	UBYTE	num_cate, cate[256], cat;
	SHORT	i;
	UWORD	total_num_rec, j;
	BOOLEAN found = FALSE;
	
	
	
	cate_name = (BYTE*)qmalloc(30*sizeof(BYTE));
	DataTotalRecord(memo_dbid, &total_num_rec);
	ListGetListItem(LIST_CATE, (USHORT)(selected_item), &list_text);
	num_cate = DataCategorySort(memo_dbid, cate);
	
	for (i =0; i <num_cate; i++)
	{
		DataCategoryName(memo_dbid, cate[i], cate_name);
		
		if (MemoCompareTwoStrings(cate_name, list_text) == SAME)
		{
			DataTotalRecord(memo_dbid, &total_num_rec);
			
			for (j =0; j <total_num_rec; j++)
			{
				DataNumtoRecID(memo_dbid,j, &rec_id);
				DataRecordInfo(memo_dbid,rec_id, NULL, &cat, NULL, NULL, NULL);
				
				if (cat == cate[i])
				{
					FormPopupForm(FORM_REMOVE_CATE);
					qfree(cate_name);
					return TRUE;
				}
			}
			
			FormPopupForm(FORM_ERASE_CATE);
			qfree(cate_name);
			return TRUE;
		}
	}
	qfree(cate_name);
	return TRUE;
}

/********************************************************
* Function:	DeleteCate
* Purpose: 	This function is used to delete the category and 
*			move all records from the previous category to unfiled
* Scope:	application/internal
* Input:	selected_item		the item number in the list object
* Output:	None
* Return:	TRUE if handled
*			FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN DeleteCate(SHORT selected_item)
{
	
	BYTE *list_text, *cate_name;
	UBYTE num_cate, cate[256];
	SHORT i;
	
	cate_name = (BYTE*)qmalloc(30*sizeof(BYTE));
	ListGetListItem(LIST_CATE, (USHORT)(selected_item), &list_text);
	num_cate = DataCategorySort(memo_dbid, cate);
	
	for (i =0; i<num_cate; i++)
	{
		DataCategoryName(memo_dbid, cate[i], cate_name);
		
		if (MemoCompareTwoStrings(cate_name, list_text) == SAME)
		{
			ListDeleteItem(LIST_CATE, selected_item);
			DataCategorySetName(memo_dbid, cate[i], (BYTE*)(""));
			ListDrawList(LIST_CATE);
			DataMoveCat(memo_dbid, cate[i], 0);
			qfree(cate_name);
			return TRUE;
		}
	}
	return FALSE;
}

/********************************************************
* Function:	InputCatCheckCharIn
* Purpose:	to check the input catergory
* Scope:	internal
* Input:    Event 		received event
* Output:	None
* Return:	TRUE if handled
*			FALSE if not handled
* Comment:  None
*********************************************************/
BOOLEAN MemoInputCatCheckCharIn()
{
	WORD	textbox_num_chars;
	UBYTE	next_free_cate_location;
	UBYTE	num_cat, cate[256];
	BYTE	*textbox_string, *list_string;
	BYTE	*cate_name, *delete_string;
    USHORT	num_items, num_items1;
	USHORT	max_num_items, total_num_items, i;
	SHORT	selected_item;
	BOOLEAN found =FALSE, added =FALSE;
	
	TextboxGetNumOfChars(TEXTBOX_NEW_CATE, &textbox_num_chars);
	TextboxGetTextPointer(TEXTBOX_NEW_CATE, &textbox_string);
	
	if (textbox_num_chars == 0)
	{
		FormPopupForm(FORM_EDIT_CATE);
		return	TRUE;
	}
	else if (MemoCompareTwoStrings(textbox_string, MEMOALL) == SAME ||
		MemoCompareTwoStrings(textbox_string, MEMOUNFILED) == SAME ||
		MemoCompareTwoStrings(textbox_string, MEMOECAT) == SAME )
	{
		FormDrawForm(FORM_EDIT_CATE);
		FormPopupForm(FORM_EXISTS_CATE);
		return TRUE;
	}
	if (pressed_key == BUTTON_MEMO_NEW)
	{
        ListGetNumOfItems(LIST_CATE, &num_items);
		num_items1 = num_items;
		
        while (num_items >0)
		{
			ListGetListItem(LIST_CATE, --num_items, &list_string);
			
			if (MemoCompareTwoStrings(textbox_string, list_string) == SAME)
			{
				FormDrawForm(FORM_EDIT_CATE);
				FormPopupForm(FORM_EXISTS_CATE);
				return TRUE;
			}
		}
		
		DataCategoryNextFree(memo_dbid, &next_free_cate_location);
		DataCategorySetName(memo_dbid, next_free_cate_location, textbox_string);
		
		for (i =0; i <num_items1; i++)
		{
			ListGetListItem(LIST_CATE, i, &list_string);
			
			if (MemoCompareTwoStrings(textbox_string, list_string) == FIRST)
			{
				ListInsertItem(LIST_CATE, i, textbox_string);
				MemoEditCateSetScrollbar();
				
				FormPopupForm(FORM_EDIT_CATE);
				strcpy(current_cate, textbox_string);
                pressed_key = 0;
				added = TRUE;
				break;
			}
		}
		
		if (added == FALSE)
			ListInsertItem(LIST_CATE, num_items1, textbox_string);
		
		ListGetNumOfItems(LIST_CATE, &total_num_items);
		ListGetMaxNumItemsDisplay (LIST_CATE, &max_num_items);
		
		if (added == FALSE || (added == TRUE && i >= (total_num_items - max_num_items)))
			ListSetTopItemNum(LIST_CATE, (USHORT)(total_num_items - max_num_items));
		else if (i < max_num_items)
			ListSetTopItemNum(LIST_CATE, 0);
		else
			ListSetTopItemNum(LIST_CATE, (USHORT)i);
		
		if (textbox_num_chars != 0)
			ListSetHighlightedItem(LIST_CATE, i);
		
		MemoEditCateSetScrollbar();
		FormPopupForm(FORM_EDIT_CATE);
		pressed_key = 0;
		return TRUE;
	}
	else if (pressed_key == BUTTON_RENAME_CATE)
	{
		ListGetNumOfItems(LIST_CATE,&num_items);
		ListGetSelectedItem(LIST_CATE,&selected_item);
		
		for (i =0; i <num_items; i++)
		{
            if (i == selected_item)
                continue;			
			ListGetListItem(LIST_CATE, i, &list_string);
			if (MemoCompareTwoStrings(textbox_string, list_string) == SAME)
			{
				found = TRUE;
				break;
			}
		}
		
		if (found == FALSE)
		{
			ListGetSelectedItem(LIST_CATE, &selected_item);
			ListGetListItem(LIST_CATE, (USHORT)selected_item, &delete_string);
			num_cat = DataCategorySort(memo_dbid, cate);
			cate_name = (BYTE*)qmalloc(30*sizeof(BYTE));
			
			for (i =0; i<num_cat; i++)
			{
				DataCategoryName(memo_dbid, cate[i], cate_name);
				
				if (MemoCompareTwoStrings(delete_string, cate_name) == SAME)
				{	
					DataCategorySetName(memo_dbid, cate[i],textbox_string);
					break;
				}
			}	
			
			ListDeleteItem(LIST_CATE, (USHORT)selected_item);
			ListGetNumOfItems(LIST_CATE, &num_items);
			
			for (i =0; i <num_items; i++)
			{
				ListGetListItem(LIST_CATE, i, &list_string);
				
				if (MemoCompareTwoStrings(textbox_string, list_string) == FIRST)
				{	
					ListInsertItem(LIST_CATE, i, textbox_string);
					found = TRUE;
					break;
				}
			}			
			
			if (found == FALSE)
				ListInsertItem(LIST_CATE, num_items, textbox_string);
			
			ListGetNumOfItems(LIST_CATE, &total_num_items);
			ListGetMaxNumItemsDisplay(LIST_CATE, &max_num_items);
			
			if (found == FALSE || (found == TRUE && i >= (total_num_items - max_num_items)))
				ListSetTopItemNum(LIST_CATE, (USHORT)(total_num_items - max_num_items));
			else if (i < max_num_items)
				ListSetTopItemNum(LIST_CATE, 0);
			else
				ListSetTopItemNum(LIST_CATE, (USHORT)i);
			
			if (textbox_num_chars != 0)
				ListSetHighlightedItem(LIST_CATE, i);
			
			MemoEditCateSetScrollbar();
			FormPopupForm(FORM_EDIT_CATE);
			strcpy(current_cate, textbox_string);
            pressed_key = 0;
			qfree(cate_name);
			return TRUE;
		}
		else
		{
			FormDrawForm(FORM_EDIT_CATE);
			FormPopupForm(FORM_EXISTS_CATE);
			return TRUE;
		}
	}
	return FALSE;
}

/********************************************************
* Function:	MemoCateNameToPopupTrigger
* Purpose: 	This function is used to update teh items of the 
*			POPUP_TRIGGER_CATE
* Scope:	application
* Input:	dbid		THE dbid of a database
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoCateNameToPopupTrigger(DatabaseID dbid)
{
	UBYTE	num_cate, cate[255];
	BYTE	*cate_name;
	SHORT	i;
	
	
	num_cate = DataCategorySort(memo_dbid, cate);
	ControlPopupDeleteAllItems(POPUP_TRIGGER_CATEGORY);
	ControlPopupInsertItem(POPUP_TRIGGER_CATEGORY, 0, MEMOALL);
	ControlPopupInsertItem(POPUP_TRIGGER_CATEGORY, 1, MEMOUNFILED);
	cate_name = (BYTE*)qmalloc(30*sizeof(BYTE));
	
	for (i =0; i<num_cate; i++)
	{
		DataCategoryName(memo_dbid, cate[i], cate_name);
		ControlPopupInsertItem(POPUP_TRIGGER_CATEGORY, (i+2), cate_name);
	}
	
	ControlPopupInsertItem(POPUP_TRIGGER_CATEGORY, (num_cate+2), MEMOECAT);
	qfree(cate_name);
}

/********************************************************
* Function:	ToDoNewSetUpVariable
* Purpose: 	This function is called to set variable for 
*			New Screen
* Scope:	application
* Input:	None
* Output:	None
* Return:	TRUE		Updated
*			FALSE		No change
* Comment: 	None
*********************************************************/
void MemoNewSetUpVariable()
{
	BYTE		object_type;
	Bitmap		*bmp_addr;
	Field		*field_addr;
	String		*string_addr;
	RTM		time;
	
	/* Set up New Screen */
	memo_top_line = 0;
	memo_insert_pt_pos =0;
	app_status.sketch_status = 0;
	app_status.field_change = FALSE;
	
	RtcGetTime(&time);
	RtcFormatDate(&time, MEMOSTR1, app_status.create_time);
	/* Clear and Disable Sketch Bitmap */
	FormGetObjectPointer(BITMAP_MEMO_SKETCH, &object_type, (void **)&bmp_addr);
	bmp_addr->bitmap_attr.bitmap_visible = FALSE;
	bmp_addr->bitmap_attr.bitmap_enable = FALSE;
	/* Set up Category */
	MemoCateNameToPopupTrigger(memo_dbid);
	ControlPopupDeleteItem(POPUP_TRIGGER_CATEGORY, 0);
	//HENRY	ControlSetLabel(POPUP_TRIGGER_CATEGORY, MEMOUNFILED);
	ControlSetLabel(POPUP_TRIGGER_CATEGORY, current_cate);
	strcpy(temp_cate, current_cate);
	
	//HENRY	strcpy(current_cate, MEMOUNFILED);
	
	//strcpy(current_cate, MEMOUNFILED);
	/* Set up Field Size */
	FieldSetFont(FIELD_MEMO_NEW, table_font);
	FieldSetHighlightSelection(FIELD_MEMO_NEW, 0, 0);
	FormGetObjectPointer(FIELD_MEMO_NEW, &object_type, (void **)&field_addr);
	field_addr->field_attr.field_highlight = FALSE;
	/* Create a new record */
#ifdef	DEBUG
	printf("\n\n----> Create New Rec Id %d <----\n\n", app_status.rec_id);
#endif
	DataNewRecord(memo_dbid, 0, MEMO_NUM_FIELD, &app_status.rec_id);
}

/********************************************************
* Function:	ToDoListTableSetScrollbar
* Purpose: 	This function is called in order to set the values for a scrollbar		
* Scope:	application
* Input:	BYTE				the starting_char
* Output:	None
* Return:	TRUE		scrollbar is erased
*			FALSE		scrollbar is drawn
* Comment: 	If a scrollbar is not required, then the scrollbar will be erased 
*			If a scrollbar is required, the scrollbar will be displayed accordingly 
*********************************************************/
BOOLEAN MemoTableSetScrollbar()
{
	WORD temp_value, max_value, min_value, pagesize, total_num_rows;
	
	ScrollbarGetScrollbar(SCROLLBAR_MEMO_LIST, &temp_value, &max_value, &min_value, &pagesize, &total_num_rows);
	
	if (memo_list.total_num_rows > memo_list.num_rows_displayed)
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,TRUE);
	else
	{
		ScrollbarSetScrollbarVisible(SCROLLBAR_MEMO_LIST,FALSE);
		ScrollbarEraseScrollbar(SCROLLBAR_MEMO_LIST);
		return FALSE;
	}
	ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);
	return TRUE;
}

/********************************************************
* Function:    MemoChangeListFontSize
* Purpose: 	This function is called to change the font of the list
object 
* Scope:		application
* Input:		Event		
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
void MemoChangeCateListFontSize()
{
	List		*list_ptr;
	Scrollbar	*scroll_ptr;
    BYTE        object_type;
	
	
	FormGetObjectPointer(LIST_CATE, &object_type, (void**)&list_ptr);
	FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_ptr);
	
	if (list_ptr->list_text_font == SMALL_FONT)
	{
		table_font = MEDIUM_FONT;
		ListSetFont(LIST_CATE, MEDIUM_FONT);
	}
	else 
	{
		table_font = SMALL_FONT;
		ListSetFont(LIST_CATE, SMALL_FONT);
	}
	
	if (list_ptr->list_total_num_items > list_ptr->list_max_num_items_on_display)
	{
		scroll_ptr->scrollbar_attr.scrollbar_visible = TRUE;
		
		if (list_ptr->list_highlighted_item >0 && list_ptr->list_highlighted_item < list_ptr->list_top_item_num)
			list_ptr->list_top_item_num = list_ptr->list_highlighted_item;
        else if (list_ptr->list_highlighted_item >= (list_ptr->list_top_item_num + list_ptr->list_max_num_items_on_display))
			list_ptr->list_top_item_num = list_ptr->list_highlighted_item;
		
        if (list_ptr->list_top_item_num >= (list_ptr->list_total_num_items - list_ptr->list_max_num_items_on_display))
			list_ptr->list_top_item_num = (list_ptr->list_total_num_items - list_ptr->list_max_num_items_on_display);
		
		scroll_ptr->scrollbar_value 		= list_ptr->list_top_item_num;
        scroll_ptr->scrollbar_pagesize		= list_ptr->list_max_num_items_on_display;
		scroll_ptr->scrollbar_draw_pagesize = scroll_ptr->scrollbar_pagesize;
		scroll_ptr->scrollbar_total_num_lines = list_ptr->list_total_num_items;
		scroll_ptr->scrollbar_max			= scroll_ptr->scrollbar_total_num_lines - scroll_ptr->scrollbar_pagesize;
		scroll_ptr->scrollbar_min			= 0;
	}
	else
	{
		scroll_ptr->scrollbar_attr.scrollbar_visible = FALSE;
		ScrollbarEraseScrollbar(SCROLLBAR_MEMO_LIST);	
		list_ptr->list_top_item_num = 0;
	}
	
	if (list_ptr->list_text_font == SMALL_FONT)
	{
		MenuDeleteItem(MEMO_CATE_MENU, 0);
		MenuInsertItem(MEMO_CATE_MENU, 0, MEMOLFONT);
	}
	else
	{
		MenuDeleteItem(MEMO_CATE_MENU, 0);
		MenuInsertItem(MEMO_CATE_MENU, 0, MEMOSFONT);
	}
	
	ListDrawList(LIST_CATE);
	ScrollbarDrawScrollbar(SCROLLBAR_MEMO_LIST);	
}

/********************************************************
* Function:	ToDoMenuSelectedAction
* Purpose: 	This fucntion is to do an action when 
*			an item in a menu is selected
* Scope:	application/internal
* Input:	item_num	The item number of the selectd menu item
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
BOOLEAN MemoViewingSelectedLargeFontOnly()
{
	BYTE	original_font;
	
	
	
	FieldGetFont(FIELD_MEMO_VIEWING, &original_font);
	
	switch (original_font)
	{
	case	SMALL_FONT:
		MenuDeleteItem(MEMO_MENU, 0);
		MenuInsertItem(MEMO_MENU, 0, MEMOSFONT);
		original_font = MEDIUM_FONT;
		break;
		
	case	MEDIUM_FONT:
		MenuDeleteItem(MEMO_MENU, 0);
		MenuInsertItem(MEMO_MENU, 0, MEMOLFONT);
		original_font = SMALL_FONT;
		break;
		
	default: 
		return FALSE;
	}
	
	FieldSetFont(FIELD_MEMO_VIEWING, original_font);
	FieldSetFont(FIELD_MEMO_NEW, original_font);
	
	table_font = original_font;
	
	if (show_line == TRUE)
		FieldSetInsertPointOn(FIELD_MEMO_VIEWING);
	else
		FieldSetInsertPointOff(FIELD_MEMO_VIEWING);
	
	MemoEditSetField(FORM_MEMO_VIEWING, FIELD_MEMO_VIEWING);
	FieldEraseField(FIELD_MEMO_VIEWING);
	FieldDrawField(FIELD_MEMO_VIEWING);
	/* Field update scrollbar */
	MemoFieldSetScrollbar(FIELD_MEMO_VIEWING, SCROLLBAR_MEMO_VIEWING);
	return	TRUE;
}

/********************************************************
* Function:	ToDoMenuSelectedAction
* Purpose: 	This fucntion is to do an action when 
*			an item in a menu is selected
* Scope:	application/internal
* Input:	item_num	The item number of the selectd menu item
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void MemoSetTableFont()
{
	BYTE		object_type, font_height;
	USHORT		row_number;
	String		*string_addr;
	Scrollbar	*scroll_addr;
	
	/* Set Large Table Font */
	if (table_font == MEDIUM_FONT)
	{
		FormGetObjectPointer(STRING_MEMO_CONTENT_N1, &object_type, (void **)&string_addr);
		if (string_addr->text_font == MEDIUM_FONT) return;
		MenuDeleteItem(MENU_CHANGE_FONT, 0);
		MenuInsertItem(MENU_CHANGE_FONT, 0, MEMOSFONT);
		
		font_height = SysGetFontHeight(MEDIUM_FONT);
		for (row_number =0; row_number < MEMO_LFONT_NUM_OF_ROW; row_number++)
			TableSetRowHeight(TABLE_MEMO_LIST, row_number, font_height+3);
		
		TableSetColumnWidth(TABLE_MEMO_LIST, 0, MEMO_LCOLUMN_1);
		TableSetColumnWidth(TABLE_MEMO_LIST, 1, MEMO_LCOLUMN_2);
		TableSetColumnWidth(TABLE_MEMO_LIST, 2, MEMO_LCOLUMN_3);
		
		FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_addr);
		scroll_addr->scrollbar_pagesize = MEMO_LFONT_NUM_OF_ROW;
		scroll_addr->scrollbar_draw_pagesize = MEMO_LFONT_NUM_OF_ROW;
		scroll_addr->scrollbar_total_num_lines = memo_list.total_num_rows;
		scroll_addr->scrollbar_value = memo_list.top_row_num;
		scroll_addr->scrollbar_max = scroll_addr->scrollbar_total_num_lines - scroll_addr->scrollbar_pagesize;
	}
	else
	{
		FormGetObjectPointer(STRING_MEMO_CONTENT_N1, &object_type, (void **)&string_addr);
		if (string_addr->text_font == SMALL_FONT) return;
		MenuDeleteItem(MENU_CHANGE_FONT, 0);
		MenuInsertItem(MENU_CHANGE_FONT, 0, MEMOLFONT);
		
		font_height = SysGetFontHeight(SMALL_FONT);
		for (row_number =0; row_number < MEMO_SFONT_NUM_OF_ROW; row_number++)
			TableSetRowHeight(TABLE_MEMO_LIST, row_number, font_height+1);
		
		/* Set Small Column Width */
		TableSetColumnWidth(TABLE_MEMO_LIST, 0, MEMO_SCOLUMN_1);
		TableSetColumnWidth(TABLE_MEMO_LIST, 1, MEMO_SCOLUMN_2);
		TableSetColumnWidth(TABLE_MEMO_LIST, 2, MEMO_SCOLUMN_3);
		
		FormGetObjectPointer(SCROLLBAR_MEMO_LIST, &object_type, (void**)&scroll_addr);
		scroll_addr->scrollbar_pagesize = MEMO_SFONT_NUM_OF_ROW;
		scroll_addr->scrollbar_draw_pagesize = MEMO_SFONT_NUM_OF_ROW;
		scroll_addr->scrollbar_total_num_lines = memo_list.total_num_rows;
		scroll_addr->scrollbar_value = memo_list.top_row_num;
		scroll_addr->scrollbar_max = scroll_addr->scrollbar_total_num_lines - scroll_addr->scrollbar_pagesize;
		
		if (scroll_addr->scrollbar_value < (MEMO_SFONT_NUM_OF_ROW - MEMO_LFONT_NUM_OF_ROW))
			memo_list.top_row_num = 0;
		else if (scroll_addr->scrollbar_value == memo_list.total_num_rows - memo_list.num_rows_displayed) /* Last row */
			memo_list.top_row_num = scroll_addr->scrollbar_value - (MEMO_SFONT_NUM_OF_ROW - MEMO_LFONT_NUM_OF_ROW);
		else
			memo_list.top_row_num = scroll_addr->scrollbar_value - (MEMO_SFONT_NUM_OF_ROW - MEMO_LFONT_NUM_OF_ROW -1);
	}
}
