/******************************************************************************/
/* Tedit.CPP: IMPLEMENTATION OF THE CTedit CLASS                              */
/*                                                                            */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/* Methods in this file                                                       */
/*                                                                            */
/*  Edit Control Object                                                       */
/*      CAttrEdit::OnPaint                                                   */
/*      CAttrEdit::OnEraseBkgnd                                               */
/*      CAttrEdit::OnRButtonDown                                              */
/*      CAttrEdit::OnChar                                                     */
/*      CAttrEdit::OnMouseMove                                                */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/*  Text Edit Control Parent Window (Parent of Edit Control)                  */
/*      CTedit::CTedit                                                        */
/*      CTedit::CTedit                                                        */
/*      CTedit::~CTedit                                                       */
/*                                                                            */
/*  Miscellaneous Methods                                                     */
/*      CTedit::RefreshWindow                                                 */
/*      CTedit::SetTextColor                                                  */
/*      CTedit::SetBackColor                                                  */
/*      CTedit::SetTransparentMode                                            */
/*      CTedit::Undo                                                          */
/*      CTedit::ShowFontPalette                                               */
/*      CTedit::IsFontPaletteVisible                                          */
/*      CTedit::GetBitmap                                                     */
/*      CTedit::PostNcDestroy                                                 */
/*      CTedit::GetDefaultMinSize                                             */
/*                                                                            */
/*  Edit Control Notification and processing methods                          */
/*      CTedit::OnAttrEditEnChange                                            */
/*      CTedit::OnAttrEditFontChange                                          */
/*                                                                            */
/*  Control Notification/Window Messages                                      */
/*      CTedit::OnEraseBkgnd                                                  */
/*      CTedit::OnSize                                                        */
/*      CTedit::OnMove                                                        */
/*      CTedit::OnCtlColor                                                    */
/*      CTedit::OnNcCalcSize                                                  */
/*      CTedit::OnNcPaint                                                     */
/*      CTedit::OnNcHitTest                                                   */
/*      CTedit::OnRButtonDown                                                 */
/*                                                                            */
/*  Popup Menu Control Notification/Window Messages                           */
/*      CTedit::OnTextPlain                                                   */
/*      CTedit::OnTextBold                                                    */
/*      CTedit::OnTextItalic                                                  */
/*      CTedit::OnTextUnderline                                               */
/*      CTedit::OnTextSelectfont                                              */
/*      CTedit::OnTextSelectpointsize                                         */
/*      CTedit::OnEditCut                                                     */
/*      CTedit::OnEditCopy                                                    */
/*      CTedit::OnEditPaste                                                   */
/*      CTedit::OnTextDelete                                                  */
/*      CTedit::OnTextSelectall                                               */
/*      CTedit::OnTextPlace                                                   */
/*      CTedit::OnTextTexttool                                                */
/*                                                                            */
/*      CTedit::OnUpdateTextPlain                                             */
/*      CTedit::OnUpdateTextBold                                              */
/*      CTedit::OnUpdateTextItalic                                            */
/*      CTedit::OnUpdateTextUnderline                                         */
/*      CTedit::OnUpdateTextTexttool                                          */
/*                                                                            */
/******************************************************************************/

// TEDIT.CPP: IMPLEMENTATION OF THE CTEDIT CLASS
//
#include "stdafx.h"
#include "global.h"
#include "pbrush.h"
#include "pbrusvw.h"
#include "pbrusfrm.h"
#include "imgwnd.h"
#include "pictures.h"
#include "minifwnd.h"
#include "tfont.h"
#include "tedit.h"
#include "tracker.h"

#include <imm.h>

#include "imgsuprt.h"

#ifndef WM_SYSTIMER
#define WM_SYSTIMER     0x118
#endif //WM_SYSTIMER


#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE( CAttrEdit, CEdit )
IMPLEMENT_DYNCREATE( CTedit, CWnd )

#include "memtrace.h"




/******************************************************************************/
// CAttrEdit

BEGIN_MESSAGE_MAP( CAttrEdit, CEdit )
    //{{AFX_MSG_MAP(CAttrEdit)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    ON_WM_RBUTTONDOWN()
    ON_WM_CHAR()

    ON_MESSAGE(WM_IME_CHAR, OnImeChar)
    ON_MESSAGE(WM_IME_COMPOSITION, OnImeComposition)
    ON_MESSAGE(WM_INPUTLANGCHANGE, OnInputLangChange)
    ON_WM_KILLFOCUS()


    ON_WM_NCHITTEST()
    ON_WM_SETFOCUS()
    ON_WM_SIZE()
    ON_WM_LBUTTONDBLCLK()
    ON_WM_LBUTTONDOWN()
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONUP()
    ON_WM_KEYDOWN()
    ON_MESSAGE(WM_SYSTIMER, OnSysTimer)

        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

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

CAttrEdit::CAttrEdit()
    {
    m_bBackgroundTransparent = TRUE;
    m_pParentWnd             = NULL;
    m_uiLastChar[0] = 32;
    m_uiLastChar[1] = 32;

    m_rectUpdate.SetRectEmpty();


    m_strResult.Empty();
    m_bMouseDown = FALSE;
    m_hHCursor = theApp.LoadStandardCursor( IDC_IBEAM );
    m_hVCursor = theApp.LoadCursor( IDCUR_HIBEAM );
    m_hOldCursor = NULL;
    m_rectFmt.SetRectEmpty();
    m_iPrevStart = -1;
    m_bResizeOnly = FALSE;

    }

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

void CAttrEdit::OnPaint()
    {
    GetUpdateRect( &m_rectUpdate );


    if ( !m_pParentWnd->m_bVertEdit )
        {
        Default();
        return;
        }
    else
        {
        CFont*      pFont;
        CFont*      pOldFont = NULL;
        CPalette*   ppalOld = NULL;
        int         OldBkMode;
        COLORREF    OldTxtColor;
        CRect       rc = m_rectFmt;
        int         cnt = 0;
        int         i = 0, h = 0;
        int         nLen;
        CString     cStr;
        LPTSTR      lpStr;
        int         nStart, nEnd;
        CDC*        pDC = NULL;
        PAINTSTRUCT ps;

        const MSG *pCurrentMessage = GetCurrentMessage();
        //wParam is DC
        if ( pCurrentMessage->wParam )
            {
            HDC     hDC = (HDC) pCurrentMessage->wParam;
            pDC = CDC::FromHandle( hDC );
            }
        else
            pDC = BeginPaint( &ps );

        if (pDC == NULL || pDC->m_hDC == NULL)
            {
            theApp.SetGdiEmergency();
            return;
            }

        OldBkMode = pDC->GetBkMode();
        OldTxtColor = pDC->GetTextColor();
        ppalOld = PBSelectPalette(pDC, theApp.m_pPalette, FALSE);

        m_pParentWnd->SendMessage( WM_CTLCOLOREDIT, (WPARAM)pDC->m_hDC,
                                   (LPARAM) m_hWnd );

        pFont = GetFont();
        pOldFont = pDC->SelectObject( pFont );

        h = m_pParentWnd->m_iLineHeight;

        cnt = GetLineCount();

        GetSel( nStart, nEnd );
        if ( nStart == nEnd )
            {
            for ( i = 0; i < cnt; i++ )
                {
                nLen = LineLength( LineIndex( i ) );
                lpStr = cStr.GetBufferSetLength( nLen );
                GetLine( i, lpStr, nLen );
                TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0,
                            (LPTSTR)lpStr, nLen, FALSE );
                }
            }
        else
            {
            int nStartLn, nEndLn;
            int nMaxText = GetWindowTextLength();
            int nChar = 0;

            nStartLn = LineFromChar( nStart );
            nEndLn   = LineFromChar( nEnd );

            //Before Start
            for ( i = 0; i < nStartLn; i++ )
                {
                nLen = LineLength( LineIndex( i ) );
                lpStr = cStr.GetBufferSetLength( nLen );
                GetLine( i, lpStr, nLen );
                TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0,
                            (LPTSTR)lpStr, nLen, FALSE );
                nChar = LineIndex( i + 1 );
                }
            nLen = LineLength( LineIndex( i ) );
            lpStr = cStr.GetBufferSetLength( nLen );
            GetLine( i, lpStr, nLen );
            TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0,
                        (LPTSTR)lpStr, nStart - nChar, FALSE );

            //Selected Text
            COLORREF bkColor  = pDC->SetBkColor( GetSysColor(COLOR_HIGHLIGHT) );
            COLORREF txtColor = pDC->SetTextColor( GetSysColor(COLOR_HIGHLIGHTTEXT) );
            int      bkMode   = pDC->SetBkMode( OPAQUE );

            CPoint ptStart( (DWORD)SendMessage( EM_POSFROMCHAR, nStart ) );
            if ( nStartLn == nEndLn )
                {
                TabTextOut( pDC, nStart, rc.right - h * i, ptStart.x,
                            (LPTSTR)lpStr + (nStart - nChar), nEnd - nStart, TRUE );
                }
            else
                {
                TabTextOut( pDC, nStart, rc.right - h * i, ptStart.x,
                            (LPTSTR)lpStr + (nStart - nChar), nLen + nChar - nStart, TRUE );
                nChar = LineIndex( i + 1 );

                for ( i++; i < nEndLn; i++ )
                    {
                    nLen = LineLength( LineIndex( i ) );
                    lpStr = cStr.GetBufferSetLength( nLen );
                    GetLine( i, lpStr, nLen );
                    TabTextOut( pDC, nChar, rc.right - h * i, 0,
                                (LPTSTR)lpStr, nLen, TRUE );
                    nChar = LineIndex( i + 1 );
                    }

                nLen = LineLength( LineIndex( i ) );
                lpStr = cStr.GetBufferSetLength( nLen );
                GetLine( i, lpStr, nLen );
                TabTextOut( pDC, nChar, rc.right - h * i, 0,
                            (LPTSTR)lpStr, nEnd - nChar, TRUE );
                }

            pDC->SetBkColor( bkColor );
            pDC->SetTextColor( txtColor );
            pDC->SetBkMode( bkMode );

            //After End
            if ( nEnd < nMaxText )
                {
                CPoint ptEnd( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) );
                TabTextOut( pDC, nEnd, rc.right - h * i, ptEnd.x,
                            (LPTSTR)lpStr + (nEnd - nChar), nChar + nLen - nEnd, FALSE );
                for ( i++; i < cnt; i++ )
                    {
                    nLen = LineLength( LineIndex( i ) );
                    lpStr = cStr.GetBufferSetLength( nLen );
                    GetLine( i, lpStr, nLen );
                    TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0,
                                (LPTSTR)lpStr, nLen, FALSE );
                    }
                }
            }

        cStr.Empty();

        if (pOldFont)   pDC->SelectObject( pOldFont );
        if (ppalOld)    pDC->SelectPalette( ppalOld, FALSE );
        pDC->SetBkMode( OldBkMode );
        pDC->SetTextColor( OldTxtColor );

        if ( !pCurrentMessage->wParam )
            EndPaint( &ps );
        }
    }

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

