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


#include "stdafx.h"
#include "system.h"

//#define DEBUG
//#define DEBUG_TT
//#define DEBUG_BIG
//#define DEBUG_GF
//#define   DEBUG_KEY
//#define   DEBUG_SEARCH

BOOLEAN (*SystemFormDispatchEvent)(EvtType *Event);
void GlobalFindRestoreRunningApp(void);
void GlobalFindRestoreRunningApp1(void);

/********************* Global Find Variable ***********************
******************************************************************/
BOOLEAN					gf_popup = FALSE;
BOOLEAN                 gf_keyboard_status = FALSE;
BYTE					gf_error = GF_NO_ERROR;
BOOLEAN                 gf_menu_status = FALSE;
BOOLEAN                 gf_popup_status = FALSE;
EvtType                 gf_old_event = {0, 0, 0, 0, NULL};
EvtType                 gf_inlay_event;


USHORT					gf_num_items		= 0;
GFindResultBlock        *gf_link            = NULL;
USHORT                  gf_top_item_num     = 0;

AppID                   gf_current_app_id   = 0;
ObjectID                gf_current_form_id  = 0;
BitmapTemplate          gf_current_display_image;

BYTE                    gf_previous_search_string[120];

BOOLEAN                 gf_keyboard_visible = FALSE;

/*****************************************************************
* Function:	GlobalFindInit()
* Purpose: 	This function is called to initialise the global variables
of Global Find
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindInit(void)
{
    gf_keyboard_status = FALSE;
	gf_popup = FALSE;
	gf_error = GF_NO_ERROR;
	gf_num_items = 0;
	gf_link = NULL;
	gf_num_items = 0;
	gf_old_event.eventType = NULL_EVENT;
	gf_top_item_num = 0;
	gf_current_app_id = 0;
	gf_current_form_id = 0;
	gf_current_display_image.xcoord = 0;
	gf_current_display_image.ycoord = 0;
	gf_current_display_image.width = 160;
	gf_current_display_image.height = 160;
	gf_current_display_image.bitmap_data = NULL;
	
    gf_previous_search_string[0] = 0;
    gf_keyboard_visible = FALSE;
}

/*****************************************************************
* Function:	GlobalFindDeleteAllItems()
* Purpose: 	This function is called to delete all the items in 
the link list
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindDeleteAllItems(void)
{
	GFindResultBlock *temp;
	
	if (gf_link == NULL)
		return;
	
	while (gf_link != NULL)
	{
        if(gf_link->display_string)
            pfree(gf_link->display_string);
        temp = gf_link;
        gf_link = gf_link->next;
		pfree(temp);
	}
	gf_num_items = 0;
	gf_top_item_num = 0;
}

/*****************************************************************
* Function:	GlobalFindAddItem()
* Purpose:		This function is called to add an item to 
the gf_link				
* Scope:		application/internal
* Input:		app_id			application id
dbid			the database id
rec_id			record id
field_num
string			the display_string
* Output:		None
* Return:		None
* Comment: 	if app_id == 0xFF, then it is noted as a separator
******************************************************************/
BOOLEAN GlobalFindAddItem(AppID app_id, DatabaseID dbid, RecordID rec_id, USHORT field_num, BYTE *string, BOOLEAN override)
{
	GFindResultBlock *temp;
	
	
    if (gf_error == GF_NO_MEM)
		return FALSE;	
    if (MemoryTotalFree() <= PMALLOC_WARNING && override == FALSE)
	{
		gf_error = GF_NO_MEM;
		return FALSE;
	} 			
	
	temp = gf_link;
	while (temp != NULL)
	{
		if (temp->next == NULL)
		{
            temp->next              = (GFindResultBlock *)pmalloc(sizeof(GFindResultBlock));
			temp = temp->next;
			temp->app_id			= app_id;
			temp->dbid				= dbid;
			temp->rec_id			= rec_id;
			temp->field_num			= field_num;
            temp->display_string    = (BYTE*)pmalloc((strlen(string) + 1) * sizeof(BYTE));
			strcpy(temp->display_string, string);
			temp->next				= NULL;       
			gf_num_items ++;
            return TRUE;
		}
		temp = temp->next;
	}
	
    gf_link                 = (GFindResultBlock *)pmalloc(sizeof(GFindResultBlock));
	gf_link->app_id			= app_id;
	gf_link->dbid			= dbid;
	gf_link->rec_id			= rec_id;
	gf_link->field_num		= field_num;
    gf_link->display_string = (BYTE*)pmalloc((strlen(string) + 1) * sizeof(BYTE));
	strcpy(gf_link->display_string, string);
    gf_link->next           = NULL;
	gf_num_items ++;
    return TRUE;
}

