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