• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/formfiller/FFL_IFormFiller.h"
8 
9 #include "fpdfsdk/include/formfiller/FFL_CheckBox.h"
10 #include "fpdfsdk/include/formfiller/FFL_ComboBox.h"
11 #include "fpdfsdk/include/formfiller/FFL_FormFiller.h"
12 #include "fpdfsdk/include/formfiller/FFL_ListBox.h"
13 #include "fpdfsdk/include/formfiller/FFL_PushButton.h"
14 #include "fpdfsdk/include/formfiller/FFL_RadioButton.h"
15 #include "fpdfsdk/include/formfiller/FFL_TextField.h"
16 #include "fpdfsdk/include/fsdk_mgr.h"
17 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
18 
19 #define FFL_MAXLISTBOXHEIGHT 140.0f
20 
CFFL_IFormFiller(CPDFDoc_Environment * pApp)21 CFFL_IFormFiller::CFFL_IFormFiller(CPDFDoc_Environment* pApp)
22     : m_pApp(pApp), m_bNotifying(FALSE) {}
23 
~CFFL_IFormFiller()24 CFFL_IFormFiller::~CFFL_IFormFiller() {
25   for (auto& it : m_Maps)
26     delete it.second;
27   m_Maps.clear();
28 }
29 
Annot_HitTest(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,CPDF_Point point)30 FX_BOOL CFFL_IFormFiller::Annot_HitTest(CPDFSDK_PageView* pPageView,
31                                         CPDFSDK_Annot* pAnnot,
32                                         CPDF_Point point) {
33   CPDF_Rect rc = pAnnot->GetRect();
34   if (rc.Contains(point.x, point.y))
35     return TRUE;
36   return FALSE;
37 }
38 
GetViewBBox(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot)39 FX_RECT CFFL_IFormFiller::GetViewBBox(CPDFSDK_PageView* pPageView,
40                                       CPDFSDK_Annot* pAnnot) {
41   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE))
42     return pFormFiller->GetViewBBox(pPageView, pAnnot);
43 
44   ASSERT(pPageView);
45 
46   CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
47   CPDF_Rect rcAnnot;
48   pPDFAnnot->GetRect(rcAnnot);
49 
50   CPDF_Rect rcWin = CPWL_Utils::InflateRect(rcAnnot, 1);
51   return rcWin.GetOutterRect();
52 }
53 
OnDraw(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,FX_DWORD dwFlags)54 void CFFL_IFormFiller::OnDraw(CPDFSDK_PageView* pPageView,
55                               CPDFSDK_Annot* pAnnot,
56                               CFX_RenderDevice* pDevice,
57                               CFX_Matrix* pUser2Device,
58                               FX_DWORD dwFlags) {
59   ASSERT(pPageView);
60   CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
61 
62   if (IsVisible(pWidget)) {
63     if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
64       if (pFormFiller->IsValid()) {
65         pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device, dwFlags);
66         pAnnot->GetPDFPage();
67 
68         CPDFSDK_Document* pDocument = m_pApp->GetSDKDocument();
69         if (pDocument->GetFocusAnnot() == pAnnot) {
70           CPDF_Rect rcFocus = pFormFiller->GetFocusBox(pPageView);
71           if (!rcFocus.IsEmpty()) {
72             CFX_PathData path;
73             path.SetPointCount(5);
74             path.SetPoint(0, rcFocus.left, rcFocus.top, FXPT_MOVETO);
75             path.SetPoint(1, rcFocus.left, rcFocus.bottom, FXPT_LINETO);
76             path.SetPoint(2, rcFocus.right, rcFocus.bottom, FXPT_LINETO);
77             path.SetPoint(3, rcFocus.right, rcFocus.top, FXPT_LINETO);
78             path.SetPoint(4, rcFocus.left, rcFocus.top, FXPT_LINETO);
79 
80             CFX_GraphStateData gsd;
81             gsd.SetDashCount(1);
82             gsd.m_DashArray[0] = 1.0f;
83             gsd.m_DashPhase = 0;
84             gsd.m_LineWidth = 1.0f;
85             pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
86                               ArgbEncode(255, 0, 0, 0), FXFILL_ALTERNATE);
87           }
88         }
89         return;
90       }
91     }
92 
93     if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE))
94       pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, pUser2Device,
95                                   dwFlags);
96     else
97       pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, NULL);
98 
99     if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget))
100       pWidget->DrawShadow(pDevice, pPageView);
101   }
102 }
103 
OnCreate(CPDFSDK_Annot * pAnnot)104 void CFFL_IFormFiller::OnCreate(CPDFSDK_Annot* pAnnot) {
105   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
106     pFormFiller->OnCreate(pAnnot);
107   }
108 }
109 
OnLoad(CPDFSDK_Annot * pAnnot)110 void CFFL_IFormFiller::OnLoad(CPDFSDK_Annot* pAnnot) {
111   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
112     pFormFiller->OnLoad(pAnnot);
113   }
114 }
115 
OnDelete(CPDFSDK_Annot * pAnnot)116 void CFFL_IFormFiller::OnDelete(CPDFSDK_Annot* pAnnot) {
117   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
118     pFormFiller->OnDelete(pAnnot);
119   }
120 
121   UnRegisterFormFiller(pAnnot);
122 }
123 
OnMouseEnter(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlag)124 void CFFL_IFormFiller::OnMouseEnter(CPDFSDK_PageView* pPageView,
125                                     CPDFSDK_Annot* pAnnot,
126                                     FX_UINT nFlag) {
127   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
128 
129   if (!m_bNotifying) {
130     CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
131     if (pWidget->GetAAction(CPDF_AAction::CursorEnter)) {
132       m_bNotifying = TRUE;
133 
134       int nValueAge = pWidget->GetValueAge();
135 
136       pWidget->ClearAppModified();
137 
138       ASSERT(pPageView);
139 
140       PDFSDK_FieldAction fa;
141       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
142       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
143       pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView);
144       m_bNotifying = FALSE;
145 
146       if (pWidget->IsAppModified()) {
147         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
148           pFormFiller->ResetPDFWindow(pPageView,
149                                       pWidget->GetValueAge() == nValueAge);
150         }
151       }
152     }
153   }
154 
155   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, TRUE)) {
156     pFormFiller->OnMouseEnter(pPageView, pAnnot);
157   }
158 }
159 
OnMouseExit(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlag)160 void CFFL_IFormFiller::OnMouseExit(CPDFSDK_PageView* pPageView,
161                                    CPDFSDK_Annot* pAnnot,
162                                    FX_UINT nFlag) {
163   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
164 
165   if (!m_bNotifying) {
166     CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
167     if (pWidget->GetAAction(CPDF_AAction::CursorExit)) {
168       m_bNotifying = TRUE;
169       pWidget->GetAppearanceAge();
170       int nValueAge = pWidget->GetValueAge();
171       pWidget->ClearAppModified();
172 
173       ASSERT(pPageView);
174 
175       PDFSDK_FieldAction fa;
176       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
177       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
178 
179       pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView);
180       m_bNotifying = FALSE;
181 
182       if (pWidget->IsAppModified()) {
183         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
184           pFormFiller->ResetPDFWindow(pPageView,
185                                       nValueAge == pWidget->GetValueAge());
186         }
187       }
188     }
189   }
190 
191   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
192     pFormFiller->OnMouseExit(pPageView, pAnnot);
193   }
194 }
195 
OnLButtonDown(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)196 FX_BOOL CFFL_IFormFiller::OnLButtonDown(CPDFSDK_PageView* pPageView,
197                                         CPDFSDK_Annot* pAnnot,
198                                         FX_UINT nFlags,
199                                         const CPDF_Point& point) {
200   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
201 
202   if (!m_bNotifying) {
203     CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
204     if (Annot_HitTest(pPageView, pAnnot, point) &&
205         pWidget->GetAAction(CPDF_AAction::ButtonDown)) {
206       m_bNotifying = TRUE;
207       pWidget->GetAppearanceAge();
208       int nValueAge = pWidget->GetValueAge();
209       pWidget->ClearAppModified();
210 
211       ASSERT(pPageView);
212 
213       PDFSDK_FieldAction fa;
214       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlags);
215       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlags);
216       pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView);
217       m_bNotifying = FALSE;
218 
219       if (!IsValidAnnot(pPageView, pAnnot))
220         return TRUE;
221 
222       if (pWidget->IsAppModified()) {
223         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
224           pFormFiller->ResetPDFWindow(pPageView,
225                                       nValueAge == pWidget->GetValueAge());
226         }
227       }
228     }
229   }
230 
231   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
232     return pFormFiller->OnLButtonDown(pPageView, pAnnot, nFlags, point);
233   }
234 
235   return FALSE;
236 }
237 
OnLButtonUp(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)238 FX_BOOL CFFL_IFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView,
239                                       CPDFSDK_Annot* pAnnot,
240                                       FX_UINT nFlags,
241                                       const CPDF_Point& point) {
242   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
243   CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
244   CPDFSDK_Document* pDocument = m_pApp->GetSDKDocument();
245 
246   switch (pWidget->GetFieldType()) {
247     case FIELDTYPE_PUSHBUTTON:
248     case FIELDTYPE_CHECKBOX:
249     case FIELDTYPE_RADIOBUTTON:
250       if (GetViewBBox(pPageView, pAnnot).Contains((int)point.x, (int)point.y))
251         pDocument->SetFocusAnnot(pAnnot);
252       break;
253     default:
254       pDocument->SetFocusAnnot(pAnnot);
255       break;
256   }
257 
258   FX_BOOL bRet = FALSE;
259 
260   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
261     bRet = pFormFiller->OnLButtonUp(pPageView, pAnnot, nFlags, point);
262   }
263 
264   if (pDocument->GetFocusAnnot() == pAnnot) {
265     FX_BOOL bExit = FALSE;
266     FX_BOOL bReset = FALSE;
267     OnButtonUp(pWidget, pPageView, bReset, bExit, nFlags);
268     if (bExit)
269       return TRUE;
270 #ifdef PDF_ENABLE_XFA
271     OnClick(pWidget, pPageView, bReset, bExit, nFlags);
272     if (bExit)
273       return TRUE;
274 #endif  // PDF_ENABLE_XFA
275   }
276   return bRet;
277 }
278 
OnButtonUp(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bReset,FX_BOOL & bExit,FX_UINT nFlag)279 void CFFL_IFormFiller::OnButtonUp(CPDFSDK_Widget* pWidget,
280                                   CPDFSDK_PageView* pPageView,
281                                   FX_BOOL& bReset,
282                                   FX_BOOL& bExit,
283                                   FX_UINT nFlag) {
284   ASSERT(pWidget);
285 
286   if (!m_bNotifying) {
287     if (pWidget->GetAAction(CPDF_AAction::ButtonUp)) {
288       m_bNotifying = TRUE;
289       int nAge = pWidget->GetAppearanceAge();
290       int nValueAge = pWidget->GetValueAge();
291 
292       ASSERT(pPageView);
293 
294       PDFSDK_FieldAction fa;
295       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
296       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
297 
298       pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView);
299       m_bNotifying = FALSE;
300 
301       if (!IsValidAnnot(pPageView, pWidget)) {
302         bExit = TRUE;
303         return;
304       }
305 
306       if (nAge != pWidget->GetAppearanceAge()) {
307         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
308           pFormFiller->ResetPDFWindow(pPageView,
309                                       nValueAge == pWidget->GetValueAge());
310         }
311 
312         bReset = TRUE;
313       }
314     }
315   }
316 }
317 
OnLButtonDblClk(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)318 FX_BOOL CFFL_IFormFiller::OnLButtonDblClk(CPDFSDK_PageView* pPageView,
319                                           CPDFSDK_Annot* pAnnot,
320                                           FX_UINT nFlags,
321                                           const CPDF_Point& point) {
322   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
323 
324   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
325     return pFormFiller->OnLButtonDblClk(pPageView, pAnnot, nFlags, point);
326   }
327 
328   return FALSE;
329 }
330 
OnMouseMove(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)331 FX_BOOL CFFL_IFormFiller::OnMouseMove(CPDFSDK_PageView* pPageView,
332                                       CPDFSDK_Annot* pAnnot,
333                                       FX_UINT nFlags,
334                                       const CPDF_Point& point) {
335   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
336 
337   // change cursor
338   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, TRUE)) {
339     return pFormFiller->OnMouseMove(pPageView, pAnnot, nFlags, point);
340   }
341 
342   return FALSE;
343 }
344 
OnMouseWheel(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,short zDelta,const CPDF_Point & point)345 FX_BOOL CFFL_IFormFiller::OnMouseWheel(CPDFSDK_PageView* pPageView,
346                                        CPDFSDK_Annot* pAnnot,
347                                        FX_UINT nFlags,
348                                        short zDelta,
349                                        const CPDF_Point& point) {
350   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
351 
352   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
353     return pFormFiller->OnMouseWheel(pPageView, pAnnot, nFlags, zDelta, point);
354   }
355 
356   return FALSE;
357 }
358 
OnRButtonDown(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)359 FX_BOOL CFFL_IFormFiller::OnRButtonDown(CPDFSDK_PageView* pPageView,
360                                         CPDFSDK_Annot* pAnnot,
361                                         FX_UINT nFlags,
362                                         const CPDF_Point& point) {
363   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
364 
365   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
366     return pFormFiller->OnRButtonDown(pPageView, pAnnot, nFlags, point);
367   }
368 
369   return FALSE;
370 }
371 
OnRButtonUp(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,FX_UINT nFlags,const CPDF_Point & point)372 FX_BOOL CFFL_IFormFiller::OnRButtonUp(CPDFSDK_PageView* pPageView,
373                                       CPDFSDK_Annot* pAnnot,
374                                       FX_UINT nFlags,
375                                       const CPDF_Point& point) {
376   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
377 
378   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
379     return pFormFiller->OnRButtonUp(pPageView, pAnnot, nFlags, point);
380   }
381 
382   return FALSE;
383 }
384 
OnKeyDown(CPDFSDK_Annot * pAnnot,FX_UINT nKeyCode,FX_UINT nFlags)385 FX_BOOL CFFL_IFormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot,
386                                     FX_UINT nKeyCode,
387                                     FX_UINT nFlags) {
388   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
389 
390   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
391     return pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags);
392   }
393 
394   return FALSE;
395 }
396 
OnChar(CPDFSDK_Annot * pAnnot,FX_UINT nChar,FX_UINT nFlags)397 FX_BOOL CFFL_IFormFiller::OnChar(CPDFSDK_Annot* pAnnot,
398                                  FX_UINT nChar,
399                                  FX_UINT nFlags) {
400   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
401   if (nChar == FWL_VKEY_Tab)
402     return TRUE;
403 
404   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE))
405     return pFormFiller->OnChar(pAnnot, nChar, nFlags);
406 
407   return FALSE;
408 }
409 
OnSetFocus(CPDFSDK_Annot * pAnnot,FX_UINT nFlag)410 FX_BOOL CFFL_IFormFiller::OnSetFocus(CPDFSDK_Annot* pAnnot, FX_UINT nFlag) {
411   if (!pAnnot)
412     return FALSE;
413 
414   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
415 
416   if (!m_bNotifying) {
417     CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
418     if (pWidget->GetAAction(CPDF_AAction::GetFocus)) {
419       m_bNotifying = TRUE;
420       pWidget->GetAppearanceAge();
421 
422       int nValueAge = pWidget->GetValueAge();
423       pWidget->ClearAppModified();
424 
425       CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
426       ASSERT(pPageView);
427 
428       PDFSDK_FieldAction fa;
429       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
430       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
431 
432       CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, TRUE);
433       if (!pFormFiller)
434         return FALSE;
435       pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa);
436       pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView);
437       m_bNotifying = FALSE;
438 
439       if (pWidget->IsAppModified()) {
440         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
441           pFormFiller->ResetPDFWindow(pPageView,
442                                       nValueAge == pWidget->GetValueAge());
443         }
444       }
445     }
446   }
447 
448   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, TRUE))
449     pFormFiller->SetFocusForAnnot(pAnnot, nFlag);
450 
451   return TRUE;
452 }
453 
OnKillFocus(CPDFSDK_Annot * pAnnot,FX_UINT nFlag)454 FX_BOOL CFFL_IFormFiller::OnKillFocus(CPDFSDK_Annot* pAnnot, FX_UINT nFlag) {
455   if (!pAnnot)
456     return FALSE;
457   ASSERT(pAnnot->GetPDFAnnot()->GetSubType() == "Widget");
458 
459   if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, FALSE)) {
460     pFormFiller->KillFocusForAnnot(pAnnot, nFlag);
461 
462     if (!m_bNotifying) {
463       CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
464       if (pWidget->GetAAction(CPDF_AAction::LoseFocus)) {
465         m_bNotifying = TRUE;
466         pWidget->ClearAppModified();
467 
468         CPDFSDK_PageView* pPageView = pWidget->GetPageView();
469         ASSERT(pPageView);
470 
471         PDFSDK_FieldAction fa;
472         fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
473         fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
474 
475         pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa);
476 
477         pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView);
478         m_bNotifying = FALSE;
479       }
480     }
481   }
482 
483   return TRUE;
484 }
485 
IsVisible(CPDFSDK_Widget * pWidget)486 FX_BOOL CFFL_IFormFiller::IsVisible(CPDFSDK_Widget* pWidget) {
487   return pWidget->IsVisible();
488 }
489 
IsReadOnly(CPDFSDK_Widget * pWidget)490 FX_BOOL CFFL_IFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) {
491   int nFieldFlags = pWidget->GetFieldFlags();
492   return (nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY;
493 }
494 
IsFillingAllowed(CPDFSDK_Widget * pWidget)495 FX_BOOL CFFL_IFormFiller::IsFillingAllowed(CPDFSDK_Widget* pWidget) {
496   if (pWidget->GetFieldType() == FIELDTYPE_PUSHBUTTON)
497     return TRUE;
498 
499   CPDF_Page* pPage = pWidget->GetPDFPage();
500   CPDF_Document* pDocument = pPage->m_pDocument;
501   FX_DWORD dwPermissions = pDocument->GetUserPermissions();
502   return (dwPermissions & FPDFPERM_FILL_FORM) ||
503          (dwPermissions & FPDFPERM_ANNOT_FORM) ||
504          (dwPermissions & FPDFPERM_MODIFY);
505 }
506 
GetFormFiller(CPDFSDK_Annot * pAnnot,FX_BOOL bRegister)507 CFFL_FormFiller* CFFL_IFormFiller::GetFormFiller(CPDFSDK_Annot* pAnnot,
508                                                  FX_BOOL bRegister) {
509   auto it = m_Maps.find(pAnnot);
510   if (it != m_Maps.end())
511     return it->second;
512 
513   if (!bRegister)
514     return nullptr;
515 
516   CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
517   int nFieldType = pWidget->GetFieldType();
518   CFFL_FormFiller* pFormFiller;
519   switch (nFieldType) {
520     case FIELDTYPE_PUSHBUTTON:
521       pFormFiller = new CFFL_PushButton(m_pApp, pWidget);
522       break;
523     case FIELDTYPE_CHECKBOX:
524       pFormFiller = new CFFL_CheckBox(m_pApp, pWidget);
525       break;
526     case FIELDTYPE_RADIOBUTTON:
527       pFormFiller = new CFFL_RadioButton(m_pApp, pWidget);
528       break;
529     case FIELDTYPE_TEXTFIELD:
530       pFormFiller = new CFFL_TextField(m_pApp, pWidget);
531       break;
532     case FIELDTYPE_LISTBOX:
533       pFormFiller = new CFFL_ListBox(m_pApp, pWidget);
534       break;
535     case FIELDTYPE_COMBOBOX:
536       pFormFiller = new CFFL_ComboBox(m_pApp, pWidget);
537       break;
538     case FIELDTYPE_UNKNOWN:
539     default:
540       pFormFiller = nullptr;
541       break;
542   }
543 
544   if (!pFormFiller)
545     return nullptr;
546 
547   m_Maps[pAnnot] = pFormFiller;
548   return pFormFiller;
549 }
550 
RemoveFormFiller(CPDFSDK_Annot * pAnnot)551 void CFFL_IFormFiller::RemoveFormFiller(CPDFSDK_Annot* pAnnot) {
552   if (pAnnot) {
553     UnRegisterFormFiller(pAnnot);
554   }
555 }
556 
UnRegisterFormFiller(CPDFSDK_Annot * pAnnot)557 void CFFL_IFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) {
558   auto it = m_Maps.find(pAnnot);
559   if (it == m_Maps.end())
560     return;
561 
562   delete it->second;
563   m_Maps.erase(it);
564 }
565 
QueryWherePopup(void * pPrivateData,FX_FLOAT fPopupMin,FX_FLOAT fPopupMax,int32_t & nRet,FX_FLOAT & fPopupRet)566 void CFFL_IFormFiller::QueryWherePopup(void* pPrivateData,
567                                        FX_FLOAT fPopupMin,
568                                        FX_FLOAT fPopupMax,
569                                        int32_t& nRet,
570                                        FX_FLOAT& fPopupRet) {
571   CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
572 
573   CPDF_Rect rcPageView(0, 0, 0, 0);
574   rcPageView.right = pData->pWidget->GetPDFPage()->GetPageWidth();
575   rcPageView.bottom = pData->pWidget->GetPDFPage()->GetPageHeight();
576   rcPageView.Normalize();
577 
578   CPDF_Rect rcAnnot = pData->pWidget->GetRect();
579 
580   FX_FLOAT fTop = 0.0f;
581   FX_FLOAT fBottom = 0.0f;
582 
583   CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pData->pWidget;
584   switch (pWidget->GetRotate() / 90) {
585     default:
586     case 0:
587       fTop = rcPageView.top - rcAnnot.top;
588       fBottom = rcAnnot.bottom - rcPageView.bottom;
589       break;
590     case 1:
591       fTop = rcAnnot.left - rcPageView.left;
592       fBottom = rcPageView.right - rcAnnot.right;
593       break;
594     case 2:
595       fTop = rcAnnot.bottom - rcPageView.bottom;
596       fBottom = rcPageView.top - rcAnnot.top;
597       break;
598     case 3:
599       fTop = rcPageView.right - rcAnnot.right;
600       fBottom = rcAnnot.left - rcPageView.left;
601       break;
602   }
603 
604   FX_FLOAT fFactHeight = 0;
605   FX_BOOL bBottom = TRUE;
606   FX_FLOAT fMaxListBoxHeight = 0;
607   if (fPopupMax > FFL_MAXLISTBOXHEIGHT) {
608     if (fPopupMin > FFL_MAXLISTBOXHEIGHT) {
609       fMaxListBoxHeight = fPopupMin;
610     } else {
611       fMaxListBoxHeight = FFL_MAXLISTBOXHEIGHT;
612     }
613   } else {
614     fMaxListBoxHeight = fPopupMax;
615   }
616 
617   if (fBottom > fMaxListBoxHeight) {
618     fFactHeight = fMaxListBoxHeight;
619     bBottom = TRUE;
620   } else {
621     if (fTop > fMaxListBoxHeight) {
622       fFactHeight = fMaxListBoxHeight;
623       bBottom = FALSE;
624     } else {
625       if (fTop > fBottom) {
626         fFactHeight = fTop;
627         bBottom = FALSE;
628       } else {
629         fFactHeight = fBottom;
630         bBottom = TRUE;
631       }
632     }
633   }
634 
635   nRet = bBottom ? 0 : 1;
636   fPopupRet = fFactHeight;
637 }
638 
OnKeyStrokeCommit(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bRC,FX_BOOL & bExit,FX_DWORD nFlag)639 void CFFL_IFormFiller::OnKeyStrokeCommit(CPDFSDK_Widget* pWidget,
640                                          CPDFSDK_PageView* pPageView,
641                                          FX_BOOL& bRC,
642                                          FX_BOOL& bExit,
643                                          FX_DWORD nFlag) {
644   if (!m_bNotifying) {
645     if (pWidget->GetAAction(CPDF_AAction::KeyStroke)) {
646       m_bNotifying = TRUE;
647       pWidget->ClearAppModified();
648 
649       ASSERT(pPageView);
650 
651       PDFSDK_FieldAction fa;
652       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
653       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
654       fa.bWillCommit = TRUE;
655       fa.bKeyDown = TRUE;
656       fa.bRC = TRUE;
657 
658       CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE);
659       pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa);
660       pFormFiller->SaveState(pPageView);
661 
662       PDFSDK_FieldAction faOld = fa;
663       pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView);
664 
665       bRC = fa.bRC;
666       m_bNotifying = FALSE;
667     }
668   }
669 }
670 
OnValidate(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bRC,FX_BOOL & bExit,FX_DWORD nFlag)671 void CFFL_IFormFiller::OnValidate(CPDFSDK_Widget* pWidget,
672                                   CPDFSDK_PageView* pPageView,
673                                   FX_BOOL& bRC,
674                                   FX_BOOL& bExit,
675                                   FX_DWORD nFlag) {
676   if (!m_bNotifying) {
677     if (pWidget->GetAAction(CPDF_AAction::Validate)) {
678       m_bNotifying = TRUE;
679       pWidget->ClearAppModified();
680 
681       ASSERT(pPageView);
682 
683       PDFSDK_FieldAction fa;
684       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
685       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
686       fa.bKeyDown = TRUE;
687       fa.bRC = TRUE;
688 
689       CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE);
690       pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa);
691       pFormFiller->SaveState(pPageView);
692 
693       PDFSDK_FieldAction faOld = fa;
694       pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView);
695 
696       bRC = fa.bRC;
697       m_bNotifying = FALSE;
698     }
699   }
700 }
701 
OnCalculate(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bExit,FX_DWORD nFlag)702 void CFFL_IFormFiller::OnCalculate(CPDFSDK_Widget* pWidget,
703                                    CPDFSDK_PageView* pPageView,
704                                    FX_BOOL& bExit,
705                                    FX_DWORD nFlag) {
706   if (!m_bNotifying) {
707     ASSERT(pWidget);
708     CPDFSDK_Document* pDocument = pPageView->GetSDKDocument();
709     CPDFSDK_InterForm* pInterForm =
710         (CPDFSDK_InterForm*)pDocument->GetInterForm();
711     pInterForm->OnCalculate(pWidget->GetFormField());
712 
713     m_bNotifying = FALSE;
714   }
715 }
716 
OnFormat(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bExit,FX_DWORD nFlag)717 void CFFL_IFormFiller::OnFormat(CPDFSDK_Widget* pWidget,
718                                 CPDFSDK_PageView* pPageView,
719                                 FX_BOOL& bExit,
720                                 FX_DWORD nFlag) {
721   if (!m_bNotifying) {
722     ASSERT(pWidget);
723     CPDFSDK_Document* pDocument = pPageView->GetSDKDocument();
724     CPDFSDK_InterForm* pInterForm =
725         (CPDFSDK_InterForm*)pDocument->GetInterForm();
726 
727     FX_BOOL bFormated = FALSE;
728     CFX_WideString sValue =
729         pInterForm->OnFormat(pWidget->GetFormField(), bFormated);
730 
731     if (bExit)
732       return;
733 
734     if (bFormated) {
735       pInterForm->ResetFieldAppearance(pWidget->GetFormField(), sValue.c_str(),
736                                        TRUE);
737       pInterForm->UpdateField(pWidget->GetFormField());
738     }
739 
740     m_bNotifying = FALSE;
741   }
742 }
743 
744 #ifdef PDF_ENABLE_XFA
OnClick(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bReset,FX_BOOL & bExit,FX_UINT nFlag)745 void CFFL_IFormFiller::OnClick(CPDFSDK_Widget* pWidget,
746                                CPDFSDK_PageView* pPageView,
747                                FX_BOOL& bReset,
748                                FX_BOOL& bExit,
749                                FX_UINT nFlag) {
750   ASSERT(pWidget != NULL);
751 
752   if (!m_bNotifying) {
753     if (pWidget->HasXFAAAction(PDFSDK_XFA_Click)) {
754       m_bNotifying = TRUE;
755       int nAge = pWidget->GetAppearanceAge();
756       int nValueAge = pWidget->GetValueAge();
757 
758       PDFSDK_FieldAction fa;
759       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
760       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
761 
762       pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView);
763       m_bNotifying = FALSE;
764 
765       if (!IsValidAnnot(pPageView, pWidget)) {
766         bExit = TRUE;
767         return;
768       }
769 
770       if (nAge != pWidget->GetAppearanceAge()) {
771         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
772           pFormFiller->ResetPDFWindow(pPageView,
773                                       nValueAge == pWidget->GetValueAge());
774         }
775 
776         bReset = TRUE;
777       }
778     }
779   }
780 }
781 
OnFull(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bReset,FX_BOOL & bExit,FX_UINT nFlag)782 void CFFL_IFormFiller::OnFull(CPDFSDK_Widget* pWidget,
783                               CPDFSDK_PageView* pPageView,
784                               FX_BOOL& bReset,
785                               FX_BOOL& bExit,
786                               FX_UINT nFlag) {
787   ASSERT(pWidget != NULL);
788 
789   if (!m_bNotifying) {
790     if (pWidget->HasXFAAAction(PDFSDK_XFA_Full)) {
791       m_bNotifying = TRUE;
792       int nAge = pWidget->GetAppearanceAge();
793       int nValueAge = pWidget->GetValueAge();
794 
795       PDFSDK_FieldAction fa;
796       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
797       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
798 
799       pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView);
800       m_bNotifying = FALSE;
801 
802       if (!IsValidAnnot(pPageView, pWidget)) {
803         bExit = TRUE;
804         return;
805       }
806 
807       if (nAge != pWidget->GetAppearanceAge()) {
808         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
809           pFormFiller->ResetPDFWindow(pPageView,
810                                       nValueAge == pWidget->GetValueAge());
811         }
812 
813         bReset = TRUE;
814       }
815     }
816   }
817 }
818 
OnPopupPreOpen(void * pPrivateData,FX_BOOL & bExit,FX_DWORD nFlag)819 void CFFL_IFormFiller::OnPopupPreOpen(void* pPrivateData,
820                                       FX_BOOL& bExit,
821                                       FX_DWORD nFlag) {
822   ASSERT(pPrivateData != NULL);
823   CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
824   ASSERT(pData->pWidget != NULL);
825 
826   FX_BOOL bTempReset = FALSE;
827   FX_BOOL bTempExit = FALSE;
828   this->OnPreOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit,
829                   nFlag);
830 
831   if (bTempReset || bTempExit) {
832     bExit = TRUE;
833   }
834 }
835 
OnPopupPostOpen(void * pPrivateData,FX_BOOL & bExit,FX_DWORD nFlag)836 void CFFL_IFormFiller::OnPopupPostOpen(void* pPrivateData,
837                                        FX_BOOL& bExit,
838                                        FX_DWORD nFlag) {
839   ASSERT(pPrivateData != NULL);
840   CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
841   ASSERT(pData->pWidget != NULL);
842 
843   FX_BOOL bTempReset = FALSE;
844   FX_BOOL bTempExit = FALSE;
845   this->OnPostOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit,
846                    nFlag);
847 
848   if (bTempReset || bTempExit) {
849     bExit = TRUE;
850   }
851 }
852 
OnPreOpen(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bReset,FX_BOOL & bExit,FX_UINT nFlag)853 void CFFL_IFormFiller::OnPreOpen(CPDFSDK_Widget* pWidget,
854                                  CPDFSDK_PageView* pPageView,
855                                  FX_BOOL& bReset,
856                                  FX_BOOL& bExit,
857                                  FX_UINT nFlag) {
858   ASSERT(pWidget != NULL);
859 
860   if (!m_bNotifying) {
861     if (pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) {
862       m_bNotifying = TRUE;
863       int nAge = pWidget->GetAppearanceAge();
864       int nValueAge = pWidget->GetValueAge();
865 
866       PDFSDK_FieldAction fa;
867       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
868       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
869 
870       pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView);
871       m_bNotifying = FALSE;
872 
873       if (!IsValidAnnot(pPageView, pWidget)) {
874         bExit = TRUE;
875         return;
876       }
877 
878       if (nAge != pWidget->GetAppearanceAge()) {
879         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
880           pFormFiller->ResetPDFWindow(pPageView,
881                                       nValueAge == pWidget->GetValueAge());
882         }
883 
884         bReset = TRUE;
885       }
886     }
887   }
888 }
889 
OnPostOpen(CPDFSDK_Widget * pWidget,CPDFSDK_PageView * pPageView,FX_BOOL & bReset,FX_BOOL & bExit,FX_UINT nFlag)890 void CFFL_IFormFiller::OnPostOpen(CPDFSDK_Widget* pWidget,
891                                   CPDFSDK_PageView* pPageView,
892                                   FX_BOOL& bReset,
893                                   FX_BOOL& bExit,
894                                   FX_UINT nFlag) {
895   ASSERT(pWidget != NULL);
896 
897   if (!m_bNotifying) {
898     if (pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) {
899       m_bNotifying = TRUE;
900       int nAge = pWidget->GetAppearanceAge();
901       int nValueAge = pWidget->GetValueAge();
902 
903       PDFSDK_FieldAction fa;
904       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
905       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
906 
907       pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView);
908       m_bNotifying = FALSE;
909 
910       if (!IsValidAnnot(pPageView, pWidget)) {
911         bExit = TRUE;
912         return;
913       }
914 
915       if (nAge != pWidget->GetAppearanceAge()) {
916         if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, FALSE)) {
917           pFormFiller->ResetPDFWindow(pPageView,
918                                       nValueAge == pWidget->GetValueAge());
919         }
920 
921         bReset = TRUE;
922       }
923     }
924   }
925 }
926 #endif  // PDF_ENABLE_XFA
927 
IsValidAnnot(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot)928 FX_BOOL CFFL_IFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView,
929                                        CPDFSDK_Annot* pAnnot) {
930   if (pPageView)
931     return pPageView->IsValidAnnot(pAnnot->GetPDFAnnot());
932 
933   return FALSE;
934 }
935 
OnBeforeKeyStroke(void * pPrivateData,CFX_WideString & strChange,const CFX_WideString & strChangeEx,int nSelStart,int nSelEnd,FX_BOOL bKeyDown,FX_BOOL & bRC,FX_BOOL & bExit,FX_DWORD nFlag)936 void CFFL_IFormFiller::OnBeforeKeyStroke(void* pPrivateData,
937                                          CFX_WideString& strChange,
938                                          const CFX_WideString& strChangeEx,
939                                          int nSelStart,
940                                          int nSelEnd,
941                                          FX_BOOL bKeyDown,
942                                          FX_BOOL& bRC,
943                                          FX_BOOL& bExit,
944                                          FX_DWORD nFlag) {
945   CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
946   ASSERT(pData->pWidget);
947 
948   CFFL_FormFiller* pFormFiller = GetFormFiller(pData->pWidget, FALSE);
949 
950 #ifdef PDF_ENABLE_XFA
951   if (pFormFiller->IsFieldFull(pData->pPageView)) {
952     FX_BOOL bFullExit = FALSE;
953     FX_BOOL bFullReset = FALSE;
954     OnFull(pData->pWidget, pData->pPageView, bFullReset, bFullExit, nFlag);
955 
956     if (bFullReset || bFullExit) {
957       bExit = TRUE;
958       return;
959     }
960   }
961 #endif  // PDF_ENABLE_XFA
962 
963   if (!m_bNotifying) {
964     if (pData->pWidget->GetAAction(CPDF_AAction::KeyStroke)) {
965       m_bNotifying = TRUE;
966       int nAge = pData->pWidget->GetAppearanceAge();
967       int nValueAge = pData->pWidget->GetValueAge();
968 
969       CPDFSDK_Document* pDocument = pData->pPageView->GetSDKDocument();
970 
971       PDFSDK_FieldAction fa;
972       fa.bModifier = m_pApp->FFI_IsCTRLKeyDown(nFlag);
973       fa.bShift = m_pApp->FFI_IsSHIFTKeyDown(nFlag);
974       fa.sChange = strChange;
975       fa.sChangeEx = strChangeEx;
976       fa.bKeyDown = bKeyDown;
977       fa.bWillCommit = FALSE;
978       fa.bRC = TRUE;
979       fa.nSelStart = nSelStart;
980       fa.nSelEnd = nSelEnd;
981 
982       pFormFiller->GetActionData(pData->pPageView, CPDF_AAction::KeyStroke, fa);
983       pFormFiller->SaveState(pData->pPageView);
984 
985       if (pData->pWidget->OnAAction(CPDF_AAction::KeyStroke, fa,
986                                     pData->pPageView)) {
987         if (!IsValidAnnot(pData->pPageView, pData->pWidget)) {
988           bExit = TRUE;
989           m_bNotifying = FALSE;
990           return;
991         }
992 
993         if (nAge != pData->pWidget->GetAppearanceAge()) {
994           CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow(
995               pData->pPageView, nValueAge == pData->pWidget->GetValueAge());
996           pData = (CFFL_PrivateData*)pWnd->GetAttachedData();
997           bExit = TRUE;
998         }
999 
1000         if (fa.bRC) {
1001           pFormFiller->SetActionData(pData->pPageView, CPDF_AAction::KeyStroke,
1002                                      fa);
1003           bRC = FALSE;
1004         } else {
1005           pFormFiller->RestoreState(pData->pPageView);
1006           bRC = FALSE;
1007         }
1008 
1009         if (pDocument->GetFocusAnnot() != pData->pWidget) {
1010           pFormFiller->CommitData(pData->pPageView, nFlag);
1011           bExit = TRUE;
1012         }
1013       } else {
1014         if (!IsValidAnnot(pData->pPageView, pData->pWidget)) {
1015           bExit = TRUE;
1016           m_bNotifying = FALSE;
1017           return;
1018         }
1019       }
1020 
1021       m_bNotifying = FALSE;
1022     }
1023   }
1024 }
1025