BOOL CAttrEdit::OnEraseBkgnd( CDC* pDC )
    {
    if (m_pParentWnd == NULL)
        return CEdit::OnEraseBkgnd( pDC );

    ASSERT( m_pParentWnd->m_pImgWnd->m_pImg      != NULL );
    ASSERT( m_pParentWnd->m_pImgWnd->m_pImg->hDC != NULL );

    CPalette* ppalOld = NULL;

    if (m_rectUpdate.IsRectEmpty())
        {
        if (! GetUpdateRect( &m_rectUpdate, FALSE ))
            GetClientRect( &m_rectUpdate );

        ValidateRect( &m_rectUpdate );
        }
    CRect destRect = m_rectUpdate;

    ClientToScreen( &m_rectUpdate );

    m_pParentWnd->m_pImgWnd->ScreenToClient( &m_rectUpdate );

    ppalOld = PBSelectPalette(pDC, theApp.m_pPalette, FALSE);

    if (m_bBackgroundTransparent)
        m_pParentWnd->m_pImgWnd->DrawImage( pDC, &m_rectUpdate, &destRect );
    else
        pDC->FillRect( &destRect, &m_pParentWnd->m_hbrBkColor );

    if (ppalOld)
        pDC->SelectPalette( ppalOld, FALSE );

    m_rectUpdate.SetRectEmpty();

    return TRUE;
    }

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

void CAttrEdit::OnRButtonDown(UINT nFlags, CPoint point)
    {
    const MSG *pCurrentMessage = GetCurrentMessage();

    m_pParentWnd->SendMessage( pCurrentMessage->message,
                               pCurrentMessage->wParam,
                               pCurrentMessage->lParam);
    }

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

void CAttrEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{

    m_uiLastChar[0] = m_uiLastChar[1];

#ifndef UNICODE
    //
    // For DBCS we have to peek for the trail byte if the current
    // byte is a lead byte
    //
    if (IsDBCSLeadByte((BYTE)nChar))
    {
       MSG msg;
       ZeroMemory (&msg, sizeof(msg));
       ::PeekMessage (&msg, m_hWnd, WM_CHAR, WM_CHAR, PM_NOREMOVE);
       m_uiLastChar[1] = (UINT)MAKEWORD((BYTE)msg.wParam, (BYTE)nChar);
    }
    else
#endif // UNICODE
       m_uiLastChar[1] = nChar;


    if ( m_pParentWnd->m_bVertEdit )
       {
       SetCaretPosition( TRUE, NULL, -1 );
       UpdateInput();
       HideCaret();
       }

    CEdit::OnChar( nChar, nRepCnt, nFlags );

    if ( m_pParentWnd->m_bVertEdit )
       {
       SetCaretShape();
       UpdateInput();
       ShowCaret();
       }


    BOOL bRefresh = FALSE;

    switch (nChar)
        {
        case VK_BACK:
        case VK_DELETE:
        case VK_INSERT:
            bRefresh = TRUE;

            break;
        }

    if (bRefresh)
        m_pParentWnd->RefreshWindow(); /* enhance to do only the character involved */


     //
     // The edit control may have to resize
     //
     m_bResizeOnly = TRUE;
     m_pParentWnd->OnEnMaxText ();
     m_bResizeOnly = FALSE;

}


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

LRESULT CAttrEdit::OnInputLangChange( WPARAM wParam, LPARAM lParam )
{
    LRESULT lRet = Default();

    if ( m_pParentWnd->m_bVertEdit )
    {
        SetCaretPosition( TRUE, NULL, -1 );
    }
    return lRet;
}

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

LRESULT CAttrEdit::OnImeChar( WPARAM wParam, LPARAM lParam )
    {



        if ( m_pParentWnd->m_bVertEdit )
            {
            SetCaretPosition( TRUE, NULL, -1 );
            UpdateInput();
            HideCaret();
            }


            return Default();

    }

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

LRESULT CAttrEdit::OnImeComposition( WPARAM wParam, LPARAM lParam )
    {
    // Use Faster Way undr Japanese Keyboard Layout (Japanese IME)
    // Japanese IME may generate lots of chars at one time.
    // This way is better than waiting WM_CHAR.

    DWORD dwKeyboardLayout = PRIMARYLANGID(LOWORD(GetKeyboardLayout(0)));

    if ( dwKeyboardLayout == LANG_JAPANESE)
        {
        if (lParam & GCS_RESULTSTR)
            {
            HIMC hIMC = ImmGetContext(m_hWnd);

            DWORD dwSize;
            if (hIMC &&
                (dwSize = ImmGetCompositionString(hIMC,GCS_RESULTSTR,NULL,0L)))
                {
                    // ImmGetCompositionString returns the buffer size, IN BYTES.
                    // even if Unicode version.
                    LPTSTR lp = m_strResult.GetBufferSetLength(dwSize);
                    ImmGetCompositionString(hIMC,GCS_RESULTSTR,lp,dwSize+sizeof(TCHAR));
                    *(lp + dwSize/sizeof(TCHAR)) = TEXT('\0');
                    ReplaceSel(lp);
                    m_strResult.Empty();
                }

            ImmReleaseContext(m_hWnd, hIMC);

            lParam &= ~( GCS_RESULTREADSTR | GCS_RESULTREADCLAUSE | GCS_RESULTSTR | GCS_RESULTCLAUSE);
            if (lParam)
                DefWindowProc(WM_IME_COMPOSITION,wParam,lParam);

            // We'are not sure, how IME hide its composiiton window.
            m_pParentWnd->RefreshWindow();
            return 0;
            }
        }
    else if ( dwKeyboardLayout == LANG_KOREAN)
        {
        if ( m_pParentWnd->m_bVertEdit ) {

           Default();

           SetCaretPosition( FALSE, NULL, -2);

           // We should update current composition string.
           UpdateInput();
           return 0;
        }
        else {
           // We should update current composition string.
           UpdateInput();
               return Default();
        }
    }

    return Default();
    }

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

void CAttrEdit::OnKillFocus(CWnd* pNewWnd)
    {
    HIMC hIMC = ImmGetContext(m_hWnd);
    ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0L);
    ImmReleaseContext(m_hWnd, hIMC);

    CEdit::OnKillFocus(pNewWnd);


        if ( m_pParentWnd->m_bVertEdit )
                {
                SetFmtRect();
                Repaint();
                }


    }



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

UINT CAttrEdit::OnNcHitTest( CPoint point )
    {
    const MSG *pCurrentMessage = GetCurrentMessage();
    UINT  uiHitTestCode = (UINT)DefWindowProc( pCurrentMessage->message,
                   pCurrentMessage->wParam,
                   pCurrentMessage->lParam);

        if ( (uiHitTestCode == HTCLIENT) )
                {
                if ( (m_pParentWnd->m_bVertEdit) )  SetVCursorShape();
                else                                SetHCursorShape();
                }

    return uiHitTestCode;
    }

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

void CAttrEdit::OnSetFocus( CWnd* pOldWnd )
    {
        Default();

        if ( m_pParentWnd->m_bVertEdit )
                {
                SetCaretShape();
                SetCaretPosition( FALSE, NULL, -1 );
                Repaint();
                }
    }

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

void CAttrEdit::OnSize( UINT nType, int cx, int cy )
    {
        Default();

        m_rectFmt.left = m_rectFmt.top = 0;
        m_rectFmt.right  = cx;
        m_rectFmt.bottom = cy;

        SetFmtRect();
    }


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

void CAttrEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                Default();
                return;
                }

        HideCaret();
        UpdateSel();
        SetStartSelect();

        int     tt = point.y;
        point.y = m_rectFmt.right - point.x;
        point.x = tt;

    const MSG *pCurrentMessage = GetCurrentMessage();
        DefWindowProc( pCurrentMessage->message,
                   pCurrentMessage->wParam,
                   MAKELPARAM( point.x, point.y ));

        SetCaretPosition( TRUE, &point, -1 );
        ShowCaret();
        UpdateSel();
        UpdateWindow();
    }

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

void CAttrEdit::OnLButtonDown(UINT nFlags, CPoint point)
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                Default();
                return;
                }

        HideCaret();
        UpdateSel();
        SetStartSelect();

        int     iPrevEnd;
        GetSel( m_iPrevStart, iPrevEnd );

        int     tt = point.y;
        point.y = m_rectFmt.right - point.x;
        point.x = tt;

        //reset caret position to get correct caret position
        CPoint  pt( -20000, -20000 );
        SetCaretPos( pt );

    const MSG *pCurrentMessage = GetCurrentMessage();
        DefWindowProc( pCurrentMessage->message,
                   pCurrentMessage->wParam,
                   MAKELPARAM( point.x, point.y ));

        SetCaretPosition( TRUE, &point, m_iPrevStart );
        if ( GetKeyState(VK_SHIFT) >= 0 )       //not extend selection
                        GetSel( m_iPrevStart, iPrevEnd );
        ShowCaret();
        UpdateSel();
        UpdateWindow();

        m_bMouseDown = TRUE;

    }

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

void CAttrEdit::OnLButtonUp(UINT nFlags, CPoint point)
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                Default();
                return;
                }

        m_bMouseDown = FALSE;

        HideCaret();
        UpdateSel();
        SetStartSelect();

        int     tt = point.y;
        point.y = m_rectFmt.right - point.x;
        point.x = tt;

    const MSG *pCurrentMessage = GetCurrentMessage();
        DefWindowProc( pCurrentMessage->message,
                   pCurrentMessage->wParam,
                   MAKELPARAM( point.x, point.y ));

        SetCaretPosition( TRUE, &point, m_iPrevStart );
        ShowCaret();
        UpdateSel();
        UpdateWindow();
    }


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

void CAttrEdit::OnMouseMove(UINT nFlags, CPoint point)
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                Default();
                return;
                }

        if ( m_bMouseDown )
                {
                HideCaret();
                UpdateSel();
                SetStartSelect();

                int     tt = point.y;
                point.y = m_rectFmt.right - point.x;
                point.x = tt;

        const MSG *pCurrentMessage = GetCurrentMessage();
                DefWindowProc( pCurrentMessage->message,
                           pCurrentMessage->wParam,
                       MAKELPARAM( point.x, point.y ));

                SetCaretPosition( TRUE, &point, m_iPrevStart );
                ShowCaret();
                UpdateSel();
                UpdateWindow();
                }
        else    CEdit::OnMouseMove( nFlags, point );

    }

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

void CAttrEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
                return;
                }

        BOOL    bPrev = FALSE;

        HideCaret();

    switch (nChar)
        {
        case VK_LEFT:
                case VK_RIGHT:
                case VK_UP:
                case VK_DOWN:
                case VK_HOME:
        case VK_END:
                        {
                        UpdateSel();

                        CPoint ptCaretPos = GetCaretPos();
                        if ( ptCaretPos.y != 0 ) bPrev = TRUE;

                        int     iPrevEnd;
                        GetSel( m_iPrevStart, iPrevEnd );

                        SetStartSelect();       //for VK_RETURN

                        //reset caret position to get correct caret position
                        CPoint  pt( -20000, -20000 );
                        SetCaretPos( pt );

                        break;
                        }
        }

    switch (nChar)
        {
        case VK_LEFT:   nChar = VK_DOWN;                                        break;
                case VK_RIGHT:  nChar = VK_UP;                                          break;
                case VK_UP:             nChar = VK_LEFT;        bPrev = FALSE;  break;
                case VK_DOWN:   nChar = VK_RIGHT;       bPrev = FALSE;  break;
                case VK_HOME:                                           bPrev = FALSE;  break;
        case VK_END:                                            bPrev = TRUE;   break;
        }

    const MSG *pCurrentMessage = GetCurrentMessage();
    DefWindowProc( pCurrentMessage->message,
                   nChar,
                   pCurrentMessage->lParam);

    switch (nChar)
        {
        case VK_LEFT:
                case VK_RIGHT:
                case VK_UP:
                case VK_DOWN:
                case VK_HOME:
        case VK_END:
                        {
                        SetCaretPosition( bPrev, NULL, m_iPrevStart );
                        UpdateSel();
                        UpdateWindow();
                        break;
                        }
        case VK_HANJA:
                // For Korea hanja conversion.
                SetCaretPosition( FALSE, NULL, -2);
                break;

                }

        ShowCaret();
}

/******************************************************************************/
void            CAttrEdit::SetStartSelect( void )
        {
        int     nStart, nEnd;

        CPoint ptCaretPos = GetCaretPos();

        if ( ptCaretPos.y == 0 )
                {
                GetSel( nStart, nEnd );
                if ( nStart == nEnd )   SetSel( nStart, nEnd );
                }
        }

/******************************************************************************/
void CAttrEdit::SetCaretPosition( BOOL bPrev, CPoint* ptMouse, int iPrevStart )
        {

        HideCaret();

        // Get Caret Position
        CPoint  ptCaretPos;

        // Get End Selected Position to be Caret Position
        int     nStart, nEnd;

        GetSel( nStart, nEnd );

        if ( iPrevStart != -1 && nStart < iPrevStart )
            nEnd = nStart;
#ifdef UNICODE
        // When NT bug 116057 is fixed, remove this code


        // For composition string support
        if ( m_pParentWnd->m_bVertEdit && iPrevStart == -2)
            nEnd -= 1 * sizeof(WCHAR)/sizeof(TCHAR);
#endif //UNICODE
        CPoint ptPos( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) );

        if ( nEnd >= GetWindowTextLength() ||
             ( ptPos.x == 0 && (bPrev) && (ptMouse == NULL ||
                                           ptMouse->y < ptPos.y ) ) )
            {
            CString cStr;
            CDC*    pDC = GetDC();
            CFont*  pFont = GetFont();
            CFont*  pOldFont;
            int     nLine = ( (ptPos.x < 0) ? GetLineCount() : LineFromChar( nEnd ) ) - 1;
            int     nChar = LineIndex( nLine );
            int     nLen = LineLength( nChar );
            LPTSTR  lpStr = cStr.GetBufferSetLength( nLen );
            TEXTMETRIC tm;

            pOldFont = pDC->SelectObject( pFont );
            GetLine( nLine, lpStr, nLen );

            pDC->GetTextMetrics( &tm );

            if ( !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH) )
                m_iTabPos = tm.tmAveCharWidth;
            else
                {
                CPoint  len( pDC->GetTextExtent( TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52) );
                m_iTabPos = (len.x / 26 + 1) / 2;
                if ( m_iTabPos <= 0 )   m_iTabPos = tm.tmAveCharWidth;
                }

            m_iTabPos *= 8;
            if ( m_iTabPos <= 0 )   m_iTabPos = 1;

            CPoint  tt( 0, 0 );
            if ( nLen > 0 )
                {
                if ( *(lpStr + nLen - 1) == TEXT('\t') )
                    {
                    tt = (CPoint) (DWORD)SendMessage( EM_POSFROMCHAR, nChar + nLen - 1 );
                    tt.x = min( (tt.x / m_iTabPos + 1) * m_iTabPos, m_rectFmt.bottom - 1 );
                    }
                else
                    {
                    LPTSTR  lpChar = lpStr + nLen - 1;
                    int     nCnt;

                    for ( nCnt = 0; nCnt < nLen && *lpChar != TEXT('\t'); nCnt++, lpChar-- );
                    lpChar++;
                    tt = (CPoint) (DWORD)SendMessage( EM_POSFROMCHAR, nChar + nLen - nCnt );
                    tt.Offset( pDC->GetTextExtent( lpChar, nCnt ) );
                    }
                }
            cStr.Empty();
            ptCaretPos.x = tt.x;
            ptCaretPos.y = m_pParentWnd->m_iLineHeight * nLine;
            pDC->SelectObject( pOldFont );

            ReleaseDC( pDC );
            }
        else
            {
            ptCaretPos.x = ptPos.x;
            ptCaretPos.y = ptPos.y;
            }

        // H -> V
        CPoint  pt( m_rectFmt.right - ptCaretPos.y - m_pParentWnd->m_iLineHeight,
                    ptCaretPos.x );
        //
        // for some reason, typing spaces pushes the caret beyond the bottom of the rect.
        // Cover that case by forcing the caret to be at the bottom of the rect.
        //
        if (pt.y > m_rectFmt.bottom)
        {
           pt.y = m_rectFmt.bottom-2;
        }
        SetCaretPos( pt );

        //Set IME composition window position
        HIMC        himc;

        if (himc=ImmGetContext(m_hWnd))
            {
            COMPOSITIONFORM cf;
            RECT    rcClient;

            cf.dwStyle = CFS_RECT;
            cf.ptCurrentPos.x = m_rectFmt.right - ptCaretPos.y - 1;
            cf.ptCurrentPos.y = pt.y;
            GetClientRect( &rcClient );
            cf.rcArea = rcClient;

            ImmSetCompositionWindow(himc,&cf);
            ImmReleaseContext(m_hWnd, himc);
            }

