Home | History | Annotate | Download | only in formfiller
      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/formfiller/cffl_combobox.h"
      8 
      9 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
     10 #include "fpdfsdk/cpdfsdk_widget.h"
     11 #include "fpdfsdk/formfiller/cba_fontmap.h"
     12 #include "fpdfsdk/formfiller/cffl_formfiller.h"
     13 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
     14 #include "fpdfsdk/fsdk_common.h"
     15 #include "fpdfsdk/pdfwindow/PWL_ComboBox.h"
     16 
     17 CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp,
     18                              CPDFSDK_Annot* pAnnot)
     19     : CFFL_FormFiller(pApp, pAnnot), m_pFontMap(nullptr) {
     20   m_State.nIndex = 0;
     21   m_State.nStart = 0;
     22   m_State.nEnd = 0;
     23 }
     24 
     25 CFFL_ComboBox::~CFFL_ComboBox() {
     26   for (const auto& it : m_Maps)
     27     it.second->InvalidateFocusHandler(this);
     28 
     29   // See comment in cffl_formfiller.h.
     30   // The font map should be stored somewhere more appropriate so it will live
     31   // until the PWL_Edit is done with it. pdfium:566
     32   DestroyWindows();
     33   delete m_pFontMap;
     34 }
     35 
     36 PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() {
     37   PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
     38 
     39   int nFlags = m_pWidget->GetFieldFlags();
     40   if (nFlags & FIELDFLAG_EDIT) {
     41     cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
     42   }
     43 
     44   if (!m_pFontMap)
     45     m_pFontMap = new CBA_FontMap(m_pWidget, GetSystemHandler());
     46   cp.pFontMap = m_pFontMap;
     47   cp.pFocusHandler = this;
     48 
     49   return cp;
     50 }
     51 
     52 CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
     53                                       CPDFSDK_PageView* pPageView) {
     54   CPWL_ComboBox* pWnd = new CPWL_ComboBox();
     55   pWnd->AttachFFLData(this);
     56   pWnd->Create(cp);
     57 
     58   CFFL_InteractiveFormFiller* pFormFiller =
     59       m_pFormFillEnv->GetInteractiveFormFiller();
     60   pWnd->SetFillerNotify(pFormFiller);
     61 
     62   int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
     63   CFX_WideString swText;
     64   if (nCurSel < 0)
     65     swText = m_pWidget->GetValue();
     66   else
     67     swText = m_pWidget->GetOptionLabel(nCurSel);
     68 
     69   for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++) {
     70     pWnd->AddString(m_pWidget->GetOptionLabel(i));
     71   }
     72 
     73   pWnd->SetSelect(nCurSel);
     74   pWnd->SetText(swText);
     75   return pWnd;
     76 }
     77 
     78 bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot,
     79                            uint32_t nChar,
     80                            uint32_t nFlags) {
     81   return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
     82 }
     83 
     84 bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
     85   CPWL_ComboBox* pWnd = (CPWL_ComboBox*)GetPDFWindow(pPageView, false);
     86   if (!pWnd)
     87     return false;
     88 
     89   int32_t nCurSel = pWnd->GetSelect();
     90   if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT))
     91     return nCurSel != m_pWidget->GetSelectedIndex(0);
     92 
     93   if (nCurSel >= 0)
     94     return nCurSel != m_pWidget->GetSelectedIndex(0);
     95 
     96   return pWnd->GetText() != m_pWidget->GetValue();
     97 }
     98 
     99 void CFFL_ComboBox::SaveData(CPDFSDK_PageView* pPageView) {
    100   CPWL_ComboBox* pWnd =
    101       static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false));
    102   if (!pWnd)
    103     return;
    104 
    105   CFX_WideString swText = pWnd->GetText();
    106   int32_t nCurSel = pWnd->GetSelect();
    107 
    108   bool bSetValue = false;
    109 
    110   if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
    111     bSetValue = (nCurSel < 0) || (swText != m_pWidget->GetOptionLabel(nCurSel));
    112 
    113   if (bSetValue) {
    114     m_pWidget->SetValue(swText, false);
    115   } else {
    116     m_pWidget->GetSelectedIndex(0);
    117     m_pWidget->SetOptionSelection(nCurSel, true, false);
    118   }
    119 
    120   m_pWidget->ResetFieldAppearance(true);
    121   m_pWidget->UpdateField();
    122   SetChangeMark();
    123 
    124   m_pWidget->GetPDFPage();
    125 }
    126 
    127 void CFFL_ComboBox::GetActionData(CPDFSDK_PageView* pPageView,
    128                                   CPDF_AAction::AActionType type,
    129                                   PDFSDK_FieldAction& fa) {
    130   switch (type) {
    131     case CPDF_AAction::KeyStroke:
    132       if (CPWL_ComboBox* pComboBox =
    133               static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
    134         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
    135           fa.bFieldFull = pEdit->IsTextFull();
    136           int nSelStart = 0;
    137           int nSelEnd = 0;
    138           pEdit->GetSel(nSelStart, nSelEnd);
    139           fa.nSelEnd = nSelEnd;
    140           fa.nSelStart = nSelStart;
    141           fa.sValue = pEdit->GetText();
    142           fa.sChangeEx = GetSelectExportText();
    143 
    144           if (fa.bFieldFull) {
    145             fa.sChange = L"";
    146             fa.sChangeEx = L"";
    147           }
    148         }
    149       }
    150       break;
    151     case CPDF_AAction::Validate:
    152       if (CPWL_ComboBox* pComboBox =
    153               static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
    154         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
    155           fa.sValue = pEdit->GetText();
    156         }
    157       }
    158       break;
    159     case CPDF_AAction::LoseFocus:
    160     case CPDF_AAction::GetFocus:
    161       fa.sValue = m_pWidget->GetValue();
    162       break;
    163     default:
    164       break;
    165   }
    166 }
    167 
    168 void CFFL_ComboBox::SetActionData(CPDFSDK_PageView* pPageView,
    169                                   CPDF_AAction::AActionType type,
    170                                   const PDFSDK_FieldAction& fa) {
    171   switch (type) {
    172     case CPDF_AAction::KeyStroke:
    173       if (CPWL_ComboBox* pComboBox =
    174               static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
    175         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
    176           pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
    177           pEdit->ReplaceSel(fa.sChange);
    178         }
    179       }
    180       break;
    181     default:
    182       break;
    183   }
    184 }
    185 
    186 bool CFFL_ComboBox::IsActionDataChanged(CPDF_AAction::AActionType type,
    187                                         const PDFSDK_FieldAction& faOld,
    188                                         const PDFSDK_FieldAction& faNew) {
    189   switch (type) {
    190     case CPDF_AAction::KeyStroke:
    191       return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
    192              faOld.nSelStart != faNew.nSelStart ||
    193              faOld.sChange != faNew.sChange;
    194     default:
    195       break;
    196   }
    197 
    198   return false;
    199 }
    200 
    201 void CFFL_ComboBox::SaveState(CPDFSDK_PageView* pPageView) {
    202   ASSERT(pPageView);
    203 
    204   if (CPWL_ComboBox* pComboBox =
    205           static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
    206     m_State.nIndex = pComboBox->GetSelect();
    207 
    208     if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
    209       pEdit->GetSel(m_State.nStart, m_State.nEnd);
    210       m_State.sValue = pEdit->GetText();
    211     }
    212   }
    213 }
    214 
    215 void CFFL_ComboBox::RestoreState(CPDFSDK_PageView* pPageView) {
    216   ASSERT(pPageView);
    217 
    218   if (CPWL_ComboBox* pComboBox =
    219           static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, true))) {
    220     if (m_State.nIndex >= 0) {
    221       pComboBox->SetSelect(m_State.nIndex);
    222     } else {
    223       if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
    224         pEdit->SetText(m_State.sValue);
    225         pEdit->SetSel(m_State.nStart, m_State.nEnd);
    226       }
    227     }
    228   }
    229 }
    230 
    231 CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
    232                                         bool bRestoreValue) {
    233   if (bRestoreValue)
    234     SaveState(pPageView);
    235 
    236   DestroyPDFWindow(pPageView);
    237 
    238   CPWL_Wnd* pRet = nullptr;
    239 
    240   if (bRestoreValue) {
    241     RestoreState(pPageView);
    242     pRet = GetPDFWindow(pPageView, false);
    243   } else {
    244     pRet = GetPDFWindow(pPageView, true);
    245   }
    246 
    247   m_pWidget->UpdateField();
    248 
    249   return pRet;
    250 }
    251 
    252 #ifdef PDF_ENABLE_XFA
    253 bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) {
    254   if (CPWL_ComboBox* pComboBox =
    255           static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
    256     if (CPWL_Edit* pEdit = pComboBox->GetEdit())
    257       return pEdit->IsTextFull();
    258   }
    259   return false;
    260 }
    261 #endif  // PDF_ENABLE_XFA
    262 
    263 void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) {
    264   ASSERT(m_pFormFillEnv);
    265 
    266   if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
    267     CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
    268     pEdit->SetCharSet(FXFONT_GB2312_CHARSET);
    269     pEdit->SetCodePage(936);
    270 
    271     pEdit->SetReadyToInput();
    272     CFX_WideString wsText = pEdit->GetText();
    273     int nCharacters = wsText.GetLength();
    274     CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
    275     unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
    276     m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
    277   }
    278 }
    279 
    280 CFX_WideString CFFL_ComboBox::GetSelectExportText() {
    281   CFX_WideString swRet;
    282 
    283   int nExport = -1;
    284   CPDFSDK_PageView* pPageView = GetCurPageView(true);
    285   if (CPWL_ComboBox* pComboBox =
    286           (CPWL_ComboBox*)GetPDFWindow(pPageView, false)) {
    287     nExport = pComboBox->GetSelect();
    288   }
    289 
    290   if (nExport >= 0) {
    291     if (CPDF_FormField* pFormField = m_pWidget->GetFormField()) {
    292       swRet = pFormField->GetOptionValue(nExport);
    293       if (swRet.IsEmpty())
    294         swRet = pFormField->GetOptionLabel(nExport);
    295     }
    296   }
    297 
    298   return swRet;
    299 }
    300