/*
================================ 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        :   strapi.c
Author(s)   :   Brian Lee, Thomas Cheng
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   String API calls
Revision    :   1.1
Note        :   None
===========================================================================
*/              



#include "stdafx.h"
#include "StrApi.h"
#include "LcdApi.h"

#define FIELD_LINE_STEPS 128  // 128 lines


/*	Function	: _strrev
*	Purpose		: To reverse the characters in a string
*  Scope		: Application/System
*	Input		: string	  the string pointer	
*	Output      : non
*	Comment		: Author(s)   :   Konstantin Forostyan
Company     :   Top Technology (85) Ltd
*/

void _strrev(char* string)
{
	char ch, *str_end;
	
	str_end = string;
	while(*str_end != 0) str_end++;
	while(str_end > string)
	{
		ch = *(string);
		*(string++) = *(--str_end);
		*(str_end) = ch;
	}
}

/*	Function	: StrExtract
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrExtract(BYTE *string1, WORD start, WORD length, BYTE *string2)
{
	string1 += start;
	if (length > 0) {
		do {*string2++ = *string1++;} while (--length);
	}
	*string2 = 0;
}

/*	Function	: StrGetWidth
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
UWORD StrGetWidth(BYTE *string, BYTE font)
{
	UWORD width = SPACE_CHAR;
	UWORD text;
	const BYTE *text_width = &FontWidth[font * NUM_OF_CHARS];
	
	while (text = *string++) {
        if (text == 11) width += *(UBYTE*)string++;
		else
			width += SPACE_CHAR + (UWORD)text_width[(UBYTE)text];
	}
    return (UWORD)width;
}

/*	Function	: StrAnalyzeWord
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrAnalyzeWord(BYTE *string, BYTE font, SHORT width, WORD *len, SHORT *wordw)
{
	const BYTE *fontw = &FontWidth[font * NUM_OF_CHARS];
	WORD length, word_width;
	
	length = 0; word_width = SPACE_CHAR;
	do
	{
		if (*string == 0 || *string == '\r' || word_width + SPACE_CHAR + fontw[(UBYTE)*string] > width)
			break;
		
		length += 1;
		word_width += SPACE_CHAR + fontw[(UBYTE)*string];
	}
	while (*string++ != ' ' || word_width > width);
	*len = length; *wordw = word_width;
}

/*	Function	: StrAnalyzeLine
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrAnalyzeLine(Field *field_ptr)
{
	
	
	SHORT width, height;
	WORD str_pos = 0, length;
	SHORT str_width = 0, word_width, str_height = SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id];
	BYTE *string = field_ptr->field_string;
	WORD total_lines, prev_total, i;
	LineInfo *new_lineinfo;
	
	//	printf("\n Enter String Analyze Line");
	
	if (field_ptr->identification.table_related == 0xFFFF)
	{
		width = field_ptr->bounds.width - (SHORT)(field_ptr->field_style)*2;
		height = field_ptr->bounds.height - (SHORT)(field_ptr->field_style)*2;
	}
	else
	{
		width = field_ptr->screen_bounds.width - (SHORT)(field_ptr->field_style)*2;
		height = field_ptr->screen_bounds.height - (SHORT)(field_ptr->field_style)*2;
	}
	field_ptr->field_num_lines_displayed = height / (str_height);
	
	if (field_ptr->field_lineinfo == NULL)
	{
		field_ptr->field_lineinfo = (LineInfo *)qmalloc(FIELD_LINE_STEPS*sizeof(LineInfo));
		prev_total = FIELD_LINE_STEPS-1;
	}
	else {
		prev_total =  (((field_ptr->field_total_num_lines-1)/FIELD_LINE_STEPS)+1)*FIELD_LINE_STEPS-1;
	}
	
	total_lines = 0;
	field_ptr->field_lineinfo[total_lines].start = 0;
	field_ptr->field_lineinfo[total_lines].length = 0;
	
	while ((UBYTE)*string)
	{
		StrAnalyzeWord(string, field_ptr->field_font_id, (SHORT)width, &length, &word_width);
		if(length == 0 && *string != '\r')
			break;
		
		if (str_width + word_width <= width)
		{
			str_pos += length;
			field_ptr->field_lineinfo[total_lines].length = str_pos
				- field_ptr->field_lineinfo[total_lines].start;
			str_width += word_width - SPACE_CHAR;
			string += length;
		}
		else
		{
			if (str_width < width)
				field_ptr->field_lineinfo[total_lines].length = str_pos
				- field_ptr->field_lineinfo[total_lines].start;
			
			if (total_lines >= prev_total) {
				prev_total += FIELD_LINE_STEPS;
				new_lineinfo = (LineInfo *)qmalloc(prev_total*sizeof(LineInfo));
				i = total_lines;
				do {
					new_lineinfo[i] = field_ptr->field_lineinfo[i];
				} while (i--);
				qfree(field_ptr->field_lineinfo);
				field_ptr->field_lineinfo = new_lineinfo;
			}
			total_lines++;
			
			field_ptr->field_lineinfo[total_lines].start = str_pos;
			str_pos += length;
			field_ptr->field_lineinfo[total_lines].length = length;
			str_width = word_width - SPACE_CHAR;
			string += length;
		}
		
		//Bug Fixed 10-Feb-2001
		//Regard the ' ' as normal character, dont special handle
		//------------------------------------------------------ Deleting Codes
		/*
		while (*string == ' ')
		{
		str_pos++;
		str_width += SPACE_CHAR + FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string++];
		if (str_width < width)
		field_ptr->field_lineinfo[total_lines].length = str_pos
		- field_ptr->field_lineinfo[total_lines].start;
		}
		*/
		//------------------------------------------------------ Deleting Codes
		while (*string == '\r')
		{
			str_pos++;
			
			if (total_lines >= prev_total) {
				prev_total += FIELD_LINE_STEPS;
				new_lineinfo = (LineInfo *)qmalloc(prev_total*sizeof(LineInfo));
				i = total_lines;
				do
				{
					new_lineinfo[i] = field_ptr->field_lineinfo[i];
				} while (i--);
				qfree(field_ptr->field_lineinfo);
				field_ptr->field_lineinfo = new_lineinfo;
			}
			total_lines++;
			
			field_ptr->field_lineinfo[total_lines].start = str_pos;
			field_ptr->field_lineinfo[total_lines].length = str_pos
				- field_ptr->field_lineinfo[total_lines].start;
			str_width = 0;
			string++;
		}
		
		while (*string == '\t')
		{
			str_pos++;
			str_width += SPACE_CHAR + FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string++];
			if (str_width < width)
				field_ptr->field_lineinfo[total_lines].length = str_pos
				- field_ptr->field_lineinfo[total_lines].start;
		}
	}
	total_lines++;
	if (field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed > total_lines)
		field_ptr->field_num_lines_displayed = total_lines - field_ptr->field_top_line_num;
	field_ptr->field_total_num_lines = total_lines;
}

