• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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/formfiller/cffl_interactiveformfiller.h"
8 
9 #include "constants/access_permissions.h"
10 #include "constants/ascii.h"
11 #include "constants/form_flags.h"
12 #include "core/fpdfapi/page/cpdf_page.h"
13 #include "core/fxcrt/autorestorer.h"
14 #include "core/fxge/cfx_drawutils.h"
15 #include "fpdfsdk/cpdfsdk_pageview.h"
16 #include "fpdfsdk/cpdfsdk_widget.h"
17 #include "fpdfsdk/formfiller/cffl_checkbox.h"
18 #include "fpdfsdk/formfiller/cffl_combobox.h"
19 #include "fpdfsdk/formfiller/cffl_formfield.h"
20 #include "fpdfsdk/formfiller/cffl_listbox.h"
21 #include "fpdfsdk/formfiller/cffl_perwindowdata.h"
22 #include "fpdfsdk/formfiller/cffl_pushbutton.h"
23 #include "fpdfsdk/formfiller/cffl_radiobutton.h"
24 #include "fpdfsdk/formfiller/cffl_textfield.h"
25 #include "public/fpdf_fwlevent.h"
26 #include "third_party/base/check.h"
27 #include "third_party/base/cxx17_backports.h"
28 
CFFL_InteractiveFormFiller(CallbackIface * pCallbackIface)29 CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller(
30     CallbackIface* pCallbackIface)
31     : m_pCallbackIface(pCallbackIface) {}
32 
33 CFFL_InteractiveFormFiller::~CFFL_InteractiveFormFiller() = default;
34 
Annot_HitTest(const CPDFSDK_Widget * pWidget,const CFX_PointF & point)35 bool CFFL_InteractiveFormFiller::Annot_HitTest(const CPDFSDK_Widget* pWidget,
36                                                const CFX_PointF& point) {
37   return pWidget->GetRect().Contains(point);
38 }
39 
GetViewBBox(const CPDFSDK_PageView * pPageView,CPDFSDK_Widget * pWidget)40 FX_RECT CFFL_InteractiveFormFiller::GetViewBBox(
41     const CPDFSDK_PageView* pPageView,
42     CPDFSDK_Widget* pWidget) {
43   if (CFFL_FormField* pFormField = GetFormField(pWidget))
44     return pFormField->GetViewBBox(pPageView);
45 
46   DCHECK(pPageView);
47 
48   CPDF_Annot* pPDFAnnot = pWidget->GetPDFAnnot();
49   CFX_FloatRect rcWin = pPDFAnnot->GetRect();
50   if (!rcWin.IsEmpty()) {
51     rcWin.Inflate(1, 1);
52     rcWin.Normalize();
53   }
54   return rcWin.GetOuterRect();
55 }
56 
OnDraw(CPDFSDK_PageView * pPageView,CPDFSDK_Widget * pWidget,CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)57 void CFFL_InteractiveFormFiller::OnDraw(CPDFSDK_PageView* pPageView,
58                                         CPDFSDK_Widget* pWidget,
59                                         CFX_RenderDevice* pDevice,
60                                         const CFX_Matrix& mtUser2Device) {
61   DCHECK(pPageView);
62   if (!IsVisible(pWidget))
63     return;
64 
65   CFFL_FormField* pFormField = GetFormField(pWidget);
66   if (pFormField && pFormField->IsValid()) {
67     pFormField->OnDraw(pPageView, pWidget, pDevice, mtUser2Device);
68     if (m_pCallbackIface->GetFocusAnnot() != pWidget)
69       return;
70 
71     CFX_FloatRect rcFocus = pFormField->GetFocusBox(pPageView);
72     if (rcFocus.IsEmpty())
73       return;
74 
75     CFX_DrawUtils::DrawFocusRect(pDevice, mtUser2Device, rcFocus);
76 
77     return;
78   }
79 
80   if (pFormField) {
81     pFormField->OnDrawDeactive(pPageView, pWidget, pDevice, mtUser2Device);
82   } else {
83     pWidget->DrawAppearance(pDevice, mtUser2Device,
84                             CPDF_Annot::AppearanceMode::kNormal);
85   }
86 
87   if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget))
88     pWidget->DrawShadow(pDevice, pPageView);
89 }
90 
OnDelete(CPDFSDK_Widget * pWidget)91 void CFFL_InteractiveFormFiller::OnDelete(CPDFSDK_Widget* pWidget) {
92   UnregisterFormField(pWidget);
93 }
94 
OnMouseEnter(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlag)95 void CFFL_InteractiveFormFiller::OnMouseEnter(
96     CPDFSDK_PageView* pPageView,
97     ObservedPtr<CPDFSDK_Widget>& pWidget,
98     Mask<FWL_EVENTFLAG> nFlag) {
99   if (!m_bNotifying) {
100     if (pWidget->GetAAction(CPDF_AAction::kCursorEnter).HasDict()) {
101       uint32_t nValueAge = pWidget->GetValueAge();
102       pWidget->ClearAppModified();
103       DCHECK(pPageView);
104       {
105         AutoRestorer<bool> restorer(&m_bNotifying);
106         m_bNotifying = true;
107 
108         CFFL_FieldAction fa;
109         fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
110         fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
111         pWidget->OnAAction(CPDF_AAction::kCursorEnter, &fa, pPageView);
112       }
113       if (!pWidget)
114         return;
115 
116       if (pWidget->IsAppModified()) {
117         CFFL_FormField* pFormField = GetFormField(pWidget.Get());
118         if (pFormField)
119           pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(),
120                                                 nValueAge);
121       }
122     }
123   }
124   if (CFFL_FormField* pFormField = GetOrCreateFormField(pWidget.Get()))
125     pFormField->OnMouseEnter(pPageView);
126 }
127 
OnMouseExit(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlag)128 void CFFL_InteractiveFormFiller::OnMouseExit(
129     CPDFSDK_PageView* pPageView,
130     ObservedPtr<CPDFSDK_Widget>& pWidget,
131     Mask<FWL_EVENTFLAG> nFlag) {
132   if (!m_bNotifying) {
133     if (pWidget->GetAAction(CPDF_AAction::kCursorExit).HasDict()) {
134       uint32_t nValueAge = pWidget->GetValueAge();
135       pWidget->ClearAppModified();
136       DCHECK(pPageView);
137       {
138         AutoRestorer<bool> restorer(&m_bNotifying);
139         m_bNotifying = true;
140 
141         CFFL_FieldAction fa;
142         fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
143         fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
144         pWidget->OnAAction(CPDF_AAction::kCursorExit, &fa, pPageView);
145       }
146       if (!pWidget)
147         return;
148 
149       if (pWidget->IsAppModified()) {
150         CFFL_FormField* pFormField = GetFormField(pWidget.Get());
151         if (pFormField) {
152           pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(),
153                                                 nValueAge);
154         }
155       }
156     }
157   }
158   if (CFFL_FormField* pFormField = GetFormField(pWidget.Get()))
159     pFormField->OnMouseExit(pPageView);
160 }
161 
OnLButtonDown(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)162 bool CFFL_InteractiveFormFiller::OnLButtonDown(
163     CPDFSDK_PageView* pPageView,
164     ObservedPtr<CPDFSDK_Widget>& pWidget,
165     Mask<FWL_EVENTFLAG> nFlags,
166     const CFX_PointF& point) {
167   if (!m_bNotifying) {
168     if (Annot_HitTest(pWidget.Get(), point) &&
169         pWidget->GetAAction(CPDF_AAction::kButtonDown).HasDict()) {
170       uint32_t nValueAge = pWidget->GetValueAge();
171       pWidget->ClearAppModified();
172       DCHECK(pPageView);
173       {
174         AutoRestorer<bool> restorer(&m_bNotifying);
175         m_bNotifying = true;
176 
177         CFFL_FieldAction fa;
178         fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlags);
179         fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlags);
180         pWidget->OnAAction(CPDF_AAction::kButtonDown, &fa, pPageView);
181       }
182       if (!pWidget)
183         return true;
184 
185       if (!IsValidAnnot(pPageView, pWidget.Get()))
186         return true;
187 
188       if (pWidget->IsAppModified()) {
189         CFFL_FormField* pFormField = GetFormField(pWidget.Get());
190         if (pFormField) {
191           pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(),
192                                                 nValueAge);
193         }
194       }
195     }
196   }
197   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
198   return pFormField &&
199          pFormField->OnLButtonDown(pPageView, pWidget.Get(), nFlags, point);
200 }
201 
OnLButtonUp(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)202 bool CFFL_InteractiveFormFiller::OnLButtonUp(
203     CPDFSDK_PageView* pPageView,
204     ObservedPtr<CPDFSDK_Widget>& pWidget,
205     Mask<FWL_EVENTFLAG> nFlags,
206     const CFX_PointF& point) {
207   bool bSetFocus;
208   switch (pWidget->GetFieldType()) {
209     case FormFieldType::kPushButton:
210     case FormFieldType::kCheckBox:
211     case FormFieldType::kRadioButton: {
212       FX_RECT bbox = GetViewBBox(pPageView, pWidget.Get());
213       bSetFocus =
214           bbox.Contains(static_cast<int>(point.x), static_cast<int>(point.y));
215       break;
216     }
217     default:
218       bSetFocus = true;
219       break;
220   }
221   if (bSetFocus) {
222     ObservedPtr<CPDFSDK_Annot> pObserved(pWidget.Get());
223     m_pCallbackIface->SetFocusAnnot(pObserved);
224   }
225 
226   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
227   bool bRet = pFormField &&
228               pFormField->OnLButtonUp(pPageView, pWidget.Get(), nFlags, point);
229   if (m_pCallbackIface->GetFocusAnnot() != pWidget.Get())
230     return bRet;
231   if (OnButtonUp(pWidget, pPageView, nFlags) || !pWidget)
232     return true;
233 #ifdef PDF_ENABLE_XFA
234   if (OnClick(pWidget, pPageView, nFlags) || !pWidget)
235     return true;
236 #endif  // PDF_ENABLE_XFA
237   return bRet;
238 }
239 
OnButtonUp(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)240 bool CFFL_InteractiveFormFiller::OnButtonUp(
241     ObservedPtr<CPDFSDK_Widget>& pWidget,
242     const CPDFSDK_PageView* pPageView,
243     Mask<FWL_EVENTFLAG> nFlag) {
244   if (m_bNotifying)
245     return false;
246 
247   if (!pWidget->GetAAction(CPDF_AAction::kButtonUp).HasDict())
248     return false;
249 
250   uint32_t nAge = pWidget->GetAppearanceAge();
251   uint32_t nValueAge = pWidget->GetValueAge();
252   DCHECK(pPageView);
253   {
254     AutoRestorer<bool> restorer(&m_bNotifying);
255     m_bNotifying = true;
256 
257     CFFL_FieldAction fa;
258     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
259     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
260     pWidget->OnAAction(CPDF_AAction::kButtonUp, &fa, pPageView);
261   }
262   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get()))
263     return true;
264   if (nAge == pWidget->GetAppearanceAge())
265     return false;
266 
267   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
268   if (pFormField)
269     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
270   return true;
271 }
272 
SetIndexSelected(ObservedPtr<CPDFSDK_Widget> & pWidget,int index,bool selected)273 bool CFFL_InteractiveFormFiller::SetIndexSelected(
274     ObservedPtr<CPDFSDK_Widget>& pWidget,
275     int index,
276     bool selected) {
277   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
278   return pFormField && pFormField->SetIndexSelected(index, selected);
279 }
280 
IsIndexSelected(ObservedPtr<CPDFSDK_Widget> & pWidget,int index)281 bool CFFL_InteractiveFormFiller::IsIndexSelected(
282     ObservedPtr<CPDFSDK_Widget>& pWidget,
283     int index) {
284   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
285   return pFormField && pFormField->IsIndexSelected(index);
286 }
287 
OnLButtonDblClk(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)288 bool CFFL_InteractiveFormFiller::OnLButtonDblClk(
289     CPDFSDK_PageView* pPageView,
290     ObservedPtr<CPDFSDK_Widget>& pWidget,
291     Mask<FWL_EVENTFLAG> nFlags,
292     const CFX_PointF& point) {
293   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
294   return pFormField && pFormField->OnLButtonDblClk(pPageView, nFlags, point);
295 }
296 
OnMouseMove(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)297 bool CFFL_InteractiveFormFiller::OnMouseMove(
298     CPDFSDK_PageView* pPageView,
299     ObservedPtr<CPDFSDK_Widget>& pWidget,
300     Mask<FWL_EVENTFLAG> nFlags,
301     const CFX_PointF& point) {
302   CFFL_FormField* pFormField = GetOrCreateFormField(pWidget.Get());
303   return pFormField && pFormField->OnMouseMove(pPageView, nFlags, point);
304 }
305 
OnMouseWheel(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point,const CFX_Vector & delta)306 bool CFFL_InteractiveFormFiller::OnMouseWheel(
307     CPDFSDK_PageView* pPageView,
308     ObservedPtr<CPDFSDK_Widget>& pWidget,
309     Mask<FWL_EVENTFLAG> nFlags,
310     const CFX_PointF& point,
311     const CFX_Vector& delta) {
312   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
313   return pFormField &&
314          pFormField->OnMouseWheel(pPageView, nFlags, point, delta);
315 }
316 
OnRButtonDown(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)317 bool CFFL_InteractiveFormFiller::OnRButtonDown(
318     CPDFSDK_PageView* pPageView,
319     ObservedPtr<CPDFSDK_Widget>& pWidget,
320     Mask<FWL_EVENTFLAG> nFlags,
321     const CFX_PointF& point) {
322   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
323   return pFormField && pFormField->OnRButtonDown(pPageView, nFlags, point);
324 }
325 
OnRButtonUp(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)326 bool CFFL_InteractiveFormFiller::OnRButtonUp(
327     CPDFSDK_PageView* pPageView,
328     ObservedPtr<CPDFSDK_Widget>& pWidget,
329     Mask<FWL_EVENTFLAG> nFlags,
330     const CFX_PointF& point) {
331   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
332   return pFormField && pFormField->OnRButtonUp(pPageView, nFlags, point);
333 }
334 
OnKeyDown(CPDFSDK_Widget * pWidget,FWL_VKEYCODE nKeyCode,Mask<FWL_EVENTFLAG> nFlags)335 bool CFFL_InteractiveFormFiller::OnKeyDown(CPDFSDK_Widget* pWidget,
336                                            FWL_VKEYCODE nKeyCode,
337                                            Mask<FWL_EVENTFLAG> nFlags) {
338   CFFL_FormField* pFormField = GetFormField(pWidget);
339   return pFormField && pFormField->OnKeyDown(nKeyCode, nFlags);
340 }
341 
OnChar(CPDFSDK_Widget * pWidget,uint32_t nChar,Mask<FWL_EVENTFLAG> nFlags)342 bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Widget* pWidget,
343                                         uint32_t nChar,
344                                         Mask<FWL_EVENTFLAG> nFlags) {
345   if (nChar == pdfium::ascii::kTab)
346     return true;
347 
348   CFFL_FormField* pFormField = GetFormField(pWidget);
349   return pFormField && pFormField->OnChar(pWidget, nChar, nFlags);
350 }
351 
OnSetFocus(ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlag)352 bool CFFL_InteractiveFormFiller::OnSetFocus(
353     ObservedPtr<CPDFSDK_Widget>& pWidget,
354     Mask<FWL_EVENTFLAG> nFlag) {
355   if (!pWidget)
356     return false;
357 
358   if (!m_bNotifying) {
359     if (pWidget->GetAAction(CPDF_AAction::kGetFocus).HasDict()) {
360       uint32_t nValueAge = pWidget->GetValueAge();
361       pWidget->ClearAppModified();
362 
363       CFFL_FormField* pFormField = GetOrCreateFormField(pWidget.Get());
364       if (!pFormField)
365         return false;
366 
367       CPDFSDK_PageView* pPageView = pWidget->GetPageView();
368       DCHECK(pPageView);
369       {
370         AutoRestorer<bool> restorer(&m_bNotifying);
371         m_bNotifying = true;
372 
373         CFFL_FieldAction fa;
374         fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
375         fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
376         pFormField->GetActionData(pPageView, CPDF_AAction::kGetFocus, fa);
377         pWidget->OnAAction(CPDF_AAction::kGetFocus, &fa, pPageView);
378       }
379       if (!pWidget)
380         return false;
381 
382       if (pWidget->IsAppModified()) {
383         CFFL_FormField* pFiller = GetFormField(pWidget.Get());
384         if (pFiller) {
385           pFiller->ResetPWLWindowForValueAge(pPageView, pWidget.Get(),
386                                              nValueAge);
387         }
388       }
389     }
390   }
391 
392   if (CFFL_FormField* pFormField = GetOrCreateFormField(pWidget.Get()))
393     pFormField->SetFocusForAnnot(pWidget.Get(), nFlag);
394 
395   return true;
396 }
397 
OnKillFocus(ObservedPtr<CPDFSDK_Widget> & pWidget,Mask<FWL_EVENTFLAG> nFlag)398 bool CFFL_InteractiveFormFiller::OnKillFocus(
399     ObservedPtr<CPDFSDK_Widget>& pWidget,
400     Mask<FWL_EVENTFLAG> nFlag) {
401   if (!pWidget)
402     return false;
403 
404   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
405   if (!pFormField)
406     return true;
407 
408   pFormField->KillFocusForAnnot(nFlag);
409   if (!pWidget)
410     return false;
411 
412   if (m_bNotifying)
413     return true;
414 
415   if (!pWidget->GetAAction(CPDF_AAction::kLoseFocus).HasDict())
416     return true;
417 
418   pWidget->ClearAppModified();
419 
420   CPDFSDK_PageView* pPageView = pWidget->GetPageView();
421   DCHECK(pPageView);
422   {
423     AutoRestorer<bool> restorer(&m_bNotifying);
424     m_bNotifying = true;
425 
426     CFFL_FieldAction fa;
427     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
428     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
429     pFormField->GetActionData(pPageView, CPDF_AAction::kLoseFocus, fa);
430     pWidget->OnAAction(CPDF_AAction::kLoseFocus, &fa, pPageView);
431   }
432   return !!pWidget;
433 }
434 
OnSetFieldInputFocus(const WideString & text)435 void CFFL_InteractiveFormFiller::OnSetFieldInputFocus(const WideString& text) {
436   m_pCallbackIface->OnSetFieldInputFocus(text);
437 }
438 
Invalidate(IPDF_Page * pPage,const FX_RECT & rect)439 void CFFL_InteractiveFormFiller::Invalidate(IPDF_Page* pPage,
440                                             const FX_RECT& rect) {
441   m_pCallbackIface->Invalidate(pPage, rect);
442 }
443 
GetOrCreatePageView(IPDF_Page * pPage)444 CPDFSDK_PageView* CFFL_InteractiveFormFiller::GetOrCreatePageView(
445     IPDF_Page* pPage) {
446   return m_pCallbackIface->GetOrCreatePageView(pPage);
447 }
448 
GetPageView(IPDF_Page * pPage)449 CPDFSDK_PageView* CFFL_InteractiveFormFiller::GetPageView(IPDF_Page* pPage) {
450   return m_pCallbackIface->GetPageView(pPage);
451 }
452 
GetTimerHandler()453 CFX_Timer::HandlerIface* CFFL_InteractiveFormFiller::GetTimerHandler() {
454   return m_pCallbackIface->GetTimerHandler();
455 }
456 
OnChange()457 void CFFL_InteractiveFormFiller::OnChange() {
458   m_pCallbackIface->OnChange();
459 }
460 
IsVisible(CPDFSDK_Widget * pWidget)461 bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) {
462   return pWidget->IsVisible();
463 }
464 
IsReadOnly(CPDFSDK_Widget * pWidget)465 bool CFFL_InteractiveFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) {
466   int nFieldFlags = pWidget->GetFieldFlags();
467   return !!(nFieldFlags & pdfium::form_flags::kReadOnly);
468 }
469 
IsFillingAllowed(CPDFSDK_Widget * pWidget) const470 bool CFFL_InteractiveFormFiller::IsFillingAllowed(
471     CPDFSDK_Widget* pWidget) const {
472   if (pWidget->GetFieldType() == FormFieldType::kPushButton)
473     return false;
474 
475   return m_pCallbackIface->HasPermissions(
476       pdfium::access_permissions::kFillForm |
477       pdfium::access_permissions::kModifyAnnotation |
478       pdfium::access_permissions::kModifyContent);
479 }
480 
GetFormField(CPDFSDK_Widget * pWidget)481 CFFL_FormField* CFFL_InteractiveFormFiller::GetFormField(
482     CPDFSDK_Widget* pWidget) {
483   auto it = m_Map.find(pWidget);
484   return it != m_Map.end() ? it->second.get() : nullptr;
485 }
486 
GetOrCreateFormField(CPDFSDK_Widget * pWidget)487 CFFL_FormField* CFFL_InteractiveFormFiller::GetOrCreateFormField(
488     CPDFSDK_Widget* pWidget) {
489   CFFL_FormField* result = GetFormField(pWidget);
490   if (result)
491     return result;
492 
493   std::unique_ptr<CFFL_FormField> pFormField;
494   switch (pWidget->GetFieldType()) {
495     case FormFieldType::kPushButton:
496       pFormField = std::make_unique<CFFL_PushButton>(this, pWidget);
497       break;
498     case FormFieldType::kCheckBox:
499       pFormField = std::make_unique<CFFL_CheckBox>(this, pWidget);
500       break;
501     case FormFieldType::kRadioButton:
502       pFormField = std::make_unique<CFFL_RadioButton>(this, pWidget);
503       break;
504     case FormFieldType::kTextField:
505       pFormField = std::make_unique<CFFL_TextField>(this, pWidget);
506       break;
507     case FormFieldType::kListBox:
508       pFormField = std::make_unique<CFFL_ListBox>(this, pWidget);
509       break;
510     case FormFieldType::kComboBox:
511       pFormField = std::make_unique<CFFL_ComboBox>(this, pWidget);
512       break;
513     case FormFieldType::kUnknown:
514     default:
515       return nullptr;
516   }
517 
518   result = pFormField.get();
519   m_Map[pWidget] = std::move(pFormField);
520   return result;
521 }
522 
GetText(CPDFSDK_Widget * pWidget)523 WideString CFFL_InteractiveFormFiller::GetText(CPDFSDK_Widget* pWidget) {
524   CFFL_FormField* pFormField = GetFormField(pWidget);
525   return pFormField ? pFormField->GetText() : WideString();
526 }
527 
GetSelectedText(CPDFSDK_Widget * pWidget)528 WideString CFFL_InteractiveFormFiller::GetSelectedText(
529     CPDFSDK_Widget* pWidget) {
530   CFFL_FormField* pFormField = GetFormField(pWidget);
531   return pFormField ? pFormField->GetSelectedText() : WideString();
532 }
533 
ReplaceAndKeepSelection(CPDFSDK_Widget * pWidget,const WideString & text)534 void CFFL_InteractiveFormFiller::ReplaceAndKeepSelection(
535     CPDFSDK_Widget* pWidget,
536     const WideString& text) {
537   CFFL_FormField* pFormField = GetFormField(pWidget);
538   if (!pFormField)
539     return;
540 
541   pFormField->ReplaceAndKeepSelection(text);
542 }
543 
ReplaceSelection(CPDFSDK_Widget * pWidget,const WideString & text)544 void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Widget* pWidget,
545                                                   const WideString& text) {
546   CFFL_FormField* pFormField = GetFormField(pWidget);
547   if (!pFormField)
548     return;
549 
550   pFormField->ReplaceSelection(text);
551 }
552 
SelectAllText(CPDFSDK_Widget * pWidget)553 bool CFFL_InteractiveFormFiller::SelectAllText(CPDFSDK_Widget* pWidget) {
554   CFFL_FormField* pFormField = GetFormField(pWidget);
555   return pFormField && pFormField->SelectAllText();
556 }
557 
CanUndo(CPDFSDK_Widget * pWidget)558 bool CFFL_InteractiveFormFiller::CanUndo(CPDFSDK_Widget* pWidget) {
559   CFFL_FormField* pFormField = GetFormField(pWidget);
560   return pFormField && pFormField->CanUndo();
561 }
562 
CanRedo(CPDFSDK_Widget * pWidget)563 bool CFFL_InteractiveFormFiller::CanRedo(CPDFSDK_Widget* pWidget) {
564   CFFL_FormField* pFormField = GetFormField(pWidget);
565   return pFormField && pFormField->CanRedo();
566 }
567 
Undo(CPDFSDK_Widget * pWidget)568 bool CFFL_InteractiveFormFiller::Undo(CPDFSDK_Widget* pWidget) {
569   CFFL_FormField* pFormField = GetFormField(pWidget);
570   return pFormField && pFormField->Undo();
571 }
572 
Redo(CPDFSDK_Widget * pWidget)573 bool CFFL_InteractiveFormFiller::Redo(CPDFSDK_Widget* pWidget) {
574   CFFL_FormField* pFormField = GetFormField(pWidget);
575   return pFormField && pFormField->Redo();
576 }
577 
UnregisterFormField(CPDFSDK_Widget * pWidget)578 void CFFL_InteractiveFormFiller::UnregisterFormField(CPDFSDK_Widget* pWidget) {
579   auto it = m_Map.find(pWidget);
580   if (it == m_Map.end())
581     return;
582 
583   m_Map.erase(it);
584 }
585 
InvalidateRect(PerWindowData * pWidgetData,const CFX_FloatRect & rect)586 void CFFL_InteractiveFormFiller::InvalidateRect(PerWindowData* pWidgetData,
587                                                 const CFX_FloatRect& rect) {
588   auto* pPrivateData = static_cast<CFFL_PerWindowData*>(pWidgetData);
589   CPDFSDK_Widget* pWidget = pPrivateData->GetWidget();
590   if (!pWidget)
591     return;
592 
593   m_pCallbackIface->InvalidateRect(pWidget, rect);
594 }
595 
OutputSelectedRect(PerWindowData * pWidgetData,const CFX_FloatRect & rect)596 void CFFL_InteractiveFormFiller::OutputSelectedRect(PerWindowData* pWidgetData,
597                                                     const CFX_FloatRect& rect) {
598   auto* pPrivateData = static_cast<CFFL_PerWindowData*>(pWidgetData);
599   if (!pPrivateData)
600     return;
601 
602   CFFL_FormField* pFormField = pPrivateData->GetFormField();
603   if (!pFormField)
604     return;
605 
606   m_pCallbackIface->OutputSelectedRect(pFormField, rect);
607 }
608 
IsSelectionImplemented() const609 bool CFFL_InteractiveFormFiller::IsSelectionImplemented() const {
610   return m_pCallbackIface->IsSelectionImplemented();
611 }
612 
SetCursor(CursorStyle nCursorStyle)613 void CFFL_InteractiveFormFiller::SetCursor(CursorStyle nCursorStyle) {
614   m_pCallbackIface->SetCursor(nCursorStyle);
615 }
616 
QueryWherePopup(const IPWL_FillerNotify::PerWindowData * pAttached,float fPopupMin,float fPopupMax,bool * bBottom,float * fPopupRet)617 void CFFL_InteractiveFormFiller::QueryWherePopup(
618     const IPWL_FillerNotify::PerWindowData* pAttached,
619     float fPopupMin,
620     float fPopupMax,
621     bool* bBottom,
622     float* fPopupRet) {
623   auto* pData = static_cast<const CFFL_PerWindowData*>(pAttached);
624   CPDFSDK_Widget* pWidget = pData->GetWidget();
625   CPDF_Page* pPage = pWidget->GetPDFPage();
626 
627   CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0);
628   rcPageView.Normalize();
629 
630   CFX_FloatRect rcAnnot = pWidget->GetRect();
631   float fTop = 0.0f;
632   float fBottom = 0.0f;
633   switch (pWidget->GetRotate() / 90) {
634     default:
635     case 0:
636       fTop = rcPageView.top - rcAnnot.top;
637       fBottom = rcAnnot.bottom - rcPageView.bottom;
638       break;
639     case 1:
640       fTop = rcAnnot.left - rcPageView.left;
641       fBottom = rcPageView.right - rcAnnot.right;
642       break;
643     case 2:
644       fTop = rcAnnot.bottom - rcPageView.bottom;
645       fBottom = rcPageView.top - rcAnnot.top;
646       break;
647     case 3:
648       fTop = rcPageView.right - rcAnnot.right;
649       fBottom = rcAnnot.left - rcPageView.left;
650       break;
651   }
652 
653   constexpr float kMaxListBoxHeight = 140;
654   const float fMaxListBoxHeight =
655       pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax);
656 
657   if (fBottom > fMaxListBoxHeight) {
658     *fPopupRet = fMaxListBoxHeight;
659     *bBottom = true;
660     return;
661   }
662 
663   if (fTop > fMaxListBoxHeight) {
664     *fPopupRet = fMaxListBoxHeight;
665     *bBottom = false;
666     return;
667   }
668 
669   if (fTop > fBottom) {
670     *fPopupRet = fTop;
671     *bBottom = false;
672   } else {
673     *fPopupRet = fBottom;
674     *bBottom = true;
675   }
676 }
677 
OnKeyStrokeCommit(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)678 bool CFFL_InteractiveFormFiller::OnKeyStrokeCommit(
679     ObservedPtr<CPDFSDK_Widget>& pWidget,
680     const CPDFSDK_PageView* pPageView,
681     Mask<FWL_EVENTFLAG> nFlag) {
682   if (m_bNotifying)
683     return true;
684 
685   if (!pWidget->GetAAction(CPDF_AAction::kKeyStroke).HasDict())
686     return true;
687 
688   DCHECK(pPageView);
689   pWidget->ClearAppModified();
690 
691   AutoRestorer<bool> restorer(&m_bNotifying);
692   m_bNotifying = true;
693 
694   CFFL_FieldAction fa;
695   fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
696   fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
697   fa.bWillCommit = true;
698   fa.bKeyDown = true;
699   fa.bRC = true;
700 
701   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
702   pFormField->GetActionData(pPageView, CPDF_AAction::kKeyStroke, fa);
703   pFormField->SavePWLWindowState(pPageView);
704   pWidget->OnAAction(CPDF_AAction::kKeyStroke, &fa, pPageView);
705 
706   if (!pWidget)
707     return true;
708 
709   return fa.bRC;
710 }
711 
OnValidate(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)712 bool CFFL_InteractiveFormFiller::OnValidate(
713     ObservedPtr<CPDFSDK_Widget>& pWidget,
714     const CPDFSDK_PageView* pPageView,
715     Mask<FWL_EVENTFLAG> nFlag) {
716   if (m_bNotifying)
717     return true;
718 
719   if (!pWidget->GetAAction(CPDF_AAction::kValidate).HasDict())
720     return true;
721 
722   DCHECK(pPageView);
723   pWidget->ClearAppModified();
724 
725   AutoRestorer<bool> restorer(&m_bNotifying);
726   m_bNotifying = true;
727 
728   CFFL_FieldAction fa;
729   fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
730   fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
731   fa.bKeyDown = true;
732   fa.bRC = true;
733 
734   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
735   pFormField->GetActionData(pPageView, CPDF_AAction::kValidate, fa);
736   pFormField->SavePWLWindowState(pPageView);
737   pWidget->OnAAction(CPDF_AAction::kValidate, &fa, pPageView);
738 
739   if (!pWidget)
740     return true;
741 
742   return fa.bRC;
743 }
744 
OnCalculate(ObservedPtr<CPDFSDK_Widget> & pWidget)745 void CFFL_InteractiveFormFiller::OnCalculate(
746     ObservedPtr<CPDFSDK_Widget>& pWidget) {
747   if (m_bNotifying)
748     return;
749 
750   ObservedPtr<CPDFSDK_Annot> pObserved(pWidget.Get());
751   m_pCallbackIface->OnCalculate(pObserved);
752 }
753 
OnFormat(ObservedPtr<CPDFSDK_Widget> & pWidget)754 void CFFL_InteractiveFormFiller::OnFormat(
755     ObservedPtr<CPDFSDK_Widget>& pWidget) {
756   if (m_bNotifying)
757     return;
758 
759   ObservedPtr<CPDFSDK_Annot> pObserved(pWidget.Get());
760   m_pCallbackIface->OnFormat(pObserved);
761 }
762 
763 #ifdef PDF_ENABLE_XFA
OnClick(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)764 bool CFFL_InteractiveFormFiller::OnClick(ObservedPtr<CPDFSDK_Widget>& pWidget,
765                                          const CPDFSDK_PageView* pPageView,
766                                          Mask<FWL_EVENTFLAG> nFlag) {
767   if (m_bNotifying)
768     return false;
769 
770   if (!pWidget->HasXFAAAction(PDFSDK_XFA_Click))
771     return false;
772 
773   uint32_t nAge = pWidget->GetAppearanceAge();
774   uint32_t nValueAge = pWidget->GetValueAge();
775   {
776     AutoRestorer<bool> restorer(&m_bNotifying);
777     m_bNotifying = true;
778 
779     CFFL_FieldAction fa;
780     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
781     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
782 
783     pWidget->OnXFAAAction(PDFSDK_XFA_Click, &fa, pPageView);
784   }
785   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get()))
786     return true;
787   if (nAge == pWidget->GetAppearanceAge())
788     return false;
789 
790   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
791   if (pFormField)
792     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
793   return false;
794 }
795 
OnFull(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)796 bool CFFL_InteractiveFormFiller::OnFull(ObservedPtr<CPDFSDK_Widget>& pWidget,
797                                         const CPDFSDK_PageView* pPageView,
798                                         Mask<FWL_EVENTFLAG> nFlag) {
799   if (m_bNotifying)
800     return false;
801 
802   if (!pWidget->HasXFAAAction(PDFSDK_XFA_Full))
803     return false;
804 
805   uint32_t nAge = pWidget->GetAppearanceAge();
806   uint32_t nValueAge = pWidget->GetValueAge();
807   {
808     AutoRestorer<bool> restorer(&m_bNotifying);
809     m_bNotifying = true;
810 
811     CFFL_FieldAction fa;
812     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
813     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
814     pWidget->OnXFAAAction(PDFSDK_XFA_Full, &fa, pPageView);
815   }
816   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get()))
817     return true;
818   if (nAge == pWidget->GetAppearanceAge())
819     return false;
820 
821   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
822   if (pFormField)
823     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
824   return true;
825 }
826 
OnPreOpen(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)827 bool CFFL_InteractiveFormFiller::OnPreOpen(ObservedPtr<CPDFSDK_Widget>& pWidget,
828                                            const CPDFSDK_PageView* pPageView,
829                                            Mask<FWL_EVENTFLAG> nFlag) {
830   if (m_bNotifying)
831     return false;
832 
833   if (!pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen))
834     return false;
835 
836   uint32_t nAge = pWidget->GetAppearanceAge();
837   uint32_t nValueAge = pWidget->GetValueAge();
838   {
839     AutoRestorer<bool> restorer(&m_bNotifying);
840     m_bNotifying = true;
841 
842     CFFL_FieldAction fa;
843     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
844     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
845     pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, &fa, pPageView);
846   }
847   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get()))
848     return true;
849   if (nAge == pWidget->GetAppearanceAge())
850     return false;
851 
852   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
853   if (pFormField)
854     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
855   return true;
856 }
857 
OnPostOpen(ObservedPtr<CPDFSDK_Widget> & pWidget,const CPDFSDK_PageView * pPageView,Mask<FWL_EVENTFLAG> nFlag)858 bool CFFL_InteractiveFormFiller::OnPostOpen(
859     ObservedPtr<CPDFSDK_Widget>& pWidget,
860     const CPDFSDK_PageView* pPageView,
861     Mask<FWL_EVENTFLAG> nFlag) {
862   if (m_bNotifying)
863     return false;
864 
865   if (!pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen))
866     return false;
867 
868   uint32_t nAge = pWidget->GetAppearanceAge();
869   uint32_t nValueAge = pWidget->GetValueAge();
870   {
871     AutoRestorer<bool> restorer(&m_bNotifying);
872     m_bNotifying = true;
873 
874     CFFL_FieldAction fa;
875     fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
876     fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
877     pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, &fa, pPageView);
878   }
879   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get()))
880     return true;
881 
882   if (nAge == pWidget->GetAppearanceAge())
883     return false;
884 
885   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
886   if (pFormField)
887     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
888   return true;
889 }
890 #endif  // PDF_ENABLE_XFA
891 
892 // static
IsValidAnnot(const CPDFSDK_PageView * pPageView,CPDFSDK_Widget * pWidget)893 bool CFFL_InteractiveFormFiller::IsValidAnnot(const CPDFSDK_PageView* pPageView,
894                                               CPDFSDK_Widget* pWidget) {
895   return pPageView && pPageView->IsValidAnnot(pWidget->GetPDFAnnot());
896 }
897 
OnBeforeKeyStroke(const IPWL_FillerNotify::PerWindowData * pAttached,WideString & strChange,const WideString & strChangeEx,int nSelStart,int nSelEnd,bool bKeyDown,Mask<FWL_EVENTFLAG> nFlag)898 std::pair<bool, bool> CFFL_InteractiveFormFiller::OnBeforeKeyStroke(
899     const IPWL_FillerNotify::PerWindowData* pAttached,
900     WideString& strChange,
901     const WideString& strChangeEx,
902     int nSelStart,
903     int nSelEnd,
904     bool bKeyDown,
905     Mask<FWL_EVENTFLAG> nFlag) {
906   // Copy out of private data since the window owning it may not survive.
907   auto* pPrivateData = static_cast<const CFFL_PerWindowData*>(pAttached);
908   const CPDFSDK_PageView* pPageView = pPrivateData->GetPageView();
909   ObservedPtr<CPDFSDK_Widget> pWidget(pPrivateData->GetWidget());
910   DCHECK(pWidget);
911 
912   CFFL_FormField* pFormField = GetFormField(pWidget.Get());
913 
914 #ifdef PDF_ENABLE_XFA
915   if (pFormField->IsFieldFull(pPageView)) {
916     if (OnFull(pWidget, pPageView, nFlag) || !pWidget)
917       return {true, true};
918   }
919 #endif  // PDF_ENABLE_XFA
920 
921   if (m_bNotifying ||
922       !pWidget->GetAAction(CPDF_AAction::kKeyStroke).HasDict()) {
923     return {true, false};
924   }
925 
926   AutoRestorer<bool> restorer(&m_bNotifying);
927   m_bNotifying = true;
928 
929   uint32_t nAge = pWidget->GetAppearanceAge();
930   uint32_t nValueAge = pWidget->GetValueAge();
931 
932   CFFL_FieldAction fa;
933   fa.bModifier = CPWL_Wnd::IsCTRLKeyDown(nFlag);
934   fa.bShift = CPWL_Wnd::IsSHIFTKeyDown(nFlag);
935   fa.sChange = strChange;
936   fa.sChangeEx = strChangeEx;
937   fa.bKeyDown = bKeyDown;
938   fa.bWillCommit = false;
939   fa.bRC = true;
940   fa.nSelStart = nSelStart;
941   fa.nSelEnd = nSelEnd;
942   pFormField->GetActionData(pPageView, CPDF_AAction::kKeyStroke, fa);
943   pFormField->SavePWLWindowState(pPageView);
944 
945   bool action_status =
946       pWidget->OnAAction(CPDF_AAction::kKeyStroke, &fa, pPageView);
947 
948   if (!pWidget || !IsValidAnnot(pPageView, pWidget.Get())) {
949     return {true, true};
950   }
951   if (!action_status)
952     return {true, false};
953 
954   bool bExit = false;
955   if (nAge != pWidget->GetAppearanceAge()) {
956     pFormField->ResetPWLWindowForValueAge(pPageView, pWidget.Get(), nValueAge);
957     pPrivateData = pFormField->GetPerPWLWindowData(pPageView);
958     if (!pPrivateData)
959       return {true, true};
960 
961     pWidget.Reset(pPrivateData->GetWidget());
962     pPageView = pPrivateData->GetPageView();
963     bExit = true;
964   }
965   if (fa.bRC) {
966     pFormField->SetActionData(pPageView, CPDF_AAction::kKeyStroke, fa);
967   } else {
968     pFormField->RecreatePWLWindowFromSavedState(pPageView);
969   }
970   if (m_pCallbackIface->GetFocusAnnot() == pWidget)
971     return {false, bExit};
972 
973   pFormField->CommitData(pPageView, nFlag);
974   return {false, true};
975 }
976 
OnPopupPreOpen(const IPWL_FillerNotify::PerWindowData * pAttached,Mask<FWL_EVENTFLAG> nFlag)977 bool CFFL_InteractiveFormFiller::OnPopupPreOpen(
978     const IPWL_FillerNotify::PerWindowData* pAttached,
979     Mask<FWL_EVENTFLAG> nFlag) {
980 #ifdef PDF_ENABLE_XFA
981   auto* pData = static_cast<const CFFL_PerWindowData*>(pAttached);
982   DCHECK(pData->GetWidget());
983 
984   ObservedPtr<CPDFSDK_Widget> pObserved(pData->GetWidget());
985   return OnPreOpen(pObserved, pData->GetPageView(), nFlag) || !pObserved;
986 #else
987   return false;
988 #endif
989 }
990 
OnPopupPostOpen(const IPWL_FillerNotify::PerWindowData * pAttached,Mask<FWL_EVENTFLAG> nFlag)991 bool CFFL_InteractiveFormFiller::OnPopupPostOpen(
992     const IPWL_FillerNotify::PerWindowData* pAttached,
993     Mask<FWL_EVENTFLAG> nFlag) {
994 #ifdef PDF_ENABLE_XFA
995   auto* pData = static_cast<const CFFL_PerWindowData*>(pAttached);
996   DCHECK(pData->GetWidget());
997 
998   ObservedPtr<CPDFSDK_Widget> pObserved(pData->GetWidget());
999   return OnPostOpen(pObserved, pData->GetPageView(), nFlag) || !pObserved;
1000 #else
1001   return false;
1002 #endif
1003 }
1004