summaryrefslogtreecommitdiff
path: root/xfa/fwl/cfwl_edit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fwl/cfwl_edit.cpp')
-rw-r--r--xfa/fwl/cfwl_edit.cpp631
1 files changed, 273 insertions, 358 deletions
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<float>(txtEdtParams->pFont->GetAscent()) *
- txtEdtParams->fFontSize / 1000;
-
- std::vector<CFX_RectF> 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<CFX_RectF> 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<size_t, size_t> 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<int32_t>(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<IFDE_TxtEdtDoRecord> 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<CFX_RectF> 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<CFX_RectF> 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<CFGAS_GEFont> pFont = params->pFont;
- if (!pFont)
+ CFX_RetainPtr<CFGAS_GEFont> 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<float>(pRenderDev->GetWidth());
rtDocClip.height = static_cast<float>(pRenderDev->GetHeight());
}
rtDocClip = mt.GetInverse().TransformRect(rtDocClip);
- std::vector<FXTEXT_CHARPOS> 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<FXTEXT_CHARPOS> char_pos = m_EdtEngine.GetDisplayPos(info);
+ if (char_pos.empty())
continue;
- if (char_pos.size() < static_cast<size_t>(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<CFGAS_GEFont> 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<IFDE_TxtEdtDoRecord> pRecord) {
- int32_t nCount = pdfium::CollectionSize<int32_t>(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<int32_t>(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<wchar_t>(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,