/********************************************************
* Function:	GlobalFindSearchText
* Purpose: 	This function is called to search a string from a long text.
* Scope:		application
* Input:		short_string		a short text for searching
whole_string		the string to be searched			
* Output:		None
* Return:		-1					not found
0 or larger num		character position
* Comment: 	
*********************************************************/
WORD GlobalFindSearchText(BYTE *short_string, BYTE *whole_string)
{
	UWORD		chars, charw;
	UBYTE		*strings, *stringw, *bufferw;
	
	strings = short_string;
	stringw = bufferw = whole_string;
	chars = *strings;
	charw = *bufferw;
	
	while (chars && charw)
	{
		if (chars >= 'a' && chars <= 'z') chars = chars - 32;
		if (charw >= 'a' && charw <= 'z') charw = charw - 32;
		if (chars == charw) {
			strings++;
			bufferw++;
		} else {
			strings = short_string;
			bufferw = ++stringw;
		}
		chars = *strings;
		charw = *bufferw;
	}
	if(!chars) return (WORD)((UBYTE*)stringw - (UBYTE*)whole_string);
	else return -1;
}
/*****************************************************************
* Function:	GlobalFindStringHandleEvent
* Purpose:		Thsi function is called to handle the click down on string object
* Scope:		application/internal
* Input:		app_id			application id
dbid			the database id
rec_id			record id
string			the display_string
* Output:		None
* Return:		None
* Comment: 	if app_id == 0xFF, then it is noted as a separator
******************************************************************/
BOOLEAN GlobalFindStringHandleEvent(EvtType *Event)
{
	Table *table_ptr;
	String *string_ptr;
	BYTE object_type;
	ObjectID count_id;
	USHORT count = 0;
	GFindResultBlock *temp;
	
	FormGetObjectPointer(TABLE_GFIND_RESULT, &object_type, (void**)&table_ptr);
	if (gf_old_event.eventType != NULL_EVENT)
		FormGetObjectPointer((ObjectID)(gf_old_event.eventID), &object_type, (void**)&string_ptr);
	
	switch (Event->eventType)
	{
	case PEN_EVENT:
		switch (Event->eventID)
		{
		case PEN_UP:
			switch (gf_old_event.eventType)
			{
			case EVT_GFIND_STRING_ENTER:
				EvtAppendEvt(EVT_GFIND_STRING_SELECT, gf_old_event.eventID,
					gf_old_event.para1, 0, gf_old_event.evtPBP);
				string_ptr->string_color = COLOR_BLACK;
				string_ptr->string_bg_color = COLOR_WHITE;
				StringDrawString(string_ptr->identification.ui_object_id);
				gf_old_event.eventType = NULL_EVENT;
				return TRUE;
			case EVT_GFIND_STRING_EXIT:
				string_ptr->string_color = COLOR_BLACK;
				string_ptr->string_bg_color = COLOR_WHITE;
				StringDrawString(string_ptr->identification.ui_object_id);
				gf_old_event.eventType = NULL_EVENT;
				return TRUE;
			default: return FALSE;
			}
			return FALSE;
            case PEN_DOWN:
				for (count_id = STRING_GFIND_RESULT_0; count_id <= STRING_GFIND_RESULT_10; count_id++)
				{
					FormGetObjectPointer(count_id, &object_type, (void**)&string_ptr);
					if (Event->para1 >= string_ptr->screen_bounds.xcoord &&
						Event->para1 < (string_ptr->screen_bounds.xcoord + string_ptr->screen_bounds.width) &&
						Event->para2 >= string_ptr->screen_bounds.ycoord &&
						Event->para2 < (string_ptr->screen_bounds.ycoord + string_ptr->screen_bounds.height) &&
						((count_id - STRING_GFIND_RESULT_0 + gf_top_item_num) < gf_num_items))
					{
						count = 0;
						temp = gf_link;
						while (count < gf_num_items)
						{
							if (temp->app_id == 0xFF && (count == (gf_top_item_num + count_id - STRING_GFIND_RESULT_0)))
							{
								gf_old_event.eventType = NULL_EVENT;
								return FALSE;
							}
							else if (temp->app_id != 0xFF && (count == (gf_top_item_num + count_id - STRING_GFIND_RESULT_0)))
							{
								EvtAppendEvt(EVT_GFIND_STRING_ENTER, count_id, 
									(gf_top_item_num + (count_id - STRING_GFIND_RESULT_0)), 0, (void*)string_ptr);
								return TRUE;
							}
							count ++;
							temp = temp->next;
						}
					}
				}
				gf_old_event.eventType = NULL_EVENT;
				return FALSE;
            case PEN_MOVE:
				switch (gf_old_event.eventType)
				{
                case EVT_GFIND_STRING_ENTER:
					FormGetObjectPointer((ObjectID)(gf_old_event.eventID), &object_type, (void**)&string_ptr);
					if (Event->para1 < string_ptr->screen_bounds.xcoord ||
						Event->para1 >= (string_ptr->screen_bounds.xcoord + string_ptr->screen_bounds.width) ||
						Event->para2 < string_ptr->screen_bounds.ycoord ||
						Event->para2 >= (string_ptr->screen_bounds.ycoord + string_ptr->screen_bounds.height))
						EvtAppendEvt(EVT_GFIND_STRING_EXIT, (ObjectID)(gf_old_event.eventID),
						(gf_top_item_num + (gf_old_event.eventID - STRING_GFIND_RESULT_0)), 0, (void*)string_ptr);
					return TRUE;
                case EVT_GFIND_STRING_EXIT:
					FormGetObjectPointer((ObjectID)(gf_old_event.eventID), &object_type, (void**)&string_ptr);
					if (Event->para1 >= string_ptr->screen_bounds.xcoord &&
						Event->para1 < (string_ptr->screen_bounds.xcoord + string_ptr->screen_bounds.width) &&
						Event->para2 >= string_ptr->screen_bounds.ycoord &&
						Event->para2 < (string_ptr->screen_bounds.ycoord + string_ptr->screen_bounds.height))
						EvtAppendEvt(EVT_GFIND_STRING_ENTER, (ObjectID)(gf_old_event.eventID), 
						(gf_top_item_num + (gf_old_event.eventID - STRING_GFIND_RESULT_0)), 0, (void*)string_ptr);
					return TRUE;
                default: return FALSE;
				}
				return FALSE;
				default: return FALSE;
		}
		case EVT_GFIND_STRING_ENTER:
			gf_old_event = *Event;
			FormGetObjectPointer((ObjectID)(gf_old_event.eventID), &object_type, (void**)&string_ptr);
			string_ptr->string_color = COLOR_WHITE;
			string_ptr->string_bg_color = COLOR_BLACK;
			StringDrawString(string_ptr->identification.ui_object_id);
			return TRUE;
		case EVT_GFIND_STRING_EXIT:
			gf_old_event = *Event;
			FormGetObjectPointer((ObjectID)(gf_old_event.eventID), &object_type, (void**)&string_ptr);
			string_ptr->string_color = COLOR_BLACK;
			string_ptr->string_bg_color = COLOR_WHITE;
			StringDrawString(string_ptr->identification.ui_object_id);
			return TRUE;
		default: return FALSE;
    }
}

