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