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