/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417)         $Workfile:: mfw_edt.c       $|
| $Author:: Es  $ CONDAT GmbH           $Revision:: 15              $|
| CREATED: 21.09.98                     $Modtime:: 23.03.00 8:57    $|
| STATE  : code                                                      |
+--------------------------------------------------------------------+

   MODULE  : MFW_EDT

   PURPOSE : edit handling functions

   EXPORT  :

   TO DO   :

   $History:: mfw_edt.c    
   
	Aug 16, 2004    REF: CRR 24323   Deepa M.D
	Bug:Clenup of sprintf used for tracing
	Fix:Replace the char buf[]; sprintf (buf, "...", ...); TRACE_EVENT (buf); statements by TRACE_EVENT_PX                                     $
 * 
 * *****************  Version 15  *****************
 * User: Es           Date: 23.03.00   Time: 14:40
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * added edtUnhide()
 * 
 * *****************  Version 14  *****************
 * User: Kk           Date: 21.02.00   Time: 9:36
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * changes from es inserted
 *
 * *****************  Version 13  *****************
 * User: Es           Date: 18.02.00   Time: 15:45
 * Updated in $/GSM/Condat/MS/SRC/MFW
 * added edit controls: ecTop, ecBottom
|
| *****************  Version 12  *****************
| User: Le           Date: 6.01.00    Time: 9:23
| Updated in $/GSM/Condat/MS/SRC/MFW
| Alignment of MFW versions
 *
 * *****************  Version 3  *****************
 * User: Kk           Date: 13.12.99   Time: 17:30
 * Updated in $/GSM/Condat/SND-MMI/MFW
 *
 * *****************  Version 2  *****************
 * User: Es           Date: 22.11.99   Time: 10:29
 * Updated in $/GSM/Condat/SND-MMI/MFW
 *
 * *****************  Version 1  *****************
 * User: Es           Date: 18.11.99   Time: 16:35
 * Created in $/GSM/Condat/SND-MMI/MFW
 * Initial
 *
 * *****************  Version 11  *****************
 * User: Es           Date: 6.07.99    Time: 12:18
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 10  *****************
 * User: Es           Date: 14.04.99   Time: 17:34
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * moved to CST
|
| *****************  Version 9  *****************
| User: Le           Date: 14.04.99   Time: 9:51
| Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 8  *****************
 * User: Es           Date: 1.04.99    Time: 17:07
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * removed lots of traces
 *
 * *****************  Version 7  *****************
 * User: Es           Date: 18.02.99   Time: 17:01
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 6  *****************
 * User: Es           Date: 17.02.99   Time: 19:10
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 5  *****************
 * User: Es           Date: 8.02.99    Time: 19:06
 * Updated in $/GSM/DEV/MS/SRC/MFW
 * Cursor auf 0 !
 *
 * *****************  Version 4  *****************
 * User: Es           Date: 27.01.99   Time: 15:06
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 3  *****************
 * User: Es           Date: 14.01.99   Time: 17:19
 * Updated in $/GSM/DEV/MS/SRC/MFW
 *
 * *****************  Version 2  *****************
 * User: Es           Date: 23.12.98   Time: 16:19
 * Updated in $/GSM/DEV/MS/SRC/MFW
*/


#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 "mfw_mfw.h"
#include "mfw_sys.h"
#include "gdi.h"
#include "dspl.h"
#include "mfw_edt.h"
#include "font_bitmaps.h"

#include "mfw_mmi.h"

#define TIME_TRACE_EVENT TRACE_EVENT
#ifndef TIME_TRACE_EVENT 
#define TIME_TRACE_EVENT
#endif

static int edtInsert (int c, char *b, int s, U8 curMode, U16 curCP);
static int edtCommand (U32 cmd, void *h);
void moveLeft (char * str, int ofs);

static void edtUnicodeSplitLine (int px, int py, int ls, int ly, U16 *tp);

static void moveLeftUnicode(U16 *unicodeStr, int nChars);
static int  edtInsertUnicode (MfwEdt *e, int c, U16 *b, int s);

U16 strlenUnicode(U16* str);

static void edtOutTextLines (int px, int py, int ls, int ly, U16 *tpUnicode, unsigned char* tpAscii,
							 int fontHeight, int display);
MfwRes updateWindow (MfwEdt *e, int  dy	);

int isAWordChar( char chr);

//Define the chars that correspond to the end of a word.
#define STR_WORDBREAK " .?!"

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtInit            |
+--------------------------------------------------------------------+

  PURPOSE : initialize edit handler

*/

