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