summaryrefslogtreecommitdiffstats
path: root/widget/TextRange.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/TextRange.h')
-rw-r--r--widget/TextRange.h314
1 files changed, 314 insertions, 0 deletions
diff --git a/widget/TextRange.h b/widget/TextRange.h
new file mode 100644
index 000000000..7934e9e23
--- /dev/null
+++ b/widget/TextRange.h
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_TextRage_h_
+#define mozilla_TextRage_h_
+
+#include <stdint.h>
+
+#include "mozilla/EventForwards.h"
+
+#include "nsColor.h"
+#include "nsISelectionController.h"
+#include "nsITextInputProcessor.h"
+#include "nsStyleConsts.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+
+/******************************************************************************
+ * mozilla::TextRangeStyle
+ ******************************************************************************/
+
+struct TextRangeStyle
+{
+ enum
+ {
+ LINESTYLE_NONE = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
+ LINESTYLE_SOLID = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
+ LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
+ LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
+ LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
+ LINESTYLE_WAVY = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
+ };
+
+ enum
+ {
+ DEFINED_NONE = 0x00,
+ DEFINED_LINESTYLE = 0x01,
+ DEFINED_FOREGROUND_COLOR = 0x02,
+ DEFINED_BACKGROUND_COLOR = 0x04,
+ DEFINED_UNDERLINE_COLOR = 0x08
+ };
+
+ // Initialize all members, because TextRange instances may be compared by
+ // memcomp.
+ TextRangeStyle()
+ {
+ Clear();
+ }
+
+ void Clear()
+ {
+ mDefinedStyles = DEFINED_NONE;
+ mLineStyle = LINESTYLE_NONE;
+ mIsBoldLine = false;
+ mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
+ }
+
+ bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
+
+ bool IsLineStyleDefined() const
+ {
+ return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
+ }
+
+ bool IsForegroundColorDefined() const
+ {
+ return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
+ }
+
+ bool IsBackgroundColorDefined() const
+ {
+ return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
+ }
+
+ bool IsUnderlineColorDefined() const
+ {
+ return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
+ }
+
+ bool IsNoChangeStyle() const
+ {
+ return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
+ IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
+ }
+
+ bool Equals(const TextRangeStyle& aOther) const
+ {
+ if (mDefinedStyles != aOther.mDefinedStyles)
+ return false;
+ if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
+ !mIsBoldLine != !aOther.mIsBoldLine))
+ return false;
+ if (IsForegroundColorDefined() &&
+ (mForegroundColor != aOther.mForegroundColor))
+ return false;
+ if (IsBackgroundColorDefined() &&
+ (mBackgroundColor != aOther.mBackgroundColor))
+ return false;
+ if (IsUnderlineColorDefined() &&
+ (mUnderlineColor != aOther.mUnderlineColor))
+ return false;
+ return true;
+ }
+
+ bool operator !=(const TextRangeStyle &aOther) const
+ {
+ return !Equals(aOther);
+ }
+
+ bool operator ==(const TextRangeStyle &aOther) const
+ {
+ return Equals(aOther);
+ }
+
+ uint8_t mDefinedStyles;
+ uint8_t mLineStyle; // DEFINED_LINESTYLE
+
+ bool mIsBoldLine; // DEFINED_LINESTYLE
+
+ nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
+ nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
+ nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
+};
+
+/******************************************************************************
+ * mozilla::TextRange
+ ******************************************************************************/
+
+enum class TextRangeType : RawTextRangeType
+{
+ eUninitialized = 0x00,
+ eCaret = 0x01,
+ eRawClause = nsITextInputProcessor::ATTR_RAW_CLAUSE,
+ eSelectedRawClause = nsITextInputProcessor::ATTR_SELECTED_RAW_CLAUSE,
+ eConvertedClause = nsITextInputProcessor::ATTR_CONVERTED_CLAUSE,
+ eSelectedClause = nsITextInputProcessor::ATTR_SELECTED_CLAUSE
+};
+
+bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeValue);
+RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType);
+TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType);
+const char* ToChar(TextRangeType aTextRangeType);
+SelectionType ToSelectionType(TextRangeType aTextRangeType);
+
+inline RawSelectionType ToRawSelectionType(TextRangeType aTextRangeType)
+{
+ return ToRawSelectionType(ToSelectionType(aTextRangeType));
+}
+
+struct TextRange
+{
+ TextRange()
+ : mStartOffset(0)
+ , mEndOffset(0)
+ , mRangeType(TextRangeType::eUninitialized)
+ {
+ }
+
+ uint32_t mStartOffset;
+ // XXX Storing end offset makes the initializing code very complicated.
+ // We should replace it with mLength.
+ uint32_t mEndOffset;
+
+ TextRangeStyle mRangeStyle;
+
+ TextRangeType mRangeType;
+
+ uint32_t Length() const { return mEndOffset - mStartOffset; }
+
+ bool IsClause() const
+ {
+ return mRangeType != TextRangeType::eCaret;
+ }
+
+ bool Equals(const TextRange& aOther) const
+ {
+ return mStartOffset == aOther.mStartOffset &&
+ mEndOffset == aOther.mEndOffset &&
+ mRangeType == aOther.mRangeType &&
+ mRangeStyle == aOther.mRangeStyle;
+ }
+
+ void RemoveCharacter(uint32_t aOffset)
+ {
+ if (mStartOffset > aOffset) {
+ --mStartOffset;
+ --mEndOffset;
+ } else if (mEndOffset > aOffset) {
+ --mEndOffset;
+ }
+ }
+};
+
+/******************************************************************************
+ * mozilla::TextRangeArray
+ ******************************************************************************/
+class TextRangeArray final : public AutoTArray<TextRange, 10>
+{
+ friend class WidgetCompositionEvent;
+
+ ~TextRangeArray() {}
+
+ NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
+
+ const TextRange* GetTargetClause() const
+ {
+ for (uint32_t i = 0; i < Length(); ++i) {
+ const TextRange& range = ElementAt(i);
+ if (range.mRangeType == TextRangeType::eSelectedRawClause ||
+ range.mRangeType == TextRangeType::eSelectedClause) {
+ return &range;
+ }
+ }
+ return nullptr;
+ }
+
+ // Returns target clause offset. If there are selected clauses, this returns
+ // the first selected clause offset. Otherwise, 0.
+ uint32_t TargetClauseOffset() const
+ {
+ const TextRange* range = GetTargetClause();
+ return range ? range->mStartOffset : 0;
+ }
+
+ // Returns target clause length. If there are selected clauses, this returns
+ // the first selected clause length. Otherwise, UINT32_MAX.
+ uint32_t TargetClauseLength() const
+ {
+ const TextRange* range = GetTargetClause();
+ return range ? range->Length() : UINT32_MAX;
+ }
+
+public:
+ bool IsComposing() const
+ {
+ for (uint32_t i = 0; i < Length(); ++i) {
+ if (ElementAt(i).IsClause()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool Equals(const TextRangeArray& aOther) const
+ {
+ size_t len = Length();
+ if (len != aOther.Length()) {
+ return false;
+ }
+ for (size_t i = 0; i < len; i++) {
+ if (!ElementAt(i).Equals(aOther.ElementAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void RemoveCharacter(uint32_t aOffset)
+ {
+ for (size_t i = 0, len = Length(); i < len; i++) {
+ ElementAt(i).RemoveCharacter(aOffset);
+ }
+ }
+
+ bool HasCaret() const
+ {
+ for (const TextRange& range : *this) {
+ if (range.mRangeType == TextRangeType::eCaret) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool HasClauses() const
+ {
+ for (const TextRange& range : *this) {
+ if (range.IsClause()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ uint32_t GetCaretPosition() const
+ {
+ for (const TextRange& range : *this) {
+ if (range.mRangeType == TextRangeType::eCaret) {
+ return range.mStartOffset;
+ }
+ }
+ return UINT32_MAX;
+ }
+
+ const TextRange* GetFirstClause() const
+ {
+ for (const TextRange& range : *this) {
+ // Look for the range of a clause whose start offset is 0 because the
+ // first clause's start offset is always 0.
+ if (range.IsClause() && !range.mStartOffset) {
+ return &range;
+ }
+ }
+ MOZ_ASSERT(!HasClauses());
+ return nullptr;
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_TextRage_h_