MfwRes edtInit (void)
{
    mfwCommand[MfwTypEdt] = (MfwCb) edtCommand;

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtExit            |
+--------------------------------------------------------------------+

  PURPOSE : finalize edit handler

*/

MfwRes edtExit (void)
{
    mfwCommand[MfwTypEdt] = 0;

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtCreate          |
+--------------------------------------------------------------------+

  PURPOSE : create editor control

*/

MfwHnd edtCreate (MfwHnd w, MfwEdtAttr *a, MfwEvt e, MfwCb f)
{
    MfwHdr *hdr = (MfwHdr *) mfwAlloc(sizeof(MfwHdr));
    MfwEdt *edt = (MfwEdt *) mfwAlloc(sizeof(MfwEdt));
	MfwHdr *insert_status =0;
	TRACE_FUNCTION("edtCreate");
	
    if (!hdr || !edt)
    {
    	TRACE_ERROR("ERROR: edtCreate() Mem Alloc Failed.");
			
	   	if(hdr)
   			mfwFree((U8*)hdr,sizeof(MfwHdr));

   		if(edt)
   			mfwFree((U8*)edt,sizeof(MfwEdt));
	   	return 0;
  	}

    edt->mask = e;
    edt->flags = 0;
    edt->handler = f;
    edt->attr = a;
    edt->cp = 0;                        /* cursor position          */
    edt->curOffs = 0;

    hdr->data = edt;
    hdr->type = MfwTypEdt;

    edtUpdate(edt);

    insert_status = mfwInsert(w,hdr);
    
    if(!insert_status)
	{
  		TRACE_ERROR("ERROR: edtCreate() Failed to Install Handler. ");
   		mfwFree((U8*)hdr,sizeof(MfwHdr));
   		mfwFree((U8*)edt,sizeof(MfwEdt));
		return 0;
  	}
    return insert_status;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtDelete          |
+--------------------------------------------------------------------+

  PURPOSE : delete editor control

*/

MfwRes edtDelete (MfwHnd e)
{
    MfwRes res;

    if (!e)
        return MfwResIllHnd;

    edtHide(e);                         /* hide editor contents     */
    res = (mfwRemove(e)) ? MfwResOk : MfwResIllHnd;

    mfwFree(((MfwHdr *) e)->data,sizeof(MfwEdt));
    mfwFree(e,sizeof(MfwHdr));

    return res;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtReset           |
+--------------------------------------------------------------------+

  PURPOSE : reset editor control

*/

MfwRes edtReset (MfwHnd w)
{
    MfwEdt *e;


	TRACE_FUNCTION("edtReset()");
    if (!w)
        return MfwResIllHnd;            /* editor does not exist    */

    e = ((MfwHdr *) w)->data;

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

    e->cp = 0;                          /* cursor position          */
    e->curOffs = 0;

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtShow            |
+--------------------------------------------------------------------+

  PURPOSE : show editor

*/

MfwRes edtShow (MfwHnd e)
{
    MfwEdt *edt;

	TRACE_FUNCTION("edtShow()");

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

    edt = ((MfwHdr *) e)->data;         /* get control block        */

    edt->flags |= MfwEdtVisible;        /* editor is visible        */
    if (edt->handler)                   /* call event handler       */
        if (edt->mask & MfwEdtVisible)
            edt->handler(MfwEdtVisible,edt);
    edt->display = 1;                        /* really show it           */
    edtUpdate(edt);                     /* draw editor elements     */

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtHide            |
+--------------------------------------------------------------------+

  PURPOSE : hide editor

*/

MfwRes edtHide (MfwHnd e)
{
    MfwEdt *edt;

	TRACE_FUNCTION("edtHide()");
    if (!e)
        return MfwResIllHnd;            /* element does not exist   */

    edt = ((MfwHdr *) e)->data;         /* get edit control block   */
    edt->flags &= ~MfwEdtVisible;       /* editor is not visible    */
    if (edt->handler)                   /* call event handler       */
        if (edt->mask & MfwEdtVisible)
            edt->handler(MfwEdtVisible,edt);

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtUnhide          |
+--------------------------------------------------------------------+

  PURPOSE : unhide editor (without drawing)

*/

MfwRes edtUnhide (MfwHnd e)
{
    MfwEdt *edt;
    
	TRACE_FUNCTION("edtunhide()");
	
    if (!e)
        return MfwResIllHnd;            /* element does not exist   */

    edt = ((MfwHdr *) e)->data;         /* get edit control block   */
    edt->flags |= MfwEdtVisible;        /* editor is visible        */
    if (edt->handler)                   /* call event handler       */
        if (edt->mask & MfwEdtVisible)
            edt->handler(MfwEdtVisible,edt);

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtClear           |
+--------------------------------------------------------------------+

  PURPOSE : clear editor

*/

MfwRes edtClear (MfwHnd e)
{
    MfwEdt *edt;

    TRACE_FUNCTION("edtClear()");

    if (!e)
        return MfwResIllHnd;            /* element does not exist   */

    edt = ((MfwHdr *) e)->data;         /* get edit control block   */
    if (edtReset(e) && edt->attr->text)
    {
        *(edt->attr->text) = 0;         /* clear buffer             */
        edtUpdate(edt);                 /* clear edit area          */
    }

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtUpdate          |
+--------------------------------------------------------------------+

  PURPOSE : draw editor
GW 06/09/01 - Call chinese update if first char is 0x80,0x81 or 0x82.
GW 06/09/01 - Added extra parameters to displ_setCursorPos for the size of cursor.
*/

//Return non-zero result if chr is in the string str.
int chrInString(char chr,char* str)
{
	int i;
	i=0;

	TRACE_FUNCTION("chrInString()");
	
	while (str[i] != 0x00)
	{
		if (str[i]== chr)
			return (i+1);
		else
			i++;
	}
	//Not found -
	return (0);
}

//GW 18/09/01 Use 'isAWordChar' procedure instead of 'chrInString' 
void findWordBounds(MfwEdt *e, int *opStChr, int *opEndChr)
{
	int found;
	int stChr,endChr;

	TRACE_FUNCTION("findWordBounds()");
	
	//Find char before start of the word.
	stChr = e->cp-1;
	found = FALSE;
	while ((stChr >0) && (!found))
	{
		if (isAWordChar(e->attr->text[stChr])==0)
			found = TRUE;
		else
			stChr--;
	}
	//find char after end of the word.
	endChr = e->cp;
	found = FALSE;
	while ((e->attr->text[endChr]!=0x00 ) && (!found))
	{
		if (isAWordChar(e->attr->text[endChr])==0)
			found = TRUE;
		else
			endChr++;
	}
	*opStChr  = stChr;
	*opEndChr = endChr;
}

//GW 18/09/01 Commented out debug code. 
MfwRes edtUpdate (MfwEdt *e)
{
	UBYTE temp;

    char *tp;
    S16 px, py;                         /* top left corner of edit  */
    S16 ls;                             /* width of edit window     */
    S16 ly;                             /* bottom of edit window    */
    U8 oldFont = -1;                    /* store previous font      */
	char* endChar;

    unsigned char *tb;

	//Data used to add word highlight 
	char saveChr[2];
	char startHtext[2] = {0x01,0x00};
	char endHtext[2]   = {0x02,0x00};
	int stChr,endChr;

	U16* tmp;

	TRACE_FUNCTION("edtUpdate()");

    if (!e)
        return MfwResIllHnd;

    if (!e->attr->text)
        return MfwResErr;               /* no text to display       */

	//Have we still got keys in the buffer to process? - process them first!
    if (mfwKey_skipDisplay())
		return (MfwResOk);
    
	tb = (unsigned char*)e->attr->text;

	if ((tb[0] == 0x80) || (tb[0] == 0x81) || (tb[0] == 0x82))
	{
		return( edtUpdateUnicode (e ) );
	}

	temp = dspl_get_char_type();		
	dspl_set_char_type(DSPL_TYPE_ASCII);

	//TRACE_EVENT_P1("flags: %d", e->flags);
    if (!(e->flags & MfwEdtVisible))
        e->display = 0;                    /* invisible editor         */

	resources_setColour(e->attr->edtCol);	
    tp = e->attr->text + e->curOffs;    /* start of display buffer  */
    px = e->attr->win.px;               /* left of edit window      */
    py = e->attr->win.py;               /* top of edit window       */
    ls = e->attr->win.sx;               /* width of edit window     */
    ly = (S16) (py+e->attr->win.sy);	/* bottom of edit window    */
    if (e->attr->font != (U8) -1)
        oldFont = dspl_SelectFontbyID(e->attr->font); /* setup font */
    e->fontHeight = dspl_GetFontHeight();  /* get height of curr font  */
    e->curMode = e->attr->mode;            /* setup edi mode           */
    if (e->display)
	{
		dspl_TextOut (e->attr->win.px, e->attr->win.py, 0, endHtext);
        dspl_Clear(e->attr->win.px,e->attr->win.py,(U16)(ls+e->attr->win.px-1),(U16)(ly-1));
	}

    dspl_SetCursor(0,(U8)(e->curMode&edtCurMask));

	//Add a space to the end of the line
	endChar = &tp[strlen(tp)];
	if ((endChar[0] == 0x00) &&
		(endChar[1] == 0x00))
	{
		endChar[0] = ' ';
		endChar[1] = 0x00;
		//For some editors, we want to highlight a complete word
		if (e->curMode & edtModWordSkip)
		{

			//find char at the start of the word
			findWordBounds(e,&stChr,&endChr);
			saveChr[0] = e->attr->text[stChr];
			saveChr[1] = e->attr->text[endChr];
			if (endChr == e->cp) // do not highlight if at the start of a word
			{
				if (stChr > e->curOffs)
					e->attr->text[stChr] = 0x01;
				else
					dspl_TextOut (e->attr->win.px, e->attr->win.py, 0, startHtext);
				e->attr->text[endChr] = 0x02;
			}

		}
		edtOutTextLines(e->attr->win.px, e->attr->win.py, ls, ly, NULL, (unsigned char*)tp,
						e->fontHeight, e->display); //* show it     * /
		if (e->curMode & edtModWordSkip)
		{
			e->attr->text[stChr] = saveChr[0];
			e->attr->text[endChr]= saveChr[1];
		}
		//and remove space again.
		endChar[0] = 0x00;
	}
	else
	{	//Cannot add space
		edtOutTextLines(e->attr->win.px, e->attr->win.py, ls, ly, NULL, (unsigned char*)tp,
						e->fontHeight, e->display); //* show it     * /
	}
	//GW 18/09/01 - Display predicted word.
    if (e->display)
	{
		if ((e->attr->predText[0] != '\0') && (e->attr->win.py >=e->fontHeight))
        {
			dspl_TextOut(0,e->attr->win.py-e->fontHeight,0,"             " );
			dspl_TextOut(0,e->attr->win.py-e->fontHeight,1,e->attr->predText );
        }
	}

    if (e->display && (e->curMode & edtCurMask))
    	{
        dspl_SetCursorPos(e->curCX+e->attr->win.px,e->curCY,e->curCSize,(S16)e->fontHeight); // sbh 19/02/02, position cursor correctly
    	}
    if (oldFont != (U8) -1)
        dspl_SelectFontbyID(oldFont);   /* restore previous font    */

#ifdef MFW_DEBUG_DISPLAY_SIZE
	{
		USHORT ax,ay,aw,ah;
		ax = e->attr->win.px;
		ay = e->attr->win.py;
		aw = e->attr->win.sx;
		ah = e->attr->win.sy;
    	dspl_DrawRect(ax,ay,(ax+aw-1),(ay+ah-1));
	    {
			/***************************Go-lite Optimization changes Start***********************/
	    	//	Aug 16, 2004    REF: CRR 24323   Deepa M.D
	    	TRACE_EVENT_P4(" ax:%d ay:%d aw:%d ah:%d",ax,ay,aw,ah);
			/***************************Go-lite Optimization changes end***********************/
	    } 	
    }
#endif
	dspl_set_char_type(temp);
	resources_restoreColour();
TIME_TRACE_EVENT("edtUpdate-end");
    return MfwResOk;
}



//GW 18/09/01 - Corrected linefeed definition and added carriage return definition.
#define UNICODE_SPACE			0x2000
#define UNICODE_LINEFEED		0x0A00
#define UNICODE_CR				0x0D00
#define UNICODE_EOLN			0x0000
#define UNICODE_NONASCII		0x00FF
#define UNICODE_STARTHIGHLIGHT	0x0100 
#define UNICODE_ENDHIGHLIGHT	0x0200


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtChar            |
+--------------------------------------------------------------------+

  PURPOSE : handle editing char
//GW 06/09/01 - Call chinese procedure if first char is 0x80,0x81 or 0x82 or display type is not ascii.

*/
char getCursorChar(MfwHnd e, int offset )
{
    MfwEdt *edit; 
	int chPos;

	TRACE_FUNCTION("getCursorChar()");

	if (!e)
        return (0xFF);

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return (0xFF);            /* not an editor            */

	edit = ((MfwHdr *) e)->data;


	chPos = offset + edit->cp;
	if ((chPos < 0) || (chPos > strlen(edit->attr->text)))
		return (0x00);
	else
		return (edit->attr->text[chPos]);
}
int isAWordChar( char chr)
{	TRACE_FUNCTION("isAWordChar()");



	if ( ((chr >='A') && (chr <='Z')) || 
		 ((chr >='a') && (chr <='z')) )
		return (TRUE);
	else
		return(FALSE);
}
MfwRes edtChar (MfwHnd e, int c)
{
	int warn99;
    MfwEdt *edit; 
    U16 bs; 
	int dy;	//Change in cursor y position when moving up/down lines.
    char *tbString; 
	int found;

	TRACE_FUNCTION("edtChar()");

   if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            /* not an editor            */

	edit = ((MfwHdr *) e)->data;
 	tbString = &edit->attr->text[0];

	if (tbString[0] & 0x80)
	{
		return(edtCharUnicode(e,c));
	}
	bs = edit->attr->size;
	dy = 0;
    switch (c)
    {
		
        case ecEscape:                  //* quit editor              
            return MfwResDone;
        case ecLeft:					//* cursor left              
			if (edit->attr->mode & edtModWordSkip) 
			{
				edit->cp = edit->cp-1;
				if (isAWordChar(edit->attr->text[edit->cp]))
				{	//pointing to a letter in a word. Move left until next char is not a word char
					found = FALSE;
					while (!found)
					{
				        if (edit->cp == 0)
							found = TRUE;
						else if (isAWordChar(edit->attr->text[edit->cp-1]))
							edit->cp = edit->cp-1;
						else
							found = TRUE;
					}
				}
			}
			else
				edit->cp = edit->cp-1;
	        if (edit->cp <= 0)
				edit->cp = 0;
            break;
        case ecRight:                   //* cursor right 
			if (edit->attr->mode & edtModWordSkip) 
			{
				if (!isAWordChar(edit->attr->text[edit->cp]))
					edit->cp = edit->cp+1;//current char is not a word - move to next and stop.
				else 
				{
					found = FALSE;
					while (!found)
					{
						edit->cp = edit->cp+1;
				        if (!isAWordChar(edit->attr->text[edit->cp]))
							found = TRUE;//found a non-word char (could be the end of the string
					}
				}
			}
			else
				edit->cp = edit->cp+1;
            break;
        case ecUp:                      //* cursor up      
  			dy =  -1;
            break;
        case ecDown:                    //* cursor down           
  			dy = 1;
            break;
        case ecTop:                     //* cursor to start of text  
            edit->cp = 0;
            edit->curOffs = 0;
            break;
        case ecBottom:                  //* cursor to end of text   
            edit->cp = strlen(tbString);
            edit->curOffs = 0;
            break;
        case ecBack:                    //* backspace                *
            if ((edit->cp != 0) && (strlen(tbString)+1 > edit->cp))
			{
				moveLeft(&tbString[edit->cp-1],1);
			}
			edit->cp = edit->cp-1;
	        if (edit->cp <= 0)
				edit->cp = 0;
            break;
        case ecDel:                     //* delete                   *
			if (strlen(tbString) > edit->cp)
			{
				moveLeft(&tbString[edit->cp],1);
			}
            break;
        case ecEnter:                   //* cr/lf                    
            c = UNICODE_LINEFEED;
            edtInsert(c,tbString,bs, edit->curMode, edit->cp);
			return (edtChar(e,ecRight));
            break;
        default:                        //* normal char              
            edtInsert(c,tbString,bs, edit->curMode, edit->cp);

			if (edit->attr->alphaMode NEQ TRUE)
				return (edtChar(e,ecRight));
			/*NM, p003 end*/	
            break;
    }
    edit->display = 1;                        //* really show it           
  	updateWindow( edit, dy);
    edtUpdate(edit);

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtCharUnicode     |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
MfwRes edtCharUnicode (MfwHnd e, int c)
{
    MfwEdt *edit; 
    U16 bs; 
	int dy;
    U16 *tbUnicode; 

 	TRACE_FUNCTION("edtCharUnicode()");
 	
    if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            //* not an editor            

	edit = ((MfwHdr *) e)->data;
	bs = edit->attr->size;
	tbUnicode = (U16*) &edit->attr->text[2];

	dy = 0;
    switch (c)
    {
        case ecEscape:                  //* quit editor              
            return MfwResDone;
        case ecLeft:                    //* cursor left              
            if (edit->cp <= 0)
				edit->cp = 0;
			else
	            edit->cp = edit->cp-1;
            break;
        case ecRight:                   //* cursor right             
			if (tbUnicode[edit->cp]!=UNICODE_EOLN)
	            edit->cp = edit->cp +1;
            break;
        case ecUp:                      //* cursor up                
  			dy = -1;
            break;
        case ecDown:                    //* cursor down              
  			dy = 1;
            break;
        case ecTop:                     //* cursor to start of text  
            edit->cp = 0;
            edit->curOffs = 0;
  			dy = 0;
            break;
        case ecBottom:                  //* cursor to end of text    
			while (tbUnicode[edit->cp]!=UNICODE_EOLN)
			{
	            edit->cp = edit->cp +1;
			}
            break;
        case ecBack:                    //* backspace                
            if (edit->cp != 0)
	            moveLeftUnicode(tbUnicode+edit->cp-1,1);
            return edtCharUnicode(e,ecLeft);
        case ecDel:                     //* delete                   
            moveLeftUnicode(tbUnicode+edit->cp,1);
            break;
        case ecEnter:                   //* cr/lf                    
            c = UNICODE_LINEFEED;
            edtInsertUnicode(edit,c,tbUnicode,bs);
            return edtCharUnicode(e,ecRight);
        default:                        //* normal char  
            edtInsertUnicode(edit,c,tbUnicode,bs);

			if (edit->attr->alphaMode NEQ TRUE)
				return (edtCharUnicode(e,ecRight));
			/*MC end*/	
            break;

    }
    edit->display = 1;                        // really show it           
  	updateWindow( edit, dy);
    edtUpdateUnicode(edit);


    return MfwResOk;
}




/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : Return no of chinese chars in a string

  GW 06/09/01 - Created
  GW 25/09/01 - Corrected length - now skips first two chars.
*/

U16 strlenUnicode(U16* str)
{
	U16 len = 2; //First char is 0x80, second char is 0x00

	TRACE_FUNCTION("strlenUnicode()");
	
	while (*str!=UNICODE_EOLN)
	{
		//treat ascii chars as half size chinese chars.
		len = len + 2;
		str++;
	}
	return (len);
}


//Assumptions :-
//str is a null-terminated string 
//edit->cp is the cursor position of the char 
//The string is inserted before the cursor char
//The cursor is moved strlen(str) chars forward.
MfwRes edtInsertString (MfwHnd e, char* insWord)
{
    MfwEdt *edit;
    char *textBfr;

	int lenText;
	int lenInsWord;
    int maxTextBfrLen;
	int i;


TRACE_FUNCTION("edtInsertString()");

    if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            /* not an editor            */

	edit = ((MfwHdr *) e)->data;
	if (insWord == NULL)
		return (MfwResOk);	//no string to insert - trivial operation.
	if (insWord[0] == 0x00)
		return (MfwResOk);	//no string to insert - trivial operation.
	textBfr			= edit->attr->text;
	if ((textBfr[0] == 0x80) || (textBfr[1] == 0x81) || (textBfr[2] == 0x82))
	{//String is unicode
		return (edtInsertUnicodeString (e, insWord));
	}
	maxTextBfrLen	= edit->attr->size;
	lenText		= strlen(textBfr);
	lenInsWord	= strlen(insWord);
	if ((lenText+lenInsWord) >= maxTextBfrLen)
		return (MfwResErr); //String too long 

	//move text up by 'lemnInsWord' words
	for (i=lenText;i>=edit->cp;i--)
	{
		textBfr[i+lenInsWord]=textBfr[i];
	}
	//and copy string into buffer.
	for (i=0;i<lenInsWord;i++)
		textBfr[edit->cp+i] = insWord[i];
	edit->cp = edit->cp+lenInsWord;
	//Update cursor position
	//<TBD>
	//And output updated text
	edit->display = 1;
	updateWindow( edit, 0);
    edtUpdate(edit);

    return MfwResOk;
}
#define MAXWORD_ARRAY 32
//Assumptions :-
//'removeWord' is char array of MAXWORD chars 
//edit->cp is the cursor position of the char 
//The word removed is at or just before the cursor char
//The cursor is placed before the previous word.
//a space char (start or end) will be removed if there is one.
//GW 18/09/01 - Use 'isAWordChar' procedure
MfwRes edtRemoveString (MfwHnd e, char* removeWord)
{
    MfwEdt *edit;
    char *textBfr;

	int i,j;
	int stChr,endChr;

	TRACE_FUNCTION("edtRemoveString");
	
	if (dspl_get_char_type() != DSPL_TYPE_ASCII)
	{	//String is unicode - can't remove word (could remove a char but...)
		return(MfwResIllHnd);
	}

    if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            //* not an editor            *

	edit = ((MfwHdr *) e)->data;
	textBfr			= edit->attr->text;
	if ((textBfr[0] == 0x80) || (textBfr[1] == 0x81) || (textBfr[2] == 0x82))
	{//String is unicode - can't remove word (could remove a char but...)
		return(MfwResIllHnd);
	}

	findWordBounds(edit, &stChr, &endChr);
	//Copy word out
	j = 0;
	for (i=stChr;i<endChr;i++)
	{
		if (j<MAXWORD_ARRAY-1)
		{
			removeWord[j] = textBfr[i];
			if (isAWordChar(removeWord[j]))
				j++;//not punctuation .
			else if (removeWord[j] == ' ') //but do include last space (if it is a space)
				j++;
		}
	}
	removeWord[j] = 0x00;

	//and now move text up by 'j' chars.
	i=stChr;
	j=endChr; 
	//skip one space at start/end.
	if (textBfr[i] != ' ')
	{
		i++;
		if (textBfr[j] == ' ')
			j++;
	}
	//else overwrite first space
	edit->cp = i;

	while((textBfr[i] != 0x00) && (i < j))
	{
		textBfr[i] = textBfr[j];
		i++;
		j++;
	}

	edit->display = 1;
	updateWindow( edit, 0);
    edtUpdate(edit);

    return MfwResOk;
}


//Create a copy of the current word.
//GW 18/09/01 - Use 'isAWordChar' procedure
MfwRes edtCopyString (MfwHnd e, char* removeWord)
{
    MfwEdt *edit;
    char *textBfr;

	int i,j;
	int stChr,endChr;
	
	TRACE_FUNCTION("edtCopyString");
	
	if (dspl_get_char_type() != DSPL_TYPE_ASCII)
	{	//String is unicode - can't remove word (could remove a char but...)
		return(MfwResIllHnd);
	}

    if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            //* not an editor            *

	edit = ((MfwHdr *) e)->data;
	textBfr			= edit->attr->text;
	if ((textBfr[0] == 0x80) || (textBfr[0] == 0x81) || (textBfr[0] == 0x82))
	{//String is unicode - can't remove word (could remove a char but...)
		return(MfwResIllHnd);
	}

	findWordBounds(edit, &stChr, &endChr);
	//Copy word out
	j = 0;
	for (i=stChr;i<endChr;i++)
	{
		if (j<MAXWORD_ARRAY-1)
		{
			removeWord[j] = textBfr[i];
			if (isAWordChar(removeWord[j]))
				j++;//not punctuation.
			else if (removeWord[j] == ' ') //but do include last space (if it is a space)
				j++;
		}
	}
	removeWord[j] = 0x00;

	edit->display = 1;
	updateWindow( edit, 0);
    edtUpdate(edit);

    return MfwResOk;
}




MfwRes edtInsertUnicodeString (MfwHnd e, char* insWordChar)
{
    MfwEdt *edit;
    U16 *unicodeBfr;

	int lenText;
	int lenInsWord;
    int maxTextBfrLen;
	int i;
	U16* insWordUnicode;
	insWordUnicode = (U16*) insWordChar;


	TRACE_FUNCTION("edtInsertUnicodeString");
    if (!e)
        return MfwResIllHnd;

    if (((MfwHdr *)e)->type != MfwTypEdt)
        return MfwResIllHnd;            //* not an editor 

	edit = ((MfwHdr *) e)->data;
	if (insWordUnicode == NULL)
		return (MfwResOk);	//no string to insert - trivial operation.
	if (insWordUnicode[0] == 0x0000)
		return (MfwResOk);	//no string to insert - trivial operation.
	unicodeBfr	= (U16*) &edit->attr->text[2];
	if ((edit->attr->text[0] != (char)0x80) && 
		(edit->attr->text[0] != (char)0x81) && 
		(edit->attr->text[0] != (char)0x82))
	{//String is unicode
		return (edtInsertString (e, insWordChar));
	}

	maxTextBfrLen	= edit->attr->size;
	lenText		= strlenUnicode(unicodeBfr);
	lenInsWord	= strlenUnicode(insWordUnicode);
	if ((lenText+lenInsWord) >= maxTextBfrLen)
		return (MfwResErr); //String too long 

	//move text up by 'lemnInsWord' chars
	for (i=lenText/2;i>=edit->cp;i--)
	{
		unicodeBfr[i+lenInsWord]=unicodeBfr[i];
	}
	//and copy string into buffer.
	for (i=0;i<lenInsWord/2;i++)
		unicodeBfr[edit->cp+i] = insWordUnicode[i];
	edit->cp = edit->cp+lenInsWord/2;
	//Update cursor position
	//<TBD>
	//And output updated text
	edit->display = 1;
	updateWindow( edit, 0);
    edtUpdateUnicode(edit);

    return MfwResOk;
}




/*

  
	
	  
		
		  
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtInsert          |
+--------------------------------------------------------------------+

  PURPOSE : insert editing char
  SPR1017 - NH  - Added "curMode" and "curCP" parameters.

*/

static int edtInsert (int c, char *b, int s, U8 curMode, U16 curCP)
{
    int size = (c > 0x80) ? 2 : 1;

	TRACE_FUNCTION("edtInsert");
    if (!curMode)
        return 0;

	if (!(curMode & edtModOverWr))
		{
		if ((int) strlen(b) >= s - size)          /* no more space in buffer  */
        	return 0;
    	
        moveRight(b+curCP,strlen(b+curCP),size);
		}
	else
		{
		if (curCP > s-size )				/* SH - for overwrite mode, only stop input */
			return 0;						/* when the cursor is at the maximum string size */
		}

    if (size == 2)
        *((U16 *) (b+curCP)) = (U16) c;
    else
    	{
    	*(b+strlen(b)+1) = (char) 0;		// SH - make sure string is null terminated
        *(b+curCP) = (char) c;
    	}
    return 1;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : moveRight          |
+--------------------------------------------------------------------+

  PURPOSE : move right memory
  s = no of chars to move 
  d = size (no of chars to be inserted in string) 
  b = current position
*/
void moveRight (char *b, int s, int d)
{
    char *p;
    
	TRACE_FUNCTION("edtInsert");
	
    b += s++;                           /* start with trailing zero */
    p = b + d;                          /* new = old + distance     */
    while (s--)
    {
        *p = *b;
        p--;
        b--;
    }
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : moveLeft           |
+--------------------------------------------------------------------+

  PURPOSE : move left memory
  s = no of chars to move 
  d = size (no of chars to be inserted in string) 
  b = current position
  str - string
*/
void moveLeft (char * str, int ofs)
{

	
	while (*str)
	{
		str[0] = str[ofs];
		if (*str)
			str++;
	}
	
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE : edtCommand         |
+--------------------------------------------------------------------+

  PURPOSE : handle mfw windows command

*/

static int edtCommand (U32 cmd, void *h)
{
	TRACE_FUNCTION("edtCommand");

    switch (cmd)
    {
        case MfwCmdDelete:              /* delete me                */
            if (!h)
                return 0;
            edtDelete(h);
            return 1;
        case MfwCmdUpdate:              /* repaint                  */
            if (!h || ((MfwHdr *) h)->type != MfwTypEdt)
                return 0;
            edtUpdate(((MfwHdr *) h)->data);
            return 1;
        default:
            break;
    }

    return 0;
}




/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
  //Move part of string right (delete char)
void moveLeftUnicode(U16* unicodeStr, int nChars)
{
	TRACE_FUNCTION("moveLeftUnicode");
	//Copy until end of line char reached - do not overwrite existing EOLN char 
	while (unicodeStr[0] != UNICODE_EOLN)
	{
		unicodeStr[0] = unicodeStr[nChars];
		if (unicodeStr[0] != UNICODE_EOLN)
			unicodeStr++;
		//else we have copied end of line char - stop.
	}

}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
U16 strlenUnicodePixels(U16* str)
{
	U16 len = 0;

	TRACE_FUNCTION("strlenUnicodePixels");
	
	while (*str!=UNICODE_EOLN)
	{	//Is next char an ascii char ? 
		if ((*str & UNICODE_NONASCII) != 0)
			len = len+12;
		else
			len = len+6;
		str++;
	}
	return (len);
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
U16* strchrUnicode(U16* str,U16 chr)
{
	TRACE_FUNCTION("strchrUnicode");
	
	while (*str!=UNICODE_EOLN)
	{
		if (*str==chr)
			return (str);
		else
			str++;
	}
	return (NULL);
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
//Return pointer to end of unicode string.
U16* strendUnicode(U16* tp)
{	TRACE_FUNCTION("strendUnicode");
	while (*tp!=UNICODE_EOLN)
	{
		tp++;
	}
	return (tp);

}
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
//Move string right by 'nChars' (insert char)
static void moveRightUnicode(U16 *unicodeStr, int nChars)
{
	U16* strEndPtr;

	TRACE_FUNCTION("moveRightUnicode");
	
	strEndPtr = strendUnicode( unicodeStr);
	while (strEndPtr >= unicodeStr)
	{
		strEndPtr[nChars] = strEndPtr[0];
		strEndPtr--;
	}
}

static int edtInsertUnicode (MfwEdt *edit, int c, U16 *b, int s)
{	//Unicode chars are always 2 bytes.
	U16* bCursor;

	TRACE_FUNCTION("edtInsertUnicode");

    if (!edit->curMode)
        return 0;

    if ( strlenUnicode(b) >= s/* -2 MC SPR 1319, allow last 2 bytes to be used*/ )          //* no more space in buffer  *
        return 0;

	bCursor = b+edit->cp;

    if (!(edit->curMode & edtModOverWr))
        moveRightUnicode(bCursor,1);

	*((U16 *) (b+edit->cp )) = (U16) c;

    return 1;

}

int wArray[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

int getCharWidth(int nextChar)
{
	int w;
	if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
		w = 6;
	else
		w = font_getCharWidth( ((nextChar & 0x00FF) <<8) | ((nextChar & 0xFF00) >>8) );
	return (w);
}

static void edtOutTextLines (int px, int py, int ls, int ly, U16 *tpUnicode, unsigned char* tpAscii,
							 int fontHeight, int display)
{
    U16 ctWord;
	unsigned char ctByte;
    unsigned int fitChars;			//No of chars that fit on this line.
	U16 nextChar;					//next char to display
	int lineWidth;					//Width (so far) of the current line of text.
	int dispEnd = 0;
	int spaceChar;
	int charWidth;
	int punctuation;
	char chr;
	if ((tpAscii==NULL) && (tpUnicode == NULL))
		return;

         
	fitChars = 0;
	if (tpAscii)
	{
		nextChar = (tpAscii[fitChars] << 8) & 0xFF00;
		if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
		{
			fitChars++;
			nextChar = (tpAscii[fitChars] << 8) & 0xFF00;
		}
	}
	else
	{
		 nextChar = tpUnicode[fitChars];
		if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
		{
			fitChars++;
			nextChar = tpUnicode[fitChars];
		}
	}

    while ((nextChar != UNICODE_EOLN) && (!dispEnd))                /* any more to display      */
    {
		fitChars = 0;
		if (tpAscii)
		{
			charWidth = getCharWidth(nextChar);
			nextChar = (tpAscii[fitChars] << 8) & 0xFF00;
			if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
			{	//linefeed - always start a new-line.
				charWidth = ls+1;
			}
		}
		else
		{
			nextChar = tpUnicode[fitChars];
			charWidth = getCharWidth(nextChar);
			if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
				{	//linefeed - always start a new-line.
					charWidth = ls+1;
				}
		}
		lineWidth = 0;
		spaceChar = -1;

		while ((lineWidth <= ls) && (nextChar != UNICODE_EOLN))
		{
			lineWidth = lineWidth + charWidth;

			//If the last char added still fits on the line
			if (lineWidth <= ls)
			{	//move on to the next character.
				fitChars++;
				//if the previous char was a space, we can cut the line on the next char.
				punctuation = FALSE;
				if ((nextChar & UNICODE_NONASCII) == 0)
				{
					chr = (nextChar >> 8) & 0x00FF;
					if (chr==' ')			// sbh - only space is punctuation now.
						punctuation = TRUE;
				}
				//Remember when we find a space if it is not the first char of a new line
				if ((fitChars > 1) &&
					((punctuation) || 
					 (nextChar == UNICODE_STARTHIGHLIGHT)|| 
					 (nextChar == UNICODE_ENDHIGHLIGHT)))
				{	//save char after space.
					spaceChar = fitChars;
				}
				if (tpAscii)
				{
					charWidth = getCharWidth(nextChar);
					nextChar = (tpAscii[fitChars] << 8) & 0xFF00;
				}
				else
				{
					 nextChar = tpUnicode[fitChars];
					charWidth = getCharWidth(nextChar);
				}
				if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
				{	//linefeed - always start a new-line.
					charWidth = ls+1;
				}

			}
		}
        if (nextChar == UNICODE_EOLN)
        {                               /* all fits fine ...        */
			dispEnd = TRUE;
		}
		else if ((nextChar == UNICODE_LINEFEED) || (nextChar == UNICODE_CR))
		{	//Break line on this linefeed char
		}
		else if (spaceChar != -1) // we have a space in the line
		{	
			fitChars = spaceChar;
		}
		if (tpAscii)
		{
	        ctByte = tpAscii[fitChars];			/* save not fitting char    */		
	        tpAscii[fitChars] = 0x00;//UNICODE_EOLN;	/* cut the line             */
			if (display)
				dspl_TextOut((U16)px,(U16)py, 0, (char*)tpAscii); /* display line         */
			tpAscii[fitChars] = ctByte;			/* restore                  */
	        tpAscii = &tpAscii[fitChars];				/* and go ahead             */
			//For linefeed char - move to next char.
			if (((ctByte <<8) == UNICODE_LINEFEED) || ((ctByte <<8) == UNICODE_CR))
				tpAscii++;

		}
		else
		{
	        ctWord = tpUnicode[fitChars];			/* save not fitting char    */
	        tpUnicode[fitChars] = UNICODE_EOLN;	/* cut the line             */
			if (display)
				dspl_TextOut((U16)px,(U16)py, DSPL_TXTATTR_UNICODE, (char*)tpUnicode); /* display line         */
			tpUnicode[fitChars] = ctWord;			/* restore                  */
	        tpUnicode = &tpUnicode[fitChars];				/* and go ahead             */
			if ((ctWord == UNICODE_LINEFEED) || (ctWord == UNICODE_CR))
				tpUnicode++;
		}        
        py = py + fontHeight;			/* move to next screen line */
        if (py > ly - fontHeight)		/* past end of screen ?     */
            dispEnd = TRUE;             /* clip the rest            */
    }
}

/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/
MfwRes edtUpdateUnicode (MfwEdt *e)
{
	int warn;
	UBYTE temp;

    S16 ls;                             /* width of edit window     */
    S16 ly;                             /* bottom of edit window    */
    U8 oldFont = -1;                    /* store previous font      */
	/* NM p004
	U8 uMode;
	*/
    U16 *tpWord;	
	U16 *endChar;	
	static char bmp[5];

	TRACE_FUNCTION("edtUpdateUnicode");
	
    if (!e)
        return MfwResIllHnd;

    if (!e->attr->text)
        return MfwResErr;               /* no text to display       */

	if (((unsigned char)e->attr->text[0] < 0x80) || ((unsigned char)e->attr->text[0] > 0x83))
        return MfwResErr;               /* text is not unicode      */
		
	temp = dspl_get_char_type();		
	dspl_set_char_type(DSPL_TYPE_UNICODE);

    if (!(e->flags & MfwEdtVisible))
        e->display = 0;                    /* invisible editor         */

	tpWord = ((U16*)&e->attr->text[2]) + e->curOffs;
    ls = e->attr->win.sx;               /* width of edit window     */
    ly = (S16) (e->attr->win.py+e->attr->win.sy);  /* bottom of edit window    */
    if (e->attr->font != (U8) -1)
        oldFont = dspl_SelectFontbyID(e->attr->font); /* setup font */
    e->fontHeight = dspl_GetFontHeight();  /* get height of curr font  */
    e->curMode = e->attr->mode;            /* setup edi mode           */
    if (e->display)
        dspl_Clear(e->attr->win.px,e->attr->win.py,(U16)(ls+e->attr->win.px-1),(U16)(ly-1));
    dspl_SetCursor(0,(U8)(e->curMode&edtCurMask));

	//Add a space to the end of the line
	endChar = strendUnicode(tpWord);
	if ((endChar[0] == UNICODE_EOLN) &&
		(endChar[1] == UNICODE_EOLN))
	{

		endChar[0] = UNICODE_SPACE;
		endChar[1] = UNICODE_EOLN;

		edtOutTextLines(e->attr->win.px, e->attr->win.py, ls, ly, tpWord, NULL,
						e->fontHeight, e->display); //* show it     * /

		//and remove space again.
		endChar[0] = UNICODE_EOLN;
	}
	else
	{	//Cannot add space
		edtOutTextLines(e->attr->win.px, e->attr->win.py, ls, ly, tpWord, NULL,
						e->fontHeight, e->display); //* show it     * /
	}
	
	
    if (e->display && (e->curMode & edtCurMask))
        dspl_SetCursorPos(e->curCX,e->curCY,e->curCSize,(S16)e->fontHeight); /* display cursor           */
    if (oldFont != (U8) -1)
        dspl_SelectFontbyID(oldFont);   /* restore previous font    */


		
	dspl_set_char_type(temp);

    return MfwResOk;
}


/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417)        MODULE  : MFW_EDT            |
| STATE   : code                        ROUTINE :        |
+--------------------------------------------------------------------+

  PURPOSE : 

  GW 06/09/01 - Created
*/

//Incodmation relating to last 'space' char found.
typedef struct {
	int charWidth;
	int lineCharPos;
} T_SPACE_EDITINFO;

//Information about current editor
typedef struct  {
	int txtWidth;
	int charWidth;
	int endOfLine;		//TRUE indicates end of a text line
	int endOfText;		//TRUE indicates no more chars in line.
	int lineXpos;		//Current x-pos (in pixels) of cursor.
	int lineCharPos;	//Current char/word position in array
	int lastChar;		//index of last char on cursor line
	BOOL precedingEOL;	// sbh - preceding character was a CR/LF
	T_SPACE_EDITINFO space;
} T_EDITINFO;


//Calculate width of chars on screen so far.
//GW 18/09/01 - Corrected code dealing with linefeeds and also deal with carriage returns.
void getTotalWidth(U16 txtChar, int scrSxPixels, T_EDITINFO *editInfo )
{
	char chr;
	int punctuation;
	
	TRACE_FUNCTION("getTotalWidth");
	
	editInfo->endOfLine = FALSE;

	if (editInfo->precedingEOL)				// Previous character was CR/LF
		{
		editInfo->precedingEOL = FALSE;
		editInfo->endOfLine = TRUE;
		}
		
	if (txtChar == UNICODE_EOLN)
	{
		editInfo->endOfText = TRUE;		
		editInfo->charWidth = getCharWidth(txtChar);//6;	// sbh - Has width, so it can be wrapped if necessary
	}
	else if ((txtChar == UNICODE_LINEFEED) || (txtChar == UNICODE_CR))
	{
		editInfo->precedingEOL = TRUE;
		editInfo->charWidth = getCharWidth(txtChar);//6;
	}
	else //GW-Get actual width for proportional fonts.
		editInfo->charWidth = getCharWidth(txtChar);
	
	if (editInfo->txtWidth+editInfo->charWidth >  scrSxPixels)
	{	//newline
		editInfo->txtWidth = 0;
		editInfo->endOfLine = TRUE;

		//update start of window.
		if ((txtChar == UNICODE_LINEFEED)||(txtChar == UNICODE_CR))
		{
			editInfo->lineCharPos	= editInfo->space.lineCharPos+1;

		}
		else if (editInfo->space.lineCharPos > 0) 
		{	//reset editor position back to here
			editInfo->lineCharPos	= editInfo->space.lineCharPos+1;
			editInfo->charWidth     = editInfo->space.charWidth;
			editInfo->endOfText = FALSE;
		}

		editInfo->space.lineCharPos = 0;
	}
	else
	{	
		punctuation = FALSE;
		if (txtChar==UNICODE_SPACE)						// sbh - will only wrap on a space
			punctuation = TRUE;

		if ((punctuation) && (editInfo->txtWidth > 0)) 
		{	//A space is a good point for a soft break - remember enough info so that this
			//point can be restored
			editInfo->space.lineCharPos = editInfo->lineCharPos;		
			if ((txtChar == UNICODE_LINEFEED) || (txtChar == UNICODE_CR))
				editInfo->space.charWidth   = getCharWidth(txtChar);
			else
				editInfo->space.charWidth   = editInfo->charWidth;
			}
	}

}
//Update the cursor position
// SPR920 - NH (SH) - provide editor handle e, as cursor vars are now in structure

void updateCursorPos(MfwEdt *e, T_EDITINFO *editInfo)
{
	TRACE_FUNCTION("updateCursorPos");
	e->curCSize	= editInfo->charWidth;
	if (e->curCSize < 3)
		e->curCSize = 3;
	e->curCX	= editInfo->txtWidth;
}

//dy - move cursor up/down screen by dy lines
MfwRes updateWindow (MfwEdt *e, int  dy	)
{
T_EDITINFO editInfo;

	int winCharPos;		//char position  in string of the first text line in current window
	int winLineNo;		//line no of the first text line to be displayed

	int ipCursorCharPos;	
	int opCursorCharPos;	
	int cursorLineNo;	//line no the cursor is on

	int linePos;		//char pos in string of current line.
	int lineNo;			//overall displayed line (from start of text)

	int editComplete;	//flag indicating cursor position found/updated or end of line reached.

	int scrSxPixels;
	int scrSyLines;

	char* textStartAscii;
	U16* textStartUnicode;
	U16  charUnicode;	//current unicode char.

	int textStrType;

	TRACE_FUNCTION("UpdateWindow()");

	//Set up screen size - the width in pixels and no of lines displayed.
	if (e->fontHeight > 5)
		scrSyLines = e->attr->win.sy / e->fontHeight;
	else
		scrSyLines = e->attr->win.sy / 6;
	scrSxPixels = e->attr->win.sx;

	ipCursorCharPos = e->cp;
	if ((ipCursorCharPos < 0) || (ipCursorCharPos > 32767))
		ipCursorCharPos = 0;
	opCursorCharPos = ipCursorCharPos;
	lineNo = 0;
	winLineNo = 0;
	winCharPos = 0;
	editComplete = FALSE;
	editInfo.endOfText = FALSE;
	editInfo.lineCharPos = 0;
	editInfo.lastChar = 9999;
	editInfo.space.lineCharPos = 0;
	editInfo.precedingEOL = FALSE;
	linePos = 0;

	editInfo.txtWidth = 0;
	cursorLineNo = 0;

	if ((e->attr->text[0] == (char)0x80) || 
		(e->attr->text[0] == (char)0x81) || 
		(e->attr->text[0] == (char)0x82))
	{
		textStrType = DSPL_TYPE_UNICODE;
		textStartUnicode = (U16*) &e->attr->text[2];    /* start of edit text - 16 bits/char      */
	}
	else
	{
		textStrType = DSPL_TYPE_ASCII;
		textStartAscii = &e->attr->text[0];				/* start of edit text - 8 bits/char       */
	}

	//Go through editor and work out 
	// (1) current x-pixel position for cursor 
	// (2) line number of the start of the display.
	while( (!editInfo.endOfText) && (!editComplete) )
	{
		if (textStrType == DSPL_TYPE_UNICODE)
		{
			charUnicode = textStartUnicode[editInfo.lineCharPos];
			getTotalWidth(charUnicode,scrSxPixels,&editInfo);
		}
		else
		{
			charUnicode = (textStartAscii[editInfo.lineCharPos] << 8) & 0xFF00;
			getTotalWidth(charUnicode,scrSxPixels,&editInfo);
		}

		if (editInfo.endOfLine)
		{
			//newline or current char will not fit on previous line.
			lineNo++;
			linePos = editInfo.lineCharPos;
			editInfo.txtWidth = 0;
			//Is this the first line to be displayed in the editor?
			if (editInfo.lineCharPos <= e->curOffs)
			{
				winLineNo = lineNo;
				winCharPos= editInfo.lineCharPos;
			}
		}

		if (editInfo.endOfText)
		{
			//Cursor is past end of line - move to char before end of line.
			if (ipCursorCharPos > editInfo.lineCharPos)
			{
				ipCursorCharPos = editInfo.lineCharPos;
				opCursorCharPos = editInfo.lineCharPos;
			}
		}
		
		if (editInfo.lineCharPos == ipCursorCharPos)
		{	//found the cursor position - either 
			//		the new pos if dy=0 or 
			//		the old pos if we have moved up/down a line.
			updateCursorPos(e, &editInfo);
			editInfo.lineXpos  = editInfo.txtWidth;
			cursorLineNo   = lineNo;
		}
		else if ((editInfo.lineCharPos > ipCursorCharPos) &&
		  		 (lineNo      > cursorLineNo      ) &&
				 (lineNo      > cursorLineNo + dy))
		{
			//we have moved far enough down to store all required information
			editComplete   = TRUE;
		}
		editInfo.txtWidth = editInfo.txtWidth + editInfo.charWidth;
		editInfo.lineCharPos++;
	}	//end while
	
	//We now know either (a) the line the cursor is on and the char offset of the cursor or (b) the
	//original line the cursor was on and the x-pixel position of the cursor (for dy != 0)  
	
	if (dy)
	{	//update line with the cursor on it
		if (cursorLineNo+dy >lineNo )
			cursorLineNo = lineNo; //last line of editor.
		else if (cursorLineNo+dy < 0)
			cursorLineNo = 0;
		else
			cursorLineNo = cursorLineNo+dy;

		//Now we need to calculate cursor char pos. 'opCursorCharPos'

	}
	else
	{	
		//Cursor line no is already set up.

		//the new cursor position was passed into the procedure.
		opCursorCharPos = ipCursorCharPos;
	}

	editInfo.lineCharPos = 0;
	lineNo    = 0;
	editInfo.txtWidth  = 0;
	editComplete = FALSE;
	editInfo.endOfText = FALSE;
	editInfo.space.lineCharPos = 0;

	//Update start of windows position
	if (cursorLineNo < winLineNo || !(e->attr->mode & edtCurMask)) 
	{//cursor is on a line before current window screen - search from the start
	// sbh - or we're in read-only mode, no cursor, scroll with every up/down press
		winLineNo = cursorLineNo;
		winCharPos = 0;
	}
	else if (cursorLineNo >= winLineNo+scrSyLines) 
	{	//cursor is below the bottom of the screen
		winLineNo = cursorLineNo-(scrSyLines-1);
		winCharPos = 0;
	}
	else if (dy != 0)
	{	//windows line no is unchanged - start search at win char pos.
		editInfo.lineCharPos = winCharPos;
		lineNo = winLineNo;
	}
	else
	{	//we do not need to calculate new window position - it is unchanged.
		//and we have already calculated the new cursor position.
		editComplete = TRUE;
	}

	//Calculate last char on cursor line and winCharPos
	if (!editComplete)
	{
		while( (!editInfo.endOfText) && (!editComplete) )
		{
			if (textStrType == DSPL_TYPE_UNICODE)
			{
				charUnicode = textStartUnicode[editInfo.lineCharPos];
				getTotalWidth(charUnicode,scrSxPixels,&editInfo);
			}
			else
			{
				charUnicode = (textStartAscii[editInfo.lineCharPos] << 8) & 0xFF00;
				getTotalWidth(charUnicode,scrSxPixels,&editInfo);
			}
			if (editInfo.endOfLine)
			{	//newline
				editInfo.txtWidth = 0;
				//update start of window.
				linePos = editInfo.lineCharPos;

				//Remember char before first char on next line.
				if (lineNo == cursorLineNo)
				{
					if (ipCursorCharPos >=  editInfo.lineCharPos) 
						ipCursorCharPos = editInfo.lineCharPos-1;
				}
				lineNo++;
				if (winLineNo == lineNo)
					winCharPos = editInfo.lineCharPos;
			}
			if (dy!=0)
			{	//line number has changed
				//Once we have found the correct line, look for the char at the same x-pixel pos
				//as before (or the last char before we pass the position).
				if (lineNo == cursorLineNo)
				{	
					if (editInfo.txtWidth <= editInfo.lineXpos)
					{	//Update cursor char pos...
						ipCursorCharPos = editInfo.lineCharPos;
					}
				}
			}
			else if (lineNo > cursorLineNo) //...or we start a new line
			{
				editComplete = TRUE;
			}
		
			editInfo.txtWidth = editInfo.txtWidth + editInfo.charWidth;
			editInfo.lineCharPos++;
		}	//end while

		editComplete = FALSE;
	}
	
	editInfo.lineCharPos = winCharPos;
	lineNo    = winLineNo;
	editInfo.txtWidth  = 0;
	editInfo.endOfText = FALSE;
	editInfo.space.lineCharPos = 0;

	//Calculate where the window is to start from
	while( (!editInfo.endOfText) && (!editComplete) )
	{
		if (textStrType == DSPL_TYPE_UNICODE)
		{
			charUnicode = textStartUnicode[editInfo.lineCharPos];
			getTotalWidth(charUnicode,scrSxPixels,&editInfo);
		}
		else
		{
			charUnicode = (textStartAscii[editInfo.lineCharPos] << 8) & 0xFF00;
			getTotalWidth(charUnicode,scrSxPixels,&editInfo);
		}
		if (editInfo.endOfLine)
		{	//newline
			editInfo.txtWidth = 0;
			//update start of window.
			linePos = editInfo.lineCharPos;
			lineNo++;
		}

		if ((lineNo == cursorLineNo) &&
			(ipCursorCharPos == editInfo.lineCharPos))
		{	//we have reached desired char.
			opCursorCharPos = editInfo.lineCharPos;
			updateCursorPos(e, &editInfo);
			cursorLineNo   = lineNo;
			editComplete = TRUE;
		}
	
		editInfo.txtWidth = editInfo.txtWidth + editInfo.charWidth;
		editInfo.lineCharPos++;
	}	//end while

	//Calculate y position of cursor
	//GW 17/09/01 Place cursor for windows that have blank lines at the top of the screen
	e->curCY = (cursorLineNo - winLineNo)*e->fontHeight+e->attr->win.py; 

	//Output updated window start position
	e->curOffs = winCharPos;
	e->cp = opCursorCharPos;

    return (MfwResOk);
}








