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
19CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL),
20	m_pSpellCheck(NULL),
21	m_bFocus(FALSE)
22{
23	m_pFormFiller = NULL;
24}
25
26CPWL_Edit::~CPWL_Edit()
27{
28	ASSERT(m_bFocus == FALSE);
29}
30
31CFX_ByteString CPWL_Edit::GetClassName() const
32{
33	return PWL_CLASSNAME_EDIT;
34}
35
36void CPWL_Edit::OnDestroy()
37{
38}
39
40void 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
84void 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
105CPDF_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
120void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat, FX_BOOL bPaint/* = TRUE*/)
121{
122	m_pEdit->SetAlignmentH((FX_INT32)nFormat, bPaint);
123}
124
125void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, FX_BOOL bPaint/* = TRUE*/)
126{
127	m_pEdit->SetAlignmentV((FX_INT32)nFormat, bPaint);
128}
129
130FX_BOOL	CPWL_Edit::CanSelectAll() const
131{
132	return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();
133}
134
135FX_BOOL	CPWL_Edit::CanClear() const
136{
137	return !IsReadOnly() && m_pEdit->IsSelected();
138}
139
140FX_BOOL	CPWL_Edit::CanCopy() const
141{
142	return 	!HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();
143}
144
145FX_BOOL	CPWL_Edit::CanCut() const
146{
147	return 	CanCopy() && !IsReadOnly();
148}
149
150FX_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
161void 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
171void 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
206void 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
218void 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
236void 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
294void 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
407void 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	}
480IFX_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
493FX_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
511FX_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
532FX_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
708void 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
721void 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
739void CPWL_Edit::SetHorzScale(FX_INT32 nHorzScale, FX_BOOL bPaint/* = TRUE*/)
740{
741	m_pEdit->SetHorzScale(nHorzScale, bPaint);
742}
743
744void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint/* = TRUE*/)
745{
746	m_pEdit->SetCharSpace(fCharSpace, bPaint);
747}
748
749void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint/* = TRUE*/)
750{
751	m_pEdit->SetLineLeading(fLineLeading, bPaint);
752}
753
754CFX_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
760CPVT_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
778CFX_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
791CFX_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
799CPDF_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
819FX_BOOL	CPWL_Edit::IsTextFull() const
820{
821	return m_pEdit->IsTextFull();
822}
823
824FX_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
841void 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
863void CPWL_Edit::SetLimitChar(FX_INT32 nLimitChar)
864{
865	m_pEdit->SetLimitChar(nLimitChar);
866}
867
868void CPWL_Edit::ReplaceSel(FX_LPCWSTR csText)
869{
870	m_pEdit->Clear();
871	m_pEdit->InsertText(csText);
872}
873
874CPDF_Rect CPWL_Edit::GetFocusRect() const
875{
876	return CPDF_Rect();
877}
878
879void 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
905FX_BOOL	CPWL_Edit::IsVScrollBarVisible() const
906{
907	if (CPWL_ScrollBar * pScroll = GetVScrollBar())
908	{
909		return pScroll->IsVisible();
910	}
911
912	return FALSE;
913}
914
915void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled)
916{
917	if (bEnabled)
918		AddFlag(PES_SPELLCHECK);
919	else
920		RemoveFlag(PES_SPELLCHECK);
921}
922
923FX_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*/
971FX_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
1006FX_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
1072FX_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
1094void 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
1107void 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
1120void 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
1133void 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
1146void 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
1159void CPWL_Edit::OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)
1160{
1161}
1162
1163void 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
1176void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem)
1177{
1178	if (m_pEditNotify)
1179	{
1180		m_pEditNotify->OnAddUndo(this);
1181	}
1182}
1183
1184CPVT_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
1209CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const
1210{
1211	return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);
1212}
1213
1214CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPVT_WordPlace & place) const
1215{
1216	return GetSameWordsRange(place, TRUE, FALSE);
1217}
1218
1219CPVT_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
1226CPVT_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
1304void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr)
1305{
1306}
1307
1308void 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
1314void 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