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 <map>
8 
9 #include "fpdfsdk/include/pdfwindow/PWL_ScrollBar.h"
10 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
11 #include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"
12 
GetPWLTimeMap()13 static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
14   // Leak the object at shutdown.
15   static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
16   return *timeMap;
17 }
18 
CPWL_Timer(CPWL_TimerHandler * pAttached,IFX_SystemHandler * pSystemHandler)19 CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
20                        IFX_SystemHandler* pSystemHandler)
21     : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
22   ASSERT(m_pAttached);
23   ASSERT(m_pSystemHandler);
24 }
25 
~CPWL_Timer()26 CPWL_Timer::~CPWL_Timer() {
27   KillPWLTimer();
28 }
29 
SetPWLTimer(int32_t nElapse)30 int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
31   if (m_nTimerID != 0)
32     KillPWLTimer();
33   m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
34 
35   GetPWLTimeMap()[m_nTimerID] = this;
36   return m_nTimerID;
37 }
38 
KillPWLTimer()39 void CPWL_Timer::KillPWLTimer() {
40   if (m_nTimerID == 0)
41     return;
42 
43   m_pSystemHandler->KillTimer(m_nTimerID);
44   GetPWLTimeMap().erase(m_nTimerID);
45   m_nTimerID = 0;
46 }
47 
TimerProc(int32_t idEvent)48 void CPWL_Timer::TimerProc(int32_t idEvent) {
49   auto it = GetPWLTimeMap().find(idEvent);
50   if (it == GetPWLTimeMap().end())
51     return;
52 
53   CPWL_Timer* pTimer = it->second;
54   if (pTimer->m_pAttached)
55     pTimer->m_pAttached->TimerProc();
56 }
57 
CPWL_TimerHandler()58 CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL) {}
59 
~CPWL_TimerHandler()60 CPWL_TimerHandler::~CPWL_TimerHandler() {
61   delete m_pTimer;
62 }
63 
BeginTimer(int32_t nElapse)64 void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
65   if (!m_pTimer)
66     m_pTimer = new CPWL_Timer(this, GetSystemHandler());
67 
68   if (m_pTimer)
69     m_pTimer->SetPWLTimer(nElapse);
70 }
71 
EndTimer()72 void CPWL_TimerHandler::EndTimer() {
73   if (m_pTimer)
74     m_pTimer->KillPWLTimer();
75 }
76 
TimerProc()77 void CPWL_TimerHandler::TimerProc() {}
78 
79 class CPWL_MsgControl {
80   friend class CPWL_Wnd;
81 
82  public:
CPWL_MsgControl(CPWL_Wnd * pWnd)83   explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
84     m_pCreatedWnd = pWnd;
85     Default();
86   }
87 
~CPWL_MsgControl()88   ~CPWL_MsgControl() {
89     Default();
90   }
91 
Default()92   void Default() {
93     m_aMousePath.RemoveAll();
94     m_aKeyboardPath.RemoveAll();
95     m_pMainMouseWnd = NULL;
96     m_pMainKeyboardWnd = NULL;
97   }
98 
IsWndCreated(const CPWL_Wnd * pWnd) const99   FX_BOOL IsWndCreated(const CPWL_Wnd* pWnd) const {
100     return m_pCreatedWnd == pWnd;
101   }
102 
IsMainCaptureMouse(const CPWL_Wnd * pWnd) const103   FX_BOOL IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
104     return pWnd == m_pMainMouseWnd;
105   }
106 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const107   FX_BOOL IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
108     if (pWnd) {
109       for (int32_t i = 0, sz = m_aMousePath.GetSize(); i < sz; i++) {
110         if (m_aMousePath.GetAt(i) == pWnd)
111           return TRUE;
112       }
113     }
114 
115     return FALSE;
116   }
117 
IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const118   FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
119     return pWnd == m_pMainKeyboardWnd;
120   }
121 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const122   FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
123     if (pWnd) {
124       for (int32_t i = 0, sz = m_aKeyboardPath.GetSize(); i < sz; i++) {
125         if (m_aKeyboardPath.GetAt(i) == pWnd)
126           return TRUE;
127       }
128     }
129 
130     return FALSE;
131   }
132 
SetFocus(CPWL_Wnd * pWnd)133   void SetFocus(CPWL_Wnd* pWnd) {
134     m_aKeyboardPath.RemoveAll();
135 
136     if (pWnd) {
137       m_pMainKeyboardWnd = pWnd;
138 
139       CPWL_Wnd* pParent = pWnd;
140       while (pParent) {
141         m_aKeyboardPath.Add(pParent);
142         pParent = pParent->GetParentWindow();
143       }
144 
145       pWnd->OnSetFocus();
146     }
147   }
148 
KillFocus()149   void KillFocus() {
150     if (m_aKeyboardPath.GetSize() > 0)
151       if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
152         pWnd->OnKillFocus();
153 
154     m_pMainKeyboardWnd = NULL;
155     m_aKeyboardPath.RemoveAll();
156   }
157 
SetCapture(CPWL_Wnd * pWnd)158   void SetCapture(CPWL_Wnd* pWnd) {
159     m_aMousePath.RemoveAll();
160 
161     if (pWnd) {
162       m_pMainMouseWnd = pWnd;
163 
164       CPWL_Wnd* pParent = pWnd;
165       while (pParent) {
166         m_aMousePath.Add(pParent);
167         pParent = pParent->GetParentWindow();
168       }
169     }
170   }
171 
ReleaseCapture()172   void ReleaseCapture() {
173     m_pMainMouseWnd = NULL;
174     m_aMousePath.RemoveAll();
175   }
176 
177  private:
178   CFX_ArrayTemplate<CPWL_Wnd*> m_aMousePath;
179   CFX_ArrayTemplate<CPWL_Wnd*> m_aKeyboardPath;
180   CPWL_Wnd* m_pCreatedWnd;
181   CPWL_Wnd* m_pMainMouseWnd;
182   CPWL_Wnd* m_pMainKeyboardWnd;
183 };
184 
CPWL_Wnd()185 CPWL_Wnd::CPWL_Wnd()
186     : m_pVScrollBar(NULL),
187       m_rcWindow(),
188       m_rcClip(),
189       m_bCreated(FALSE),
190       m_bVisible(FALSE),
191       m_bNotifying(FALSE),
192       m_bEnabled(TRUE) {}
193 
~CPWL_Wnd()194 CPWL_Wnd::~CPWL_Wnd() {
195   ASSERT(m_bCreated == FALSE);
196 }
197 
GetClassName() const198 CFX_ByteString CPWL_Wnd::GetClassName() const {
199   return "CPWL_Wnd";
200 }
201 
Create(const PWL_CREATEPARAM & cp)202 void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
203   if (!IsValid()) {
204     m_sPrivateParam = cp;
205 
206     OnCreate(m_sPrivateParam);
207 
208     m_sPrivateParam.rcRectWnd.Normalize();
209     m_rcWindow = m_sPrivateParam.rcRectWnd;
210     m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);
211 
212     CreateMsgControl();
213 
214     if (m_sPrivateParam.pParentWnd)
215       m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);
216 
217     PWL_CREATEPARAM ccp = m_sPrivateParam;
218 
219     ccp.dwFlags &= 0xFFFF0000L;  // remove sub styles
220     ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0);
221 
222     CreateScrollBar(ccp);
223     CreateChildWnd(ccp);
224 
225     m_bVisible = HasFlag(PWS_VISIBLE);
226 
227     OnCreated();
228 
229     RePosChildWnd();
230     m_bCreated = TRUE;
231   }
232 }
233 
OnCreate(PWL_CREATEPARAM & cp)234 void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}
235 
OnCreated()236 void CPWL_Wnd::OnCreated() {}
237 
OnDestroy()238 void CPWL_Wnd::OnDestroy() {}
239 
InvalidateFocusHandler(IPWL_FocusHandler * handler)240 void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
241   if (m_sPrivateParam.pFocusHandler == handler)
242     m_sPrivateParam.pFocusHandler = nullptr;
243 }
244 
InvalidateProvider(IPWL_Provider * provider)245 void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
246   if (m_sPrivateParam.pProvider == provider)
247     m_sPrivateParam.pProvider = nullptr;
248 }
249 
Destroy()250 void CPWL_Wnd::Destroy() {
251   KillFocus();
252 
253   OnDestroy();
254 
255   if (m_bCreated) {
256     for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
257       if (CPWL_Wnd* pChild = m_aChildren[i]) {
258         pChild->Destroy();
259         delete pChild;
260         pChild = NULL;
261       }
262     }
263 
264     if (m_sPrivateParam.pParentWnd)
265       m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
266     m_bCreated = FALSE;
267   }
268 
269   DestroyMsgControl();
270 
271   FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
272   m_aChildren.RemoveAll();
273   m_pVScrollBar = NULL;
274 }
275 
Move(const CPDF_Rect & rcNew,FX_BOOL bReset,FX_BOOL bRefresh)276 void CPWL_Wnd::Move(const CPDF_Rect& rcNew, FX_BOOL bReset, FX_BOOL bRefresh) {
277   if (IsValid()) {
278     CPDF_Rect rcOld = GetWindowRect();
279 
280     m_rcWindow = rcNew;
281     m_rcWindow.Normalize();
282 
283     if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
284         rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
285       if (bReset) {
286         RePosChildWnd();
287       }
288     }
289     if (bRefresh) {
290       InvalidateRectMove(rcOld, rcNew);
291     }
292 
293     m_sPrivateParam.rcRectWnd = m_rcWindow;
294   }
295 }
296 
InvalidateRectMove(const CPDF_Rect & rcOld,const CPDF_Rect & rcNew)297 void CPWL_Wnd::InvalidateRectMove(const CPDF_Rect& rcOld,
298                                   const CPDF_Rect& rcNew) {
299   CPDF_Rect rcUnion = rcOld;
300   rcUnion.Union(rcNew);
301 
302   InvalidateRect(&rcUnion);
303 }
304 
GetAppearanceStream(CFX_ByteTextBuf & sAppStream)305 void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
306   if (IsValid() && IsVisible()) {
307     GetThisAppearanceStream(sAppStream);
308     GetChildAppearanceStream(sAppStream);
309   }
310 }
311 
312 // if don't set,Get default apperance stream
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)313 void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
314   CPDF_Rect rectWnd = GetWindowRect();
315   if (!rectWnd.IsEmpty()) {
316     CFX_ByteTextBuf sThis;
317 
318     if (HasFlag(PWS_BACKGROUND))
319       sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());
320 
321     if (HasFlag(PWS_BORDER)) {
322       sThis << CPWL_Utils::GetBorderAppStream(
323           rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
324           GetBorderLeftTopColor(GetBorderStyle()),
325           GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
326           GetBorderDash());
327     }
328 
329     sAppStream << sThis;
330   }
331 }
332 
GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)333 void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
334   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
335     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
336       pChild->GetAppearanceStream(sAppStream);
337     }
338   }
339 }
340 
DrawAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)341 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
342                               CFX_Matrix* pUser2Device) {
343   if (IsValid() && IsVisible()) {
344     DrawThisAppearance(pDevice, pUser2Device);
345     DrawChildAppearance(pDevice, pUser2Device);
346   }
347 }
348 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)349 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
350                                   CFX_Matrix* pUser2Device) {
351   CPDF_Rect rectWnd = GetWindowRect();
352   if (!rectWnd.IsEmpty()) {
353     if (HasFlag(PWS_BACKGROUND)) {
354       CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
355           rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
356       CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
357                                GetBackgroundColor(), GetTransparency());
358     }
359 
360     if (HasFlag(PWS_BORDER))
361       CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd,
362                              (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
363                              GetBorderLeftTopColor(GetBorderStyle()),
364                              GetBorderRightBottomColor(GetBorderStyle()),
365                              GetBorderStyle(), GetTransparency());
366   }
367 }
368 
DrawChildAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)369 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
370                                    CFX_Matrix* pUser2Device) {
371   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
372     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
373       CFX_Matrix mt = pChild->GetChildMatrix();
374       if (mt.IsIdentity()) {
375         pChild->DrawAppearance(pDevice, pUser2Device);
376       } else {
377         mt.Concat(*pUser2Device);
378         pChild->DrawAppearance(pDevice, &mt);
379       }
380     }
381   }
382 }
383 
InvalidateRect(CPDF_Rect * pRect)384 void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect) {
385   if (IsValid()) {
386     CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();
387 
388     if (!HasFlag(PWS_NOREFRESHCLIP)) {
389       CPDF_Rect rcClip = GetClipRect();
390       if (!rcClip.IsEmpty()) {
391         rcRefresh.Intersect(rcClip);
392       }
393     }
394 
395     FX_RECT rcWin = PWLtoWnd(rcRefresh);
396     rcWin.left -= PWL_INVALIDATE_INFLATE;
397     rcWin.top -= PWL_INVALIDATE_INFLATE;
398     rcWin.right += PWL_INVALIDATE_INFLATE;
399     rcWin.bottom += PWL_INVALIDATE_INFLATE;
400 
401     if (IFX_SystemHandler* pSH = GetSystemHandler()) {
402       if (FX_HWND hWnd = GetAttachedHWnd()) {
403         pSH->InvalidateRect(hWnd, rcWin);
404       }
405     }
406   }
407 }
408 
409 #define PWL_IMPLEMENT_KEY_METHOD(key_method_name)                      \
410   FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag) {   \
411     if (IsValid() && IsVisible() && IsEnabled()) {                     \
412       if (IsWndCaptureKeyboard(this)) {                                \
413         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) { \
414           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {               \
415             if (IsWndCaptureKeyboard(pChild)) {                        \
416               return pChild->key_method_name(nChar, nFlag);            \
417             }                                                          \
418           }                                                            \
419         }                                                              \
420       }                                                                \
421     }                                                                  \
422     return FALSE;                                                      \
423   }
424 
425 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)                        \
426   FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point& point,               \
427                                       FX_DWORD nFlag) {                      \
428     if (IsValid() && IsVisible() && IsEnabled()) {                           \
429       if (IsWndCaptureMouse(this)) {                                         \
430         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
431           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
432             if (IsWndCaptureMouse(pChild)) {                                 \
433               return pChild->mouse_method_name(pChild->ParentToChild(point), \
434                                                nFlag);                       \
435             }                                                                \
436           }                                                                  \
437         }                                                                    \
438         SetCursor();                                                         \
439       } else {                                                               \
440         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
441           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
442             if (pChild->WndHitTest(pChild->ParentToChild(point))) {          \
443               return pChild->mouse_method_name(pChild->ParentToChild(point), \
444                                                nFlag);                       \
445             }                                                                \
446           }                                                                  \
447         }                                                                    \
448         if (WndHitTest(point))                                               \
449           SetCursor();                                                       \
450       }                                                                      \
451     }                                                                        \
452     return FALSE;                                                            \
453   }
454 
455 PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)456 PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
457 PWL_IMPLEMENT_KEY_METHOD(OnChar)
458 
459 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
460 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
461 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
462 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
463 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
464 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
465 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
466 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
467 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
468 
469 FX_BOOL CPWL_Wnd::OnMouseWheel(short zDelta,
470                                const CPDF_Point& point,
471                                FX_DWORD nFlag) {
472   if (IsValid() && IsVisible() && IsEnabled()) {
473     SetCursor();
474     if (IsWndCaptureKeyboard(this)) {
475       for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
476         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
477           if (IsWndCaptureKeyboard(pChild)) {
478             return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point),
479                                         nFlag);
480           }
481         }
482       }
483     }
484   }
485   return FALSE;
486 }
487 
AddChild(CPWL_Wnd * pWnd)488 void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
489   m_aChildren.Add(pWnd);
490 }
491 
RemoveChild(CPWL_Wnd * pWnd)492 void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
493   for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
494     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
495       if (pChild == pWnd) {
496         m_aChildren.RemoveAt(i);
497         break;
498       }
499     }
500   }
501 }
502 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)503 void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
504                         FX_DWORD msg,
505                         intptr_t wParam,
506                         intptr_t lParam) {
507   switch (msg) {
508     case PNM_ADDCHILD:
509       AddChild(pWnd);
510       break;
511     case PNM_REMOVECHILD:
512       RemoveChild(pWnd);
513       break;
514     default:
515       break;
516   }
517 }
518 
IsValid() const519 FX_BOOL CPWL_Wnd::IsValid() const {
520   return m_bCreated;
521 }
522 
GetCreationParam() const523 const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
524   return m_sPrivateParam;
525 }
526 
GetParentWindow() const527 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
528   return m_sPrivateParam.pParentWnd;
529 }
530 
GetWindowRect() const531 CPDF_Rect CPWL_Wnd::GetWindowRect() const {
532   return m_rcWindow;
533 }
534 
GetClientRect() const535 CPDF_Rect CPWL_Wnd::GetClientRect() const {
536   CPDF_Rect rcWindow = GetWindowRect();
537   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
538       rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
539   if (CPWL_ScrollBar* pVSB = GetVScrollBar())
540     rcClient.right -= pVSB->GetScrollBarWidth();
541 
542   rcClient.Normalize();
543   return rcWindow.Contains(rcClient) ? rcClient : CPDF_Rect();
544 }
545 
GetCenterPoint() const546 CPDF_Point CPWL_Wnd::GetCenterPoint() const {
547   CPDF_Rect rcClient = GetClientRect();
548   return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
549                     (rcClient.top + rcClient.bottom) * 0.5f);
550 }
551 
HasFlag(FX_DWORD dwFlags) const552 FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const {
553   return (m_sPrivateParam.dwFlags & dwFlags) != 0;
554 }
555 
RemoveFlag(FX_DWORD dwFlags)556 void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags) {
557   m_sPrivateParam.dwFlags &= ~dwFlags;
558 }
559 
AddFlag(FX_DWORD dwFlags)560 void CPWL_Wnd::AddFlag(FX_DWORD dwFlags) {
561   m_sPrivateParam.dwFlags |= dwFlags;
562 }
563 
GetBackgroundColor() const564 CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
565   return m_sPrivateParam.sBackgroundColor;
566 }
567 
SetBackgroundColor(const CPWL_Color & color)568 void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
569   m_sPrivateParam.sBackgroundColor = color;
570 }
571 
SetTextColor(const CPWL_Color & color)572 void CPWL_Wnd::SetTextColor(const CPWL_Color& color) {
573   m_sPrivateParam.sTextColor = color;
574 }
575 
SetTextStrokeColor(const CPWL_Color & color)576 void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color& color) {
577   m_sPrivateParam.sTextStrokeColor = color;
578 }
579 
GetTextColor() const580 CPWL_Color CPWL_Wnd::GetTextColor() const {
581   return m_sPrivateParam.sTextColor;
582 }
583 
GetTextStrokeColor() const584 CPWL_Color CPWL_Wnd::GetTextStrokeColor() const {
585   return m_sPrivateParam.sTextStrokeColor;
586 }
587 
GetBorderStyle() const588 int32_t CPWL_Wnd::GetBorderStyle() const {
589   return m_sPrivateParam.nBorderStyle;
590 }
591 
SetBorderStyle(int32_t nBorderStyle)592 void CPWL_Wnd::SetBorderStyle(int32_t nBorderStyle) {
593   if (HasFlag(PWS_BORDER))
594     m_sPrivateParam.nBorderStyle = nBorderStyle;
595 }
596 
GetBorderWidth() const597 int32_t CPWL_Wnd::GetBorderWidth() const {
598   if (HasFlag(PWS_BORDER))
599     return m_sPrivateParam.dwBorderWidth;
600 
601   return 0;
602 }
603 
GetInnerBorderWidth() const604 int32_t CPWL_Wnd::GetInnerBorderWidth() const {
605   return 0;
606 }
607 
GetBorderColor() const608 CPWL_Color CPWL_Wnd::GetBorderColor() const {
609   if (HasFlag(PWS_BORDER))
610     return m_sPrivateParam.sBorderColor;
611 
612   return CPWL_Color();
613 }
614 
GetBorderDash() const615 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
616   return m_sPrivateParam.sDash;
617 }
618 
GetAttachedData() const619 void* CPWL_Wnd::GetAttachedData() const {
620   return m_sPrivateParam.pAttachedData;
621 }
622 
GetVScrollBar() const623 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
624   if (HasFlag(PWS_VSCROLL))
625     return m_pVScrollBar;
626 
627   return NULL;
628 }
629 
CreateScrollBar(const PWL_CREATEPARAM & cp)630 void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
631   CreateVScrollBar(cp);
632 }
633 
CreateVScrollBar(const PWL_CREATEPARAM & cp)634 void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
635   if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
636     PWL_CREATEPARAM scp = cp;
637 
638     // flags
639     scp.dwFlags =
640         PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
641 
642     scp.pParentWnd = this;
643     scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
644     scp.eCursorType = FXCT_ARROW;
645     scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;
646 
647     m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
648     m_pVScrollBar->Create(scp);
649   }
650 }
651 
SetCapture()652 void CPWL_Wnd::SetCapture() {
653   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
654     pMsgCtrl->SetCapture(this);
655 }
656 
ReleaseCapture()657 void CPWL_Wnd::ReleaseCapture() {
658   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++)
659     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
660       pChild->ReleaseCapture();
661 
662   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
663     pMsgCtrl->ReleaseCapture();
664 }
665 
SetFocus()666 void CPWL_Wnd::SetFocus() {
667   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
668     if (!pMsgCtrl->IsMainCaptureKeyboard(this))
669       pMsgCtrl->KillFocus();
670     pMsgCtrl->SetFocus(this);
671   }
672 }
673 
KillFocus()674 void CPWL_Wnd::KillFocus() {
675   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
676     if (pMsgCtrl->IsWndCaptureKeyboard(this))
677       pMsgCtrl->KillFocus();
678   }
679 }
680 
OnSetFocus()681 void CPWL_Wnd::OnSetFocus() {}
682 
OnKillFocus()683 void CPWL_Wnd::OnKillFocus() {}
684 
WndHitTest(const CPDF_Point & point) const685 FX_BOOL CPWL_Wnd::WndHitTest(const CPDF_Point& point) const {
686   return IsValid() && IsVisible() && GetWindowRect().Contains(point.x, point.y);
687 }
688 
ClientHitTest(const CPDF_Point & point) const689 FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point& point) const {
690   return IsValid() && IsVisible() && GetClientRect().Contains(point.x, point.y);
691 }
692 
GetRootWnd() const693 const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
694   if (m_sPrivateParam.pParentWnd)
695     return m_sPrivateParam.pParentWnd->GetRootWnd();
696 
697   return this;
698 }
699 
SetVisible(FX_BOOL bVisible)700 void CPWL_Wnd::SetVisible(FX_BOOL bVisible) {
701   if (IsValid()) {
702     for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
703       if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
704         pChild->SetVisible(bVisible);
705       }
706     }
707 
708     if (bVisible != m_bVisible) {
709       m_bVisible = bVisible;
710       RePosChildWnd();
711       InvalidateRect();
712     }
713   }
714 }
715 
SetClipRect(const CPDF_Rect & rect)716 void CPWL_Wnd::SetClipRect(const CPDF_Rect& rect) {
717   m_rcClip = rect;
718   m_rcClip.Normalize();
719 }
720 
GetClipRect() const721 const CPDF_Rect& CPWL_Wnd::GetClipRect() const {
722   return m_rcClip;
723 }
724 
IsReadOnly() const725 FX_BOOL CPWL_Wnd::IsReadOnly() const {
726   return HasFlag(PWS_READONLY);
727 }
728 
RePosChildWnd()729 void CPWL_Wnd::RePosChildWnd() {
730   CPDF_Rect rcContent = CPWL_Utils::DeflateRect(
731       GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
732 
733   CPWL_ScrollBar* pVSB = GetVScrollBar();
734 
735   CPDF_Rect rcVScroll =
736       CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
737                 rcContent.right - 1.0f, rcContent.top);
738 
739   if (pVSB)
740     pVSB->Move(rcVScroll, TRUE, FALSE);
741 }
742 
CreateChildWnd(const PWL_CREATEPARAM & cp)743 void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}
744 
SetCursor()745 void CPWL_Wnd::SetCursor() {
746   if (IsValid()) {
747     if (IFX_SystemHandler* pSH = GetSystemHandler()) {
748       int32_t nCursorType = GetCreationParam().eCursorType;
749       pSH->SetCursor(nCursorType);
750     }
751   }
752 }
753 
CreateMsgControl()754 void CPWL_Wnd::CreateMsgControl() {
755   if (!m_sPrivateParam.pMsgControl)
756     m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
757 }
758 
DestroyMsgControl()759 void CPWL_Wnd::DestroyMsgControl() {
760   if (CPWL_MsgControl* pMsgControl = GetMsgControl())
761     if (pMsgControl->IsWndCreated(this))
762       delete pMsgControl;
763 }
764 
GetMsgControl() const765 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
766   return m_sPrivateParam.pMsgControl;
767 }
768 
IsCaptureMouse() const769 FX_BOOL CPWL_Wnd::IsCaptureMouse() const {
770   return IsWndCaptureMouse(this);
771 }
772 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const773 FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
774   if (CPWL_MsgControl* pCtrl = GetMsgControl())
775     return pCtrl->IsWndCaptureMouse(pWnd);
776 
777   return FALSE;
778 }
779 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const780 FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
781   if (CPWL_MsgControl* pCtrl = GetMsgControl())
782     return pCtrl->IsWndCaptureKeyboard(pWnd);
783 
784   return FALSE;
785 }
786 
IsFocused() const787 FX_BOOL CPWL_Wnd::IsFocused() const {
788   if (CPWL_MsgControl* pCtrl = GetMsgControl())
789     return pCtrl->IsMainCaptureKeyboard(this);
790 
791   return FALSE;
792 }
793 
GetFocusRect() const794 CPDF_Rect CPWL_Wnd::GetFocusRect() const {
795   return CPWL_Utils::InflateRect(GetWindowRect(), 1);
796 }
797 
GetFontSize() const798 FX_FLOAT CPWL_Wnd::GetFontSize() const {
799   return m_sPrivateParam.fFontSize;
800 }
801 
SetFontSize(FX_FLOAT fFontSize)802 void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
803   m_sPrivateParam.fFontSize = fFontSize;
804 }
805 
GetSystemHandler() const806 IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
807   return m_sPrivateParam.pSystemHandler;
808 }
809 
GetFocusHandler() const810 IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
811   return m_sPrivateParam.pFocusHandler;
812 }
813 
GetProvider() const814 IPWL_Provider* CPWL_Wnd::GetProvider() const {
815   return m_sPrivateParam.pProvider;
816 }
817 
GetFontMap() const818 IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const {
819   return m_sPrivateParam.pFontMap;
820 }
821 
GetBorderLeftTopColor(int32_t nBorderStyle) const822 CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(int32_t nBorderStyle) const {
823   CPWL_Color color;
824 
825   switch (nBorderStyle) {
826     case PBS_SOLID:
827       break;
828     case PBS_DASH:
829       break;
830     case PBS_BEVELED:
831       color = CPWL_Color(COLORTYPE_GRAY, 1);
832       break;
833     case PBS_INSET:
834       color = CPWL_Color(COLORTYPE_GRAY, 0.5f);
835       break;
836     case PBS_UNDERLINED:
837       break;
838   }
839 
840   return color;
841 }
842 
GetBorderRightBottomColor(int32_t nBorderStyle) const843 CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(int32_t nBorderStyle) const {
844   CPWL_Color color;
845 
846   switch (nBorderStyle) {
847     case PBS_SOLID:
848       break;
849     case PBS_DASH:
850       break;
851     case PBS_BEVELED:
852       color = CPWL_Utils::DevideColor(GetBackgroundColor(), 2);
853       break;
854     case PBS_INSET:
855       color = CPWL_Color(COLORTYPE_GRAY, 0.75f);
856       break;
857     case PBS_UNDERLINED:
858       break;
859   }
860 
861   return color;
862 }
863 
GetTransparency()864 int32_t CPWL_Wnd::GetTransparency() {
865   return m_sPrivateParam.nTransparency;
866 }
867 
SetTransparency(int32_t nTransparency)868 void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
869   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
870     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
871       pChild->SetTransparency(nTransparency);
872     }
873   }
874 
875   m_sPrivateParam.nTransparency = nTransparency;
876 }
877 
GetWindowMatrix() const878 CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
879   CFX_Matrix mt = GetChildToRoot();
880 
881   if (IPWL_Provider* pProvider = GetProvider()) {
882     mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
883     return mt;
884   }
885 
886   return mt;
887 }
888 
PWLtoWnd(const CPDF_Point & point,int32_t & x,int32_t & y) const889 void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, int32_t& x, int32_t& y) const {
890   CFX_Matrix mt = GetWindowMatrix();
891   CPDF_Point pt = point;
892   mt.Transform(pt.x, pt.y);
893   x = (int32_t)(pt.x + 0.5);
894   y = (int32_t)(pt.y + 0.5);
895 }
896 
PWLtoWnd(const CPDF_Rect & rect) const897 FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect& rect) const {
898   CPDF_Rect rcTemp = rect;
899   CFX_Matrix mt = GetWindowMatrix();
900   mt.TransformRect(rcTemp);
901   return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
902                  (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
903 }
904 
GetAttachedHWnd() const905 FX_HWND CPWL_Wnd::GetAttachedHWnd() const {
906   return m_sPrivateParam.hAttachedWnd;
907 }
908 
ChildToParent(const CPDF_Point & point) const909 CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const {
910   CFX_Matrix mt = GetChildMatrix();
911   if (mt.IsIdentity())
912     return point;
913 
914   CPDF_Point pt = point;
915   mt.Transform(pt.x, pt.y);
916   return pt;
917 }
918 
ChildToParent(const CPDF_Rect & rect) const919 CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const {
920   CFX_Matrix mt = GetChildMatrix();
921   if (mt.IsIdentity())
922     return rect;
923 
924   CPDF_Rect rc = rect;
925   mt.TransformRect(rc);
926   return rc;
927 }
928 
ParentToChild(const CPDF_Point & point) const929 CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const {
930   CFX_Matrix mt = GetChildMatrix();
931   if (mt.IsIdentity())
932     return point;
933 
934   mt.SetReverse(mt);
935   CPDF_Point pt = point;
936   mt.Transform(pt.x, pt.y);
937   return pt;
938 }
939 
ParentToChild(const CPDF_Rect & rect) const940 CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const {
941   CFX_Matrix mt = GetChildMatrix();
942   if (mt.IsIdentity())
943     return rect;
944 
945   mt.SetReverse(mt);
946   CPDF_Rect rc = rect;
947   mt.TransformRect(rc);
948   return rc;
949 }
950 
GetChildToRoot() const951 CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
952   CFX_Matrix mt(1, 0, 0, 1, 0, 0);
953   if (HasFlag(PWS_CHILD)) {
954     const CPWL_Wnd* pParent = this;
955     while (pParent) {
956       mt.Concat(pParent->GetChildMatrix());
957       pParent = pParent->GetParentWindow();
958     }
959   }
960   return mt;
961 }
962 
GetChildMatrix() const963 CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
964   if (HasFlag(PWS_CHILD))
965     return m_sPrivateParam.mtChild;
966 
967   return CFX_Matrix(1, 0, 0, 1, 0, 0);
968 }
969 
SetChildMatrix(const CFX_Matrix & mt)970 void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
971   m_sPrivateParam.mtChild = mt;
972 }
973 
GetFocused() const974 const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
975   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
976     return pMsgCtrl->m_pMainKeyboardWnd;
977   }
978 
979   return NULL;
980 }
981 
EnableWindow(FX_BOOL bEnable)982 void CPWL_Wnd::EnableWindow(FX_BOOL bEnable) {
983   if (m_bEnabled != bEnable) {
984     for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
985       if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
986         pChild->EnableWindow(bEnable);
987       }
988     }
989 
990     m_bEnabled = bEnable;
991 
992     if (bEnable)
993       OnEnabled();
994     else
995       OnDisabled();
996   }
997 }
998 
IsEnabled()999 FX_BOOL CPWL_Wnd::IsEnabled() {
1000   return m_bEnabled;
1001 }
1002 
OnEnabled()1003 void CPWL_Wnd::OnEnabled() {}
1004 
OnDisabled()1005 void CPWL_Wnd::OnDisabled() {}
1006 
IsCTRLpressed(FX_DWORD nFlag) const1007 FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const {
1008   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
1009     return pSystemHandler->IsCTRLKeyDown(nFlag);
1010   }
1011 
1012   return FALSE;
1013 }
1014 
IsSHIFTpressed(FX_DWORD nFlag) const1015 FX_BOOL CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const {
1016   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
1017     return pSystemHandler->IsSHIFTKeyDown(nFlag);
1018   }
1019 
1020   return FALSE;
1021 }
1022 
IsALTpressed(FX_DWORD nFlag) const1023 FX_BOOL CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const {
1024   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
1025     return pSystemHandler->IsALTKeyDown(nFlag);
1026   }
1027 
1028   return FALSE;
1029 }
1030 
IsINSERTpressed(FX_DWORD nFlag) const1031 FX_BOOL CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const {
1032   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
1033     return pSystemHandler->IsINSERTKeyDown(nFlag);
1034   }
1035 
1036   return FALSE;
1037 }
1038