#ifndef WINNT // don't call ImmSetCompositionWindow at this time.
        SetFmtRect();   //it should be called after set IME position
#endif

        ShowCaret();
        }

/******************************************************************************/
void            CAttrEdit::SetCaretShape( void )
        {
        HideCaret();
        ::DestroyCaret();
        ::CreateCaret( m_hWnd, NULL, m_pParentWnd->m_iLineHeight, 2 );
        ShowCaret();
        }

/******************************************************************************/
void            CAttrEdit::SetFmtRect()
        {
        RECT    rc;

        rc.left = rc.top = 0;
        if ( m_pParentWnd->m_bVertEdit )
                {
                rc.right  = m_rectFmt.bottom;
                rc.bottom = m_rectFmt.right;
                }
        else
                {
                rc.right  = m_rectFmt.right;
                rc.bottom = m_rectFmt.bottom;
                }
        
        HIMC            himc;
        COMPOSITIONFORM cf;
        BOOL            bResult = FALSE;

        if (himc=ImmGetContext(m_hWnd)) {
            bResult = ImmGetCompositionWindow(himc,&cf);
        }
        
        SetRectNP( &rc );
        
        if (himc && bResult) {
            ImmSetCompositionWindow(himc,&cf);
        }

        }

/******************************************************************************/
void CAttrEdit::Repaint(void)
    {
        InvalidateRect( NULL, TRUE );
        UpdateWindow();
        }

/******************************************************************************/
void CAttrEdit::UpdateSel(void)
    {
        int     nStart, nEnd;

        GetSel( nStart, nEnd );

        if (nStart != nEnd )
                {
                RECT    rc = m_rectFmt;

                if ( nStart > nEnd )
                        {
                        int     tt = nStart;
                        nStart = nEnd;
                        nEnd = tt;
                        }

                CPoint ptStart( (DWORD)SendMessage( EM_POSFROMCHAR, nStart ) );
                rc.right -= ptStart.y;

                if ( nEnd < GetWindowTextLength() )
                        {
                        CPoint ptEnd( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) );
                        rc.left = m_rectFmt.right - ptEnd.y  - m_pParentWnd->m_iLineHeight;
                        }

                InvalidateRect( &rc );
                }
        }

/******************************************************************************/
void CAttrEdit::UpdateInput(void)
    {
        RECT    rc = m_rectFmt;

        CPoint pt( GetCaretPos() );
        rc.right = pt.x + m_pParentWnd->m_iLineHeight;

        InvalidateRect( &rc );
        }

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

LRESULT CAttrEdit::OnSysTimer( WPARAM wParam, LPARAM lParam )
    {

        if ( !m_pParentWnd->m_bVertEdit )
                {
                Default();
                return 1L;
                }

    return 1L;
    }

/******************************************************************************/
void CAttrEdit::SetHCursorShape(void)
    {
        if ( GetSafeHwnd() )
                {
                ShowCursor( FALSE );
                SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_hHCursor );
                ShowCursor( TRUE );
                }
        }

/******************************************************************************/
void CAttrEdit::SetVCursorShape(void)
    {
        if ( GetSafeHwnd() )
                {
                ShowCursor( FALSE );
                SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_hVCursor );
                ShowCursor( TRUE );
                }
        }

/******************************************************************************/
void CAttrEdit::TabTextOut( CDC* pDC, int nCharIndex, int x, int y, LPCTSTR lpStr, int nCount, BOOL bSelect )
{
    int     i, nCnt;
    LPCTSTR lpChar = lpStr;
    CPoint  pt;
    CPoint  ptEnd;
    RECT    rc;
    BOOL    bReverse;

    CSize s1 = pDC->GetTextExtent( TEXT("a"), 1 );
    CSize s2 = pDC->GetTextExtent( TEXT("aa"), 2 );
    bReverse = (s1.cx == s2.cx);

    rc.left = x - m_pParentWnd->m_iLineHeight;
    rc.right = x;

    for ( i = 0, nCnt = 0; i < nCount; i++, nCnt++, lpStr++ )
    {
        if ( *lpStr == TEXT('\t') )
        {
            pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex );
            if ( nCnt > 0 )
            {
                pDC->TextOut( x, pt.x, lpChar, nCnt );
            }

            nCharIndex += nCnt + 1;
            nCnt = -1;
            lpChar = lpStr + 1;
            if ( bSelect )
            {
                pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex - 1 );
                rc.top = pt.x;

                if ( i < (nCount - 1) )
                {
                    pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex );
                    rc.bottom = pt.x;
                }
                else
                {
                    rc.bottom = min( (pt.x / m_iTabPos + 1) * m_iTabPos,
                                     m_rectFmt.bottom - 1 );
                }

                pDC->ExtTextOut( x, rc.top, 0 /*ETO_OPAQUE*/, &rc, NULL, 0, NULL );
            }
        }
    }

    if ( nCnt > 0 )
    {
        pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex );
        pDC->TextOut( x, pt.x, lpChar, nCnt );
    }
}


/******************************************************************************/
/******************************************************************************/
// CTedit

BEGIN_MESSAGE_MAP( CTedit, CWnd )
    //{{AFX_MSG_MAP(CTedit)
    ON_WM_SIZE()
    ON_WM_MOVE()
    ON_WM_CTLCOLOR()
    ON_WM_NCCALCSIZE()
    ON_WM_NCPAINT()
    ON_WM_NCHITTEST()
    ON_WM_RBUTTONDOWN()
    ON_COMMAND(ID_TEXT_PLAIN, OnTextPlain)
    ON_COMMAND(ID_TEXT_BOLD, OnTextBold)
    ON_COMMAND(ID_TEXT_ITALIC, OnTextItalic)
    ON_COMMAND(ID_TEXT_UNDERLINE, OnTextUnderline)
    ON_COMMAND(ID_TEXT_SELECTFONT, OnTextSelectfont)
    ON_COMMAND(ID_TEXT_SELECTPOINTSIZE, OnTextSelectpointsize)
    ON_COMMAND(ID_EDIT_CUT, OnEditCut)
    ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
    ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
    ON_COMMAND(ID_EDIT_CLEAR, OnTextDelete)
    ON_COMMAND(ID_EDIT_SELECT_ALL, OnTextSelectall)
    ON_COMMAND(ID_EDIT_UNDO, OnTextUndo)
    ON_COMMAND(ID_TEXT_PLACE, OnTextPlace)
    ON_COMMAND(ID_VIEW_TEXT_TOOLBAR, OnTextTexttool)
    ON_WM_LBUTTONDOWN()
        //}}AFX_MSG_MAP
    ON_WM_GETMINMAXINFO()
    ON_MESSAGE(WM_MOVING, OnMoving)
    ON_EN_CHANGE(IDC_ATTREDIT, OnAttrEditEnChange)
    ON_EN_MAXTEXT(IDC_ATTREDIT, OnEnMaxText)
    ON_EN_UPDATE(IDC_ATTREDIT, OnEnUpdate)

    ON_WM_DESTROY()

END_MESSAGE_MAP()

/******************************************************************************/
// CTedit construction/destruction

CTedit::CTedit()
    {
    m_eLastAction     = eNO_CHANGE;
    m_bCleanupBKBrush = FALSE;
    m_bStarting       = TRUE;
    m_bPasting        = FALSE;
    m_bExpand         = FALSE;
    m_bChanged        = FALSE;
    m_uiHitArea       = HTNOWHERE;
    m_crFGColor       = ::GetSysColor( COLOR_WINDOWTEXT );
    m_crBKColor       = ::GetSysColor( COLOR_WINDOW     );

    // Need to be initialized during first GETMINMAXINFO call
    m_SizeMinimum.cx = 1;
    m_SizeMinimum.cy = 1;

    m_bBackgroundTransparent = TRUE;

    m_cRectOldPos.SetRectEmpty();
    m_cRectWindow.SetRectEmpty();


    m_bVertEdit = FALSE;
    m_bAssocIMC = FALSE;
    m_hIMCEdit = NULL;
    m_hIMCFace = NULL;
    m_hIMCSize = NULL;
    m_hWndFace = NULL;
    m_hWndSize = NULL;

    }

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

CTedit::~CTedit()
    {
    if (m_bCleanupBKBrush)
        {
        m_hbrBkColor.DeleteObject();      //Set in SetTransparentMode
        m_bCleanupBKBrush = FALSE;
        }
    }

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

