/*******************************************************************************

					CONDAT (UK)

********************************************************************************                                                                              

 This software product is the property of Condat (UK) Ltd and may not be
 disclosed to any third party without the express permission of the owner.                                 
                                                                              
********************************************************************************

 $Project name:	                                                      
 $Project code:	                                                           
 $Module:		
 $File:		    ATBEditor.c
 $Revision:		                                                      
                                                                              
 $Author:		SH - Condat(UK)                                                         
 $Date:		                                                          
                                                                               
********************************************************************************
                                                                              
 Description: ATB Editor component.
    
                        
********************************************************************************

 $History: ATBEditor.c
 
       Feb 02, 2006 DR: OMAPS00061468 - x0035544.
       Description: SAT 27.22.4.22.2 SET UP IDLE MODE TEXT (Icon support) fails 
       Solution : Modifications for displaying idle mode text and icon are done in 
                           ATB_edit_OutTextLines. 
       
	Jan 16, 2006 DR: OMAPS00061460 - Shashi Shekar B.S.
	Description: SAT Icon support
	Solution : Modifications done in ATB_edit_OutTextLines 
				for display of the title icon.

  CRR:25542 - xpradipg - 26 Oct 2004
 Description: The last character is not deleted from the text entry screen in
 any WAP page.
 Solution: The formatIndex was set to zero on reaching the last character which
 skips the removal of the last character. This assignment is moved out.
	
	 Jul 22,2004 CRR:21605 xrashmic - SASKEN
	 Description: After deleting all the characters in the editor the case does not change to 
	 sentence case.
	 Fix: After deleting a character, check if editor is empty and then set the case to
	 sentence case only if the user has not modified the case.

	
 $End

*******************************************************************************/

#ifndef ATB_EDITOR_C
#define ATB_EDITOR_C
#if defined (NEW_FRAME)

#include "typedefs.h"
#include "vsi.h"
#include "pei.h"
#include "custom.h"
#include "gsm.h"

#else

#include "STDDEFS.H"
#include "custom.h"
#include "gsm.h"
#include "vsi.h"

#endif

#include <stdio.h>
#include <string.h>
#include <math.h>

#include "dspl.h"
#include "ATBCommon.h"
#include "ATBDisplay.h"
#include "ATBEditor.h"
#include "font_bitmaps.h"

#include "cus_aci.h"
#include "prim.h"
#include "pcm.h"

#undef	TRACE_ATBEDITOR

extern UBYTE CaseChanged; // SPR 21605

// Shashi Shekar B.S., a0876501, Jan 16, 2006, DR: OMAPS00061460
#ifdef FF_MMI_SAT_ICON
const unsigned char SATIconQuestionMark[] =
{
	0x25,0x25,0x00,0x00,0x00,0x00,0x25,0x25,
	0x25,0x00,0xE0,0xE0,0xE0,0xE0,0x00,0x25,
	0x00,0xE0,0xE0,0xFF,0xFF,0xE0,0xE0,0x00,
	0x00,0xE0,0xFF,0xE0,0xE0,0xFF,0xE0,0x00,
	0x00,0xE0,0xE0,0xE0,0xE0,0xFF,0xE0,0x00,
	0x00,0xE0,0xE0,0xFF,0xFF,0xE0,0xE0,0x00,
	0x00,0xE0,0xE0,0xFF,0xE0,0xE0,0xE0,0x00,
	0x00,0xE0,0xE0,0xFF,0xE0,0xE0,0xE0,0x00,
	0x25,0x00,0xE0,0xE0,0xE0,0xE0,0x00,0x25,
	0x25,0x25,0x00,0x00,0x00,0x00,0x25,0x25,
};
#endif


/*******************************************************************************

  LOCAL FUNCTION PROTOTYPES

*******************************************************************************/

/* SPR#1983 - SH - Add 'text' parameter */
static int		ATB_edit_Insert (T_ED_DATA *editor, T_ATB_TEXT *text, USHORT character);
static void		ATB_edit_FindNext(T_ED_DATA *editor);
static USHORT	ATB_edit_FindPrev(T_ED_DATA *editor);
static void		ATB_edit_OutTextLines (T_ED_DATA *editor);
static void		ATB_edit_WordWrap(T_ED_DATA *editor);
static void		ATB_edit_UpdateCursorPos(T_ED_DATA *editor);
static ED_RES	ATB_edit_Update (T_ED_DATA *editor, int  dy);
static void 	ATB_edit_LineDestroyAll(T_ED_DATA *editor);


/*******************************************************************************

 $Function:		ATB_edit_Create

 $Description:	Create the editor.  Allocate memory for the editor data and set up
 				some default parameters.
 
 $Returns:		Pointer to the editor data, or NULL if memory allocation failed.

 $Arguments:	editAttr	-	The editor attributes (caller allocated)
 				callback	-	Callback function

*******************************************************************************/

T_ED_DATA* ATB_edit_Create (T_ED_ATTR *editAttr, T_ED_CB callback)
{
    T_ED_DATA *editor;

	TRACE_FUNCTION("ATB_edit_Create()");

	/* Allocate memory for editor data */

	editor = (T_ED_DATA *) ATB_mem_Alloc(sizeof(T_ED_DATA));
	
    if (!editor)
        return NULL;
    
    /* Reset editor data */

    memset(editor, 0, sizeof(T_ED_DATA));
    editor->display = FALSE;
    editor->handler = callback;
    editor->attr = editAttr;
	editor->cursor.width = 8;
	editor->initialised = FALSE;
	editor->line = NULL;
	
    return editor;
}


/*******************************************************************************

 $Function:		ATB_edit_Destroy

 $Description:	Delete the editor.  Free the allocated memory.
 
 $Returns:		ED_OK			- OK
 				ED_BAD_HANDLE	- Editor data is null pointer

 $Arguments:	editor			-	The editor data

*******************************************************************************/

ED_RES ATB_edit_Destroy (T_ED_DATA *editor)
{
	ED_RES		result = ED_OK;
	
	TRACE_FUNCTION("ATB_edit_Destroy()");

	if (editor)
	{
		ATB_edit_LineDestroyAll(editor);
		
		if (editor->hiddenText)
		{
			ATB_edit_HiddenExit(editor);
		}
		
    	ATB_mem_Free((void *)editor, sizeof(T_ED_DATA));
	}
	else
		result = ED_BAD_HANDLE;
		
    return result;
}


