1// Copyright 2016 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/cpdfsdk_annothandlermgr.h"
8
9#include "core/fpdfapi/parser/cpdf_number.h"
10#include "core/fpdfapi/parser/cpdf_string.h"
11#include "core/fpdfdoc/cpdf_annot.h"
12#include "fpdfsdk/cba_annotiterator.h"
13#include "fpdfsdk/cpdfsdk_annot.h"
14#include "fpdfsdk/cpdfsdk_baannot.h"
15#include "fpdfsdk/cpdfsdk_baannothandler.h"
16#include "fpdfsdk/cpdfsdk_datetime.h"
17#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
18#include "fpdfsdk/cpdfsdk_pageview.h"
19#include "fpdfsdk/cpdfsdk_widgethandler.h"
20
21#ifdef PDF_ENABLE_XFA
22#include "fpdfsdk/cpdfsdk_xfawidgethandler.h"
23#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
24#include "xfa/fxfa/xfa_ffpageview.h"
25#include "xfa/fxfa/xfa_ffwidget.h"
26#endif  // PDF_ENABLE_XFA
27
28CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(
29    CPDFSDK_FormFillEnvironment* pFormFillEnv)
30    : m_pBAAnnotHandler(new CPDFSDK_BAAnnotHandler()),
31      m_pWidgetHandler(new CPDFSDK_WidgetHandler(pFormFillEnv)),
32#ifdef PDF_ENABLE_XFA
33      m_pXFAWidgetHandler(new CPDFSDK_XFAWidgetHandler(pFormFillEnv)),
34#endif  // PDF_ENABLE_XFA
35      m_pFormFillEnv(pFormFillEnv) {
36  m_pWidgetHandler->SetFormFiller(m_pFormFillEnv->GetInteractiveFormFiller());
37}
38
39CPDFSDK_AnnotHandlerMgr::~CPDFSDK_AnnotHandlerMgr() {}
40
41CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::NewAnnot(CPDF_Annot* pAnnot,
42                                                 CPDFSDK_PageView* pPageView) {
43  ASSERT(pPageView);
44  return GetAnnotHandler(pAnnot->GetSubtype())->NewAnnot(pAnnot, pPageView);
45}
46
47#ifdef PDF_ENABLE_XFA
48CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::NewAnnot(CXFA_FFWidget* pAnnot,
49                                                 CPDFSDK_PageView* pPageView) {
50  ASSERT(pAnnot);
51  ASSERT(pPageView);
52
53  return GetAnnotHandler(CPDF_Annot::Subtype::XFAWIDGET)
54      ->NewAnnot(pAnnot, pPageView);
55}
56#endif  // PDF_ENABLE_XFA
57
58void CPDFSDK_AnnotHandlerMgr::ReleaseAnnot(CPDFSDK_Annot* pAnnot) {
59  IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot);
60  pAnnotHandler->ReleaseAnnot(pAnnot);
61}
62
63void CPDFSDK_AnnotHandlerMgr::Annot_OnCreate(CPDFSDK_Annot* pAnnot) {
64  CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
65
66  CPDFSDK_DateTime curTime;
67  pPDFAnnot->GetAnnotDict()->SetNewFor<CPDF_String>(
68      "M", curTime.ToPDFDateTimeString(), false);
69  pPDFAnnot->GetAnnotDict()->SetNewFor<CPDF_Number>("F", 0);
70}
71
72void CPDFSDK_AnnotHandlerMgr::Annot_OnLoad(CPDFSDK_Annot* pAnnot) {
73  ASSERT(pAnnot);
74  GetAnnotHandler(pAnnot)->OnLoad(pAnnot);
75}
76
77IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler(
78    CPDFSDK_Annot* pAnnot) const {
79  return GetAnnotHandler(pAnnot->GetAnnotSubtype());
80}
81
82IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler(
83    CPDF_Annot::Subtype nAnnotSubtype) const {
84  if (nAnnotSubtype == CPDF_Annot::Subtype::WIDGET)
85    return m_pWidgetHandler.get();
86
87#ifdef PDF_ENABLE_XFA
88  if (nAnnotSubtype == CPDF_Annot::Subtype::XFAWIDGET)
89    return m_pXFAWidgetHandler.get();
90#endif  // PDF_ENABLE_XFA
91
92  return m_pBAAnnotHandler.get();
93}
94
95void CPDFSDK_AnnotHandlerMgr::Annot_OnDraw(CPDFSDK_PageView* pPageView,
96                                           CPDFSDK_Annot* pAnnot,
97                                           CFX_RenderDevice* pDevice,
98                                           CFX_Matrix* pUser2Device,
99                                           bool bDrawAnnots) {
100  ASSERT(pAnnot);
101  GetAnnotHandler(pAnnot)->OnDraw(pPageView, pAnnot, pDevice, pUser2Device,
102                                  bDrawAnnots);
103}
104
105bool CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDown(
106    CPDFSDK_PageView* pPageView,
107    CPDFSDK_Annot::ObservedPtr* pAnnot,
108    uint32_t nFlags,
109    const CFX_PointF& point) {
110  ASSERT(*pAnnot);
111  return GetAnnotHandler(pAnnot->Get())
112      ->OnLButtonDown(pPageView, pAnnot, nFlags, point);
113}
114
115bool CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonUp(
116    CPDFSDK_PageView* pPageView,
117    CPDFSDK_Annot::ObservedPtr* pAnnot,
118    uint32_t nFlags,
119    const CFX_PointF& point) {
120  ASSERT(*pAnnot);
121  return GetAnnotHandler(pAnnot->Get())
122      ->OnLButtonUp(pPageView, pAnnot, nFlags, point);
123}
124
125bool CPDFSDK_AnnotHandlerMgr::Annot_OnLButtonDblClk(
126    CPDFSDK_PageView* pPageView,
127    CPDFSDK_Annot::ObservedPtr* pAnnot,
128    uint32_t nFlags,
129    const CFX_PointF& point) {
130  ASSERT(*pAnnot);
131  return GetAnnotHandler(pAnnot->Get())
132      ->OnLButtonDblClk(pPageView, pAnnot, nFlags, point);
133}
134
135bool CPDFSDK_AnnotHandlerMgr::Annot_OnMouseMove(
136    CPDFSDK_PageView* pPageView,
137    CPDFSDK_Annot::ObservedPtr* pAnnot,
138    uint32_t nFlags,
139    const CFX_PointF& point) {
140  ASSERT(*pAnnot);
141  return GetAnnotHandler(pAnnot->Get())
142      ->OnMouseMove(pPageView, pAnnot, nFlags, point);
143}
144
145bool CPDFSDK_AnnotHandlerMgr::Annot_OnMouseWheel(
146    CPDFSDK_PageView* pPageView,
147    CPDFSDK_Annot::ObservedPtr* pAnnot,
148    uint32_t nFlags,
149    short zDelta,
150    const CFX_PointF& point) {
151  ASSERT(*pAnnot);
152  return GetAnnotHandler(pAnnot->Get())
153      ->OnMouseWheel(pPageView, pAnnot, nFlags, zDelta, point);
154}
155
156bool CPDFSDK_AnnotHandlerMgr::Annot_OnRButtonDown(
157    CPDFSDK_PageView* pPageView,
158    CPDFSDK_Annot::ObservedPtr* pAnnot,
159    uint32_t nFlags,
160    const CFX_PointF& point) {
161  ASSERT(*pAnnot);
162  return GetAnnotHandler(pAnnot->Get())
163      ->OnRButtonDown(pPageView, pAnnot, nFlags, point);
164}
165
166bool CPDFSDK_AnnotHandlerMgr::Annot_OnRButtonUp(
167    CPDFSDK_PageView* pPageView,
168    CPDFSDK_Annot::ObservedPtr* pAnnot,
169    uint32_t nFlags,
170    const CFX_PointF& point) {
171  ASSERT(*pAnnot);
172  return GetAnnotHandler(pAnnot->Get())
173      ->OnRButtonUp(pPageView, pAnnot, nFlags, point);
174}
175
176void CPDFSDK_AnnotHandlerMgr::Annot_OnMouseEnter(
177    CPDFSDK_PageView* pPageView,
178    CPDFSDK_Annot::ObservedPtr* pAnnot,
179    uint32_t nFlag) {
180  ASSERT(*pAnnot);
181  GetAnnotHandler(pAnnot->Get())->OnMouseEnter(pPageView, pAnnot, nFlag);
182}
183
184void CPDFSDK_AnnotHandlerMgr::Annot_OnMouseExit(
185    CPDFSDK_PageView* pPageView,
186    CPDFSDK_Annot::ObservedPtr* pAnnot,
187    uint32_t nFlag) {
188  ASSERT(*pAnnot);
189  GetAnnotHandler(pAnnot->Get())->OnMouseExit(pPageView, pAnnot, nFlag);
190}
191
192bool CPDFSDK_AnnotHandlerMgr::Annot_OnChar(CPDFSDK_Annot* pAnnot,
193                                           uint32_t nChar,
194                                           uint32_t nFlags) {
195  return GetAnnotHandler(pAnnot)->OnChar(pAnnot, nChar, nFlags);
196}
197
198bool CPDFSDK_AnnotHandlerMgr::Annot_OnKeyDown(CPDFSDK_Annot* pAnnot,
199                                              int nKeyCode,
200                                              int nFlag) {
201  if (m_pFormFillEnv->IsCTRLKeyDown(nFlag) ||
202      m_pFormFillEnv->IsALTKeyDown(nFlag)) {
203    return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
204  }
205
206  CPDFSDK_PageView* pPage = pAnnot->GetPageView();
207  CPDFSDK_Annot* pFocusAnnot = pPage->GetFocusAnnot();
208  if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
209    CPDFSDK_Annot::ObservedPtr pNext(
210        GetNextAnnot(pFocusAnnot, !m_pFormFillEnv->IsSHIFTKeyDown(nFlag)));
211    if (pNext && pNext.Get() != pFocusAnnot) {
212      pPage->GetFormFillEnv()->SetFocusAnnot(&pNext);
213      return true;
214    }
215  }
216
217  return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
218}
219
220bool CPDFSDK_AnnotHandlerMgr::Annot_OnKeyUp(CPDFSDK_Annot* pAnnot,
221                                            int nKeyCode,
222                                            int nFlag) {
223  return false;
224}
225
226bool CPDFSDK_AnnotHandlerMgr::Annot_OnSetFocus(
227    CPDFSDK_Annot::ObservedPtr* pAnnot,
228    uint32_t nFlag) {
229  ASSERT(*pAnnot);
230  return GetAnnotHandler(pAnnot->Get())->OnSetFocus(pAnnot, nFlag);
231}
232
233bool CPDFSDK_AnnotHandlerMgr::Annot_OnKillFocus(
234    CPDFSDK_Annot::ObservedPtr* pAnnot,
235    uint32_t nFlag) {
236  ASSERT(*pAnnot);
237  return GetAnnotHandler(pAnnot->Get())->OnKillFocus(pAnnot, nFlag);
238}
239
240#ifdef PDF_ENABLE_XFA
241bool CPDFSDK_AnnotHandlerMgr::Annot_OnChangeFocus(
242    CPDFSDK_Annot::ObservedPtr* pSetAnnot,
243    CPDFSDK_Annot::ObservedPtr* pKillAnnot) {
244  bool bXFA = (*pSetAnnot && (*pSetAnnot)->GetXFAWidget()) ||
245              (*pKillAnnot && (*pKillAnnot)->GetXFAWidget());
246
247  if (bXFA) {
248    if (IPDFSDK_AnnotHandler* pXFAAnnotHandler =
249            GetAnnotHandler(CPDF_Annot::Subtype::XFAWIDGET))
250      return pXFAAnnotHandler->OnXFAChangedFocus(pKillAnnot, pSetAnnot);
251  }
252
253  return true;
254}
255#endif  // PDF_ENABLE_XFA
256
257CFX_FloatRect CPDFSDK_AnnotHandlerMgr::Annot_OnGetViewBBox(
258    CPDFSDK_PageView* pPageView,
259    CPDFSDK_Annot* pAnnot) {
260  ASSERT(pAnnot);
261  return GetAnnotHandler(pAnnot)->GetViewBBox(pPageView, pAnnot);
262}
263
264bool CPDFSDK_AnnotHandlerMgr::Annot_OnHitTest(CPDFSDK_PageView* pPageView,
265                                              CPDFSDK_Annot* pAnnot,
266                                              const CFX_PointF& point) {
267  ASSERT(pAnnot);
268  IPDFSDK_AnnotHandler* pAnnotHandler = GetAnnotHandler(pAnnot);
269  if (pAnnotHandler->CanAnswer(pAnnot))
270    return pAnnotHandler->HitTest(pPageView, pAnnot, point);
271
272  return false;
273}
274
275CPDFSDK_Annot* CPDFSDK_AnnotHandlerMgr::GetNextAnnot(CPDFSDK_Annot* pSDKAnnot,
276                                                     bool bNext) {
277#ifdef PDF_ENABLE_XFA
278  CPDFSDK_PageView* pPageView = pSDKAnnot->GetPageView();
279  CPDFXFA_Page* pPage = pPageView->GetPDFXFAPage();
280  if (!pPage)
281    return nullptr;
282  if (pPage->GetPDFPage()) {  // for pdf annots.
283    CBA_AnnotIterator ai(pSDKAnnot->GetPageView(),
284                         pSDKAnnot->GetAnnotSubtype());
285    CPDFSDK_Annot* pNext =
286        bNext ? ai.GetNextAnnot(pSDKAnnot) : ai.GetPrevAnnot(pSDKAnnot);
287    return pNext;
288  }
289  // for xfa annots
290  std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
291      pPage->GetXFAPageView()->CreateWidgetIterator(
292          XFA_TRAVERSEWAY_Tranvalse, XFA_WidgetStatus_Visible |
293                                         XFA_WidgetStatus_Viewable |
294                                         XFA_WidgetStatus_Focused));
295  if (!pWidgetIterator)
296    return nullptr;
297  if (pWidgetIterator->GetCurrentWidget() != pSDKAnnot->GetXFAWidget())
298    pWidgetIterator->SetCurrentWidget(pSDKAnnot->GetXFAWidget());
299  CXFA_FFWidget* hNextFocus =
300      bNext ? pWidgetIterator->MoveToNext() : pWidgetIterator->MoveToPrevious();
301  if (!hNextFocus && pSDKAnnot)
302    hNextFocus = pWidgetIterator->MoveToFirst();
303
304  return pPageView->GetAnnotByXFAWidget(hNextFocus);
305#else   // PDF_ENABLE_XFA
306  CBA_AnnotIterator ai(pSDKAnnot->GetPageView(), CPDF_Annot::Subtype::WIDGET);
307  return bNext ? ai.GetNextAnnot(pSDKAnnot) : ai.GetPrevAnnot(pSDKAnnot);
308#endif  // PDF_ENABLE_XFA
309}
310