BOOL CTedit::Create( CImgWnd* pParentWnd,
                     COLORREF crefForeground,
                     COLORREF crefBackground,
                     CRect&   rectPos,
                     BOOL     bBackTransparent )
    {
    if (! m_bStarting)
        return FALSE;

    // Initialize member variables
    m_pImgWnd   = pParentWnd;
    m_crBKColor = crefBackground;
    m_crFGColor = crefForeground;
    m_bBackgroundTransparent = bBackTransparent; // Do this or else

    SetTransparentMode( bBackTransparent );

    CRect rectText = rectPos;

    rectText.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
    rectText.right  += CTracker::HANDLE_SIZE * 2;
    rectText.bottom += CTracker::HANDLE_SIZE * 2;

    if (! CWnd::Create( NULL, TEXT(""), WS_CHILD | WS_THICKFRAME, rectText, pParentWnd, IDC_ATTREDIT + 1 ))
        return FALSE;

    CRect rectEditArea;

    GetClientRect( &rectEditArea );

    m_cEdit.m_pParentWnd = this;

    if (! m_cEdit.Create( WS_CHILD | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN, rectEditArea, this, IDC_ATTREDIT ))
        {
        theApp.SetMemoryEmergency();

        DestroyWindow();
        return FALSE;
        }

    ClientToScreen( &rectEditArea ); // use this to let the font tool where not to cover

    m_pcTfont = new CTfont( this ); // this is the class Text Font Pallette
                                    // it is derived from cframewnd and will
    ASSERT( m_pcTfont != NULL );    // auto destruct when this window
                                    // 'CTedit' is Destroyed
    if (m_pcTfont == NULL || ! m_pcTfont->Create( rectEditArea ))
        {
        theApp.SetMemoryEmergency();

        DestroyWindow();

        m_pcTfont = NULL;
        return FALSE;
        }

    // reset the width and height to the minimum if nessesary
    CSize size = GetDefaultMinSize(); // must call after ctfont object created (it sets our font).
    m_cRectWindow = CRect( rectText.TopLeft(), size );
    SetWindowPos( &wndTop, 0, 0, size.cx, size.cy, SWP_NOACTIVATE | SWP_NOMOVE );

    ShowWindow( SW_SHOWNOACTIVATE );

    GetClientRect( &rectEditArea );

    m_cEdit.SetWindowPos( &wndTopMost, 0, 0, rectEditArea.Width(),
                                             rectEditArea.Height(), 0 );
    m_cEdit.ShowWindow( SW_SHOWNOACTIVATE );

    m_bStarting = FALSE;


        //get all control windows on ToolBar for controling IME
        CWnd* pcWndFace = m_pcTfont->GetFontFaceControl();
        if ( (pcWndFace != NULL) && (pcWndFace->GetSafeHwnd() != NULL) )
                        m_hWndFace = pcWndFace->m_hWnd; //static

        CWnd* pcWndSize = m_pcTfont->GetFontSizeControl();
        if ( (pcWndSize != NULL) && (
                  pcWndSize->GetSafeHwnd() != NULL) )
                {
                CWnd* pcWndEditSize = pcWndSize->GetWindow( GW_CHILD ); //edit
                if ( (pcWndEditSize != NULL) && (
                          pcWndEditSize->GetSafeHwnd() != NULL) )
                                m_hWndSize = pcWndEditSize->m_hWnd;     //edit
                }

        //save original Edit control
        if ( m_cEdit.GetSafeHwnd() )
                m_cEdit.m_hOldCursor = (HCURSOR) SetClassLongPtr( m_cEdit.m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_cEdit.m_hHCursor );


         //only DBCS font would enable IME
        CFont* pcFont = m_cEdit.GetFont();
        LOGFONT     lf;
        pcFont->GetObject( sizeof( LOGFONT ), &lf );
        if ( !IS_DBCS_CHARSET( lf.lfCharSet ) )
                {
                m_bAssocIMC = TRUE;
                if (!IsCUAS())
                    m_hIMCEdit = DisableIme( m_cEdit.m_hWnd );
                m_hIMCFace = DisableIme( m_hWndFace );
                m_hIMCSize = DisableIme( m_hWndSize );
                }


        //initial Caret Position
        if ( m_bVertEdit )
                {
                CPoint  pt( 0, 0 );
                m_cEdit.SetCaretPos( pt );
                m_cEdit.SetCaretPosition( FALSE, NULL, -1 );
                }

    m_cEdit.SetFocus();

    return TRUE;
    }

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

BOOL CTedit::PreCreateWindow( CREATESTRUCT& cs )
    {
    cs.dwExStyle |= WS_EX_TRANSPARENT;

    return CWnd::PreCreateWindow( cs );
    }

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

void CTedit::RefreshWindow( CRect* prect, BOOL bErase )
    {
    if (! m_bStarting)
        {
        UINT flags = RDW_INVALIDATE;

        if (bErase)
            flags |= RDW_ERASE;

        if ( m_bVertEdit )
            {
            m_cEdit.SetFmtRect();
            m_cEdit.Repaint();
            }

        else
            m_cEdit.RedrawWindow( prect, NULL, flags );
        }
    }

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

void CTedit::SetTextColor( COLORREF crColor )
    {
    m_crFGColor = crColor;
    RefreshWindow( NULL, FALSE );
    }

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

void CTedit::SetBackColor( COLORREF crColor )
    {
    m_crBKColor = crColor;

    if (! m_bBackgroundTransparent)
        {
        m_bBackgroundTransparent = TRUE; // just fake it out
        SetTransparentMode( FALSE ); // to setup the background brush when in opaque mode
        }
    }

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

void CTedit::SetTransparentMode( BOOL bTransparent )
    {
    BOOL bRefresh = ((! m_bBackgroundTransparent &&   bTransparent)
                  || (  m_bBackgroundTransparent && ! bTransparent));

    m_cEdit.m_bBackgroundTransparent = bTransparent;
            m_bBackgroundTransparent = bTransparent;

    if (m_bCleanupBKBrush)
        {
        m_hbrBkColor.DeleteObject();
        m_bCleanupBKBrush = FALSE;
        }

    if (! m_bBackgroundTransparent)
        {
        m_hbrBkColor.CreateSolidBrush( m_crBKColor );
        m_bCleanupBKBrush = TRUE;
        }

    if (bRefresh)
        {
        InvalidateRect( NULL );
        UpdateWindow();

        RefreshWindow();
        }
    }

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

void CTedit::Undo()
    {

    if ( m_bVertEdit )
        m_cEdit.HideCaret();

    switch(m_eLastAction)
        {
        case eEBOX_CHANGE:
            m_cEdit.Undo();
            break;

        case eFONT_CHANGE:
            ASSERT(m_pcTfont != NULL);

            if (m_pcTfont != NULL)
                {
                m_pcTfont->Undo();
                }
             break;

        case eSIZE_MOVE_CHANGE:
            if (! m_cRectOldPos.IsRectEmpty())
                MoveWindow( m_cRectOldPos );
             break;

        default:
             break;
        }


        if ( m_bVertEdit )
                {
                m_cEdit.SetCaretShape();
                m_cEdit.SetCaretPosition( TRUE, NULL, -1 );
                m_cEdit.ShowCaret();
                }

    }

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

void CTedit::ShowFontPalette(int nCmdShow)
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        theApp.m_bShowTextToolbar = ! theApp.m_bShowTextToolbar;

        m_pcTfont->ShowWindow(nCmdShow);
        }
    }

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

BOOL CTedit::IsFontPaletteVisible(void)
    {
    BOOL bWindowVisible = FALSE;

    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        bWindowVisible = m_pcTfont->IsWindowVisible();
        }

    return bWindowVisible;
    }

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

void CTedit::ShowFontToolbar(BOOL bActivate)
{
        // FEATURE: Remove ShowFontPalette after RTM

        if (m_pcTfont == NULL)
        {
                return;
        }

        m_pcTfont->ShowWindow(bActivate ? SW_SHOW : SW_SHOWNOACTIVATE);
}

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

void CTedit::HideFontToolbar(void)
{
        if (m_pcTfont == NULL)
        {
                return;
        }

        m_pcTfont->ShowWindow(SW_HIDE);
}

/******************************************************************************/
// Returns a Ptr to a discardable bitmap (CBitmap object) or NULL on error

void CTedit::GetBitmap( CDC* pDC, CRect* prectImg )
    {
    if (! m_bBackgroundTransparent)
        pDC->FillRect( prectImg, &m_hbrBkColor );

    m_cEdit.SetSel( -1, 0 );


    if ( m_bVertEdit )
        {
        m_cEdit.SetFmtRect();
        m_cEdit.UpdateWindow();
        }


    CPoint ptViewOrgOld = pDC->SetViewportOrg( prectImg->left, prectImg->top );

    m_cEdit.SendMessage( WM_PAINT, (WPARAM)(pDC->m_hDC) );

    pDC->SetViewportOrg( ptViewOrgOld );
    pDC->SelectClipRgn( NULL );
    }

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

void CTedit::PostNcDestroy()
    {

    // If m_pcTfont is destroyed by shutdown before CTedit,
    // m_pcTfont will be null
    if (m_pcTfont != NULL)
        {
        m_pcTfont->DestroyWindow();
        m_pcTfont = NULL;
        }

    delete this;
    }

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

