/*
================================ 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        :   jotmacdb.c
Author(s)   :   J. Wang
Company     :   Communication Intelligence Corporation
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   application c file
Revision    :   1.1
Note        :   None
===========================================================================
*/              

#include <stdafx.h>
#include "mmu.h"
#include "ui.h"
#include "uifunc.h"
#include "app.h"
#include "jot.h"
#include "jotui.h"
#include "jotlang.h"

#ifdef PR31700
#include "ioconmsg.h"
#endif

extern JOT_STATUS jot_status;

DatabaseID	g_dbID = (DatabaseID)NULL;
int			g_editMacro = -1;
short		g_deleteMacro = -1;
BYTE        *g_deleteMacroName = NULL;
BOOLEAN		g_macroEditted = FALSE;
BYTE        g_macroName[MAX_MACRO_NAME_LEN+1];
BYTE		g_macroText[MAX_MACRO_TEXT_LEN+1];
BOOLEAN		g_keyboardON = FALSE;
BOOLEAN     g_modified = FALSE;

/* Globals used by WARNING dialog */
ObjectID	g_prevForm;	// Form before the popup warning message
BYTE		*g_warningMessage;

/* Globals used by OKCANCEL dialog */
BYTE		*g_okcancelString1;
BYTE		*g_okcancelString2;
BOOLEAN     g_okcancel;
BYTE		*g_okcancelTitle;
USHORT		g_okForm;
USHORT		g_cancelForm;
BOOLEAN		g_fromOkCancel;
int			g_askReason;
BYTE		g_lastChar;
BYTE		g_lastNotChar;

#define CONFLICT_WITH_SYMBOL	1
#define DELETE_MACRO			2
#define EXIT_WITHOUT_SAVE		3

#define TEXT(x) (x)

#define	EXTENDEDCHARLISTSIZE	73
static char	*ExtendedCharacterList[EXTENDEDCHARLISTSIZE][2] =
{
	{TEXT("ao"),TEXT(JOTSTR25)},
	{TEXT("oa"),TEXT(JOTSTR26)},
	{TEXT("olo"),TEXT(JOTSTR27)},
	{TEXT("ulo"),TEXT(JOTSTR28)},
	{TEXT("olu"),TEXT(JOTSTR29)},
	{TEXT("ulu"),TEXT(JOTSTR30)},
	{TEXT("ool"),TEXT(JOTSTR31)},
	{TEXT("uol"),TEXT(JOTSTR32)},
	{TEXT("oul"),TEXT(JOTSTR33)},
	{TEXT("uul"),TEXT(JOTSTR34)},
	{TEXT("loo"),TEXT(JOTSTR35)},
	{TEXT("luo"),TEXT(JOTSTR36)},
	{TEXT("lou"),TEXT(JOTSTR37)},
	{TEXT("luu"),TEXT(JOTSTR38)},
	{TEXT("ro"),TEXT(JOTSTR39)},
	{TEXT("or"),TEXT(JOTSTR40)},
	{TEXT("co"),TEXT(JOTSTR41)},
	{TEXT("oc"),TEXT(JOTSTR42)},
	{TEXT("ss"),TEXT(JOTSTR43)},
	{TEXT("cl"),TEXT(JOTSTR44)},
	{TEXT("lc"),TEXT(JOTSTR45)},
	{TEXT("m"),TEXT(JOTSTR46)},
	{TEXT("ol"),TEXT(JOTSTR47)},
	{TEXT("oll"),TEXT(JOTSTR48)},
	{TEXT("ae"),TEXT(JOTSTR49)},
	{TEXT("ael"),TEXT(JOTSTR50)},
	{TEXT("o"),TEXT(JOTSTR51)},
	{TEXT("cll"),TEXT(JOTSTR52)},
	{TEXT("l"),TEXT(JOTSTR53)},
	{TEXT("ll"),TEXT(JOTSTR54)},
	{TEXT("c"),TEXT(JOTSTR55)},
	{TEXT("j"),TEXT(JOTSTR56)},
	{TEXT("p"),TEXT(JOTSTR57)},
	{TEXT("pl"),TEXT(JOTSTR58)},
	{TEXT("jl"),TEXT(JOTSTR59)},
	{TEXT("n"),TEXT(JOTSTR60)},
	{TEXT("sl"),TEXT(JOTSTR61)},
	{TEXT("ls"),TEXT(JOTSTR62)},
	{TEXT("sll"),TEXT(JOTSTR63)},
	{TEXT("lls"),TEXT(JOTSTR64)},
	{TEXT("el"),TEXT(JOTSTR65)},
	{TEXT("le"),TEXT(JOTSTR66)},
	{TEXT("cj"),TEXT(JOTSTR67)},
	{TEXT("cjl"),TEXT(JOTSTR68)},
	{TEXT("tm"),TEXT(JOTSTR69)},
	{TEXT("f"),TEXT(JOTSTR70)},
	{TEXT("sv"),TEXT(JOTSTR71)},
	{TEXT("oioo"),TEXT(JOTSTR72)},
	{TEXT("uioo"),TEXT(JOTSTR73)},
	{TEXT("oiuo"),TEXT(JOTSTR74)},
	{TEXT("oiou"),TEXT(JOTSTR75)},
	{TEXT("uiuo"),TEXT(JOTSTR76)},
	{TEXT("uiou"),TEXT(JOTSTR77)},
	{TEXT("oiuu"),TEXT(JOTSTR78)},
	{TEXT("uiuu"),TEXT(JOTSTR79)},
	{TEXT("iooo"),TEXT(JOTSTR80)},
	{TEXT("iuoo"),TEXT(JOTSTR81)},
	{TEXT("iouo"),TEXT(JOTSTR82)},
	{TEXT("ioou"),TEXT(JOTSTR83)},
	{TEXT("iouu"),TEXT(JOTSTR84)},
	{TEXT("iuou"),TEXT(JOTSTR85)},
	{TEXT("iuuo"),TEXT(JOTSTR86)},
	{TEXT("iuuu"),TEXT(JOTSTR87)},
	{TEXT("oe"),TEXT(JOTSTR88)},
	{TEXT("a"),TEXT(JOTSTR89)},
	{TEXT("b"),TEXT(JOTSTR90)},
	{TEXT("q"),TEXT(JOTSTR91)},
	{TEXT("om"),TEXT(JOTSTR92)},
	{TEXT("z"),TEXT(JOTSTR93)},
	{TEXT("si"),TEXT(JOTSTR94)},
	{TEXT("in"),TEXT(JOTSTR95)},
	{TEXT("pi"),TEXT(JOTSTR96)},
	{TEXT("nn"),TEXT(JOTSTR97)},
};