/*******************************************************************************

 $Function:		ATB_edit_Init

 $Description:	Initialise the editor.  Ensures that valid combinations of editing modes
 				are set.  Sets uppercase/lowercase appropriately.  Moves the cursor
 				to the correct place in the text.  Performs a word-wrap.
 
 $Returns:		ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Init (T_ED_DATA *editor)
{
	TRACE_FUNCTION("ATB_edit_Init()");


   if (!editor)											/* If editor handle doesn't exist, return error */
    	return ED_BAD_HANDLE;

	/* Get the length of the supplied string */

	ATB_string_Length(&editor->attr->text);

	/* SPR#1983 - SH - Set CAPS preference after moving cursor,
	 * as any cursor moves now reset CAPS to LOWER case. */
	 
	ATB_edit_SetCase(editor, ED_CASE_LOWER);
	 
	/* Non read-only modes*/

	if (!ATB_edit_Mode(editor, ED_MODE_READONLY))
	{
		/* Initialise hidden mode */
		
		if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
		{
			ATB_edit_HiddenInit(editor);
			ATB_edit_SetMode(editor, ED_MODE_OVERWRITE);
		}

		/* Initialise formatted mode */

		if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))
		{
			ATB_edit_SetMode(editor, ED_MODE_OVERWRITE | ED_MODE_ALPHA);
			ATB_edit_MoveCursor(editor,ctrlTop,FALSE);	    /* Send cursor to start of string */
			
			/* Check for "M" & "m" formats; these set the case to upper/lower by default. */
			/* SPR#1983 - SH - Also, overwrite mode can be switched off for these
			 * cases, free entry allowed.*/
			
			ATB_edit_SetCase(editor, ED_CASE_CAPS);			/* Caps is on by default */

			if (strcmp(editor->attr->FormatString, "*M")==0)
			{
				ATB_edit_SetCase(editor, ED_CASE_UPPER);
				ATB_edit_ResetMode(editor, ED_MODE_OVERWRITE);
			}
			
			if (strcmp(editor->attr->FormatString, "*m")==0)
			{
				ATB_edit_SetCase(editor, ED_CASE_LOWER);
				ATB_edit_ResetMode(editor, ED_MODE_OVERWRITE);
			}

		}
		/* Of the cursor modes, only formatted starts at the top, others start at the bottom */
		else
		{
			ATB_edit_MoveCursor(editor, ctrlBottom, FALSE);

			/* SPR#1983 - SH - If the buffer is empty, first character will be capitalised.
			 * Otherwise, lowercase is the default. */
			 
			if (editor->attr->text.len==0)
			{
				ATB_edit_SetCase(editor, ED_CASE_CAPS);			/* Caps is on if first character */
			}
		}
	}

	/* No cursor modes */
	else
	{
		ATB_edit_MoveCursor(editor, ctrlTop, FALSE);
	}

	/* Format text */
	
	ATB_edit_Update(editor, 0);

	/* Make editor visible */
	
	editor->display = TRUE;                        		/* really show it           */

	return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Reset

 $Description:	Reset the editor - move the cursor to the start.
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Reset (T_ED_DATA *editor)
{

	TRACE_FUNCTION("ATB_edit_Reset()");

    if (!editor)
        return ED_BAD_HANDLE;            	/* Editor does not exist */

    editor->cursor.pos = 0;					/* Reset cursor position */
	editor->initialised = FALSE;			/* Fully wrap all of text */
	ATB_edit_Refresh(editor);				/* Refresh word wrap */
    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Show

 $Description:	Show the editor, if it is visible.
 
 $Returns:		ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Show (T_ED_DATA *editor)
{
	UBYTE		previousFont = -1;								// store previous font
	USHORT		editX		= editor->attr->win_size.px;				// pos. of left of edit window
	USHORT		editY		= editor->attr->win_size.py;				// pos. of top of edit window
    USHORT		editWidth    = editor->attr->win_size.sx;       	  	// width of edit window
    USHORT		editHeight	= editor->attr->win_size.sy;				// height of edit window

	TRACE_FUNCTION("ATB_edit_Show()");
	
    if (!editor)
        return ED_BAD_HANDLE;									// Editor doesn't exist

    if (editor->display)
    {
    	resources_setColour(editor->attr->colour);

		if (editor->attr->font != (UBYTE) -1)
        	previousFont = dspl_SelectFontbyID(editor->attr->font);		// setup font
    
        dspl_Clear(editX,editY,editX+editWidth-1,editY+editHeight-1);	// Clear the editor window
	
		ATB_edit_OutTextLines(editor); 										// Show text

		/* Display cursor, if it's switched on and we're not in multitap */
		
	    if (editor->attr->cursor!=ED_CURSOR_NONE && !editor->multitap)
	    {
	        ATB_display_Cursor(&editor->attr->text, editor->cursor.pos, editor->attr->cursor, editX+editor->cursor.x,editY+editor->cursor.y,
	        	editor->cursor.width,editor->cursor.height);
	    }
    }

    if (previousFont != (UBYTE) -1)
        dspl_SelectFontbyID(previousFont);   							// Restore previous font

    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Refresh

 $Description:	Refresh the editor word wrap etc.
 
 $Returns:		ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Refresh (T_ED_DATA *editor)
{
	TRACE_FUNCTION("ATB_edit_Refresh()");

    if (!editor)
        return ED_BAD_HANDLE;        		    /* editor does not exist    */

    /* Get the length of the supplied string */

	ATB_string_Length(&editor->attr->text);

	/* Update word wrap */
	
 	ATB_edit_Update(editor, 0);

    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Hide

 $Description:	Hide the editor
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Hide (T_ED_DATA *editor)
{
	TRACE_FUNCTION("ATB_edit_Hide()");

    if (!editor)
        return ED_BAD_HANDLE;            /* element does not exist   */
    
    editor->display = FALSE;       /* editor is not visible    */
    
    if (editor->handler)                   /* call event handler       */
    {
		editor->handler(ED_INVISIBLE,editor);
    }
    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Unhide

 $Description:	Unhide the editor
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_Unhide (T_ED_DATA *editor)
{
	TRACE_FUNCTION("ATB_edit_Unhide()");

    if (!editor)
        return ED_BAD_HANDLE;            /* element does not exist   */

    editor->display = TRUE;
    
    if (editor->handler)                   /* call event handler       */
    {
		editor->handler(ED_VISIBLE,editor);
    }
    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_MoveCursor

 $Description:	Move the cursor
 
 $Returns:		ED_ERROR	- Unexpected cursor movement
 				ED_OK		- OK

 $Arguments:	editor		- The editor data
 				character	- The control character (ctrlLeft etc)
 				update		- TRUE if word wrap is to be carried out after move

*******************************************************************************/

ED_RES ATB_edit_MoveCursor (T_ED_DATA *editor, USHORT control, UBYTE update)
{
	USHORT altCursorPos;
	SHORT dy;
	ED_RES result;
	
	TRACE_FUNCTION("ATB_edit_MoveCursor");
	
    if (!editor)
        return ED_BAD_HANDLE;            /* element does not exist   */

	/* Can't move cursor in hidden mode, except to start and end */

	result = ED_OK;
	dy = 0;
		
	switch(control)
	{
		case ctrlLeft:
		 	if (!ATB_edit_Mode(editor, ED_MODE_READONLY))			/* Not in read only mode*/
		 	{	
				if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))  		/* formatted input */
				{
	        		ATB_edit_FindPrev(editor);            			 /* find previous non-fixed character */
	        	}
	        	else
	        	{
	        		altCursorPos = editor->cursor.pos;					/* Store original cursor position */
	        		
	        		editor->cursor.pos = ATB_string_IndexMove(&editor->attr->text, editor->cursor.pos, -1);
	        			
		        	if (editor->cursor.pos==altCursorPos) 				/* If we're at the start of text */
					{
		        		ATB_edit_MoveCursor(editor, ctrlBottom, FALSE);	/* .. then go to the end of text! */
					}
				}
			}
			break;

		case ctrlRight:
			if (!ATB_edit_Mode(editor, ED_MODE_READONLY))			/* Not in read only mode*/
		 	{
				if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))  		/* formatted input */
				{
					ATB_edit_FindNext(editor);						/* Move cursor forward once */
				}
				else
				{
	        		altCursorPos = editor->cursor.pos;					/* Store original cursor position */
	        	
					editor->cursor.pos = ATB_string_IndexMove(&editor->attr->text, editor->cursor.pos, 1);
					if (editor->cursor.pos==altCursorPos) 				/* If we're at the end of text */
	        		{
	        			ATB_edit_MoveCursor(editor, ctrlTop, FALSE);	/* .. then go to the start of text! */
	        		}
	        	}
			}
			break;

		case ctrlUp:
			if (editor->cursor.line > 0)
	  			dy = -1;
	  		break;
	  		
		case ctrlDown:
			if (editor->cursor.line < (editor->numLines-1))
	  			dy = 1;
			break;

		case ctrlTop:
			editor->cursor.pos = 0;
			editor->initialised = FALSE;						/* We need to recalculate whole editor */

			/* For formatted mode, skip over any fixed characters at the start */
			
			if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))
			{
				editor->formatIndex = 0;
				editor->fieldIndex = 0;
				ATB_edit_FindNext(editor);
				ATB_edit_FindPrev(editor);
			}
			break;
			
		case ctrlBottom:
			/* Search until we find end of text */
			while (ATB_string_GetChar(&editor->attr->text, editor->cursor.pos)!=UNICODE_EOLN)
			{
	            editor->cursor.pos++;
			}
			editor->initialised = FALSE;						/* We need to recalculate whole editor */
			break;

		default:
			TRACE_EVENT("** ERROR ** Unexpected cursor movement.");
			return ED_ERROR;
			break;
	}

	/* SPR#1983 - SH - In caps mode, any keypress switches to lower case */

	if (editor->textcase==ED_CASE_CAPS)
		editor->textcase = ED_CASE_LOWER;

	if (update || dy!=0)
	{
		ATB_edit_Update(editor, dy);
	}
	
	return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_DeleteLeft

 $Description:	Delete the character to the left of the cursor
 				SPR#2342 - SH - Added flag 'update'
 
 $Returns:		ED_OK		- OK

 $Arguments:	editor		- The editor data
				update		- TRUE if word wrap is to be carried out after deletion

*******************************************************************************/

ED_RES ATB_edit_DeleteLeft (T_ED_DATA *editor, UBYTE update)
{
	ED_RES	result = ED_OK;
	USHORT	altCursorPos;
	char formatchar;
	
	TRACE_FUNCTION("ATB_edit_DeleteLeft");
	
    if (!editor)
        return ED_BAD_HANDLE;            /* element does not exist   */

	/* SPR#1983 - SH - Hidden text changes now mirror normal text changes. */

	/* Formatted mode */
	
	if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))			/* Formatted input */
    {
		if (ATB_edit_FindPrev(editor)!=FINDPREV_FIRST_CHAR)                 			/* Skip over fixed characters */
		{
			if (editor->formatIndex>0)													/* So we don't look back beyond start of string */
			{
				/* If we're in a delimited field, do normal delete, otherwise just cursor back */
				formatchar = editor->attr->FormatString[editor->formatIndex-1];
				if ((formatchar>'0' && formatchar<='9') || formatchar=='*')				/* If it's a number between 1 and 9, or a * */
				{
					ATB_string_MoveLeft(&editor->attr->text, editor->cursor.pos, 1);
					if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
					{
						ATB_string_MoveLeft(editor->hiddenText, editor->cursor.pos, 1);
					}
                                   //CRR:25546 - xpradipg - 26 Oct 2004
                                   //the if block is moved out from the ATB_edit_FindPrev()
                                   if (editor->fieldIndex==0)													// If we've reached the beginning of the field
   				            editor->formatIndex--;	
				}
			}
			result = ED_OK;
		}
		else
		{
			result = ED_DONE;  			/* Delete with empty buffer - escape from editor */
		}
	}

	/* Overwrite mode */
	
	else if (ATB_edit_Mode(editor, ED_MODE_OVERWRITE))
	{
		/* If we're at the end of the string, shift the '0' back */
		if (editor->cursor.pos>0)
		{
			if (editor->cursor.pos == editor->attr->text.len)
			{
				result = ATB_edit_MoveCursor(editor, ctrlLeft, FALSE);
				ATB_string_SetChar(&editor->attr->text, editor->cursor.pos, UNICODE_EOLN);
				editor->attr->text.len--;
				if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
				{
					ATB_string_SetChar(editor->hiddenText, editor->cursor.pos, UNICODE_EOLN);
					editor->hiddenText->len--;
				}
			}
			/* Otherwise, overwrite with a space */
			else
			{
				result = ATB_edit_MoveCursor(editor, ctrlLeft, FALSE);
				ATB_string_SetChar(&editor->attr->text, editor->cursor.pos, UNICODE_SPACE);
				if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
				{
					ATB_string_SetChar(editor->hiddenText, editor->cursor.pos, UNICODE_SPACE);
				}
			}
		}
		else
		{
			result = ED_DONE;				/* Delete with empty buffer - escape from editor */
		}
	}
	else
	{
		/* Otherwise, just perform normal delete operation */
    	altCursorPos = ATB_string_IndexMove(&editor->attr->text, editor->cursor.pos,-1);
        if (altCursorPos!=editor->cursor.pos)
        {
            ATB_string_MoveLeft(&editor->attr->text, altCursorPos, editor->cursor.pos-altCursorPos);	// Delete the difference!
	
			if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
			{
				ATB_string_MoveLeft(editor->hiddenText, altCursorPos, editor->cursor.pos-altCursorPos);	// Delete the difference!
			}
				
			editor->cursor.pos = altCursorPos;
			result = ED_OK;
        }
        else
        	result = ED_DONE;
	}
		
	/* SPR#1983 - SH - In caps mode, any keypress switches to lower case */

	if (editor->textcase==ED_CASE_CAPS)
		editor->textcase = ED_CASE_LOWER;

	 // Jul 22,2004 CRR:21605 xrashmic - SASKEN
	 // When deleting a character, if editor is empty, then set the case to 
	 // sentence case only if the user has not modified the case explicitly.
	if(editor->cursor.pos==0 && CaseChanged == FALSE)
	{
		editor->textcase = ED_CASE_CAPS;		
	}

	if (update)
	{
		ATB_edit_Update(editor,0);
	}
	
	return result;
}