/*****************************************************************
* Function:	GlobalFindSetMatchingString
* Purpose:		This function is called to set the 
STRING_GFIND_RESULT_MATCH
* Scope:		application/internal
* Input:		matching_string
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindSetMatchString(BYTE *matching_string)
{
	BOOLEAN found = FALSE;
	GFindResultBlock *temp;
	BYTE *string;
	UWORD j;
	
	temp = gf_link;
	while (temp != NULL)
	{
		if (temp->app_id != 0xFF)
		{
			found = TRUE;
			break;
		}
		temp = temp->next;
	}
	
	string = (BYTE*)pmalloc((20 + strlen(matching_string)) * sizeof(BYTE));
	
	if (found == TRUE)
	{
		j = sprintf((char*)string, "%s", SYSTR17);
		j += sprintf((char*)string + j, "%s", (char*)matching_string);
		j += sprintf((char*)string + j, "%s", (char*)("\""));
	}
	else
	{
		j = sprintf((char*)string, "%s", SYSTR18);
		j += sprintf((char*)string + j, "%s", (char*)matching_string);
		j += sprintf((char*)string + j, "%s", (char*)("\""));
	}
	StringSetText(STRING_GFIND_RESULT_MATCH, string);
	pfree(string);
}

/*****************************************************************
* Function:	GlobalFindPutDataToTable
* Purpose:		This function is called to put the data to table object
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindPutDataToTable()
{
	USHORT count = 0;
	GFindResultBlock *temp;
	BYTE *string;
	
	for (count = 0; count < 11; count++)
		StringSetText((ObjectID)(STRING_GFIND_RESULT_0 + count), (BYTE*)(""));
	
	count = 0;
	temp = gf_link;
	while (temp != NULL && (count < (gf_top_item_num + 11)))
	{
		if (count >= gf_num_items)
			return;
		if (count >= gf_top_item_num && count < (gf_top_item_num + gf_num_items))
		{
			StringSetText((ObjectID)(count - gf_top_item_num + STRING_GFIND_RESULT_0), 
				temp->display_string);
		}
		count ++;
		temp = temp->next;
	}
}


/*****************************************************************
* Function:	GlobalFindScrollbarSetTable
* Purpose:		This function is called to set the table when teh 
scrollbar is dragged
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindScrollbarSetTable(EvtType *Event)
{
	WORD value, max_value, min_value, pagesize, total_num_lines;
	
	ScrollbarGetScrollbar(SCROLLBAR_GFIND_RESULT, &value, &max_value, 
						  &min_value, &pagesize, &total_num_lines);
	
	ScrollbarSetScrollbar(SCROLLBAR_GFIND_RESULT, (Event->para2), max_value, 
						  min_value, pagesize, total_num_lines);
	
	ScrollbarSetScrollbarDrawPagesize(SCROLLBAR_GFIND_RESULT, (SHORT)pagesize);
	
	gf_top_item_num = (USHORT)(Event->para2);
	GlobalFindPutDataToTable();
	TableDrawTable(TABLE_GFIND_RESULT);
	ScrollbarDrawScrollbar(SCROLLBAR_GFIND_RESULT);
}

/*****************************************************************
* Function:	GlobalFindSetupScrollbar
* Purpose:		This function is called to setup the scrollbar 
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindSetupScrollbar()
{
	Scrollbar *scroll_ptr;
	BYTE object_type;
	
    UISearchForAddress(SCROLLBAR_GFIND_RESULT, &object_type, (void**)&scroll_ptr);
    if (gf_num_items <= 11)
	{
		scroll_ptr->scrollbar_attr.scrollbar_visible = FALSE;
		return;
	}
	else scroll_ptr->scrollbar_attr.scrollbar_visible = TRUE;
	ScrollbarSetScrollbar(SCROLLBAR_GFIND_RESULT, gf_top_item_num,
		(gf_num_items - 11), 0, 11, gf_num_items);
	ScrollbarSetScrollbarDrawPagesize(SCROLLBAR_GFIND_RESULT, 11);
}

/*****************************************************************
* Function:    GlobalFindPopupGlobalFind
* Purpose: 	This function is called to set up all variables
before calling the popup function of
global Find
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindPopupGlobalFind(void)
{
	ObjectID active_form_id;
    Textbox  *textbox_ptr;
    BYTE     object_type;
	
#ifdef PCSIM
	return;
#endif 
	
    if (gf_popup == TRUE)
		return;
	
    gf_keyboard_visible = keyboard.keyboard_attr.keyboard_visible;
    keyboard.keyboard_attr.keyboard_visible = TRUE;
    gf_keyboard_status = keyboard_status;
	gf_popup = TRUE;
	gf_num_items = 0;
	
	if (gf_link != NULL)
		GlobalFindDeleteAllItems();
	
	gf_num_items = 0;
	gf_old_event.eventType = NULL_EVENT;
	gf_top_item_num = 0;
	
    gf_menu_status = menu_status;
    gf_popup_status = popup_status;
    gf_old_event = old_event;
    gf_inlay_event = inlay_event;
    old_event.eventType = NULL_EVENT;
    inlay_event.eventType = NULL_EVENT;
	
    FormGetActiveFormID(&active_form_id);
	gf_current_app_id = SysGetActiveAppID();
    gf_current_form_id = active_form_id;
	
    LcdGetBitmap(&gf_current_display_image);  
    
    FormInitAllFormObjects(FORM_GFIND_RESULT);
    FormInitAllFormObjects(FORM_GFIND_INPUT);
	
    FormSetFormActiveObject(FORM_GFIND_INPUT, TEXTBOX_GFIND_INPUT);
    TextboxSetText(TEXTBOX_GFIND_INPUT, gf_previous_search_string);
	
    FormGetObjectPointer(TEXTBOX_GFIND_INPUT, &object_type, (void**)&textbox_ptr);
	
    if (strlen(gf_previous_search_string) > 0)
    {
        textbox_ptr->textbox_attr.textbox_highlight = TRUE;
        textbox_ptr->textbox_highlight_start_char = 0;
        textbox_ptr->textbox_highlight_end_char = strlen(gf_previous_search_string) - 1;
        textbox_ptr->textbox_highlight_length = strlen(gf_previous_search_string);
        TextboxSetInsertPointOff(TEXTBOX_GFIND_INPUT);
        TextboxSetInsertPointPositionByCharPos(TEXTBOX_GFIND_INPUT, 0);
    }
    else
    {
        TextboxSetInsertPointOn(TEXTBOX_GFIND_INPUT);
        TextboxSetInsertPointPositionByCharPos(TEXTBOX_GFIND_INPUT, 0);
        textbox_ptr->textbox_attr.textbox_highlight = FALSE;
    }
    FormPopupForm(FORM_GFIND_INPUT);
}

/*****************************************************************
* Function:	GlobalFindRestoreRunningApp
* Purpose: 	This function is called when global find is popup,
but nothing happens and the original running 
application is required to be restored				
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindRestoreRunningApp(void)
{
	if (gf_popup == FALSE)
		return;
    
    LcdEnableInsertPt(FALSE, 0, 0, SMALL_FONT);		
    gf_popup = FALSE;
	gf_error = GF_NO_ERROR;
	gf_num_items = 0;
	
	if (gf_link != NULL)
		GlobalFindDeleteAllItems();
	
    gf_num_items = 0;
	gf_old_event.eventType = NULL_EVENT;
	gf_top_item_num = 0;
    
    
    LcdDrawBitmap(&gf_current_display_image, FALSE);
    if (gf_current_display_image.bitmap_data)
    {
        qfree(gf_current_display_image.bitmap_data);
        gf_current_display_image.bitmap_data = NULL;
    }
	
    FormSetActiveForm(gf_current_form_id);
    GlobalFindRestorePreviousFormStatus();
    if (gf_keyboard_status)
    {
		EvtAppendEvt(EVT_FORM_LOAD, gf_current_form_id, 0, 0, NULL);
		keyboard_status = TRUE;
		keyboard.keyboard_attr.keyboard_drawn = TRUE;
		KeyboardDrawKeyboardBitmap(keyboard.keyboard_current_bitmap_index);
		EvtAppendEvt(EVT_KEYBOARD_STATUS, 0, 1, 0, NULL);
    }
    else keyboard_status = FALSE;
	
    gf_keyboard_status = FALSE;
    LcdEnableInsertPt(FALSE, 0, 0, SMALL_FONT);
    keyboard.keyboard_attr.keyboard_visible = gf_keyboard_visible;
    gf_keyboard_visible = FALSE;
    EvtAppendEvt(EVT_FORM_ACTIVE, gf_current_form_id, 0, 0, NULL);
}

/*****************************************************************
* Function:	GlobalFindRestoreRunningApp1
* Purpose: 	This function is called when global find is popup,
but nothing happens and the original running 
application is required to be restored				
* Scope:		application/internal
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindRestoreRunningApp1(void)
{
	if (gf_popup == FALSE)
		return;
    gf_popup = FALSE;
	gf_error = GF_NO_ERROR;
	gf_num_items = 0;
	
	if (gf_link != NULL)
		GlobalFindDeleteAllItems();
	
    gf_num_items = 0;
	gf_old_event.eventType = NULL_EVENT;
	gf_top_item_num = 0;               
	
    FormSetActiveForm(gf_current_form_id);
    keyboard_status = FALSE;
    gf_keyboard_status = FALSE;
    LcdEnableInsertPt(FALSE, 0, 0, SMALL_FONT);
    keyboard.keyboard_attr.keyboard_visible = gf_keyboard_visible;
    gf_keyboard_visible = FALSE;
    EvtAppendEvt(EVT_FORM_ACTIVE, gf_current_form_id, 0, 0, NULL);
}

/*****************************************************************
* Function:	GlobalFindSearchData()
* Purpose: 	This function is called to preform the search in all application 				
* Scope:		application/internal
* Input:		search_string
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindSearchData(BYTE *search_string)
{
	AppID		app_id, active_app_id;
	void		(*mainfct)(WORD, void*);
    BYTE        *temp_string, string[100];
    USHORT      total_installed_apps, count;
	USHORT		app_num;
	
#ifdef PR31700
	gf_link = NULL;
	gf_num_items = 0;
	gf_top_item_num = 0;
	temp_string = (BYTE*)pmalloc((strlen(search_string) + 1) * sizeof(BYTE));
	strcpy(temp_string, search_string);
	active_app_id = SysGetActiveAppID();
	
    if(SysGetAppAttribute(active_app_id, BIT_FIND, NULL))
	{
		GlobalFindPrepareAppSeparator(active_app_id);
        mainfct = (void*)0x10000020;
        (*mainfct)(LAUNCH_CMD_FIND, (void*)temp_string);
	}
    total_installed_apps = SysTotalInstalledApp(BIT_FIND);
    
	for (app_num = 0; app_num < total_installed_apps; app_num++)
	{
        app_id  = SysGetAppIDFromIndex(app_num, BIT_FIND);
		if (app_id == active_app_id || app_id == 0xFFFF)
			continue;
		if (gf_error == GF_NO_MEM)
		{
            GlobalFindAddItem(0xFF, 0, 0, 0, SYSTR19, TRUE);
            GlobalFindAddItem(0xFF, 0, 0, 0, SYSTR20, TRUE);
			gf_error = GF_NO_ERROR;
			break;
		}
		GlobalFindPrepareAppSeparator(app_id);
		temp_string = (BYTE*)pmalloc((strlen(search_string) + 1) * sizeof(BYTE));
		strcpy(temp_string, search_string);
        SysRunMode1App(app_id, LAUNCH_CMD_FIND, temp_string);
	}
	
	
    if (total_installed_apps < gf_num_items)
    {
		count =  sprintf((char*)string, "%d", (gf_num_items - total_installed_apps));
		count += sprintf((char*)(string + count), " ");    	
		count += sprintf((char*)(string + count), SYSTR17);
        count += sprintf((char*)(string + count), "%s", search_string);
        count += sprintf((char*)(string + count), "\"");
    }
    else
    {
		count = sprintf((char*)string, SYSTR18);
        count += sprintf((char*)(string + count), "%s", search_string);
        count += sprintf((char*)(string + count), "\"");
    }
    StringSetText(STRING_GFIND_RESULT_MATCH, string);
	
#endif
}

/*****************************************************************
* Function:	GlobalFindPrepareAppSeparator()
* Purpose: 	This function is called to prepare the application
separator that will be displayed in the global
find result
* Scope:		application/internal
* Input:		app_id
* Output:		None
* Return:		None
* Comment: 	None
******************************************************************/
void GlobalFindPrepareAppSeparator(AppID app_id)
{
    BYTE            app_name[20], left_string[200], right_string[200], result_string[200];
	UBYTE		app_name_width; 
	UBYTE		left_width;
	UBYTE		right_width;
	UBYTE		app_name_starting_pt;
    UBYTE           app_name_end_pt;
	UBYTE		temp_width;
	UBYTE		num_chars, temp;
	
#ifdef PR31700
	
   	SysGetAppName(app_id, app_name);
    if (app_id >=1 && app_id <= 16)
    {
		switch(app_name[0])
		{
		case 'C':
			strcpy(app_name, GF_CALCULATOR);
			break;
		case 'T':
			strcpy(app_name, GF_TODOLIST);
			break;
		case 'V':
			strcpy(app_name, GF_VOXMEMO);
			break;
		case 'J':
			strcpy(app_name, GF_JOT);
			break;
		case 'M':
			if (app_name[1] == 'e')
				strcpy(app_name, GF_MEMO);
			else
				strcpy(app_name, GF_MAINMENU);
			break;
		case 'S':
			if (app_name[1] == 'c')
				strcpy(app_name, GF_SCHEDULER);
			else if (app_name[1] == 'k')
				strcpy(app_name, GF_SKETCH);
			else
				strcpy(app_name, GF_SYSETUP);
			break;
		case 'A':
			if (app_name[1] == 'l')
				strcpy(app_name, GF_ALARMGR);
			else
				strcpy(app_name, GF_ANN);
			break;
		case 'P':
			if (app_name[1] == 'C')
				strcpy(app_name, GF_PC_SYNC);
			else if (app_name[1] == 'a')
				strcpy(app_name, GF_PASSWORD);
			else
				strcpy(app_name, GF_PHONEBOOK);
			break;
		case 'E':
			if (app_name[1] == 'm')
				strcpy(app_name, GF_EMAIL);
			else
				strcpy(app_name, GF_EXPENSE);
			break;
		}	
    }
	app_name_width			= StrGetWidth(app_name, SMALL_FONT);
	app_name_starting_pt	= (140 - app_name_width) / 2;
	app_name_end_pt			= (140 + app_name_width) / 2;	
	
	left_width				= app_name_starting_pt - 5;
	right_width				= 140 - (app_name_end_pt + 5);
	
	temp_width = 0;
	num_chars = 0;	
	while (1)
	{
        num_chars += sprintf((char*)(left_string + num_chars), "%s", (char*)("-"));
        temp_width = StrGetWidth(left_string, SMALL_FONT);
		if (temp_width >= left_width)
		{
			left_string[strlen(left_string) - 1] = 0;
			left_width = StrGetWidth(left_string, SMALL_FONT);
            break;
		}
		
	}
	temp_width = 0;
	num_chars = 0;
	while (1)
	{
        num_chars += sprintf((char*)(right_string + num_chars), "%s", (char*)("-"));
        temp_width = StrGetWidth(right_string, SMALL_FONT);
		if (temp_width >= right_width)
		{
			right_string[strlen(right_string) - 1] = 0;
			right_width = StrGetWidth(right_string, SMALL_FONT);
			break;
		}
	}
	
	num_chars = sprintf((char*)result_string, "%s", (char*)left_string);
	temp = strlen(result_string);
	result_string[temp] = 11;
	result_string[temp + 1] = app_name_starting_pt - left_width;
	result_string[temp + 2] = 0;
    num_chars += sprintf((char*)(result_string + num_chars + 2), "%s", (char*)app_name);
	temp = strlen(result_string);
	result_string[temp] = 11;
	result_string[temp + 1] = 140 - right_width - app_name_end_pt;
	result_string[temp + 2] = 0;
	
    num_chars += sprintf((char*)(result_string + num_chars + 4), "%s", (char*)right_string);
	GlobalFindAddItem(0xFF, 0, 0, 0, result_string, TRUE);
#endif
}

