Remove trailing whitespaces in fpdfsdk.
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Edit.cpp
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 "../../../core/include/fxcrt/fx_safe_types.h"
8 #include "../../include/pdfwindow/PDFWindow.h"
9 #include "../../include/pdfwindow/PWL_Caret.h"
10 #include "../../include/pdfwindow/PWL_Edit.h"
11 #include "../../include/pdfwindow/PWL_EditCtrl.h"
12 #include "../../include/pdfwindow/PWL_FontMap.h"
13 #include "../../include/pdfwindow/PWL_ScrollBar.h"
14 #include "../../include/pdfwindow/PWL_Utils.h"
15 #include "../../include/pdfwindow/PWL_Wnd.h"
16
17 /* ---------------------------- CPWL_Edit ------------------------------ */
18
19 CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL),
20         m_pSpellCheck(NULL),
21         m_bFocus(FALSE)
22 {
23         m_pFormFiller = NULL;
24 }
25
26 CPWL_Edit::~CPWL_Edit()
27 {
28         ASSERT(m_bFocus == FALSE);
29 }
30
31 CFX_ByteString CPWL_Edit::GetClassName() const
32 {
33         return PWL_CLASSNAME_EDIT;
34 }
35
36 void CPWL_Edit::OnDestroy()
37 {
38 }
39
40 void CPWL_Edit::SetText(const FX_WCHAR* 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                         int32_t nCount = pXML->CountChildren();
51                         FX_BOOL bFirst = TRUE;
52
53                         swText.Empty();
54
55                         for (int32_t 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(int32_t j=0; j<nChild; j++)
65                                                 {
66                                                         swSection += pSubElement->GetContent(j);
67                                                 }
68
69                                                 if (bFirst)bFirst = FALSE;
70                                                 else
71                                                         swText += FWL_VKEY_Return;
72                                                 swText += swSection;
73                                         }
74                                 }
75                         }
76
77                         delete pXML;
78                 }
79         }
80
81         m_pEdit->SetText(swText.c_str());
82 }
83
84 void CPWL_Edit::RePosChildWnd()
85 {
86     if (CPWL_ScrollBar * pVSB = GetVScrollBar()) {
87         CPDF_Rect rcWindow = m_rcOldWindow;
88         CPDF_Rect rcVScroll = CPDF_Rect(rcWindow.right,
89                                         rcWindow.bottom,
90                                         rcWindow.right + PWL_SCROLLBAR_WIDTH,
91                                         rcWindow.top);
92         pVSB->Move(rcVScroll, TRUE, FALSE);
93     }
94
95         if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
96                 m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border
97
98         CPWL_EditCtrl::RePosChildWnd();
99 }
100
101 CPDF_Rect CPWL_Edit::GetClientRect() const
102 {
103         CPDF_Rect rcClient = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
104
105         if (CPWL_ScrollBar * pVSB = GetVScrollBar())
106         {
107                 if (pVSB->IsVisible())
108                 {
109                         rcClient.right -= PWL_SCROLLBAR_WIDTH;
110                 }
111         }
112
113         return rcClient;
114 }
115
116 void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat, FX_BOOL bPaint/* = TRUE*/)
117 {
118         m_pEdit->SetAlignmentH((int32_t)nFormat, bPaint);
119 }
120
121 void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, FX_BOOL bPaint/* = TRUE*/)
122 {
123         m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
124 }
125
126 FX_BOOL CPWL_Edit::CanSelectAll() const
127 {
128         return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();
129 }
130
131 FX_BOOL CPWL_Edit::CanClear() const
132 {
133         return !IsReadOnly() && m_pEdit->IsSelected();
134 }
135
136 FX_BOOL CPWL_Edit::CanCopy() const
137 {
138         return  !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();
139 }
140
141 FX_BOOL CPWL_Edit::CanCut() const
142 {
143         return  CanCopy() && !IsReadOnly();
144 }
145
146 FX_BOOL CPWL_Edit::CanPaste() const
147 {
148         if (IsReadOnly()) return FALSE;
149
150         CFX_WideString swClipboard;
151         if (IFX_SystemHandler* pSH = GetSystemHandler())
152                 swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
153
154         return !swClipboard.IsEmpty();
155 }
156
157 void CPWL_Edit::CopyText()
158 {
159         if (!CanCopy()) return;
160
161         CFX_WideString str = m_pEdit->GetSelText();
162
163         if (IFX_SystemHandler* pSH = GetSystemHandler())
164                 pSH->SetClipboardText(GetAttachedHWnd(), str);
165 }
166
167 void CPWL_Edit::PasteText()
168 {
169         if (!CanPaste()) return;
170
171         CFX_WideString swClipboard;
172         if (IFX_SystemHandler* pSH = GetSystemHandler())
173                 swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
174
175         if (m_pFillerNotify)
176         {
177                 FX_BOOL bRC = TRUE;
178                 FX_BOOL bExit = FALSE;
179                 CFX_WideString strChangeEx;
180                 int nSelStart = 0;
181                 int nSelEnd = 0;
182                 GetSel(nSelStart, nSelEnd);
183                 m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), 0 , swClipboard, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, 0);
184                 if (!bRC) return;
185                 if (bExit) return;
186         }
187
188         if (swClipboard.GetLength() > 0)
189         {
190                 Clear();
191                 InsertText(swClipboard.c_str());
192         }
193
194         if (m_pFillerNotify)
195         {
196                 FX_BOOL bExit = FALSE;
197                 m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,0);
198                 if (bExit) return;
199         }
200 }
201
202 void CPWL_Edit::CutText()
203 {
204         if (!CanCut()) return;
205
206         CFX_WideString str = m_pEdit->GetSelText();
207
208         if (IFX_SystemHandler* pSH = GetSystemHandler())
209                 pSH->SetClipboardText(GetAttachedHWnd(), str);
210
211         m_pEdit->Clear();
212 }
213
214 void CPWL_Edit::OnCreated()
215 {
216         CPWL_EditCtrl::OnCreated();
217
218         if (CPWL_ScrollBar * pScroll = GetVScrollBar())
219         {
220                 pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
221                 pScroll->SetTransparency(255);
222         }
223
224         SetParamByFlag();
225
226         m_rcOldWindow = GetWindowRect();
227
228         m_pEdit->SetOprNotify(this);
229         m_pEdit->EnableOprNotify(TRUE);
230 }
231
232 void CPWL_Edit::SetParamByFlag()
233 {
234         if (HasFlag(PES_RIGHT))
235         {
236                 m_pEdit->SetAlignmentH(2, FALSE);
237         }
238         else if (HasFlag(PES_MIDDLE))
239         {
240                 m_pEdit->SetAlignmentH(1, FALSE);
241         }
242         else
243         {
244                 m_pEdit->SetAlignmentH(0, FALSE);
245         }
246
247         if (HasFlag(PES_BOTTOM))
248         {
249                 m_pEdit->SetAlignmentV(2, FALSE);
250         }
251         else if (HasFlag(PES_CENTER))
252         {
253                 m_pEdit->SetAlignmentV(1, FALSE);
254         }
255         else
256         {
257                 m_pEdit->SetAlignmentV(0, FALSE);
258         }
259
260         if (HasFlag(PES_PASSWORD))
261         {
262                 m_pEdit->SetPasswordChar('*', FALSE);
263         }
264
265         m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), FALSE);
266         m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), FALSE);
267         m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), FALSE);
268         m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), FALSE);
269         m_pEdit->EnableUndo(HasFlag(PES_UNDO));
270
271         if (HasFlag(PES_TEXTOVERFLOW))
272         {
273                 SetClipRect(CPDF_Rect(0.0f,0.0f,0.0f,0.0f));
274                 m_pEdit->SetTextOverflow(TRUE, FALSE);
275         }
276         else
277         {
278                 if (m_pEditCaret)
279                 {
280                         m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border
281                 }
282         }
283
284         if (HasFlag(PES_SPELLCHECK))
285         {
286                 m_pSpellCheck = GetCreationParam().pSpellCheck;
287         }
288 }
289
290 void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
291 {
292         CPWL_Wnd::GetThisAppearanceStream(sAppStream);
293
294         CPDF_Rect rcClient = GetClientRect();
295         CFX_ByteTextBuf sLine;
296
297         int32_t nCharArray = m_pEdit->GetCharArray();
298
299         if (nCharArray > 0)
300         {
301                 switch (GetBorderStyle())
302                 {
303                 case PBS_SOLID:
304                         {
305                                 sLine << "q\n" << GetBorderWidth() << " w\n"
306                                         << CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n";
307
308                                 for (int32_t i=1;i<nCharArray;i++)
309                                 {
310                                         sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
311                                                 << rcClient.bottom << " m\n"
312                                                 << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
313                                                 << rcClient.top << " l S\n";
314                                 }
315
316                                 sLine << "Q\n";
317                         }
318                         break;
319                 case PBS_DASH:
320                         {
321                                 sLine << "q\n" << GetBorderWidth() << " w\n"
322                                         << CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n"
323                                         << "[" << GetBorderDash().nDash << " "
324                                         << GetBorderDash().nGap << "] "
325                                         << GetBorderDash().nPhase << " d\n";
326
327                                 for (int32_t i=1;i<nCharArray;i++)
328                                 {
329                                         sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
330                                                 << rcClient.bottom << " m\n"
331                                                 << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "
332                                                 << rcClient.top << " l S\n";
333                                 }
334
335                                 sLine << "Q\n";
336                         }
337                         break;
338                 }
339         }
340
341         sAppStream << sLine;
342
343         CFX_ByteTextBuf sText;
344
345         CPDF_Point ptOffset = CPDF_Point(0.0f,0.0f);
346
347         CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
348         CPVT_WordRange wrSelect = GetSelectWordRange();
349         CPVT_WordRange wrVisible = (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());
350         CPVT_WordRange wrSelBefore(wrWhole.BeginPos,wrSelect.BeginPos);
351         CPVT_WordRange wrSelAfter(wrSelect.EndPos,wrWhole.EndPos);
352
353         CPVT_WordRange wrTemp = CPWL_Utils::OverlapWordRange(GetSelectWordRange(),wrVisible);
354         CFX_ByteString sEditSel = CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset,
355                         &wrTemp);
356
357         if (sEditSel.GetLength() > 0)
358                 sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR) << sEditSel ;
359
360         wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelBefore);
361         CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
362                         &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
363
364         if (sEditBefore.GetLength() > 0)
365                 sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditBefore << "ET\n";
366
367         wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelect);
368         CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
369                         &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
370
371         if (sEditMid.GetLength() > 0)
372                 sText << "BT\n" << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY,1)) << sEditMid << "ET\n";
373
374         wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelAfter);
375         CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,
376                         &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());
377
378         if (sEditAfter.GetLength() > 0)
379                 sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditAfter<< "ET\n";
380
381         if (HasFlag(PES_SPELLCHECK))
382         {
383                 CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);
384                 if (sSpellCheck.GetLength() > 0)
385                         sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB,1,0,0),FALSE) << sSpellCheck;
386         }
387
388         if (sText.GetLength() > 0)
389         {
390                 CPDF_Rect rcClient = GetClientRect();
391                 sAppStream << "q\n/Tx BMC\n";
392
393                 if (!HasFlag(PES_TEXTOVERFLOW))
394                         sAppStream << rcClient.left << " " << rcClient.bottom << " "
395                                 << rcClient.right - rcClient.left << " " << rcClient.top - rcClient.bottom << " re W n\n";
396
397                 sAppStream << sText;
398
399                 sAppStream << "EMC\nQ\n";
400         }
401 }
402
403 void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
404 {
405         CPWL_Wnd::DrawThisAppearance(pDevice,pUser2Device);
406
407         CPDF_Rect rcClient = GetClientRect();
408         CFX_ByteTextBuf sLine;
409
410         int32_t nCharArray = m_pEdit->GetCharArray();
411         FX_SAFE_INT32 nCharArraySafe = nCharArray;
412         nCharArraySafe -= 1;
413         nCharArraySafe *= 2;
414
415         if (nCharArray > 0 && nCharArraySafe.IsValid())
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(nCharArraySafe.ValueOrDie());
426
427                                 for (int32_t 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(nCharArraySafe.ValueOrDie());
451
452                                 for (int32_t 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(), GetTransparency()),
479                 CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(), 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, 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                         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         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                                         int32_t nSuggest = sSuggestWords.GetSize();
563
564                                         for (int32_t 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 = 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(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         int32_t x, y;
643         PWLtoWnd(ptPopup, x, y);
644         pSH->ClientToScreen(GetAttachedHWnd(), x, y);
645         pSH->SetCursor(FXCT_ARROW);
646         int32_t 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                 CutText();
662                 break;
663         case WM_PWLEDIT_COPY:
664                 CopyText();
665                 break;
666         case WM_PWLEDIT_PASTE:
667                 PasteText();
668                 break;
669         case WM_PWLEDIT_DELETE:
670                 Clear();
671                 break;
672         case WM_PWLEDIT_SELECTALL:
673                 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().c_str());
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().c_str());
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().c_str());
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().c_str());
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().c_str());
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(int32_t 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                 int32_t nStart = -1;
761                 int32_t 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, int32_t 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(int32_t 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 = 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(int32_t nLimitChar)
860 {
861         m_pEdit->SetLimitChar(nLimitChar);
862 }
863
864 void CPWL_Edit::ReplaceSel(const FX_WCHAR* 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                         int32_t 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                 int32_t nOldCharSet = GetCharSet();
1048                 int32_t 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 += GetFontSize();
1077                 }
1078                 else
1079                 {
1080                         ptScroll.y -= GetFontSize();
1081                 }
1082                 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