Home | History | Annotate | Download | only in fxedit
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/fxedit/fxet_stub.h"
      8 #include "../../include/fxedit/fxet_edit.h"
      9 
     10 #define FX_EDIT_UNDO_MAXITEM				10000
     11 
     12 /* ---------------------------- CFX_Edit_Iterator ---------------------------- */
     13 
     14 CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit * pEdit,IPDF_VariableText_Iterator * pVTIterator) :
     15 	m_pEdit(pEdit),
     16 	m_pVTIterator(pVTIterator)
     17 {
     18 }
     19 
     20 CFX_Edit_Iterator::~CFX_Edit_Iterator()
     21 {
     22 }
     23 
     24 FX_BOOL	CFX_Edit_Iterator::NextWord()
     25 {
     26 	ASSERT(m_pVTIterator != NULL);
     27 
     28 	return m_pVTIterator->NextWord();
     29 }
     30 
     31 FX_BOOL CFX_Edit_Iterator::NextLine()
     32 {
     33 	ASSERT(m_pVTIterator != NULL);
     34 
     35 	return m_pVTIterator->NextLine();
     36 }
     37 
     38 FX_BOOL CFX_Edit_Iterator::NextSection()
     39 {
     40 	ASSERT(m_pVTIterator != NULL);
     41 
     42 	return m_pVTIterator->NextSection();
     43 }
     44 
     45 FX_BOOL	CFX_Edit_Iterator::PrevWord()
     46 {
     47 	ASSERT(m_pVTIterator != NULL);
     48 
     49 	return m_pVTIterator->PrevWord();
     50 }
     51 
     52 FX_BOOL	CFX_Edit_Iterator::PrevLine()
     53 {
     54 	ASSERT(m_pVTIterator != NULL);
     55 
     56 	return m_pVTIterator->PrevLine();
     57 }
     58 
     59 FX_BOOL	CFX_Edit_Iterator::PrevSection()
     60 {
     61 	ASSERT(m_pVTIterator != NULL);
     62 
     63 	return m_pVTIterator->PrevSection();
     64 }
     65 
     66 FX_BOOL CFX_Edit_Iterator::GetWord(CPVT_Word & word) const
     67 {
     68 	ASSERT(m_pEdit != NULL);
     69 	ASSERT(m_pVTIterator != NULL);
     70 
     71 	if (m_pVTIterator->GetWord(word))
     72 	{
     73 		word.ptWord = m_pEdit->VTToEdit(word.ptWord);
     74 		return TRUE;
     75 	}
     76 
     77 	return FALSE;
     78 }
     79 
     80 FX_BOOL CFX_Edit_Iterator::GetLine(CPVT_Line & line) const
     81 {
     82 	ASSERT(m_pEdit != NULL);
     83 	ASSERT(m_pVTIterator != NULL);
     84 
     85 	if (m_pVTIterator->GetLine(line))
     86 	{
     87 		line.ptLine = m_pEdit->VTToEdit(line.ptLine);
     88 		return TRUE;
     89 	}
     90 
     91 	return FALSE;
     92 }
     93 
     94 FX_BOOL CFX_Edit_Iterator::GetSection(CPVT_Section & section) const
     95 {
     96 	ASSERT(m_pEdit != NULL);
     97 	ASSERT(m_pVTIterator != NULL);
     98 
     99 	if (m_pVTIterator->GetSection(section))
    100 	{
    101 		section.rcSection = m_pEdit->VTToEdit(section.rcSection);
    102 		return TRUE;
    103 	}
    104 
    105 	return FALSE;
    106 }
    107 
    108 void CFX_Edit_Iterator::SetAt(FX_INT32 nWordIndex)
    109 {
    110 	ASSERT(m_pVTIterator != NULL);
    111 
    112 	m_pVTIterator->SetAt(nWordIndex);
    113 }
    114 
    115 void CFX_Edit_Iterator::SetAt(const CPVT_WordPlace & place)
    116 {
    117 	ASSERT(m_pVTIterator != NULL);
    118 
    119 	m_pVTIterator->SetAt(place);
    120 }
    121 
    122 const CPVT_WordPlace & CFX_Edit_Iterator::GetAt() const
    123 {
    124 	ASSERT(m_pVTIterator != NULL);
    125 
    126 	return m_pVTIterator->GetAt();
    127 }
    128 
    129 IFX_Edit* CFX_Edit_Iterator::GetEdit() const
    130 {
    131 	return m_pEdit;
    132 }
    133 
    134 /* --------------------------- CFX_Edit_Provider ------------------------------- */
    135 
    136 CFX_Edit_Provider::CFX_Edit_Provider(IFX_Edit_FontMap * pFontMap) : m_pFontMap(pFontMap)
    137 {
    138 	ASSERT(m_pFontMap != NULL);
    139 }
    140 
    141 CFX_Edit_Provider::~CFX_Edit_Provider()
    142 {
    143 }
    144 
    145 IFX_Edit_FontMap* CFX_Edit_Provider::GetFontMap()
    146 {
    147 	return m_pFontMap;
    148 }
    149 
    150 FX_INT32 CFX_Edit_Provider::GetCharWidth(FX_INT32 nFontIndex, FX_WORD word, FX_INT32 nWordStyle)
    151 {
    152 	if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
    153 	{
    154 		FX_DWORD charcode = word;
    155 
    156 		if (pPDFFont->IsUnicodeCompatible())
    157 			charcode = pPDFFont->CharCodeFromUnicode(word);
    158 		else
    159 			charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word);
    160 
    161 		if (charcode != -1)
    162 			return pPDFFont->GetCharWidthF(charcode);
    163 	}
    164 
    165 	return 0;
    166 }
    167 
    168 FX_INT32 CFX_Edit_Provider::GetTypeAscent(FX_INT32 nFontIndex)
    169 {
    170 	if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
    171 		return pPDFFont->GetTypeAscent();
    172 
    173 	return 0;
    174 }
    175 
    176 FX_INT32 CFX_Edit_Provider::GetTypeDescent(FX_INT32 nFontIndex)
    177 {
    178 	if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
    179 		return pPDFFont->GetTypeDescent();
    180 
    181 	return 0;
    182 }
    183 
    184 FX_INT32 CFX_Edit_Provider::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
    185 {
    186 	return m_pFontMap->GetWordFontIndex(word,charset,nFontIndex);
    187 }
    188 
    189 FX_INT32 CFX_Edit_Provider::GetDefaultFontIndex()
    190 {
    191 	return 0;
    192 }
    193 
    194 FX_BOOL	CFX_Edit_Provider::IsLatinWord(FX_WORD word)
    195 {
    196 	return FX_EDIT_ISLATINWORD(word);
    197 }
    198 
    199 /* --------------------------------- CFX_Edit_Refresh --------------------------------- */
    200 
    201 CFX_Edit_Refresh::CFX_Edit_Refresh()
    202 {
    203 }
    204 
    205 CFX_Edit_Refresh::~CFX_Edit_Refresh()
    206 {
    207 }
    208 
    209 void CFX_Edit_Refresh::BeginRefresh()
    210 {
    211 	m_RefreshRects.Empty();
    212 	m_OldLineRects = m_NewLineRects;
    213 }
    214 
    215 void CFX_Edit_Refresh::Push(const CPVT_WordRange & linerange,const CPDF_Rect & rect)
    216 {
    217 	m_NewLineRects.Add(linerange,rect);
    218 }
    219 
    220 void CFX_Edit_Refresh::NoAnalyse()
    221 {
    222 	{
    223 		for (FX_INT32 i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++)
    224 			if (CFX_Edit_LineRect * pOldRect = m_OldLineRects.GetAt(i))
    225 				m_RefreshRects.Add(pOldRect->m_rcLine);
    226 	}
    227 
    228 	{
    229 		for (FX_INT32 i = 0, sz = m_NewLineRects.GetSize(); i < sz; i++)
    230 			if (CFX_Edit_LineRect * pNewRect = m_NewLineRects.GetAt(i))
    231 				m_RefreshRects.Add(pNewRect->m_rcLine);
    232 	}
    233 }
    234 
    235 void CFX_Edit_Refresh::Analyse(FX_INT32 nAlignment)
    236 {
    237 	FX_BOOL bLineTopChanged = FALSE;
    238 	CPDF_Rect rcResult;
    239 	FX_FLOAT fWidthDiff;
    240 
    241 	FX_INT32 szMax = FX_EDIT_MAX(m_OldLineRects.GetSize(),m_NewLineRects.GetSize());
    242 	FX_INT32 i = 0;
    243 
    244 	while (i < szMax)
    245 	{
    246 		CFX_Edit_LineRect * pOldRect = m_OldLineRects.GetAt(i);
    247 		CFX_Edit_LineRect * pNewRect = m_NewLineRects.GetAt(i);
    248 
    249 		if (pOldRect)
    250 		{
    251 			if (pNewRect)
    252 			{
    253 				if (bLineTopChanged)
    254 				{
    255 					rcResult = pOldRect->m_rcLine;
    256 					rcResult.Union(pNewRect->m_rcLine);
    257 					m_RefreshRects.Add(rcResult);
    258 				}
    259 				else
    260 				{
    261 					if (*pNewRect != *pOldRect)
    262 					{
    263 						if (!pNewRect->IsSameTop(*pOldRect) || !pNewRect->IsSameHeight(*pOldRect))
    264 						{
    265 							bLineTopChanged = TRUE;
    266 							continue;
    267 						}
    268 
    269 						if (nAlignment == 0)
    270 						{
    271 							if (pNewRect->m_wrLine.BeginPos != pOldRect->m_wrLine.BeginPos)
    272 							{
    273 								rcResult = pOldRect->m_rcLine;
    274 								rcResult.Union(pNewRect->m_rcLine);
    275 								m_RefreshRects.Add(rcResult);
    276 							}
    277 							else
    278 							{
    279 								if (!pNewRect->IsSameLeft(*pOldRect))
    280 								{
    281 									rcResult = pOldRect->m_rcLine;
    282 									rcResult.Union(pNewRect->m_rcLine);
    283 								}
    284 								else
    285 								{
    286 									fWidthDiff = pNewRect->m_rcLine.Width() - pOldRect->m_rcLine.Width();
    287 									rcResult = pNewRect->m_rcLine;
    288 									if (fWidthDiff > 0.0f)
    289 										rcResult.left = rcResult.right - fWidthDiff;
    290 									else
    291 									{
    292 										rcResult.left = rcResult.right;
    293 										rcResult.right += (-fWidthDiff);
    294 									}
    295 								}
    296 								m_RefreshRects.Add(rcResult);
    297 							}
    298 						}
    299 						else
    300 						{
    301 							rcResult = pOldRect->m_rcLine;
    302 							rcResult.Union(pNewRect->m_rcLine);
    303 							m_RefreshRects.Add(rcResult);
    304 						}
    305 					}
    306 					else
    307 					{
    308 						//don't need to do anything
    309 					}
    310 				}
    311 			}
    312 			else
    313 			{
    314 				m_RefreshRects.Add(pOldRect->m_rcLine);
    315 			}
    316 		}
    317 		else
    318 		{
    319 			if (pNewRect)
    320 			{
    321 				m_RefreshRects.Add(pNewRect->m_rcLine);
    322 			}
    323 			else
    324 			{
    325 				//error
    326 			}
    327 		}
    328 		i++;
    329 	}
    330 }
    331 
    332 void CFX_Edit_Refresh::AddRefresh(const CPDF_Rect & rect)
    333 {
    334 	m_RefreshRects.Add(rect);
    335 }
    336 
    337 const CFX_Edit_RectArray * CFX_Edit_Refresh::GetRefreshRects() const
    338 {
    339 	return &m_RefreshRects;
    340 }
    341 
    342 void CFX_Edit_Refresh::EndRefresh()
    343 {
    344 	m_RefreshRects.Empty();
    345 }
    346 
    347 /* ------------------------------------- CFX_Edit_Undo ------------------------------------- */
    348 
    349 CFX_Edit_Undo::CFX_Edit_Undo(FX_INT32 nBufsize) : m_nCurUndoPos(0),
    350 	m_nBufSize(nBufsize),
    351 	m_bModified(FALSE),
    352 	m_bVirgin(TRUE),
    353 	m_bWorking(FALSE)
    354 {
    355 }
    356 
    357 CFX_Edit_Undo::~CFX_Edit_Undo()
    358 {
    359 	Reset();
    360 }
    361 
    362 FX_BOOL CFX_Edit_Undo::CanUndo() const
    363 {
    364 	return m_nCurUndoPos > 0;
    365 }
    366 
    367 void CFX_Edit_Undo::Undo()
    368 {
    369 	m_bWorking = TRUE;
    370 
    371 	if (m_nCurUndoPos > 0)
    372 	{
    373 		IFX_Edit_UndoItem * pItem = m_UndoItemStack.GetAt(m_nCurUndoPos-1);
    374 		ASSERT(pItem != NULL);
    375 
    376 		pItem->Undo();
    377 
    378 		m_nCurUndoPos--;
    379 		m_bModified = (m_nCurUndoPos != 0);
    380 	}
    381 
    382 	m_bWorking = FALSE;
    383 }
    384 
    385 FX_BOOL	CFX_Edit_Undo::CanRedo() const
    386 {
    387 	return m_nCurUndoPos < m_UndoItemStack.GetSize();
    388 }
    389 
    390 void CFX_Edit_Undo::Redo()
    391 {
    392 	m_bWorking = TRUE;
    393 
    394 	FX_INT32 nStackSize = m_UndoItemStack.GetSize();
    395 
    396 	if (m_nCurUndoPos < nStackSize)
    397 	{
    398 		IFX_Edit_UndoItem * pItem = m_UndoItemStack.GetAt(m_nCurUndoPos);
    399 		ASSERT(pItem != NULL);
    400 
    401 		pItem->Redo();
    402 
    403 		m_nCurUndoPos++;
    404 		m_bModified = (m_nCurUndoPos != 0);
    405 	}
    406 
    407 	m_bWorking = FALSE;
    408 }
    409 
    410 FX_BOOL	CFX_Edit_Undo::IsWorking() const
    411 {
    412 	return m_bWorking;
    413 }
    414 
    415 void CFX_Edit_Undo::AddItem(IFX_Edit_UndoItem* pItem)
    416 {
    417 	ASSERT(!m_bWorking);
    418 	ASSERT(pItem != NULL);
    419 	ASSERT(m_nBufSize > 1);
    420 
    421 	if (m_nCurUndoPos < m_UndoItemStack.GetSize())
    422 		RemoveTails();
    423 
    424 	if (m_UndoItemStack.GetSize() >= m_nBufSize)
    425 	{
    426 		RemoveHeads();
    427 		m_bVirgin = FALSE;
    428 	}
    429 
    430 	m_UndoItemStack.Add(pItem);
    431 	m_nCurUndoPos = m_UndoItemStack.GetSize();
    432 
    433 	m_bModified = (m_nCurUndoPos != 0);
    434 }
    435 
    436 FX_BOOL	CFX_Edit_Undo::IsModified() const
    437 {
    438 	if (m_bVirgin)
    439 		return m_bModified;
    440 	else
    441 		return TRUE;
    442 }
    443 
    444 IFX_Edit_UndoItem* CFX_Edit_Undo::GetItem(FX_INT32 nIndex)
    445 {
    446 	if (nIndex>=0 && nIndex < m_UndoItemStack.GetSize())
    447 		return m_UndoItemStack.GetAt(nIndex);
    448 
    449 	return NULL;
    450 }
    451 
    452 void CFX_Edit_Undo::RemoveHeads()
    453 {
    454 	ASSERT(m_UndoItemStack.GetSize() > 1);
    455 
    456 	IFX_Edit_UndoItem* pItem = m_UndoItemStack.GetAt(0);
    457 	ASSERT(pItem != NULL);
    458 
    459 	pItem->Release();
    460 	m_UndoItemStack.RemoveAt(0);
    461 }
    462 
    463 void CFX_Edit_Undo::RemoveTails()
    464 {
    465 	for (FX_INT32 i = m_UndoItemStack.GetSize()-1; i >= m_nCurUndoPos; i--)
    466 	{
    467 		IFX_Edit_UndoItem* pItem = m_UndoItemStack.GetAt(i);
    468 		ASSERT(pItem != NULL);
    469 
    470 		pItem->Release();
    471 		m_UndoItemStack.RemoveAt(i);
    472 	}
    473 }
    474 
    475 void CFX_Edit_Undo::Reset()
    476 {
    477 	for (FX_INT32 i=0, sz=m_UndoItemStack.GetSize(); i < sz; i++)
    478 	{
    479 		IFX_Edit_UndoItem * pItem = m_UndoItemStack.GetAt(i);
    480 		ASSERT(pItem != NULL);
    481 
    482 		pItem->Release();
    483 	}
    484 	m_nCurUndoPos = 0;
    485 	m_UndoItemStack.RemoveAll();
    486 }
    487 
    488 /* -------------------------------- CFX_Edit_GroupUndoItem -------------------------------- */
    489 
    490 CFX_Edit_GroupUndoItem::CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle) : m_sTitle(sTitle)
    491 {
    492 }
    493 
    494 CFX_Edit_GroupUndoItem::~CFX_Edit_GroupUndoItem()
    495 {
    496 	for (int i=0,sz=m_Items.GetSize(); i<sz; i++)
    497 	{
    498 		CFX_Edit_UndoItem* pUndoItem = m_Items[i];
    499 		ASSERT(pUndoItem != NULL);
    500 
    501 		pUndoItem->Release();
    502 	}
    503 
    504 	m_Items.RemoveAll();
    505 }
    506 
    507 void CFX_Edit_GroupUndoItem::AddUndoItem(CFX_Edit_UndoItem* pUndoItem)
    508 {
    509 	ASSERT(pUndoItem != NULL);
    510 
    511 	pUndoItem->SetFirst(FALSE);
    512 	pUndoItem->SetLast(FALSE);
    513 
    514 	m_Items.Add(pUndoItem);
    515 
    516 	if (m_sTitle.IsEmpty())
    517 		m_sTitle = pUndoItem->GetUndoTitle();
    518 }
    519 
    520 void CFX_Edit_GroupUndoItem::UpdateItems()
    521 {
    522 	if (m_Items.GetSize() > 0)
    523 	{
    524 		CFX_Edit_UndoItem* pFirstItem = m_Items[0];
    525 		ASSERT(pFirstItem != NULL);
    526 		pFirstItem->SetFirst(TRUE);
    527 
    528 		CFX_Edit_UndoItem* pLastItem = m_Items[m_Items.GetSize() - 1];
    529 		ASSERT(pLastItem != NULL);
    530 		pLastItem->SetLast(TRUE);
    531 	}
    532 }
    533 
    534 void CFX_Edit_GroupUndoItem::Undo()
    535 {
    536 	for (int i=m_Items.GetSize()-1; i>=0; i--)
    537 	{
    538 		CFX_Edit_UndoItem* pUndoItem = m_Items[i];
    539 		ASSERT(pUndoItem != NULL);
    540 
    541 		pUndoItem->Undo();
    542 	}
    543 }
    544 
    545 void CFX_Edit_GroupUndoItem::Redo()
    546 {
    547 	for (int i=0,sz=m_Items.GetSize(); i<sz; i++)
    548 	{
    549 		CFX_Edit_UndoItem* pUndoItem = m_Items[i];
    550 		ASSERT(pUndoItem != NULL);
    551 
    552 		pUndoItem->Redo();
    553 	}
    554 }
    555 
    556 CFX_WideString CFX_Edit_GroupUndoItem::GetUndoTitle()
    557 {
    558 	return m_sTitle;
    559 }
    560 
    561 void CFX_Edit_GroupUndoItem::Release()
    562 {
    563 	delete this;
    564 }
    565 
    566 /* ------------------------------------- CFX_Edit_UndoItem derived classes ------------------------------------- */
    567 
    568 CFXEU_InsertWord::CFXEU_InsertWord(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    569 								 FX_WORD word, FX_INT32 charset, const CPVT_WordProps * pWordProps)
    570 	: m_pEdit(pEdit), m_wpOld(wpOldPlace), m_wpNew(wpNewPlace), m_Word(word), m_nCharset(charset), m_WordProps()
    571 {
    572 	if (pWordProps)
    573 		m_WordProps = *pWordProps;
    574 }
    575 
    576 CFXEU_InsertWord::~CFXEU_InsertWord()
    577 {
    578 }
    579 
    580 void CFXEU_InsertWord::Redo()
    581 {
    582 	if (m_pEdit)
    583 	{
    584 		m_pEdit->SelectNone();
    585 		m_pEdit->SetCaret(m_wpOld);
    586 		m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,FALSE,TRUE);
    587 	}
    588 }
    589 
    590 void CFXEU_InsertWord::Undo()
    591 {
    592 	if (m_pEdit)
    593 	{
    594 		m_pEdit->SelectNone();
    595 		m_pEdit->SetCaret(m_wpNew);
    596 		m_pEdit->Backspace(FALSE,TRUE);
    597 	}
    598 }
    599 
    600 /* -------------------------------------------------------------------------- */
    601 
    602 CFXEU_InsertReturn::CFXEU_InsertReturn(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    603 			 const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps) :
    604 			m_pEdit(pEdit),
    605 			m_wpOld(wpOldPlace),
    606 			m_wpNew(wpNewPlace),
    607 			m_SecProps(),
    608 			m_WordProps()
    609 {
    610 	if (pSecProps)
    611 		m_SecProps = *pSecProps;
    612 	if (pWordProps)
    613 		m_WordProps = *pWordProps;
    614 }
    615 
    616 CFXEU_InsertReturn::~CFXEU_InsertReturn()
    617 {
    618 }
    619 
    620 void CFXEU_InsertReturn::Redo()
    621 {
    622 	if (m_pEdit)
    623 	{
    624 		m_pEdit->SelectNone();
    625 		m_pEdit->SetCaret(m_wpOld);
    626 		m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,FALSE,TRUE);
    627 	}
    628 }
    629 
    630 void CFXEU_InsertReturn::Undo()
    631 {
    632 	if (m_pEdit)
    633 	{
    634 		m_pEdit->SelectNone();
    635 		m_pEdit->SetCaret(m_wpNew);
    636 		m_pEdit->Backspace(FALSE,TRUE);
    637 	}
    638 }
    639 
    640 /* -------------------------------------------------------------------------- */
    641 //CFXEU_Backspace
    642 
    643 CFXEU_Backspace::CFXEU_Backspace(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    644 							   FX_WORD word, FX_INT32 charset,
    645 							   const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps) :
    646 			m_pEdit(pEdit),
    647 			m_wpOld(wpOldPlace),
    648 			m_wpNew(wpNewPlace),
    649 			m_Word(word),
    650 			m_nCharset(charset),
    651 			m_SecProps(SecProps),
    652 			m_WordProps(WordProps)
    653 {
    654 }
    655 
    656 CFXEU_Backspace::~CFXEU_Backspace()
    657 {
    658 }
    659 
    660 void CFXEU_Backspace::Redo()
    661 {
    662 	if (m_pEdit)
    663 	{
    664 		m_pEdit->SelectNone();
    665 		m_pEdit->SetCaret(m_wpOld);
    666 		m_pEdit->Backspace(FALSE,TRUE);
    667 	}
    668 }
    669 
    670 void CFXEU_Backspace::Undo()
    671 {
    672 	if (m_pEdit)
    673 	{
    674 		m_pEdit->SelectNone();
    675 		m_pEdit->SetCaret(m_wpNew);
    676 		if (m_wpNew.SecCmp(m_wpOld) != 0)
    677 		{
    678 			m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,FALSE,TRUE);
    679 		}
    680 		else
    681 		{
    682 			m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,FALSE,TRUE);
    683 		}
    684 	}
    685 }
    686 
    687 /* -------------------------------------------------------------------------- */
    688 //CFXEU_Delete
    689 
    690 CFXEU_Delete::CFXEU_Delete(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    691 							   FX_WORD word, FX_INT32 charset,
    692 							   const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps, FX_BOOL bSecEnd) :
    693 			m_pEdit(pEdit),
    694 			m_wpOld(wpOldPlace),
    695 			m_wpNew(wpNewPlace),
    696 			m_Word(word),
    697 			m_nCharset(charset),
    698 			m_SecProps(SecProps),
    699 			m_WordProps(WordProps),
    700 			m_bSecEnd(bSecEnd)
    701 {
    702 }
    703 
    704 CFXEU_Delete::~CFXEU_Delete()
    705 {
    706 }
    707 
    708 void CFXEU_Delete::Redo()
    709 {
    710 	if (m_pEdit)
    711 	{
    712 		m_pEdit->SelectNone();
    713 		m_pEdit->SetCaret(m_wpOld);
    714 		m_pEdit->Delete(FALSE,TRUE);
    715 	}
    716 }
    717 
    718 void CFXEU_Delete::Undo()
    719 {
    720 	if (m_pEdit)
    721 	{
    722 		m_pEdit->SelectNone();
    723 		m_pEdit->SetCaret(m_wpNew);
    724 		if (m_bSecEnd)
    725 		{
    726 			m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,FALSE,TRUE);
    727 		}
    728 		else
    729 		{
    730 			m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,FALSE,TRUE);
    731 		}
    732 	}
    733 }
    734 
    735 /* -------------------------------------------------------------------------- */
    736 //CFXEU_Clear
    737 
    738 CFXEU_Clear::CFXEU_Clear(CFX_Edit * pEdit,  const CPVT_WordRange & wrSel, const CFX_WideString & swText) :
    739 			m_pEdit(pEdit),
    740 			m_wrSel(wrSel),
    741 			m_swText(swText)
    742 {
    743 }
    744 
    745 CFXEU_Clear::~CFXEU_Clear()
    746 {
    747 }
    748 
    749 void CFXEU_Clear::Redo()
    750 {
    751 	if (m_pEdit)
    752 	{
    753 		m_pEdit->SelectNone();
    754 		m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
    755 		m_pEdit->Clear(FALSE,TRUE);
    756 	}
    757 }
    758 
    759 void CFXEU_Clear::Undo()
    760 {
    761 	if (m_pEdit)
    762 	{
    763 		m_pEdit->SelectNone();
    764 		m_pEdit->SetCaret(m_wrSel.BeginPos);
    765 		m_pEdit->InsertText(m_swText, DEFAULT_CHARSET, NULL,NULL,FALSE,TRUE);
    766 		m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
    767 	}
    768 }
    769 
    770 /* -------------------------------------------------------------------------- */
    771 //CFXEU_ClearRich
    772 
    773 CFXEU_ClearRich::CFXEU_ClearRich(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    774 							   const CPVT_WordRange & wrSel, FX_WORD word, FX_INT32 charset,
    775 							   const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps) :
    776 			m_pEdit(pEdit),
    777 			m_wpOld(wpOldPlace),
    778 			m_wpNew(wpNewPlace),
    779 			m_wrSel(wrSel),
    780 			m_Word(word),
    781 			m_nCharset(charset),
    782 			m_SecProps(SecProps),
    783 			m_WordProps(WordProps)
    784 {
    785 }
    786 
    787 CFXEU_ClearRich::~CFXEU_ClearRich()
    788 {
    789 }
    790 
    791 void CFXEU_ClearRich::Redo()
    792 {
    793 	if (m_pEdit && IsLast())
    794 	{
    795 		m_pEdit->SelectNone();
    796 		m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
    797 		m_pEdit->Clear(FALSE,TRUE);
    798 	}
    799 }
    800 
    801 void CFXEU_ClearRich::Undo()
    802 {
    803 	if (m_pEdit)
    804 	{
    805 		m_pEdit->SelectNone();
    806 		m_pEdit->SetCaret(m_wpOld);
    807 		if (m_wpNew.SecCmp(m_wpOld) != 0)
    808 		{
    809 			m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,FALSE,FALSE);
    810 		}
    811 		else
    812 		{
    813 			m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,FALSE,FALSE);
    814 		}
    815 
    816 		if (IsFirst())
    817 		{
    818 			m_pEdit->PaintInsertText(m_wrSel.BeginPos,m_wrSel.EndPos);
    819 			m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
    820 		}
    821 	}
    822 }
    823 /* -------------------------------------------------------------------------- */
    824 //CFXEU_InsertText
    825 
    826 CFXEU_InsertText::CFXEU_InsertText(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
    827 							   const CFX_WideString & swText, FX_INT32 charset,
    828 							   const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps) :
    829 			m_pEdit(pEdit),
    830 			m_wpOld(wpOldPlace),
    831 			m_wpNew(wpNewPlace),
    832 			m_swText(swText),
    833 			m_nCharset(charset),
    834 			m_SecProps(),
    835 			m_WordProps()
    836 {
    837 	if (pSecProps)
    838 		m_SecProps = *pSecProps;
    839 	if (pWordProps)
    840 		m_WordProps = *pWordProps;
    841 }
    842 
    843 CFXEU_InsertText::~CFXEU_InsertText()
    844 {
    845 }
    846 
    847 void CFXEU_InsertText::Redo()
    848 {
    849 	if (m_pEdit && IsLast())
    850 	{
    851 		m_pEdit->SelectNone();
    852 		m_pEdit->SetCaret(m_wpOld);
    853 		m_pEdit->InsertText(m_swText, m_nCharset,&m_SecProps, &m_WordProps,FALSE,TRUE);
    854 	}
    855 }
    856 
    857 void CFXEU_InsertText::Undo()
    858 {
    859 	if (m_pEdit)
    860 	{
    861 		m_pEdit->SelectNone();
    862 		m_pEdit->SetSel(m_wpOld,m_wpNew);
    863 		m_pEdit->Clear(FALSE,TRUE);
    864 	}
    865 }
    866 
    867 /* -------------------------------------------------------------------------- */
    868 
    869 CFXEU_SetSecProps::CFXEU_SetSecProps(CFX_Edit * pEdit, const CPVT_WordPlace & place, EDIT_PROPS_E ep,
    870 		const CPVT_SecProps & oldsecprops, const CPVT_WordProps & oldwordprops,
    871 		const CPVT_SecProps & newsecprops, const CPVT_WordProps & newwordprops, const CPVT_WordRange & range)
    872 		: m_pEdit(pEdit),
    873 		m_wpPlace(place),
    874 		m_eProps(ep),
    875 		m_OldSecProps(oldsecprops),
    876 		m_NewSecProps(newsecprops),
    877 		m_OldWordProps(oldwordprops),
    878 		m_NewWordProps(newwordprops),
    879 		m_wrPlace(range)
    880 {
    881 }
    882 
    883 CFXEU_SetSecProps::~CFXEU_SetSecProps()
    884 {
    885 }
    886 
    887 void CFXEU_SetSecProps::Redo()
    888 {
    889 	if (m_pEdit)
    890 	{
    891 		m_pEdit->SetSecProps(m_eProps,m_wpPlace,&m_NewSecProps,&m_NewWordProps,m_wrPlace,FALSE);
    892 		if (IsLast())
    893 		{
    894 			m_pEdit->SelectNone();
    895 			m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
    896 			m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
    897 		}
    898 	}
    899 }
    900 
    901 void CFXEU_SetSecProps::Undo()
    902 {
    903 	if (m_pEdit)
    904 	{
    905 		m_pEdit->SetSecProps(m_eProps,m_wpPlace,&m_OldSecProps,&m_OldWordProps,m_wrPlace,FALSE);
    906 		if (IsFirst())
    907 		{
    908 			m_pEdit->SelectNone();
    909 			m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
    910 			m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
    911 		}
    912 	}
    913 }
    914 
    915 /* -------------------------------------------------------------------------- */
    916 
    917 CFXEU_SetWordProps::CFXEU_SetWordProps(CFX_Edit * pEdit, const CPVT_WordPlace & place, EDIT_PROPS_E ep,
    918 		const CPVT_WordProps & oldprops, const CPVT_WordProps & newprops, const CPVT_WordRange & range)
    919 		: m_pEdit(pEdit),
    920 		m_wpPlace(place),
    921 		m_eProps(ep),
    922 		m_OldWordProps(oldprops),
    923 		m_NewWordProps(newprops),
    924 		m_wrPlace(range)
    925 {
    926 }
    927 
    928 CFXEU_SetWordProps::~CFXEU_SetWordProps()
    929 {
    930 }
    931 
    932 void CFXEU_SetWordProps::Redo()
    933 {
    934 	if (m_pEdit)
    935 	{
    936 		m_pEdit->SetWordProps(m_eProps,m_wpPlace,&m_NewWordProps,m_wrPlace,FALSE);
    937 		if (IsLast())
    938 		{
    939 			m_pEdit->SelectNone();
    940 			m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
    941 			m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
    942 		}
    943 	}
    944 }
    945 
    946 void CFXEU_SetWordProps::Undo()
    947 {
    948 	if (m_pEdit)
    949 	{
    950 		m_pEdit->SetWordProps(m_eProps,m_wpPlace,&m_OldWordProps,m_wrPlace,FALSE);
    951 		if (IsFirst())
    952 		{
    953 			m_pEdit->SelectNone();
    954 			m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
    955 			m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
    956 		}
    957 	}
    958 }
    959 
    960 /* ------------------------------------- CFX_Edit ------------------------------------- */
    961 
    962 CFX_Edit::CFX_Edit(IPDF_VariableText * pVT) :
    963 	m_pVT(pVT),
    964 	m_pNotify(NULL),
    965 	m_pOprNotify(NULL),
    966 	m_wpCaret(-1,-1,-1),
    967 	m_wpOldCaret(-1,-1,-1),
    968 	m_ptScrollPos(0,0),
    969 	m_ptRefreshScrollPos(0,0),
    970 	m_bEnableScroll(FALSE),
    971 	m_bEnableOverflow(FALSE),
    972 	m_pVTProvide(NULL),
    973 	m_pIterator(NULL),
    974 	m_SelState(),
    975 	m_ptCaret(0.0f,0.0f),
    976 	m_Undo(FX_EDIT_UNDO_MAXITEM),
    977 	m_nAlignment(0),
    978 	m_bNotifyFlag(FALSE),
    979 	m_bEnableRefresh(TRUE),
    980 	m_rcOldContent(0.0f,0.0f,0.0f,0.0f),
    981 	m_bEnableUndo(TRUE),
    982 	m_bNotify(TRUE),
    983 	m_bOprNotify(FALSE),
    984 	m_pGroupUndoItem(NULL)
    985 {
    986 	ASSERT(pVT != NULL);
    987 }
    988 
    989 CFX_Edit::~CFX_Edit()
    990 {
    991 	if (m_pVTProvide)
    992 	{
    993 		delete m_pVTProvide;
    994 		m_pVTProvide = NULL;
    995 	}
    996 
    997 	if (m_pIterator)
    998 	{
    999 		delete m_pIterator;
   1000 		m_pIterator = NULL;
   1001 	}
   1002 
   1003 	ASSERT(m_pGroupUndoItem == NULL);
   1004 }
   1005 
   1006 // public methods
   1007 
   1008 void CFX_Edit::Initialize()
   1009 {
   1010 	m_pVT->Initialize();
   1011 	SetCaret(m_pVT->GetBeginWordPlace());
   1012 	SetCaretOrigin();
   1013 }
   1014 
   1015 void CFX_Edit::SetFontMap(IFX_Edit_FontMap * pFontMap)
   1016 {
   1017 	if (m_pVTProvide)
   1018 		delete m_pVTProvide;
   1019 
   1020 	m_pVT->SetProvider(m_pVTProvide = new CFX_Edit_Provider(pFontMap));
   1021 }
   1022 
   1023 void CFX_Edit::SetVTProvider(IPDF_VariableText_Provider* pProvider)
   1024 {
   1025 	m_pVT->SetProvider(pProvider);
   1026 }
   1027 
   1028 void CFX_Edit::SetNotify(IFX_Edit_Notify* pNotify)
   1029 {
   1030 	m_pNotify = pNotify;
   1031 }
   1032 
   1033 void CFX_Edit::SetOprNotify(IFX_Edit_OprNotify* pOprNotify)
   1034 {
   1035 	m_pOprNotify = pOprNotify;
   1036 }
   1037 
   1038 IFX_Edit_Iterator * CFX_Edit::GetIterator()
   1039 {
   1040 	if (!m_pIterator)
   1041 		m_pIterator = new CFX_Edit_Iterator(this,m_pVT->GetIterator());
   1042 
   1043 	return m_pIterator;
   1044 }
   1045 
   1046 IPDF_VariableText *	CFX_Edit::GetVariableText()
   1047 {
   1048 	return m_pVT;
   1049 }
   1050 
   1051 IFX_Edit_FontMap* CFX_Edit::GetFontMap()
   1052 {
   1053 	if (m_pVTProvide)
   1054 		return m_pVTProvide->GetFontMap();
   1055 
   1056 	return NULL;
   1057 }
   1058 
   1059 void CFX_Edit::SetPlateRect(const CPDF_Rect & rect, FX_BOOL bPaint/* = TRUE*/)
   1060 {
   1061 	m_pVT->SetPlateRect(rect);
   1062 	m_ptScrollPos = CPDF_Point(rect.left,rect.top);
   1063 	if (bPaint) Paint();
   1064 }
   1065 
   1066 void CFX_Edit::SetAlignmentH(FX_INT32 nFormat/* =0 */, FX_BOOL bPaint/* = TRUE*/)
   1067 {
   1068 	m_pVT->SetAlignment(nFormat);
   1069 	if (bPaint) Paint();
   1070 }
   1071 
   1072 void CFX_Edit::SetAlignmentV(FX_INT32 nFormat/* =0 */, FX_BOOL bPaint/* = TRUE*/)
   1073 {
   1074 	m_nAlignment = nFormat;
   1075 	if (bPaint) Paint();
   1076 }
   1077 
   1078 void CFX_Edit::SetPasswordChar(FX_WORD wSubWord/* ='*' */, FX_BOOL bPaint/* = TRUE*/)
   1079 {
   1080 	m_pVT->SetPasswordChar(wSubWord);
   1081 	if (bPaint) Paint();
   1082 }
   1083 
   1084 void CFX_Edit::SetLimitChar(FX_INT32 nLimitChar/* =0 */, FX_BOOL bPaint/* = TRUE*/)
   1085 {
   1086 	m_pVT->SetLimitChar(nLimitChar);
   1087 	if (bPaint) Paint();
   1088 }
   1089 
   1090 void CFX_Edit::SetCharArray(FX_INT32 nCharArray/* =0 */, FX_BOOL bPaint/* = TRUE*/)
   1091 {
   1092 	m_pVT->SetCharArray(nCharArray);
   1093 	if (bPaint) Paint();
   1094 }
   1095 
   1096 void CFX_Edit::SetCharSpace(FX_FLOAT fCharSpace/* =0.0f */, FX_BOOL bPaint/* = TRUE*/)
   1097 {
   1098 	m_pVT->SetCharSpace(fCharSpace);
   1099 	if (bPaint) Paint();
   1100 }
   1101 
   1102 void CFX_Edit::SetHorzScale(FX_INT32 nHorzScale/* =100 */, FX_BOOL bPaint/* = TRUE*/)
   1103 {
   1104 	m_pVT->SetHorzScale(nHorzScale);
   1105 	if (bPaint) Paint();
   1106 }
   1107 
   1108 void CFX_Edit::SetMultiLine(FX_BOOL bMultiLine/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1109 {
   1110 	m_pVT->SetMultiLine(bMultiLine);
   1111 	if (bPaint) Paint();
   1112 }
   1113 
   1114 void CFX_Edit::SetAutoReturn(FX_BOOL bAuto/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1115 {
   1116 	m_pVT->SetAutoReturn(bAuto);
   1117 	if (bPaint) Paint();
   1118 }
   1119 
   1120 void CFX_Edit::SetLineLeading(FX_FLOAT fLineLeading/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1121 {
   1122 	m_pVT->SetLineLeading(fLineLeading);
   1123 	if (bPaint) Paint();
   1124 }
   1125 
   1126 void CFX_Edit::SetAutoFontSize(FX_BOOL bAuto/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1127 {
   1128 	m_pVT->SetAutoFontSize(bAuto);
   1129 	if (bPaint) Paint();
   1130 }
   1131 
   1132 void CFX_Edit::SetFontSize(FX_FLOAT fFontSize, FX_BOOL bPaint/* = TRUE*/)
   1133 {
   1134 	m_pVT->SetFontSize(fFontSize);
   1135 	if (bPaint) Paint();
   1136 }
   1137 
   1138 void CFX_Edit::SetAutoScroll(FX_BOOL bAuto/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1139 {
   1140 	m_bEnableScroll = bAuto;
   1141 	if (bPaint) Paint();
   1142 }
   1143 
   1144 void CFX_Edit::SetTextOverflow(FX_BOOL bAllowed /*= FALSE*/, FX_BOOL bPaint/* = TRUE*/)
   1145 {
   1146 	m_bEnableOverflow = bAllowed;
   1147 	if (bPaint) Paint();
   1148 }
   1149 
   1150 void CFX_Edit::SetSel(FX_INT32 nStartChar,FX_INT32 nEndChar)
   1151 {
   1152 	if (m_pVT->IsValid())
   1153 	{
   1154 		if (nStartChar == 0 && nEndChar < 0)
   1155 		{
   1156 			SelectAll();
   1157 		}
   1158 		else if (nStartChar < 0)
   1159 		{
   1160 			this->SelectNone();
   1161 		}
   1162 		else
   1163 		{
   1164 			if (nStartChar < nEndChar)
   1165 			{
   1166 				SetSel(m_pVT->WordIndexToWordPlace(nStartChar),m_pVT->WordIndexToWordPlace(nEndChar));
   1167 			}
   1168 			else
   1169 			{
   1170 				SetSel(m_pVT->WordIndexToWordPlace(nEndChar),m_pVT->WordIndexToWordPlace(nStartChar));
   1171 			}
   1172 		}
   1173 	}
   1174 }
   1175 
   1176 void CFX_Edit::SetSel(const CPVT_WordPlace & begin,const CPVT_WordPlace & end)
   1177 {
   1178 	if (m_pVT->IsValid())
   1179 	{
   1180 		SelectNone();
   1181 
   1182 		m_SelState.Set(begin,end);
   1183 
   1184 		SetCaret(m_SelState.EndPos);
   1185 
   1186 		if (m_SelState.IsExist())
   1187 		{
   1188 			ScrollToCaret();
   1189 			CPVT_WordRange wr(m_SelState.BeginPos,m_SelState.EndPos);
   1190 			Refresh(RP_OPTIONAL,&wr);
   1191 			SetCaretInfo();
   1192 		}
   1193 		else
   1194 		{
   1195 			ScrollToCaret();
   1196 			SetCaretInfo();
   1197 		}
   1198 	}
   1199 }
   1200 
   1201 void CFX_Edit::GetSel(FX_INT32 & nStartChar, FX_INT32 & nEndChar) const
   1202 {
   1203 	nStartChar = -1;
   1204 	nEndChar = -1;
   1205 
   1206 	if (m_pVT->IsValid())
   1207 	{
   1208 		if (m_SelState.IsExist())
   1209 		{
   1210 			if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
   1211 			{
   1212 				nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
   1213 				nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
   1214 			}
   1215 			else
   1216 			{
   1217 				nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
   1218 				nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
   1219 			}
   1220 		}
   1221 		else
   1222 		{
   1223 			nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
   1224 			nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
   1225 		}
   1226 	}
   1227 }
   1228 
   1229 FX_INT32 CFX_Edit::GetCaret() const
   1230 {
   1231 	if (m_pVT->IsValid())
   1232 		return m_pVT->WordPlaceToWordIndex(m_wpCaret);
   1233 
   1234 	return -1;
   1235 }
   1236 
   1237 CPVT_WordPlace CFX_Edit::GetCaretWordPlace() const
   1238 {
   1239 	return m_wpCaret;
   1240 }
   1241 
   1242 CFX_WideString CFX_Edit::GetText() const
   1243 {
   1244 	CFX_WideString swRet;
   1245 
   1246 	if (m_pVT->IsValid())
   1247 	{
   1248 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1249 		{
   1250 			FX_BOOL bRich = m_pVT->IsRichText();
   1251 
   1252 			pIterator->SetAt(0);
   1253 
   1254 			CPVT_Word wordinfo;
   1255 			CPVT_WordPlace oldplace = pIterator->GetAt();
   1256 			while (pIterator->NextWord())
   1257 			{
   1258 				CPVT_WordPlace place = pIterator->GetAt();
   1259 
   1260 				if (pIterator->GetWord(wordinfo))
   1261 				{
   1262 					if (bRich)
   1263 					{
   1264 						swRet += wordinfo.Word;
   1265 					}
   1266 					else
   1267 					{
   1268 						swRet += wordinfo.Word;
   1269 					}
   1270 				}
   1271 
   1272 				if (oldplace.SecCmp(place) != 0)
   1273 				{
   1274 					swRet += 0x0D;
   1275 					swRet += 0x0A;
   1276 				}
   1277 
   1278 				oldplace = place;
   1279 			}
   1280 		}
   1281 	}
   1282 
   1283 	return swRet;
   1284 }
   1285 
   1286 CFX_WideString CFX_Edit::GetRangeText(const CPVT_WordRange & range) const
   1287 {
   1288 	CFX_WideString swRet;
   1289 
   1290 	if (m_pVT->IsValid())
   1291 	{
   1292 		FX_BOOL bRich = m_pVT->IsRichText();
   1293 
   1294 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1295 		{
   1296 			CPVT_WordRange wrTemp = range;
   1297 			m_pVT->UpdateWordPlace(wrTemp.BeginPos);
   1298 			m_pVT->UpdateWordPlace(wrTemp.EndPos);
   1299 			pIterator->SetAt(wrTemp.BeginPos);
   1300 
   1301 			CPVT_Word wordinfo;
   1302 			CPVT_WordPlace oldplace = wrTemp.BeginPos;
   1303 			while (pIterator->NextWord())
   1304 			{
   1305 				CPVT_WordPlace place = pIterator->GetAt();
   1306 				if (place.WordCmp(wrTemp.EndPos) > 0)break;
   1307 
   1308 				if (pIterator->GetWord(wordinfo))
   1309 				{
   1310 					if (bRich)
   1311 					{
   1312 						swRet += wordinfo.Word;
   1313 					}
   1314 					else
   1315 					{
   1316 						swRet += wordinfo.Word;
   1317 					}
   1318 				}
   1319 
   1320 				if (oldplace.SecCmp(place) != 0)
   1321 				{
   1322 					swRet += 0x0D;
   1323 					swRet += 0x0A;
   1324 				}
   1325 
   1326 				oldplace = place;
   1327 			}
   1328 		}
   1329 	}
   1330 
   1331 	return swRet;
   1332 }
   1333 
   1334 CFX_WideString CFX_Edit::GetSelText() const
   1335 {
   1336 	return GetRangeText(m_SelState.ConvertToWordRange());
   1337 }
   1338 
   1339 FX_INT32 CFX_Edit::GetTotalWords() const
   1340 {
   1341 	return m_pVT->GetTotalWords();
   1342 }
   1343 
   1344 FX_INT32 CFX_Edit::GetTotalLines() const
   1345 {
   1346 	FX_INT32 nLines = 0;
   1347 
   1348 	if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1349 	{
   1350 		pIterator->SetAt(0);
   1351 		while (pIterator->NextLine())
   1352 			nLines++;
   1353 	}
   1354 
   1355 	return nLines+1;
   1356 }
   1357 
   1358 CPVT_WordRange CFX_Edit::GetSelectWordRange() const
   1359 {
   1360 	return m_SelState.ConvertToWordRange();
   1361 }
   1362 
   1363 CPVT_WordRange CFX_Edit::CombineWordRange(const CPVT_WordRange & wr1, const CPVT_WordRange & wr2)
   1364 {
   1365 	CPVT_WordRange wrRet;
   1366 
   1367 	if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0)
   1368 	{
   1369 		wrRet.BeginPos = wr1.BeginPos;
   1370 	}
   1371 	else
   1372 	{
   1373 		wrRet.BeginPos = wr2.BeginPos;
   1374 	}
   1375 
   1376 	if (wr1.EndPos.WordCmp(wr2.EndPos) < 0)
   1377 	{
   1378 		wrRet.EndPos = wr2.EndPos;
   1379 	}
   1380 	else
   1381 	{
   1382 		wrRet.EndPos = wr1.EndPos;
   1383 	}
   1384 
   1385 	return wrRet;
   1386 }
   1387 
   1388 FX_BOOL	CFX_Edit::IsRichText() const
   1389 {
   1390 	return m_pVT->IsRichText();
   1391 }
   1392 
   1393 void CFX_Edit::SetRichText(FX_BOOL bRichText/* =TRUE */, FX_BOOL bPaint/* = TRUE*/)
   1394 {
   1395 	m_pVT->SetRichText(bRichText);
   1396 	if (bPaint) Paint();
   1397 }
   1398 
   1399 FX_BOOL CFX_Edit::SetRichFontIndex(FX_INT32 nFontIndex)
   1400 {
   1401 	CPVT_WordProps WordProps;
   1402 	WordProps.nFontIndex = nFontIndex;
   1403 	return SetRichTextProps(EP_FONTINDEX,NULL,&WordProps);
   1404 }
   1405 
   1406 FX_BOOL CFX_Edit::SetRichFontSize(FX_FLOAT fFontSize)
   1407 {
   1408 	CPVT_WordProps WordProps;
   1409 	WordProps.fFontSize = fFontSize;
   1410 	return SetRichTextProps(EP_FONTSIZE,NULL,&WordProps);
   1411 }
   1412 
   1413 FX_BOOL CFX_Edit::SetRichTextColor(FX_COLORREF dwColor)
   1414 {
   1415 	CPVT_WordProps WordProps;
   1416 	WordProps.dwWordColor = dwColor;
   1417 	return SetRichTextProps(EP_WORDCOLOR,NULL,&WordProps);
   1418 }
   1419 
   1420 FX_BOOL CFX_Edit::SetRichTextScript(FX_INT32 nScriptType)
   1421 {
   1422 	CPVT_WordProps WordProps;
   1423 	WordProps.nScriptType = nScriptType;
   1424 	return SetRichTextProps(EP_SCRIPTTYPE,NULL,&WordProps);
   1425 }
   1426 
   1427 FX_BOOL CFX_Edit::SetRichTextBold(FX_BOOL bBold)
   1428 {
   1429 	CPVT_WordProps WordProps;
   1430 	if (bBold)
   1431 		WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
   1432 	return SetRichTextProps(EP_BOLD,NULL,&WordProps);
   1433 }
   1434 
   1435 FX_BOOL CFX_Edit::SetRichTextItalic(FX_BOOL bItalic)
   1436 {
   1437 	CPVT_WordProps WordProps;
   1438 	if (bItalic)
   1439 		WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
   1440 	return SetRichTextProps(EP_ITALIC,NULL,&WordProps);
   1441 }
   1442 
   1443 FX_BOOL CFX_Edit::SetRichTextUnderline(FX_BOOL bUnderline)
   1444 {
   1445 	CPVT_WordProps WordProps;
   1446 	if (bUnderline)
   1447 		WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
   1448 	return SetRichTextProps(EP_UNDERLINE,NULL,&WordProps);
   1449 }
   1450 
   1451 FX_BOOL CFX_Edit::SetRichTextCrossout(FX_BOOL bCrossout)
   1452 {
   1453 	CPVT_WordProps WordProps;
   1454 	if (bCrossout)
   1455 		WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
   1456 	return SetRichTextProps(EP_CROSSOUT,NULL,&WordProps);
   1457 }
   1458 
   1459 FX_BOOL CFX_Edit::SetRichTextCharSpace(FX_FLOAT fCharSpace)
   1460 {
   1461 	CPVT_WordProps WordProps;
   1462 	WordProps.fCharSpace = fCharSpace;
   1463 	return SetRichTextProps(EP_CHARSPACE,NULL,&WordProps);
   1464 }
   1465 
   1466 FX_BOOL CFX_Edit::SetRichTextHorzScale(FX_INT32 nHorzScale /*= 100*/)
   1467 {
   1468 	CPVT_WordProps WordProps;
   1469 	WordProps.nHorzScale = nHorzScale;
   1470 	return SetRichTextProps(EP_HORZSCALE,NULL,&WordProps);
   1471 }
   1472 
   1473 FX_BOOL CFX_Edit::SetRichTextLineLeading(FX_FLOAT fLineLeading)
   1474 {
   1475 	CPVT_SecProps SecProps;
   1476 	SecProps.fLineLeading = fLineLeading;
   1477 	return SetRichTextProps(EP_LINELEADING,&SecProps,NULL);
   1478 }
   1479 
   1480 FX_BOOL CFX_Edit::SetRichTextLineIndent(FX_FLOAT fLineIndent)
   1481 {
   1482 	CPVT_SecProps SecProps;
   1483 	SecProps.fLineIndent = fLineIndent;
   1484 	return SetRichTextProps(EP_LINEINDENT,&SecProps,NULL);
   1485 }
   1486 
   1487 FX_BOOL	CFX_Edit::SetRichTextAlignment(FX_INT32 nAlignment)
   1488 {
   1489 	CPVT_SecProps SecProps;
   1490 	SecProps.nAlignment = nAlignment;
   1491 	return SetRichTextProps(EP_ALIGNMENT,&SecProps,NULL);
   1492 }
   1493 
   1494 FX_BOOL CFX_Edit::SetRichTextProps(EDIT_PROPS_E eProps, const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps)
   1495 {
   1496 	FX_BOOL bSet = FALSE;
   1497 	FX_BOOL bSet1,bSet2;
   1498 	if (m_pVT->IsValid() && m_pVT->IsRichText())
   1499 	{
   1500 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1501 		{
   1502 			CPVT_WordRange wrTemp = m_SelState.ConvertToWordRange();
   1503 
   1504 			m_pVT->UpdateWordPlace(wrTemp.BeginPos);
   1505 			m_pVT->UpdateWordPlace(wrTemp.EndPos);
   1506 			pIterator->SetAt(wrTemp.BeginPos);
   1507 
   1508 			BeginGroupUndo(L"");;
   1509 
   1510 			bSet = SetSecProps(eProps,wrTemp.BeginPos,pSecProps,pWordProps,wrTemp,TRUE);
   1511 
   1512 			while (pIterator->NextWord())
   1513 			{
   1514 				CPVT_WordPlace place = pIterator->GetAt();
   1515 				if (place.WordCmp(wrTemp.EndPos) > 0) break;
   1516 				bSet1 = SetSecProps(eProps,place,pSecProps,pWordProps,wrTemp,TRUE);
   1517 				bSet2 = SetWordProps(eProps,place,pWordProps,wrTemp,TRUE);
   1518 
   1519 				if (!bSet)
   1520 					bSet = (bSet1 || bSet2);
   1521 			}
   1522 
   1523 			EndGroupUndo();
   1524 
   1525 			if (bSet)
   1526 			{
   1527 				PaintSetProps(eProps,wrTemp);
   1528 			}
   1529 		}
   1530 	}
   1531 
   1532 	return bSet;
   1533 }
   1534 
   1535 void CFX_Edit::PaintSetProps(EDIT_PROPS_E eProps, const CPVT_WordRange & wr)
   1536 {
   1537 	switch(eProps)
   1538 	{
   1539 	case EP_LINELEADING:
   1540 	case EP_LINEINDENT:
   1541 	case EP_ALIGNMENT:
   1542 		RearrangePart(wr);
   1543 		ScrollToCaret();
   1544 		Refresh(RP_ANALYSE);
   1545 		SetCaretOrigin();
   1546 		SetCaretInfo();
   1547 		break;
   1548 	case EP_WORDCOLOR:
   1549 	case EP_UNDERLINE:
   1550 	case EP_CROSSOUT:
   1551 		Refresh(RP_OPTIONAL,&wr);
   1552 		break;
   1553 	case EP_FONTINDEX:
   1554 	case EP_FONTSIZE:
   1555 	case EP_SCRIPTTYPE:
   1556 	case EP_CHARSPACE:
   1557 	case EP_HORZSCALE:
   1558 	case EP_BOLD:
   1559 	case EP_ITALIC:
   1560 		RearrangePart(wr);
   1561 		ScrollToCaret();
   1562 
   1563 		CPVT_WordRange wrRefresh(m_pVT->GetSectionBeginPlace(wr.BeginPos),
   1564 			m_pVT->GetSectionEndPlace(wr.EndPos));
   1565 		Refresh(RP_ANALYSE,&wrRefresh);
   1566 
   1567 		SetCaretOrigin();
   1568 		SetCaretInfo();
   1569 		break;
   1570 	}
   1571 }
   1572 
   1573 FX_BOOL CFX_Edit::SetSecProps(EDIT_PROPS_E eProps, const CPVT_WordPlace & place,
   1574 							   const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps,
   1575 							   const CPVT_WordRange & wr, FX_BOOL bAddUndo)
   1576 {
   1577 	if (m_pVT->IsValid() && m_pVT->IsRichText())
   1578 	{
   1579 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1580 		{
   1581 			FX_BOOL bSet = FALSE;
   1582 			CPVT_Section secinfo;
   1583 			CPVT_Section OldSecinfo;
   1584 
   1585 			CPVT_WordPlace oldplace = pIterator->GetAt();
   1586 
   1587 			if (eProps == EP_LINELEADING || eProps == EP_LINEINDENT || eProps == EP_ALIGNMENT)
   1588 			{
   1589 				if (pSecProps)
   1590 				{
   1591 					pIterator->SetAt(place);
   1592 					if (pIterator->GetSection(secinfo))
   1593 					{
   1594 						if (bAddUndo) OldSecinfo = secinfo;
   1595 
   1596 						switch(eProps)
   1597 						{
   1598 						case EP_LINELEADING:
   1599 							if (!FX_EDIT_IsFloatEqual(secinfo.SecProps.fLineLeading,pSecProps->fLineLeading))
   1600 							{
   1601 								secinfo.SecProps.fLineLeading = pSecProps->fLineLeading;
   1602 								bSet = TRUE;
   1603 							}
   1604 							break;
   1605 						case EP_LINEINDENT:
   1606 							if (!FX_EDIT_IsFloatEqual(secinfo.SecProps.fLineIndent,pSecProps->fLineIndent))
   1607 							{
   1608 								secinfo.SecProps.fLineIndent = pSecProps->fLineIndent;
   1609 								bSet = TRUE;
   1610 							}
   1611 							break;
   1612 						case EP_ALIGNMENT:
   1613 							if (secinfo.SecProps.nAlignment != pSecProps->nAlignment)
   1614 							{
   1615 								secinfo.SecProps.nAlignment = pSecProps->nAlignment;
   1616 								bSet = TRUE;
   1617 							}
   1618 							break;
   1619 						default:
   1620 							break;
   1621 						}
   1622 					}
   1623 				}
   1624 			}
   1625 			else
   1626 			{
   1627 				if (pWordProps && place == m_pVT->GetSectionBeginPlace(place))
   1628 				{
   1629 					pIterator->SetAt(place);
   1630 					if (pIterator->GetSection(secinfo))
   1631 					{
   1632 						if (bAddUndo) OldSecinfo = secinfo;
   1633 
   1634 						switch(eProps)
   1635 						{
   1636 						case EP_FONTINDEX:
   1637 							if (secinfo.WordProps.nFontIndex != pWordProps->nFontIndex)
   1638 							{
   1639 								secinfo.WordProps.nFontIndex = pWordProps->nFontIndex;
   1640 								bSet = TRUE;
   1641 							}
   1642 							break;
   1643 						case EP_FONTSIZE:
   1644 							if (!FX_EDIT_IsFloatEqual(secinfo.WordProps.fFontSize,pWordProps->fFontSize))
   1645 							{
   1646 								secinfo.WordProps.fFontSize = pWordProps->fFontSize;
   1647 								bSet = TRUE;
   1648 							}
   1649 							break;
   1650 						case EP_WORDCOLOR:
   1651 							if (secinfo.WordProps.dwWordColor != pWordProps->dwWordColor)
   1652 							{
   1653 								secinfo.WordProps.dwWordColor = pWordProps->dwWordColor;
   1654 								bSet = TRUE;
   1655 							}
   1656 							break;
   1657 						case EP_SCRIPTTYPE:
   1658 							if (secinfo.WordProps.nScriptType != pWordProps->nScriptType)
   1659 							{
   1660 								secinfo.WordProps.nScriptType = pWordProps->nScriptType;
   1661 								bSet = TRUE;
   1662 							}
   1663 							break;
   1664 						case EP_CHARSPACE:
   1665 							if (!FX_EDIT_IsFloatEqual(secinfo.WordProps.fCharSpace,pWordProps->fCharSpace))
   1666 							{
   1667 								secinfo.WordProps.fCharSpace = pWordProps->fCharSpace;
   1668 								bSet = TRUE;
   1669 							}
   1670 							break;
   1671 						case EP_HORZSCALE:
   1672 							if (secinfo.WordProps.nHorzScale != pWordProps->nHorzScale)
   1673 							{
   1674 								secinfo.WordProps.nHorzScale = pWordProps->nHorzScale;
   1675 								bSet = TRUE;
   1676 							}
   1677 							break;
   1678 						case EP_UNDERLINE:
   1679 							if (pWordProps->nWordStyle & PVTWORD_STYLE_UNDERLINE)
   1680 							{
   1681 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) == 0)
   1682 								{
   1683 									secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
   1684 									bSet = TRUE;
   1685 								}
   1686 							}
   1687 							else
   1688 							{
   1689 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) != 0)
   1690 								{
   1691 									secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_UNDERLINE;
   1692 									bSet = TRUE;
   1693 								}
   1694 							}
   1695 							break;
   1696 						case EP_CROSSOUT:
   1697 							if (pWordProps->nWordStyle & PVTWORD_STYLE_CROSSOUT)
   1698 							{
   1699 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) == 0)
   1700 								{
   1701 									secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
   1702 									bSet = TRUE;
   1703 								}
   1704 							}
   1705 							else
   1706 							{
   1707 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) != 0)
   1708 								{
   1709 									secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_CROSSOUT;
   1710 									bSet = TRUE;
   1711 								}
   1712 							}
   1713 							break;
   1714 						case EP_BOLD:
   1715 							if (pWordProps->nWordStyle & PVTWORD_STYLE_BOLD)
   1716 							{
   1717 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) == 0)
   1718 								{
   1719 									secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
   1720 									bSet = TRUE;
   1721 								}
   1722 							}
   1723 							else
   1724 							{
   1725 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) != 0)
   1726 								{
   1727 									secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_BOLD;
   1728 									bSet = TRUE;
   1729 								}
   1730 							}
   1731 							break;
   1732 						case EP_ITALIC:
   1733 							if (pWordProps->nWordStyle & PVTWORD_STYLE_ITALIC)
   1734 							{
   1735 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) == 0)
   1736 								{
   1737 									secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
   1738 									bSet = TRUE;
   1739 								}
   1740 							}
   1741 							else
   1742 							{
   1743 								if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) != 0)
   1744 								{
   1745 									secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_ITALIC;
   1746 									bSet = TRUE;
   1747 								}
   1748 							}
   1749 							break;
   1750 						default:
   1751 							break;
   1752 						}
   1753 					}
   1754 				}
   1755 			}
   1756 
   1757 			if (bSet)
   1758 			{
   1759 				pIterator->SetSection(secinfo);
   1760 
   1761 				if (bAddUndo && m_bEnableUndo)
   1762 				{
   1763 					AddEditUndoItem(new CFXEU_SetSecProps
   1764 						(this,place,eProps,OldSecinfo.SecProps,OldSecinfo.WordProps,secinfo.SecProps,secinfo.WordProps,wr));
   1765 				}
   1766 			}
   1767 
   1768 			pIterator->SetAt(oldplace);
   1769 
   1770 			return bSet;
   1771 		}
   1772 	}
   1773 
   1774 	return FALSE;
   1775 }
   1776 
   1777 FX_BOOL CFX_Edit::SetWordProps(EDIT_PROPS_E eProps, const CPVT_WordPlace & place,
   1778 								const CPVT_WordProps * pWordProps, const CPVT_WordRange & wr, FX_BOOL bAddUndo)
   1779 {
   1780 	if (m_pVT->IsValid() && m_pVT->IsRichText())
   1781 	{
   1782 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   1783 		{
   1784 			FX_BOOL bSet = FALSE;
   1785 			CPVT_Word wordinfo;
   1786 			CPVT_Word OldWordinfo;
   1787 
   1788 			CPVT_WordPlace oldplace = pIterator->GetAt();
   1789 
   1790 			if (pWordProps)
   1791 			{
   1792 				pIterator->SetAt(place);
   1793 				if (pIterator->GetWord(wordinfo))
   1794 				{
   1795 					if (bAddUndo) OldWordinfo = wordinfo;
   1796 
   1797 					switch(eProps)
   1798 					{
   1799 					case EP_FONTINDEX:
   1800 						if (wordinfo.WordProps.nFontIndex != pWordProps->nFontIndex)
   1801 						{
   1802 							if (IFX_Edit_FontMap* pFontMap = this->GetFontMap())
   1803 							{
   1804 								wordinfo.WordProps.nFontIndex = pFontMap->GetWordFontIndex(wordinfo.Word,wordinfo.nCharset,pWordProps->nFontIndex);
   1805 							}
   1806 							bSet = TRUE;
   1807 						}
   1808 						break;
   1809 					case EP_FONTSIZE:
   1810 						if (!FX_EDIT_IsFloatEqual(wordinfo.WordProps.fFontSize,pWordProps->fFontSize))
   1811 						{
   1812 							wordinfo.WordProps.fFontSize = pWordProps->fFontSize;
   1813 							bSet = TRUE;
   1814 						}
   1815 						break;
   1816 					case EP_WORDCOLOR:
   1817 						if (wordinfo.WordProps.dwWordColor != pWordProps->dwWordColor)
   1818 						{
   1819 							wordinfo.WordProps.dwWordColor = pWordProps->dwWordColor;
   1820 							bSet = TRUE;
   1821 						}
   1822 						break;
   1823 					case EP_SCRIPTTYPE:
   1824 						if (wordinfo.WordProps.nScriptType != pWordProps->nScriptType)
   1825 						{
   1826 							wordinfo.WordProps.nScriptType = pWordProps->nScriptType;
   1827 							bSet = TRUE;
   1828 						}
   1829 						break;
   1830 					case EP_CHARSPACE:
   1831 						if (!FX_EDIT_IsFloatEqual(wordinfo.WordProps.fCharSpace,pWordProps->fCharSpace))
   1832 						{
   1833 							wordinfo.WordProps.fCharSpace = pWordProps->fCharSpace;
   1834 							bSet = TRUE;
   1835 						}
   1836 						break;
   1837 					case EP_HORZSCALE:
   1838 						if (wordinfo.WordProps.nHorzScale != pWordProps->nHorzScale)
   1839 						{
   1840 							wordinfo.WordProps.nHorzScale = pWordProps->nHorzScale;
   1841 							bSet = TRUE;
   1842 						}
   1843 						break;
   1844 					case EP_UNDERLINE:
   1845 						if (pWordProps->nWordStyle & PVTWORD_STYLE_UNDERLINE)
   1846 						{
   1847 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) == 0)
   1848 							{
   1849 								wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
   1850 								bSet = TRUE;
   1851 							}
   1852 						}
   1853 						else
   1854 						{
   1855 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) != 0)
   1856 							{
   1857 								wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_UNDERLINE;
   1858 								bSet = TRUE;
   1859 							}
   1860 						}
   1861 						break;
   1862 					case EP_CROSSOUT:
   1863 						if (pWordProps->nWordStyle & PVTWORD_STYLE_CROSSOUT)
   1864 						{
   1865 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) == 0)
   1866 							{
   1867 								wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
   1868 								bSet = TRUE;
   1869 							}
   1870 						}
   1871 						else
   1872 						{
   1873 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) != 0)
   1874 							{
   1875 								wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_CROSSOUT;
   1876 								bSet = TRUE;
   1877 							}
   1878 						}
   1879 						break;
   1880 					case EP_BOLD:
   1881 						if (pWordProps->nWordStyle & PVTWORD_STYLE_BOLD)
   1882 						{
   1883 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) == 0)
   1884 							{
   1885 								wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
   1886 								bSet = TRUE;
   1887 							}
   1888 						}
   1889 						else
   1890 						{
   1891 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) != 0)
   1892 							{
   1893 								wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_BOLD;
   1894 								bSet = TRUE;
   1895 							}
   1896 						}
   1897 						break;
   1898 					case EP_ITALIC:
   1899 						if (pWordProps->nWordStyle & PVTWORD_STYLE_ITALIC)
   1900 						{
   1901 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) == 0)
   1902 							{
   1903 								wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
   1904 								bSet = TRUE;
   1905 							}
   1906 						}
   1907 						else
   1908 						{
   1909 							if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) != 0)
   1910 							{
   1911 								wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_ITALIC;
   1912 								bSet = TRUE;
   1913 							}
   1914 						}
   1915 						break;
   1916 					default:
   1917 						break;
   1918 					}
   1919 				}
   1920 			}
   1921 
   1922 			if (bSet)
   1923 			{
   1924 				pIterator->SetWord(wordinfo);
   1925 
   1926 				if (bAddUndo && m_bEnableUndo)
   1927 				{
   1928 					AddEditUndoItem(new CFXEU_SetWordProps
   1929 						(this,place,eProps,OldWordinfo.WordProps,wordinfo.WordProps,wr));
   1930 				}
   1931 			}
   1932 
   1933 			pIterator->SetAt(oldplace);
   1934 			return bSet;
   1935 		}
   1936 	}
   1937 
   1938 	return FALSE;
   1939 }
   1940 
   1941 void CFX_Edit::SetText(FX_LPCWSTR text,FX_INT32 charset /*= DEFAULT_CHARSET*/,
   1942 						const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
   1943 {
   1944 	SetText(text,charset,pSecProps,pWordProps,TRUE,TRUE);
   1945 }
   1946 
   1947 FX_BOOL CFX_Edit::InsertWord(FX_WORD word, FX_INT32 charset /*= DEFAULT_CHARSET*/, const CPVT_WordProps * pWordProps /*= NULL*/)
   1948 {
   1949 	return InsertWord(word,charset,pWordProps,TRUE,TRUE);
   1950 }
   1951 
   1952 FX_BOOL CFX_Edit::InsertReturn(const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
   1953 {
   1954 	return InsertReturn(pSecProps,pWordProps,TRUE,TRUE);
   1955 }
   1956 
   1957 FX_BOOL CFX_Edit::Backspace()
   1958 {
   1959 	return Backspace(TRUE,TRUE);
   1960 }
   1961 
   1962 FX_BOOL CFX_Edit::Delete()
   1963 {
   1964 	return Delete(TRUE,TRUE);
   1965 }
   1966 
   1967 FX_BOOL CFX_Edit::Clear()
   1968 {
   1969 	return Clear(TRUE,TRUE);
   1970 }
   1971 
   1972 FX_BOOL CFX_Edit::InsertText(FX_LPCWSTR text, FX_INT32 charset /*= DEFAULT_CHARSET*/,
   1973 								const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
   1974 {
   1975 	return InsertText(text,charset,pSecProps,pWordProps,TRUE,TRUE);
   1976 }
   1977 
   1978 FX_FLOAT CFX_Edit::GetFontSize() const
   1979 {
   1980 	return m_pVT->GetFontSize();
   1981 }
   1982 
   1983 FX_WORD CFX_Edit::GetPasswordChar() const
   1984 {
   1985 	return m_pVT->GetPasswordChar();
   1986 }
   1987 
   1988 FX_INT32 CFX_Edit::GetCharArray() const
   1989 {
   1990 	return m_pVT->GetCharArray();
   1991 }
   1992 
   1993 CPDF_Rect CFX_Edit::GetPlateRect() const
   1994 {
   1995 	return m_pVT->GetPlateRect();
   1996 }
   1997 
   1998 CPDF_Rect CFX_Edit::GetContentRect() const
   1999 {
   2000 	return VTToEdit(m_pVT->GetContentRect());
   2001 }
   2002 
   2003 FX_INT32 CFX_Edit::GetHorzScale() const
   2004 {
   2005 	return m_pVT->GetHorzScale();
   2006 }
   2007 
   2008 FX_FLOAT CFX_Edit::GetCharSpace() const
   2009 {
   2010 	return m_pVT->GetCharSpace();
   2011 }
   2012 
   2013 // inner methods
   2014 
   2015 CPVT_WordRange CFX_Edit::GetWholeWordRange() const
   2016 {
   2017 	if (m_pVT->IsValid())
   2018 		return CPVT_WordRange(m_pVT->GetBeginWordPlace(),m_pVT->GetEndWordPlace());
   2019 
   2020 	return CPVT_WordRange();
   2021 }
   2022 
   2023 CPVT_WordRange CFX_Edit::GetVisibleWordRange() const
   2024 {
   2025 	if (m_bEnableOverflow) return GetWholeWordRange();
   2026 
   2027 	if (m_pVT->IsValid())
   2028 	{
   2029 		CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2030 
   2031 		CPVT_WordPlace place1 = m_pVT->SearchWordPlace(EditToVT(CPDF_Point(rcPlate.left,rcPlate.top)));
   2032 		CPVT_WordPlace place2 = m_pVT->SearchWordPlace(EditToVT(CPDF_Point(rcPlate.right,rcPlate.bottom)));
   2033 
   2034 		return CPVT_WordRange(place1,place2);
   2035 	}
   2036 
   2037 	return CPVT_WordRange();
   2038 }
   2039 
   2040 CPVT_WordPlace CFX_Edit::SearchWordPlace(const CPDF_Point& point) const
   2041 {
   2042 	if (m_pVT->IsValid())
   2043 	{
   2044 		return m_pVT->SearchWordPlace(EditToVT(point));
   2045 	}
   2046 
   2047 	return CPVT_WordPlace();
   2048 }
   2049 
   2050 void CFX_Edit::Paint()
   2051 {
   2052 	if (m_pVT->IsValid())
   2053 	{
   2054 		RearrangeAll();
   2055 		ScrollToCaret();
   2056 		Refresh(RP_NOANALYSE);
   2057 		SetCaretOrigin();
   2058 		SetCaretInfo();
   2059 	}
   2060 }
   2061 
   2062 void CFX_Edit::RearrangeAll()
   2063 {
   2064 	if (m_pVT->IsValid())
   2065 	{
   2066 		m_pVT->UpdateWordPlace(m_wpCaret);
   2067 		m_pVT->RearrangeAll();
   2068 		m_pVT->UpdateWordPlace(m_wpCaret);
   2069 		SetScrollInfo();
   2070 		SetContentChanged();
   2071 	}
   2072 }
   2073 
   2074 void CFX_Edit::RearrangePart(const CPVT_WordRange & range)
   2075 {
   2076 	if (m_pVT->IsValid())
   2077 	{
   2078 		m_pVT->UpdateWordPlace(m_wpCaret);
   2079 		m_pVT->RearrangePart(range);
   2080 		m_pVT->UpdateWordPlace(m_wpCaret);
   2081 		SetScrollInfo();
   2082 		SetContentChanged();
   2083 	}
   2084 }
   2085 
   2086 void CFX_Edit::SetContentChanged()
   2087 {
   2088 	if (m_bNotify && m_pNotify)
   2089 	{
   2090 		CPDF_Rect rcContent = m_pVT->GetContentRect();
   2091 		if (rcContent.Width() != m_rcOldContent.Width() ||
   2092 			rcContent.Height() != m_rcOldContent.Height())
   2093 		{
   2094 			if (!m_bNotifyFlag)
   2095 			{
   2096 				m_bNotifyFlag = TRUE;
   2097 				m_pNotify->IOnContentChange(rcContent);
   2098 				m_bNotifyFlag = FALSE;
   2099 			}
   2100 			m_rcOldContent = rcContent;
   2101 		}
   2102 	}
   2103 }
   2104 
   2105 void CFX_Edit::SelectAll()
   2106 {
   2107 	if (m_pVT->IsValid())
   2108 	{
   2109 		m_SelState = GetWholeWordRange();
   2110 		SetCaret(m_SelState.EndPos);
   2111 
   2112 		ScrollToCaret();
   2113 		CPVT_WordRange wrVisible = GetVisibleWordRange();
   2114 		Refresh(RP_OPTIONAL,&wrVisible);
   2115 		SetCaretInfo();
   2116 	}
   2117 }
   2118 
   2119 void CFX_Edit::SelectNone()
   2120 {
   2121 	if (m_pVT->IsValid())
   2122 	{
   2123 		if (m_SelState.IsExist())
   2124 		{
   2125 			CPVT_WordRange wrTemp = m_SelState.ConvertToWordRange();
   2126 			m_SelState.Default();
   2127 			Refresh(RP_OPTIONAL,&wrTemp);
   2128 		}
   2129 	}
   2130 }
   2131 
   2132 FX_BOOL	CFX_Edit::IsSelected() const
   2133 {
   2134 	return m_SelState.IsExist();
   2135 }
   2136 
   2137 CPDF_Point CFX_Edit::VTToEdit(const CPDF_Point & point) const
   2138 {
   2139 	CPDF_Rect rcContent = m_pVT->GetContentRect();
   2140 	CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2141 
   2142 	FX_FLOAT fPadding = 0.0f;
   2143 
   2144 	switch (m_nAlignment)
   2145 	{
   2146 	case 0:
   2147 		fPadding = 0.0f;
   2148 		break;
   2149 	case 1:
   2150 		fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
   2151 		break;
   2152 	case 2:
   2153 		fPadding = rcPlate.Height() - rcContent.Height();
   2154 		break;
   2155 	}
   2156 
   2157 	return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left),
   2158 		point.y - (m_ptScrollPos.y + fPadding - rcPlate.top));
   2159 }
   2160 
   2161 CPDF_Point CFX_Edit::EditToVT(const CPDF_Point & point) const
   2162 {
   2163 	CPDF_Rect rcContent = m_pVT->GetContentRect();
   2164 	CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2165 
   2166 	FX_FLOAT fPadding = 0.0f;
   2167 
   2168 	switch (m_nAlignment)
   2169 	{
   2170 	case 0:
   2171 		fPadding = 0.0f;
   2172 		break;
   2173 	case 1:
   2174 		fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
   2175 		break;
   2176 	case 2:
   2177 		fPadding = rcPlate.Height() - rcContent.Height();
   2178 		break;
   2179 	}
   2180 
   2181 	return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left),
   2182 		point.y + (m_ptScrollPos.y + fPadding - rcPlate.top));
   2183 }
   2184 
   2185 CPDF_Rect CFX_Edit::VTToEdit(const CPDF_Rect & rect) const
   2186 {
   2187 	CPDF_Point ptLeftBottom = VTToEdit(CPDF_Point(rect.left,rect.bottom));
   2188 	CPDF_Point ptRightTop = VTToEdit(CPDF_Point(rect.right,rect.top));
   2189 
   2190 	return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
   2191 }
   2192 
   2193 CPDF_Rect CFX_Edit::EditToVT(const CPDF_Rect & rect) const
   2194 {
   2195 	CPDF_Point ptLeftBottom = EditToVT(CPDF_Point(rect.left,rect.bottom));
   2196 	CPDF_Point ptRightTop = EditToVT(CPDF_Point(rect.right,rect.top));
   2197 
   2198 	return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
   2199 }
   2200 
   2201 void CFX_Edit::SetScrollInfo()
   2202 {
   2203 	if (m_bNotify && m_pNotify)
   2204 	{
   2205 		CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2206 		CPDF_Rect rcContent = m_pVT->GetContentRect();
   2207 
   2208 		if (!m_bNotifyFlag)
   2209 		{
   2210 			m_bNotifyFlag = TRUE;
   2211 			m_pNotify->IOnSetScrollInfoX(rcPlate.left, rcPlate.right,
   2212 								rcContent.left, rcContent.right, rcPlate.Width() / 3, rcPlate.Width());
   2213 
   2214 			m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
   2215 					rcContent.bottom, rcContent.top, rcPlate.Height() / 3, rcPlate.Height());
   2216 			m_bNotifyFlag = FALSE;
   2217 		}
   2218 	}
   2219 }
   2220 
   2221 void CFX_Edit::SetScrollPosX(FX_FLOAT fx)
   2222 {
   2223 	if (!m_bEnableScroll) return;
   2224 
   2225 	if (m_pVT->IsValid())
   2226 	{
   2227 		if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.x,fx))
   2228 		{
   2229 			m_ptScrollPos.x = fx;
   2230 			Refresh(RP_NOANALYSE);
   2231 
   2232 			if (m_bNotify && m_pNotify)
   2233 			{
   2234 				if (!m_bNotifyFlag)
   2235 				{
   2236 					m_bNotifyFlag = TRUE;
   2237 					m_pNotify->IOnSetScrollPosX(fx);
   2238 					m_bNotifyFlag = FALSE;
   2239 				}
   2240 			}
   2241 		}
   2242 	}
   2243 }
   2244 
   2245 void CFX_Edit::SetScrollPosY(FX_FLOAT fy)
   2246 {
   2247 	if (!m_bEnableScroll) return;
   2248 
   2249 	if (m_pVT->IsValid())
   2250 	{
   2251 		if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y,fy))
   2252 		{
   2253 			m_ptScrollPos.y = fy;
   2254 			Refresh(RP_NOANALYSE);
   2255 
   2256 			if (m_bNotify && m_pNotify)
   2257 			{
   2258 				if (!m_bNotifyFlag)
   2259 				{
   2260 					m_bNotifyFlag = TRUE;
   2261 					m_pNotify->IOnSetScrollPosY(fy);
   2262 					m_bNotifyFlag = FALSE;
   2263 				}
   2264 			}
   2265 		}
   2266 	}
   2267 }
   2268 
   2269 void CFX_Edit::SetScrollPos(const CPDF_Point & point)
   2270 {
   2271 	SetScrollPosX(point.x);
   2272 	SetScrollPosY(point.y);
   2273 	SetScrollLimit();
   2274 	SetCaretInfo();
   2275 }
   2276 
   2277 CPDF_Point CFX_Edit::GetScrollPos() const
   2278 {
   2279 	return m_ptScrollPos;
   2280 }
   2281 
   2282 void CFX_Edit::SetScrollLimit()
   2283 {
   2284 	if (m_pVT->IsValid())
   2285 	{
   2286 		CPDF_Rect rcContent = m_pVT->GetContentRect();
   2287 		CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2288 
   2289 		if (rcPlate.Width() > rcContent.Width())
   2290 		{
   2291 			SetScrollPosX(rcPlate.left);
   2292 		}
   2293 		else
   2294 		{
   2295 			if (FX_EDIT_IsFloatSmaller(m_ptScrollPos.x, rcContent.left))
   2296 			{
   2297 				SetScrollPosX(rcContent.left);
   2298 			}
   2299 			else if (FX_EDIT_IsFloatBigger(m_ptScrollPos.x, rcContent.right - rcPlate.Width()))
   2300 			{
   2301 				SetScrollPosX(rcContent.right - rcPlate.Width());
   2302 			}
   2303 		}
   2304 
   2305 		if (rcPlate.Height() > rcContent.Height())
   2306 		{
   2307 			SetScrollPosY(rcPlate.top);
   2308 		}
   2309 		else
   2310 		{
   2311 			if (FX_EDIT_IsFloatSmaller(m_ptScrollPos.y, rcContent.bottom + rcPlate.Height()))
   2312 			{
   2313 				SetScrollPosY(rcContent.bottom + rcPlate.Height());
   2314 			}
   2315 			else if (FX_EDIT_IsFloatBigger(m_ptScrollPos.y, rcContent.top))
   2316 			{
   2317 				SetScrollPosY(rcContent.top);
   2318 			}
   2319 		}
   2320 	}
   2321 }
   2322 
   2323 void CFX_Edit::ScrollToCaret()
   2324 {
   2325 	SetScrollLimit();
   2326 
   2327 	if (m_pVT->IsValid())
   2328 	{
   2329 		CPDF_Point ptHead(0,0);
   2330 		CPDF_Point ptFoot(0,0);
   2331 
   2332 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2333 		{
   2334 			pIterator->SetAt(m_wpCaret);
   2335 
   2336 			CPVT_Word word;
   2337 			CPVT_Line line;
   2338 			if (pIterator->GetWord(word))
   2339 			{
   2340 				ptHead.x = word.ptWord.x + word.fWidth;
   2341 				ptHead.y = word.ptWord.y + word.fAscent;
   2342 				ptFoot.x = word.ptWord.x + word.fWidth;
   2343 				ptFoot.y = word.ptWord.y + word.fDescent;
   2344 			}
   2345 			else if (pIterator->GetLine(line))
   2346 			{
   2347 				ptHead.x = line.ptLine.x;
   2348 				ptHead.y = line.ptLine.y + line.fLineAscent;
   2349 				ptFoot.x = line.ptLine.x;
   2350 				ptFoot.y = line.ptLine.y + line.fLineDescent;
   2351 			}
   2352 		}
   2353 
   2354 		CPDF_Point ptHeadEdit = VTToEdit(ptHead);
   2355 		CPDF_Point ptFootEdit = VTToEdit(ptFoot);
   2356 
   2357 		CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   2358 
   2359 		if (!FX_EDIT_IsFloatEqual(rcPlate.left,rcPlate.right))
   2360 		{
   2361 			if (FX_EDIT_IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
   2362 				FX_EDIT_IsFloatEqual(ptHeadEdit.x, rcPlate.left))
   2363 			{
   2364 				SetScrollPosX(ptHead.x);
   2365 			}
   2366 			else if (FX_EDIT_IsFloatBigger(ptHeadEdit.x, rcPlate.right))
   2367 			{
   2368 				SetScrollPosX(ptHead.x - rcPlate.Width());
   2369 			}
   2370 		}
   2371 
   2372 		if (!FX_EDIT_IsFloatEqual(rcPlate.top,rcPlate.bottom))
   2373 		{
   2374 			if (FX_EDIT_IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
   2375 				FX_EDIT_IsFloatEqual(ptFootEdit.y, rcPlate.bottom))
   2376 			{
   2377 				if (FX_EDIT_IsFloatSmaller(ptHeadEdit.y, rcPlate.top))
   2378 				{
   2379 					SetScrollPosY(ptFoot.y + rcPlate.Height());
   2380 				}
   2381 			}
   2382 			else if (FX_EDIT_IsFloatBigger(ptHeadEdit.y, rcPlate.top))
   2383 			{
   2384 				if (FX_EDIT_IsFloatBigger(ptFootEdit.y, rcPlate.bottom))
   2385 				{
   2386 					SetScrollPosY(ptHead.y);
   2387 				}
   2388 			}
   2389 		}
   2390 	}
   2391 }
   2392 
   2393 void CFX_Edit::Refresh(REFRESH_PLAN_E ePlan,const CPVT_WordRange * pRange1,const CPVT_WordRange * pRange2)
   2394 {
   2395 	if (m_bEnableRefresh && m_pVT->IsValid())
   2396 	{
   2397 		m_Refresh.BeginRefresh();
   2398 		RefreshPushLineRects(GetVisibleWordRange());
   2399 
   2400 // 		if (!FX_EDIT_IsFloatEqual(m_ptRefreshScrollPos.x,m_ptScrollPos.x) ||
   2401 // 			!FX_EDIT_IsFloatEqual(m_ptRefreshScrollPos.y,m_ptScrollPos.y))
   2402 // 		{
   2403 			m_Refresh.NoAnalyse();
   2404 			m_ptRefreshScrollPos = m_ptScrollPos;
   2405 // 		}
   2406 // 		else
   2407 // 		{
   2408 // 			switch (ePlan)
   2409 // 			{
   2410 // 			case RP_ANALYSE:
   2411 // 				m_Refresh.Analyse(m_pVT->GetAlignment());
   2412 //
   2413 // 				if (pRange1) RefreshPushRandomRects(*pRange1);
   2414 // 				if (pRange2) RefreshPushRandomRects(*pRange2);
   2415 // 				break;
   2416 // 			case RP_NOANALYSE:
   2417 // 				m_Refresh.NoAnalyse();
   2418 // 				break;
   2419 // 			case RP_OPTIONAL:
   2420 // 				if (pRange1) RefreshPushRandomRects(*pRange1);
   2421 // 				if (pRange2) RefreshPushRandomRects(*pRange2);
   2422 // 				break;
   2423 // 			}
   2424 // 		}
   2425 
   2426 		if (m_bNotify && m_pNotify)
   2427 		{
   2428 			if (!m_bNotifyFlag)
   2429 			{
   2430 				m_bNotifyFlag = TRUE;
   2431 				if (const CFX_Edit_RectArray * pRects = m_Refresh.GetRefreshRects())
   2432 				{
   2433 					for (FX_INT32 i = 0, sz = pRects->GetSize(); i < sz; i++)
   2434 						m_pNotify->IOnInvalidateRect(pRects->GetAt(i));
   2435 				}
   2436 				m_bNotifyFlag = FALSE;
   2437 			}
   2438 		}
   2439 
   2440 		m_Refresh.EndRefresh();
   2441 	}
   2442 }
   2443 
   2444 void CFX_Edit::RefreshPushLineRects(const CPVT_WordRange & wr)
   2445 {
   2446 	if (m_pVT->IsValid())
   2447 	{
   2448 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2449 		{
   2450 			CPVT_WordPlace wpBegin = wr.BeginPos;
   2451 			m_pVT->UpdateWordPlace(wpBegin);
   2452 			CPVT_WordPlace wpEnd = wr.EndPos;
   2453 			m_pVT->UpdateWordPlace(wpEnd);
   2454 			pIterator->SetAt(wpBegin);
   2455 
   2456 			CPVT_Line lineinfo;
   2457 			do
   2458 			{
   2459 				if (!pIterator->GetLine(lineinfo))break;
   2460 				if (lineinfo.lineplace.LineCmp(wpEnd) > 0)break;
   2461 
   2462 				CPDF_Rect rcLine(lineinfo.ptLine.x,
   2463 									lineinfo.ptLine.y + lineinfo.fLineDescent,
   2464 									lineinfo.ptLine.x + lineinfo.fLineWidth,
   2465 									lineinfo.ptLine.y + lineinfo.fLineAscent);
   2466 
   2467 				m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace,lineinfo.lineEnd),VTToEdit(rcLine));
   2468 
   2469 			}while (pIterator->NextLine());
   2470 		}
   2471 	}
   2472 }
   2473 
   2474 void CFX_Edit::RefreshPushRandomRects(const CPVT_WordRange & wr)
   2475 {
   2476 	if (m_pVT->IsValid())
   2477 	{
   2478 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2479 		{
   2480 			CPVT_WordRange wrTemp = wr;
   2481 
   2482 			m_pVT->UpdateWordPlace(wrTemp.BeginPos);
   2483 			m_pVT->UpdateWordPlace(wrTemp.EndPos);
   2484 			pIterator->SetAt(wrTemp.BeginPos);
   2485 
   2486 			CPVT_Word wordinfo;
   2487 			CPVT_Line lineinfo;
   2488 			CPVT_WordPlace place;
   2489 
   2490 			while (pIterator->NextWord())
   2491 			{
   2492 				place = pIterator->GetAt();
   2493 				if (place.WordCmp(wrTemp.EndPos) > 0) break;
   2494 
   2495 				pIterator->GetWord(wordinfo);
   2496 				pIterator->GetLine(lineinfo);
   2497 
   2498 				if (place.LineCmp(wrTemp.BeginPos) == 0 || place.LineCmp(wrTemp.EndPos) == 0)
   2499 				{
   2500 					CPDF_Rect rcWord(wordinfo.ptWord.x,
   2501 										lineinfo.ptLine.y + lineinfo.fLineDescent,
   2502 										wordinfo.ptWord.x + wordinfo.fWidth,
   2503 										lineinfo.ptLine.y + lineinfo.fLineAscent);
   2504 
   2505 					m_Refresh.AddRefresh(VTToEdit(rcWord));
   2506 				}
   2507 				else
   2508 				{
   2509 					CPDF_Rect rcLine(lineinfo.ptLine.x,
   2510 										lineinfo.ptLine.y + lineinfo.fLineDescent,
   2511 										lineinfo.ptLine.x + lineinfo.fLineWidth,
   2512 										lineinfo.ptLine.y + lineinfo.fLineAscent);
   2513 
   2514 					m_Refresh.AddRefresh(VTToEdit(rcLine));
   2515 
   2516 					pIterator->NextLine();
   2517 				}
   2518 			}
   2519 		}
   2520 	}
   2521 }
   2522 
   2523 void CFX_Edit::RefreshWordRange(const CPVT_WordRange& wr)
   2524 {
   2525 	if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2526 	{
   2527 		CPVT_WordRange wrTemp = wr;
   2528 
   2529 		m_pVT->UpdateWordPlace(wrTemp.BeginPos);
   2530 		m_pVT->UpdateWordPlace(wrTemp.EndPos);
   2531 		pIterator->SetAt(wrTemp.BeginPos);
   2532 
   2533 		CPVT_Word wordinfo;
   2534 		CPVT_Line lineinfo;
   2535 		CPVT_WordPlace place;
   2536 
   2537 		while (pIterator->NextWord())
   2538 		{
   2539 			place = pIterator->GetAt();
   2540 			if (place.WordCmp(wrTemp.EndPos) > 0) break;
   2541 
   2542 			pIterator->GetWord(wordinfo);
   2543 			pIterator->GetLine(lineinfo);
   2544 
   2545 			if (place.LineCmp(wrTemp.BeginPos) == 0 || place.LineCmp(wrTemp.EndPos) == 0)
   2546 			{
   2547 				CPDF_Rect rcWord(wordinfo.ptWord.x,
   2548 									lineinfo.ptLine.y + lineinfo.fLineDescent,
   2549 									wordinfo.ptWord.x + wordinfo.fWidth,
   2550 									lineinfo.ptLine.y + lineinfo.fLineAscent);
   2551 
   2552 				if (m_bNotify && m_pNotify)
   2553 				{
   2554 					if (!m_bNotifyFlag)
   2555 					{
   2556 						m_bNotifyFlag = TRUE;
   2557 						CPDF_Rect rcRefresh = VTToEdit(rcWord);
   2558 						m_pNotify->IOnInvalidateRect(&rcRefresh);
   2559 						m_bNotifyFlag = FALSE;
   2560 					}
   2561 				}
   2562 			}
   2563 			else
   2564 			{
   2565 				CPDF_Rect rcLine(lineinfo.ptLine.x,
   2566 									lineinfo.ptLine.y + lineinfo.fLineDescent,
   2567 									lineinfo.ptLine.x + lineinfo.fLineWidth,
   2568 									lineinfo.ptLine.y + lineinfo.fLineAscent);
   2569 
   2570 				if (m_bNotify && m_pNotify)
   2571 				{
   2572 					if (!m_bNotifyFlag)
   2573 					{
   2574 						m_bNotifyFlag = TRUE;
   2575 						CPDF_Rect rcRefresh = VTToEdit(rcLine);
   2576 						m_pNotify->IOnInvalidateRect(&rcRefresh);
   2577 						m_bNotifyFlag = FALSE;
   2578 					}
   2579 				}
   2580 
   2581 				pIterator->NextLine();
   2582 			}
   2583 		}
   2584 	}
   2585 }
   2586 
   2587 void CFX_Edit::SetCaret(const CPVT_WordPlace & place)
   2588 {
   2589 	m_wpOldCaret = m_wpCaret;
   2590 	m_wpCaret = place;
   2591 }
   2592 
   2593 void CFX_Edit::SetCaretInfo()
   2594 {
   2595 	if (m_bNotify && m_pNotify)
   2596 	{
   2597 		if (!m_bNotifyFlag)
   2598 		{
   2599 			CPDF_Point ptHead(0.0f,0.0f),ptFoot(0.0f,0.0f);
   2600 
   2601 			if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2602 			{
   2603 				pIterator->SetAt(m_wpCaret);
   2604 				CPVT_Word word;
   2605 				CPVT_Line line;
   2606 				if (pIterator->GetWord(word))
   2607 				{
   2608 					ptHead.x = word.ptWord.x + word.fWidth;
   2609 					ptHead.y = word.ptWord.y + word.fAscent;
   2610 					ptFoot.x = word.ptWord.x + word.fWidth;
   2611 					ptFoot.y = word.ptWord.y + word.fDescent;
   2612 				}
   2613 				else if (pIterator->GetLine(line))
   2614 				{
   2615 					ptHead.x = line.ptLine.x;
   2616 					ptHead.y = line.ptLine.y + line.fLineAscent;
   2617 					ptFoot.x = line.ptLine.x;
   2618 					ptFoot.y = line.ptLine.y + line.fLineDescent;
   2619 				}
   2620 			}
   2621 
   2622 			m_bNotifyFlag = TRUE;
   2623 			m_pNotify->IOnSetCaret(!m_SelState.IsExist(),VTToEdit(ptHead),VTToEdit(ptFoot), m_wpCaret);
   2624 			m_bNotifyFlag = FALSE;
   2625 		}
   2626 	}
   2627 
   2628 	SetCaretChange();
   2629 }
   2630 
   2631 void CFX_Edit::SetCaretChange()
   2632 {
   2633 	if (this->m_wpCaret == this->m_wpOldCaret) return;
   2634 
   2635 	if (m_bNotify && m_pVT->IsRichText() && m_pNotify)
   2636 	{
   2637 		CPVT_SecProps SecProps;
   2638 		CPVT_WordProps WordProps;
   2639 
   2640 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   2641 		{
   2642 			pIterator->SetAt(m_wpCaret);
   2643 			CPVT_Word word;
   2644 			CPVT_Section section;
   2645 
   2646 			if (pIterator->GetSection(section))
   2647 			{
   2648 				SecProps = section.SecProps;
   2649 				WordProps = section.WordProps;
   2650 			}
   2651 
   2652 			if (pIterator->GetWord(word))
   2653 			{
   2654 				WordProps = word.WordProps;
   2655 			}
   2656 		}
   2657 
   2658 		if (!m_bNotifyFlag)
   2659 		{
   2660 			m_bNotifyFlag = TRUE;
   2661 			m_pNotify->IOnCaretChange(SecProps,WordProps);
   2662 			m_bNotifyFlag = FALSE;
   2663 		}
   2664 	}
   2665 }
   2666 
   2667 void CFX_Edit::SetCaret(FX_INT32 nPos)
   2668 {
   2669 	if (m_pVT->IsValid())
   2670 	{
   2671 		SelectNone();
   2672 		SetCaret(m_pVT->WordIndexToWordPlace(nPos));
   2673 		m_SelState.Set(m_wpCaret,m_wpCaret);
   2674 
   2675 		ScrollToCaret();
   2676 		SetCaretOrigin();
   2677 		SetCaretInfo();
   2678 	}
   2679 }
   2680 
   2681 void CFX_Edit::OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)
   2682 {
   2683 	if (m_pVT->IsValid())
   2684 	{
   2685 		SelectNone();
   2686 		SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
   2687 		m_SelState.Set(m_wpCaret,m_wpCaret);
   2688 
   2689 		ScrollToCaret();
   2690 		SetCaretOrigin();
   2691 		SetCaretInfo();
   2692 	}
   2693 }
   2694 
   2695 void CFX_Edit::OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)
   2696 {
   2697 	if (m_pVT->IsValid())
   2698 	{
   2699 		SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
   2700 
   2701 		if (m_wpCaret != m_wpOldCaret)
   2702 		{
   2703 			m_SelState.SetEndPos(m_wpCaret);
   2704 
   2705 			ScrollToCaret();
   2706 			CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
   2707 			Refresh(RP_OPTIONAL,&wr);
   2708 			SetCaretOrigin();
   2709 			SetCaretInfo();
   2710 		}
   2711 	}
   2712 }
   2713 
   2714 void CFX_Edit::OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl)
   2715 {
   2716 	if (m_pVT->IsValid())
   2717 	{
   2718 		SetCaret(m_pVT->GetUpWordPlace(m_wpCaret,m_ptCaret));
   2719 
   2720 		if (bShift)
   2721 		{
   2722 			if (m_SelState.IsExist())
   2723 				m_SelState.SetEndPos(m_wpCaret);
   2724 			else
   2725 				m_SelState.Set(m_wpOldCaret,m_wpCaret);
   2726 
   2727 			if (m_wpOldCaret != m_wpCaret)
   2728 			{
   2729 				ScrollToCaret();
   2730 				CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
   2731 				Refresh(RP_OPTIONAL, &wr);
   2732 				SetCaretInfo();
   2733 			}
   2734 		}
   2735 		else
   2736 		{
   2737 			SelectNone();
   2738 
   2739 			ScrollToCaret();
   2740 			SetCaretInfo();
   2741 		}
   2742 	}
   2743 }
   2744 
   2745 void CFX_Edit::OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl)
   2746 {
   2747 	if (m_pVT->IsValid())
   2748 	{
   2749 		SetCaret(m_pVT->GetDownWordPlace(m_wpCaret,m_ptCaret));
   2750 
   2751 		if (bShift)
   2752 		{
   2753 			if (m_SelState.IsExist())
   2754 				m_SelState.SetEndPos(m_wpCaret);
   2755 			else
   2756 				m_SelState.Set(m_wpOldCaret,m_wpCaret);
   2757 
   2758 			if (m_wpOldCaret != m_wpCaret)
   2759 			{
   2760 				ScrollToCaret();
   2761 				CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
   2762 				Refresh(RP_OPTIONAL, &wr);
   2763 				SetCaretInfo();
   2764 			}
   2765 		}
   2766 		else
   2767 		{
   2768 			SelectNone();
   2769 
   2770 			ScrollToCaret();
   2771 			SetCaretInfo();
   2772 		}
   2773 	}
   2774 }
   2775 
   2776 void CFX_Edit::OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl)
   2777 {
   2778 	if (m_pVT->IsValid())
   2779 	{
   2780 		if (bShift)
   2781 		{
   2782 			if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
   2783 				m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
   2784 				SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
   2785 
   2786 			SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
   2787 
   2788 			if (m_SelState.IsExist())
   2789 				m_SelState.SetEndPos(m_wpCaret);
   2790 			else
   2791 				m_SelState.Set(m_wpOldCaret, m_wpCaret);
   2792 
   2793 			if (m_wpOldCaret != m_wpCaret)
   2794 			{
   2795 				ScrollToCaret();
   2796 				CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
   2797 				Refresh(RP_OPTIONAL,&wr);
   2798 				SetCaretInfo();
   2799 			}
   2800 		}
   2801 		else
   2802 		{
   2803 			if (m_SelState.IsExist())
   2804 			{
   2805 				if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
   2806 					SetCaret(m_SelState.BeginPos);
   2807 				else
   2808 					SetCaret(m_SelState.EndPos);
   2809 
   2810 				SelectNone();
   2811 				ScrollToCaret();
   2812 				SetCaretInfo();
   2813 			}
   2814 			else
   2815 			{
   2816 				if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
   2817 					m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
   2818 					SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
   2819 
   2820 				SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
   2821 
   2822 				ScrollToCaret();
   2823 				SetCaretOrigin();
   2824 				SetCaretInfo();
   2825 			}
   2826 		}
   2827 	}
   2828 }
   2829 
   2830 void CFX_Edit::OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl)
   2831 {
   2832 	if (m_pVT->IsValid())
   2833 	{
   2834 		if (bShift)
   2835 		{
   2836 			SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
   2837 
   2838 			if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
   2839 				m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
   2840 				SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
   2841 
   2842 			if (m_SelState.IsExist())
   2843 				m_SelState.SetEndPos(m_wpCaret);
   2844 			else
   2845 				m_SelState.Set(m_wpOldCaret,m_wpCaret);
   2846 
   2847 			if (m_wpOldCaret != m_wpCaret)
   2848 			{
   2849 				ScrollToCaret();
   2850 				CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
   2851 				Refresh(RP_OPTIONAL,&wr);
   2852 				SetCaretInfo();
   2853 			}
   2854 		}
   2855 		else
   2856 		{
   2857 			if (m_SelState.IsExist())
   2858 			{
   2859 				if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)>0)
   2860 					SetCaret(m_SelState.BeginPos);
   2861 				else
   2862 					SetCaret(m_SelState.EndPos);
   2863 
   2864 				SelectNone();
   2865 				ScrollToCaret();
   2866 				SetCaretInfo();
   2867 			}
   2868 			else
   2869 			{
   2870 				SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
   2871 
   2872 				if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
   2873 					m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
   2874 					SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
   2875 
   2876 				ScrollToCaret();
   2877 				SetCaretOrigin();
   2878 				SetCaretInfo();
   2879 			}
   2880 		}
   2881 	}
   2882 }
   2883 
   2884 void CFX_Edit::OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl)
   2885 {
   2886 	if (m_pVT->IsValid())
   2887 	{
   2888 		if (bShift)
   2889 		{
   2890 			if (bCtrl)
   2891 				SetCaret(m_pVT->GetBeginWordPlace());
   2892 			else
   2893 				SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
   2894 
   2895 			if (m_SelState.IsExist())
   2896 				m_SelState.SetEndPos(m_wpCaret);
   2897 			else
   2898 				m_SelState.Set(m_wpOldCaret,m_wpCaret);
   2899 
   2900 			ScrollToCaret();
   2901 			CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
   2902 			Refresh(RP_OPTIONAL, &wr);
   2903 			SetCaretInfo();
   2904 		}
   2905 		else
   2906 		{
   2907 			if (m_SelState.IsExist())
   2908 			{
   2909 				if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
   2910 					SetCaret(m_SelState.BeginPos);
   2911 				else
   2912 					SetCaret(m_SelState.EndPos);
   2913 
   2914 				SelectNone();
   2915 				ScrollToCaret();
   2916 				SetCaretInfo();
   2917 			}
   2918 			else
   2919 			{
   2920 				if (bCtrl)
   2921 					SetCaret(m_pVT->GetBeginWordPlace());
   2922 				else
   2923 					SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
   2924 
   2925 				ScrollToCaret();
   2926 				SetCaretOrigin();
   2927 				SetCaretInfo();
   2928 			}
   2929 		}
   2930 	}
   2931 }
   2932 
   2933 void CFX_Edit::OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl)
   2934 {
   2935 	if (m_pVT->IsValid())
   2936 	{
   2937 		if (bShift)
   2938 		{
   2939 			if (bCtrl)
   2940 				SetCaret(m_pVT->GetEndWordPlace());
   2941 			else
   2942 				SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
   2943 
   2944 			if (m_SelState.IsExist())
   2945 				m_SelState.SetEndPos(m_wpCaret);
   2946 			else
   2947 				m_SelState.Set(m_wpOldCaret, m_wpCaret);
   2948 
   2949 			ScrollToCaret();
   2950 			CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
   2951 			Refresh(RP_OPTIONAL, &wr);
   2952 			SetCaretInfo();
   2953 		}
   2954 		else
   2955 		{
   2956 			if (m_SelState.IsExist())
   2957 			{
   2958 				if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)>0)
   2959 					SetCaret(m_SelState.BeginPos);
   2960 				else
   2961 					SetCaret(m_SelState.EndPos);
   2962 
   2963 				SelectNone();
   2964 				ScrollToCaret();
   2965 				SetCaretInfo();
   2966 			}
   2967 			else
   2968 			{
   2969 				if (bCtrl)
   2970 					SetCaret(m_pVT->GetEndWordPlace());
   2971 				else
   2972 					SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
   2973 
   2974 				ScrollToCaret();
   2975 				SetCaretOrigin();
   2976 				SetCaretInfo();
   2977 			}
   2978 		}
   2979 	}
   2980 }
   2981 
   2982 void CFX_Edit::SetText(FX_LPCWSTR text,FX_INT32 charset,
   2983 						const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps, FX_BOOL bAddUndo, FX_BOOL bPaint)
   2984 {
   2985 	Empty();
   2986 	DoInsertText(CPVT_WordPlace(0,0,-1), text, charset, pSecProps, pWordProps);
   2987 	if (bPaint) Paint();
   2988 	if (m_bOprNotify && m_pOprNotify)
   2989 		m_pOprNotify->OnSetText(m_wpCaret, m_wpOldCaret);
   2990 	//if (bAddUndo)
   2991 }
   2992 
   2993 FX_BOOL CFX_Edit::InsertWord(FX_WORD word, FX_INT32 charset, const CPVT_WordProps * pWordProps, FX_BOOL bAddUndo, FX_BOOL bPaint)
   2994 {
   2995 	if (IsTextOverflow()) return FALSE;
   2996 
   2997 	if (m_pVT->IsValid())
   2998 	{
   2999 		m_pVT->UpdateWordPlace(m_wpCaret);
   3000 
   3001 		SetCaret(m_pVT->InsertWord(m_wpCaret,word,GetCharSetFromUnicode(word, charset),pWordProps));
   3002 		m_SelState.Set(m_wpCaret,m_wpCaret);
   3003 
   3004 		if (m_wpCaret != m_wpOldCaret)
   3005 		{
   3006 			if (bAddUndo && m_bEnableUndo)
   3007 			{
   3008 				AddEditUndoItem(new CFXEU_InsertWord(this,m_wpOldCaret,m_wpCaret,word,charset,pWordProps));
   3009 			}
   3010 
   3011 			if (bPaint)
   3012 				PaintInsertText(m_wpOldCaret, m_wpCaret);
   3013 
   3014 			if (m_bOprNotify && m_pOprNotify)
   3015 				m_pOprNotify->OnInsertWord(m_wpCaret, m_wpOldCaret);
   3016 
   3017 			return TRUE;
   3018 		}
   3019 	}
   3020 
   3021 	return FALSE;
   3022 }
   3023 
   3024 FX_BOOL CFX_Edit::InsertReturn(const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,
   3025 							   FX_BOOL bAddUndo, FX_BOOL bPaint)
   3026 {
   3027 	if (IsTextOverflow()) return FALSE;
   3028 
   3029 	if (m_pVT->IsValid())
   3030 	{
   3031 		m_pVT->UpdateWordPlace(m_wpCaret);
   3032 		SetCaret(m_pVT->InsertSection(m_wpCaret,pSecProps,pWordProps));
   3033 		m_SelState.Set(m_wpCaret,m_wpCaret);
   3034 
   3035 		if (m_wpCaret != m_wpOldCaret)
   3036 		{
   3037 			if (bAddUndo && m_bEnableUndo)
   3038 			{
   3039 				AddEditUndoItem(new CFXEU_InsertReturn(this,m_wpOldCaret,m_wpCaret,pSecProps,pWordProps));
   3040 			}
   3041 
   3042 			if (bPaint)
   3043 			{
   3044 				RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
   3045 				ScrollToCaret();
   3046 				CPVT_WordRange wr(m_wpOldCaret, GetVisibleWordRange().EndPos);
   3047 				Refresh(RP_ANALYSE, &wr);
   3048 				SetCaretOrigin();
   3049 				SetCaretInfo();
   3050 			}
   3051 
   3052 			if (m_bOprNotify && m_pOprNotify)
   3053 				m_pOprNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret);
   3054 
   3055 			return TRUE;
   3056 		}
   3057 	}
   3058 
   3059 	return FALSE;
   3060 }
   3061 
   3062 FX_BOOL CFX_Edit::Backspace(FX_BOOL bAddUndo, FX_BOOL bPaint)
   3063 {
   3064 	if (m_pVT->IsValid())
   3065 	{
   3066 		if (m_wpCaret == m_pVT->GetBeginWordPlace()) return FALSE;
   3067 
   3068 		CPVT_Section section;
   3069 		CPVT_Word word;
   3070 
   3071 		if (bAddUndo)
   3072 		{
   3073 			if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   3074 			{
   3075 				pIterator->SetAt(m_wpCaret);
   3076 				pIterator->GetSection(section);
   3077 				pIterator->GetWord(word);
   3078 			}
   3079 		}
   3080 
   3081 		m_pVT->UpdateWordPlace(m_wpCaret);
   3082 		SetCaret(m_pVT->BackSpaceWord(m_wpCaret));
   3083 		m_SelState.Set(m_wpCaret,m_wpCaret);
   3084 
   3085 		if (m_wpCaret != m_wpOldCaret)
   3086 		{
   3087 			if (bAddUndo && m_bEnableUndo)
   3088 			{
   3089 				if (m_wpCaret.SecCmp(m_wpOldCaret) != 0)
   3090 					AddEditUndoItem(new CFXEU_Backspace(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
   3091 						section.SecProps,section.WordProps));
   3092 				else
   3093 					AddEditUndoItem(new CFXEU_Backspace(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
   3094 						section.SecProps,word.WordProps));
   3095 			}
   3096 
   3097 			if (bPaint)
   3098 			{
   3099 				RearrangePart(CPVT_WordRange(m_wpCaret,m_wpOldCaret));
   3100 				ScrollToCaret();
   3101 
   3102 				CPVT_WordRange wr;
   3103 				if (m_wpCaret.SecCmp(m_wpOldCaret) !=0)
   3104 					wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpCaret),GetVisibleWordRange().EndPos);
   3105 				else if (m_wpCaret.LineCmp(m_wpOldCaret) !=0)
   3106 					wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
   3107 				else
   3108 					wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
   3109 
   3110 				Refresh(RP_ANALYSE, &wr);
   3111 
   3112 				SetCaretOrigin();
   3113 				SetCaretInfo();
   3114 			}
   3115 
   3116 			if (m_bOprNotify && m_pOprNotify)
   3117 				m_pOprNotify->OnBackSpace(m_wpCaret, m_wpOldCaret);
   3118 
   3119 			return TRUE;
   3120 		}
   3121 	}
   3122 
   3123 	return FALSE;
   3124 }
   3125 
   3126 FX_BOOL CFX_Edit::Delete(FX_BOOL bAddUndo, FX_BOOL bPaint)
   3127 {
   3128 	if (m_pVT->IsValid())
   3129 	{
   3130 		if (m_wpCaret == m_pVT->GetEndWordPlace()) return FALSE;
   3131 
   3132 		CPVT_Section section;
   3133 		CPVT_Word word;
   3134 
   3135 		if (bAddUndo)
   3136 		{
   3137 			if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   3138 			{
   3139 				pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret));
   3140 				pIterator->GetSection(section);
   3141 				pIterator->GetWord(word);
   3142 			}
   3143 		}
   3144 
   3145 		m_pVT->UpdateWordPlace(m_wpCaret);
   3146 		FX_BOOL bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret));
   3147 
   3148 		SetCaret(m_pVT->DeleteWord(m_wpCaret));
   3149 		m_SelState.Set(m_wpCaret,m_wpCaret);
   3150 
   3151 		if (bAddUndo && m_bEnableUndo)
   3152 		{
   3153 			if (bSecEnd)
   3154 				AddEditUndoItem(new CFXEU_Delete(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
   3155 					section.SecProps,section.WordProps,bSecEnd));
   3156 			else
   3157 				AddEditUndoItem(new CFXEU_Delete(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
   3158 					section.SecProps,word.WordProps,bSecEnd));
   3159 		}
   3160 
   3161 		if (bPaint)
   3162 		{
   3163 			RearrangePart(CPVT_WordRange(m_wpOldCaret,m_wpCaret));
   3164 			ScrollToCaret();
   3165 
   3166 			CPVT_WordRange wr;
   3167 			if (bSecEnd)
   3168 				wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpOldCaret),GetVisibleWordRange().EndPos);
   3169 			else if (m_wpCaret.LineCmp(m_wpOldCaret) !=0)
   3170 				wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
   3171 			else
   3172 				wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpOldCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
   3173 
   3174 			Refresh(RP_ANALYSE, &wr);
   3175 
   3176 			SetCaretOrigin();
   3177 			SetCaretInfo();
   3178 		}
   3179 
   3180 		if (m_bOprNotify && m_pOprNotify)
   3181 			m_pOprNotify->OnDelete(m_wpCaret, m_wpOldCaret);
   3182 
   3183 		return TRUE;
   3184 	}
   3185 
   3186 	return FALSE;
   3187 }
   3188 
   3189 FX_BOOL	CFX_Edit::Empty()
   3190 {
   3191 	if (m_pVT->IsValid())
   3192 	{
   3193 		m_pVT->DeleteWords(GetWholeWordRange());
   3194 		SetCaret(m_pVT->GetBeginWordPlace());
   3195 
   3196 		return TRUE;
   3197 	}
   3198 
   3199 	return FALSE;
   3200 }
   3201 
   3202 FX_BOOL CFX_Edit::Clear(FX_BOOL bAddUndo, FX_BOOL bPaint)
   3203 {
   3204 	if (m_pVT->IsValid())
   3205 	{
   3206 		if (m_SelState.IsExist())
   3207 		{
   3208 			CPVT_WordRange range = m_SelState.ConvertToWordRange();
   3209 
   3210 			if (bAddUndo && m_bEnableUndo)
   3211 			{
   3212 				if (m_pVT->IsRichText())
   3213 				{
   3214 					BeginGroupUndo(L"");
   3215 
   3216 					if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   3217 					{
   3218 						pIterator->SetAt(range.EndPos);
   3219 
   3220 						CPVT_Word wordinfo;
   3221 						CPVT_Section secinfo;
   3222 						do
   3223 						{
   3224 							CPVT_WordPlace place = pIterator->GetAt();
   3225 							if (place.WordCmp(range.BeginPos) <= 0)break;
   3226 
   3227 							CPVT_WordPlace oldplace = m_pVT->GetPrevWordPlace(place);
   3228 
   3229 							if (oldplace.SecCmp(place) != 0)
   3230 							{
   3231 								if (pIterator->GetSection(secinfo))
   3232 								{
   3233 									AddEditUndoItem(new CFXEU_ClearRich(this,oldplace,place,range,wordinfo.Word,
   3234 										wordinfo.nCharset,secinfo.SecProps,secinfo.WordProps));
   3235 								}
   3236 							}
   3237 							else
   3238 							{
   3239 								if (pIterator->GetWord(wordinfo))
   3240 								{
   3241 									oldplace = m_pVT->AjustLineHeader(oldplace,TRUE);
   3242 									place = m_pVT->AjustLineHeader(place,TRUE);
   3243 
   3244 									AddEditUndoItem(new CFXEU_ClearRich(this,oldplace,place,range,wordinfo.Word,
   3245 										wordinfo.nCharset,secinfo.SecProps,wordinfo.WordProps));
   3246 								}
   3247 							}
   3248 						}while (pIterator->PrevWord());
   3249 					}
   3250 					EndGroupUndo();
   3251 				}
   3252 				else
   3253 				{
   3254 					AddEditUndoItem(new CFXEU_Clear(this,range,GetSelText()));
   3255 				}
   3256 			}
   3257 
   3258 			SelectNone();
   3259 			SetCaret(m_pVT->DeleteWords(range));
   3260 			m_SelState.Set(m_wpCaret,m_wpCaret);
   3261 
   3262 			if (bPaint)
   3263 			{
   3264 				RearrangePart(range);
   3265 				ScrollToCaret();
   3266 
   3267 				CPVT_WordRange wr(m_wpOldCaret, GetVisibleWordRange().EndPos);
   3268 				Refresh(RP_ANALYSE, &wr);
   3269 
   3270 				SetCaretOrigin();
   3271 				SetCaretInfo();
   3272 			}
   3273 
   3274 			if (m_bOprNotify && m_pOprNotify)
   3275 				m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret);
   3276 
   3277 			return TRUE;
   3278 		}
   3279 	}
   3280 
   3281 	return FALSE;
   3282 }
   3283 
   3284 FX_BOOL CFX_Edit::InsertText(FX_LPCWSTR text, FX_INT32 charset,
   3285 					const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps, FX_BOOL bAddUndo, FX_BOOL bPaint)
   3286 {
   3287 	if (IsTextOverflow()) return FALSE;
   3288 
   3289 	m_pVT->UpdateWordPlace(m_wpCaret);
   3290 	SetCaret(DoInsertText(m_wpCaret, text, charset, pSecProps, pWordProps));
   3291 	m_SelState.Set(m_wpCaret,m_wpCaret);
   3292 
   3293 	if (m_wpCaret != m_wpOldCaret)
   3294 	{
   3295 		if (bAddUndo && m_bEnableUndo)
   3296 		{
   3297 			AddEditUndoItem(new CFXEU_InsertText(this,m_wpOldCaret,m_wpCaret,text,charset,pSecProps,pWordProps));
   3298 		}
   3299 
   3300 		if (bPaint)
   3301 			PaintInsertText(m_wpOldCaret, m_wpCaret);
   3302 
   3303 		if (m_bOprNotify && m_pOprNotify)
   3304 			m_pOprNotify->OnInsertText(m_wpCaret, m_wpOldCaret);
   3305 
   3306 		return TRUE;
   3307 	}
   3308 	return FALSE;
   3309 }
   3310 
   3311 void CFX_Edit::PaintInsertText(const CPVT_WordPlace & wpOld, const CPVT_WordPlace & wpNew)
   3312 {
   3313 	if (m_pVT->IsValid())
   3314 	{
   3315 		RearrangePart(CPVT_WordRange(wpOld,wpNew));
   3316 		ScrollToCaret();
   3317 
   3318 		CPVT_WordRange wr;
   3319 		if (m_wpCaret.LineCmp(wpOld) !=0)
   3320 			wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(wpOld),m_pVT->GetSectionEndPlace(wpNew));
   3321 		else
   3322 			wr = CPVT_WordRange(wpOld,m_pVT->GetSectionEndPlace(wpNew));
   3323 		Refresh(RP_ANALYSE, &wr);
   3324 		SetCaretOrigin();
   3325 		SetCaretInfo();
   3326 	}
   3327 }
   3328 
   3329 FX_BOOL CFX_Edit::Redo()
   3330 {
   3331 	if (m_bEnableUndo)
   3332 	{
   3333 		if (m_Undo.CanRedo())
   3334 		{
   3335 			m_Undo.Redo();
   3336 			return TRUE;
   3337 		}
   3338 	}
   3339 
   3340 	return FALSE;
   3341 }
   3342 
   3343 FX_BOOL CFX_Edit::Undo()
   3344 {
   3345 	if (m_bEnableUndo)
   3346 	{
   3347 		if (m_Undo.CanUndo())
   3348 		{
   3349 			m_Undo.Undo();
   3350 			return TRUE;
   3351 		}
   3352 	}
   3353 
   3354 	return FALSE;
   3355 }
   3356 
   3357 void CFX_Edit::SetCaretOrigin()
   3358 {
   3359 	if (m_pVT->IsValid())
   3360 	{
   3361 		if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
   3362 		{
   3363 			pIterator->SetAt(m_wpCaret);
   3364 			CPVT_Word word;
   3365 			CPVT_Line line;
   3366 			if (pIterator->GetWord(word))
   3367 			{
   3368 				m_ptCaret.x = word.ptWord.x + word.fWidth;
   3369 				m_ptCaret.y = word.ptWord.y;
   3370 			}
   3371 			else if (pIterator->GetLine(line))
   3372 			{
   3373 				m_ptCaret.x = line.ptLine.x;
   3374 				m_ptCaret.y = line.ptLine.y;
   3375 			}
   3376 		}
   3377 	}
   3378 }
   3379 
   3380 FX_INT32 CFX_Edit::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
   3381 {
   3382 	if (m_pVT->IsValid())
   3383 		return m_pVT->WordPlaceToWordIndex(place);
   3384 
   3385 	return -1;
   3386 }
   3387 
   3388 CPVT_WordPlace CFX_Edit::WordIndexToWordPlace(FX_INT32 index) const
   3389 {
   3390 	if (m_pVT->IsValid())
   3391 		return m_pVT->WordIndexToWordPlace(index);
   3392 
   3393 	return CPVT_WordPlace();
   3394 }
   3395 
   3396 FX_BOOL	CFX_Edit::IsTextFull() const
   3397 {
   3398 	FX_INT32 nTotalWords = m_pVT->GetTotalWords();
   3399 	FX_INT32 nLimitChar = m_pVT->GetLimitChar();
   3400 	FX_INT32 nCharArray = m_pVT->GetCharArray();
   3401 
   3402 	return IsTextOverflow() || (nLimitChar>0 && nTotalWords >= nLimitChar)
   3403 		|| (nCharArray>0 && nTotalWords >= nCharArray);
   3404 }
   3405 
   3406 FX_BOOL	CFX_Edit::IsTextOverflow() const
   3407 {
   3408 	if (!m_bEnableScroll && !m_bEnableOverflow)
   3409 	{
   3410 		CPDF_Rect rcPlate = m_pVT->GetPlateRect();
   3411 		CPDF_Rect rcContent = m_pVT->GetContentRect();
   3412 
   3413 		if (m_pVT->IsMultiLine() && GetTotalLines() > 1)
   3414 		{
   3415 			if (FX_EDIT_IsFloatBigger(rcContent.Height(),rcPlate.Height())) return TRUE;
   3416 		}
   3417 
   3418 		if (FX_EDIT_IsFloatBigger(rcContent.Width(),rcPlate.Width())) return TRUE;
   3419 	}
   3420 
   3421 	return FALSE;
   3422 }
   3423 
   3424 CPVT_WordPlace CFX_Edit::GetLineBeginPlace(const CPVT_WordPlace & place) const
   3425 {
   3426 	return m_pVT->GetLineBeginPlace(place);
   3427 }
   3428 
   3429 CPVT_WordPlace CFX_Edit::GetLineEndPlace(const CPVT_WordPlace & place) const
   3430 {
   3431 	return m_pVT->GetLineEndPlace(place);
   3432 }
   3433 
   3434 CPVT_WordPlace CFX_Edit::GetSectionBeginPlace(const CPVT_WordPlace & place) const
   3435 {
   3436 	return m_pVT->GetSectionBeginPlace(place);
   3437 }
   3438 
   3439 CPVT_WordPlace CFX_Edit::GetSectionEndPlace(const CPVT_WordPlace & place) const
   3440 {
   3441 	return m_pVT->GetSectionEndPlace(place);
   3442 }
   3443 
   3444 FX_BOOL	CFX_Edit::CanUndo() const
   3445 {
   3446 	if (m_bEnableUndo)
   3447 	{
   3448 		return m_Undo.CanUndo();
   3449 	}
   3450 
   3451 	return FALSE;
   3452 }
   3453 
   3454 FX_BOOL	CFX_Edit::CanRedo() const
   3455 {
   3456 	if (m_bEnableUndo)
   3457 	{
   3458 		return m_Undo.CanRedo();
   3459 	}
   3460 
   3461 	return FALSE;
   3462 }
   3463 
   3464 FX_BOOL	CFX_Edit::IsModified() const
   3465 {
   3466 	if (m_bEnableUndo)
   3467 	{
   3468 		return m_Undo.IsModified();
   3469 	}
   3470 
   3471 	return FALSE;
   3472 }
   3473 
   3474 void CFX_Edit::EnableRefresh(FX_BOOL bRefresh)
   3475 {
   3476 	m_bEnableRefresh = bRefresh;
   3477 }
   3478 
   3479 void CFX_Edit::EnableUndo(FX_BOOL bUndo)
   3480 {
   3481 	this->m_bEnableUndo = bUndo;
   3482 }
   3483 
   3484 void CFX_Edit::EnableNotify(FX_BOOL bNotify)
   3485 {
   3486 	this->m_bNotify = bNotify;
   3487 }
   3488 
   3489 void CFX_Edit::EnableOprNotify(FX_BOOL bNotify)
   3490 {
   3491 	this->m_bOprNotify = bNotify;
   3492 }
   3493 
   3494 FX_FLOAT CFX_Edit::GetLineTop(const CPVT_WordPlace& place) const
   3495 {
   3496 	if (IPDF_VariableText_Iterator* pIterator = m_pVT->GetIterator())
   3497 	{
   3498 		CPVT_WordPlace wpOld = pIterator->GetAt();
   3499 
   3500 		pIterator->SetAt(place);
   3501 		CPVT_Line line;
   3502 		pIterator->GetLine(line);
   3503 
   3504 		pIterator->SetAt(wpOld);
   3505 
   3506 		return line.ptLine.y + line.fLineAscent;
   3507 	}
   3508 
   3509 	return 0.0f;
   3510 }
   3511 
   3512 FX_FLOAT CFX_Edit::GetLineBottom(const CPVT_WordPlace& place) const
   3513 {
   3514 	if (IPDF_VariableText_Iterator* pIterator = m_pVT->GetIterator())
   3515 	{
   3516 		CPVT_WordPlace wpOld = pIterator->GetAt();
   3517 
   3518 		pIterator->SetAt(place);
   3519 		CPVT_Line line;
   3520 		pIterator->GetLine(line);
   3521 
   3522 		pIterator->SetAt(wpOld);
   3523 
   3524 		return line.ptLine.y + line.fLineDescent;
   3525 	}
   3526 
   3527 	return 0.0f;
   3528 }
   3529 
   3530 CPVT_WordPlace CFX_Edit::DoInsertText(const CPVT_WordPlace& place, FX_LPCWSTR text, FX_INT32 charset,
   3531 									  const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps)
   3532 {
   3533 	CPVT_WordPlace wp = place;
   3534 
   3535 	if (m_pVT->IsValid())
   3536 	{
   3537 		CFX_WideString sText = text;
   3538 
   3539 		for (FX_INT32 i = 0, sz = sText.GetLength(); i < sz; i++)
   3540 		{
   3541 			FX_WORD word = sText[i];
   3542 			switch (word)
   3543 			{
   3544 			case 0x0D:
   3545 				wp = m_pVT->InsertSection(wp,pSecProps,pWordProps);
   3546 				if (sText[i+1] == 0x0A)
   3547 					i++;
   3548 				break;
   3549 			case 0x0A:
   3550 				wp = m_pVT->InsertSection(wp,pSecProps,pWordProps);
   3551 				if (sText[i+1] == 0x0D)
   3552 					i++;
   3553 				break;
   3554 			case 0x09:
   3555 				word = 0x20;
   3556 			default:
   3557 				wp = m_pVT->InsertWord(wp,word,GetCharSetFromUnicode(word, charset),pWordProps);
   3558 				break;
   3559 			}
   3560 		}
   3561 	}
   3562 
   3563 	return wp;
   3564 }
   3565 
   3566 FX_INT32 CFX_Edit::GetCharSetFromUnicode(FX_WORD word, FX_INT32 nOldCharset)
   3567 {
   3568 	if (IFX_Edit_FontMap* pFontMap = this->GetFontMap())
   3569 		return pFontMap->CharSetFromUnicode(word, nOldCharset);
   3570 	else
   3571 		return nOldCharset;
   3572 }
   3573 
   3574 void CFX_Edit::BeginGroupUndo(const CFX_WideString& sTitle)
   3575 {
   3576 	ASSERT(m_pGroupUndoItem == NULL);
   3577 
   3578 	m_pGroupUndoItem = new CFX_Edit_GroupUndoItem(sTitle);
   3579 }
   3580 
   3581 void CFX_Edit::EndGroupUndo()
   3582 {
   3583 	ASSERT(m_pGroupUndoItem != NULL);
   3584 
   3585 	m_pGroupUndoItem->UpdateItems();
   3586 	m_Undo.AddItem(m_pGroupUndoItem);
   3587 	if (m_bOprNotify && m_pOprNotify)
   3588 		m_pOprNotify->OnAddUndo(m_pGroupUndoItem);
   3589 	m_pGroupUndoItem = NULL;
   3590 }
   3591 
   3592 void CFX_Edit::AddEditUndoItem(CFX_Edit_UndoItem* pEditUndoItem)
   3593 {
   3594 	if (m_pGroupUndoItem)
   3595 		m_pGroupUndoItem->AddUndoItem(pEditUndoItem);
   3596 	else
   3597 	{
   3598 		m_Undo.AddItem(pEditUndoItem);
   3599 		if (m_bOprNotify && m_pOprNotify)
   3600 			m_pOprNotify->OnAddUndo(pEditUndoItem);
   3601 	}
   3602 }
   3603 
   3604 void CFX_Edit::AddUndoItem(IFX_Edit_UndoItem* pUndoItem)
   3605 {
   3606 	m_Undo.AddItem(pUndoItem);
   3607 	if (m_bOprNotify && m_pOprNotify)
   3608 		m_pOprNotify->OnAddUndo(pUndoItem);
   3609 }
   3610 
   3611