/*****************************************************************
* Function:    GlobalFindPrepareGotoRecCmd
* Purpose:     This function is called to prepare the
(GotoRec*)cmd_ptr to launch the corresponding record
* Scope:		application/internal
* Input:       clicked_string_id
* Output:      cmd_ptr
* Return:          None
* Comment: 	None
******************************************************************/
void GlobalFindPrepareGotoRecCmd(ObjectID clicked_string_id, void **cmd_ptr)
{
	GFindResultBlock       *temp;
	USHORT                 abs_value, count = 0;
	BYTE                   *search_string;
	
	TextboxGetTextPointer(TEXTBOX_GFIND_INPUT, &search_string);
	abs_value = gf_top_item_num + (USHORT)(clicked_string_id - STRING_GFIND_RESULT_0);
	
	(*cmd_ptr) = (GotoRec*)pmalloc(sizeof(GotoRec));
	
	temp = gf_link;
	count = 0;
    while ((temp != NULL) && (count <= abs_value))
	{
		if (count == abs_value)
			break;
		temp = temp->next;
		count ++;
	} 
	
	((GotoRec*)(*cmd_ptr))->app_id = temp->app_id;
	((GotoRec*)(*cmd_ptr))->dbid = temp->dbid;
	((GotoRec*)(*cmd_ptr))->rec_id = temp->rec_id;
	((GotoRec*)(*cmd_ptr))->field_num = temp->field_num;
	((GotoRec*)(*cmd_ptr))->find_string = (BYTE*)pmalloc((strlen(search_string) + 1) * sizeof(BYTE));
	strcpy(((GotoRec*)(*cmd_ptr))->find_string, search_string);
}