CSize CTedit::GetDefaultMinSize( void )
    {
    CRect cRectClient;
    int   iWidth;
    int   iHeight;

    // edit control takes up the whole client area of the ctedit
    // object/window, so width of client of ctedit is same as widht of edit
    // control window.  Edit control window has no border.
    GetClientRect( &cRectClient );

    iWidth  = cRectClient.Width();
    iHeight = cRectClient.Height();

    CDC*   pDC    = m_cEdit.GetDC();
    CFont* pcFont = m_cEdit.GetFont();

    if (pDC    != NULL
    &&  pcFont != NULL)
        {
        TEXTMETRIC tm;
        CFont*     pcFontOld = NULL;

        pcFontOld = pDC->SelectObject( pcFont );

        pDC->GetTextMetrics( &tm );

        BOOL bUpdateSize = FALSE;

        m_SizeMinimum.cx = tm.tmAveCharWidth * MIN_CHARS_DISPLAY_SIZE + CTracker::HANDLE_SIZE * 2;
        m_SizeMinimum.cy = tm.tmHeight                                + CTracker::HANDLE_SIZE * 2;

        if (m_SizeMinimum.cx > iWidth) // must be able to at least display MIN_CHARS_DISPLAY_SIZE
            {
            iWidth      = m_SizeMinimum.cx;
            bUpdateSize = TRUE;
            }

        if (m_SizeMinimum.cy > iHeight) // must be able to at least 1 char high
            {
            iHeight     = m_SizeMinimum.cy;
            bUpdateSize = TRUE;
            }

        if (bUpdateSize)
            m_eLastAction = eNO_CHANGE; // don't want user to be able to undo this

        if (pcFontOld != NULL)
            {
            pDC->SelectObject( pcFontOld );
            }
        }
    if (pDC != NULL)
        m_cEdit.ReleaseDC( pDC );

    cRectClient.SetRect( 0, 0, iWidth - 1, iHeight - 1 );

    ClientToScreen( &cRectClient );
    m_pImgWnd->ScreenToClient( &cRectClient );

    CRect rectDrawing = m_pImgWnd->GetDrawingRect();

    if (cRectClient.right > rectDrawing.right)
        iWidth -= (cRectClient.right - rectDrawing.right) - CTracker::HANDLE_SIZE;

    if (cRectClient.bottom > rectDrawing.bottom)
        iHeight -= (cRectClient.bottom - rectDrawing.bottom) - CTracker::HANDLE_SIZE;

    m_SizeMinimum.cx = iWidth;
    m_SizeMinimum.cy = iHeight;

    return CSize( iWidth, iHeight );
    }

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

void CTedit::OnAttrEditEnChange(void)
    {
    m_eLastAction = eEBOX_CHANGE;

    if (m_bRefresh)
        m_cEdit.UpdateWindow();


        if ( m_bVertEdit )
                {
                m_cEdit.SetCaretPosition( TRUE, NULL, -1 );
                m_cEdit.UpdateWindow();
                }

    }

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

void CTedit::OnEnUpdate()
    {
    CPoint ptCaretPos = m_cEdit.GetCaretPos();
    CPoint ptLastChar( (DWORD)m_cEdit.SendMessage( EM_POSFROMCHAR,
                               (WPARAM)(m_cEdit.GetWindowTextLength() - 1) ) );
    CRect rect;
    m_cEdit.GetClientRect( &rect );
    rect.top    = ptCaretPos.y;
    rect.bottom = ptLastChar.y + m_iLineHeight;
    m_cEdit.InvalidateRect( &rect, TRUE );

    m_bChanged = TRUE;
    }

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

void CTedit::OnEnMaxText()
    {

    if (m_bPasting)
        {
        if (!m_cEdit.m_bResizeOnly)
        {
            AfxMessageBox( IDS_UNABLE_TO_PASTE, MB_OK | MB_ICONEXCLAMATION );
        }
        return;
        }

    CFont* pfntEdit = m_cEdit.GetFont();

    if (pfntEdit == NULL)
        return;

    CClientDC dc( &m_cEdit );

    CFont* pfntOld = dc.SelectObject( pfntEdit );

    TEXTMETRIC tm;

    dc.GetTextMetrics( &tm );

    CRect rectText;
    CRect rectImg;

    GetWindowRect( &rectText );

    m_pImgWnd->ScreenToClient( &rectText );

    POINT pt;
    ::GetCaretPos (&pt);
    //
    // If the next character would extend past the end of the
    // edit window, grow the window


    if (!m_bVertEdit && m_cEdit.m_bResizeOnly &&
       ((rectText.left + pt.x + 2*tm.tmMaxCharWidth < rectText.right)
       || (rectText.top + pt.y + 2*tm.tmHeight < rectText.bottom)) )
    {
       return;
    }
    else if (m_bVertEdit && m_cEdit.m_bResizeOnly &&
       ((pt.x - tm.tmMaxCharWidth > 0)
       || (rectText.top + pt.y + 2*tm.tmHeight < rectText.bottom)) )
    {
       return;
    }
    m_pImgWnd->GetClientRect ( &rectImg );


    if (m_cEdit.m_strResult.IsEmpty())
    {

                if (m_bVertEdit)
                        rectText.left -= tm.tmHeight;
                else
                rectText.bottom += tm.tmHeight;
    }
    else
    {
        CRect rectTmp = rectText;
        int nLen = m_cEdit.m_strResult.GetLength();


        if (m_bVertEdit)
           rectText.left -= dc.DrawText(m_cEdit.m_strResult.GetBuffer(nLen),
                                      nLen,&rectTmp,
                                      DT_CALCRECT | DT_LEFT | DT_WORDBREAK);
        else
           rectText.bottom += dc.DrawText(m_cEdit.m_strResult.GetBuffer(nLen),
                                      nLen,&rectTmp,
                                      DT_CALCRECT | DT_LEFT | DT_WORDBREAK);
    }

    CRect rectDrawing = m_pImgWnd->GetDrawingRect();

    if ( ((m_bVertEdit) && rectText.left>=rectDrawing.left && rectText.left >= rectImg.left) ||
         ((!m_bVertEdit) && rectText.bottom<=rectDrawing.bottom && rectText.bottom<=rectImg.bottom) )
    {
        MoveWindow( &rectText );
        m_cEdit.UpdateWindow();

        if ( m_bVertEdit )
            m_cEdit.UpdateInput();

        if (!m_cEdit.m_bResizeOnly)
        {
            if (m_cEdit.m_strResult.IsEmpty())
            {
                #ifdef UNICODE
                WCHAR ch[3];

                ch[0] = (WCHAR)m_cEdit.m_uiLastChar[0];
                ch[1] = L'\0';
                #else
                BYTE ch[3];
                //
                // Put lead and trail bytes in proper place for DBCS characters.
                //
                if (IsDBCSLeadByte (HIBYTE(LOWORD(m_cEdit.m_uiLastChar[0]))))
                {
                   ch[0] = HIBYTE(LOWORD(m_cEdit.m_uiLastChar[0]));
                   ch[1] = LOBYTE(LOWORD(m_cEdit.m_uiLastChar[0]));
                   ch[2] = '\0';
                }
                else
                {
                   ch[0] = LOBYTE(LOWORD(m_cEdit.m_uiLastChar[0]));
                   ch[1] = '\0';
                }
                #endif // UNICODE
                if (ch[0] == VK_RETURN)
                {
                    lstrcpy((LPTSTR)ch, TEXT("\r\n"));
                }

                m_cEdit.ReplaceSel((LPCTSTR) ch );
            }
             else
            {
                int nLen = m_cEdit.m_strResult.GetLength();

                m_cEdit.ReplaceSel( m_cEdit.m_strResult.GetBuffer(nLen));
            }
        }
    }

    if (pfntOld)
        dc.SelectObject( pfntOld );
    }

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

void CTedit::OnAttrEditFontChange(void)
    {
    CClientDC editDC( &m_cEdit );
    CFont* pcFont = m_cEdit.GetFont();
    if (!pcFont)
    {
        return; // this happens when you "escape" from the font
                //  selection listbox
    }
    CFont* pFontOld = editDC.SelectObject( pcFont);

    TEXTMETRIC tm;

    editDC.GetTextMetrics( &tm );

    m_iLineHeight = tm.tmHeight;


    #ifdef _DEBUG
    TRACE1( "New font line height %d.\n", m_iLineHeight );
    #endif


        //only DBCS associated font would enable IME
        if ( !m_bStarting )
                {

                LOGFONT     lf;

                pcFont->GetObject( sizeof( LOGFONT ), &lf );
                if ( IS_DBCS_CHARSET( lf.lfCharSet ) )

                        {

                        if (m_bAssocIMC)
                                {

                                m_bAssocIMC = FALSE;
                                if (!IsCUAS())
                                    {
                                    EnableIme( m_cEdit.m_hWnd, m_hIMCEdit );
                                    m_hIMCEdit = NULL;
                                    }
                                EnableIme( m_hWndFace, m_hIMCFace );
                                EnableIme( m_hWndSize, m_hIMCSize );
                                m_hIMCFace = NULL;
                                m_hIMCSize = NULL;
                                m_pcTfont->SetFocus();
                                }
                        }
                else
                        {

                        if (!m_bAssocIMC)
                                {

                                m_bAssocIMC = TRUE;
                                if (!IsCUAS())
                                    m_hIMCEdit = DisableIme( m_cEdit.m_hWnd );
                                m_hIMCFace = DisableIme( m_hWndFace );
                                m_hIMCSize = DisableIme( m_hWndSize );
                                m_pcTfont->SetFocus();
                                }
                        }
                }


    if (pFontOld != NULL)
        editDC.SelectObject( pFontOld );

    m_eLastAction = eFONT_CHANGE;
    }

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

