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