/********************************************************
* Function:    GlobalFindRestorePreviousFormStatus
* Purpose:     This function is called to restore previous active form status
* Scope:		application/internal
* Input:       None
* Output:		None
* Return:      None
* Comment: 	None
*********************************************************/
void GlobalFindRestorePreviousFormStatus()
{
    ObjectID    menu_id, active_object_id;
    BYTE        object_type, temp_undo_action;
    Menu        *menu_ptr;
    Control     *control_ptr;
    USHORT      num_of_objects, count;
    Form        *form_ptr;
    Field       *field_ptr;
    Textbox     *textbox_ptr;
    void        *addr;
	
    menu_status = FALSE;
    popup_status = FALSE;
    old_event = gf_old_event;
    inlay_event = gf_inlay_event;
	
    if (gf_menu_status == TRUE)
    {
		gf_menu_status = FALSE;
        FormGetMenuID(gf_current_form_id, &menu_id);
        FormGetObjectPointer(menu_id, &object_type, (void**)&menu_ptr);
        if (menu_ptr->menu_attr.menu_drawn == TRUE)
            MenuRestoreBehindBits(menu_id);
        menu_ptr->menu_attr.menu_drawn = FALSE;
        old_event.eventType = NULL_EVENT;
        temp_undo_action = undo_action;
        FormObjectRestoreFocus();
        undo_action = temp_undo_action;
    }
	
    if (gf_popup_status == TRUE)
    {
        gf_popup_status = FALSE;
        FormGetObjectPointer(old_event.eventID, &object_type, (void**)&addr);
        if (object_type == CONTROL)
        {
            if (((Control*)addr)->control_style == POPUP_TRIGGER &&
                ((ControlTemplatePopupTrigger*)(((Control*)addr)->control_template))->control_value == TRUE)
            {
                ((ControlTemplatePopupTrigger*)(((Control*)addr)->control_template))->control_value = FALSE;
                popup_status = FALSE;
                ((Control*)addr)->control_attr.control_enter = FALSE;
				
                ControlRestoreBitBehind(old_event.eventID);
                FormObjectRestoreFocus();
                old_event.eventType = NULL_EVENT;
            }
        }
    }
	
    FormGetObjectPointer(gf_current_form_id, &object_type, (void**)&form_ptr);
    num_of_objects = form_ptr->form_num_objects;
	
    FormGetActiveObject(gf_current_form_id, &active_object_id);
    for (count = 0; count < num_of_objects; count++)
    {
        if (form_ptr->form_objects_list[count].object_id == active_object_id)
        {
            FormGetObjectPointer(active_object_id, &object_type, (void**)&addr);
            if (form_ptr->form_objects_list[count].object_type == FIELD)
            {
                if (((Field*)addr)->field_attr.field_insert_pt_visible == TRUE &&
                    ((Field*)addr)->field_attr.field_drawn == TRUE)                    
                    FieldDrawField(form_ptr->form_objects_list[count].object_id);
                break;
            }
            else if (form_ptr->form_objects_list[count].object_type == TEXTBOX)
            {
                if (((Textbox*)addr)->textbox_attr.textbox_insert_pt_visible == TRUE &&
                    ((Textbox*)addr)->textbox_attr.textbox_drawn == TRUE)                    
                    TextboxDrawTextbox(form_ptr->form_objects_list[count].object_id);
                break;
            }
        }
    }
    old_event.eventType     = NULL_EVENT;
    inlay_event.eventType   = NULL_EVENT;
}