/*	Function	: StrChopString
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrChopString(ObjectBounds *bounds, BYTE *string, BYTE font,
				   BOOLEAN dotdot, SHORT margin)
{
	SHORT xcoord1 = bounds->xcoord, ycoord1 = bounds->ycoord;
	ObjectBounds bounds2;
	BYTE strdotdot[4] = "...";
	BYTE *temp_string = string;
	xcoord1 += margin;
	ycoord1 += margin;
	
	while ((UBYTE)*temp_string)
	{
		xcoord1 += SPACE_CHAR;
		if (dotdot == DOTDOT)
		{
			if (xcoord1 + FontWidth[font * NUM_OF_CHARS + (UBYTE)*temp_string] + StrGetWidth((BYTE *)strdotdot, font) >
				bounds->xcoord + bounds->width)
			{
				bounds2.xcoord = xcoord1 - SPACE_LINE;
				bounds2.ycoord = ycoord1;
				bounds2.width = StrGetWidth((BYTE *)strdotdot, font);
				strcpy((char *)temp_string, (char *)strdotdot);
				xcoord1 += bounds2.width - 2*SPACE_LINE;
				break;
			}
		}
		xcoord1 += FontWidth[font * NUM_OF_CHARS + (UBYTE)*temp_string++];
		if (dotdot == NO_DOTDOT)
		{
			if (xcoord1 + FontWidth[font * NUM_OF_CHARS + (UBYTE)*temp_string] + SPACE_CHAR >
				bounds->xcoord + bounds->width)
			{
				*temp_string = 0;
				break;
			}
		}
	}
	xcoord1 += SPACE_CHAR;
}

/*	Function	: StrGetInsertPtPos
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrGetInsertPtPos(Field *field_ptr, SHORT xcoord, SHORT ycoord,
					   WORD *insert_pos, SHORT *insert_pt_x, SHORT *insert_pt_y)
{
	WORD line;
	SHORT xcoord1, ycoord1, width, str_width;
	BYTE *string = field_ptr->field_string;
	
	if (field_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = field_ptr->bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->bounds.ycoord + (SHORT)(field_ptr->field_style);
		width = field_ptr->bounds.width - (SHORT)(field_ptr->field_style)*2;
	}
	else
	{
		xcoord1 = field_ptr->screen_bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->screen_bounds.ycoord + (SHORT)(field_ptr->field_style);
		width = field_ptr->screen_bounds.width - (SHORT)(field_ptr->field_style)*2;
	}
	if (ycoord < ycoord1)
	{
		line = field_ptr->field_top_line_num;
		xcoord = 0;
	}
	else if (ycoord >= ycoord1 + field_ptr->field_num_lines_displayed * (SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]))
	{
		line = field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1;
		xcoord = xcoord1 + width;
	}
	else
	{
		line = field_ptr->field_top_line_num + (ycoord - ycoord1)/(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
	}
	*insert_pt_y = ycoord1 + (line - field_ptr->field_top_line_num) * (SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
	str_width = xcoord1;
	*insert_pos = field_ptr->field_lineinfo[line].start;
	string += *insert_pos;
	if (xcoord >= str_width)
		while(*insert_pos + 1 < field_ptr->field_lineinfo[line].start + field_ptr->field_lineinfo[line].length)
		{
			if (xcoord >= str_width && xcoord < str_width + FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR)
				break;
			str_width += FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string++] + SPACE_CHAR;
			(*insert_pos)++;
		}
		*insert_pt_x = str_width;
		// Change
		//	if (*string != 0 && xcoord - str_width > FONT_WIDTH[field_ptr->field_font_id][(UBYTE)*string]/2)
		
		if ((UBYTE)*string != '\r' && (UBYTE)*string != 0 && xcoord - str_width > FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string]/2)
		{
			(*insert_pos)++;
			*insert_pt_x += FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR;
		}
}

/*	Function	: StrCharPosToXY
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrCharPosToXY(Field *field_ptr, WORD char_pos, SHORT *xcoord, SHORT *ycoord)
{
	WORD i;
    SHORT xcoord1, ycoord1;
    UWORD str_width;
	BYTE *char_string, *string = field_ptr->field_string;
    BYTE char_buf[128*sizeof(BYTE)];
	
	char_string = char_buf;
	
	if (field_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = field_ptr->bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->bounds.ycoord + (SHORT)(field_ptr->field_style);
	}
	else
	{
		xcoord1 = field_ptr->screen_bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->screen_bounds.ycoord + (SHORT)(field_ptr->field_style);
	}
	
    if (char_pos < field_ptr->field_lineinfo[field_ptr->field_top_line_num].start
        || char_pos > field_ptr->field_lineinfo[field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1].start
        + field_ptr->field_lineinfo[field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1].length)
        return;
	
    for (i = field_ptr->field_top_line_num; i < field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1; i++)
	{	
		if (char_pos >= field_ptr->field_lineinfo[i].start
			&& char_pos < field_ptr->field_lineinfo[i+1].start)
		{
			if (char_pos <= field_ptr->field_lineinfo[i].start + field_ptr->field_lineinfo[i].length)
				StrExtract(string, field_ptr->field_lineinfo[i].start, char_pos - field_ptr->field_lineinfo[i].start, char_string);
			else
				StrExtract(string, field_ptr->field_lineinfo[i].start, field_ptr->field_lineinfo[i].length, char_string);
			str_width = StrGetWidth(char_string, field_ptr->field_font_id);
			*xcoord = xcoord1 + str_width - SPACE_CHAR;
			*ycoord = ycoord1 + (i - field_ptr->field_top_line_num)*(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
			break;
		}
	}
	
	if (i == field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1)
	{
		if (char_pos <= field_ptr->field_lineinfo[i].start + field_ptr->field_lineinfo[i].length)
			StrExtract(string, field_ptr->field_lineinfo[i].start, char_pos - field_ptr->field_lineinfo[i].start, char_string);
		else
			StrExtract(string, field_ptr->field_lineinfo[i].start, field_ptr->field_lineinfo[i].length, char_string);
		str_width = StrGetWidth(char_string, field_ptr->field_font_id);
		*xcoord = xcoord1 + str_width - SPACE_CHAR;
		*ycoord = ycoord1 + (i - field_ptr->field_top_line_num)*(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
	}
}


/*	Function	: StrXYToCharPos
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrXYToCharPos(Field *field_ptr, SHORT xcoord, SHORT ycoord, WORD *char_pos)
{
	WORD line;
	SHORT xcoord1, ycoord1, width, str_width;
	BYTE *string = field_ptr->field_string;
	if (field_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = field_ptr->bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->bounds.ycoord + (SHORT)(field_ptr->field_style);
		width = field_ptr->bounds.width - (SHORT)(field_ptr->field_style)*2;
	}
	else
	{
		xcoord1 = field_ptr->screen_bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->screen_bounds.ycoord + (SHORT)(field_ptr->field_style);
		width = field_ptr->screen_bounds.width - (SHORT)(field_ptr->field_style)*2;
	}
	if (ycoord < ycoord1)
	{
		line = field_ptr->field_top_line_num;
		xcoord = 0;
	}
	else if (ycoord >= ycoord1 + field_ptr->field_num_lines_displayed * (SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]))
	{
		line = field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1;
		xcoord = xcoord1 + width;
	}
	else
	{
		line = field_ptr->field_top_line_num + (ycoord - ycoord1)/(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
	}
	str_width = xcoord1;
	*char_pos = field_ptr->field_lineinfo[line].start;
	string += *char_pos;
	if (xcoord >= str_width)
		while(*char_pos + 1 < field_ptr->field_lineinfo[line].start + field_ptr->field_lineinfo[line].length)
		{
			if (xcoord >= str_width && xcoord < str_width + FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR)
				break;
			str_width += FontWidth[field_ptr->field_font_id * NUM_OF_CHARS + (UBYTE)*string++] + SPACE_CHAR;
			(*char_pos)++;
		}
}

/*	Function	: StrTextboxGetInsertPtPos
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrTextboxGetInsertPtPos(Textbox *tb_ptr, SHORT xcoord, SHORT ycoord,
							  WORD *insert_pos, SHORT *insert_pt_x, SHORT *insert_pt_y)
{
	WORD line;
	SHORT xcoord1, ycoord1, width, str_width;
	BYTE *string = tb_ptr->textbox_string;
	if (tb_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = tb_ptr->bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
		width = tb_ptr->bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	else
	{
		xcoord1 = tb_ptr->screen_bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->screen_bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
		width = tb_ptr->screen_bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	if (ycoord < ycoord1)
	{
		xcoord = 0;
	}
	else if (ycoord >= ycoord1 + SPACE_LINE + FONT_HEIGHT[tb_ptr->textbox_font_id])
	{
		xcoord = xcoord1 + width;
	}
	*insert_pt_y = ycoord1;
	str_width = xcoord1;
	*insert_pos = tb_ptr->textbox_left_char_pos;
	string += *insert_pos;
	if (xcoord >= str_width)
		while(*insert_pos + 1 < tb_ptr->textbox_left_char_pos + tb_ptr->textbox_num_chars_displayed)
		{
			if (xcoord >= str_width && xcoord < str_width + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR)
				break;
			str_width += FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string++] + SPACE_CHAR;
			(*insert_pos)++;
		}
		*insert_pt_x = str_width;
		if (*string != 0 && xcoord - str_width > FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string]/2)
		{
			(*insert_pos)++;
			//Ipaty		*insert_pt_x += FONT_WIDTH[tb_ptr->textbox_font_id][(UBYTE)*string] + SPACE_CHAR;
			*insert_pt_x += FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR;
		}
}

/*	Function	: StrTextboxCharPosToXY
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrTextboxCharPosToXY(Textbox *tb_ptr, WORD char_pos, SHORT *xcoord, SHORT *ycoord)
{
	WORD i;
    SHORT xcoord1, ycoord1, width, height;
    UWORD str_width;
	BYTE *char_string, *string = tb_ptr->textbox_string;
    BYTE char_buf[128*sizeof(BYTE)];
	
	char_string = char_buf;
	
	if (tb_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = tb_ptr->bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
	}
	else
	{
		xcoord1 = tb_ptr->screen_bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->screen_bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
	}
	StrExtract(string, tb_ptr->textbox_left_char_pos, char_pos - tb_ptr->textbox_left_char_pos, char_string);
	str_width = StrGetWidth(char_string, tb_ptr->textbox_font_id);
	*xcoord = xcoord1 + str_width - SPACE_CHAR;
	*ycoord = ycoord1;
}

/*	Function	: StrTextboxXYToCharPos
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrTextboxXYToCharPos(Textbox *tb_ptr, SHORT xcoord, SHORT ycoord, WORD *char_pos)
{
	WORD line;
	SHORT xcoord1, ycoord1, width, str_width;
	BYTE *string = tb_ptr->textbox_string;
	if (tb_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = tb_ptr->bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
		width = tb_ptr->bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	else
	{
		xcoord1 = tb_ptr->screen_bounds.xcoord + (SHORT)(tb_ptr->textbox_style);
		ycoord1 = tb_ptr->screen_bounds.ycoord + (SHORT)(tb_ptr->textbox_style);
		width = tb_ptr->screen_bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	if (ycoord < ycoord1)
	{
		xcoord = 0;
	}
	else if (ycoord >= ycoord1 + SPACE_LINE + FONT_HEIGHT[tb_ptr->textbox_font_id])
	{
		xcoord = xcoord1 + width;
	}
	str_width = xcoord1;
	*char_pos = tb_ptr->textbox_left_char_pos;
	string += *char_pos;
	if (xcoord >= str_width)
		while(*char_pos + 1 < tb_ptr->textbox_left_char_pos + tb_ptr->textbox_num_chars_displayed)
		{
			if (xcoord >= str_width && xcoord < str_width + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] + SPACE_CHAR)
				break;
			str_width += FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string++] + SPACE_CHAR;
			(*char_pos)++;
		}
}

/*	Function	: StrTextboxAnalyze
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrTextboxAnalyze(Textbox *tb_ptr)
{
	WORD width, xcoord2, word_width=0, length=0;
	ObjectBounds bounds1;
	BYTE *string = tb_ptr->textbox_string;
	if (tb_ptr->identification.table_related == 0xFFFF)
	{
		width = tb_ptr->bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	else
	{
		width = tb_ptr->screen_bounds.width - (SHORT)(tb_ptr->textbox_style)*2;
	}
	if (tb_ptr->textbox_left_char_pos != -1)
	{
		string += tb_ptr->textbox_left_char_pos;
		while (*string != 0 && word_width + SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] <= width)
		{
			length++;
			word_width += SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string++];
		}
		tb_ptr->textbox_right_char_pos = tb_ptr->textbox_left_char_pos + length - 1;
	}
	else
	{
		string += tb_ptr->textbox_right_char_pos;
		while (length-1 != tb_ptr->textbox_right_char_pos && word_width + SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] <= width)
		{
			length++;
			word_width += SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string--];
		}
		tb_ptr->textbox_left_char_pos = tb_ptr->textbox_right_char_pos - length + 1;
		string = tb_ptr->textbox_string + tb_ptr->textbox_right_char_pos + 1;
		while (*string != 0 && word_width + SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string] <= width)
		{
			length++;
			word_width += SPACE_CHAR + FontWidth[tb_ptr->textbox_font_id* NUM_OF_CHARS + (UBYTE)*string++];
		}
		tb_ptr->textbox_right_char_pos = tb_ptr->textbox_left_char_pos + length - 1;
	}
	tb_ptr->textbox_num_chars_displayed = length;
}

/*	Function	: StrCharPosToXYForTable
*	Purpose		:
*  Scope		:
*	Input		:
*	Output      :
*	Comment		:
*/
void StrCharPosToXYForTable(Field *field_ptr, WORD char_pos, SHORT *xcoord, SHORT *ycoord)
{
	WORD i;
    SHORT xcoord1, ycoord1;
    UWORD str_width;
	BYTE *char_string, *string = field_ptr->field_string;
    BYTE char_buf[128*sizeof(BYTE)];
	
	char_string = char_buf;
	
	if (field_ptr->identification.table_related == 0xFFFF)
	{
		xcoord1 = field_ptr->bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->bounds.ycoord + (SHORT)(field_ptr->field_style);
	}
	else
	{
		xcoord1 = field_ptr->screen_bounds.xcoord + (SHORT)(field_ptr->field_style);
		ycoord1 = field_ptr->screen_bounds.ycoord + (SHORT)(field_ptr->field_style);
	}
	
    if (char_pos < field_ptr->field_lineinfo[field_ptr->field_top_line_num].start
        || char_pos > field_ptr->field_lineinfo[field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1].start
        + field_ptr->field_lineinfo[field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1].length)
    {
        *xcoord     =   -100;
        *ycoord     =   -100;
        return;
    }
	
    for (i = field_ptr->field_top_line_num; i < field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1; i++)
	{
		if (char_pos >= field_ptr->field_lineinfo[i].start
			&& char_pos < field_ptr->field_lineinfo[i+1].start)
		{
			if (char_pos <= field_ptr->field_lineinfo[i].start + field_ptr->field_lineinfo[i].length)
				StrExtract(string, field_ptr->field_lineinfo[i].start, char_pos - field_ptr->field_lineinfo[i].start, char_string);
			else
				StrExtract(string, field_ptr->field_lineinfo[i].start, field_ptr->field_lineinfo[i].length, char_string);
			str_width = StrGetWidth(char_string, field_ptr->field_font_id);
			*xcoord = xcoord1 + str_width - SPACE_CHAR;
			*ycoord = ycoord1 + (i - field_ptr->field_top_line_num)*(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
			break;
		}
	}
	
	if (i == field_ptr->field_top_line_num + field_ptr->field_num_lines_displayed - 1)
	{
		if (char_pos <= field_ptr->field_lineinfo[i].start + field_ptr->field_lineinfo[i].length)
			StrExtract(string, field_ptr->field_lineinfo[i].start, char_pos - field_ptr->field_lineinfo[i].start, char_string);
		else
			StrExtract(string, field_ptr->field_lineinfo[i].start, field_ptr->field_lineinfo[i].length, char_string);
		str_width = StrGetWidth(char_string, field_ptr->field_font_id);
		*xcoord = xcoord1 + str_width - SPACE_CHAR;
		*ycoord = ycoord1 + (i - field_ptr->field_top_line_num)*(SPACE_LINE + FONT_HEIGHT[field_ptr->field_font_id]);
	}	
}
