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