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 
CPWL_Edit()19 CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL),
20 	m_pSpellCheck(NULL),
21 	m_bFocus(FALSE)
22 {
23 	m_pFormFiller = NULL;
24 }
25 
~CPWL_Edit()26 CPWL_Edit::~CPWL_Edit()
27 {
28 	ASSERT(m_bFocus == FALSE);
29 }
30 
GetClassName() const31 CFX_ByteString CPWL_Edit::GetClassName() const
32 {
33 	return PWL_CLASSNAME_EDIT;
34 }
35 
OnDestroy()36 void CPWL_Edit::OnDestroy()
37 {
38 }
39 
SetText(FX_LPCWSTR csText)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 
RePosChildWnd()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 
GetClientRect() const105 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 
SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat,FX_BOOL bPaint)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 
SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat,FX_BOOL bPaint)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 
CanSelectAll() const130 FX_BOOL	CPWL_Edit::CanSelectAll() const
131 {
132 	return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();
133 }
134 
CanClear() const135 FX_BOOL	CPWL_Edit::CanClear() const
136 {
137 	return !IsReadOnly() && m_pEdit->IsSelected();
138 }
139 
CanCopy() const140 FX_BOOL	CPWL_Edit::CanCopy() const
141 {
142 	return 	!HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();
143 }
144 
CanCut() const145 FX_BOOL	CPWL_Edit::CanCut() const
146 {
147 	return 	CanCopy() && !IsReadOnly();
148 }
149 
CanPaste() const150 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 
CopyText()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 
PasteText()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 
CutText()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 
OnCreated()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 
SetParamByFlag()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 
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)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 
DrawThisAppearance(CFX_RenderDevice * pDevice,CPDF_Matrix * pUser2Device)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 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)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 
OnLButtonDblClk(const CPDF_Point & point,FX_DWORD nFlag)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 
OnRButtonUp(const CPDF_Point & point,FX_DWORD nFlag)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 
OnSetFocus()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 
OnKillFocus()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 
SetHorzScale(FX_INT32 nHorzScale,FX_BOOL bPaint)739 void CPWL_Edit::SetHorzScale(FX_INT32 nHorzScale, FX_BOOL bPaint/* = TRUE*/)
740 {
741 	m_pEdit->SetHorzScale(nHorzScale, bPaint);
742 }
743 
SetCharSpace(FX_FLOAT fCharSpace,FX_BOOL bPaint)744 void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint/* = TRUE*/)
745 {
746 	m_pEdit->SetCharSpace(fCharSpace, bPaint);
747 }
748 
SetLineLeading(FX_FLOAT fLineLeading,FX_BOOL bPaint)749 void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint/* = TRUE*/)
750 {
751 	m_pEdit->SetLineLeading(fLineLeading, bPaint);
752 }
753 
GetSelectAppearanceStream(const CPDF_Point & ptOffset) const754 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 
GetSelectWordRange() const760 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 
GetTextAppearanceStream(const CPDF_Point & ptOffset) const778 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 
GetCaretAppearanceStream(const CPDF_Point & ptOffset) const791 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 
GetWordRightBottomPoint(const CPVT_WordPlace & wpWord)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 
IsTextFull() const819 FX_BOOL	CPWL_Edit::IsTextFull() const
820 {
821 	return m_pEdit->IsTextFull();
822 }
823 
GetCharArrayAutoFontSize(CPDF_Font * pFont,const CPDF_Rect & rcPlate,FX_INT32 nCharArray)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 
SetCharArray(FX_INT32 nCharArray)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 
SetLimitChar(FX_INT32 nLimitChar)863 void CPWL_Edit::SetLimitChar(FX_INT32 nLimitChar)
864 {
865 	m_pEdit->SetLimitChar(nLimitChar);
866 }
867 
ReplaceSel(FX_LPCWSTR csText)868 void CPWL_Edit::ReplaceSel(FX_LPCWSTR csText)
869 {
870 	m_pEdit->Clear();
871 	m_pEdit->InsertText(csText);
872 }
873 
GetFocusRect() const874 CPDF_Rect CPWL_Edit::GetFocusRect() const
875 {
876 	return CPDF_Rect();
877 }
878 
ShowVScrollBar(FX_BOOL bShow)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 
IsVScrollBarVisible() const905 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 
EnableSpellCheck(FX_BOOL bEnabled)915 void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled)
916 {
917 	if (bEnabled)
918 		AddFlag(PES_SPELLCHECK);
919 	else
920 		RemoveFlag(PES_SPELLCHECK);
921 }
922 
OnKeyDown(FX_WORD nChar,FX_DWORD nFlag)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 */
IsProceedtoOnChar(FX_WORD nKeyCode,FX_DWORD nFlag)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 
OnChar(FX_WORD nChar,FX_DWORD nFlag)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 
OnMouseWheel(short zDelta,const CPDF_Point & point,FX_DWORD nFlag)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 
OnInsertReturn(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnBackSpace(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnDelete(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnClear(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnInsertWord(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnSetText(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)1159 void CPWL_Edit::OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
1160 {
1161 }
1162 
OnInsertText(const CPVT_WordPlace & place,const CPVT_WordPlace & oldplace)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 
OnAddUndo(IFX_Edit_UndoItem * pUndoItem)1176 void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem)
1177 {
1178 	if (m_pEditNotify)
1179 	{
1180 		m_pEditNotify->OnAddUndo(this);
1181 	}
1182 }
1183 
CombineWordRange(const CPVT_WordRange & wr1,const CPVT_WordRange & wr2)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 
GetLatinWordsRange(const CPDF_Point & point) const1209 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const
1210 {
1211 	return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);
1212 }
1213 
GetLatinWordsRange(const CPVT_WordPlace & place) const1214 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPVT_WordPlace & place) const
1215 {
1216 	return GetSameWordsRange(place, TRUE, FALSE);
1217 }
1218 
GetArabicWordsRange(const CPVT_WordPlace & place) const1219 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 
GetSameWordsRange(const CPVT_WordPlace & place,FX_BOOL bLatin,FX_BOOL bArabic) const1226 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 
AjustArabicWords(const CPVT_WordRange & wr)1304 void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr)
1305 {
1306 }
1307 
GeneratePageObjects(CPDF_PageObjects * pPageObjects,const CPDF_Point & ptOffset,CFX_ArrayTemplate<CPDF_TextObject * > & ObjArray)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 
GeneratePageObjects(CPDF_PageObjects * pPageObjects,const CPDF_Point & ptOffset)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