/*******************************************************************************

 $Function:		ATB_edit_DeleteRight

 $Description:	Delete the character to the right of the cursor
 				SPR#2342 - SH - Added flag 'update'
 
 $Returns:		ED_OK		- OK

 $Arguments:	editor		- The editor data
				update		- TRUE if word wrap is to be carried out after deletion

*******************************************************************************/

ED_RES ATB_edit_DeleteRight (T_ED_DATA *editor, UBYTE update)
{
	ED_RES result;
	char formatchar;

	TRACE_FUNCTION("ATB_edit_DeleteRight");
	
    if (!editor)
        return ED_BAD_HANDLE;            /* element does not exist   */
	
	/* SPR#1983 - SH - Hidden text changes now mirror normal text changes. */

	/* Formatted mode */
	
	if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))			/* Formatted input */
    {
		/* If we're in a delimited field, do normal delete right, otherwise ignore */
		if (editor->formatIndex>0)
		{
			formatchar = editor->attr->FormatString[editor->formatIndex-1];
			if ((formatchar>'0' && formatchar<='9') || formatchar=='*')				/* If it's a number between 1 and 9, or a * */
			{
				ATB_string_MoveLeft(&editor->attr->text, editor->cursor.pos, 1);
				if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
				{
					ATB_string_MoveLeft(editor->hiddenText, editor->cursor.pos, 1);
				}
			}
		}
	}

	/* Overwrite mode */
	
	else if (ATB_edit_Mode(editor, ED_MODE_OVERWRITE))
	{
		/* Make sure we're not at the end of the string */
		if (editor->cursor.pos<editor->attr->text.len)
		{
			if (!ATB_edit_Mode(editor, ED_MODE_HIDDEN))
			{
				ATB_string_SetChar(&editor->attr->text, editor->cursor.pos, UNICODE_SPACE);
			}
		}
	}
	else
	{
		ATB_string_MoveLeft(&editor->attr->text, editor->cursor.pos, 1);		/* Otherwise, just perform normal delete operation */
		if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
		{
			ATB_string_MoveLeft(&editor->attr->text, editor->cursor.pos, 1);		/* Otherwise, just perform normal delete operation */
		}
	}

	/* SPR#1983 - SH - In caps mode, any keypress switches to lower case, if we're
	 * not in multi-tap */

	if (!editor->multitap && editor->textcase==ED_CASE_CAPS)
		editor->textcase = ED_CASE_LOWER;

	if (update)
	{
		ATB_edit_Update(editor,0);
	}
	
	return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_ClearAll

 $Description:	Clear all text from the editor, move cursor to the top
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_DONE			- Deleted from start of editor, exit editor
 				ED_OK			- OK

 $Arguments:	editor		- The editor data

*******************************************************************************/

ED_RES ATB_edit_ClearAll (T_ED_DATA *editor)
{
	/* SPR#2275 - SH - No longer use variable 'textlength' */
	ED_RES result;
	
	TRACE_FUNCTION("ATB_edit_ClearAll()");

    if (!editor)
        return ED_BAD_HANDLE;            			// element does not exist
	
	/* FORMATTED MODE */
	
	if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))
	{
  		/* Find first non-fixed character.  SPR#2275 - Simplified */
		ATB_edit_MoveCursor(editor, ctrlTop, FALSE);													// starting from the top.
	}

	/* NORMAL MODE */
	
	else
	{
		if (editor->attr->text.len==0)
		{
			result = ED_DONE;
		}
		else
		{
	        memset(editor->attr->text.data,'\0',editor->attr->size*ATB_string_Size(&editor->attr->text));        /* Clear buffer */
			editor->attr->text.len = 0;
			if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))
			{
	        	memset(editor->hiddenText->data,'\0',editor->attr->size*ATB_string_Size(&editor->attr->text));
	        	editor->hiddenText->len = 0;
			}
			ATB_edit_Reset(editor);										/* Send cursor to start */

		 	result = ED_OK;
		}
	}

	ATB_edit_Update(editor,0);                 			/* Update word wrap & cursor */
	        
    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_Char

 $Description:	Insert a character into the editor text, or execute a control code
 
 $Returns:		ED_OK			- OK

 $Arguments:	editor		- The editor data
 				character	- The character - in unicode representation
 				update		- TRUE if word wrap is to be carried out after insertion

*******************************************************************************/

