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_Widget* pWidget)
     17     : CFFL_TextObject(pApp, pWidget) {}
     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 CPWL_Wnd::CreateParams CFFL_TextField::GetCreateParam() {
     30   CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
     31   int nFlags = m_pWidget->GetFieldFlags();
     32   if (nFlags & FIELDFLAG_PASSWORD)
     33     cp.dwFlags |= PES_PASSWORD;
     34 
     35   if (nFlags & FIELDFLAG_MULTILINE) {
     36     cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;
     37     if (!(nFlags & FIELDFLAG_DONOTSCROLL))
     38       cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
     39   } else {
     40     cp.dwFlags |= PES_CENTER;
     41     if (!(nFlags & FIELDFLAG_DONOTSCROLL))
     42       cp.dwFlags |= PES_AUTOSCROLL;
     43   }
     44 
     45   if (nFlags & FIELDFLAG_COMB)
     46     cp.dwFlags |= PES_CHARARRAY;
     47 
     48   if (nFlags & FIELDFLAG_RICHTEXT)
     49     cp.dwFlags |= PES_RICH;
     50 
     51   cp.dwFlags |= PES_UNDO;
     52 
     53   switch (m_pWidget->GetAlignment()) {
     54     default:
     55     case BF_ALIGN_LEFT:
     56       cp.dwFlags |= PES_LEFT;
     57       break;
     58     case BF_ALIGN_MIDDLE:
     59       cp.dwFlags |= PES_MIDDLE;
     60       break;
     61     case BF_ALIGN_RIGHT:
     62       cp.dwFlags |= PES_RIGHT;
     63       break;
     64   }
     65   cp.pFontMap = MaybeCreateFontMap();
     66   cp.pFocusHandler = this;
     67   return cp;
     68 }
     69 
     70 CPWL_Wnd* CFFL_TextField::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
     71   auto* pWnd = new CPWL_Edit();
     72   pWnd->AttachFFLData(this);
     73   pWnd->Create(cp);
     74   pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
     75 
     76   int32_t nMaxLen = m_pWidget->GetMaxLen();
     77   WideString swValue = m_pWidget->GetValue();
     78 
     79   if (nMaxLen > 0) {
     80     if (pWnd->HasFlag(PES_CHARARRAY)) {
     81       pWnd->SetCharArray(nMaxLen);
     82       pWnd->SetAlignFormatV(PEAV_CENTER);
     83     } else {
     84       pWnd->SetLimitChar(nMaxLen);
     85     }
     86   }
     87 
     88   pWnd->SetText(swValue);
     89   return pWnd;
     90 }
     91 
     92 bool CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot,
     93                             uint32_t nChar,
     94                             uint32_t nFlags) {
     95   switch (nChar) {
     96     case FWL_VKEY_Return: {
     97       if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)
     98         break;
     99 
    100       CPDFSDK_PageView* pPageView = GetCurPageView(true);
    101       ASSERT(pPageView);
    102       m_bValid = !m_bValid;
    103       m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
    104                                  pAnnot->GetRect().GetOuterRect());
    105 
    106       if (m_bValid) {
    107         if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
    108           pWnd->SetFocus();
    109         break;
    110       }
    111 
    112       if (!CommitData(pPageView, nFlags))
    113         return false;
    114 
    115       DestroyPDFWindow(pPageView);
    116       return true;
    117     }
    118     case FWL_VKEY_Escape: {
    119       CPDFSDK_PageView* pPageView = GetCurPageView(true);
    120       ASSERT(pPageView);
    121       EscapeFiller(pPageView, true);
    122       return true;
    123     }
    124   }
    125 
    126   return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
    127 }
    128 
    129 bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
    130   CPWL_Edit* pEdit = GetEdit(pPageView, false);
    131   return pEdit && pEdit->GetText() != m_pWidget->GetValue();
    132 }
    133 
    134 void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) {
    135   CPWL_Edit* pWnd = GetEdit(pPageView, false);
    136   if (!pWnd)
    137     return;
    138 
    139   WideString sOldValue = m_pWidget->GetValue();
    140   WideString sNewValue = pWnd->GetText();
    141 
    142   CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
    143   CFFL_TextField::ObservedPtr observed_this(this);
    144 
    145   m_pWidget->SetValue(sNewValue, false);
    146   if (!observed_widget)
    147     return;
    148   m_pWidget->ResetFieldAppearance(true);
    149   if (!observed_widget)
    150     return;
    151   m_pWidget->UpdateField();
    152   if (!observed_widget || !observed_this)
    153     return;
    154   SetChangeMark();
    155 }
    156 
    157 void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView,
    158                                    CPDF_AAction::AActionType type,
    159                                    PDFSDK_FieldAction& fa) {
    160   switch (type) {
    161     case CPDF_AAction::KeyStroke:
    162       if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
    163         fa.bFieldFull = pWnd->IsTextFull();
    164 
    165         fa.sValue = pWnd->GetText();
    166 
    167         if (fa.bFieldFull) {
    168           fa.sChange = L"";
    169           fa.sChangeEx = L"";
    170         }
    171       }
    172       break;
    173     case CPDF_AAction::Validate:
    174       if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
    175         fa.sValue = pWnd->GetText();
    176       }
    177       break;
    178     case CPDF_AAction::LoseFocus:
    179     case CPDF_AAction::GetFocus:
    180       fa.sValue = m_pWidget->GetValue();
    181       break;
    182     default:
    183       break;
    184   }
    185 }
    186 
    187 void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView,
    188                                    CPDF_AAction::AActionType type,
    189                                    const PDFSDK_FieldAction& fa) {
    190   switch (type) {
    191     case CPDF_AAction::KeyStroke:
    192       if (CPWL_Edit* pEdit = GetEdit(pPageView, false)) {
    193         pEdit->SetFocus();
    194         pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
    195         pEdit->ReplaceSel(fa.sChange);
    196       }
    197       break;
    198     default:
    199       break;
    200   }
    201 }
    202 
    203 bool CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type,
    204                                          const PDFSDK_FieldAction& faOld,
    205                                          const PDFSDK_FieldAction& faNew) {
    206   switch (type) {
    207     case CPDF_AAction::KeyStroke:
    208       return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
    209              faOld.nSelStart != faNew.nSelStart ||
    210              faOld.sChange != faNew.sChange;
    211     default:
    212       break;
    213   }
    214 
    215   return false;
    216 }
    217 
    218 void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) {
    219   ASSERT(pPageView);
    220 
    221   CPWL_Edit* pWnd = GetEdit(pPageView, false);
    222   if (!pWnd)
    223     return;
    224 
    225   pWnd->GetSelection(m_State.nStart, m_State.nEnd);
    226   m_State.sValue = pWnd->GetText();
    227 }
    228 
    229 void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) {
    230   ASSERT(pPageView);
    231 
    232   CPWL_Edit* pWnd = GetEdit(pPageView, true);
    233   if (!pWnd)
    234     return;
    235 
    236   pWnd->SetText(m_State.sValue);
    237   pWnd->SetSelection(m_State.nStart, m_State.nEnd);
    238 }
    239 
    240 #ifdef PDF_ENABLE_XFA
    241 bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
    242   CPWL_Edit* pWnd = GetEdit(pPageView, false);
    243   return pWnd && pWnd->IsTextFull();
    244 }
    245 #endif  // PDF_ENABLE_XFA
    246 
    247 void CFFL_TextField::OnSetFocus(CPWL_Edit* pEdit) {
    248   pEdit->SetCharSet(FX_CHARSET_ChineseSimplified);
    249   pEdit->SetReadyToInput();
    250 
    251   WideString wsText = pEdit->GetText();
    252   int nCharacters = wsText.GetLength();
    253   ByteString bsUTFText = wsText.UTF16LE_Encode();
    254   auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
    255   m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
    256 }
    257 
    258 CPWL_Edit* CFFL_TextField::GetEdit(CPDFSDK_PageView* pPageView, bool bNew) {
    259   return static_cast<CPWL_Edit*>(GetPDFWindow(pPageView, bNew));
    260 }
    261