/*****************************************************************
/*****************************************************************
***************** Application Event Handle Function **************
******************************************************************
*****************************************************************/
/********************************************************
* Function:	GlobalFindInput
* Purpose: 	This function is called to handle the events on
FORM_GFIND_INPUT
* Scope:		application/internal
* Input:		Event		received event
* Output:		None
* Return:		TRUE if handled
FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN GlobalFindInput(EvtType* Event)
{
	BYTE        *string;
	AppID       app_id;
	
	if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
	{
        if ((Event->para2 & 0x00000200))      
		{
			if (Event->para1 == LLETTER_PROCEED || Event->para1 == SLETTER_PROCEED)
			{
				Event->eventType    = EVT_CONTROL_SELECT;
                Event->eventID      = BUTTON_GFIND_INPUT_PROCEED;
                Event->evtPBP       = NULL;
            }
            else if (Event->para1 == LLETTER_CANCEL || Event->para1 == LLETTER_CANCEL)
            {
				Event->eventType    = EVT_CONTROL_SELECT;
                Event->eventID      = BUTTON_GFIND_INPUT_CANCEL;
                Event->evtPBP       = NULL;
            }            	            
        }       
    }                    
	
	
	
	switch (Event->eventType)
	{
	case EVT_KEYBOARD_STATUS:
		return TRUE;
	case EVT_KEY:	
		if (Event->eventID == SOFT_KEY)		
		{
			if (((UBYTE)(Event->para1) >= 32 && (UBYTE)(Event->para1) <= 255) ||
				(UBYTE)(Event->para1) == 9)
			{                   
				TextboxAddKeyInChar(TEXTBOX_GFIND_INPUT, (BYTE)(Event->para1));
				return TRUE;
			}
			else if ((UBYTE)(Event->para1) == '\r' || (UBYTE)(Event->para1) == '\n')
			{
				TextboxGetTextPointer(TEXTBOX_GFIND_INPUT, &string);
				if (strlen(string) == 0)
				{
					GlobalFindRestoreRunningApp();
					return TRUE;
				}
				strcpy(gf_previous_search_string, string);
				GlobalFindSearchData(string);
				keyboard_status = FALSE;
				FormPopupForm(FORM_GFIND_RESULT);
				return TRUE;
			}
		}
		return FALSE;
	case EVT_CONTROL_SELECT:
		if (Event->eventID == BUTTON_GFIND_INPUT_PROCEED)
		{	
			SndPlaySndEffect(SNDRES5_BEEP);
			TextboxGetTextPointer(TEXTBOX_GFIND_INPUT, &string);
			if (strlen(string) == 0)
			{
				GlobalFindRestoreRunningApp();
				return TRUE;
			}
			strcpy(gf_previous_search_string, string);
			GlobalFindSearchData(string);
			keyboard_status = FALSE;
			FormPopupForm(FORM_GFIND_RESULT);
			return TRUE;
		}
		else if (Event->eventID == BUTTON_GFIND_INPUT_CANCEL)
		{
			SndPlaySndEffect(SNDRES5_BEEP);
			GlobalFindRestoreRunningApp();
			return TRUE;
		}
		return TRUE;
	case EVT_INLAY_SELECT:
		if (Event->para1 == INLAY_OK)
		{
			TextboxGetTextPointer(TEXTBOX_GFIND_INPUT, &string);
			if (strlen(string) == 0)
			{
				GlobalFindRestoreRunningApp();
				return TRUE;
			}
			
			strcpy(gf_previous_search_string, string);
			GlobalFindSearchData(string);
			keyboard_status = FALSE;
			FormPopupForm(FORM_GFIND_RESULT);
			return TRUE;
		}
		else if (Event->para1 == INLAY_EXIT)
		{
			GlobalFindRestoreRunningApp();
			return TRUE;
		}
		return FALSE;
	case EVT_FORM_OPEN:
		FormDrawForm(FORM_GFIND_INPUT);
		return TRUE;
	case EVT_APP_STOP:            
		if (gf_popup)
		{
			if (gf_current_display_image.bitmap_data != NULL)
			{
				Event->para1    = FROM_SYSTEM_DIALOG;
				Event->evtPBP   = &gf_current_display_image;
			}
			else
			{                    
				Event->para1    = 0;
				Event->evtPBP   = NULL;
			}
			
		}                    
		GlobalFindRestoreRunningApp1();
		return FALSE;		                
	default: return FALSE;
	}
	return FALSE;
}


/********************************************************
* Function:	GlobalFindResult
* Purpose: 	This function is called to handle the events on
FORM_GFIND_RESULT
* Scope:		application/internal
* Input:		Event		received event
* Output:		None
* Return:		TRUE if handled
FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN GlobalFindResult(EvtType *Event)
{
	ObjectID        object_id;
	void            *cmd_ptr;
	AppID           app_id = 0xFFFF;
	BOOLEAN         app_name_found = FALSE;
	
	
	if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
	{
        if ((Event->para2 & 0x00000200))
		{
			if (Event->para1 == LLETTER_CANCEL || Event->para1 == SLETTER_CANCEL)
			{
				Event->eventType    = EVT_CONTROL_SELECT;
                Event->eventID      = 0;
                Event->evtPBP       = NULL;
            }
            else if (Event->para2 == 0x215 || Event->para2 == 0x21c)
            {           
                ScrollbarHardButtonSetScrollbar(SCROLLBAR_GFIND_RESULT, SCROLLBAR_UP_ARROW);            
                return TRUE;            
            }
            else if (Event->para2 == 0x216 || Event->para2 == 0x21d)
            {           
                ScrollbarHardButtonSetScrollbar(SCROLLBAR_GFIND_RESULT, SCROLLBAR_DOWN_ARROW);            
                return TRUE;            
            }                    
        }       
    }                    
	
	
	switch (Event->eventType)
	{
	case EVT_KEYBOARD_STATUS:
		return TRUE;
#ifdef PR31700
	case EVT_IO_KEY_CTRL:
		if (Event->eventID == EVT_IO_KEY_PRESS || Event->eventID == EVT_IO_KEY_REPEAT)
		{
			if (Event->para2 == IO_UP_ARROW)
				ScrollbarHardButtonSetScrollbar(SCROLLBAR_GFIND_RESULT, SCROLLBAR_UP_ARROW);
			else if (Event->para2 == IO_DOWN_ARROW)
				ScrollbarHardButtonSetScrollbar(SCROLLBAR_GFIND_RESULT, SCROLLBAR_DOWN_ARROW);
			return TRUE;
		}
		return FALSE;
#endif
	case EVT_SCROLLBAR_SELECT:
		GlobalFindScrollbarSetTable(Event);
		return TRUE;
	case EVT_SCROLLBAR_REPEAT:
		GlobalFindScrollbarSetTable(Event);
		return FALSE;
	case PEN_EVENT:
		if (GlobalFindStringHandleEvent(Event))
			return TRUE;
		return FALSE;
	case EVT_GFIND_STRING_ENTER:
		if (GlobalFindStringHandleEvent(Event))
			return TRUE;
		return FALSE;
	case EVT_GFIND_STRING_EXIT:
		if (GlobalFindStringHandleEvent(Event))
			return TRUE;
		return FALSE;
	case EVT_GFIND_STRING_SELECT:
		GlobalFindPrepareGotoRecCmd((ObjectID)(Event->eventID), &cmd_ptr);               
		GlobalFindRestoreRunningApp1();            
		EvtAppendEvt(EVT_APP_STOP, (WORD)(SysGetActiveAppID()), FROM_SYSTEM_DIALOG, 0, &gf_current_display_image);                
		EvtAppendEvt(EVT_APP_LAUNCH, ((GotoRec*)cmd_ptr)->app_id, LAUNCH_CMD_GOTO_REC, 0, cmd_ptr);                
		return TRUE;
	case EVT_CONTROL_SELECT:
		SndPlaySndEffect(SNDRES5_BEEP);
		GlobalFindRestoreRunningApp();
		return TRUE;
	case EVT_INLAY_SELECT:
		if (Event->para1 == INLAY_OK || Event->para1 == INLAY_EXIT)
			GlobalFindRestoreRunningApp();
		return TRUE;
	case EVT_FORM_OPEN:
		GlobalFindPutDataToTable();
		GlobalFindSetupScrollbar();
		FormDrawForm(FORM_GFIND_RESULT);
		FormGetActiveFormID(&object_id);
		return TRUE;
	case EVT_APP_STOP:            
		if (gf_popup)
		{
			if (gf_current_display_image.bitmap_data != NULL)
			{
				Event->para1    = FROM_SYSTEM_DIALOG;
				Event->evtPBP   = &gf_current_display_image;
			}                    
			else
			{
				Event->para1    = 0;
				Event->evtPBP   = NULL;
			}                                    
		}                    
		GlobalFindRestoreRunningApp1();
		return FALSE;		    
	default: return FALSE;
	}
    return FALSE;
}