ED_RES ATB_edit_Char (T_ED_DATA *editor, USHORT character, UBYTE update)
{
	TRACE_FUNCTION("ATB_edit_Char()");

    if (!editor)
        return ED_BAD_HANDLE;            			// element does not exist

    switch (character)
    {
    	/* Quit editor */
    	
        case ctrlEscape:                  							             
            return ED_DONE;
        	break;

        /* Cursor movements*/
        
        case ctrlLeft:
        case ctrlRight:
        case ctrlUp:
        case ctrlDown:
        case ctrlTop:
        case ctrlBottom:
        	ATB_edit_MoveCursor(editor, character, update);
			break;

        /* Backspace */ 
        
        case ctrlBack:
        	ATB_edit_DeleteLeft(editor, update); /* SPR#2342 - SH */
       		break;

		/* Delete character under cursor */
		
        case ctrlDel:
			ATB_edit_DeleteRight(editor, update); /* SPR#2342 - SH */
			break;

		/* CR/LF */

        case ctrlEnter:
            character = UNICODE_LINEFEED;
            /* SPR#1983 - SH - Insert into normal buffer */
            if (ATB_edit_Insert(editor, &editor->attr->text, character))
            {
            	ATB_edit_MoveCursor(editor,ctrlRight,update);
            }
			break;
        
		/* Normal character */ 
            
        default:
	        /* SPR#1983 - SH - Insert into normal buffer */
            if (ATB_edit_Insert(editor, &editor->attr->text, character))
            {
				/* Character inserted OK.  Move cursor to right if we're not in multitap */
	            if (!editor->multitap)
	            {
		            ATB_edit_MoveCursor(editor,ctrlRight,FALSE);
		        }

	        	if (update)
				{
				  	ATB_edit_Update(editor, 0);
				}
			}
			break;
	}        

	/* SPR#1983 - SH - In caps mode, any keypress switches to lower case */
	
	if (!editor->multitap && editor->textcase==ED_CASE_CAPS)
		editor->textcase = ED_CASE_LOWER;
	
    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_AsciiChar

 $Description:	Insert an ascii character into the editor text, or execute a control code
 
 $Returns:		ED_OK			- OK

 $Arguments:	editor		- The editor data
 				character	- The ascii character
 				update		- TRUE if word wrap is to be carried out after insertion

*******************************************************************************/

ED_RES ATB_edit_AsciiChar (T_ED_DATA *editor, char character, UBYTE update)
{
	USHORT unicodeChar;
	
	if (character<ctrlMax)
		unicodeChar = (USHORT)character;
	else
		unicodeChar = ATB_char_Unicode(character);
		
	return ATB_edit_Char(editor, unicodeChar, update);
}


/*******************************************************************************

 $Function:		ATB_edit_Insert

 $Description:	Insert a character into the editor text
 				SPR#1983 - SH - Added 'text' parameter.
 
 $Returns:		TRUE if character was inserted

 $Arguments:	editor		- The editor data
 				text		- The text string (normal or hidden buffer)
 				character	- The character - in unicode representation

*******************************************************************************/

static int ATB_edit_Insert (T_ED_DATA *editor, T_ATB_TEXT *text, USHORT character)
{
	int result = FALSE;
	
	TRACE_FUNCTION("ATB_edit_Insert()");

    if (!ATB_edit_Mode(editor, ED_MODE_READONLY))				// Can't insert into read only mode
    {
	    if (ATB_edit_Mode(editor, ED_MODE_OVERWRITE))									
	    {
	    	if (editor->cursor.pos < (editor->attr->size-1))	/* Make sure character will fit */
	    	{
	    		result = TRUE;									/* We can write the cahracter */
	    		
		    	/* If overwriting end of line, we need to increment length of string */
		    	if (ATB_string_GetChar(text, editor->cursor.pos)==UNICODE_EOLN)
		    	{
		    		
	    			/* Ensure string ends with end of line character */
	    			ATB_string_SetChar(text, editor->cursor.pos+1, UNICODE_EOLN);
	    			text->len++;
	    		}
		    }
	    }
	   	else /* For insert mode, check if we have space */
	    {
	        result = ATB_string_MoveRight(text, editor->cursor.pos, 1, editor->attr->size);	// move rest of text right to leave space
	    }

        if (result)
	    {
	    	ATB_string_SetChar(text, editor->cursor.pos, character);	// Insert the character
	    }
    }
    else
    {
    	result = FALSE;
    }
    
    return result;
}


/*******************************************************************************

 $Function:		ATB_edit_MultiTap 

 $Description:	Displays the specified character over the cursor

 $Returns:		None.

 $Arguments:	editor		- The editor data
 				character	- The character to display
 				multitap	- TRUE if multi-tap is currently in progress
 
*******************************************************************************/

ED_RES ATB_edit_MultiTap(T_ED_DATA *editor, USHORT character, BOOL multitap)
{
	UBYTE oldmultitap;
	ED_RES result = ED_OK;
	
	TRACE_FUNCTION("ATB_edit_MultiTap()");

	if (!editor)
        return ED_BAD_HANDLE;            			// element does not exist
        
	oldmultitap = editor->multitap;
	editor->multitap = multitap;
	
	/* If we were previously in multitap, and in insert mode, delete character under cursor.
	 * Since this deletes current character in both visible and
	 * hidden buffer, do this before inserting character to either buffer. */

	if (oldmultitap && !multitap && !ATB_edit_Mode(editor, ED_MODE_HIDDEN))
	{
		result = ATB_edit_MoveCursor(editor, ctrlRight, TRUE);
	}
	else
	{
		if (oldmultitap && !ATB_edit_Mode(editor, ED_MODE_OVERWRITE))
		{
			ATB_edit_DeleteRight(editor, FALSE); /* SPR#2342 - SH */
		}
		
		/* Hidden mode */

		if (ATB_edit_Mode(editor, ED_MODE_HIDDEN))							/* In hidden mode... */
	    {
		    ATB_edit_Insert(editor, editor->hiddenText, character);
		    
	    	if (!multitap)													/* n multi-tap, show character...*/
	    		character = UNICODE_STAR;									/* ...otherwise show star */
	    }

		result = ATB_edit_Char(editor,character,TRUE);
	}
		
    return result;
}


/*******************************************************************************

 $Function:		ATB_edit_AsciiMultiTap 

 $Description:	Displays the specified ascii character over the cursor

 $Returns:		None.

 $Arguments:	editor		- The editor data
 				character	- The ascii character to display
 				multitap	- TRUE if multi-tap is currently in progress
 
*******************************************************************************/

ED_RES ATB_edit_AsciiMultiTap(T_ED_DATA *editor, char character, BOOL multitap)
{
	USHORT unicodeChar;
	
	if (character<ctrlMax)
		unicodeChar = (USHORT)character;
	else
		unicodeChar = ATB_char_Unicode(character);
		
	return ATB_edit_MultiTap(editor, unicodeChar, multitap);
}


/*******************************************************************************

 $Function:		ATB_edit_FindNext 

 $Description:	For formatted input, adds a character to the input buffer then finds
 				the next non-fixed character space for the cursor to occupy

 $Returns:		None

 $Arguments:	editor		- The editor data
 				character	- The character (or code) to insert
 
*******************************************************************************/

static void ATB_edit_FindNext(T_ED_DATA *editor)
{
    char			*format 		= editor->attr->FormatString;
   	char			formatchar;
	UBYTE			inField			= ENTRY_NOT_IN_FIELD;

	TRACE_FUNCTION("ATB_edit_FindNext()");

	// xreddymn - Included xrashmic's fix for 12470
	if(editor->attr->text.len==0)
	{
		return;
	}

	/* Check for delimited field */
	
	if (editor->formatIndex>0)
	{
		formatchar = format[editor->formatIndex-1];
		if ((formatchar>'0' && formatchar<='9') || formatchar=='*')
			inField = ENTRY_IN_FIELD;
	}
	
	formatchar = format[editor->formatIndex];
	if ((formatchar>'0' && formatchar<='9') || formatchar=='*')
		inField = ENTRY_ENTERING_FIELD;
	
	/* Check for cursor right at end of string - don't allow */
	
	if (editor->cursor.pos>=editor->attr->text.len
		&& editor->formatIndex>-1 && inField==ENTRY_NOT_IN_FIELD)
	{
		return;
	}

	/* Move cursor position right */

	editor->cursor.pos = ATB_string_IndexMove(&editor->attr->text, editor->cursor.pos, 1);

	/* Check for start of fixed input field */

	if (inField==ENTRY_ENTERING_FIELD)
	{
		editor->formatIndex++;														// Get us into the field...
		editor->fieldIndex = 0;														// ...and reset the field index
		formatchar = format[editor->formatIndex];
		if (formatchar=='M')
			editor->textcase = ED_CASE_UPPER;
		if (formatchar=='m')
			editor->textcase = ED_CASE_LOWER;
		inField = ENTRY_IN_FIELD;
	}

	/* Check whether we're in a fixed input field, e.g. "4N" or "8X" */

	if (inField==ENTRY_IN_FIELD)															// So we don't look back beyond start of string
	{
		formatchar = format[editor->formatIndex-1];
		editor->fieldIndex++;													// Increment the position in the field
		if (editor->fieldIndex==(int)(formatchar-'0'))								// If we've entered the number of characters specified (note- will never happen for the '*' !)
		{
			editor->formatIndex++;												// point to NULL at end of string (no more input)
		}
		return;
	}

	/* If not, just look at next format character as usual */
	
	editor->formatIndex++;															// Point to next character
	
	while (editor->formatIndex<strlen(format) && format[editor->formatIndex]=='\\')		// Fixed characters encountered
	{
		editor->cursor.pos = ATB_string_IndexMove(&editor->attr->text, editor->cursor.pos, 1);				// Skip over them
		editor->formatIndex+=2;
	}

	if (editor->formatIndex>(strlen(format)))											// Don't look beyond end of string
		editor->formatIndex = strlen(format);

	return;
}


/*******************************************************************************

 $Function:  ATB_edit_FindPrev 

 $Description:	For formatted input, finds the previous non-fixed character and
 				moves the cursor there if possible

 $Returns:		FINDPREV_NO_CHANGE if the cursor position is not changed (nowhere to go)
 				FINDPREV_PREV_FOUND if the previous character has been found
 				FINDPREV_FIRST_CHAR if the cursor was over the first non-fixed character
 				FINDPREV_LAST_CHAR if the cursor is at the last non-fixed character

 $Arguments:	editor	- The editor data
 
*******************************************************************************/

static USHORT ATB_edit_FindPrev(T_ED_DATA *editor)
{
    char			*format 		= editor->attr->FormatString;
   	char			formatchar;
   	SHORT			editIndex;

	TRACE_FUNCTION("ATB_edit_FindPrev()");

	/* Check if cursor is at start of string, return 2 */
	
	if (editor->cursor.pos == 0)
	{
		return FINDPREV_FIRST_CHAR;
	}
	
	/* Check whether we're in a fixed input field, e.g. "4N" or "8X" */
			
	if (editor->formatIndex>0)															// So we don't look back beyond start of string
	{
		formatchar = format[editor->formatIndex-1];
		if ((formatchar>'0' && formatchar<='9') || formatchar=='*')				// If it's a number between 1 and 9, or a *
		{
			if (editor->cursor.pos > 0)
				editor->cursor.pos--;
				
			if (editor->cursor.pos < editor->attr->size-1)									// (Don't decrement if at last char in string)
				editor->fieldIndex--;												// Decrement the position in the field
			
			if (editor->cursor.pos==editor->attr->text.len-1)		// Special case if last character - tell editor to shorten the string
				return FINDPREV_LAST_CHAR;
			
			return FINDPREV_PREV_FOUND;											// then we're done
		}
	}

	/* If not (or if we've just come out of one) just look at next format character as usual */

	editIndex	= editor->formatIndex-1;												// Make copy of format position, starting off to left
	 	
	while (editIndex>0)
	{
		if (format[editIndex-1]=='\\')										// If there's a fixed char
			editIndex -=2;														// Look back a further 2 characters
		else																	// If there's a non-fixed character
			break;																// then exit loop
   }

	if (editIndex==-1)															// Go back from 1st character in editor
	{
		return FINDPREV_FIRST_CHAR;
	}
	
	formatchar = format[editIndex-1];											
	if ((formatchar>'0' && formatchar<='9') || formatchar=='*')
		editor->fieldIndex--;
		
	if (editIndex>-1)															// Provided there is somewhere to go....
	{
		while(editor->formatIndex>editIndex)
		{
			if (editor->cursor.pos > 0)
			{
				editor->cursor.pos--;					// move cursor there
				editor->formatIndex--;
			}
			if (format[editor->formatIndex]=='\\')
				editor->formatIndex--;
		}
		return FINDPREV_PREV_FOUND;												// Found new position
	}
	
	return FINDPREV_NO_CHANGE;													// Position unchanged
}


/*******************************************************************************

 $Function:		ATB_edit_GetCasePref 

 $Description:	Returns the preferred case for the current position in the editor

 $Returns:		ED_CASEPREF_NUM					- Any numeric character
 				ED_CASEPREF_ALPHA_UC			- Any symbolic or alphabetic uppercase
 											  character
 				ED_CASEPREF_ALPHA_LC			- Any symbolic or alphabetic lowercase
 											  character
   				ED_CASEPREF_ALPHANUM			- Any symbolic, numeric, or alphabetic
 											  character
 				ED_CASEPREF_ALPHANUM_UC			- Any symbolic, numeric, or alphabetic
 											  uppercase character
				ED_CASEPREF_ALPHANUM_LC			- Any symbolic, numeric, or alphabetic
 											  lowercase character

 $Arguments:	editor		- The editor data
 
*******************************************************************************/

T_ED_CASE_PREF ATB_edit_GetCasePref(T_ED_DATA *editor)
{
	T_ED_CASE_PREF	casePref;
	char			formatchar;
	char			*format;

	/* FORMATTED MODE */
	
	if (ATB_edit_Mode(editor, ED_MODE_FORMATTED))
	{
		format = editor->attr->FormatString;
		formatchar = format[editor->formatIndex];
	  
		if ((formatchar>'0' && formatchar<='9') || formatchar=='*')			// Delimiter for format field
		{
	       	editor->formatIndex++;
	       	editor->fieldIndex = 0;
	       	formatchar = format[editor->formatIndex];						// Next character is the format for the field
		}

	    switch(formatchar)
		{
			case 'X':														/* Uppercase alphanumeric */
				casePref = ED_CASEPREF_ALPHANUM_UC;
				break;
			case 'x':
				casePref = ED_CASEPREF_ALPHANUM_LC;								/* Lowercase alphanumeric */
				break;
			case 'A':														/* Uppercase alphabetic */
				casePref = ED_CASEPREF_ALPHA_UC;
				break;
			case 'a':														/* Lowercase alphabetic */
				casePref = ED_CASEPREF_ALPHA_LC;
				break;
			case 'M':
				casePref = ED_CASEPREF_ALPHANUM;
				break;
			case 'm':
				casePref = ED_CASEPREF_ALPHANUM;
				break;
			case 'N':
				casePref = ED_CASEPREF_NUM;
				break;
				
			default:
				casePref = ED_CASEPREF_NONE;
				break;
	    }
	}

	/* NORMAL MODE */
	else
	{
		casePref = ED_CASEPREF_NUM;	/* SPR#2342 - SH - Default to numeric mode */
				
		if (ATB_edit_Mode(editor, ED_MODE_ALPHA)
			&& ATB_edit_GetCase(editor)!=ED_CASE_NUM)
		{
			casePref = ED_CASEPREF_ALPHANUM;
		}
	}
	
	return casePref;
}


/*******************************************************************************

 $Function:		ATB_edit_OutTextLines

 $Description:	Draw the visible lines of text onto the screen
 
 $Returns:		None

 $Arguments:	editor		- The editor data

*******************************************************************************/

static void ATB_edit_OutTextLines (T_ED_DATA *editor)
{
	USHORT		editX			= editor->attr->win_size.px;				/* X position in editor */
	USHORT		editY			= editor->attr->win_size.py;				/* Y position in editor */
	USHORT		editWidth		= editor->attr->win_size.sx;				/* Height of the editor */
	USHORT		editHeight		= editor->attr->win_size.sy;				/* Height of the editor */
	USHORT		lineNo;
	USHORT		heightOnScreen;										/* Height of lines shown so far */
	USHORT		offsetX;											/* X offset of line */
	T_DS_TEXTFORMAT	tempFormat;										/* Temporary storage for format attributes */
	T_ED_LINE	*line;												/* Current line attributes */
	T_ATB_TEXT	currentLine;										/* Current line */
// Shashi Shekar B.S., a0876501, Jan 16, 2006, DR: OMAPS00061460
#ifdef FF_MMI_SAT_ICON
	USHORT		titleIconWidth = 0;
	USHORT 		iconX, iconY;
	USHORT		titleHeight = 0;
#endif

	TRACE_FUNCTION("ATB_edit_OutTextLines()");

	if (editor == NULL)
		return;

// Shashi Shekar B.S., a0876501, Jan 16, 2006, DR: OMAPS00061460
#ifdef FF_MMI_SAT_ICON
       if (editor->attr->TitleIcon.data != NULL && !editor->attr->TitleIcon.isTitle)
	{
		if (editor->attr->TitleIcon.width > TITLE_ICON_WIDTH) 
		{
			titleIconWidth = TITLE_ICON_WIDTH;
		}
		else
		{
			titleIconWidth = editor->attr->TitleIcon.width;
		}
	}			
	else
	{
		titleIconWidth = 0;
	}

	if(titleIconWidth)
		editX = editX + titleIconWidth + 1;
#endif

	heightOnScreen = 0;
	line = ATB_edit_LineGet(editor, editor->winStartLine);

// Shashi Shekar B.S., a0876501, Jan 16, 2006, DR: OMAPS00061460
#ifdef FF_MMI_SAT_ICON
	if(line != NULL)
		titleHeight = line->height;
#endif

	for (lineNo = editor->winStartLine; lineNo < editor->numLines && heightOnScreen<=editHeight; lineNo++)
	{
    	heightOnScreen 	+= line->height;							/* Add this height to the total height so far... */

		if (editor->display && heightOnScreen <= editHeight)		/* and make sure this fits onto the screen */
		{
			currentLine.len = line->next->pos - line->pos;  		/* End of line is the first character of the next line */
			currentLine.dcs = editor->attr->text.dcs;
			currentLine.data = &editor->attr->text.data[line->pos*ATB_string_Size(&currentLine)];

			offsetX = 0;
			if (line->format.attr & DS_ALIGN_RIGHT)
			{
				offsetX = editWidth-ATB_display_StringWidth(&currentLine, &line->format);
			}
			else if (line->format.attr & DS_ALIGN_CENTRE)
			{
				offsetX = (editWidth-ATB_display_StringWidth(&currentLine, &line->format))/2;
			}
			ATB_display_CopyFormat(&tempFormat, &line->format);		/* So format of lines doesn't change */
			ATB_display_Text(offsetX+editX, editY, &tempFormat, &currentLine);
		}

		editY += line->height;										/* Move down by line height, ready for the next one */
		line = line->next;											/* Get next line */
	}
//Sudha.V., x0035544, Feb 02, 2006, DR: OMAPS00061468
// Shashi Shekar B.S., a0876501, Jan 16, 2006, DR: OMAPS00061460
#ifdef FF_MMI_SAT_ICON
	if(editor->attr->TitleIcon.data != NULL && !editor->attr->TitleIcon.isTitle)
	{
	switch(editor->attr->TitleIcon.display_type)
		{
		case SAT_ICON_NONE:
			break;
		case SAT_ICON_IDLEMODE_TEXT:
			
		        if ((editor->attr->TitleIcon.width > TITLE_ICON_WIDTH) || (editor->
attr->TitleIcon.height > TITLE_ICON_HEIGHT))
		        {
			         iconX = editX+offsetX - editor->attr->TitleIcon.width-2;
		              iconY = editor->attr->win_size.py+ ((titleHeight-2)/2);
			         dspl_BitBlt2(iconX, iconY, 8, 
					    10, (void*)SATIconQuestionMark, 0, BMP_FORMAT_256_COLOUR);

		         }
		     else
		     {
			       iconX = editX+offsetX - editor->attr->TitleIcon.width-2;
		              iconY = editor->attr->win_size.py + ((titleHeight-2)/2) - (
editor->attr->TitleIcon.height / 2);
		              dspl_BitBlt2(iconX, iconY, editor->attr->TitleIcon.width, 
				        editor->attr->TitleIcon.height, (void*)editor->attr->TitleIcon.
data, 0, BMP_FORMAT_256_COLOUR);
		      }
		 break;

		 case SAT_ICON_DISPLAY_TEXT:
			
		        if ((editor->attr->TitleIcon.width > TITLE_ICON_WIDTH) || (editor->
attr->TitleIcon.height > TITLE_ICON_HEIGHT))
		       {
			      iconX = 1;
			      iconY = 1+ ((titleHeight-2) / 2) - (10 / 2);
			     dspl_BitBlt2(iconX, iconY, 8, 
					   10, (void*)SATIconQuestionMark, 0, BMP_FORMAT_256_COLOUR);

		       }
		    else
		    {
		           iconX = 1;
		           iconY = 1+ ((titleHeight-2) / 2) - (editor->attr->TitleIcon.
height / 2);
		          dspl_BitBlt2(iconX, iconY, editor->attr->TitleIcon.width, 
				    editor->attr->TitleIcon.height, (void*)editor->attr->TitleIcon.data, 0
, BMP_FORMAT_256_COLOUR);
		     }
		break;
	    }
		}
#endif

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_Update

 $Description:	Update editor (without displaying), moving cursor up or down by 'dy' lines.

  This function goes through the text, word-wraps it with the help of ATB_edit_WordWrap,
  and works out the start position of text on-screen and the X and Y pixel positions
  of the cursor (with the help of ATB_edit_UpdateCursorPos).  The character position of
  the start of each line within the string is stored, so that ATB_edit_OutTextLines can
  quickly display the editor contents without further calculation.
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_OK			- OK

 $Arguments:	editor		- The editor data
 				dy			- number of lines (+ or -) that the cursor must scroll
 								up or down.

*******************************************************************************/

static ED_RES ATB_edit_Update (T_ED_DATA *editor, int dy)
{
	USHORT				cursorCharPos;			/* New cursor character position */
	USHORT				linePos;				/* Char pos in string of current line. */
	USHORT				lineNo;					/* Line being considered */
	USHORT				editComplete;			/* Flag indicating cursor position found/updated or end of line reached. */
	USHORT				character;				/* Current unicode char. */
	T_ED_LINE			*line;					/* Pointer to current entry in line chain */
	USHORT				cursorColumn;			/* Column cursor is in - always multiple of 8 pixels */
	SHORT				charMaxWidth;
	
	TRACE_FUNCTION("ATB_edit_Update()");

	/* Make sure the editor exists and has text in it */
	
	if (!editor)
		return ED_BAD_HANDLE;

	/* For non read-only modes, or on first process, perform word wrap */

	if (!ATB_edit_Mode(editor, ED_MODE_READONLY) || editor->initialised==FALSE)
	{
		editor->viewStartPos = 0;
		editor->viewHeight = 0;
		editor->totalHeight = 0;
		editor->startOfLine = TRUE;								/* We're at the start of a line */	
		editor->endOfText = FALSE;
		editor->precedingEOL = FALSE;							/* Used to detect if preceding character was CR/LF */
		editor->thischar.lineWidth = 0;							/* Width of current line */
		editor->cursor.line = 0;								/* Line that the cursor is on */
		editor->space.pos = 0;									/* Possible position for soft linebreak - none as yet */

		/* Set up data if this is the first time... */
		
		if (!editor->initialised)
		{
			editor->thischar.pos = 0;
			editor->numLines = 0;								/* total number of lines in editor, start at 0 */

			line = ATB_edit_LineGet(editor, 0);
			line->pos = 0;										/* first line starts at start of buffer */
			line->height = 0;									/* Height of first line */
			ATB_display_CopyFormat(&line->format, &editor->attr->startFormat);	/* Start with this text formatting */
			ATB_display_CopyFormat(&editor->thischar.format, &editor->attr->startFormat); // Start with this text formatting
			
			editor->winStartLine = 0;							/* First line to be displayed in window */

			editor->initialised = TRUE;
		}
		
		/* Set up data if this is NOT the first time */

		else
		{
			/* We only need to word wrap text that might have been changed by user text entry.
			 * The user can affect the previous line (by inserting a space or deleting, so the word is
			 * wrapped to a previous line) and all subsequent lines.  Therefore if we start word wrapping
			 * on the line previous to where the cursor is, we can encompass all changes. */
			line = ATB_edit_LineGet(editor, 0);
			for (lineNo = 0; lineNo<editor->numLines && editor->cursor.pos>=line->pos; lineNo++)
			{
				line = line->next;
			}
			if (lineNo>0)
				lineNo--;
			if (lineNo>0)
				lineNo--;

			line = ATB_edit_LineGet(editor, lineNo);
			editor->thischar.pos = line->pos;							/* Start looking at this line */						
			editor->numLines = lineNo;									/* This no. of lines so far */								
			ATB_display_CopyFormat(&editor->thischar.format, &line->format); /* Start with this text formatting */
			line->height = 0;											/* Height of first line */
		}


		/* Set up some values */
		
		cursorCharPos	= editor->cursor.pos;						/* Cursor position in the string */
		linePos			= 0;										// Position on the current line
			
		/* Word wrap the text into separate lines, storing the start position and height of each.
		 * Also, find the cursor and work out its X position. */
		
		while(!editor->endOfText)									// Go through from first character to last character
		{
			ATB_edit_WordWrap(editor);      						// What is the character?  What's its width?

			if (editor->endOfLine)									// Newline, or current char will not fit on previous line.
			{
				editor->numLines++;								// We've got another line
				editor->startOfLine = TRUE;						// New line is starting
			}
							
			if (editor->startOfLine)
			{
				line = ATB_edit_LineGet(editor, editor->numLines);
				line->pos = editor->startPos;
				line->height = editor->thischar.height; // Height of line set to that of first character
				ATB_display_CopyFormat(&line->format,&editor->thischar.format);
																	/* Formatting at start of line to that of 1st character */
				editor->thischar.lineWidth = 0;

				line = ATB_edit_LineGet(editor, editor->winStartLine);
				if (editor->startPos <= line->pos)	/* Is this the first line to be displayed in the editor? */
				{
					editor->winStartLine = editor->numLines;					/* If so, set this line to the start window line */
				}
				editor->startOfLine = FALSE;
			}

			if (editor->endOfText)												/* If it's a unicode terminator... */
			{
				if (cursorCharPos > editor->thischar.pos)						/* Cursor is past end of text - move to char before end of line. */
					cursorCharPos = editor->thischar.pos;
			}

			if (editor->startPos == cursorCharPos)					// We've found the cursor
			{
				editor->cursor.line 	= editor->numLines;				// Store the line it's on
				editor->cursor.width	= editor->thischar.width;			// Set the width of the cursor
				editor->cursor.x		= editor->thischar.lineWidth;			// And its position
				editor->cursor.attr		= editor->thischar.format.attr;			// Save the format attribute
			}

			editor->thischar.lineWidth += editor->thischar.width;
			editor->thischar.pos++;
		}					// End while

		editor->numLines++;										// Number of lines is one more than the last line
		line = ATB_edit_LineGet(editor, editor->numLines);
		line->pos = editor->thischar.pos;		// End of last line
		
		ATB_edit_UpdateCursorPos(editor);								// Update, but if dy!=0 we may have to change this
	}
	
	/* We now have the start position of each line and its height stored in an array.
	 * We also have the cursor's current X position on its line (but its line may be offscreen) */

	if (dy)														// If we're sending the cursor up/down some lines...
	{
		editor->cursor.line = editor->cursor.line+dy;	// Change cursor line
	
		if (editor->cursor.line >= editor->numLines )		// Make sure line cursor is on doesn't go beyond...
			editor->cursor.line = editor->numLines-1;		// ...last line of editor...

		if (editor->cursor.line < 0)					// ...or above...
			editor->cursor.line = 0;							// ...first line of editor

		/* In read-only mode, stop scrolling down when the bottom line of the text
		 * is visible at the bottom of the window */
		 
		if (ATB_edit_Mode(editor,ED_MODE_READONLY))
		{
			if (editor->numLines>=editor->linesPerScreen
				&& editor->cursor.line >= (editor->numLines - editor->linesPerScreen))
			{
				editor->cursor.line = (editor->numLines - editor->linesPerScreen);
			}
			
			editor->winStartLine = editor->cursor.line;
		}	
	}

	/* Reset all our horizontal variables */
	
	editor->thischar.pos		= 0;
	editor->thischar.lineWidth	= 0;
	editComplete				= TRUE;
	editor->endOfText			= FALSE;
	editor->space.pos			= 0;

	/* Work out how many lines fit on the current screen */

	ATB_edit_UpdateCursorPos(editor); 
	lineNo = 0;

	/* Update the line where we start showing the text on the window */
	
	if (editor->cursor.line < editor->winStartLine) 	//cursor is on a line before current window screen
	{
		editor->winStartLine = editor->cursor.line;
		editComplete = FALSE;
	}
	else if (editor->cursor.line >= (editor->winStartLine+editor->linesPerScreen)) //cursor is below the bottom of the screen
	{
		editor->winStartLine = editor->cursor.line-(editor->linesPerScreen-1);
		editComplete = FALSE;
	}
	
	if (dy!= 0)														/* If we're moving up or down */
	{
		editComplete = FALSE;
	}

	if (!editComplete)												/* Calculate new cursor X and Y positions */
	{
		if (dy!=0)													/* If we've changed line, find new X position */
		{
			line = ATB_edit_LineGet(editor, editor->cursor.line);
			editor->thischar.lineWidth = 0;
			linePos = line->pos;		// Start of current line
			ATB_display_CopyFormat(&editor->thischar.format, &line->format); // Format attributes of 1st character
			/* Get column - is always a multiple of the maximum character width.  Makes sure cursor doesn't wander
			 * left or right too much when moving up or down by lines */
			charMaxWidth = (SHORT)ATB_display_GetMaxCharWidth(&editor->thischar.format);
			cursorColumn = editor->cursor.x - (editor->cursor.x % charMaxWidth);

			linePos--;
			editor->thischar.width = 0;
			
			/* SPR#2342 - SH - Improved finding cursor position on adjacent lines.
			 * First search until we're in the column or at the end of the line */

			do
			{
				linePos++;
				editor->thischar.lineWidth += editor->thischar.width;
				character = ATB_string_GetChar(&editor->attr->text, linePos);
				editor->thischar.width = ATB_display_GetCharWidth(character, &editor->thischar.format);
			}
			while (editor->thischar.lineWidth<cursorColumn && linePos < (line->next->pos-1));

			/* Is there a character also in the column, but closer to our original character? */
			
			while ((editor->thischar.lineWidth+editor->thischar.width) < (cursorColumn+charMaxWidth)
				&& linePos< (line->next->pos-1)
				&& (editor->cursor.x - editor->thischar.lineWidth)> editor->thischar.width)
			{
				linePos++;
				editor->thischar.lineWidth += editor->thischar.width;
				character = ATB_string_GetChar(&editor->attr->text, linePos);
				editor->thischar.width = ATB_display_GetCharWidth(character, &editor->thischar.format);
			}
			
			/* Set the new cursor X position */
			cursorCharPos			= linePos;									// New cursor position in buffer
			editor->cursor.width	= editor->thischar.width;					// Set the width of the cursor
			editor->cursor.x		= editor->thischar.lineWidth;				// And its position
			editor->cursor.attr		= editor->thischar.format.attr;				// Save the format attribute
		}
		ATB_edit_UpdateCursorPos(editor);
	}

	/* Change cursor position */
	
	editor->cursor.pos = cursorCharPos;

    return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_WordWrap

 $Description:	Main word wrap function.  Takes in the characters of the string
				one by one, calculating the total width displayed on screen and setting flags
				when a string should be wrapped, a carriage return is encountered, the end
				of string has been reached.
				
				Tracks the last space character and goes back there when a word runs over
				the edge of the screen.  Also works out the height of the current line, based on
				the maximum character height found.
 
 $Returns:		None

 $Arguments:	editor		- The editor data

*******************************************************************************/

static void ATB_edit_WordWrap(T_ED_DATA *editor)
{
	USHORT		character;
	char		asciiChar;
	int			punctuation;
	T_ED_LINE	*line;

#ifdef TRACE_ATBEDITOR
	TRACE_FUNCTION("ATB_edit_WordWrap()");
#endif

	editor->endOfLine = FALSE;
	line = ATB_edit_LineGet(editor, editor->numLines);

	/* Get the character from the buffer */

	editor->startPos = editor->thischar.pos;
	character = ATB_string_GetChar(&editor->attr->text, editor->thischar.pos);
	
	/* Find the character's dimensions */

	/* If we're multi-tapping a character, or in fixed-width mode, it has the maximum width */
	
	if (editor->multitap && editor->thischar.pos==editor->cursor.pos)
		editor->thischar.width = ATB_display_GetCharWidth(UNICODE_WIDEST_CHAR, &editor->thischar.format);
	else
		editor->thischar.width = ATB_display_GetCharWidth(character, &editor->thischar.format);						// Character width
	
	editor->thischar.height = ATB_display_GetCharHeight(character, &editor->thischar.format);

	/* Check to see if last character was a CR/LF */

	if (editor->precedingEOL)
	{
		editor->endOfLine = TRUE;
		editor->precedingEOL = FALSE;
	}
	else										// otherwise, character included on line
	{
		if (editor->thischar.height > line->height)		// if height>height so far...
			line->height = editor->thischar.height;		// ...adjust the height so far
	}
			
	/* Set flags appropriate for the character */
	
	switch(character)
	{
		case UNICODE_EOLN:
			editor->endOfText = TRUE;							// We're at the end of the editor text
		break;

		case UNICODE_LINEFEED:
		case UNICODE_CR:
			editor->precedingEOL = TRUE;							// This is an end of line
		break;
		
		default:
		break;
	}

	/* Check if wrapping required */
	
	if ( (editor->thischar.lineWidth+editor->thischar.width)>editor->attr->win_size.sx )		// Current character will go off edge of editor
	{
		editor->endOfLine = TRUE;

		// If we've found a space, and it's a word wrapping mode */
		
		if (editor->space.pos > 0 && editor->precedingSpace==FALSE
			&& !ATB_edit_Mode(editor, ED_MODE_OVERWRITE)) 
		{
			editor->thischar.pos			= editor->space.pos;	// reset character position back to here
			editor->startPos				= editor->space.pos;	// character is space, so start of block=character pos
			editor->thischar.width			= editor->space.width;
			editor->thischar.height			= editor->space.height;
			ATB_display_CopyFormat(&editor->thischar.format,&editor->space.format);
			line->height = editor->space.lineHeight;
			editor->endOfText			= FALSE;					// If we're wrapping on an EOLN, we've gone back
		}
		editor->space.pos = 0;								// Reset space position to start of line
		editor->precedingSpace = FALSE;
	}
	else
	{
		if (editor->precedingSpace)	// Remember enough info so that this point can be restored
		{
			editor->space.pos			= editor->startPos;				// Store position of start of current block, or just character pos.	
			editor->space.width			= editor->thischar.width;
			editor->space.height		= editor->thischar.height;
			ATB_display_CopyFormat(&editor->space.format,&editor->thischar.format);
			editor->space.lineHeight	= line->height;
			editor->precedingSpace		= FALSE;
		}
		
		punctuation = FALSE;
		if (character==UNICODE_SPACE)  								 // Wrap only on spaces
		{
			punctuation = TRUE;
		}
	
		if ((punctuation) && (editor->thischar.lineWidth > 0)) 					//A space is a good point for a soft break
		{
			editor->precedingSpace = TRUE;
		}
	}

	return;
}


/*******************************************************************************

 $Function:		ATB_edit_UpdateCursorPos

 $Description:	Update the cursor's vertical position, based on its position within
				the string.
 
 $Returns:		None

 $Arguments:	editor		- The editor data

*******************************************************************************/

static void ATB_edit_UpdateCursorPos(T_ED_DATA *editor)
{
	USHORT lineNo;
	USHORT	lineHeight;
	USHORT	editHeight = editor->attr->win_size.sy;
	T_ED_LINE *line;

#ifdef TRACE_ATBEDITOR
	TRACE_FUNCTION("ATB_edit_UpdateCursorPos()");
#endif

	editor->cursor.y = 0;										// Recalculate cursor Y position...
	editor->viewHeight = 0;										// ...and height of viewable screen...
	editor->totalHeight = 0;									// ...and total height of screen...
	editor->viewStartPos = 0;									// ...and the start pixel position of the view...
	editor->linesPerScreen = 0;								// ...and number of lines to the screen
	lineNo = 0;
		
	while (lineNo<editor->numLines)
	{
		line = ATB_edit_LineGet(editor, lineNo);

		lineHeight = line->height;
	
		if (lineNo==editor->cursor.line)
			editor->cursor.y = editor->viewHeight;							// Y position of cursor

		if (lineNo==editor->winStartLine)									// starting posn rel to start of editor text
			editor->viewStartPos = editor->totalHeight;
		
		if (lineNo>=editor->winStartLine && (editor->viewHeight+lineHeight)<=editHeight)
		{
			editor->viewHeight += lineHeight;
			editor->linesPerScreen++;
		}

		editor->totalHeight += lineHeight;
		lineNo++;
	}

	line = ATB_edit_LineGet(editor, editor->cursor.line);
	editor->cursor.height  = line->height;	// Change its height

	return;
}


/************************************/  
/* GLOBAL PROCEDURES				*/
/* Add/removing words in the editor    */
/************************************/

/*******************************************************************************

 $Function:		ATB_edit_InsertString

 $Description:	Insert a string at the cursor.
 
 $Returns:		ED_BAD_HANDLE	- Editor data pointer is null
 				ED_OK			- OK

 $Arguments:	editor		- The editor data
 				insText		- The text to insert

*******************************************************************************/

ED_RES ATB_edit_InsertString (T_ED_DATA *editor, T_ATB_TEXT *insText)
{
    T_ATB_TEXT	*text;
	int 		textIndex;
	USHORT		character;

	TRACE_FUNCTION("ATB_edit_InsertString()");

    if (!editor)													// Make sure editor exists
        return ED_BAD_HANDLE;
	
	if (insText==NULL || insText->len==0)
		return ED_OK;												/* No string to insert - trivial operation. */

	if (ATB_edit_Mode(editor, ED_MODE_READONLY)	)					/* Don't insert in read-only mode*/
		return ED_ERROR;
		
	text = &editor->attr->text;

	if ((text->len+insText->len) >= editor->attr->size)
		return ED_ERROR; 											/* String too long */ 

	/* Move text up by the length of insText */

	ATB_string_MoveRight(text, editor->cursor.pos, insText->len, editor->attr->size); 
	
	/* Copy string into buffer */
	
	for (textIndex=0; textIndex<insText->len; textIndex++)
	{
		character = ATB_string_GetChar(insText, textIndex);
		ATB_string_SetChar(text, editor->cursor.pos+textIndex, character);
	}

	editor->cursor.pos = editor->cursor.pos+insText->len;
	
	/* Reformat updated text */
	
	ATB_edit_Update(editor, 0);

    return ED_OK;
   }


/*******************************************************************************

 $Function:		ATB_edit_GetCursorChar

 $Description:	Return the character at a position offset from the current cursor
				position by the value supplied.
 
 $Returns:		The character, or UNICODE_EOLN if goes beyond bounds of string.

 $Arguments:	editor		- The editor data
 				offset		- The offset from the current cursor position from which
 								to get the character

*******************************************************************************/

USHORT ATB_edit_GetCursorChar(T_ED_DATA *editor, int offset)
{
	USHORT	textIndex;
	USHORT character;

	TRACE_FUNCTION("ATB_edit_GetCursorChar");
        
	textIndex = editor->cursor.pos+offset;

	if (textIndex<0 || textIndex > editor->attr->text.len)
		character = UNICODE_EOLN;
	else
		character = ATB_string_GetChar(&editor->attr->text, textIndex);

	return character;
}


/*******************************************************************************

 $Function:		ATB_edit_CapitaliseWord

 $Description:	Returns TRUE if next word after cursor ought to be capitalised

 $Returns:		None.

 $Arguments:	editor	- The editor data

*******************************************************************************/

BOOL ATB_edit_CapitaliseWord(T_ED_DATA *editor)
{
	USHORT LastChar;
	USHORT CharBefore;

	/* First check to see if first word is to be capitalised */
	
	if (editor->textcase==ED_CASE_CAPS)
		return TRUE;

	/* If not, look at preceding characters */
	
	LastChar = ATB_edit_GetCursorChar(editor, -1);
	CharBefore = ATB_edit_GetCursorChar(editor, -2);

	if (LastChar==UNICODE_FULLSTOP || LastChar==UNICODE_EXCLAMATION
		|| LastChar==UNICODE_QUESTION || LastChar==UNICODE_EOLN)
		return TRUE;
		
	if (LastChar==UNICODE_SPACE)
		if(CharBefore==UNICODE_FULLSTOP || CharBefore==UNICODE_EXCLAMATION || CharBefore==UNICODE_QUESTION)
			return TRUE;

	return FALSE;
}

/*******************************************************************************

 $Function:		ATB_edit_FindCapital

 $Description:	returns the code of the input char converted to a capital. If char has no 
 				upper case equivalent returns original char.
 				Added for issue 1508
 
 $Returns:		UBYTE

 $Arguments:	char
 
*******************************************************************************/
	
USHORT ATB_edit_FindCapital(USHORT small_char)
{	char ascii_code= ATB_char_Ascii(small_char);	
		

		/*if "normal" character*/
		if (ascii_code>96 && ascii_code< 123)
			return (ATB_char_Unicode(ascii_code - 0x20));
		
		switch (ascii_code)
		{
			case (130): return ATB_char_Unicode(154);break;/*U with umlaut*/
			case (132): return ATB_char_Unicode(142);break;/*A with umlaut*/
			case (148): return ATB_char_Unicode(153);break;/*O with umlaut*/
			default: return ATB_char_Unicode(ascii_code);
		}

}
/*******************************************************************************

 $Function:		ATB_edit_HiddenInit

 $Description:	Initialize editor for hidden mode.

 $Returns:    	None.

 $Arguments:  	editor	- The editor data

*******************************************************************************/

ED_RES ATB_edit_HiddenInit(T_ED_DATA *editor)
{
	USHORT  len = editor->attr->text.len;

	TRACE_FUNCTION("ATB_edit_HiddenInit()");

	if (!editor)
        return ED_BAD_HANDLE;            			// element does not exist
    if (editor->hiddenText)
    	return ED_ERROR;
    	
	/* get memory for the temporary buffer */
	editor->hiddenText = (T_ATB_TEXT *) ATB_mem_Alloc(sizeof(T_ATB_TEXT));
	editor->hiddenText->len = 0;
	editor->hiddenText->data = (UBYTE *)ATB_mem_Alloc(editor->attr->size*ATB_string_Size(&editor->attr->text));	

	/* copy text to the temporary buffer */
	ATB_string_Copy(editor->hiddenText, &editor->attr->text);

	/* overwrite the string in the editor buffer with stars */
    memset(editor->attr->text.data,'\0',editor->attr->size*ATB_string_Size(&editor->attr->text));        /* Clear buffer */
	editor->attr->text.len = 0;
	ATB_edit_Reset(editor);										/* Send cursor to start */

	while (editor->attr->text.len < len)
		ATB_edit_AsciiChar(editor,'*',FALSE);
	
 	return ED_OK;
}


/*******************************************************************************

 $Function:		ATB_edit_HiddenExit

 $Description:	Deinitialize editor for hidden mode.

 $Returns:    	None.

 $Arguments:  	editor	- The editor data

*******************************************************************************/

ED_RES ATB_edit_HiddenExit(T_ED_DATA *editor)
{
	TRACE_FUNCTION("ATB_edit_HiddenExit()");
	
	if (!editor)
        return ED_BAD_HANDLE;            			// element does not exist
    if (!editor->hiddenText)
    	return ED_ERROR;
    	
	/* For hidden mode, copy the hidden text into the buffer & free memory */	
    ATB_string_Copy(&editor->attr->text, editor->hiddenText);
    ATB_mem_Free ((void *)editor->hiddenText->data, editor->attr->size*ATB_string_Size(editor->hiddenText));
    ATB_mem_Free ((void *)editor->hiddenText, sizeof(T_ATB_TEXT));
    editor->hiddenText = NULL;

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_Mode

 $Description:	Returns TRUE if the appropriate bits are set in the editor mode

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				mode	- The mode bits to check

*******************************************************************************/

void ATB_edit_SetAttr(T_ED_DATA *editor, T_ATB_WIN_SIZE *win_size, ULONG colour, UBYTE font, USHORT mode, USHORT cursor, T_ATB_TEXT *text, USHORT size)
{
	memcpy(&editor->attr->win_size, win_size, sizeof(T_ATB_WIN_SIZE));
	editor->attr->colour = colour;
	editor->attr->font = font;
	editor->attr->cursor = cursor;
	editor->attr->mode = mode;
	memcpy(&editor->attr->text, text, sizeof(T_ATB_TEXT));
	editor->attr->size = size;

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_Mode

 $Description:	Returns TRUE if the appropriate bits are set in the editor mode

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				mode	- The mode bits to check

*******************************************************************************/

UBYTE ATB_edit_Mode(T_ED_DATA *editor, USHORT mode)
{
	UBYTE result;

	if (editor->attr->mode & mode)
		result = TRUE;
	else
		result = FALSE;

    return result;
}


/*******************************************************************************

 $Function:		ATB_edit_SetMode

 $Description:	Sets the appropriate bits in the editor mode

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				mode	- The mode bits to set

*******************************************************************************/

void ATB_edit_SetMode(T_ED_DATA *editor, USHORT mode)
{
	editor->attr->mode |= mode;

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_ResetMode

 $Description:	Resets the appropriate bits in the editor mode

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				mode	- The mode bits to reset

*******************************************************************************/

void ATB_edit_ResetMode(T_ED_DATA *editor, USHORT mode)
{
	editor->attr->mode &= (~mode);

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_SetStyle

 $Description:	Sets the appropriate bits in the editor style

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				format	- The format bits to set

*******************************************************************************/

void ATB_edit_SetStyle(T_ED_DATA *editor, USHORT style)
{
	UBYTE mask;

	mask = 0;
	
	switch(style)
	{
		case DS_ALIGN_LEFT:
		case DS_ALIGN_RIGHT:
		case DS_ALIGN_CENTRE:
			mask = DS_ALIGN_RIGHT | DS_ALIGN_CENTRE;
			break;
	}

	/* Switch off previous format */
	editor->attr->startFormat.attr &= (~mask);
	/* Switch on new format */
	editor->attr->startFormat.attr |= style;

    return;
}

/*******************************************************************************

 $Function:		ATB_edit_ResetFormat

 $Description:	Resets the appropriate bits in the editor format

 $Returns:    	None.

 $Arguments:  	editor	- The editor data
 				format	- The format bits to reset

*******************************************************************************/

void ATB_edit_ResetFormat(T_ED_DATA *editor, USHORT format)
{
	editor->attr->startFormat.attr &= (~format);

    return;
}


/*******************************************************************************

 $Function:		ATB_edit_GetCase

 $Description:	Returns the currently selected text case

 $Returns:    	ED_CASE_UPPER
 				ED_CASE_LOWER
 				ED_CASE_CAPS
 				ED_CASE_NUM
 				ED_CASE_NONE

 $Arguments:  	editor	- The editor data

*******************************************************************************/

UBYTE ATB_edit_GetCase(T_ED_DATA *editor)
{
	return (UBYTE)editor->textcase;
}


/*******************************************************************************

 $Function:		ATB_edit_SetCase

 $Description:	Changes the currently selected text case

 $Returns:    	None

 $Arguments:  	editor		- The editor data
 				textcase	- Case to select.  One of:
 				 			  ED_CASE_UPPER
 							  ED_CASE_LOWER
 							  ED_CASE_CAPS
 							  ED_CASE_NUM
 							  ED_CASE_NONE

*******************************************************************************/

void ATB_edit_SetCase(T_ED_DATA *editor, UBYTE textcase)
{
	editor->textcase = textcase;
	return;
}


/*******************************************************************************

 $Function:		ATB_edit_LineGet

 $Description:	Get the pointer to the requested line in the linked list
 				
 $Returns:		The required line structure

 $Arguments:	editor		- The text editor
 				lineNo		- The line required
				
*******************************************************************************/

T_ED_LINE *ATB_edit_LineGet(T_ED_DATA *editor, SHORT lineNo)
{
	T_ED_LINE *line = editor->line;
	SHORT thisLineNo;

	thisLineNo = 0;
	if (lineNo<0)
		lineNo = 0;

	/* If the first line doesn't exist... */
	
	if (line==NULL)
	{
		editor->line = (T_ED_LINE *)ATB_mem_Alloc(sizeof(T_ED_LINE));
		memset(editor->line, 0, sizeof(T_ED_LINE));
		editor->line->next = NULL;
		line = editor->line;
	}

	/* Search for the line required */
	
	while (thisLineNo<lineNo)
	{
		if (line->next==NULL)
		{
			line->next = (T_ED_LINE *)ATB_mem_Alloc(sizeof(T_ED_LINE));
			memset(line->next, 0, sizeof(T_ED_LINE));
			line->next->next = NULL;
		}
		line = line->next;
		lineNo--;
	}
	
	return line;
}


/*******************************************************************************

 $Function:		ATB_edit_LineDestroyAll

 $Description:	Destroy all entries in the line linked list
 				
 $Returns:		None

 $Arguments:	editor		- The text editor
				
*******************************************************************************/

static void ATB_edit_LineDestroyAll(T_ED_DATA *editor)
{
	T_ED_LINE *line = editor->line;
	T_ED_LINE *newLine;
	SHORT lineNo;
		
	while (line!=NULL)
	{
		newLine = line->next;
		ATB_mem_Free((void *)line, sizeof(T_ED_LINE));
		line = newLine;
	}

	return;
}
#endif
