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