From 68eefa6a6f6bbab73000a29e2cac3e104be1cc81 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 30 Aug 2017 12:16:16 -0400 Subject: Rebuild CFDE_TextEditEngine. This CL rebuilds the text edit engine in a simpler fashion. Instead of depending on multiple pages, paragraphs and buffer fields there is a single text edit engine which contains a gap buffer. This makes the code easier to understand and follow. Change-Id: I10fe85603fa9ed15a647eaac2d931f113cd0c7b0 Reviewed-on: https://pdfium-review.googlesource.com/11990 Commit-Queue: dsinclair Reviewed-by: Henrique Nakashima Reviewed-by: Ryan Harrison --- xfa/fwl/cfwl_combobox.cpp | 2 +- xfa/fwl/cfwl_combobox.h | 6 +- xfa/fwl/cfwl_comboedit.cpp | 10 +- xfa/fwl/cfwl_datetimepicker.h | 8 +- xfa/fwl/cfwl_edit.cpp | 631 ++++++++++++++++++------------------------ xfa/fwl/cfwl_edit.h | 50 ++-- 6 files changed, 311 insertions(+), 396 deletions(-) (limited to 'xfa/fwl') diff --git a/xfa/fwl/cfwl_combobox.cpp b/xfa/fwl/cfwl_combobox.cpp index a3dbe8c946..cbfbd9a447 100644 --- a/xfa/fwl/cfwl_combobox.cpp +++ b/xfa/fwl/cfwl_combobox.cpp @@ -11,8 +11,8 @@ #include #include "third_party/base/ptr_util.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fde/cfde_textout.h" -#include "xfa/fde/cfde_txtedtengine.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_eventselectchanged.h" diff --git a/xfa/fwl/cfwl_combobox.h b/xfa/fwl/cfwl_combobox.h index 0e1f815872..7242b1f450 100644 --- a/xfa/fwl/cfwl_combobox.h +++ b/xfa/fwl/cfwl_combobox.h @@ -76,7 +76,7 @@ class CFWL_ComboBox : public CFWL_Widget { bool EditCanRedo() const { return m_pEdit->CanRedo(); } bool EditUndo() { return m_pEdit->Undo(); } bool EditRedo() { return m_pEdit->Redo(); } - bool EditCanCopy() const { return m_pEdit->CountSelRanges() > 0; } + bool EditCanCopy() const { return m_pEdit->HasSelection(); } bool EditCanCut() const { if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) return false; @@ -88,9 +88,9 @@ class CFWL_ComboBox : public CFWL_Widget { bool EditPaste(const CFX_WideString& wsPaste) { return m_pEdit->Paste(wsPaste); } - void EditSelectAll() { m_pEdit->AddSelRange(0); } + void EditSelectAll() { m_pEdit->SelectAll(); } void EditDelete() { m_pEdit->ClearText(); } - void EditDeSelect() { m_pEdit->ClearSelections(); } + void EditDeSelect() { m_pEdit->ClearSelection(); } CFX_RectF GetBBox() const; void EditModifyStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved); diff --git a/xfa/fwl/cfwl_comboedit.cpp b/xfa/fwl/cfwl_comboedit.cpp index 68cde76707..2e53dbdf80 100644 --- a/xfa/fwl/cfwl_comboedit.cpp +++ b/xfa/fwl/cfwl_comboedit.cpp @@ -9,7 +9,7 @@ #include #include -#include "xfa/fde/cfde_txtedtengine.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fwl/cfwl_combobox.h" #include "xfa/fwl/cfwl_messagemouse.h" @@ -22,14 +22,16 @@ CFWL_ComboEdit::CFWL_ComboEdit( } void CFWL_ComboEdit::ClearSelected() { - ClearSelections(); + ClearSelection(); RepaintRect(GetRTClient()); } void CFWL_ComboEdit::SetSelected() { FlagFocus(true); - GetTxtEdtEngine()->MoveCaretPos(FDE_CaretMove::End, false); - AddSelRange(0); + + // TODO(dsinclair): Fix CFWL_CombEdit::SetSelected + // GetTxtEdtEngine()->MoveCaretPos(FDE_CaretMove::End, false); + SelectAll(); } void CFWL_ComboEdit::FlagFocus(bool bSet) { diff --git a/xfa/fwl/cfwl_datetimepicker.h b/xfa/fwl/cfwl_datetimepicker.h index fa7653ecf0..ece489e276 100644 --- a/xfa/fwl/cfwl_datetimepicker.h +++ b/xfa/fwl/cfwl_datetimepicker.h @@ -8,6 +8,7 @@ #define XFA_FWL_CFWL_DATETIMEPICKER_H_ #include +#include #include "xfa/fwl/cfwl_datetimeedit.h" #include "xfa/fwl/cfwl_event.h" @@ -51,9 +52,10 @@ class CFWL_DateTimePicker : public CFWL_Widget { void SetEditText(const CFX_WideString& wsText); CFX_WideString GetEditText() const; - int32_t CountSelRanges() const { return m_pEdit->CountSelRanges(); } - int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const { - return m_pEdit->GetSelRange(nIndex, nStart); + bool HasSelection() const { return m_pEdit->HasSelection(); } + // Returns indices of the selection. + std::pair GetSelection() const { + return m_pEdit->GetSelection(); } CFX_RectF GetBBox() const; diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp index 5ec9378f09..72adb5392b 100644 --- a/xfa/fwl/cfwl_edit.cpp +++ b/xfa/fwl/cfwl_edit.cpp @@ -13,10 +13,8 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fde/cfde_textout.h" -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/cfde_txtedtpage.h" -#include "xfa/fde/cfde_txtedttextset.h" #include "xfa/fgas/font/cfgas_gefont.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_caret.h" @@ -38,6 +36,12 @@ namespace { const int kEditMargin = 3; +#if (_FX_OS_ == _FX_MACOSX_) +constexpr int kEditingModifier = FWL_KEYFLAG_Command; +#else +constexpr int kEditingModifier = FWL_KEYFLAG_Ctrl; +#endif + bool FxEditIsLatinWord(wchar_t c) { return c == 0x2D || (c <= 0x005A && c >= 0x0041) || (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) || @@ -65,24 +69,22 @@ CFWL_Edit::CFWL_Edit(const CFWL_App* app, m_fScrollOffsetX(0.0f), m_fScrollOffsetY(0.0f), m_bLButtonDown(false), - m_nSelStart(0), + m_CursorPosition(0), m_nLimit(-1), m_fFontSize(0), m_bSetRange(false), - m_iMax(0xFFFFFFF), - m_iCurRecord(-1), - m_iMaxRecord(128) { + m_iMax(0xFFFFFFF) { m_rtClient.Reset(); m_rtEngine.Reset(); m_rtStatic.Reset(); InitCaret(); + m_EdtEngine.SetDelegate(this); } CFWL_Edit::~CFWL_Edit() { if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) HideCaret(nullptr); - ClearRecord(); } FWL_Type CFWL_Edit::GetClassID() const { @@ -108,12 +110,14 @@ CFX_RectF CFWL_Edit::GetWidgetRect() { CFX_RectF CFWL_Edit::GetAutosizedWidgetRect() { CFX_RectF rect; - if (m_EdtEngine.GetTextLength() > 0) { - CFX_SizeF sz = CalcTextSize( - m_EdtEngine.GetText(0, -1), m_pProperties->m_pThemeProvider, + + if (m_EdtEngine.GetLength() > 0) { + CFX_SizeF size = CalcTextSize( + m_EdtEngine.GetText(), m_pProperties->m_pThemeProvider, !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine)); - rect = CFX_RectF(0, 0, sz); + rect = CFX_RectF(0, 0, size); } + InflateWidgetRect(rect); return rect; } @@ -163,23 +167,16 @@ void CFWL_Edit::AddSpellCheckObj(CXFA_Path& PathData, int32_t nCount, float fOffSetX, float fOffSetY) { - float fStartX = 0.0f; - float fEndX = 0.0f; - float fY = 0.0f; - float fStep = 0.0f; - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams(); - float fAsent = static_cast(txtEdtParams->pFont->GetAscent()) * - txtEdtParams->fFontSize / 1000; - - std::vector rectArray; - pPage->CalcRangeRectArray(nStart, nCount, &rectArray); - - for (const auto& rectText : rectArray) { - fY = rectText.top + fAsent + fOffSetY; - fStep = txtEdtParams->fFontSize / 16.0f; - fStartX = rectText.left + fOffSetX; - fEndX = fStartX + rectText.Width(); + float fStep = m_EdtEngine.GetFontSize() / 16.0f; + float font_ascent = m_EdtEngine.GetFontAscent(); + + std::vector rects = + m_EdtEngine.GetCharacterRectsInRange(nStart, nCount); + for (const auto& rect : rects) { + float fY = rect.top + font_ascent + fOffSetY; + float fStartX = rect.left + fOffSetX; + float fEndX = fStartX + rect.Width(); + AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep); } } @@ -273,35 +270,36 @@ void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { } void CFWL_Edit::SetText(const CFX_WideString& wsText) { - m_EdtEngine.SetText(wsText); + m_EdtEngine.Clear(); + m_EdtEngine.Insert(0, wsText); } int32_t CFWL_Edit::GetTextLength() const { - return m_EdtEngine.GetTextLength(); + return m_EdtEngine.GetLength(); } CFX_WideString CFWL_Edit::GetText() const { - return m_EdtEngine.GetText(0, -1); + return m_EdtEngine.GetText(); } void CFWL_Edit::ClearText() { - m_EdtEngine.ClearText(); + m_EdtEngine.Clear(); } -void CFWL_Edit::AddSelRange(int32_t nStart) { - m_EdtEngine.AddSelRange(nStart, -1); +void CFWL_Edit::SelectAll() { + m_EdtEngine.SelectAll(); } -int32_t CFWL_Edit::CountSelRanges() const { - return m_EdtEngine.CountSelRanges(); +bool CFWL_Edit::HasSelection() const { + return m_EdtEngine.HasSelection(); } -int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t* nStart) const { - return m_EdtEngine.GetSelRange(nIndex, nStart); +std::pair CFWL_Edit::GetSelection() const { + return m_EdtEngine.GetSelection(); } -void CFWL_Edit::ClearSelections() { - m_EdtEngine.ClearSelection(); +void CFWL_Edit::ClearSelection() { + return m_EdtEngine.ClearSelection(); } int32_t CFWL_Edit::GetLimit() const { @@ -310,7 +308,13 @@ int32_t CFWL_Edit::GetLimit() const { void CFWL_Edit::SetLimit(int32_t nLimit) { m_nLimit = nLimit; - m_EdtEngine.SetLimit(nLimit); + + if (m_nLimit > 0) { + m_EdtEngine.SetHasCharacterLimit(true); + m_EdtEngine.SetCharacterLimit(nLimit); + } else { + m_EdtEngine.SetHasCharacterLimit(false); + } } void CFWL_Edit::SetAliasChar(wchar_t wAlias) { @@ -318,73 +322,55 @@ void CFWL_Edit::SetAliasChar(wchar_t wAlias) { } bool CFWL_Edit::Copy(CFX_WideString& wsCopy) { - int32_t nCount = m_EdtEngine.CountSelRanges(); - if (nCount == 0) + if (!m_EdtEngine.HasSelection()) return false; - wsCopy.clear(); - int32_t nStart; - int32_t nLength; - for (int32_t i = 0; i < nCount; i++) { - nLength = m_EdtEngine.GetSelRange(i, &nStart); - wsCopy += m_EdtEngine.GetText(nStart, nLength); - } + wsCopy = m_EdtEngine.GetSelectedText(); return true; } bool CFWL_Edit::Cut(CFX_WideString& wsCut) { - int32_t nCount = m_EdtEngine.CountSelRanges(); - if (nCount == 0) + if (!m_EdtEngine.HasSelection()) return false; - wsCut.clear(); - CFX_WideString wsTemp; - int32_t nStart, nLength; - for (int32_t i = 0; i < nCount; i++) { - nLength = m_EdtEngine.GetSelRange(i, &nStart); - wsTemp = m_EdtEngine.GetText(nStart, nLength); - wsCut += wsTemp; - wsTemp.clear(); - } - m_EdtEngine.Delete(false); + wsCut = m_EdtEngine.DeleteSelectedText(); return true; } bool CFWL_Edit::Paste(const CFX_WideString& wsPaste) { - FDE_EditResult iError = m_EdtEngine.Insert(wsPaste); - if (iError != FDE_EditResult::kSuccess) { - ProcessInsertError(iError); - return false; - } + if (m_EdtEngine.HasSelection()) + m_EdtEngine.ReplaceSelectedText(wsPaste); + else + m_EdtEngine.Insert(m_CursorPosition, wsPaste); + return true; } bool CFWL_Edit::Undo() { - if (!CanUndo()) - return false; - m_EdtEngine.Undo(m_DoRecords[m_iCurRecord--].get()); - return true; + return CanUndo() ? m_EdtEngine.Undo() : false; } bool CFWL_Edit::Redo() { - if (!CanRedo()) - return false; - m_EdtEngine.Redo(m_DoRecords[++m_iCurRecord].get()); - return true; + return CanRedo() ? m_EdtEngine.Redo() : false; } bool CFWL_Edit::CanUndo() { - return m_iCurRecord >= 0; + return m_EdtEngine.CanUndo(); } bool CFWL_Edit::CanRedo() { - return m_iCurRecord < pdfium::CollectionSize(m_DoRecords) - 1; + return m_EdtEngine.CanRedo(); } void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) { m_pOuter = pOuter; } +void CFWL_Edit::NotifyTextFull() { + CFWL_Event evt(CFWL_Event::Type::TextFull, this); + DispatchEvent(&evt); +} + void CFWL_Edit::OnCaretChanged() { if (m_rtEngine.IsEmpty()) return; @@ -425,10 +411,6 @@ void CFWL_Edit::OnSelChanged() { RepaintRect(GetClientRect()); } -void CFWL_Edit::OnAddDoRecord(std::unique_ptr pRecord) { - AddDoRecord(std::move(pRecord)); -} - bool CFWL_Edit::OnValidate(const CFX_WideString& wsText) { CFWL_Widget* pDst = GetOuter(); if (!pDst) @@ -480,17 +462,15 @@ void CFWL_Edit::DrawTextBk(CXFA_Graphics* pGraphics, void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - pGraphics->SaveGraphState(); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) pGraphics->SaveGraphState(); CFX_RectF rtClip = m_rtEngine; float fOffSetX = m_rtEngine.left - m_fScrollOffsetX; float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + CFX_Matrix mt(1, 0, 0, 1, fOffSetX, fOffSetY); if (pMatrix) { rtClip = pMatrix->TransformRect(rtClip); @@ -498,28 +478,15 @@ void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics, } bool bShowSel = !!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); - int32_t nSelCount = m_EdtEngine.CountSelRanges(); - if (bShowSel && nSelCount > 0) { - int32_t nPageCharStart = pPage->GetCharStart(); - int32_t nPageCharCount = pPage->GetCharCount(); - int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1; - int32_t nCharCount; - int32_t nCharStart; - std::vector rectArr; - for (int32_t i = 0; i < nSelCount; i++) { - nCharCount = m_EdtEngine.GetSelRange(i, &nCharStart); - int32_t nCharEnd = nCharStart + nCharCount - 1; - if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) - continue; - - int32_t nBgn = std::max(nCharStart, nPageCharStart); - int32_t nEnd = std::min(nCharEnd, nPageCharEnd); - pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1, - &rectArr); - } + if (bShowSel && m_EdtEngine.HasSelection()) { + size_t sel_start; + size_t sel_end; + std::tie(sel_start, sel_end) = m_EdtEngine.GetSelection(); + std::vector rects = m_EdtEngine.GetCharacterRectsInRange( + sel_start, sel_end - sel_start + 1); CXFA_Path path; - for (auto& rect : rectArr) { + for (auto& rect : rects) { rect.left += fOffSetX; rect.top += fOffSetY; path.AddRectangle(rect.left, rect.top, rect.width, rect.height); @@ -539,10 +506,11 @@ void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics, if (!pRenderDev) return; - RenderText(pRenderDev, rtClip, *pPage, mt); + RenderText(pRenderDev, rtClip, mt); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { pGraphics->RestoreGraphState(); + CXFA_Path path; int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1; float fStep = m_rtEngine.width / iLimit; @@ -566,83 +534,66 @@ void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics, void CFWL_Edit::RenderText(CFX_RenderDevice* pRenderDev, const CFX_RectF& clipRect, - const CFDE_TxtEdtPage& pPage, const CFX_Matrix& mt) { ASSERT(pRenderDev); - CFDE_TxtEdtTextSet* pTextSet = pPage.GetTextSet(); - if (!pTextSet) - return; - - CFDE_TxtEdtEngine* engine = pPage.GetEngine(); - ASSERT(engine); - const FDE_TXTEDTPARAMS* params = engine->GetEditParams(); - ASSERT(params); - - CFX_RetainPtr pFont = params->pFont; - if (!pFont) + CFX_RetainPtr font = m_EdtEngine.GetFont(); + if (!font) return; pRenderDev->SetClip_Rect(clipRect); CFX_RectF rtDocClip = clipRect; if (rtDocClip.IsEmpty()) { - rtDocClip.left = rtDocClip.top = 0; + rtDocClip.left = 0; + rtDocClip.top = 0; rtDocClip.width = static_cast(pRenderDev->GetWidth()); rtDocClip.height = static_cast(pRenderDev->GetHeight()); } rtDocClip = mt.GetInverse().TransformRect(rtDocClip); - std::vector char_pos; - - for (size_t i = 0; i < pPage.GetTextPieceCount(); ++i) { - const FDE_TEXTEDITPIECE& pText = pPage.GetTextPiece(i); - if (!rtDocClip.IntersectWith(pTextSet->GetRect(pText))) + for (const FDE_TEXTEDITPIECE& info : m_EdtEngine.GetTextPieces()) { + // If this character is outside the clip, skip it. + if (!rtDocClip.IntersectWith(info.rtPiece)) continue; - int32_t iCount = pTextSet->GetDisplayPos(pText, nullptr); - if (iCount < 1) + std::vector char_pos = m_EdtEngine.GetDisplayPos(info); + if (char_pos.empty()) continue; - if (char_pos.size() < static_cast(iCount)) - char_pos.resize(iCount, FXTEXT_CHARPOS()); - iCount = pTextSet->GetDisplayPos(pText, char_pos.data()); - CFDE_TextOut::DrawString(pRenderDev, params->dwFontColor, pFont, - char_pos.data(), iCount, params->fFontSize, &mt); + CFDE_TextOut::DrawString(pRenderDev, m_EdtEngine.GetFontColor(), font, + char_pos.data(), char_pos.size(), + m_EdtEngine.GetFontSize(), &mt); } } void CFWL_Edit::UpdateEditEngine() { UpdateEditParams(); UpdateEditLayout(); - if (m_nLimit > -1) - m_EdtEngine.SetLimit(m_nLimit); } void CFWL_Edit::UpdateEditParams() { - FDE_TXTEDTPARAMS params; - params.fPlateWidth = m_rtEngine.width; - params.fPlateHeight = m_rtEngine.height; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) - params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) - params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) - params.dwMode |= FDE_TEXTEDITMODE_Validate; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) - params.dwMode |= FDE_TEXTEDITMODE_Password; + m_EdtEngine.SetAvailableWidth(m_rtEngine.width); + m_EdtEngine.SetCombText( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)); + + m_EdtEngine.EnableValidation( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate)); + m_EdtEngine.EnablePasswordMode( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password)); + uint32_t alignment = 0; switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) { case FWL_STYLEEXT_EDT_HNear: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Left; + alignment |= CFX_TxtLineAlignment_Left; break; } case FWL_STYLEEXT_EDT_HCenter: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Center; + alignment |= CFX_TxtLineAlignment_Center; break; } case FWL_STYLEEXT_EDT_HFar: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Right; + alignment |= CFX_TxtLineAlignment_Right; break; } default: @@ -650,88 +601,74 @@ void CFWL_Edit::UpdateEditParams() { } switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) { case FWL_STYLEEXT_EDT_Justified: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Justified; + alignment |= CFX_TxtLineAlignment_Justified; break; } default: break; } + m_EdtEngine.SetAlignment(alignment); + + bool auto_hscroll = + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { - params.dwMode |= FDE_TEXTEDITMODE_MultiLines; - if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { - params.dwMode |= - FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz; - } - if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && - (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) { - params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert; - } else { - params.fPlateHeight = 0x00FFFFFF; - } - } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == - 0) { - params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz; + m_EdtEngine.EnableMultiLine(true); + m_EdtEngine.EnableLineWrap(!auto_hscroll); + m_EdtEngine.LimitVerticalScroll( + (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0); + } else { + m_EdtEngine.EnableMultiLine(false); + m_EdtEngine.EnableLineWrap(false); + m_EdtEngine.LimitVerticalScroll(false); } + m_EdtEngine.LimitHorizontalScroll(!auto_hscroll); IFWL_ThemeProvider* theme = GetAvailableTheme(); CFWL_ThemePart part; part.m_pWidget = this; - m_fFontSize = theme ? theme->GetFontSize(&part) : FWLTHEME_CAPACITY_FontSize; - if (!theme) + if (!theme) { + m_fFontSize = FWLTHEME_CAPACITY_FontSize; return; - - params.dwFontColor = theme->GetTextColor(&part); - params.fLineSpace = theme->GetLineHeight(&part); + } + m_fFontSize = theme->GetFontSize(&part); CFX_RetainPtr pFont = theme->GetFont(&part); if (!pFont) return; - params.pFont = pFont; - params.fFontSize = m_fFontSize; - params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace); - if (params.nLineCount <= 0) - params.nLineCount = 1; - params.fTabWidth = params.fFontSize * 1; - params.pEventSink = this; - m_EdtEngine.SetEditParams(params); + m_EdtEngine.SetFont(pFont); + m_EdtEngine.SetFontColor(theme->GetTextColor(&part)); + m_EdtEngine.SetFontSize(m_fFontSize); + m_EdtEngine.SetLineSpace(theme->GetLineHeight(&part)); + m_EdtEngine.SetTabWidth(m_fFontSize); + m_EdtEngine.SetVisibleLineCount(m_rtEngine.height / + theme->GetLineHeight(&part)); } void CFWL_Edit::UpdateEditLayout() { - if (m_EdtEngine.GetTextLength() <= 0) - m_EdtEngine.SetText(L""); - - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (pPage) - pPage->UnloadPage(); - m_EdtEngine.Layout(); - - pPage = m_EdtEngine.GetPage(0); - if (pPage) - pPage->LoadPage(); } bool CFWL_Edit::UpdateOffset() { - CFX_RectF rtCaret = m_EdtEngine.GetCaretRect(); + CFX_RectF rtCaret = m_rtCaret; + float fOffSetX = m_rtEngine.left - m_fScrollOffsetX; float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; rtCaret.Offset(fOffSetX, fOffSetY); - const CFX_RectF& rtEidt = m_rtEngine; - if (rtEidt.Contains(rtCaret)) { - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return false; - CFX_RectF rtFDE = pPage->GetContentsBox(); - rtFDE.Offset(fOffSetX, fOffSetY); - if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) { - m_fScrollOffsetX += rtFDE.right() - rtEidt.right(); + const CFX_RectF& edit_bounds = m_rtEngine; + if (edit_bounds.Contains(rtCaret)) { + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); + contents_bounds.Offset(fOffSetX, fOffSetY); + if (contents_bounds.right() < edit_bounds.right() && m_fScrollOffsetX > 0) { + m_fScrollOffsetX += contents_bounds.right() - edit_bounds.right(); m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f); } - if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) { - m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom(); + if (contents_bounds.bottom() < edit_bounds.bottom() && + m_fScrollOffsetY > 0) { + m_fScrollOffsetY += contents_bounds.bottom() - edit_bounds.bottom(); m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f); } return false; @@ -739,18 +676,20 @@ bool CFWL_Edit::UpdateOffset() { float offsetX = 0.0; float offsetY = 0.0; - if (rtCaret.left < rtEidt.left) - offsetX = rtCaret.left - rtEidt.left; - if (rtCaret.right() > rtEidt.right()) - offsetX = rtCaret.right() - rtEidt.right(); - if (rtCaret.top < rtEidt.top) - offsetY = rtCaret.top - rtEidt.top; - if (rtCaret.bottom() > rtEidt.bottom()) - offsetY = rtCaret.bottom() - rtEidt.bottom(); + if (rtCaret.left < edit_bounds.left) + offsetX = rtCaret.left - edit_bounds.left; + if (rtCaret.right() > edit_bounds.right()) + offsetX = rtCaret.right() - edit_bounds.right(); + if (rtCaret.top < edit_bounds.top) + offsetY = rtCaret.top - edit_bounds.top; + if (rtCaret.bottom() > edit_bounds.bottom()) + offsetY = rtCaret.bottom() - edit_bounds.bottom(); + m_fScrollOffsetX += offsetX; m_fScrollOffsetY += offsetY; if (m_fFontSize > m_rtEngine.height) m_fScrollOffsetY = 0; + return true; } @@ -763,12 +702,6 @@ bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, float fPosChanged) { } void CFWL_Edit::UpdateVAlignment() { - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - - const CFX_RectF& rtFDE = pPage->GetContentsBox(); - float fOffsetY = 0.0f; float fSpaceAbove = 0.0f; float fSpaceBelow = 0.0f; IFWL_ThemeProvider* theme = GetAvailableTheme(); @@ -777,23 +710,21 @@ void CFWL_Edit::UpdateVAlignment() { part.m_pWidget = this; CFX_SizeF pSpace = theme->GetSpaceAboveBelow(&part); - fSpaceAbove = pSpace.width; - fSpaceBelow = pSpace.height; + fSpaceAbove = pSpace.width >= 0.1f ? pSpace.width : 0.0f; + fSpaceBelow = pSpace.height >= 0.1f ? pSpace.height : 0.0f; } - if (fSpaceAbove < 0.1f) - fSpaceAbove = 0; - if (fSpaceBelow < 0.1f) - fSpaceBelow = 0; + float fOffsetY = 0.0f; + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) { - fOffsetY = (m_rtEngine.height - rtFDE.height) / 2; - if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 && + fOffsetY = (m_rtEngine.height - contents_bounds.height) / 2.0f; + if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2.0f && fSpaceAbove < fSpaceBelow) { return; } - fOffsetY += (fSpaceAbove - fSpaceBelow) / 2; + fOffsetY += (fSpaceAbove - fSpaceBelow) / 2.0f; } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) { - fOffsetY = (m_rtEngine.height - rtFDE.height); + fOffsetY = (m_rtEngine.height - contents_bounds.height); fOffsetY -= fSpaceBelow; } else { fOffsetY += fSpaceAbove; @@ -802,11 +733,9 @@ void CFWL_Edit::UpdateVAlignment() { } void CFWL_Edit::UpdateCaret() { - CFX_RectF rtFDE = m_EdtEngine.GetCaretRect(); - - rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX, - m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); - CFX_RectF rtCaret(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height); + CFX_RectF rtCaret = m_rtCaret; + rtCaret.Offset(m_rtEngine.left - m_fScrollOffsetX, + m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); CFX_RectF rtClient = GetClientRect(); rtCaret.Intersect(rtClient); @@ -832,17 +761,13 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { if (!bShowHorz && !bShowVert) return nullptr; - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return nullptr; - - const CFX_RectF& rtFDE = pPage->GetContentsBox(); + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); CFWL_ScrollBar* pRepaint = nullptr; if (bShowHorz) { CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect(); - if (rtScroll.width < rtFDE.width) { + if (rtScroll.width < contents_bounds.width) { m_pHorzScrollBar->LockUpdate(); - float fRange = rtFDE.width - rtScroll.width; + float fRange = contents_bounds.width - rtScroll.width; m_pHorzScrollBar->SetRange(0.0f, fRange); float fPos = pdfium::clamp(m_fScrollOffsetX, 0.0f, fRange); @@ -866,10 +791,11 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { if (bShowVert) { CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect(); - if (rtScroll.height < rtFDE.height) { + if (rtScroll.height < contents_bounds.height) { m_pVertScrollBar->LockUpdate(); - float fStep = m_EdtEngine.GetEditParams()->fLineSpace; - float fRange = std::max(rtFDE.height - m_rtEngine.height, fStep); + float fStep = m_EdtEngine.GetLineSpace(); + float fRange = + std::max(contents_bounds.height - m_rtEngine.height, fStep); m_pVertScrollBar->SetRange(0.0f, fRange); float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange); @@ -907,27 +833,7 @@ bool CFWL_Edit::IsShowScrollBar(bool bVert) { } bool CFWL_Edit::IsContentHeightOverflow() { - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return false; - return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f; -} - -int32_t CFWL_Edit::AddDoRecord(std::unique_ptr pRecord) { - int32_t nCount = pdfium::CollectionSize(m_DoRecords); - if (m_iCurRecord == nCount - 1) { - if (nCount == m_iMaxRecord) { - m_DoRecords.pop_front(); - m_iCurRecord--; - } - } else { - m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1, - m_DoRecords.end()); - } - - m_DoRecords.push_back(std::move(pRecord)); - m_iCurRecord = pdfium::CollectionSize(m_DoRecords) - 1; - return m_iCurRecord; + return m_EdtEngine.GetContentsBoundingBox().height > m_rtEngine.height + 1.0f; } void CFWL_Edit::Layout() { @@ -1143,42 +1049,47 @@ bool CFWL_Edit::ValidateNumberChar(wchar_t cNum) { if (!m_bSetRange) return true; - CFX_WideString wsText = m_EdtEngine.GetText(0, -1); + CFX_WideString wsText = m_EdtEngine.GetText(); if (wsText.IsEmpty()) return cNum != L'0'; - if (CountSelRanges() != 0) + if (HasSelection()) return wsText.GetInteger() <= m_iMax; - - int32_t caretPos = m_EdtEngine.GetCaretPos(); - if (cNum == L'0' && caretPos == 0) + if (cNum == L'0' && m_CursorPosition == 0) return false; int32_t nLen = wsText.GetLength(); - CFX_WideString l = wsText.Left(caretPos); - CFX_WideString r = wsText.Right(nLen - caretPos); + CFX_WideString l = wsText.Left(m_CursorPosition); + CFX_WideString r = wsText.Right(nLen - m_CursorPosition); CFX_WideString wsNew = l + cNum + r; return wsNew.GetInteger() <= m_iMax; } void CFWL_Edit::InitCaret() { m_pCaret.reset(); + m_rtCaret = CFX_RectF(); } -void CFWL_Edit::ClearRecord() { - m_iCurRecord = -1; - m_DoRecords.clear(); -} +void CFWL_Edit::UpdateCursorRect() { + int32_t bidi_level = 0; + m_rtCaret = CFX_RectF(); + std::tie(bidi_level, m_rtCaret) = + m_EdtEngine.GetCharacterInfo(m_CursorPosition); + // TODO(dsinclair): This should handle bidi level ... -void CFWL_Edit::ProcessInsertError(FDE_EditResult iError) { - // TODO(dsinclair): This should probably also send events for Validation - // failure .... + if (m_rtCaret.width == 0 && m_rtCaret.left > 1.0f) + m_rtCaret.left -= 1.0f; - if (iError != FDE_EditResult::kFull) + m_rtCaret.width = 1.0f; +} + +void CFWL_Edit::SetCursorPosition(size_t position) { + if (m_CursorPosition == position) return; - CFWL_Event textFullEvent(CFWL_Event::Type::TextFull, this); - DispatchEvent(&textFullEvent); + m_CursorPosition = position; + UpdateCursorRect(); + OnCaretChanged(); } void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { @@ -1202,7 +1113,7 @@ void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { OnLButtonUp(pMsg); break; case FWL_MouseCommand::LeftButtonDblClk: - OnButtonDblClk(pMsg); + OnButtonDoubleClick(pMsg); break; case FWL_MouseCommand::Move: OnMouseMove(pMsg); @@ -1251,14 +1162,13 @@ void CFWL_Edit::DoButtonDown(CFWL_MessageMouse* pMsg) { if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) SetFocus(true); - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; + // TODO(dsinclair): Handle DoButtonDown + // bool bBefore = true; + // int32_t nIndex = + // std::max(0, pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos), + // bBefore)); - bool bBefore = true; - int32_t nIndex = - std::max(0, pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos), bBefore)); - m_EdtEngine.SetCaretPos(nIndex, bBefore); + // SetCursorPosition(nIndex); } void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { @@ -1273,15 +1183,11 @@ void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; HideCaret(nullptr); - int32_t nSel = CountSelRanges(); - if (nSel > 0) { - ClearSelections(); + if (HasSelection()) { + ClearSelection(); bRepaint = true; } - m_EdtEngine.SetCaretPos(0, true); UpdateOffset(); - - ClearRecord(); } LayoutScrollBar(); @@ -1300,21 +1206,24 @@ void CFWL_Edit::OnLButtonDown(CFWL_MessageMouse* pMsg) { m_bLButtonDown = true; SetGrab(true); DoButtonDown(pMsg); - int32_t nIndex = m_EdtEngine.GetCaretPos(); + bool bRepaint = false; - if (m_EdtEngine.CountSelRanges() > 0) { + if (m_EdtEngine.HasSelection()) { m_EdtEngine.ClearSelection(); bRepaint = true; } - if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) { - int32_t iStart = std::min(m_nSelStart, nIndex); - int32_t iEnd = std::max(m_nSelStart, nIndex); - m_EdtEngine.AddSelRange(iStart, iEnd - iStart); + size_t index_at_click = + m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos)); + if (index_at_click != m_CursorPosition && + !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift)) { + size_t start = std::min(m_CursorPosition, index_at_click); + size_t end = std::max(m_CursorPosition, index_at_click); + + m_EdtEngine.SetSelection(start, end); bRepaint = true; - } else { - m_nSelStart = nIndex; } + if (bRepaint) RepaintRect(m_rtEngine); } @@ -1324,80 +1233,83 @@ void CFWL_Edit::OnLButtonUp(CFWL_MessageMouse* pMsg) { SetGrab(false); } -void CFWL_Edit::OnButtonDblClk(CFWL_MessageMouse* pMsg) { - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - - int32_t nCount = 0; - int32_t nIndex = pPage->SelectWord(DeviceToEngine(pMsg->m_pos), nCount); - if (nIndex < 0) - return; - - m_EdtEngine.AddSelRange(nIndex, nCount); - m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false); +void CFWL_Edit::OnButtonDoubleClick(CFWL_MessageMouse* pMsg) { + // TODO(dsinclair): Handle OnButtonDoubleClick + // int32_t nCount = 0; + // int32_t nIndex = pPage->SelectWord(DeviceToEngine(pMsg->m_pos), nCount); + // if (nIndex < 0) + // return; + // + // m_EdtEngine.AddSelRange(nIndex, nCount); + // SetCursorPosition(nIndex + nCount - 1); RepaintRect(m_rtEngine); } void CFWL_Edit::OnMouseMove(CFWL_MessageMouse* pMsg) { - if (m_nSelStart == -1 || !m_bLButtonDown) + bool shift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); + if (!m_bLButtonDown || !shift) return; - CFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) + size_t old_cursor_pos = m_CursorPosition; + SetCursorPosition(m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos))); + if (old_cursor_pos == m_CursorPosition) return; - bool bBefore = true; - int32_t nIndex = pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos), bBefore); - m_EdtEngine.SetCaretPos(nIndex, bBefore); - nIndex = m_EdtEngine.GetCaretPos(); - m_EdtEngine.ClearSelection(); + size_t length = m_EdtEngine.GetLength(); + if (m_CursorPosition > length) + SetCursorPosition(length); - if (nIndex == m_nSelStart) - return; - - int32_t nLen = m_EdtEngine.GetTextLength(); - if (m_nSelStart >= nLen) - m_nSelStart = nLen; - - m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex), - abs(nIndex - m_nSelStart)); + size_t sel_start; + size_t sel_end; + std::tie(sel_start, sel_end) = m_EdtEngine.GetSelection(); + m_EdtEngine.SetSelection(std::min(sel_start, m_CursorPosition), + std::max(sel_end, m_CursorPosition)); } void CFWL_Edit::OnKeyDown(CFWL_MessageKey* pMsg) { bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl); + + size_t sel_start = m_CursorPosition; + if (m_EdtEngine.HasSelection()) { + size_t start_idx; + size_t end_idx; + std::tie(start_idx, end_idx) = m_EdtEngine.GetSelection(); + sel_start = start_idx; + } + switch (pMsg->m_dwKeyCode) { case FWL_VKEY_Left: - m_EdtEngine.MoveCaretPos(FDE_CaretMove::Left, bShift); + SetCursorPosition(m_EdtEngine.GetIndexLeft(m_CursorPosition)); break; case FWL_VKEY_Right: - m_EdtEngine.MoveCaretPos(FDE_CaretMove::Right, bShift); + SetCursorPosition(m_EdtEngine.GetIndexRight(m_CursorPosition)); break; case FWL_VKEY_Up: - m_EdtEngine.MoveCaretPos(FDE_CaretMove::Up, bShift); + SetCursorPosition(m_EdtEngine.GetIndexUp(m_CursorPosition)); break; case FWL_VKEY_Down: - m_EdtEngine.MoveCaretPos(FDE_CaretMove::Down, bShift); + SetCursorPosition(m_EdtEngine.GetIndexDown(m_CursorPosition)); break; case FWL_VKEY_Home: - m_EdtEngine.MoveCaretPos( - bCtrl ? FDE_CaretMove::Home : FDE_CaretMove::LineStart, bShift); + SetCursorPosition( + bCtrl ? 0 : m_EdtEngine.GetIndexAtStartOfLine(m_CursorPosition)); break; case FWL_VKEY_End: - m_EdtEngine.MoveCaretPos( - bCtrl ? FDE_CaretMove::End : FDE_CaretMove::LineEnd, bShift); + SetCursorPosition( + bCtrl ? m_EdtEngine.GetLength() + : m_EdtEngine.GetIndexAtEndOfLine(m_CursorPosition)); break; case FWL_VKEY_Delete: { if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { break; } -#if (_FX_OS_ == _FX_MACOSX_) - m_EdtEngine.Delete(true); -#else - m_EdtEngine.Delete(false); -#endif + + if (m_CursorPosition > 0) { + SetCursorPosition(m_EdtEngine.GetIndexBefore(m_CursorPosition)); + m_EdtEngine.Delete(m_CursorPosition, 1); + } break; } case FWL_VKEY_Insert: @@ -1406,6 +1318,13 @@ void CFWL_Edit::OnKeyDown(CFWL_MessageKey* pMsg) { default: break; } + + // Update the selection. + if (bShift && sel_start != m_CursorPosition) { + m_EdtEngine.SetSelection(std::min(sel_start, m_CursorPosition), + std::max(sel_start, m_CursorPosition)); + RepaintRect(m_rtEngine); + } } void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { @@ -1414,25 +1333,27 @@ void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { return; } - FDE_EditResult iError = FDE_EditResult::kSuccess; wchar_t c = static_cast(pMsg->m_dwKeyCode); switch (c) { case FWL_VKEY_Back: - m_EdtEngine.Delete(true); + if (m_CursorPosition > 0) { + SetCursorPosition(m_EdtEngine.GetIndexBefore(m_CursorPosition)); + m_EdtEngine.Delete(m_CursorPosition, 1); + } break; case FWL_VKEY_NewLine: case FWL_VKEY_Escape: break; - case FWL_VKEY_Tab: { - iError = m_EdtEngine.Insert(L"\t"); + case FWL_VKEY_Tab: + m_EdtEngine.Insert(m_CursorPosition, L"\t"); + SetCursorPosition(m_CursorPosition + 1); break; - } - case FWL_VKEY_Return: { + case FWL_VKEY_Return: if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) { - iError = m_EdtEngine.Insert(L"\n"); + m_EdtEngine.Insert(m_CursorPosition, L"\n"); + SetCursorPosition(m_CursorPosition + 1); } break; - } default: { if (!m_pWidgetMgr->IsFormDisabled()) { if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) { @@ -1445,20 +1366,14 @@ void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { break; } } -#if (_FX_OS_ == _FX_MACOSX_) - if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) -#else - if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) -#endif - { + if (pMsg->m_dwFlags & kEditingModifier) break; - } - iError = m_EdtEngine.Insert(CFX_WideString(c)); + + m_EdtEngine.Insert(m_CursorPosition, CFX_WideString(c)); + SetCursorPosition(m_CursorPosition + 1); break; } } - if (iError != FDE_EditResult::kSuccess) - ProcessInsertError(iError); } bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar, diff --git a/xfa/fwl/cfwl_edit.h b/xfa/fwl/cfwl_edit.h index 4a30904b0a..310cb81578 100644 --- a/xfa/fwl/cfwl_edit.h +++ b/xfa/fwl/cfwl_edit.h @@ -7,12 +7,11 @@ #ifndef XFA_FWL_CFWL_EDIT_H_ #define XFA_FWL_CFWL_EDIT_H_ -#include #include +#include #include -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/ifde_txtedtdorecord.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_scrollbar.h" #include "xfa/fwl/cfwl_widget.h" @@ -39,15 +38,13 @@ #define FWL_STYLEEXT_EDT_HAlignModeMask (3L << 22) #define FWL_STYLEEXT_EDT_ShowScrollbarFocus (1L << 25) #define FWL_STYLEEXT_EDT_OuterScrollbar (1L << 26) -#define FWL_STYLEEXT_EDT_LastLineHeight (1L << 27) -class IFDE_TxtEdtDoRecord; class CFWL_Edit; class CFWL_MessageMouse; class CFWL_WidgetProperties; class CFWL_Caret; -class CFWL_Edit : public CFWL_Widget { +class CFWL_Edit : public CFWL_Widget, public CFDE_TextEditEngine::Delegate { public: CFWL_Edit(const CFWL_App* app, std::unique_ptr properties, @@ -74,10 +71,12 @@ class CFWL_Edit : public CFWL_Widget { CFX_WideString GetText() const; void ClearText(); - void AddSelRange(int32_t nStart); - int32_t CountSelRanges() const; - int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const; - void ClearSelections(); + void SelectAll(); + void ClearSelection(); + bool HasSelection() const; + // Returns indices of the selection. + std::pair GetSelection() const; + int32_t GetLimit() const; void SetLimit(int32_t nLimit); void SetAliasChar(wchar_t wAlias); @@ -91,23 +90,23 @@ class CFWL_Edit : public CFWL_Widget { void SetOuter(CFWL_Widget* pOuter); - void OnCaretChanged(); - void OnTextChanged(const CFX_WideString& prevText); - void OnSelChanged(); - void OnAddDoRecord(std::unique_ptr pRecord); - bool OnValidate(const CFX_WideString& wsText); - void SetScrollOffset(float fScrollOffset); + // CFDE_TextEditEngine::Delegate + void NotifyTextFull() override; + void OnCaretChanged() override; + void OnTextChanged(const CFX_WideString& prevText) override; + void OnSelChanged() override; + bool OnValidate(const CFX_WideString& wsText) override; + void SetScrollOffset(float fScrollOffset) override; protected: void ShowCaret(CFX_RectF* pRect); void HideCaret(CFX_RectF* pRect); const CFX_RectF& GetRTClient() const { return m_rtClient; } - CFDE_TxtEdtEngine* GetTxtEdtEngine() { return &m_EdtEngine; } + CFDE_TextEditEngine* GetTxtEdtEngine() { return &m_EdtEngine; } private: void RenderText(CFX_RenderDevice* pRenderDev, const CFX_RectF& clipRect, - const CFDE_TxtEdtPage& pPage, const CFX_Matrix& mt); void DrawTextBk(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, @@ -133,22 +132,21 @@ class CFWL_Edit : public CFWL_Widget { void InitEngine(); void InitCaret(); bool ValidateNumberChar(wchar_t cNum); - void ClearRecord(); bool IsShowScrollBar(bool bVert); bool IsContentHeightOverflow(); - int32_t AddDoRecord(std::unique_ptr pRecord); - void ProcessInsertError(FDE_EditResult iError); void AddSpellCheckObj(CXFA_Path& PathData, int32_t nStart, int32_t nCount, float fOffSetX, float fOffSetY); + void SetCursorPosition(size_t position); + void UpdateCursorRect(); void DoButtonDown(CFWL_MessageMouse* pMsg); void OnFocusChanged(CFWL_Message* pMsg, bool bSet); void OnLButtonDown(CFWL_MessageMouse* pMsg); void OnLButtonUp(CFWL_MessageMouse* pMsg); - void OnButtonDblClk(CFWL_MessageMouse* pMsg); + void OnButtonDoubleClick(CFWL_MessageMouse* pMsg); void OnMouseMove(CFWL_MessageMouse* pMsg); void OnKeyDown(CFWL_MessageKey* pMsg); void OnChar(CFWL_MessageKey* pMsg); @@ -159,12 +157,13 @@ class CFWL_Edit : public CFWL_Widget { CFX_RectF m_rtClient; CFX_RectF m_rtEngine; CFX_RectF m_rtStatic; + CFX_RectF m_rtCaret; float m_fVAlignOffset; float m_fScrollOffsetX; float m_fScrollOffsetY; - CFDE_TxtEdtEngine m_EdtEngine; + CFDE_TextEditEngine m_EdtEngine; bool m_bLButtonDown; - int32_t m_nSelStart; + size_t m_CursorPosition; int32_t m_nLimit; float m_fFontSize; bool m_bSetRange; @@ -174,9 +173,6 @@ class CFWL_Edit : public CFWL_Widget { std::unique_ptr m_pCaret; CFX_WideString m_wsCache; CFX_WideString m_wsFont; - std::deque> m_DoRecords; - int32_t m_iCurRecord; - int32_t m_iMaxRecord; }; #endif // XFA_FWL_CFWL_EDIT_H_ -- cgit v1.2.3