Home | History | Annotate | Download | only in pdfwindow
      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/pdfwindow/PDFWindow.h"
      8 #include "../../include/pdfwindow/PWL_Wnd.h"
      9 #include "../../include/pdfwindow/PWL_EditCtrl.h"
     10 #include "../../include/pdfwindow/PWL_Edit.h"
     11 #include "../../include/pdfwindow/PWL_ScrollBar.h"
     12 #include "../../include/pdfwindow/PWL_Utils.h"
     13 #include "../../include/pdfwindow/PWL_Caret.h"
     14 #include "../../include/pdfwindow/PWL_FontMap.h"
     15 #include "../../../core/src/fxcrt/fx_safe_types.h"
     16 
     17 /* ---------------------------- CPWL_Edit ------------------------------ */
     18 
     19 CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL),
     20 	m_pSpellCheck(NULL),
     21 	m_bFocus(FALSE)
     22 {
     23 	m_pFormFiller = NULL;
     24 }
     25 
     26 CPWL_Edit::~CPWL_Edit()
     27 {
     28 	ASSERT(m_bFocus == FALSE);
     29 }
     30 
     31 CFX_ByteString CPWL_Edit::GetClassName() const
     32 {
     33 	return PWL_CLASSNAME_EDIT;
     34 }
     35 
     36 void CPWL_Edit::OnDestroy()
     37 {
     38 }
     39 
     40 void CPWL_Edit::SetText(FX_LPCWSTR csText)
     41 {
     42 	CFX_WideString swText = csText;
     43 
     44 	if (HasFlag(PES_RICH))
     45 	{
     46 		CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
     47 
     48 		if (CXML_Element * pXML = CXML_Element::Parse(sValue.c_str(), sValue.GetLength()))
     49 		{
     50 			FX_INT32 nCount = pXML->CountChildren();
     51 			FX_BOOL bFirst = TRUE;
     52 
     53 			swText.Empty();
     54 
     55 			for (FX_INT32 i=0; i<nCount; i++)
     56 			{
     57 				if (CXML_Element * pSubElement = pXML->GetElement(i))
     58 				{
     59 					CFX_ByteString tag=pSubElement->GetTagName();
     60 		   			if (tag.EqualNoCase("p"))
     61 					{
     62 						int nChild = pSubElement->CountChildren();
     63 						CFX_WideString swSection;
     64 						for(FX_INT32 j=0; j<nChild; j++)
     65 						{
     66 							swSection += pSubElement->GetContent(j);
     67 						}
     68 
     69 						if (bFirst)bFirst = FALSE;
     70 						else
     71 							swText += FWL_VKEY_Return;
     72 						swText += swSection;
     73 					}
     74 				}
     75 			}
     76 
     77 			delete pXML;
     78 		}
     79 	}
     80 
     81 	m_pEdit->SetText(swText.c_str());
     82 }
     83 
     84 void CPWL_Edit::RePosChildWnd()
     85 {
     86 	if (CPWL_ScrollBar * pVSB = this->GetVScrollBar())
     87 	{
     88 		//if (pVSB->IsVisible())
     89 		{
     90 			CPDF_Rect rcWindow = m_rcOldWindow;
     91 			CPDF_Rect rcVScroll = CPDF_Rect(rcWindow.right,
     92 								rcWindow.bottom,
     93 								rcWindow.right + PWL_SCROLLBAR_WIDTH,
     94 								rcWindow.top);
     95 			pVSB->Move(rcVScroll, TRUE, FALSE);
     96 		}
     97 	}
     98 
     99 	if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
    100 		m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border
    101 
    102 	CPWL_EditCtrl::RePosChildWnd();
    103 }
    104 
    105 CPDF_Rect CPWL_Edit::GetClientRect() const
    106 {
    107 	CPDF_Rect rcClient = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
    108 
    109 	if (CPWL_ScrollBar * pVSB = this->GetVScrollBar())
    110 	{
    111 		if (pVSB->IsVisible())
    112 		{
    113 			rcClient.right -= PWL_SCROLLBAR_WIDTH;
    114 		}
    115 	}
    116 
    117 	return rcClient;
    118 }
    119 
    120 void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat, FX_BOOL bPaint/* = TRUE*/)
    121 {
    122 	m_pEdit->SetAlignmentH((FX_INT32)nFormat, bPaint);
    123 }
    124 
    125 void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, FX_BOOL bPaint/* = TRUE*/)
    126 {
    127 	m_pEdit->SetAlignmentV((FX_INT32)nFormat, bPaint);
    128 }
    129 
    130 FX_BOOL	CPWL_Edit::CanSelectAll() const
    131 {
    132 	return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();
    133 }
    134 
    135 FX_BOOL	CPWL_Edit::CanClear() const
    136 {
    137 	return !IsReadOnly() && m_pEdit->IsSelected();
    138 }
    139 
    140 FX_BOOL	CPWL_Edit::CanCopy() const
    141 {
    142 	return 	!HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();
    143 }
    144 
    145 FX_BOOL	CPWL_Edit::CanCut() const
    146 {
    147 	return 	CanCopy() && !IsReadOnly();
    148 }
    149 
    150 FX_BOOL	CPWL_Edit::CanPaste() const
    151 {
    152 	if (IsReadOnly()) return FALSE;
    153 
    154 	CFX_WideString swClipboard;
    155 	if (IFX_SystemHandler* pSH = GetSystemHandler())
    156 		swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
    157 
    158 	return !swClipboard.IsEmpty();
    159 }
    160 
    161 void CPWL_Edit::CopyText()
    162 {
    163 	if (!CanCopy()) return;
    164 
    165 	CFX_WideString str = m_pEdit->GetSelText();
    166 
    167 	if (IFX_SystemHandler* pSH = GetSystemHandler())
    168 		pSH->SetClipboardText(GetAttachedHWnd(), str);
    169 }
    170 
    171 void CPWL_Edit::PasteText()
    172 {
    173 	if (!CanPaste()) return;
    174 
    175 	CFX_WideString swClipboard;
    176 	if (IFX_SystemHandler* pSH = GetSystemHandler())
    177 		swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
    178 
    179 	if (m_pFillerNotify)
    180 	{
    181 		FX_BOOL bRC = TRUE;
    182 		FX_BOOL bExit = FALSE;
    183 		CFX_WideString strChangeEx;
    184 		int nSelStart = 0;
    185 		int nSelEnd = 0;
    186 		GetSel(nSelStart, nSelEnd);
    187 		m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), 0 , swClipboard, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, 0);
    188 		if (!bRC) return;
    189 		if (bExit) return;
    190 	}
    191 
    192 	if (swClipboard.GetLength() > 0)
    193 	{
    194 		Clear();
    195 		InsertText(swClipboard.c_str());
    196 	}
    197 
    198 	if (m_pFillerNotify)
    199 	{
    200 		FX_BOOL bExit = FALSE;
    201 		m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,0);
    202 		if (bExit) return;
    203 	}
    204 }
    205 
    206 void CPWL_Edit::CutText()
    207 {
    208 	if (!CanCut()) return;
    209 
    210 	CFX_WideString str = m_pEdit->GetSelText();
    211 
    212 	if (IFX_SystemHandler* pSH = GetSystemHandler())
    213 		pSH->SetClipboardText(GetAttachedHWnd(), str);
    214 
    215 	m_pEdit->Clear();
    216 }
    217 
    218 void CPWL_Edit::OnCreated()
    219 {
    220 	CPWL_EditCtrl::OnCreated();
    221 
    222 	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
    223 	{
    224 		pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
    225 		pScroll->SetTransparency(255);
    226 	}
    227 
    228 	SetParamByFlag();
    229 
    230 	m_rcOldWindow = GetWindowRect();
    231 
    232 	m_pEdit->SetOprNotify(this);
    233 	m_pEdit->EnableOprNotify(TRUE);
    234 }
    235 
    236 void CPWL_Edit::SetParamByFlag()
    237 {
    238 	if (HasFlag(PES_RIGHT))
    239 	{
    240 		m_pEdit->SetAlignmentH(2, FALSE);
    241 	}
    242 	else if (HasFlag(PES_MIDDLE))
    243 	{
    244 		m_pEdit->SetAlignmentH(1, FALSE);
    245 	}
    246 	else
    247 	{
    248 		m_pEdit->SetAlignmentH(0, FALSE);
    249 	}
    250 
    251 	if (HasFlag(PES_BOTTOM))
    252 	{
    253 		m_pEdit->SetAlignmentV(2, FALSE);
    254 	}
    255 	else if (HasFlag(PES_CENTER))
    256 	{
    257 		m_pEdit->SetAlignmentV(1, FALSE);
    258 	}
    259 	else
    260 	{
    261 		m_pEdit->SetAlignmentV(0, FALSE);
    262 	}
    263 
    264 	if (HasFlag(PES_PASSWORD))
    265 	{
    266 		m_pEdit->SetPasswordChar('*', FALSE);
    267 	}
    268 
    269 	m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), FALSE);
    270 	m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), FALSE);
    271 	m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), FALSE);
    272 	m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), FALSE);
    273 	m_pEdit->EnableUndo(HasFlag(PES_UNDO));
    274 
    275 	if (HasFlag(PES_TEXTOVERFLOW))
    276 	{
    277 		SetClipRect(CPDF_Rect(0.0f,0.0f,0.0f,0.0f));
    278 		m_pEdit->SetTextOverflow(TRUE, FALSE);
    279 	}
    280 	else
    281 	{
    282 		if (m_pEditCaret)
    283 		{
    284 			m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border
    285 		}
    286 	}
    287 
    288 	if (HasFlag(PES_SPELLCHECK))
    289 	{
    290 		m_pSpellCheck = GetCreationParam().pSpellCheck;
    291 	}
    292 }
    293 
    294 void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
    295 {
    296 	CPWL_Wnd::GetThisAppearanceStream(sAppStream);
    297 
    298 	CPDF_Rect rcClient = GetClientRect();
    299 	CFX_ByteTextBuf sLine;
    300 
    301 	FX_INT32 nCharArray = m_pEdit->GetCharArray();
    302 
    303 	if (nCharArray > 0)
    304 	{
    305 		switch (GetBorderStyle())
    306 		{
    307 		case PBS_SOLID:
    308 			{
    309 				sLine << "q\n" << GetBorderWidth() << " w\n"
    310 					<< CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n";
    311 
    312 				for (FX_INT32 i=1;i<nCharArray;i++)
    313 				{
    314 					sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
    315 						<< rcClient.bottom << " m\n"
    316 						<< rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
    317 						<< rcClient.top << " l S\n";
    318 				}
    319 
    320 				sLine << "Q\n";
    321 			}
    322 			break;
    323 		case PBS_DASH:
    324 			{
    325 				sLine << "q\n" << GetBorderWidth() << " w\n"
    326 					<< CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n"
    327 					<< "[" << GetBorderDash().nDash << " "
    328 					<< GetBorderDash().nGap << "] "
    329 					<< GetBorderDash().nPhase << " d\n";
    330 
    331 				for (FX_INT32 i=1;i<nCharArray;i++)
    332 				{
    333 					sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
    334 						<< rcClient.bottom << " m\n"
    335 						<< rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
    336 						<< rcClient.top << " l S\n";
    337 				}
    338 
    339 				sLine << "Q\n";
    340 			}
    341 			break;
    342 		}
    343 	}
    344 
    345 	sAppStream << sLine;
    346 
    347 	CFX_ByteTextBuf sText;
    348 
    349 	CPDF_Point ptOffset = CPDF_Point(0.0f,0.0f);
    350 
    351 	CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
    352 	CPVT_WordRange wrSelect = GetSelectWordRange();
    353 	CPVT_WordRange wrVisible = (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());
    354 	CPVT_WordRange wrSelBefore(wrWhole.BeginPos,wrSelect.BeginPos);
    355 	CPVT_WordRange wrSelAfter(wrSelect.EndPos,wrWhole.EndPos);
    356 
    357 	CPVT_WordRange wrTemp = CPWL_Utils::OverlapWordRange(GetSelectWordRange(),wrVisible);
    358 	CFX_ByteString sEditSel = CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset,
    359 			&wrTemp);
    360 
    361 	if (sEditSel.GetLength() > 0)
    362 		sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR) << sEditSel ;
    363 
    364 	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelBefore);
    365 	CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
    366 			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
    367 
    368 	if (sEditBefore.GetLength() > 0)
    369 		sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditBefore << "ET\n";
    370 
    371 	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelect);
    372 	CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
    373 			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
    374 
    375 	if (sEditMid.GetLength() > 0)
    376 		sText << "BT\n" << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY,1)) << sEditMid << "ET\n";
    377 
    378 	wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelAfter);
    379 	CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
    380 			&wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
    381 
    382 	if (sEditAfter.GetLength() > 0)
    383 		sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditAfter<< "ET\n";
    384 
    385 	if (HasFlag(PES_SPELLCHECK))
    386 	{
    387 		CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);
    388 		if (sSpellCheck.GetLength() > 0)
    389 			sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB,1,0,0),FALSE) << sSpellCheck;
    390 	}
    391 
    392 	if (sText.GetLength() > 0)
    393 	{
    394 		CPDF_Rect rcClient = this->GetClientRect();
    395 		sAppStream << "q\n/Tx BMC\n";
    396 
    397 		if (!HasFlag(PES_TEXTOVERFLOW))
    398 			sAppStream << rcClient.left << " " << rcClient.bottom << " "
    399 				<< rcClient.right - rcClient.left << " " << rcClient.top - rcClient.bottom << " re W n\n";
    400 
    401 		sAppStream << sText;
    402 
    403 		sAppStream << "EMC\nQ\n";
    404 	}
    405 }
    406 
    407 void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
    408 {
    409 	CPWL_Wnd::DrawThisAppearance(pDevice,pUser2Device);
    410 
    411 	CPDF_Rect rcClient = GetClientRect();
    412 	CFX_ByteTextBuf sLine;
    413 
    414 	FX_INT32 nCharArray = m_pEdit->GetCharArray();
    415 	FX_SAFE_INT32 nCharArraySafe = nCharArray;
    416 	nCharArraySafe -= 1;
    417 	nCharArraySafe *= 2;
    418 
    419 	if (nCharArray > 0 && nCharArraySafe.IsValid())
    420 	{
    421 		switch (GetBorderStyle())
    422 		{
    423 		case PBS_SOLID:
    424 			{
    425 				CFX_GraphStateData gsd;
    426 				gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
    427 
    428 				CFX_PathData path;
    429 				path.SetPointCount(nCharArraySafe.ValueOrDie());
    430 
    431 				for (FX_INT32 i=0; i<nCharArray-1; i++)
    432 				{
    433 					path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
    434 						rcClient.bottom, FXPT_MOVETO);
    435 					path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
    436 						rcClient.top, FXPT_LINETO);
    437 				}
    438 				if (path.GetPointCount() > 0)
    439 					pDevice->DrawPath(&path, pUser2Device, &gsd,0,
    440 						CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);
    441 			}
    442 			break;
    443 		case PBS_DASH:
    444 			{
    445 				CFX_GraphStateData gsd;
    446 				gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
    447 
    448 				gsd.SetDashCount(2);
    449 				gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;
    450 				gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;
    451 				gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;
    452 
    453 				CFX_PathData path;
    454 				path.SetPointCount(nCharArraySafe.ValueOrDie());
    455 
    456 				for (FX_INT32 i=0; i<nCharArray-1; i++)
    457 				{
    458 					path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
    459 						rcClient.bottom, FXPT_MOVETO);
    460 					path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),
    461 						rcClient.top, FXPT_LINETO);
    462 				}
    463 				if (path.GetPointCount() > 0)
    464 					pDevice->DrawPath(&path, pUser2Device, &gsd,0,
    465 						CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);
    466 			}
    467 			break;
    468 		}
    469 	}
    470 
    471 	CPDF_Rect rcClip;
    472 	CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
    473 	CPVT_WordRange* pRange = NULL;
    474 
    475 	if (!HasFlag(PES_TEXTOVERFLOW))
    476 	{
    477 		rcClip = GetClientRect();
    478 		pRange = &wrRange;
    479 	}
    480 IFX_SystemHandler* pSysHandler = GetSystemHandler();
    481 	IFX_Edit::DrawEdit(pDevice,pUser2Device,m_pEdit,
    482 		CPWL_Utils::PWLColorToFXColor(GetTextColor(),this->GetTransparency()),
    483 		CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(),this->GetTransparency()),
    484 		rcClip,CPDF_Point(0.0f,0.0f),pRange, pSysHandler, m_pFormFiller);
    485 
    486 	if (HasFlag(PES_SPELLCHECK))
    487 	{
    488 		CPWL_Utils::DrawEditSpellCheck(pDevice,pUser2Device,m_pEdit,rcClip,
    489 			CPDF_Point(0.0f,0.0f),pRange, this->GetCreationParam().pSpellCheck);
    490 	}
    491 }
    492 
    493 FX_BOOL CPWL_Edit::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
    494 {
    495 	CPWL_Wnd::OnLButtonDown(point,nFlag);
    496 
    497 	if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))
    498 	{
    499 		if (m_bMouseDown)
    500 			this->InvalidateRect();
    501 
    502 		m_bMouseDown = TRUE;
    503 		SetCapture();
    504 
    505 		m_pEdit->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
    506 	}
    507 
    508 	return TRUE;
    509 }
    510 
    511 FX_BOOL	CPWL_Edit::OnLButtonDblClk(const CPDF_Point & point, FX_DWORD nFlag)
    512 {
    513 	CPWL_Wnd::OnLButtonDblClk(point, nFlag);
    514 
    515 	if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))
    516 	{
    517 		m_pEdit->SelectAll();
    518 	}
    519 
    520 	return TRUE;
    521 }
    522 
    523 #define WM_PWLEDIT_UNDO					0x01
    524 #define WM_PWLEDIT_REDO					0x02
    525 #define WM_PWLEDIT_CUT					0x03
    526 #define WM_PWLEDIT_COPY					0x04
    527 #define WM_PWLEDIT_PASTE				0x05
    528 #define WM_PWLEDIT_DELETE				0x06
    529 #define WM_PWLEDIT_SELECTALL			0x07
    530 #define WM_PWLEDIT_SUGGEST				0x08
    531 
    532 FX_BOOL CPWL_Edit::OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
    533 {
    534 	if (m_bMouseDown) return FALSE;
    535 
    536 	CPWL_Wnd::OnRButtonUp(point, nFlag);
    537 
    538 	if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point)) return TRUE;
    539 
    540 	IFX_SystemHandler* pSH = GetSystemHandler();
    541 	if (!pSH) return FALSE;
    542 
    543 	this->SetFocus();
    544 
    545 	CPVT_WordRange wrLatin = GetLatinWordsRange(point);
    546 	CFX_WideString swLatin = m_pEdit->GetRangeText(wrLatin);
    547 
    548 	FX_HMENU hPopup = pSH->CreatePopupMenu();
    549 	if (!hPopup) return FALSE;
    550 
    551 	CFX_ByteStringArray sSuggestWords;
    552 	CPDF_Point ptPopup = point;
    553 
    554 	if (!IsReadOnly())
    555 	{
    556 		if (HasFlag(PES_SPELLCHECK) && !swLatin.IsEmpty())
    557 		{
    558 			if (m_pSpellCheck)
    559 			{
    560 				CFX_ByteString sLatin = CFX_ByteString::FromUnicode(swLatin);
    561 
    562 				if (!m_pSpellCheck->CheckWord(sLatin))
    563 				{
    564 					m_pSpellCheck->SuggestWords(sLatin,sSuggestWords);
    565 
    566 					FX_INT32 nSuggest = sSuggestWords.GetSize();
    567 
    568 					for (FX_INT32 nWord=0; nWord<nSuggest; nWord++)
    569 					{
    570 						pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SUGGEST+nWord, sSuggestWords[nWord].UTF8Decode());
    571 					}
    572 
    573 					if (nSuggest > 0)
    574 						pSH->AppendMenuItem(hPopup, 0, L"");
    575 
    576 					ptPopup = GetWordRightBottomPoint(wrLatin.EndPos);
    577 				}
    578 			}
    579 		}
    580 	}
    581 
    582 	IPWL_Provider* pProvider = this->GetProvider();
    583 
    584 	if (HasFlag(PES_UNDO))
    585 	{
    586 		pSH->AppendMenuItem(hPopup, WM_PWLEDIT_UNDO,
    587 			pProvider ? pProvider->LoadPopupMenuString(0) : L"&Undo");
    588 		pSH->AppendMenuItem(hPopup, WM_PWLEDIT_REDO,
    589 			pProvider ? pProvider->LoadPopupMenuString(1) : L"&Redo");
    590 		pSH->AppendMenuItem(hPopup, 0, L"");
    591 
    592 		if (!m_pEdit->CanUndo())
    593 			pSH->EnableMenuItem(hPopup, WM_PWLEDIT_UNDO, FALSE);
    594 		if (!m_pEdit->CanRedo())
    595 			pSH->EnableMenuItem(hPopup, WM_PWLEDIT_REDO, FALSE);
    596 	}
    597 
    598 	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_CUT,
    599 		pProvider ? pProvider->LoadPopupMenuString(2) : L"Cu&t");
    600 	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_COPY,
    601 		pProvider ? pProvider->LoadPopupMenuString(3) : L"&Copy");
    602 	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_PASTE,
    603 		pProvider ? pProvider->LoadPopupMenuString(4) : L"&Paste");
    604 	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_DELETE,
    605 		pProvider ? pProvider->LoadPopupMenuString(5) : L"&Delete");
    606 
    607 	CFX_WideString swText = pSH->GetClipboardText(this->GetAttachedHWnd());
    608 	if (swText.IsEmpty())
    609 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
    610 
    611 	if (!m_pEdit->IsSelected())
    612 	{
    613 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
    614 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
    615 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
    616 	}
    617 
    618 	if (IsReadOnly())
    619 	{
    620 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
    621 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
    622 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
    623 	}
    624 
    625 	if (HasFlag(PES_PASSWORD))
    626 	{
    627 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
    628 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
    629 	}
    630 
    631 	if (HasFlag(PES_NOREAD))
    632 	{
    633 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
    634 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
    635 	}
    636 
    637 	pSH->AppendMenuItem(hPopup, 0, L"");
    638 	pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SELECTALL,
    639 		pProvider ? pProvider->LoadPopupMenuString(6) : L"&Select All");
    640 
    641 	if (m_pEdit->GetTotalWords() == 0)
    642 	{
    643 		pSH->EnableMenuItem(hPopup, WM_PWLEDIT_SELECTALL, FALSE);
    644 	}
    645 
    646 	FX_INT32 x, y;
    647 	PWLtoWnd(ptPopup, x, y);
    648 	pSH->ClientToScreen(GetAttachedHWnd(), x, y);
    649 	pSH->SetCursor(FXCT_ARROW);
    650 	FX_INT32 nCmd = pSH->TrackPopupMenu(hPopup,
    651 					 x,
    652 					 y,
    653 					 GetAttachedHWnd());
    654 
    655 
    656 	switch (nCmd)
    657 	{
    658 	case WM_PWLEDIT_UNDO:
    659 		Undo();
    660 		break;
    661 	case WM_PWLEDIT_REDO:
    662 		Redo();
    663 		break;
    664 	case WM_PWLEDIT_CUT:
    665 		this->CutText();
    666 		break;
    667 	case WM_PWLEDIT_COPY:
    668 		this->CopyText();
    669 		break;
    670 	case WM_PWLEDIT_PASTE:
    671 		this->PasteText();
    672 		break;
    673 	case WM_PWLEDIT_DELETE:
    674 		this->Clear();
    675 		break;
    676 	case WM_PWLEDIT_SELECTALL:
    677 		this->SelectAll();
    678 		break;
    679 	case WM_PWLEDIT_SUGGEST + 0:
    680 		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
    681 		ReplaceSel(sSuggestWords[0].UTF8Decode().c_str());
    682 		break;
    683 	case WM_PWLEDIT_SUGGEST + 1:
    684 		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
    685 		ReplaceSel(sSuggestWords[1].UTF8Decode().c_str());
    686 		break;
    687 	case WM_PWLEDIT_SUGGEST + 2:
    688 		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
    689 		ReplaceSel(sSuggestWords[2].UTF8Decode().c_str());
    690 		break;
    691 	case WM_PWLEDIT_SUGGEST + 3:
    692 		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
    693 		ReplaceSel(sSuggestWords[3].UTF8Decode().c_str());
    694 		break;
    695 	case WM_PWLEDIT_SUGGEST + 4:
    696 		SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
    697 		ReplaceSel(sSuggestWords[4].UTF8Decode().c_str());
    698 		break;
    699 	default:
    700 		break;
    701 	}
    702 
    703 	pSH->DestroyMenu(hPopup);
    704 
    705 	return TRUE;
    706 }
    707 
    708 void CPWL_Edit::OnSetFocus()
    709 {
    710 	SetEditCaret(TRUE);
    711 
    712 	if (!IsReadOnly())
    713 	{
    714 		if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
    715 			pFocusHandler->OnSetFocus(this);
    716 	}
    717 
    718 	m_bFocus = TRUE;
    719 }
    720 
    721 void CPWL_Edit::OnKillFocus()
    722 {
    723 	ShowVScrollBar(FALSE);
    724 
    725 	m_pEdit->SelectNone();
    726 	SetCaret(FALSE, CPDF_Point(0.0f,0.0f), CPDF_Point(0.0f,0.0f));
    727 
    728 	SetCharSet(0);
    729 
    730 	if (!IsReadOnly())
    731 	{
    732 		if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
    733 			pFocusHandler->OnKillFocus(this);
    734 	}
    735 
    736 	m_bFocus = FALSE;
    737 }
    738 
    739 void CPWL_Edit::SetHorzScale(FX_INT32 nHorzScale, FX_BOOL bPaint/* = TRUE*/)
    740 {
    741 	m_pEdit->SetHorzScale(nHorzScale, bPaint);
    742 }
    743 
    744 void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint/* = TRUE*/)
    745 {
    746 	m_pEdit->SetCharSpace(fCharSpace, bPaint);
    747 }
    748 
    749 void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint/* = TRUE*/)
    750 {
    751 	m_pEdit->SetLineLeading(fLineLeading, bPaint);
    752 }
    753 
    754 CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(const CPDF_Point & ptOffset) const
    755 {
    756 	CPVT_WordRange wr = GetSelectWordRange();
    757 	return CPWL_Utils::GetEditSelAppStream(m_pEdit,ptOffset,&wr);
    758 }
    759 
    760 CPVT_WordRange CPWL_Edit::GetSelectWordRange() const
    761 {
    762 	if (m_pEdit->IsSelected())
    763 	{
    764 		FX_INT32 nStart = -1;
    765 		FX_INT32 nEnd = -1;
    766 
    767 		m_pEdit->GetSel(nStart, nEnd);
    768 
    769 		CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
    770 		CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);
    771 
    772 		return CPVT_WordRange(wpStart,wpEnd);
    773 	}
    774 
    775 	return CPVT_WordRange();
    776 }
    777 
    778 CFX_ByteString CPWL_Edit::GetTextAppearanceStream(const CPDF_Point & ptOffset) const
    779 {
    780 	CFX_ByteTextBuf sRet;
    781 	CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit,ptOffset);
    782 
    783 	if (sEdit.GetLength() > 0)
    784 	{
    785 		sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit << "ET\n";
    786 	}
    787 
    788 	return sRet.GetByteString();
    789 }
    790 
    791 CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(const CPDF_Point & ptOffset) const
    792 {
    793 	if (m_pEditCaret)
    794 		return m_pEditCaret->GetCaretAppearanceStream(ptOffset);
    795 
    796 	return CFX_ByteString();
    797 }
    798 
    799 CPDF_Point CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord)
    800 {
    801 	CPDF_Point pt(0.0f, 0.0f);
    802 
    803 	if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
    804 	{
    805 		CPVT_WordPlace wpOld = pIterator->GetAt();
    806 		pIterator->SetAt(wpWord);
    807 		CPVT_Word word;
    808 		if (pIterator->GetWord(word))
    809 		{
    810 			pt = CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent);
    811 		}
    812 
    813 		pIterator->SetAt(wpOld);
    814 	}
    815 
    816 	return pt;
    817 }
    818 
    819 FX_BOOL	CPWL_Edit::IsTextFull() const
    820 {
    821 	return m_pEdit->IsTextFull();
    822 }
    823 
    824 FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, const CPDF_Rect& rcPlate, FX_INT32 nCharArray)
    825 {
    826 	if (pFont && !pFont->IsStandardFont())
    827 	{
    828 		FX_RECT rcBBox;
    829 		pFont->GetFontBBox(rcBBox);
    830 
    831 		CPDF_Rect rcCell = rcPlate;
    832 		FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
    833 		FX_FLOAT ydiv = - rcCell.Height() * 1000.0f / rcBBox.Height();
    834 
    835 		return xdiv < ydiv ? xdiv : ydiv;
    836 	}
    837 
    838 	return 0.0f;
    839 }
    840 
    841 void CPWL_Edit::SetCharArray(FX_INT32 nCharArray)
    842 {
    843 	if (HasFlag(PES_CHARARRAY) && nCharArray > 0)
    844 	{
    845 		m_pEdit->SetCharArray(nCharArray);
    846 		m_pEdit->SetTextOverflow(TRUE);
    847 
    848 		if (HasFlag(PWS_AUTOFONTSIZE))
    849 		{
    850 			if (IFX_Edit_FontMap* pFontMap = this->GetFontMap())
    851 			{
    852 				FX_FLOAT fFontSize = GetCharArrayAutoFontSize(pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);
    853 				if (fFontSize > 0.0f)
    854 				{
    855 					m_pEdit->SetAutoFontSize(FALSE);
    856 					m_pEdit->SetFontSize(fFontSize);
    857 				}
    858 			}
    859 		}
    860 	}
    861 }
    862 
    863 void CPWL_Edit::SetLimitChar(FX_INT32 nLimitChar)
    864 {
    865 	m_pEdit->SetLimitChar(nLimitChar);
    866 }
    867 
    868 void CPWL_Edit::ReplaceSel(FX_LPCWSTR csText)
    869 {
    870 	m_pEdit->Clear();
    871 	m_pEdit->InsertText(csText);
    872 }
    873 
    874 CPDF_Rect CPWL_Edit::GetFocusRect() const
    875 {
    876 	return CPDF_Rect();
    877 }
    878 
    879 void CPWL_Edit::ShowVScrollBar(FX_BOOL bShow)
    880 {
    881 	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
    882 	{
    883 		if (bShow)
    884 		{
    885 			if (!pScroll->IsVisible())
    886 			{
    887 				pScroll->SetVisible(TRUE);
    888 				CPDF_Rect rcWindow = GetWindowRect();
    889 				m_rcOldWindow = rcWindow;
    890 				rcWindow.right += PWL_SCROLLBAR_WIDTH;
    891 				Move(rcWindow, TRUE, TRUE);
    892 			}
    893 		}
    894 		else
    895 		{
    896 			if (pScroll->IsVisible())
    897 			{
    898 				pScroll->SetVisible(FALSE);
    899 				Move(m_rcOldWindow, TRUE, TRUE);
    900 			}
    901 		}
    902 	}
    903 }
    904 
    905 FX_BOOL	CPWL_Edit::IsVScrollBarVisible() const
    906 {
    907 	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
    908 	{
    909 		return pScroll->IsVisible();
    910 	}
    911 
    912 	return FALSE;
    913 }
    914 
    915 void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled)
    916 {
    917 	if (bEnabled)
    918 		AddFlag(PES_SPELLCHECK);
    919 	else
    920 		RemoveFlag(PES_SPELLCHECK);
    921 }
    922 
    923 FX_BOOL CPWL_Edit::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
    924 {
    925 	if (m_bMouseDown) return TRUE;
    926 
    927 	if (nChar == FWL_VKEY_Delete)
    928 	{
    929 		if (m_pFillerNotify)
    930 		{
    931 			FX_BOOL bRC = TRUE;
    932 			FX_BOOL bExit = FALSE;
    933 			CFX_WideString strChange;
    934 			CFX_WideString strChangeEx;
    935 
    936 			int nSelStart = 0;
    937 			int nSelEnd = 0;
    938 			GetSel(nSelStart, nSelEnd);
    939 
    940 			if (nSelStart == nSelEnd)
    941 				nSelEnd = nSelStart + 1;
    942 			m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), FWL_VKEY_Delete, strChange, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, nFlag);
    943 			if (!bRC) return FALSE;
    944 			if (bExit) return FALSE;
    945 		}
    946 	}
    947 
    948 	FX_BOOL bRet = CPWL_EditCtrl::OnKeyDown(nChar,  nFlag);
    949 
    950 	if (nChar == FWL_VKEY_Delete)
    951 	{
    952 		if (m_pFillerNotify)
    953 		{
    954 			FX_BOOL bExit = FALSE;
    955 			m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,nFlag);
    956 			if (bExit) return FALSE;
    957 		}
    958 	}
    959 
    960 	//In case of implementation swallow the OnKeyDown event.
    961 	if(IsProceedtoOnChar(nChar, nFlag))
    962 			return TRUE;
    963 
    964 	return bRet;
    965 }
    966 
    967 /**
    968 *In case of implementation swallow the OnKeyDown event.
    969 *If the event is swallowed, implementation may do other unexpected things, which is not the control means to do.
    970 */
    971 FX_BOOL CPWL_Edit::IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag)
    972 {
    973 
    974 	FX_BOOL bCtrl = IsCTRLpressed(nFlag);
    975 	FX_BOOL bAlt = IsALTpressed(nFlag);
    976 	if(bCtrl && !bAlt)
    977 	{
    978 	//hot keys for edit control.
    979 		switch(nKeyCode)
    980 		{
    981 		case 'C':
    982 		case 'V':
    983 		case 'X':
    984 		case 'A':
    985 		case 'Z':
    986 			return TRUE;
    987 		default:
    988 			break;
    989 		}
    990 	}
    991 	//control characters.
    992 	switch(nKeyCode)
    993 	{
    994 	case FWL_VKEY_Escape:
    995 	case FWL_VKEY_Back:
    996 	case FWL_VKEY_Return:
    997 	case FWL_VKEY_Space:
    998 		return TRUE;
    999 	default:
   1000 		break;
   1001 	}
   1002 	return FALSE;
   1003 
   1004 }
   1005 
   1006 FX_BOOL CPWL_Edit::OnChar(FX_WORD nChar, FX_DWORD nFlag)
   1007 {
   1008 	if (m_bMouseDown) return TRUE;
   1009 
   1010 	FX_BOOL bRC = TRUE;
   1011 	FX_BOOL bExit = FALSE;
   1012 
   1013 	FX_BOOL bCtrl = IsCTRLpressed(nFlag);
   1014 	if (!bCtrl)
   1015 	{
   1016 		if (m_pFillerNotify)
   1017 		{
   1018 			CFX_WideString swChange;
   1019 			FX_INT32 nKeyCode;
   1020 
   1021 			int nSelStart = 0;
   1022 			int nSelEnd = 0;
   1023 			GetSel(nSelStart, nSelEnd);
   1024 
   1025 			switch (nChar)
   1026 			{
   1027 			case FWL_VKEY_Back:
   1028 				nKeyCode = nChar;
   1029 				if (nSelStart == nSelEnd)
   1030 					nSelStart = nSelEnd - 1;
   1031 				break;
   1032 			case FWL_VKEY_Return:
   1033 				nKeyCode = nChar;
   1034 				break;
   1035 			default:
   1036 				nKeyCode = 0;
   1037 				swChange += nChar;
   1038 				break;
   1039 			}
   1040 
   1041 			CFX_WideString strChangeEx;
   1042 			m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), nKeyCode, swChange, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, nFlag);
   1043 		}
   1044 	}
   1045 
   1046 	if (!bRC) return TRUE;
   1047 	if (bExit) return FALSE;
   1048 
   1049 	if (IFX_Edit_FontMap * pFontMap = GetFontMap())
   1050 	{
   1051 		FX_INT32 nOldCharSet = GetCharSet();
   1052 		FX_INT32 nNewCharSet = pFontMap->CharSetFromUnicode(nChar, DEFAULT_CHARSET);
   1053 		if(nOldCharSet != nNewCharSet)
   1054 		{
   1055 			SetCharSet(nNewCharSet);
   1056 		}
   1057 	}
   1058 	FX_BOOL bRet = CPWL_EditCtrl::OnChar(nChar,nFlag);
   1059 
   1060 	if (!bCtrl)
   1061 	{
   1062 		if (m_pFillerNotify)
   1063 		{
   1064 			m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,nFlag);
   1065 			if (bExit) return FALSE;
   1066 		}
   1067 	}
   1068 
   1069 	return bRet;
   1070 }
   1071 
   1072 FX_BOOL	CPWL_Edit::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
   1073 {
   1074 	if (HasFlag(PES_MULTILINE))
   1075 	{
   1076 		CPDF_Point ptScroll = GetScrollPos();
   1077 
   1078 		if (zDelta > 0)
   1079 		{
   1080 			ptScroll.y += this->GetFontSize();
   1081 		}
   1082 		else
   1083 		{
   1084 			ptScroll.y -= this->GetFontSize();
   1085 		}
   1086 		this->SetScrollPos(ptScroll);
   1087 
   1088 		return TRUE;
   1089 	}
   1090 
   1091 	return FALSE;
   1092 }
   1093 
   1094 void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1095 {
   1096 	if (HasFlag(PES_SPELLCHECK))
   1097 	{
   1098 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1099 	}
   1100 
   1101 	if (m_pEditNotify)
   1102 	{
   1103 		m_pEditNotify->OnInsertReturn(place, oldplace);
   1104 	}
   1105 }
   1106 
   1107 void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1108 {
   1109 	if (HasFlag(PES_SPELLCHECK))
   1110 	{
   1111 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1112 	}
   1113 
   1114 	if (m_pEditNotify)
   1115 	{
   1116 		m_pEditNotify->OnBackSpace(place, oldplace);
   1117 	}
   1118 }
   1119 
   1120 void CPWL_Edit::OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1121 {
   1122 	if (HasFlag(PES_SPELLCHECK))
   1123 	{
   1124 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1125 	}
   1126 
   1127 	if (m_pEditNotify)
   1128 	{
   1129 		m_pEditNotify->OnDelete(place, oldplace);
   1130 	}
   1131 }
   1132 
   1133 void CPWL_Edit::OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1134 {
   1135 	if (HasFlag(PES_SPELLCHECK))
   1136 	{
   1137 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1138 	}
   1139 
   1140 	if (m_pEditNotify)
   1141 	{
   1142 		m_pEditNotify->OnClear(place, oldplace);
   1143 	}
   1144 }
   1145 
   1146 void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1147 {
   1148 	if (HasFlag(PES_SPELLCHECK))
   1149 	{
   1150 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1151 	}
   1152 
   1153 	if (m_pEditNotify)
   1154 	{
   1155 		m_pEditNotify->OnInsertWord(place, oldplace);
   1156 	}
   1157 }
   1158 
   1159 void CPWL_Edit::OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1160 {
   1161 }
   1162 
   1163 void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
   1164 {
   1165 	if (HasFlag(PES_SPELLCHECK))
   1166 	{
   1167 		m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));
   1168 	}
   1169 
   1170 	if (m_pEditNotify)
   1171 	{
   1172 		m_pEditNotify->OnInsertText(place, oldplace);
   1173 	}
   1174 }
   1175 
   1176 void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem)
   1177 {
   1178 	if (m_pEditNotify)
   1179 	{
   1180 		m_pEditNotify->OnAddUndo(this);
   1181 	}
   1182 }
   1183 
   1184 CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1, const CPVT_WordRange& wr2)
   1185 {
   1186 	CPVT_WordRange wrRet;
   1187 
   1188 	if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0)
   1189 	{
   1190 		wrRet.BeginPos = wr1.BeginPos;
   1191 	}
   1192 	else
   1193 	{
   1194 		wrRet.BeginPos = wr2.BeginPos;
   1195 	}
   1196 
   1197 	if (wr1.EndPos.WordCmp(wr2.EndPos) < 0)
   1198 	{
   1199 		wrRet.EndPos = wr2.EndPos;
   1200 	}
   1201 	else
   1202 	{
   1203 		wrRet.EndPos = wr1.EndPos;
   1204 	}
   1205 
   1206 	return wrRet;
   1207 }
   1208 
   1209 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const
   1210 {
   1211 	return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);
   1212 }
   1213 
   1214 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPVT_WordPlace & place) const
   1215 {
   1216 	return GetSameWordsRange(place, TRUE, FALSE);
   1217 }
   1218 
   1219 CPVT_WordRange CPWL_Edit::GetArabicWordsRange(const CPVT_WordPlace & place) const
   1220 {
   1221 	return GetSameWordsRange(place, FALSE, TRUE);
   1222 }
   1223 
   1224 #define PWL_ISARABICWORD(word) ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
   1225 
   1226 CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace & place, FX_BOOL bLatin, FX_BOOL bArabic) const
   1227 {
   1228 	CPVT_WordRange range;
   1229 
   1230 	if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator())
   1231 	{
   1232 		CPVT_Word wordinfo;
   1233 		CPVT_WordPlace wpStart(place),wpEnd(place);
   1234 		pIterator->SetAt(place);
   1235 
   1236 		if (bLatin)
   1237 		{
   1238 			while (pIterator->NextWord())
   1239 			{
   1240 				if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))
   1241 				{
   1242 					wpEnd = pIterator->GetAt();
   1243 					continue;
   1244 				}
   1245 				else
   1246 					break;
   1247 			};
   1248 		}
   1249 		else if (bArabic)
   1250 		{
   1251 			while (pIterator->NextWord())
   1252 			{
   1253 				if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))
   1254 				{
   1255 					wpEnd = pIterator->GetAt();
   1256 					continue;
   1257 				}
   1258 				else
   1259 					break;
   1260 			};
   1261 		}
   1262 
   1263 		pIterator->SetAt(place);
   1264 
   1265 		if (bLatin)
   1266 		{
   1267 			do
   1268 			{
   1269 				if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))
   1270 				{
   1271 					continue;
   1272 				}
   1273 				else
   1274 				{
   1275 					wpStart = pIterator->GetAt();
   1276 					break;
   1277 				}
   1278 			}
   1279 			while (pIterator->PrevWord());
   1280 		}
   1281 		else if (bArabic)
   1282 		{
   1283 			do
   1284 			{
   1285 				if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))
   1286 				{
   1287 					continue;
   1288 				}
   1289 				else
   1290 				{
   1291 					wpStart = pIterator->GetAt();
   1292 					break;
   1293 				}
   1294 			}
   1295 			while (pIterator->PrevWord());
   1296 		}
   1297 
   1298 		range.Set(wpStart,wpEnd);
   1299 	}
   1300 
   1301 	return range;
   1302 }
   1303 
   1304 void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr)
   1305 {
   1306 }
   1307 
   1308 void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
   1309 										const CPDF_Point& ptOffset, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
   1310 {
   1311 	IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);
   1312 }
   1313 
   1314 void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
   1315 									const CPDF_Point& ptOffset)
   1316 {
   1317 	CFX_ArrayTemplate<CPDF_TextObject*> ObjArray;
   1318 	IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);
   1319 }
   1320 
   1321