BOOLEAN OpenJotMacroDB()
{
	if (DataFindDB(JOT_MACRO_DB_NAME, &g_dbID) != TRUE)
		if (DataNewDB(JOT_MACRO_DB_NAME, JOT_MACRO_DB_VERSION,
			JOT_MACRO_DB_INFO, &g_dbID) != TRUE)
			return FALSE;
		
		if (DataOpenDB(g_dbID, 0, OPEN_RW) != TRUE)
			return FALSE; 
		return TRUE;
}

BOOLEAN CloseJotMacroDB()
{
	return (BOOLEAN)DataCloseDB(g_dbID);
}

WORD DataFindExactRecord(BYTE *MacroName)
{
	USHORT 		NumItems;
	USHORT		Count;
	BYTE		*ListText;
	
	ListGetTotalItems(LIST_MACRO_NAME1, &NumItems);
	
	for (Count = 0; Count< NumItems; Count ++)
	{
		ListGetListItem(LIST_MACRO_NAME1, Count, &ListText);	
		if (strcmp(ListText, MacroName) == 0)
			return Count;
	}
	return -1;					
}

BOOLEAN AddJotMacro(BYTE *macroName, BYTE *macroText)
{
	RecordID recID;
	
	if (DataNewRecord(g_dbID, 0, 2, &recID) != TRUE)
		return FALSE;
	
	if (DataWriteField(g_dbID, recID, 0, strlen((char *)macroName)+1, macroName) != TRUE)
		return FALSE;
	
	if (DataWriteField(g_dbID, recID, 1, strlen((char *)macroText)+1, macroText) != TRUE)
		return FALSE;
	DataCloseRecord(g_dbID, recID);
	
	return TRUE;
}

BOOLEAN DeleteJotMacro(BYTE *macroName)
{
	RecordID recordID;
	
	//	if (DataFindExactRecord(macroName, &recordID) != TRUE)
	//		return FALSE;
	if (DataFindRecord(g_dbID, 0, 0, macroName, &recordID) != TRUE)
		return FALSE;
	
	if (DataDeleteRecord(g_dbID, recordID, FALSE) != TRUE)
		return FALSE;
	return TRUE;
}

BOOLEAN ChangeJotMacro(BYTE *macroName, BYTE *macroText)
{
	DeleteJotMacro(macroName);
	return AddJotMacro(macroName, macroText);
}

int GetJotMacroNum()
{
	UWORD totalRec;
	
	if (DataTotalRecord(g_dbID, &totalRec) != TRUE)
		return 0;
	return totalRec;
}

BOOLEAN GetJotMacro(int index)
{
	RecordID recID;
	UWORD macroNameLen;
	BYTE *macroName;
	UWORD macroTextLen;
	BYTE *macroText;
	
	macroName = NULL;
	macroText = NULL;
	
	if (DataOpenRecord(g_dbID, index, &recID, NULL) != TRUE)
		return FALSE;
	
	if (DataGetField(g_dbID, recID, 0, &macroName, &macroNameLen) != TRUE)
		goto ERROR_RETURN;
	
	if (DataGetField(g_dbID, recID, 1, &macroText, &macroTextLen) != TRUE)
		goto ERROR_RETURN;
	
	strcpy((char *)g_macroName, (char *)macroName);
	strcpy((char *)g_macroText, (char *)macroText);
	qfree((void *)macroName);
	qfree((void *)macroText);
	DataCloseRecord(g_dbID, recID);
	return TRUE;
	
ERROR_RETURN:
	DataCloseRecord(g_dbID, recID);
	if (macroName)
		qfree((void *)macroName);
	if (macroText)
		qfree((void *)macroText);
	return FALSE;
}

void SetMacrosInList(ObjectID listName, ObjectID listText)
{
	int numMacros;
	int i;
	USHORT numItems;
	
	ListGetTotalItems(listName, &numItems);
	for (i = numItems - 1; i >= 0; i--)
		ListDeleteItem(listName, i);
	
	ListGetTotalItems(listText, &numItems);
	for (i = numItems - 1; i >= 0; i--)
		ListDeleteItem(listText, i);
	
	numMacros = GetJotMacroNum();
	for (i = 0; i < numMacros; i++)
	{
		if (GetJotMacro(i))
		{
			ListInsertItem(listName, i, g_macroName);
			ListInsertItem(listText, i, g_macroText);			
		}
	}
	ListSetSelectedItem(listName, NO_SELECTION);
	ListSetSelectedItem(listText, NO_SELECTION);
	
	if (listName == LIST_MACRO_NAME)
	{
		ScrollbarSetScrollbar(
			SCROLLBAR_MACRO,
			0,
			numMacros - 9, 0, 9, numMacros);	
		if (numMacros <= 9)
			ScrollbarSetScrollbarVisible(SCROLLBAR_MACRO, FALSE);
		else
			ScrollbarSetScrollbarVisible(SCROLLBAR_MACRO, TRUE);
		ScrollbarSetScrollbarDrawPagesize(SCROLLBAR_MACRO, 9);
		ScrollbarDrawScrollbar(SCROLLBAR_MACRO);
	}
	else if (listName == LIST_MACRO_NAME1)
	{
		ScrollbarSetScrollbar(
			SCROLLBAR_JOT_MACRO,
			0,
			numMacros - 10, 0, 10, numMacros);	
		if (numMacros <= 10)
			ScrollbarSetScrollbarVisible(SCROLLBAR_JOT_MACRO, FALSE);
		else
			ScrollbarSetScrollbarVisible(SCROLLBAR_JOT_MACRO, TRUE);
		ScrollbarSetScrollbarDrawPagesize(SCROLLBAR_JOT_MACRO, 10);
		ScrollbarDrawScrollbar(SCROLLBAR_JOT_MACRO);
	}
}

