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



#include "stdafx.h"
#include "uidef.h"
#include "uifunc.h"

//#define DEBUG

/********************************************************
* Function:	TextboxGetNumOfCharsDisplayed
* Purpose:     To get the number of chars that are displayed
* Scope:		Application
* Input:       textbox_id 	        ID of the spceified textbox object
num_chars			the number of chars that are displayed
on the textbox object
* Output:		None
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxGetNumOfCharsDisplayed(ObjectID textbox_id, WORD *num_chars)
{
    Textbox *addr;
    BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*num_chars = addr->textbox_num_chars_displayed;
    return TRUE;
}

/********************************************************
* Function:	TextboxDirty
* Purpose:     to get the dirty bit of a textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:		dirty               Pointer to Boolean dirty
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxDirty(ObjectID textbox_id, BOOLEAN *dirty)
{
    Textbox *addr;
    BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    *dirty = addr->textbox_attr.textbox_dirty;
    return TRUE;
}
/********************************************************
* Function:	TextboxEraseTextbox
* Purpose:     to erase the particular textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:		None
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxEraseTextbox(ObjectID textbox_id)
{
    Textbox *addr;
    BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->textbox_attr.textbox_drawn)
    {
		if (addr->identification.table_related != 0xFFFF)
			LcdEraseRegion(&(addr->screen_bounds));
		else LcdEraseRegion(&(addr->bounds));
		addr->textbox_attr.textbox_drawn = FALSE;
    }
    return TRUE;
}

/********************************************************
* Function:	TextboxStoreBackspaceChar
* Purpose:  This function is called in order to store backspace character			
* Scope:	Internal
* Input:	textbox_id		DBID of the spceified textbox object
character		The character to be stored
* Output:	None
* Return:	Error code
* Comment:	None
**********************************************************/
Err TextboxStoreBackspaceChar(ObjectID textbox_id, UBYTE character)
{
	BYTE object_type;
	Textbox *textbox_ptr;
	SHORT count;
	
	if (UISearchForAddress(textbox_id, &object_type, (void**)&textbox_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (object_type != TEXTBOX) return ERR_UI_OBJECT_NOT_MATCH;
	undo_action = UNDO_BACKSPACE;
	if (textbox_id != backspace_undo.current_object_id)
	{
		backspace_undo.current_object_id = textbox_id;
		backspace_undo.index = -1;
	}
	else if (textbox_id == backspace_undo.current_object_id && backspace_undo.index == 255)
	{
		for(count = 0; count < 255; count++)
			backspace_undo.key[count] = backspace_undo.key[count + 1];
	}
	if (backspace_undo.index != 255)
		backspace_undo.index ++;
	backspace_undo.key[backspace_undo.index] = character;
	return TRUE;
}

/********************************************************
* Function:	TextboxRestoreBackspaceChar
* Purpose:  This function is called in order to restore backspace character			
* Scope:	Internal
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	character		The character for restoration
* Return:	TRUE			if restored successfully
FALSE			can't restore
* Comment:	None
**********************************************************/
Err TextboxRestoreBackspaceChar(ObjectID textbox_id, UBYTE *character)
{
	BYTE object_type;
	Textbox *textbox_ptr;
	
	if (UISearchForAddress(textbox_id, &object_type, (void**)&textbox_ptr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (object_type != TEXTBOX) return ERR_UI_OBJECT_NOT_MATCH;
	if (textbox_id != backspace_undo.current_object_id)
	{
		*character = 0;
		return FALSE;
	}
	if (backspace_undo.index != -1)
		*character = backspace_undo.key[backspace_undo.index];
	backspace_undo.index --;
	if (backspace_undo.index == -1) undo_action = UNDO_EMPTY;
	return TRUE;
}

/********************************************************
* Function:	TextboxGetTextboxBounds
* Purpose:     to get the bounds of the textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:		bounds              Pointer to bounds of textbox object
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxGetTextboxBounds(ObjectID textbox_id, ObjectBounds *bounds)
{
    Textbox *addr;
    BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->identification.table_related != 0xFFFF)
		*bounds = addr->screen_bounds;
    else *bounds = addr->bounds;
    return TRUE;
}
/********************************************************
* Function:	TextboxGetInsertPointPosition
* Purpose:     to get the insert point position of the
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:		bounds              Pointer to bounds of textbox object
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxGetInsertPointPosition(ObjectID textbox_id, WORD *char_pos)
{
    Textbox *addr;
    BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->textbox_attr.textbox_insert_pt_visible)
		*char_pos = addr->textbox_insert_pt_char_pos;
    else *char_pos = -1;
    return TRUE;
}
/********************************************************
* Function:	TextboxDeleteTextbox
* Purpose:     to delete a textbox object from memory
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:		None
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxDeleteTextbox(ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	
	Err Error;
	
	if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) == TRUE)
	{
		Error = UIDeleteLookupTableElement(textbox_id);
		if (Error !=TRUE) return Error;
		qfree(addr->textbox_string);
		qfree(addr);
		return TRUE;
	}
	return ERR_UI_RES_NOT_FOUND;
}
/********************************************************
* Function:	TextboxGetCurrentHighlightSelection
* Purpose:     to get the current highlight selection position
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:      star_char_pos       Pointer to the start character position of selected
range of characters
end_char_pos        Pointer to the end-character position of selected
range of characters
* Return:		Error code
UI_ERR_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxGetCurrentHighlightedSelection(ObjectID textbox_id, WORD *star_char_pos,
										  WORD *end_char_pos)
{
	Textbox *addr;
	BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (addr->textbox_attr.textbox_highlight)
    {
		*star_char_pos = addr->textbox_highlight_start_char;
		*end_char_pos = addr->textbox_highlight_start_char + addr->textbox_highlight_length;
    }
    else
    {
		*star_char_pos = -1;
		*end_char_pos = -1;
    }
    return TRUE;
}
/********************************************************
* Function:	TextboxSetBounds
* Purpose:     to set the object bounds of a textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
bounds              bounds of the textbox object
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxSetBounds(ObjectID textbox_id, ObjectBounds bounds)
{
	Textbox *addr;
	BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    addr->bounds = bounds;
    return TRUE;
}
/********************************************************
* Function:	TextboxSetFont
* Purpose:     to set the font of the textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
font                font type for the textbox object
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxSetFont(ObjectID textbox_id, BYTE font)
{
	Textbox *addr;
	BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    addr->textbox_font_id = font;
    return TRUE;
}
/********************************************************
* Function:	TextboxSetInsertPointOff
* Purpose:     to turn off the insert point of the textbox
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxSetInsertPointOff(ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    LcdEnableInsertPt(FALSE,0,0,0);
    addr->textbox_attr.textbox_insert_pt_visible = FALSE;
    return TRUE;
}
/********************************************************
* Function:	TextboxSetInsertPointOn
* Purpose:     to turn on the insert point of the textbox
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxSetInsertPointOn(ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    LcdEnableInsertPt(TRUE,addr->textbox_insert_pt_x, addr->textbox_insert_pt_y, addr->textbox_font_id);
    addr->textbox_attr.textbox_insert_pt_visible = TRUE;
    addr->textbox_attr.textbox_highlight = FALSE;
    return TRUE;
}

/********************************************************
* Function:	TextboxSetText
* Purpose:     to set the string of the textbox object
* Scope:		Application
* Input:       textbox_id 	        DBID of the spceified textbox object
string              Pointer to null-terminated string
* Output:      None
* Return:		Error code
ERR_UI_RES_NOT_FOUND;
* Comment:		None
*********************************************************/
Err TextboxSetText(ObjectID textbox_id, BYTE *string)
{
	Textbox *addr;
	BYTE object_type;
	WORD temp_length;
	WORD temp_length1;
	
    if (UISearchForAddress(textbox_id,&object_type, (void**)&addr) != TRUE)
        return ERR_UI_RES_NOT_FOUND;
	
    temp_length = strlen(string);
    
    if (temp_length > addr->textbox_max_chars)
        return ERR_UI_TEXTBOX_OVER_MAX_NUM_CHARS;
	
    qfree(addr->textbox_string);
	temp_length1 = ((temp_length)/STEP_SIZE + 1) * STEP_SIZE;
    addr->textbox_string = (BYTE*)qmalloc(temp_length1*sizeof(BYTE));
    strcpy(addr->textbox_string, string);
    addr->textbox_current_num_chars = temp_length;
    return TRUE;
}
/********************************************************
* Function:	TextboxGetAttribute
* Purpose:	Get the pointer of the textbox's attribute structure
* Scope:	Application
* Input:    textbox_id	DBID of the spceified textbox object
* Output:	textbox_attr	Pointer to the textbox's attribute
*						structure
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxGetAttribute(ObjectID textbox_id, TextboxAttr *textbox_attr)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	*textbox_attr = addr->textbox_attr;
	return TRUE;
}
/********************************************************
* Function:	TextboxGetFont
* Purpose:	Get the font of the textbox object
* Scope:	Application
* Input:    textbox_id	DBID of the spceified textbox object
* Output:	font_id		Return the font of the textbox object
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxGetFont(ObjectID textbox_id, BYTE *font_id)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	*font_id = addr->textbox_font_id;
	return TRUE;
}
/********************************************************
* Function:	TextboxGetMaxNumChars
* Purpose:	Get the maximum numbers of char in the textbox object
* Scope:	Application
* Input:    textbox_id			DBID of the spceified textbox object
* Output:	max_num_of_chars	Maximum number of char in the textbox
*								object
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxGetMaxNumChars(ObjectID textbox_id, WORD *max_num_of_chars)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	*max_num_of_chars = addr->textbox_max_chars;
	return TRUE;
}
/********************************************************
* Function:	TextboxGetTextPointer
* Purpose:	Get the text pointer of the specified textbox object
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
* Output:	text_ptr
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxGetTextPointer(ObjectID textbox_id, BYTE **text_ptr)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	*text_ptr = ((BYTE *)addr->textbox_string);
	return TRUE;
}
/********************************************************
* Function:	TextboxGetNumOfChars
* Purpose:	Get current number of char in the textbox object
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
* Output:	num_chars		Number of char in the textbox object
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxGetNumOfChars(ObjectID textbox_id, WORD *num_chars)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	*num_chars = addr->textbox_current_num_chars;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetAttribute
* Purpose:	Set the textbox's attributes
* Scope:	Application
* Input:    textbox_id	DBID of the spceified textbox object
* 			textbox_attr	Pointer to the textbox's attribute
*						structure
* Output:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxSetAttribute(ObjectID textbox_id, TextboxAttr input_textbox_attr)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	addr->textbox_attr = input_textbox_attr;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetDirty
* Purpose:	Set the dirty attribute of the specified textbox object
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
*			textbox_dirty		Value of the dirty attribute
* Output:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxSetDirty(ObjectID textbox_id, BOOLEAN textbox_dirty)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	addr->textbox_attr.textbox_dirty = textbox_dirty;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetInsertPointPositionByXY
* Purpose:	Set the Insert point position of a particular textbox
*			object
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
*			insert_xcoord	x-coordinate of the insert point
*			insert_ycoord	y-coordinate of the insert point
* Output:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxSetInsertPointPositionByXY(ObjectID textbox_id, SHORT insert_xcoord, SHORT insert_ycoord)
{
	Textbox *addr;
	BYTE object_type;
	WORD char_pos;
	SHORT new_xcoord, new_ycoord;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	StrTextboxAnalyze(addr);
	StrTextboxGetInsertPtPos(addr,insert_xcoord,insert_ycoord,&char_pos,
							 &new_xcoord,&new_ycoord);
	addr->textbox_insert_pt_x = new_xcoord;
	addr->textbox_insert_pt_y = new_ycoord;
	addr->textbox_insert_pt_char_pos = char_pos;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetInsertPointPositionByCharPos
* Purpose:	Set the Insert point position of a particular textbox
*			object
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
*			char_pos		character position of character that insertion point locates
* Output:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxSetInsertPointPositionByCharPos(ObjectID textbox_id, WORD char_pos)
{
	Textbox *addr;
	BYTE object_type;
	SHORT new_xcoord, new_ycoord;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	StrTextboxAnalyze(addr);
	StrTextboxCharPosToXY(addr,char_pos,&new_xcoord,&new_ycoord);
	addr->textbox_insert_pt_x = new_xcoord;
	addr->textbox_insert_pt_y = new_ycoord;
	addr->textbox_insert_pt_char_pos = char_pos;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetMaxNumChars
* Purpose:	Set the maximum numbers of char in the textbox object
* Scope:	Application
* Input:    textbox_id			DBID of the spceified textbox object
* Input:	max_num_of_chars	Maximum number of char in the textbox
*								object
* Ouput:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	None
*********************************************************/
Err TextboxSetMaxNumChars(ObjectID textbox_id, WORD max_num_of_chars)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	addr->textbox_max_chars = max_num_of_chars;
	return TRUE;
}
/********************************************************
* Function:	TextboxSetHighlightSelection
* Purpose:	Set the current selection in a textbox and highlight
*			the selection if the textbox is visible
* Scope:	Application
* Input:    textbox_id		DBID of the spceified textbox object
* 			start_char		Starting character position of the
*							character range to highlight
*			stop_char		Ending character position of the
*							character range to highlight
* Ouput:	None
* Return:	Error code
*			UI_ERR_RES_NOT_FOUND;
* Comment:	If the start_char equal stop_char, then the
*			textbox_highlight is reset
*********************************************************/
Err TextboxSetHighlightSelection(ObjectID textbox_id, WORD start_char, WORD stop_char)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	if (start_char == stop_char)
		addr->textbox_attr.textbox_highlight = FALSE;
	else
	{
		addr->textbox_attr.textbox_highlight = TRUE;
		addr->textbox_highlight_start_char = start_char;
        addr->textbox_highlight_length = (stop_char-start_char);
	}
	return TRUE;
}
/********************************************************
* Function:	TextboxDrawTextbox
* Purpose:  Get the
* Scope:	Application
* Input:	textbox_id	DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxDrawTextbox (ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	ObjectBounds bounds;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (addr->textbox_attr.textbox_visible == FALSE) return FALSE;
	
	if (addr->identification.table_related == 0xFFFF)
		bounds = addr->bounds;
	else
		bounds = addr->screen_bounds;
	
	if (addr->textbox_style == TEXTBOX_STYLE_1)
		LcdDrawBox(&bounds,color_level[COLOR_BLACK_COLOR], color_level[COLOR_WHITE_COLOR],DRAW_NOT_FILL);
	else if (addr->textbox_style == TEXTBOX_STYLE_2)
		TextboxDrawRoundTextbox(&bounds);
    else
        LcdDrawBox(&bounds,addr->textbox_background_color,addr->textbox_background_color,DRAW_NOT_FILL);
	
    if (LcdCheckInsertPt(bounds))
        LcdEnableInsertPt(FALSE, 0 , 0, FALSE);  
	
	StrTextboxAnalyze(addr);
	LcdTextboxDrawString(addr);
	addr->textbox_attr.textbox_drawn = TRUE;
	
	if (addr->textbox_attr.textbox_insert_pt_visible == TRUE)
	{
		TextboxInsertPtMove(textbox_id);
		LcdEnableInsertPt(TRUE,addr->textbox_insert_pt_x,addr->textbox_insert_pt_y, addr->textbox_font_id);
	}
	return TRUE;
}

/********************************************************
* Function: TextboxDrawTextbox2
* Purpose:  Get the
* Scope:	Application
* Input:	textbox_id	DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:  without erase
**********************************************************/
Err TextboxDrawTextbox2(ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	ObjectBounds bounds;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (addr->textbox_attr.textbox_visible == FALSE) return FALSE;
	
	if (addr->identification.table_related == 0xFFFF)
		bounds = addr->bounds;
	else
		bounds = addr->screen_bounds;
	
	StrTextboxAnalyze(addr);
	
    if (LcdCheckInsertPt(bounds))
        LcdEnableInsertPt(FALSE, 0 , 0, FALSE);  
	
	LcdTextboxDrawString(addr);
	addr->textbox_attr.textbox_drawn = TRUE;
	
	if (addr->textbox_attr.textbox_insert_pt_visible == TRUE)
	{
		TextboxInsertPtMove(textbox_id);
		LcdEnableInsertPt(TRUE,addr->textbox_insert_pt_x,addr->textbox_insert_pt_y, addr->textbox_font_id);
	}
	return TRUE;
}


/*********************************************************************
* Function	: TextboxDrawRoundTextbox
* Purpose	:
* Scope		: Application/Internal
* Input		: bounds		Pointer to the bounds structure
draw_radius	the radius of rounded corners
* Output	: None
* Return	: None
* Comment	: None
**********************************************************************/
void TextboxDrawRoundTextbox(ObjectBounds *bounds)
{
	SHORT draw_xcoord, draw_ycoord, draw_end_xcoord, draw_end_ycoord;
	ObjectBounds box;
	
	LcdEraseRegion(bounds);
	/* Draw the upper horizontal line */
	draw_xcoord = bounds->xcoord+TEXTBOX_FIXED_CORNER;
	draw_ycoord = bounds->ycoord;
	draw_end_xcoord = bounds->xcoord+bounds->width-TEXTBOX_FIXED_CORNER-1;
	draw_end_ycoord = bounds->ycoord;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	LcdDrawLine(draw_xcoord,draw_ycoord+1,draw_end_xcoord,draw_end_ycoord+1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	/* Draw the lower horizontal line */
	draw_xcoord = bounds->xcoord+TEXTBOX_FIXED_CORNER;
	draw_ycoord = bounds->ycoord+bounds->height-1;
	draw_end_xcoord = bounds->xcoord+bounds->width-TEXTBOX_FIXED_CORNER-1;
	draw_end_ycoord = bounds->ycoord+bounds->height-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	LcdDrawLine(draw_xcoord,draw_ycoord-1,draw_end_xcoord,draw_end_ycoord-1,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
	/* Draw the left vertical line */
	draw_xcoord = bounds->xcoord;
	draw_ycoord = bounds->ycoord+TEXTBOX_FIXED_CORNER;
	draw_end_xcoord = bounds->xcoord;
	draw_end_ycoord = bounds->ycoord+bounds->height-TEXTBOX_FIXED_CORNER-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	LcdDrawLine(draw_xcoord+1,draw_ycoord,draw_end_xcoord+1,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	/* Draw the right vertical line */
	draw_xcoord = bounds->xcoord+bounds->width-1;
	draw_ycoord = bounds->ycoord+TEXTBOX_FIXED_CORNER;
	draw_end_xcoord = bounds->xcoord+bounds->width-1;
	draw_end_ycoord = bounds->ycoord+bounds->height-TEXTBOX_FIXED_CORNER-1;
	LcdDrawLine(draw_xcoord,draw_ycoord,draw_end_xcoord,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_BLACK_COLOR],color_level[COLOR_BLACK_COLOR]);
	LcdDrawLine(draw_xcoord-1,draw_ycoord,draw_end_xcoord-1,draw_end_ycoord,SINGLE_LINE,NON_DOTTED_LINE,color_level[COLOR_WHITE_COLOR],color_level[COLOR_WHITE_COLOR]);
	/* Draw the background box */		
	box = *bounds;
	box.xcoord = bounds->xcoord+2;
	box.ycoord = bounds->ycoord+2;
	box.width  = bounds->width-4;
	box.height = bounds->height-4;
	LcdDrawBox(&box,color_level[COLOR_GREY1_COLOR],color_level[COLOR_GREY1_COLOR],DRAW_FILL);
	ControlDrawArc(bounds,FILL_EMPTY,TEXTBOX_FIXED_CORNER,color_level[COLOR_WHITE_COLOR]);
}
/********************************************************
* Function:	TextboxCopy
* Purpose:  Copy the current selection to the text clipboard
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxCopy (ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type, *text_pointer;
	WORD copy_start_char, copy_length;
	
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (addr->textbox_attr.textbox_highlight == TRUE)
	{
		copy_start_char = addr->textbox_highlight_start_char;
		copy_length = addr->textbox_highlight_length;
		
		if (addr->textbox_highlight_length < 0)
		{
			copy_start_char += addr->textbox_highlight_length;
			copy_length = abs(copy_length);
		}
        text_pointer = (BYTE*)qmalloc((copy_length+1)*sizeof(BYTE));
		StrExtract(addr->textbox_string,copy_start_char,copy_length,text_pointer);
		ClipboardPutItem(CLIP_TEXT_DATA,(void*)text_pointer,copy_length);
        qfree(text_pointer);
	}
	return TRUE;
}
/********************************************************
* Function:	TextboxCut
* Purpose:  Copy the current selection to the text clipboard,
*			delete the selection from the textbox, and redraw
*			the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxCut (ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (addr->textbox_attr.textbox_highlight == TRUE)
	{
		TextboxCutSelectedText (addr);
		undo_action = UNDO_CUT;
	}
	return TRUE;
}
/********************************************************
* Function:	TextboxInsert
* Purpose:  Insert text from the clipboard to the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
*			paste_size		Length of the text to be inserted
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxInsert (ObjectID textbox_id, WORD *paste_size)
{
	Textbox *addr;
	BYTE object_type, data_type, *paste_text;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	paste_text = (BYTE *) ClipboardGetItem(&data_type,paste_size);
	if (paste_text == NULL) return TRUE;
	TextboxInsertFunction(addr,paste_text,*paste_size);
    qfree(paste_text);
	return TRUE;
}
/********************************************************
* Function:	TextboxInsertText
* Purpose:  Insert text to the specified textbox object
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
*			insert_string	Pointer to the insert string
*			textbox_len		Length of the textbox
* Output:	None
* Return:	Error code      UI_ERR_RES_NOT_FOUND
* Comment:	None
**********************************************************/
Err TextboxInsertText (ObjectID textbox_id, BYTE *insert_string, WORD textbox_len)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (addr->textbox_attr.textbox_insert_pt_visible == TRUE &&
		addr->textbox_attr.textbox_highlight == FALSE)
		TextboxInsertFunction (addr,insert_string,textbox_len);
	
	if (addr->textbox_attr.textbox_insert_pt_visible == TRUE &&
		addr->textbox_attr.textbox_highlight == TRUE)
	{
		TextboxCutSelectedText (addr);
		TextboxInsertFunction (addr,insert_string,textbox_len);
	}
	return TRUE;
}
/********************************************************
* Function:	TextboxInsertFunction
* Purpose:  Insert text from the clipboard to the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
*			addr			Pointer to the structure of the textbox object
*			paste_size		Length of the text
* Output:	None
* Return:	None
* Comment:	None
**********************************************************/
void TextboxInsertFunction (Textbox *addr, BYTE *paste_text, WORD paste_size)
{
	BYTE *text_pointer;
	WORD insert_pos, total_length, org_total;
	WORD i, count=0, add_length, buffer_size;
	
	org_total = strlen(addr->textbox_string) + 1;
	total_length = org_total + paste_size;
	buffer_size = ((org_total-1)/STEP_SIZE + 1) * STEP_SIZE;
	insert_pos = addr->textbox_insert_pt_char_pos;
	
#ifdef DEBUG
    printf("\n Textbox Insert Function 1 = %ld", total_length);
    printf("\n Textbox Insert Function 1a = %ld", buffer_size);
#endif
	
	if (total_length >= buffer_size)
	{
		while(total_length >= buffer_size)
			buffer_size += STEP_SIZE;		
		
#ifdef DEBUG
        printf("\n Textbox Insert Function 2 = %ld", buffer_size);
#endif
		
        text_pointer = (BYTE *)qmalloc(buffer_size*sizeof(BYTE));
		/* If insert pt is behind the textbox text, then copy the '\0' only */
		if (insert_pos > org_total-1)
			add_length = 1;
		else
			add_length = (org_total-insert_pos);
		
		i = insert_pos;
		while (i)
		{
			i--;
			text_pointer[i] = addr->textbox_string[i];
			count++;
		}
		/* Paste the text from clipboard to the textbox */
		i = paste_size;
		while (i)
		{
			i--;
			text_pointer[count] = *paste_text++;	
			count++;
		}
		i = add_length;
		while (i)
		{
			i--;
			text_pointer[count] = addr->textbox_string[insert_pos++];
			count++;
		}
		
        qfree (addr->textbox_string);
		addr->textbox_string = text_pointer;
	}
	else
	{
#ifdef DEBUG
        printf("\n Textbox Insert Function 3");
#endif
		i = org_total;
		while (i>= insert_pos)
		{
			addr->textbox_string[total_length--] = addr->textbox_string[org_total--];
			i--;
		}
		/* Paste the text from clipboard to the textbox */
		i = paste_size;
		while (i)
		{
			i--;
			addr->textbox_string[insert_pos++] = *paste_text++;	
		}
	}
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
	undo_action = UNDO_PASTE;	
}
/********************************************************
* Function:	TextboxCutSelectedText
* Purpose:  Delete the specified range of characters from
*			the textbox and redraw the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	None
* Comment:	None
**********************************************************/
void TextboxCutSelectedText (Textbox *addr)
{
	BYTE *text_pointer;
	WORD total_length, add_length, text_cont_text, i, count;
	WORD cut_start_char, cut_length;
	
	cut_start_char = addr->textbox_highlight_start_char;
	cut_length = addr->textbox_highlight_length;
	
	if (!addr->textbox_attr.textbox_drawn)
		StrTextboxAnalyze(addr);
	if (addr->textbox_highlight_length < 0)
	{
		cut_start_char += addr->textbox_highlight_length;
		cut_length = abs(cut_length);
	}
    text_pointer = (BYTE*)qmalloc((cut_length+1)*sizeof(BYTE));
	total_length = strlen(addr->textbox_string)+1;
	text_cont_text = cut_start_char + cut_length;
	add_length = total_length - text_cont_text;
	
	/* Extract the highlight region to text_pointer*/
	StrExtract(addr->textbox_string,cut_start_char,cut_length,text_pointer);
	ClipboardPutItem(CLIP_TEXT_DATA,(void*)text_pointer,cut_length);
	count = cut_start_char;
	
	i = add_length;
	while (i >=0)
	{
		i--;
		addr->textbox_string[count] = addr->textbox_string[text_cont_text++];
		count++;
	}	
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
	addr->textbox_attr.textbox_highlight = FALSE;
	undo_action = UNDO_CUT;
    qfree(text_pointer);
}
/********************************************************
* Function:	TextboxDelete
* Purpose:  Delete the specified range of characters from
*			the textbox and redraw the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
*			start_char		start character position
*			cut_length 		Length to cut
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxDelete (ObjectID textbox_id, WORD start_char, WORD cut_length)
{
	Textbox *addr;
	BYTE object_type;
	WORD total_length, text_cont_text, add_length, i;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (cut_length < 0)
	{
		start_char += cut_length;
		cut_length = -cut_length;
	}
	
	total_length = strlen(addr->textbox_string)+1;
	text_cont_text = start_char+cut_length;
	
	if (text_cont_text > total_length)
		add_length = 0;
	else
		add_length = total_length-text_cont_text;
	
	i = add_length;
	while (i)
	{	
		i--;
		addr->textbox_string[start_char++] = addr->textbox_string[text_cont_text++];
	}
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
	return TRUE;
}

/********************************************************
* Function:	TextboxUndo
* Purpose:  Undo the last change made to the textbox object.
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxUndo (ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type, data_type, *paste_text;
	WORD undo_size;
    SHORT xcoord,ycoord;
	UBYTE character;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	switch(undo_action)
	{
	case UNDO_TYPING:
		if (typing_undo.focus_object_id != textbox_id)
			return FALSE;
		addr->textbox_insert_pt_char_pos = typing_undo.start_char;
		TextboxDelete (textbox_id, typing_undo.start_char, typing_undo.length);
		undo_action = UNDO_EMPTY;
		typing_undo.focus_object_id = 0xFFFF;
		typing_undo.start_char = 0;
		typing_undo.length = -1;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;		
		
  		    addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
			if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
			{
				addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
				addr->textbox_right_char_pos = -1;
				StrTextboxAnalyze(addr);
			}
			else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
			{
				addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
				addr->textbox_left_char_pos = -1;
				StrTextboxAnalyze(addr);
			}
            StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
				&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
			addr->textbox_attr.textbox_highlight = FALSE;
			addr->textbox_highlight_length = 0;
            if (addr->textbox_attr.textbox_drawn == TRUE)
				TextboxDrawTextbox(textbox_id);			
            EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
            EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
			return TRUE;	
	case UNDO_BACKSPACE:
		if (TextboxRestoreBackspaceChar(textbox_id, &character) == FALSE) return FALSE;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;
		TextboxAddKeyInChar(textbox_id, character);
		if (backspace_undo.index != -1)
			undo_action = UNDO_BACKSPACE;
		EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
		EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
		return TRUE;
	case UNDO_BACKSPACE_HIGHLIGHT:
		if (undo_buffer.clipboard_type == CLIP_EMPTY)
			return FALSE;
		LcdEnableInsertPt(FALSE,0,0, 0);
		undo_size = undo_buffer.clipboard_size;
		TextboxInsertFunction(addr,(BYTE*)undo_buffer.clipboard_data,undo_size);
		if (undo_buffer.clipboard_type == CLIP_TEXT_DATA)
		{
			undo_buffer.clipboard_type = CLIP_EMPTY;
			undo_buffer.clipboard_size = 0;
			qfree(undo_buffer.clipboard_data);
		}
		
		addr->textbox_insert_pt_char_pos += undo_size;
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
		if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
		{
			addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
		{
			addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_left_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
			&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
		addr->textbox_highlight_start_char = addr->textbox_highlight_end_char;
		addr->textbox_highlight_length = 0;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;
		addr->textbox_attr.textbox_highlight = FALSE;
		if (addr->textbox_attr.textbox_drawn == TRUE)
			TextboxDrawTextbox(textbox_id);
		undo_action = UNDO_EMPTY;
		EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
		EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
		break;	
	case UNDO_CUT:		
		LcdEnableInsertPt(FALSE,0,0,0);	
		if (undo_buffer.clipboard_type == CLIP_TEXT_DATA)
		{
			undo_buffer.clipboard_type = CLIP_EMPTY;
			undo_buffer.clipboard_size = 0;
			qfree(undo_buffer.clipboard_data);
		}
		paste_text = (BYTE *) ClipboardGetItem(&data_type,&undo_size);		   
		TextboxInsertFunction(addr,paste_text,undo_size);
		qfree(paste_text);
		addr->textbox_insert_pt_char_pos += undo_size;
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
		if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
		{
			addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
		{
			addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_left_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
			&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
		addr->textbox_highlight_start_char = addr->textbox_highlight_end_char;
		addr->textbox_highlight_length = 0;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;
		addr->textbox_attr.textbox_highlight = FALSE;
		if (addr->textbox_attr.textbox_drawn == TRUE)
			TextboxDrawTextbox(textbox_id);
		undo_action = UNDO_EMPTY;
		EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
		EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
		break;	
	case UNDO_PASTE:	
		undo_action = UNDO_EMPTY;	
		LcdEnableInsertPt(FALSE,0,0,0);
		paste_text = (BYTE*) ClipboardGetItem(&data_type,&undo_size);
		if (data_type != CLIP_EMPTY)
			qfree(paste_text);
		StrTextboxAnalyze(addr);
		StrTextboxGetInsertPtPos(addr,addr->textbox_insert_pt_x,addr->textbox_insert_pt_y,
			&addr->textbox_insert_pt_char_pos, &xcoord, &ycoord);
		addr->textbox_insert_pt_char_pos -= undo_size;
		TextboxDelete(textbox_id,addr->textbox_insert_pt_char_pos,undo_size);
		if (undo_buffer.clipboard_type == CLIP_TEXT_DATA)
		{
			undo_buffer.clipboard_type = CLIP_EMPTY;
			TextboxInsertFunction (addr, (BYTE*)undo_buffer.clipboard_data, undo_buffer.clipboard_size);
			qfree(undo_buffer.clipboard_data);
			addr->textbox_insert_pt_char_pos += (undo_buffer.clipboard_size);			 
		}  
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
		if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
		{
			addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
		{
			addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_left_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
			&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
		addr->textbox_attr.textbox_highlight = FALSE;
		addr->textbox_highlight_length = 0;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;
		if (addr->textbox_attr.textbox_drawn == TRUE)
			TextboxDrawTextbox(textbox_id);
		EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
		EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
		return TRUE;
	default: break;
	}
	return TRUE;
}
/********************************************************
* Function:	TextboxInsertPtMove
* Purpose:	Get the last visible character
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	Error code
*           UI_ERR_RES_NOT_FOUND;
* Comment:	None
**********************************************************/
Err TextboxInsertPtMove (ObjectID textbox_id)
{
	Textbox *addr;
	BYTE object_type;
	WORD char_pos;
	SHORT new_xcoord, new_ycoord;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	StrTextboxAnalyze(addr);
	switch (addr->textbox_insert_pt_movement)
	{
	case MOVE_LEFT:	addr->textbox_insert_pt_char_pos -= 1;
		char_pos = addr->textbox_insert_pt_char_pos;
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,&new_xcoord,&new_ycoord);
		break;
	case MOVE_RIGHT: addr->textbox_insert_pt_char_pos += 1;
		char_pos = addr->textbox_insert_pt_char_pos;
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,&new_xcoord,&new_ycoord);
		break;
	case NO_MOVEMENT: return TRUE;
	default: break;
	}
	addr->textbox_insert_pt_x = new_xcoord;
	addr->textbox_insert_pt_y = new_ycoord;
	addr->textbox_insert_pt_char_pos = char_pos;
	addr->textbox_insert_pt_movement = NO_MOVEMENT;
	return TRUE;
}
/********************************************************
* Function:	TextboxAddKeyInChar
* Purpose:	Add the key in character to the content of a textbox object
* Scope:	Application
* Input:	textbox_id	DBID of a textbox object
char		ascii of the char
* Output:	None
* Return:	Error code
*           UI_ERR_NOT_VALID_CHAR_POS
*			ERR_UI_textbox_OVER_MAX_NUM_CHARS
* Comment:	the position of the insertion point is adjusted too
**********************************************************/
Err TextboxAddKeyInChar(ObjectID textbox_id, BYTE key)
{
	Textbox 	*addr;
	BYTE 		object_type;
	BYTE		temp_undo_action;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
    if (!addr->textbox_attr.textbox_drawn) return FALSE;
    if ((UBYTE)key < 32) return TRUE;
	
	temp_undo_action = undo_action;
	
	LcdEnableInsertPt(FALSE,0,0,0); 
    if (addr->textbox_attr.textbox_highlight == TRUE)
    {
		TextboxDelete(textbox_id, addr->textbox_highlight_start_char, addr->textbox_highlight_length);
		if (addr->textbox_highlight_length <0)
			addr->textbox_insert_pt_char_pos = addr->textbox_highlight_end_char;		 
		else addr->textbox_insert_pt_char_pos = addr->textbox_highlight_start_char;
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
		if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
		{
			addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
		{
			addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_left_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
			&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
		addr->textbox_highlight_start_char = addr->textbox_highlight_end_char;
		addr->textbox_attr.textbox_highlight = FALSE;
		addr->textbox_highlight_length = 0;
		addr->textbox_attr.textbox_insert_pt_visible = TRUE;
	}
	if (insert == FALSE)
    {
#ifdef DEBUG
		printf("\n Textbox Insert");
#endif
		if (addr->textbox_insert_pt_char_pos < addr->textbox_current_num_chars)		   
			TextboxDelete(textbox_id, addr->textbox_insert_pt_char_pos, 1);			   	
	}
	if (addr->textbox_current_num_chars < addr->textbox_max_chars)
	{
#ifdef DEBUG
		printf("\n Textbox Not Highlight Not Insert");
#endif
		//	  TextboxInsertText(textbox_id,&key,1);
		//	  addr->textbox_insert_pt_char_pos++;
		if(InsertTextFunction)
			InsertTextFunction(textbox_id, object_type, addr, key);
		else
		{
			TextboxInsertText(textbox_id,&key,1);
			addr->textbox_insert_pt_char_pos++;
		}
		
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
		if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
		{
			addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_right_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
		{
			addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
			addr->textbox_left_char_pos = -1;
			StrTextboxAnalyze(addr);
		}
		StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
			&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
	}
	else
	{
		TextboxDrawTextbox(textbox_id);
		return ERR_UI_TEXTBOX_OVER_MAX_NUM_CHARS;
		
	}
    if (addr->textbox_attr.textbox_drawn == TRUE)
        TextboxDrawTextbox(textbox_id);
	
	
	if (undo_buffer.clipboard_type != CLIP_EMPTY)
	{
		undo_buffer.clipboard_type = CLIP_EMPTY;
		if (undo_buffer.clipboard_data)
			qfree(undo_buffer.clipboard_data);
	}
	
	if (temp_undo_action != UNDO_TYPING)
	{
		typing_undo.focus_object_id = addr->identification.ui_object_id;
		typing_undo.start_char = addr->textbox_insert_pt_char_pos - 1;
		typing_undo.length = 1;
		backspace_undo.index = -1;
	}
	else if (temp_undo_action == UNDO_TYPING)
	{
		typing_undo.length ++;
	}			
	undo_action = UNDO_TYPING;
	addr->textbox_attr.textbox_dirty = TRUE;
	EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
	EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
	return TRUE;
}

/********************************************************
* Function:	TextboxGetLeftCharPos
* Purpose:		To get the left char pos of the text box
* Scope:		Application
* Input:		textbox_id		DBID of the text_box object
* Output:		left_char_pos	the character position
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err TextboxGetLeftCharPos(ObjectID textbox_id, WORD *left_char_pos)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*left_char_pos = addr->textbox_left_char_pos;
	return TRUE;
}

/********************************************************
* Function:	TextboxGetRightCharPos
* Purpose:		To get the right char pos of the text box
* Scope:		Application
* Input:		textbox_id		DBID of the text_box object
* Output:		right_char_pos	the character position
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err TextboxGetRightCharPos(ObjectID textbox_id, WORD *right_char_pos)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	*right_char_pos = addr->textbox_right_char_pos;
	return TRUE;
}

/********************************************************
* Function:	TextboxSetLeftCharPos
* Purpose:		To set the left char pos of the text box
* Scope:		Application
* Input:		textbox_id		DBID of the text_box object
*				left_char_pos	the character position
* Output:		None
* Return:      TRUE if no error
*				ERR_UI_INVALID_CHAR_POS
* Comment:     None
*********************************************************/
Err TextboxSetLeftCharPos(ObjectID textbox_id, WORD left_char_pos)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (left_char_pos <0 || left_char_pos > addr->textbox_current_num_chars) return ERR_UI_INVALID_CHAR_POS;
	addr->textbox_left_char_pos = left_char_pos;
	return TRUE;
}

/********************************************************
* Function:	TextboxSetRightCharPos
* Purpose:		To set the left char pos of the text box
* Scope:		Application
* Input:		textbox_id		DBID of the text_box object
*				right_char_pos	the character position
* Output:		None
* Return:      TRUE if no error
*				ERR_UI_INVALID_CHAR_POS
* Comment:     None
*********************************************************/
Err TextboxSetRightCharPos(ObjectID textbox_id, WORD right_char_pos)
{
	Textbox *addr;
	BYTE object_type;
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE) return ERR_UI_RES_NOT_FOUND;
	if (right_char_pos > addr->textbox_current_num_chars || right_char_pos <0) return ERR_UI_INVALID_CHAR_POS;
	addr->textbox_right_char_pos = right_char_pos;
	return TRUE;
}

/********************************************************
* Function:	TextboxInitTextbox
* Purpose:		1) to initialise the textbox object
2) to read the resource file
3) to create a corresponding textbox structure
in RAM
* Scope:		Application
* Input:		control_id	DBID of the line object
* Output:		None
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err TextboxInitTextbox(ObjectID textbox_id)
{
	BYTE *buffer;
	UWORD byte_return;
	void *temp;
	Textbox *addr;
	Err Error;
	BYTE object_type;
	USHORT temp_length;
	USHORT temp_length1;
	
	object_type = TEXTBOX;
	Error = UIAddressToLookupTable(textbox_id,object_type,&temp); /*put the pointer to the DBID											  lookup table */
	if (Error != TRUE) return Error;
	addr = (Textbox *)temp;
	if (!ResOpen(textbox_id)) /*check whether the resource file									 is opened */
	{
		Error = ResOpen(textbox_id);
		if (Error != TRUE) return Error;
	}
	addr->identification.ui_object_id = textbox_id;
	/* textbox 0 */
	addr->identification.ui_object_type = TEXTBOX;
	/* textbox 1 */
	ResGetField(textbox_id,1,&buffer,&byte_return);
	addr->identification.table_related = *(ObjectID*)buffer;
    qfree(buffer);
	/* textbox 2 */
	ResReadField(textbox_id,2,0,2,&buffer,&byte_return);
	addr->bounds.xcoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,2,2,2,&buffer,&byte_return);
	addr->bounds.ycoord = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,2,4,2,&buffer,&byte_return);
	addr->bounds.width = *(SHORT*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,2,6,2,&buffer,&byte_return);
	addr->bounds.height = *(SHORT*)buffer;
    qfree(buffer);
	/* textbox 3 */
	ResGetField(textbox_id,3,&buffer,&byte_return);
	
	temp_length = strlen(buffer);
	temp_length1 = ((temp_length)/STEP_SIZE + 1) * STEP_SIZE;
    addr->textbox_string = (BYTE*)qmalloc(temp_length1*sizeof(BYTE));
	strcpy(addr->textbox_string,buffer);
    qfree(buffer);
    addr->textbox_current_num_chars = temp_length;
	
	/* textbox 4 */
	ResGetField(textbox_id,4,&buffer,&byte_return);
	addr->textbox_style = *buffer;
    qfree(buffer);
	/* textbox 5 */
	ResGetField(textbox_id,5,&buffer,&byte_return);
	addr->textbox_back_line = *buffer;
    qfree(buffer);
	/* textbox 6 */
	ResGetField(textbox_id,6,&buffer,&byte_return);
	addr->textbox_font_id = *buffer;
    qfree(buffer);
	/* textbox 7 */
	ResGetField(textbox_id,7,&buffer,&byte_return);
	addr->textbox_font_color = UIColorConversion(*buffer);
    qfree(buffer);
	/* textbox 8 */
	ResGetField(textbox_id,8,&buffer,&byte_return);
	addr->textbox_background_color = UIColorConversion(*buffer);
    qfree(buffer);
	/* textbox 9 */
	ResGetField(textbox_id,9,&buffer,&byte_return);
	addr->textbox_max_chars = *(WORD*)buffer;
    qfree(buffer);
	/* textbox 10 */
	ResGetField(textbox_id,10,&buffer,&byte_return);
	addr->textbox_left_char_pos = *(WORD*)buffer;
    qfree(buffer);
	/* TEXTBOX 11 */
	ResGetField(textbox_id,11,&buffer,&byte_return);
	addr->textbox_right_char_pos = *(WORD*)buffer;
    qfree(buffer);
	
	StrTextboxAnalyze(addr);
	
	/* textbox 12 */
	ResGetField(textbox_id,12,&buffer,&byte_return);
	addr->textbox_insert_pt_char_pos = *(WORD*)buffer;
    qfree(buffer);
	
	StrTextboxAnalyze(addr);
	StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
						  &(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
	
	addr->textbox_insert_pt_movement = NO_MOVEMENT;
	
	/* textbox 13 */
	ResGetField(textbox_id,13,&buffer,&byte_return);
	addr->textbox_highlight_start_char = *(WORD*)buffer;
    qfree(buffer);
	
	/* textbox 14 */
	ResGetField(textbox_id,14,&buffer,&byte_return);
	addr->textbox_highlight_end_char = *(WORD*)buffer;
    qfree(buffer);
	
    addr->textbox_highlight_length = addr->textbox_highlight_end_char - addr->textbox_highlight_start_char;
	addr->textbox_repeat_count = 0;
	
	/* textbox 15 */
	addr->textbox_attr.textbox_drawn = FALSE;
	ResReadField(textbox_id,15,0,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_active = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,15,2,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_enable = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,15,4,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_dirty = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,15,6,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_highlight = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,15,8,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_insert_pt_visible = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResReadField(textbox_id,15,10,2,&buffer,&byte_return);
	addr->textbox_attr.textbox_visible = *(BOOLEAN*)buffer;
    qfree(buffer);
	ResClose(textbox_id);
	return TRUE;
}

/********************************************************
* Function:	TextboxPasteString
* Purpose:		This function is called to paste string into textbox object
* Scope:		Application
* Input:		textbox_id
paste_string
* Output:		None
* Return:      TRUE if no error
* Comment:     None
*********************************************************/
Err TextboxPasteString(ObjectID textbox_id, BYTE *paste_string)
{
    BYTE            object_type;
    Textbox         *addr; 
    WORD            paste_size = 0, cut_start_char = 0, cut_length = 0;
    ObjectBounds    bounds;
	
    if (UISearchForAddress(textbox_id, &object_type, (void**)&addr) != TRUE)
        return ERR_UI_RES_NOT_FOUND;
	
    paste_size = strlen(paste_string);
	
	if (paste_string == NULL) return TRUE;
	
    if (addr->textbox_attr.textbox_highlight == FALSE)
	{
		if ((paste_size + addr->textbox_current_num_chars) > addr->textbox_max_chars)
			return FALSE;
	}
	else
	{
        if ((paste_size + addr->textbox_current_num_chars - abs(addr->textbox_highlight_length)) > addr->textbox_max_chars)     
			return FALSE;
    }
	
    undo_action = UNDO_EMPTY;	
    LcdEnableInsertPt(FALSE,0,0,0);	
    if (addr->textbox_attr.textbox_highlight == FALSE)	   
	{	 
		TextboxInsertString(textbox_id, paste_string);
        addr->textbox_insert_pt_char_pos += strlen(paste_string);
	}
	else
	{
		cut_start_char = addr->textbox_highlight_start_char;
		cut_length = addr->textbox_highlight_length;
		if (addr->textbox_highlight_length < 0)
		{
			cut_start_char += addr->textbox_highlight_length;
			cut_length = abs(cut_length);
		}
		
		if (undo_buffer.clipboard_type == CLIP_TEXT_DATA)
		{
			undo_buffer.clipboard_type = CLIP_EMPTY;
			undo_buffer.clipboard_size = 0;
            qfree(undo_buffer.clipboard_data);
		}
		
		TextboxDeleteString(textbox_id, addr->textbox_highlight_start_char, addr->textbox_highlight_length);
		addr->textbox_insert_pt_char_pos = cut_start_char;
		TextboxInsertString(textbox_id, paste_string); 
		addr->textbox_current_num_chars = strlen(addr->textbox_string);
		addr->textbox_insert_pt_char_pos += strlen(paste_string);
    }
	
    addr->textbox_right_char_pos = -1;
	StrTextboxAnalyze(addr);
	if (addr->textbox_insert_pt_char_pos < addr->textbox_left_char_pos )   
	{
		addr->textbox_left_char_pos = addr->textbox_insert_pt_char_pos;
		addr->textbox_right_char_pos = -1;
		StrTextboxAnalyze(addr);
	}
	else if (addr->textbox_insert_pt_char_pos > addr->textbox_right_char_pos)
	{
		addr->textbox_right_char_pos = addr->textbox_insert_pt_char_pos;
		addr->textbox_left_char_pos = -1;
		StrTextboxAnalyze(addr);
	}
    
	StrTextboxCharPosToXY(addr,addr->textbox_insert_pt_char_pos,
		&(addr->textbox_insert_pt_x), &(addr->textbox_insert_pt_y));
    addr->textbox_highlight_start_char = addr->textbox_highlight_end_char;
    addr->textbox_highlight_length = 0;
    addr->textbox_attr.textbox_insert_pt_visible = TRUE;
    addr->textbox_attr.textbox_highlight = FALSE;  
	addr->textbox_attr.textbox_dirty = TRUE;
    EvtAppendEvt(EVT_TEXTBOX_CHANGED, textbox_id, 0, 0, (void*)addr);
    EvtAppendEvt(EVT_TEXTBOX_MODIFIED, textbox_id, 0, 0, (void*)addr);
    return TRUE;
}

/********************************************************
* Function:    TextboxInsertString
* Purpose:     This function is called to insert a string to
textbox object
* Scope:		Application
* Input:       textbox_id            
paste_string
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     Won't re-draw the object for u
*********************************************************/
Err TextboxInsertString(ObjectID textbox_id, BYTE *paste_string)
{
    BYTE *text_pointer, object_type;
    WORD insert_pos, total_length, org_total, paste_size = 0;
	WORD i, count=0, add_length, buffer_size;
    Textbox *addr;
	
	if (UISearchForAddress(textbox_id, &object_type, (void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
    paste_size = strlen(paste_string);
	
	org_total = strlen(addr->textbox_string) + 1;
	total_length = org_total + paste_size;
	buffer_size = ((org_total-1)/STEP_SIZE + 1) * STEP_SIZE;
	insert_pos = addr->textbox_insert_pt_char_pos;
	
	if (total_length >= buffer_size)
	{
		while(total_length >= buffer_size)
			buffer_size += STEP_SIZE;		
		
        text_pointer = (BYTE *)qmalloc(buffer_size*sizeof(BYTE));
		if (insert_pos > org_total-1)
			add_length = 1;
		else
			add_length = (org_total-insert_pos);
		
		i = insert_pos;
		while (i)
		{
			i--;
			text_pointer[i] = addr->textbox_string[i];
			count++;
		}
		/* Paste the text from clipboard to the textbox */
		i = paste_size;
		while (i)
		{
			i--;
            text_pointer[count] = *paste_string++; 
			count++;
		}
		i = add_length;
		while (i)
		{
			i--;
			text_pointer[count] = addr->textbox_string[insert_pos++];
			count++;
		}
		
        qfree (addr->textbox_string);
		addr->textbox_string = text_pointer;
	}
	else
	{
		i = org_total;
		while (i>= insert_pos)
		{
			addr->textbox_string[total_length--] = addr->textbox_string[org_total--];
			i--;
		}
		i = paste_size;
		while (i)
		{
			i--;
            addr->textbox_string[insert_pos++] = *paste_string++; 
		}
	}
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
}

/********************************************************
* Function:    TextboxDeleteString
* Purpose:     This function is called to delete a string
in the textbox object                
* Scope:		Application
* Input:       textbox_id            
start_char
cut_length
* Output:		None
* Return:      TRUE if no error
ERR_UI_RES_NOT_FOUND
* Comment:     Won't re-draw the object for u
*********************************************************/
Err TextboxDeleteString(ObjectID textbox_id, WORD start_char, WORD cut_length)
{
	Textbox *addr;
	BYTE object_type;
	WORD total_length, text_cont_text, add_length, i;
	
	
	if (UISearchForAddress(textbox_id,&object_type,(void**)&addr) != TRUE)
		return ERR_UI_RES_NOT_FOUND;
	
	if (cut_length < 0)
	{
		start_char += cut_length;
		cut_length = -cut_length;
	}
	
	total_length = strlen(addr->textbox_string)+1;
	text_cont_text = start_char+cut_length;
	
	if (text_cont_text > total_length)
		add_length = 0;
	else
		add_length = total_length-text_cont_text;
	
	i = add_length;
	while (i)
	{	
		i--;
		addr->textbox_string[start_char++] = addr->textbox_string[text_cont_text++];
	}
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
	return TRUE;
}

/********************************************************
* Function: TextboxCutBackspaceHighlightText
* Purpose:  Delete the specified range of characters from
*			the textbox and redraw the textbox
* Scope:	Application
* Input:	textbox_id		DBID of the spceified textbox object
* Output:	None
* Return:	None
* Comment:	None
**********************************************************/
void TextboxCutBackspaceHighlightText(Textbox *addr)
{
	BYTE *text_pointer;
	WORD total_length, add_length, text_cont_text, i, count;
	WORD cut_start_char, cut_length;
	
	cut_start_char = addr->textbox_highlight_start_char;
	cut_length = addr->textbox_highlight_length;
	
	if (!addr->textbox_attr.textbox_drawn)
		StrTextboxAnalyze(addr);
	if (addr->textbox_highlight_length < 0)
	{
		cut_start_char += addr->textbox_highlight_length;
		cut_length = abs(cut_length);
	}
    text_pointer = (BYTE*)qmalloc((cut_length+1)*sizeof(BYTE));
	total_length = strlen(addr->textbox_string)+1;
	text_cont_text = cut_start_char + cut_length;
	add_length = total_length - text_cont_text;
	
	/* Extract the highlight region to text_pointer*/
    if (undo_buffer.clipboard_type == CLIP_TEXT_DATA &&
        undo_buffer.clipboard_data)
        qfree(undo_buffer.clipboard_data);
	
    undo_buffer.clipboard_type = CLIP_TEXT_DATA;
    undo_buffer.clipboard_size = cut_length;
    undo_buffer.clipboard_data = (BYTE*)qmalloc((cut_length+1)*sizeof(BYTE));
    StrExtract(addr->textbox_string,cut_start_char,cut_length,undo_buffer.clipboard_data);
	
	count = cut_start_char;
	
	i = add_length;
	while (i >=0)
	{
		i--;
		addr->textbox_string[count] = addr->textbox_string[text_cont_text++];
		count++;
	}	
	
	addr->textbox_current_num_chars = strlen(addr->textbox_string);
	addr->textbox_attr.textbox_highlight = FALSE;
    undo_action = UNDO_BACKSPACE_HIGHLIGHT;
    qfree(text_pointer);
}

