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/pdfwindow/PWL_ComboBox.h"
8 
9 #include "fpdfsdk/include/pdfwindow/PWL_Edit.h"
10 #include "fpdfsdk/include/pdfwindow/PWL_EditCtrl.h"
11 #include "fpdfsdk/include/pdfwindow/PWL_ListBox.h"
12 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
13 #include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"
14 #include "public/fpdf_fwlevent.h"
15 
16 #define PWLCB_DEFAULTFONTSIZE 12.0f
17 
18 #define IsFloatZero(f) ((f) < 0.0001 && (f) > -0.0001)
19 #define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
20 #define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
21 #define IsFloatEqual(fa, fb) IsFloatZero((fa) - (fb))
22 
OnLButtonUp(const CPDF_Point & point,FX_DWORD nFlag)23 FX_BOOL CPWL_CBListBox::OnLButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
24   CPWL_Wnd::OnLButtonUp(point, nFlag);
25 
26   if (m_bMouseDown) {
27     ReleaseCapture();
28     m_bMouseDown = FALSE;
29 
30     if (ClientHitTest(point)) {
31       if (CPWL_Wnd* pParent = GetParentWindow()) {
32         pParent->OnNotify(this, PNM_LBUTTONUP, 0,
33                           PWL_MAKEDWORD(point.x, point.y));
34       }
35 
36       FX_BOOL bExit = FALSE;
37       OnNotifySelChanged(FALSE, bExit, nFlag);
38       if (bExit)
39         return FALSE;
40     }
41   }
42 
43   return TRUE;
44 }
45 
OnKeyDownWithExit(FX_WORD nChar,FX_BOOL & bExit,FX_DWORD nFlag)46 FX_BOOL CPWL_CBListBox::OnKeyDownWithExit(FX_WORD nChar,
47                                           FX_BOOL& bExit,
48                                           FX_DWORD nFlag) {
49   if (!m_pList)
50     return FALSE;
51 
52   switch (nChar) {
53     default:
54       return FALSE;
55     case FWL_VKEY_Up:
56     case FWL_VKEY_Down:
57     case FWL_VKEY_Home:
58     case FWL_VKEY_Left:
59     case FWL_VKEY_End:
60     case FWL_VKEY_Right:
61       break;
62   }
63 
64   switch (nChar) {
65     case FWL_VKEY_Up:
66       m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
67       break;
68     case FWL_VKEY_Down:
69       m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
70       break;
71     case FWL_VKEY_Home:
72       m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
73       break;
74     case FWL_VKEY_Left:
75       m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
76       break;
77     case FWL_VKEY_End:
78       m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
79       break;
80     case FWL_VKEY_Right:
81       m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
82       break;
83     case FWL_VKEY_Delete:
84       break;
85   }
86 
87   OnNotifySelChanged(TRUE, bExit, nFlag);
88 
89   return TRUE;
90 }
91 
OnCharWithExit(FX_WORD nChar,FX_BOOL & bExit,FX_DWORD nFlag)92 FX_BOOL CPWL_CBListBox::OnCharWithExit(FX_WORD nChar,
93                                        FX_BOOL& bExit,
94                                        FX_DWORD nFlag) {
95   if (!m_pList)
96     return FALSE;
97 
98   if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
99     return FALSE;
100 
101   if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow()) {
102     pComboBox->SetSelectText();
103   }
104 
105   OnNotifySelChanged(TRUE, bExit, nFlag);
106 
107   return TRUE;
108 }
109 
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)110 void CPWL_CBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
111   CPWL_Wnd::GetThisAppearanceStream(sAppStream);
112 
113   CPDF_Rect rectWnd = CPWL_Wnd::GetWindowRect();
114 
115   if (IsVisible() && !rectWnd.IsEmpty()) {
116     CFX_ByteTextBuf sButton;
117 
118     CPDF_Point ptCenter = GetCenterPoint();
119 
120     CPDF_Point pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
121                    ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
122     CPDF_Point pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
123                    ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
124     CPDF_Point pt3(ptCenter.x,
125                    ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
126 
127     if (IsFloatBigger(rectWnd.right - rectWnd.left,
128                       PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
129         IsFloatBigger(rectWnd.top - rectWnd.bottom,
130                       PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
131       sButton << "0 g\n";
132       sButton << pt1.x << " " << pt1.y << " m\n";
133       sButton << pt2.x << " " << pt2.y << " l\n";
134       sButton << pt3.x << " " << pt3.y << " l\n";
135       sButton << pt1.x << " " << pt1.y << " l f\n";
136 
137       sAppStream << "q\n" << sButton << "Q\n";
138     }
139   }
140 }
141 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)142 void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
143                                        CFX_Matrix* pUser2Device) {
144   CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
145 
146   CPDF_Rect rectWnd = CPWL_Wnd::GetWindowRect();
147 
148   if (IsVisible() && !rectWnd.IsEmpty()) {
149     CPDF_Point ptCenter = GetCenterPoint();
150 
151     CPDF_Point pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
152                    ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
153     CPDF_Point pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
154                    ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
155     CPDF_Point pt3(ptCenter.x,
156                    ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
157 
158     if (IsFloatBigger(rectWnd.right - rectWnd.left,
159                       PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
160         IsFloatBigger(rectWnd.top - rectWnd.bottom,
161                       PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
162       CFX_PathData path;
163 
164       path.SetPointCount(4);
165       path.SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
166       path.SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);
167       path.SetPoint(2, pt3.x, pt3.y, FXPT_LINETO);
168       path.SetPoint(3, pt1.x, pt1.y, FXPT_LINETO);
169 
170       pDevice->DrawPath(&path, pUser2Device, NULL,
171                         CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_BLACKCOLOR,
172                                                       GetTransparency()),
173                         0, FXFILL_ALTERNATE);
174     }
175   }
176 }
177 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)178 FX_BOOL CPWL_CBButton::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
179   CPWL_Wnd::OnLButtonDown(point, nFlag);
180 
181   SetCapture();
182 
183   if (CPWL_Wnd* pParent = GetParentWindow()) {
184     pParent->OnNotify(this, PNM_LBUTTONDOWN, 0,
185                       PWL_MAKEDWORD(point.x, point.y));
186   }
187 
188   return TRUE;
189 }
190 
OnLButtonUp(const CPDF_Point & point,FX_DWORD nFlag)191 FX_BOOL CPWL_CBButton::OnLButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
192   CPWL_Wnd::OnLButtonUp(point, nFlag);
193 
194   ReleaseCapture();
195 
196   return TRUE;
197 }
198 
CPWL_ComboBox()199 CPWL_ComboBox::CPWL_ComboBox()
200     : m_pEdit(NULL),
201       m_pButton(NULL),
202       m_pList(NULL),
203       m_bPopup(FALSE),
204       m_nPopupWhere(0),
205       m_nSelectItem(-1),
206       m_pFillerNotify(NULL) {}
207 
GetClassName() const208 CFX_ByteString CPWL_ComboBox::GetClassName() const {
209   return "CPWL_ComboBox";
210 }
211 
OnCreate(PWL_CREATEPARAM & cp)212 void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM& cp) {
213   cp.dwFlags &= ~PWS_HSCROLL;
214   cp.dwFlags &= ~PWS_VSCROLL;
215 }
216 
SetFocus()217 void CPWL_ComboBox::SetFocus() {
218   if (m_pEdit)
219     m_pEdit->SetFocus();
220 }
221 
KillFocus()222 void CPWL_ComboBox::KillFocus() {
223   SetPopup(FALSE);
224   CPWL_Wnd::KillFocus();
225 }
226 
GetText() const227 CFX_WideString CPWL_ComboBox::GetText() const {
228   if (m_pEdit) {
229     return m_pEdit->GetText();
230   }
231   return CFX_WideString();
232 }
233 
SetText(const FX_WCHAR * text)234 void CPWL_ComboBox::SetText(const FX_WCHAR* text) {
235   if (m_pEdit)
236     m_pEdit->SetText(text);
237 }
238 
AddString(const FX_WCHAR * string)239 void CPWL_ComboBox::AddString(const FX_WCHAR* string) {
240   if (m_pList)
241     m_pList->AddString(string);
242 }
243 
GetSelect() const244 int32_t CPWL_ComboBox::GetSelect() const {
245   return m_nSelectItem;
246 }
247 
SetSelect(int32_t nItemIndex)248 void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
249   if (m_pList)
250     m_pList->Select(nItemIndex);
251 
252   m_pEdit->SetText(m_pList->GetText().c_str());
253 
254   m_nSelectItem = nItemIndex;
255 }
256 
SetEditSel(int32_t nStartChar,int32_t nEndChar)257 void CPWL_ComboBox::SetEditSel(int32_t nStartChar, int32_t nEndChar) {
258   if (m_pEdit) {
259     m_pEdit->SetSel(nStartChar, nEndChar);
260   }
261 }
262 
GetEditSel(int32_t & nStartChar,int32_t & nEndChar) const263 void CPWL_ComboBox::GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const {
264   nStartChar = -1;
265   nEndChar = -1;
266 
267   if (m_pEdit) {
268     m_pEdit->GetSel(nStartChar, nEndChar);
269   }
270 }
271 
Clear()272 void CPWL_ComboBox::Clear() {
273   if (m_pEdit) {
274     m_pEdit->Clear();
275   }
276 }
277 
CreateChildWnd(const PWL_CREATEPARAM & cp)278 void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM& cp) {
279   CreateEdit(cp);
280   CreateButton(cp);
281   CreateListBox(cp);
282 }
283 
CreateEdit(const PWL_CREATEPARAM & cp)284 void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) {
285   if (!m_pEdit) {
286     m_pEdit = new CPWL_CBEdit;
287     m_pEdit->AttachFFLData(m_pFormFiller);
288 
289     PWL_CREATEPARAM ecp = cp;
290     ecp.pParentWnd = this;
291     ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
292                   PES_AUTOSCROLL | PES_UNDO;
293 
294     if (HasFlag(PWS_AUTOFONTSIZE))
295       ecp.dwFlags |= PWS_AUTOFONTSIZE;
296 
297     if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
298       ecp.dwFlags |= PWS_READONLY;
299 
300     ecp.rcRectWnd = CPDF_Rect(0, 0, 0, 0);
301     ecp.dwBorderWidth = 0;
302     ecp.nBorderStyle = PBS_SOLID;
303 
304     m_pEdit->Create(ecp);
305   }
306 }
307 
CreateButton(const PWL_CREATEPARAM & cp)308 void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) {
309   if (!m_pButton) {
310     m_pButton = new CPWL_CBButton;
311 
312     PWL_CREATEPARAM bcp = cp;
313     bcp.pParentWnd = this;
314     bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
315     bcp.sBackgroundColor = PWL_SCROLLBAR_BKCOLOR;
316     bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
317     bcp.dwBorderWidth = 2;
318     bcp.nBorderStyle = PBS_BEVELED;
319     bcp.eCursorType = FXCT_ARROW;
320 
321     m_pButton->Create(bcp);
322   }
323 }
324 
CreateListBox(const PWL_CREATEPARAM & cp)325 void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM& cp) {
326   if (!m_pList) {
327     m_pList = new CPWL_CBListBox;
328     m_pList->AttachFFLData(m_pFormFiller);
329     PWL_CREATEPARAM lcp = cp;
330     lcp.pParentWnd = this;
331     lcp.dwFlags =
332         PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
333     lcp.nBorderStyle = PBS_SOLID;
334     lcp.dwBorderWidth = 1;
335     lcp.eCursorType = FXCT_ARROW;
336     lcp.rcRectWnd = CPDF_Rect(0, 0, 0, 0);
337 
338     if (cp.dwFlags & PWS_AUTOFONTSIZE)
339       lcp.fFontSize = PWLCB_DEFAULTFONTSIZE;
340     else
341       lcp.fFontSize = cp.fFontSize;
342 
343     if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT)
344       lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
345 
346     if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT)
347       lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
348 
349     m_pList->Create(lcp);
350   }
351 }
352 
RePosChildWnd()353 void CPWL_ComboBox::RePosChildWnd() {
354   CPDF_Rect rcClient = GetClientRect();
355 
356   if (m_bPopup) {
357     CPDF_Rect rclient = GetClientRect();
358     CPDF_Rect rcButton = rclient;
359     CPDF_Rect rcEdit = rcClient;
360     CPDF_Rect rcList = CPWL_Wnd::GetWindowRect();
361 
362     FX_FLOAT fOldWindowHeight = m_rcOldWindow.Height();
363     FX_FLOAT fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
364 
365     switch (m_nPopupWhere) {
366       case 0:
367         rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
368 
369         if (rcButton.left < rclient.left)
370           rcButton.left = rclient.left;
371 
372         rcButton.bottom = rcButton.top - fOldClientHeight;
373 
374         rcEdit.right = rcButton.left - 1.0f;
375 
376         if (rcEdit.left < rclient.left)
377           rcEdit.left = rclient.left;
378 
379         if (rcEdit.right < rcEdit.left)
380           rcEdit.right = rcEdit.left;
381 
382         rcEdit.bottom = rcEdit.top - fOldClientHeight;
383 
384         rcList.top -= fOldWindowHeight;
385 
386         break;
387       case 1:
388         rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
389 
390         if (rcButton.left < rclient.left)
391           rcButton.left = rclient.left;
392 
393         rcButton.top = rcButton.bottom + fOldClientHeight;
394 
395         rcEdit.right = rcButton.left - 1.0f;
396 
397         if (rcEdit.left < rclient.left)
398           rcEdit.left = rclient.left;
399 
400         if (rcEdit.right < rcEdit.left)
401           rcEdit.right = rcEdit.left;
402 
403         rcEdit.top = rcEdit.bottom + fOldClientHeight;
404 
405         rcList.bottom += fOldWindowHeight;
406 
407         break;
408     }
409 
410     if (m_pButton)
411       m_pButton->Move(rcButton, TRUE, FALSE);
412 
413     if (m_pEdit)
414       m_pEdit->Move(rcEdit, TRUE, FALSE);
415 
416     if (m_pList) {
417       m_pList->SetVisible(TRUE);
418       m_pList->Move(rcList, TRUE, FALSE);
419       m_pList->ScrollToListItem(m_nSelectItem);
420     }
421   } else {
422     CPDF_Rect rcButton = rcClient;
423 
424     rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
425 
426     if (rcButton.left < rcClient.left)
427       rcButton.left = rcClient.left;
428 
429     if (m_pButton)
430       m_pButton->Move(rcButton, TRUE, FALSE);
431 
432     CPDF_Rect rcEdit = rcClient;
433     rcEdit.right = rcButton.left - 1.0f;
434 
435     if (rcEdit.left < rcClient.left)
436       rcEdit.left = rcClient.left;
437 
438     if (rcEdit.right < rcEdit.left)
439       rcEdit.right = rcEdit.left;
440 
441     if (m_pEdit)
442       m_pEdit->Move(rcEdit, TRUE, FALSE);
443 
444     if (m_pList)
445       m_pList->SetVisible(FALSE);
446   }
447 }
448 
SelectAll()449 void CPWL_ComboBox::SelectAll() {
450   if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
451     m_pEdit->SelectAll();
452 }
453 
GetFocusRect() const454 CPDF_Rect CPWL_ComboBox::GetFocusRect() const {
455   return CPDF_Rect();
456 }
457 
SetPopup(FX_BOOL bPopup)458 void CPWL_ComboBox::SetPopup(FX_BOOL bPopup) {
459   if (!m_pList)
460     return;
461   if (bPopup == m_bPopup)
462     return;
463   FX_FLOAT fListHeight = m_pList->GetContentRect().Height();
464   if (!IsFloatBigger(fListHeight, 0.0f))
465     return;
466 
467   if (bPopup) {
468     if (m_pFillerNotify) {
469 #ifdef PDF_ENABLE_XFA
470       FX_BOOL bExit = FALSE;
471       m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, 0);
472       if (bExit)
473         return;
474 #endif  // PDF_ENABLE_XFA
475       int32_t nWhere = 0;
476       FX_FLOAT fPopupRet = 0.0f;
477       FX_FLOAT fPopupMin = 0.0f;
478       if (m_pList->GetCount() > 3)
479         fPopupMin =
480             m_pList->GetFirstHeight() * 3 + m_pList->GetBorderWidth() * 2;
481       FX_FLOAT fPopupMax = fListHeight + m_pList->GetBorderWidth() * 2;
482       m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
483                                        nWhere, fPopupRet);
484 
485       if (IsFloatBigger(fPopupRet, 0.0f)) {
486         m_bPopup = bPopup;
487 
488         CPDF_Rect rcWindow = CPWL_Wnd::GetWindowRect();
489         m_rcOldWindow = rcWindow;
490         switch (nWhere) {
491           default:
492           case 0:
493             rcWindow.bottom -= fPopupRet;
494             break;
495           case 1:
496             rcWindow.top += fPopupRet;
497             break;
498         }
499 
500         m_nPopupWhere = nWhere;
501         Move(rcWindow, TRUE, TRUE);
502 #ifdef PDF_ENABLE_XFA
503         bExit = FALSE;
504         m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, 0);
505         if (bExit)
506           return;
507 #endif  // PDF_ENABLE_XFA
508       }
509     }
510   } else {
511     m_bPopup = bPopup;
512     Move(m_rcOldWindow, TRUE, TRUE);
513   }
514 }
515 
OnKeyDown(FX_WORD nChar,FX_DWORD nFlag)516 FX_BOOL CPWL_ComboBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) {
517   if (!m_pList)
518     return FALSE;
519   if (!m_pEdit)
520     return FALSE;
521 
522   m_nSelectItem = -1;
523 
524   switch (nChar) {
525     case FWL_VKEY_Up:
526       if (m_pList->GetCurSel() > 0) {
527         FX_BOOL bExit = FALSE;
528 #ifdef PDF_ENABLE_XFA
529         if (m_pFillerNotify) {
530           m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
531           if (bExit)
532             return FALSE;
533           bExit = FALSE;
534           m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
535           if (bExit)
536             return FALSE;
537         }
538 #endif  // PDF_ENABLE_XFA
539         if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
540           if (bExit)
541             return FALSE;
542           SetSelectText();
543         }
544       }
545       return TRUE;
546     case FWL_VKEY_Down:
547       if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
548         FX_BOOL bExit = FALSE;
549 #ifdef PDF_ENABLE_XFA
550         if (m_pFillerNotify) {
551           m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
552           if (bExit)
553             return FALSE;
554           bExit = FALSE;
555           m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
556           if (bExit)
557             return FALSE;
558         }
559 #endif  // PDF_ENABLE_XFA
560         if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
561           if (bExit)
562             return FALSE;
563           SetSelectText();
564         }
565       }
566       return TRUE;
567   }
568 
569   if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
570     return m_pEdit->OnKeyDown(nChar, nFlag);
571 
572   return FALSE;
573 }
574 
OnChar(FX_WORD nChar,FX_DWORD nFlag)575 FX_BOOL CPWL_ComboBox::OnChar(FX_WORD nChar, FX_DWORD nFlag) {
576   if (!m_pList)
577     return FALSE;
578 
579   if (!m_pEdit)
580     return FALSE;
581 
582   m_nSelectItem = -1;
583   if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
584     return m_pEdit->OnChar(nChar, nFlag);
585 
586   FX_BOOL bExit = FALSE;
587 #ifdef PDF_ENABLE_XFA
588   if (m_pFillerNotify) {
589     m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
590     if (bExit)
591       return FALSE;
592 
593     m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
594     if (bExit)
595       return FALSE;
596   }
597 #endif  // PDF_ENABLE_XFA
598   return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : FALSE;
599 }
600 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)601 void CPWL_ComboBox::OnNotify(CPWL_Wnd* pWnd,
602                              FX_DWORD msg,
603                              intptr_t wParam,
604                              intptr_t lParam) {
605   switch (msg) {
606     case PNM_LBUTTONDOWN:
607       if (pWnd == m_pButton) {
608         SetPopup(!m_bPopup);
609         return;
610       }
611       break;
612     case PNM_LBUTTONUP:
613       if (m_pEdit && m_pList) {
614         if (pWnd == m_pList) {
615           SetSelectText();
616           SelectAll();
617           m_pEdit->SetFocus();
618           SetPopup(FALSE);
619           return;
620         }
621       }
622   }
623 
624   CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
625 }
626 
IsPopup() const627 FX_BOOL CPWL_ComboBox::IsPopup() const {
628   return m_bPopup;
629 }
630 
SetSelectText()631 void CPWL_ComboBox::SetSelectText() {
632   CFX_WideString swText = m_pList->GetText();
633   m_pEdit->SelectAll();
634   m_pEdit->ReplaceSel(m_pList->GetText().c_str());
635   m_pEdit->SelectAll();
636 
637   m_nSelectItem = m_pList->GetCurSel();
638 }
639 
SetFillerNotify(IPWL_Filler_Notify * pNotify)640 void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
641   m_pFillerNotify = pNotify;
642 
643   if (m_pEdit)
644     m_pEdit->SetFillerNotify(pNotify);
645 
646   if (m_pList)
647     m_pList->SetFillerNotify(pNotify);
648 }
649