void CTedit::OnSize( UINT nType, int cx, int cy )
    {
    if (! m_bStarting)
        ShowWindow( SW_HIDE );

    // need to do this if transparent to force see through
    m_cRectOldPos = m_cRectWindow;
    GetWindowRect( &m_cRectWindow );
    m_pImgWnd->ScreenToClient( m_cRectWindow );

    m_eLastAction = eSIZE_MOVE_CHANGE;

    // could be NULL when main window is created and child edit window
    // has not been created yet.
    if (m_cEdit.GetSafeHwnd() != NULL)
        {
        m_cEdit.MoveWindow( 0, 0, cx, cy );
        m_cEdit.SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        }
    InvalidateRect( NULL );
    UpdateWindow();

    if (m_bBackgroundTransparent)
        {
        RefreshWindow();
        }
    if (! m_bStarting)
        ShowWindow( SW_SHOW );


        if ( m_bVertEdit )
                {
                m_cEdit.SetFmtRect();
                CPoint pt( -20000, -20000 );
                m_cEdit.SetCaretPos( pt );
                m_cEdit.SetCaretPosition( FALSE, NULL, -1 );
                m_cEdit.Repaint();
                }


    }

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

void CTedit::OnMove( int x, int y )
    {
    // need to do this if transparent to force see through
    m_cRectOldPos = m_cRectWindow;
    GetWindowRect( &m_cRectWindow );
    m_pImgWnd->ScreenToClient( m_cRectWindow );

    if (m_cRectOldPos.Width()  != m_cRectWindow.Width()
    ||  m_cRectOldPos.Height() != m_cRectWindow.Height())
        {
        //reset back to previous, since new will be updated in onsize, due to
        // size and move happening both (e.g. sizing either left or top side
        // causes an onmove then an onsize
        m_cRectWindow = m_cRectOldPos;
        }
    m_eLastAction = eSIZE_MOVE_CHANGE;

    if (m_cEdit.GetSafeHwnd() != NULL)
        {
        m_cEdit.SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        }

    InvalidateRect( NULL );
    UpdateWindow();

    if (m_bBackgroundTransparent)
        {
        RefreshWindow();
        }
    }

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

LRESULT CTedit::OnMoving( WPARAM, LPARAM lprc )
    {
    LRESULT lResult = 0;
    CRect rectEdit  = *((LPRECT)lprc);
    CRect rectImage = m_pImgWnd->GetDrawingRect();

    m_pImgWnd->ClientToScreen( &rectImage );

    int iX = 0;
    int iY = 0;

    if (rectEdit.left < rectImage.left)
        iX = rectImage.left - rectEdit.left;
    else
        if (rectEdit.right > rectImage.right)
            iX = -(rectEdit.right - rectImage.right);

    if (rectEdit.top < rectImage.top)
        iY = rectImage.top - rectEdit.top;
    else
        if (rectEdit.bottom > rectImage.bottom)
            iY = -(rectEdit.bottom - rectImage.bottom);

    if (iX || iY)
        {
        rectEdit.OffsetRect( iX, iY );
        *((LPRECT)lprc) = rectEdit;
        lResult = 1;
        }
    return lResult;
    }

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

void CTedit::OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI )
    {
    CRect rectImage = m_pImgWnd->GetDrawingRect();
    CSize      Size = rectImage.Size();

    lpMMI->ptMaxSize.x      = Size.cx;
    lpMMI->ptMaxSize.y      = Size.cy;
    lpMMI->ptMaxPosition    = rectImage.TopLeft();
    lpMMI->ptMinTrackSize.x = m_SizeMinimum.cx;
    lpMMI->ptMinTrackSize.y = m_SizeMinimum.cy;

    CRect rectClient;

    GetWindowRect( &rectClient );
    m_pImgWnd->ScreenToClient( &rectClient );

    switch (m_uiHitArea)
        {
        case HTTOP:
        case HTLEFT:
        case HTTOPLEFT:
            break;

        case HTRIGHT:
        case HTTOPRIGHT:
        case HTBOTTOMRIGHT:
            lpMMI->ptMaxSize.x -= (rectClient.left - rectImage.left);

            if (m_uiHitArea == HTBOTTOMRIGHT)
                ; // fall thru and do the bottom
            else
                break;

        case HTBOTTOMLEFT:
        case HTBOTTOM:
            lpMMI->ptMaxSize.y -= (rectClient.top - rectImage.top);
            break;
        }

    lpMMI->ptMaxTrackSize = lpMMI->ptMaxSize;
    }

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

HBRUSH CTedit::OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor )
    {
    HBRUSH hbrBack = NULL;

    if (pWnd == &m_cEdit)
        {
        PBSelectPalette( pDC, theApp.m_pPalette, FALSE );
        pDC->SetTextColor( m_crFGColor );

        //set the background color and transparent mode
//      if (m_bBackgroundTransparent)
//          {
            pDC->SetBkMode( TRANSPARENT );

            hbrBack = (HBRUSH)::GetStockObject( NULL_BRUSH );
//          }
//      else
//          {
//          pDC->SetBkMode( OPAQUE );
//          pDC->SetBkColor( m_crBKColor );

//          hbrBack = (HBRUSH)m_hbrBkColor.GetSafeHandle();
//          }
        }
    if (hbrBack == NULL)
        return (HBRUSH)Default();

    return hbrBack;
    }

/******************************************************************************/
//void CTedit::OnLButtonDown(UINT nFlags, CPoint point )
//  {
//  SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
//  SetFocus();
//  CEdit::OnLButtonDown(nFlags, point);
//  }

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

void CTedit::OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp )
    {
    /* Increase by an extra width height of the border*/
    lpncsp->rgrc[0].left   += CTracker::HANDLE_SIZE;
    lpncsp->rgrc[0].top    += CTracker::HANDLE_SIZE;
    lpncsp->rgrc[0].right  -= CTracker::HANDLE_SIZE;
    lpncsp->rgrc[0].bottom -= CTracker::HANDLE_SIZE;
    }

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

void CTedit::OnNcPaint()
    {
    CDC *pdcWindow = GetWindowDC();

    ASSERT(pdcWindow != NULL);

    if (pdcWindow != NULL)
        {
        CRgn    rgnClipping;
        CRect   cWinRect;
        int     iWindowWidth;
        int     iWindowHeight;

        GetWindowRect( &cWinRect );

        iWindowWidth  = cWinRect.Width();
        iWindowHeight = cWinRect.Height();

        CRect cBorderRect( 0, 0, iWindowWidth, iWindowHeight );

        CTracker::DrawBorder ( pdcWindow, cBorderRect, CTracker::all );
        CTracker::DrawHandles( pdcWindow, cBorderRect, CTracker::all );

        ReleaseDC( pdcWindow );
        }
    }

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

UINT CTedit::OnNcHitTest( CPoint point )
    {
    CRect cClientRect;
    UINT  uiHitTestCode = HTCAPTION;

    ScreenToClient( &point );

    GetClientRect(&cClientRect);

    //Test to see if the pt is in THE CLIENT AREA
    if (cClientRect.PtInRect(point))
        {
        uiHitTestCode = HTCLIENT;
        }

    m_uiHitArea = HTNOWHERE;

    switch (CTracker::HitTest( cClientRect, point, CTracker::nil ))
        {
        case CTracker::resizingTop:
            m_uiHitArea = HTTOP;
            break;

        case CTracker::resizingLeft:
            m_uiHitArea = HTLEFT;
            break;

        case CTracker::resizingRight:
            m_uiHitArea = HTRIGHT;
            break;

        case CTracker::resizingBottom:
            m_uiHitArea = HTBOTTOM;
            break;

        case CTracker::resizingTopLeft:
            m_uiHitArea = HTTOPLEFT;
            break;

        case CTracker::resizingTopRight:
            m_uiHitArea = HTTOPRIGHT;
            break;

        case CTracker::resizingBottomLeft:
            m_uiHitArea = HTBOTTOMLEFT;
            break;

        case CTracker::resizingBottomRight:
            m_uiHitArea = HTBOTTOMRIGHT;
            break;
        }

    if (m_uiHitArea != HTNOWHERE)
        uiHitTestCode = m_uiHitArea;


        m_cEdit.SetHCursorShape();


    return uiHitTestCode;
    }

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

void CTedit::OnRButtonDown(UINT nFlags, CPoint point)
    {
    CMenu cMenuPopup;
    CMenu *pcContextMenu;
    CRect cRectClient;
    BOOL  bRC = cMenuPopup.LoadMenu( IDR_TEXT_POPUP );

    ASSERT( bRC );

    if (bRC)
        {
        GetClientRect( &cRectClient );

        pcContextMenu = cMenuPopup.GetSubMenu( ID_EBOX_POPUPMENU_POS );

        ASSERT( pcContextMenu != NULL );

        if (pcContextMenu != NULL)
            {
            // update the check marks
            OnUpdateTextPlain    ( pcContextMenu );
            OnUpdateTextBold     ( pcContextMenu );
            OnUpdateTextItalic   ( pcContextMenu );
            OnUpdateTextUnderline( pcContextMenu );
            OnUpdateTextTexttool ( pcContextMenu );

            ClientToScreen( &point );
            ClientToScreen( &cRectClient );

            // the frame actually has a clue about what items to enable...
            CWnd *notify = GetParentFrame();

            if( !notify )
                notify = this; // oh well...

            pcContextMenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON,
                                     point.x, point.y, notify, &cRectClient );
            }
        }
    }

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

