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