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 15CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, 16 CPDFSDK_Annot* pAnnot) 17 : CFFL_FormFiller(pApp, pAnnot) {} 18 19CFFL_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 29PWL_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 85CPWL_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 108bool 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 143bool 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 150void 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 162void 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 192void 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 208bool 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 223void 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 232void 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 241CPWL_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 263bool 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 272void 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