void CTedit::OnTextPlain()
    {
    ASSERT( m_pcTfont != NULL );

    if (m_pcTfont != NULL)
        {
        if (m_pcTfont->IsBoldOn())
            {
            m_pcTfont->OnBold();
            }

        if (m_pcTfont->IsItalicOn())
            {
            m_pcTfont->OnItalic();
            }

        if (m_pcTfont->IsUnderlineOn())
            {
            m_pcTfont->OnUnderline();
            }

        if (m_pcTfont->IsShadowOn())
            {
            m_pcTfont->OnShadow();
            }

        m_pcTfont->RefreshToolBar();

        RefreshWindow();
        }
    }

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

void CTedit::OnTextBold()
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        m_pcTfont->OnBold();
        m_pcTfont->RefreshToolBar();

        RefreshWindow();
        }
    }

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

void CTedit::OnTextItalic()
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        m_pcTfont->OnItalic();
        m_pcTfont->RefreshToolBar();

        RefreshWindow();
        }
    }

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

void CTedit::OnTextUnderline()
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        m_pcTfont->OnUnderline();
        m_pcTfont->RefreshToolBar();

        RefreshWindow();
        }
    }

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

void CTedit::OnTextSelectfont()
    {
    if (m_pcTfont != NULL)
        {
        if (! IsFontPaletteVisible())
            ShowFontPalette( SW_SHOW );
        else
            m_pcTfont->SetFocus();
        }
    }

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

void CTedit::OnTextSelectpointsize()
    {
    if (m_pcTfont != NULL)
        {
        if (! IsFontPaletteVisible())
            ShowFontPalette( SW_SHOW );
        else
            m_pcTfont->SetFocus();

        CWnd* pWnd = m_pcTfont->GetFontSizeControl();

        if (pWnd != NULL)
            {
            pWnd->SetFocus();
            }
        }
    }

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

void CTedit::OnEditCut()
    {

        if ( m_bVertEdit )      HideCaret();


    m_cEdit.Cut();
    RefreshWindow();


        if ( m_bVertEdit )
                {
                m_cEdit.SetCaretShape();
                ShowCaret();
                }

    }

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

void CTedit::OnEditCopy()
    {
    m_cEdit.Copy();
    }

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

void CTedit::OnEditPaste()
    {
    m_bPasting = TRUE;

    #ifdef _DEBUG
    TRACE0( "OnEditPaste Start\n" );
    #endif

    m_cEdit.Paste();

    #ifdef _DEBUG
    TRACE0( "OnEditPaste End\n" );
    #endif

    m_bPasting = FALSE;

    RefreshWindow();
    }

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

void CTedit::OnTextDelete()
    {
    int iLength = m_cEdit.GetWindowTextLength();
    int iStart  = iLength;
    int iEnd    = iLength;


        if ( m_bVertEdit )              m_cEdit.HideCaret();


    m_cEdit.GetSel( iStart, iEnd );

    if (iStart == iEnd)
        {
        if (iLength == iStart)
            return;

        CString strText;
        m_cEdit.GetWindowText(strText);
        if (!strText.IsEmpty() && (IsDBCSLeadByte((CHAR)strText[iStart])
            || strText[iStart]==TEXT('\r')))
            iEnd += 2;
        else
            iEnd += 1;

        m_cEdit.SetSel( iStart, iEnd, TRUE );
        }
    m_cEdit.Clear();


        if ( m_bVertEdit )
                {
                m_cEdit.SetCaretShape();
                m_cEdit.SetCaretPosition( TRUE, NULL, -1 );
                m_cEdit.ShowCaret();
                m_cEdit.Repaint();
                }
        else
                {


    UpdateWindow();
    RefreshWindow();


                }


    }

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

void CTedit::OnTextSelectall()
    {
    m_cEdit.SetSel( 0, -1, TRUE );

    RefreshWindow();
    }

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

void CTedit::OnTextUndo()
    {
    Undo();

    RefreshWindow();
    }

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

void CTedit::OnTextPlace()
    {
    CWnd* cwndParent = GetParent();

    cwndParent->PostMessage( WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM( CTracker::HANDLE_SIZE + 1, CTracker::HANDLE_SIZE + 1 ) );
    cwndParent->PostMessage( WM_LBUTTONUP,   MK_LBUTTON, MAKELPARAM( CTracker::HANDLE_SIZE + 1, CTracker::HANDLE_SIZE + 1 ) );
    }

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

void CTedit::OnTextTexttool()
    {
    if (IsFontPaletteVisible())
        {
        ShowFontPalette( SW_HIDE );
        }
    else
        {
        ShowFontPalette( SW_SHOWNOACTIVATE );
        }
    }

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

void CTedit::OnUpdateTextPlain( CMenu *pcMenu )
    {
    ASSERT( m_pcTfont != NULL );

    if (m_pcTfont != NULL)
        {
        if (! m_pcTfont->IsBoldOn()
        &&  ! m_pcTfont->IsItalicOn()
        &&  ! m_pcTfont->IsUnderlineOn()
        &&  ! m_pcTfont->IsShadowOn())
           {
           pcMenu->CheckMenuItem(ID_TEXT_PLAIN, MF_BYCOMMAND | MF_CHECKED);
           }
       else
           {
           pcMenu->CheckMenuItem(ID_TEXT_PLAIN, MF_BYCOMMAND | MF_UNCHECKED);
           }
        }
    }

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

void CTedit::OnUpdateTextBold(CMenu *pcMenu)
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        if (m_pcTfont->IsBoldOn())
            {
            pcMenu->CheckMenuItem(ID_TEXT_BOLD, MF_BYCOMMAND | MF_CHECKED);
            }
        else
            {
            pcMenu->CheckMenuItem(ID_TEXT_BOLD, MF_BYCOMMAND | MF_UNCHECKED);
            }
        }
    }

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

void CTedit::OnUpdateTextItalic(CMenu *pcMenu)
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        if (m_pcTfont->IsItalicOn())
            {
            pcMenu->CheckMenuItem(ID_TEXT_ITALIC, MF_BYCOMMAND | MF_CHECKED);
            }
        else
            {
            pcMenu->CheckMenuItem(ID_TEXT_ITALIC, MF_BYCOMMAND | MF_UNCHECKED);
            }
        }
    }

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

void CTedit::OnUpdateTextUnderline(CMenu *pcMenu)
    {
    ASSERT(m_pcTfont != NULL);

    if (m_pcTfont != NULL)
        {
        if (m_pcTfont->IsUnderlineOn())
            {
            pcMenu->CheckMenuItem(ID_TEXT_UNDERLINE, MF_BYCOMMAND | MF_CHECKED);
            }
        else
            {
            pcMenu->CheckMenuItem(ID_TEXT_UNDERLINE, MF_BYCOMMAND | MF_UNCHECKED);
            }
        }
    }

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

void CTedit::OnUpdateTextTexttool(CMenu *pcMenu)
    {
    if (IsFontPaletteVisible())
        {
        pcMenu->CheckMenuItem(ID_VIEW_TEXT_TOOLBAR, MF_BYCOMMAND | MF_CHECKED);
        }
    else
        {
        pcMenu->CheckMenuItem(ID_VIEW_TEXT_TOOLBAR, MF_BYCOMMAND | MF_UNCHECKED);
        }
    }

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



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

void CTedit::OnDestroy(void)
    {
        if ( m_cEdit.GetSafeHwnd() )
                {
                if ( m_cEdit.m_hOldCursor )
                        SetClassLongPtr( m_cEdit.m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_cEdit.m_hOldCursor );

                //restore original edit IMC
                if (m_bAssocIMC)
                        {
                        m_bAssocIMC = FALSE;
                        EnableIme( m_cEdit.m_hWnd, m_hIMCEdit );
                        EnableIme( m_hWndFace, m_hIMCFace );
                        EnableIme( m_hWndSize, m_hIMCSize );
                        m_hIMCEdit = NULL;
                        m_hIMCFace = NULL;
                        m_hIMCSize = NULL;
                        }
                }

        Default();
        return;
        }

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

HIMC    CTedit::DisableIme( HWND hWnd )
        {
        HIMC    hIMC = NULL;

        if ( (hWnd) && (::IsWindow( hWnd )) )
                hIMC = ImmAssociateContext( hWnd, NULL );

        return  hIMC;
        }

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

void    CTedit::EnableIme( HWND hWnd, HIMC hIMC )
        {
        if ( (hWnd) && (::IsWindow( hWnd )) )
                ImmAssociateContext( hWnd, hIMC );
        }

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

//
// Tablet PC.
//
// Is CUAS (Cicero Unaware App Support) is on, we need to use hIMC even on
// Ansi Font. The string from English HW/Speech TIPs will be delivered
// through hIMC.
//
BOOL CTedit::IsCUAS()
{
    BOOL bRet = FALSE;

    typedef BOOL (*PFNCTFIMMISCICEROENABLED)(void);

    static PFNCTFIMMISCICEROENABLED pfn = NULL;

    if (!pfn)
    {
        HMODULE hMod = LoadLibrary(TEXT("imm32.dll"));
        if (hMod)
        {
            pfn = (PFNCTFIMMISCICEROENABLED)GetProcAddress(hMod,
                               "CtfImmIsCiceroEnabled");

        }
    }
    if (pfn)
        bRet = pfn();
    return bRet;
}

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