/********************************************************
* Function:	MacroEditorHandleEvent
* Purpose: 	This function is the event handler for the
*				Jot Macro Editor
* Scope:		application/internal
* Input:		Event		received event
* Output:		None
* Return:		TRUE if handled
FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN MacroEditorHandleEvent(EvtType *Event)
{
	short selected;
	BOOLEAN handled = FALSE;
	BYTE	*text;
	static USHORT macroPos = 0;
	USHORT   numItems;
	
	if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
	{
		if (Event->para2 & 0x00000200)
		{
			if (Event->para1 == KEY_UP)
			{
				Event->eventType = EVT_IO_KEY_CTRL;
				Event->eventID = EVT_IO_KEY_PRESS;
				Event->para2 = IO_UP_ARROW;
			}
			else if (Event->para1 == KEY_DOWN)
			{
				Event->eventType = EVT_IO_KEY_CTRL;
				Event->eventID = EVT_IO_KEY_PRESS;
				Event->para2 = IO_DOWN_ARROW;
			}
			else if (Event->para1 == LLETTER_NEW || Event->para1 == SLETTER_NEW)
			{
				Event->eventType = EVT_CONTROL_SELECT;
				Event->eventID = BUTTON_JOT_MACROEDITOR_NEW;
			}
		}
	}
	
	switch (Event->eventType)
	{
	case EVT_INLAY_SELECT:
		if ((Event->para1 == INLAY_OK) || (Event->para1 == INLAY_EXIT))
			FormPopupForm(FORM_JOT);
		break;
	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_JOT_MACRO, SCROLLBAR_UP_ARROW);
			else if (Event->para2 == IO_DOWN_ARROW)
				ScrollbarHardButtonSetScrollbar(SCROLLBAR_JOT_MACRO, SCROLLBAR_DOWN_ARROW);
			return TRUE;
		}
		break;
	case EVT_SCROLLBAR_SELECT:
	case EVT_SCROLLBAR_REPEAT:
		{
			WORD value, max, min, pagesize, total;
			
			ListGetTotalItems(LIST_MACRO_NAME1, &numItems);
			if (Event->para2 >= 0 && Event->para2 < numItems)
			{
				macroPos = Event->para2;
				ListSetTopItemNum(LIST_MACRO_NAME1, macroPos);
				ListSetTopItemNum(LIST_MACRO_TEXT1, macroPos);
				ListDrawList(LIST_MACRO_NAME1);
				ListDrawList(LIST_MACRO_TEXT1);
			}
			ScrollbarGetScrollbar(SCROLLBAR_JOT_MACRO, &value, &max, &min, &pagesize, &total);
			ScrollbarSetScrollbar(SCROLLBAR_JOT_MACRO, Event->para2, max, min, pagesize, total);
			ScrollbarDrawScrollbar(SCROLLBAR_JOT_MACRO);
		}
		break;
	case EVT_LIST_SELECT:
		selected = Event->para1;
		if (selected != NO_SELECTION)
		{
			g_editMacro = selected;
			g_modified = FALSE;
			ListGetListItem(LIST_MACRO_NAME1, g_editMacro, &text);
			strcpy(g_macroName, text);
			ListGetListItem(LIST_MACRO_TEXT1, g_editMacro, &text);
			strcpy(g_macroText, text);
			g_keyboardON = FALSE;
			FormPopupForm(FORM_JOT_NEWMACRO);
		}
		break;
	case EVT_CONTROL_SELECT:
		{
			switch (Event->eventID)
			{
			case BUTTON_JOT_MACROEDITOR_NEW:
				g_editMacro = -1;
				g_deleteMacro = -1;
				g_macroName[0] = 0;
				g_macroText[0] = 0;
				g_keyboardON = FALSE;
				FormPopupForm(FORM_JOT_NEWMACRO);
				break;
			}
		}
		handled = TRUE;
		break;
	case EVT_FORM_OPEN:
		g_prevForm = FORM_MACRO_EDITOR;
		if (g_fromOkCancel && g_deleteMacro >= 0 && g_okcancel && g_askReason == DELETE_MACRO)
		{
			DeleteJotMacro(g_macroName);
			g_deleteMacro = -1;
			g_fromOkCancel = FALSE;
		}
		SetMacrosInList(LIST_MACRO_NAME1, LIST_MACRO_TEXT1);
		g_macroEditted = FALSE;
		FormDrawForm(FORM_MACRO_EDITOR);
		handled = TRUE;
		break;
	case EVT_FORM_CLOSE:
		break;
	}
	return handled;
	}
	
	void SaveMacro(char *macroName, char *macroText)
	{
		char *text;
		
		ChangeJotMacro(macroName, macroText);
		text = (BYTE *)"";
		TextboxSetText(TEXTBOX_JOT_MACRO_NAME, text);
		FieldSetText(FIELD_JOT_MACRO_TEXT, text);
		FormPopupForm(FORM_MACRO_EDITOR);
	}
	
	void ScrollbarSetBounds(ObjectID id, ObjectBounds rect)
	{
		Scrollbar *scroll;
		BYTE object_type;
		
		FormGetObjectPointer(id, &object_type, (void**)&scroll);
		scroll->bounds = rect;
	}
	
	void SetMyScrollbar()
	{
		WORD min, max, value, pagesize, total, displayed;
		
		FieldGetTotalNumOfLines(FIELD_JOT_MACRO_TEXT, &total);
		FieldGetMaxNumLinesDisplay(FIELD_JOT_MACRO_TEXT, &pagesize);
		FieldGetTopLineNum(FIELD_JOT_MACRO_TEXT, &value);
		min = 0;
		max = total - pagesize;
		
		if (total > pagesize)
		{
			ScrollbarSetScrollbarVisible(SCROLLBAR_NEWMACRO, TRUE);
			ScrollbarSetScrollbar(SCROLLBAR_NEWMACRO, value, max, min, pagesize, total);
			ScrollbarSetScrollbarDrawPagesize(SCROLLBAR_NEWMACRO, pagesize);
		}
		else
		{
			ScrollbarSetScrollbarVisible(SCROLLBAR_NEWMACRO, FALSE);
		}
		ScrollbarEraseScrollbar(SCROLLBAR_NEWMACRO);
		ScrollbarDrawScrollbar(SCROLLBAR_NEWMACRO);
	}
	
	void JotSetField()
	{
		ObjectBounds	rect;
		ObjectID		objID;
		BYTE			object_type, font_id;
		Field			*field;
		BOOLEAN			insert_pt_on = FALSE;
		BOOLEAN			highlight_pt_on = FALSE;
		WORD			ins_pos, first_visible_char, last_visible_char;
		WORD			pagesize, total, ins_line, temp;
		SHORT			line_height;
		
		g_keyboardON = KeyboardCheckKeyboardStatus();
		if (g_keyboardON)
		{
			rect.xcoord = 5;
			rect.ycoord = 60;
			rect.width = 140;
			rect.height = 39;
			FieldSetBounds(FIELD_JOT_MACRO_TEXT, rect);
			rect.xcoord = 145;
			rect.ycoord = 60;
			rect.width = 9;
			rect.height = 39;
			ScrollbarSetBounds(SCROLLBAR_NEWMACRO, rect);
			FormGetActiveObject(FORM_JOT_NEWMACRO, &objID);
			if (objID == FIELD_JOT_MACRO_TEXT)
			{
				UISearchForAddress(FIELD_JOT_MACRO_TEXT,&object_type,(void**)&field);
				
				insert_pt_on = field->field_attr.field_insert_pt_visible;
				highlight_pt_on = field->field_attr.field_highlight;
				
				FieldGetInsertPointPosition(FIELD_JOT_MACRO_TEXT, &ins_pos);
				FieldGetFirstVisibleChar(FIELD_JOT_MACRO_TEXT, &first_visible_char);
				FieldGetLastVisibleChar(FIELD_JOT_MACRO_TEXT, &last_visible_char);
				FieldGetFont(FIELD_JOT_MACRO_TEXT, &font_id);
				line_height = SysGetFontHeight(font_id) + SPACE_LINE;
				
				if (insert_pt_on)
				{
					if (ins_pos >= 0)
					{
						FieldGetTotalNumOfLines(FIELD_JOT_MACRO_TEXT, &total);
						FieldGetMaxNumLinesDisplay(FIELD_JOT_MACRO_TEXT, &pagesize);
						ins_line = 0;
						FieldCharPosToLineNum(field, ins_pos, &ins_line);
						if ((ins_line - (field->bounds.height/(line_height)) + 1) < 0)
							FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
						else
							FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, ins_line - (field->bounds.height/(line_height)) + 1);
						FieldSetInsertPointPositionByCharPos(FIELD_JOT_MACRO_TEXT, ins_pos);
					}
					else
						FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
				}
				else
				{
					temp = field->field_highlight_start_char;
					if (temp < field->field_highlight_end_char)
						temp = field->field_highlight_end_char;
					if (temp >= last_visible_char)
					{
						FieldCharPosToLineNum(field, temp, &ins_line);
						if ((ins_line - (field->bounds.height/(line_height)) + 1) < 0)
							FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
						else
							FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, ins_line - (field->bounds.height/(line_height)) + 1);
					}
					else
					{
						FieldGetNumOfChars(FIELD_JOT_MACRO_TEXT, &temp);
						FieldCharPosToLineNum(field, temp, &ins_line);
						if ((field->field_top_line_num + (field->bounds.height/(line_height))) >= ins_line)
							if ((ins_line - (field->bounds.height/(line_height)) + 1) < 0)
								FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
							else
								FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, ins_line - (field->bounds.height/(line_height)) + 1);
					}
				}
			}
			FieldDrawField(FIELD_JOT_MACRO_TEXT);
			SetMyScrollbar();
		}
		else
		{
			rect.xcoord = 5;
			rect.ycoord = 60;
			rect.width = 140;
			rect.height = 96;
			FieldSetBounds(FIELD_JOT_MACRO_TEXT, rect);
			rect.xcoord = 145;
			rect.ycoord = 60;
			rect.width = 9;
			rect.height = 96;
			ScrollbarSetBounds(SCROLLBAR_NEWMACRO, rect);
			FormGetActiveObject(FORM_JOT_NEWMACRO, &objID);
			if (objID == FIELD_JOT_MACRO_TEXT)
			{
				FormObjectSetFocus(FIELD_JOT_MACRO_TEXT);
				FieldGetInsertPointPosition(FIELD_JOT_MACRO_TEXT, &ins_pos);
				if (ins_pos >= 0)
				{
					UISearchForAddress(FIELD_JOT_MACRO_TEXT,&object_type,(void**)&field);
					FieldCharPosToLineNum(field, ins_pos, &ins_line);
					FieldGetMaxNumLinesDisplay(FIELD_JOT_MACRO_TEXT, &pagesize);
					FieldGetTotalNumOfLines(FIELD_JOT_MACRO_TEXT, &total);
					if (ins_line >= total - pagesize && total - pagesize >= 0)
						FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, total - pagesize);
					else
						FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
					FieldSetInsertPointPositionByCharPos(FIELD_JOT_MACRO_TEXT, ins_pos);
				}
				else
					FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, 0);
			}
			FieldEraseField(FIELD_JOT_MACRO_TEXT);
			FieldDrawField(FIELD_JOT_MACRO_TEXT);
			SetMyScrollbar();
			ScrollbarDrawScrollbar(SCROLLBAR_NEWMACRO);
		}
		return;
}

/********************************************************
* Function:	NewMacroFormEventHandler
* Purpose: 	This function is the event handler for the 
*				Jot Macro Editor
* Scope:		application/internal
* Input:		Event		received event
* Output:		None
* Return:		TRUE if handled
FALSE if not handled
* Comment: 	None
*********************************************************/
BOOLEAN NewMacroFormEventHandler(EvtType *Event)
{
	ObjectID objID;
	BYTE object_type;
	Form *form;
	Field *field;
	BYTE *text;
	BYTE *macroName;
	BYTE *macroText;
	RecordID recordID;
	int  i, len;
	static char msg1[80];
	static char msg2[80];
	ObjectBounds rect;
	WORD ins_pos;
	WORD ins_line;
	WORD pagesize, total;
	BOOLEAN ret = FALSE;
	
	WORD	char_pos;
	BYTE	*temp_text;
	
	int		SelectedItem;
	
	// Modified by Thomas 160899
	if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
	{
		if (Event->para2 & 0x00000100)
		{
			if (Event->para1 == LLETTER_CUT || Event->para1 == SLETTER_CUT)
			{
				Event->eventType = EVT_MENU_SELECT_ITEM;
				Event->para1 = MENU_ITEM_CUT;
			}
			else if (Event->para1 == LLETTER_COPY || Event->para1 == SLETTER_COPY)
			{
				Event->eventType = EVT_MENU_SELECT_ITEM;
				Event->para1 = MENU_ITEM_COPY;
			}
			else if (Event->para1 == LLETTER_UNDO || Event->para1 == SLETTER_UNDO)
			{
				Event->eventType = EVT_MENU_SELECT_ITEM;
				Event->para1 = MENU_ITEM_UNDO;
			}
			else if (Event->para1 == LLETTER_PASTE || Event->para1 == SLETTER_PASTE)
			{
				Event->eventType = EVT_MENU_SELECT_ITEM;
				Event->para1 = MENU_ITEM_PASTE;
			}
		}
		else if (Event->para2 & 0x00000200)
		{
			if (Event->para1 == KEY_UP)
			{
				Event->eventType = EVT_IO_KEY_CTRL;
				Event->eventID = EVT_IO_KEY_PRESS;
				Event->para2 = IO_UP_ARROW;
			}
			else if (Event->para1 == KEY_DOWN)
			{
				Event->eventType = EVT_IO_KEY_CTRL;
				Event->eventID = EVT_IO_KEY_PRESS;
				Event->para2 = IO_DOWN_ARROW;
			}
			else if (Event->para1 == LLETTER_DEL || Event->para1 == SLETTER_DEL)
			{
				Event->eventType = EVT_CONTROL_SELECT;
				Event->eventID = BUTTON_JOT_NEWMACRO_DELETE;
			}
		}
	}
	
	//	printf("Event->eventType = %d, id = %d\n", Event->eventType, Event->eventID);
	switch (Event->eventType)
	{
	case EVT_MENU_SELECT_ITEM:
		MenuItemSelectedAction((USHORT)(Event->para1));
		return TRUE;
	case EVT_KEYBOARD_STATUS:
		JotSetField();
		ret = TRUE;
		break;
	case EVT_INLAY_SELECT:
		if (Event->para1 == INLAY_OK)
		{
			g_prevForm = FORM_JOT_NEWMACRO;
			TextboxGetTextPointer(TEXTBOX_JOT_MACRO_NAME, &macroName);
			strcpy(g_macroName, macroName);
			FieldGetTextPointer(FIELD_JOT_MACRO_TEXT, &macroText);
			strcpy(g_macroText, macroText);
			if (macroName == NULL || strlen(macroName) <= 0)
			{
				g_warningMessage = JOTSTR1;
				FormPopupForm(FORM_WARNING);
				break;
			}
			
			if (macroText == NULL || strlen(macroText) <= 0)
			{
				g_warningMessage = JOTSTR2;
				FormPopupForm(FORM_WARNING);
				break;
			}
			
			SelectedItem = DataFindExactRecord(macroName);
			if ((g_editMacro == -1 && SelectedItem >= 0) || 
				(g_editMacro != -1 && (g_editMacro != SelectedItem) && SelectedItem >= 0))				
			{					
				g_warningMessage = JOTSTR3;
				FormPopupForm(FORM_WARNING);
				break;
			}
			
			// test conflict with extended characters
			for (i = 0; i < EXTENDEDCHARLISTSIZE; i++)\
			{
				if (strcmp(macroName, (char *)ExtendedCharacterList[i][0]) == 0)
					break;
			}
			if (i < EXTENDEDCHARLISTSIZE)
			{
				sprintf(msg1, TEXT(JOTSTR4), macroName);
				sprintf(msg2, TEXT(JOTSTR5), 
					ExtendedCharacterList[i][1]);
				g_okForm = FORM_JOT_NEWMACRO;
				g_cancelForm = FORM_JOT_NEWMACRO;
				g_okcancelTitle = JOTSTR6;
				g_okcancelString1 = msg1;
				g_okcancelString2 = msg2;
				g_okcancel = FALSE;
				g_fromOkCancel = FALSE;
				g_askReason = CONFLICT_WITH_SYMBOL;
				FormPopupForm(FORM_OKCANCEL);
			}
			else
			{
				if (g_editMacro >= 0)
				{
					ListGetListItem(LIST_MACRO_NAME1, g_editMacro, &temp_text);
					DeleteJotMacro(temp_text);
				}
				SaveMacro(macroName, macroText);
			}
			ret = TRUE;
		}
		else if (Event->para1 == INLAY_EXIT)
		{
			if (g_macroEditted)
			{
				g_okcancelTitle = JOTSTR7;
				g_okcancelString1 = JOTSTR8;
				g_okcancelString2 = JOTSTR9;
				g_okcancel = FALSE;
				g_okForm = FORM_MACRO_EDITOR;
				g_cancelForm = FORM_JOT_NEWMACRO;
				TextboxGetTextPointer(TEXTBOX_JOT_MACRO_NAME, &macroName);
				strcpy(g_macroName, macroName);
				FieldGetTextPointer(FIELD_JOT_MACRO_TEXT, &macroText);
				strcpy(g_macroText, macroText);
				g_fromOkCancel = FALSE;
				g_askReason = EXIT_WITHOUT_SAVE;
				FormPopupForm(FORM_OKCANCEL);
			}
			else
				FormPopupForm(FORM_MACRO_EDITOR);
			ret = TRUE;
		}
		break;
		
	case  EVT_KEY:	// CIC
		if (Event->eventID == SOFT_KEY)
		{
			FormGetActiveFormID(&objID);
			UISearchForAddress(objID,&object_type,(void**)&form);
			objID = form->form_focus;
			Event->para2 = Event->para2 & 0x000000FF;
			if (objID == FIELD_JOT_MACRO_TEXT)
			{
				JotSetField();
				FieldAddKeyInChar(FIELD_JOT_MACRO_TEXT, (BYTE)Event->para1);
				g_macroEditted = TRUE;
			}
			else if (objID == TEXTBOX_JOT_MACRO_NAME)
			{
				if (Event->para1 >= 'A' && Event->para1 <= 'Z')
					Event->para1 = Event->para1 - 'A' + 'a';
				if (Event->para1 >= 'a' && Event->para1 <= 'z')
				{
					if (Event->para1 == 'x' && g_lastNotChar == '.' ||
						Event->para1 == 't' && g_lastNotChar == ' ')
					{
						TextboxAddKeyInChar(TEXTBOX_JOT_MACRO_NAME, (BYTE)g_lastChar);
					}
					TextboxAddKeyInChar(TEXTBOX_JOT_MACRO_NAME, (BYTE)Event->para1);
					g_macroEditted = TRUE;
					g_lastNotChar = 0;
				}
				else
					g_lastNotChar = Event->para1;
				TextboxGetTextPointer(TEXTBOX_JOT_MACRO_NAME, &macroName);
				strcpy(g_macroName, macroName);
				len = strlen(g_macroName);
				if (len > 0)
					g_lastChar = g_macroName[len-1];
				else 
					g_lastChar = 0;
			}
			ret = TRUE;
		}
		break;
	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_NEWMACRO, SCROLLBAR_UP_ARROW);
			else if (Event->para2 == IO_DOWN_ARROW)
				ScrollbarHardButtonSetScrollbar(SCROLLBAR_NEWMACRO, SCROLLBAR_DOWN_ARROW);
			return TRUE;
		}
		break;
	case EVT_SCROLLBAR_SELECT:
	case EVT_SCROLLBAR_REPEAT:
		{
			WORD min, max, value, pagesize, total;
			
			FieldGetTotalNumOfLines(FIELD_JOT_MACRO_TEXT, &ins_line);
			if (Event->para2 >= 0 && Event->para2 < ins_line - 1)
			{
				FieldSetTopLineNum(FIELD_JOT_MACRO_TEXT, Event->para2);
				FieldDrawField(FIELD_JOT_MACRO_TEXT);
				FieldGetInsertPointPosition(FIELD_JOT_MACRO_TEXT, &char_pos);
			}
			
			ScrollbarGetScrollbar(SCROLLBAR_NEWMACRO, &value, &max, &min, &pagesize, &total);
			ScrollbarSetScrollbar(SCROLLBAR_NEWMACRO, Event->para2, max, min, pagesize, total);
			ScrollbarDrawScrollbar(SCROLLBAR_NEWMACRO);
			
			FieldSetInsertPointPositionByCharPos(FIELD_JOT_MACRO_TEXT, char_pos);
		}
		ret = TRUE;
		break;
		
	case EVT_FIELD_MODIFIED:
		SetMyScrollbar();
	case EVT_TEXTBOX_MODIFIED:
		if (!g_modified)
		{
			g_modified = TRUE;
			ControlSetAttributes(BUTTON_JOT_NEWMACRO_DELETE,
				FALSE,	// enable
				FALSE,	// drawn
				FALSE,	// save behind
				FALSE,	// active
				FALSE);	// visible
			rect.xcoord = 5;
			rect.ycoord = 60;
			rect.width = 140;
			if (g_keyboardON)
				rect.height = 39;
			else
				rect.height = 96;
			FieldSetBounds(FIELD_JOT_MACRO_TEXT, rect);	
			rect.xcoord = 145;
			rect.ycoord = 60;
			rect.width = 9;
			if (g_keyboardON)
				rect.height = 39;
			else 
				rect.height = 96;
			
			ScrollbarSetBounds(SCROLLBAR_NEWMACRO, rect);
			//				FormDrawForm(FORM_JOT_NEWMACRO);
			SetMyScrollbar();
			FieldDrawField(FIELD_JOT_MACRO_TEXT);
			ScrollbarDrawScrollbar(SCROLLBAR_NEWMACRO);
		}
		ret = TRUE;
		break;
		
	case EVT_CONTROL_SELECT:
		{
			g_prevForm = FORM_JOT_NEWMACRO;
			//			g_editMacro = -2;
			switch (Event->eventID)
			{
			case BUTTON_JOT_NEWMACRO_DELETE:
				g_deleteMacro = g_editMacro;
				if (g_deleteMacro >= 0)
				{
					ListGetListItem(LIST_MACRO_NAME1, g_deleteMacro, &g_deleteMacroName);
					strcpy(g_macroName, g_deleteMacroName);
					//						printf("DELETE: g_deleteMacro = %d, g_deleteMacroName = %s\n", g_deleteMacro, g_deleteMacroName);
					g_okForm = FORM_MACRO_EDITOR;
					g_cancelForm = FORM_JOT_NEWMACRO;
					g_okcancelTitle = JOTSTR10;
					g_okcancelString1 = JOTSTR11;
					g_okcancelString2 = JOTSTR12;
					g_okcancel = FALSE;
					g_fromOkCancel = FALSE;
					g_askReason = DELETE_MACRO;
					FormPopupForm(FORM_OKCANCEL);
				}
				break;
			}
		}
		ret = TRUE;
		break;
		
	case EVT_FORM_OPEN:
		g_prevForm = FORM_JOT_NEWMACRO;
		if (g_fromOkCancel && g_okcancel && g_askReason == CONFLICT_WITH_SYMBOL)
		{
			SaveMacro(g_macroName, g_macroText);
			g_fromOkCancel = FALSE;
		}
		
		TextboxInitTextbox(TEXTBOX_JOT_MACRO_NAME);
		FieldInitField(FIELD_JOT_MACRO_TEXT);
		ScrollbarInitScrollbar(SCROLLBAR_NEWMACRO);
		
		if (g_editMacro < 0 || g_modified)
		{
			ControlSetAttributes(BUTTON_JOT_NEWMACRO_DELETE,
				FALSE,	// enable
				FALSE,	// drawn
				FALSE,	// save behind
				FALSE,	// active
				FALSE);	// visible
			rect.xcoord = 5;
			rect.ycoord = 60;
			rect.width = 140;
			rect.height = 96;
			FieldSetBounds(FIELD_JOT_MACRO_TEXT, rect);
		}
		else
		{
			ControlSetAttributes(BUTTON_JOT_NEWMACRO_DELETE,
				TRUE,	// enable
				FALSE,	// drawn
				FALSE,	// save behind
				FALSE,	// active
				TRUE);	// visible
			rect.xcoord = 5;
			rect.ycoord = 60;
			rect.width = 140;
			rect.height = 81;
			FieldSetBounds(FIELD_JOT_MACRO_TEXT, rect);
			rect.xcoord = 145;
			rect.ycoord = 60;
			rect.width = 9;
			rect.height = 81;
			ScrollbarSetBounds(SCROLLBAR_NEWMACRO, rect);
		}
		
		TextboxSetText(TEXTBOX_JOT_MACRO_NAME, g_macroName);
		FieldSetText(FIELD_JOT_MACRO_TEXT, g_macroText);
		SetMyScrollbar();
		FormSetFormActiveObject(FORM_JOT_NEWMACRO, TEXTBOX_JOT_MACRO_NAME);
		FormObjectSetFocus(TEXTBOX_JOT_MACRO_NAME);
		FormDrawForm(FORM_JOT_NEWMACRO);
		ret = TRUE;
		break;
	case EVT_FORM_CLOSE:
		break;
		}
		return ret;
	}
	
	/********************************************************
	* Function:	WarningFormEventHandler
	* Purpose: 	This function is the event handler for the first
				page of the calculator application
				* Scope:		application/internal
				* Input:		Event		received event
				* Output:		None
				* Return:		TRUE if handled
				FALSE if not handled
				* Comment: 	None
				*********************************************************/
				BOOLEAN WarningFormEventHandler(EvtType *Event)
				{
					
					// Modified by Thomas 160899
					if (Event->eventType == EVT_INLAY_SELECT && Event->para1 == INLAY_OK)
					{
						Event->eventType = EVT_CONTROL_SELECT;
						Event->eventID = BUTTON_WARNING_OK;
					}
					
					switch (Event->eventType)
					{
					case EVT_CONTROL_SELECT:
						{
							switch (Event->eventID)
							{
							case BUTTON_WARNING_OK:
								FormPopupForm(g_prevForm);
								break;
							}
						}
						break;
					case EVT_FORM_OPEN:
						StringInitString(STRING_WARNING);
						StringSetText(STRING_WARNING, g_warningMessage);
						FormDrawForm(FORM_WARNING);
						break;
					case EVT_FORM_CLOSE:
						JotUpdate();
						break;
					}
					return TRUE;
				}
				
				/********************************************************
				* Function:	OkCancelFormEventHandler
				* Purpose: 	This function is the event handler for 
				*				OkCancel form
				* Scope:		application/internal
				* Input:		Event		received event
				* Output:		None
				* Return:		TRUE if handled
				FALSE if not handled
				* Comment: 	None
				*********************************************************/
				BOOLEAN OkCancelFormEventHandler(EvtType *Event)
				{
					
					// Modified by Thomas 160899
					if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
					{
						if (Event->para2 & 0x00000200)
						{
							if (Event->para1 == LLETTER_OK || Event->para1 == SLETTER_OK)
							{
								Event->eventType = EVT_CONTROL_SELECT;
								Event->eventID = BUTTON_OKCANCEL_OK;
							}
							else if (Event->para1 == LLETTER_CANCEL || Event->para1 == SLETTER_CANCEL)
							{
								Event->eventType = EVT_CONTROL_SELECT;
								Event->eventID = BUTTON_OKCANCEL_CANCEL;
							}
						}
					}
					
					switch (Event->eventType)
					{
					case EVT_CONTROL_SELECT:
						{
							switch (Event->eventID)
							{
							case BUTTON_OKCANCEL_OK:
								g_okcancel = TRUE;
								g_fromOkCancel = TRUE;
								FormPopupForm(g_okForm);
								break;
							case BUTTON_OKCANCEL_CANCEL:
								g_okcancel = FALSE;
								g_fromOkCancel = TRUE;
								FormPopupForm(g_cancelForm);
								break;
							}
						}
						break;
					case EVT_FORM_OPEN:
						FormSetDialogTitle(FORM_OKCANCEL, g_okcancelTitle);
						StringInitString(STRING_OKCANCEL1);
						StringSetText(STRING_OKCANCEL1, g_okcancelString1);
						StringInitString(STRING_OKCANCEL2);
						StringSetText(STRING_OKCANCEL2, g_okcancelString2);
						FormDrawForm(FORM_OKCANCEL);
						break;
					case EVT_FORM_CLOSE:
						break;
					}
					return TRUE;
				}
				
				/********************************************************
				* Function:	AdvancedHandleEvent
				* Purpose: 	This function is the event handler for the
				*				Advanced push button
				* Scope:		application/internal
				* Input:		Event		received event
				* Output:		None
				* Return:		TRUE if handled
				FALSE if not handled
				* Comment: 	None
				*********************************************************/
				BOOLEAN AdvancedHandleEvent(EvtType *Event)
				{
					short selected;
					BOOLEAN handled = FALSE;
					BYTE	*text;
					static USHORT macroPos = 0;
					USHORT   numItems;
					
					if (Event->eventType == EVT_KEY && Event->eventID == SOFT_KEY)
					{
						if (Event->para2 & 0x00000200)
						{
							if (Event->para1 == KEY_UP)
							{
								Event->eventType = EVT_IO_KEY_CTRL;
								Event->eventID = EVT_IO_KEY_PRESS;
								Event->para2 = IO_UP_ARROW;
							}
							else if (Event->para1 == KEY_DOWN)
							{
								Event->eventType = EVT_IO_KEY_CTRL;
								Event->eventID = EVT_IO_KEY_PRESS;
								Event->para2 = IO_DOWN_ARROW;
							}
							else if (Event->para1 == LLETTER_MACRO_EDITOR || Event->para1 == SLETTER_MACRO_EDITOR)
							{
								Event->eventType = EVT_CONTROL_SELECT;
								Event->eventID = BUTTON_MACRO_EDITOR;
							}
							else if (Event->para1 == LLETTER_TRAINER || Event->para1 == SLETTER_TRAINER)
							{
								Event->eventType = EVT_CONTROL_SELECT;
								Event->eventID = BUTTON_TRAINER;
							}
						}
					}
					
					switch (Event->eventType)
					{
					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_MACRO, SCROLLBAR_UP_ARROW);
							else if (Event->para2 == IO_DOWN_ARROW)
								ScrollbarHardButtonSetScrollbar(SCROLLBAR_MACRO, SCROLLBAR_DOWN_ARROW);
							return TRUE;
						}
						break;
					case EVT_SCROLLBAR_SELECT:
					case EVT_SCROLLBAR_REPEAT:
						{
							WORD min, max, value, pagesize, total;
							
							ListGetTotalItems(LIST_MACRO_NAME, &numItems);
							if (Event->para2 >= 0 && Event->para2 < numItems)
							{
								macroPos = Event->para2;
								ListSetTopItemNum(LIST_MACRO_NAME, macroPos);
								ListSetTopItemNum(LIST_MACRO_TEXT, macroPos);
								ListDrawList(LIST_MACRO_NAME);
								ListDrawList(LIST_MACRO_TEXT);
							}
							ScrollbarGetScrollbar(SCROLLBAR_MACRO, &value, &max, &min, &pagesize, &total);
							ScrollbarSetScrollbar(SCROLLBAR_MACRO, Event->para2, max, min, pagesize, total);
							ScrollbarDrawScrollbar(SCROLLBAR_MACRO);
						}
						break;
					case EVT_CONTROL_SELECT:
						{
							switch (Event->eventID)
							{
							case BUTTON_MACRO_EDITOR:
								FormPopupForm(FORM_MACRO_EDITOR);
								break;
							case BUTTON_TRAINER:
								FormPopupForm(FORM_TRAINER);
								break;
							}
						}
						handled = TRUE;
						break;
						
					case EVT_FORM_OPEN:
						SetMacrosInList(LIST_MACRO_NAME, LIST_MACRO_TEXT);
						FormDrawForm(FORM_JOT);
						handled = TRUE;
						break;
					case EVT_FORM_CLOSE:
						break;
					}
					return handled;
				}
				
				void SaveFormNewMacro()
				{
					BYTE *macroName;
					BYTE *macroText;
					
					jot_status.form_newmacro_editMacro = g_editMacro;
					jot_status.g_macroEditted = g_macroEditted;
					jot_status.g_modified = g_modified;
					TextboxGetTextPointer(TEXTBOX_JOT_MACRO_NAME, &macroName);
					strcpy(jot_status.g_macroName, macroName);
					FieldGetTextPointer(FIELD_JOT_MACRO_TEXT, &macroText);
					strcpy(jot_status.g_macroText, macroText);
				}
				
				void RestoreFormNewMacro()
				{
					g_editMacro = jot_status.form_newmacro_editMacro;
					g_macroEditted = jot_status.g_macroEditted;
					g_modified = jot_status.g_modified;
					strcpy(g_macroName, jot_status.g_macroName);
					strcpy(g_macroText, jot_status.g_macroText);
					g_fromOkCancel = FALSE;
					g_deleteMacro =g_editMacro;
					g_deleteMacroName = g_macroName;
					g_keyboardON = FALSE;
				}
