1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_TypeInState_h 7 #define mozilla_TypeInState_h 8 9 #include "mozilla/EditorDOMPoint.h" 10 #include "mozilla/EventForwards.h" 11 #include "mozilla/UniquePtr.h" 12 #include "nsCOMPtr.h" 13 #include "nsCycleCollectionParticipant.h" 14 #include "nsGkAtoms.h" 15 #include "nsISupportsImpl.h" 16 #include "nsString.h" 17 #include "nsTArray.h" 18 #include "nscore.h" 19 20 // Workaround for windows headers 21 #ifdef SetProp 22 # undef SetProp 23 #endif 24 25 class nsAtom; 26 class nsINode; 27 28 namespace mozilla { 29 class HTMLEditor; 30 namespace dom { 31 class MouseEvent; 32 class Selection; 33 } // namespace dom 34 35 enum class SpecifiedStyle : uint8_t { Preserve, Discard }; 36 37 struct PropItem { 38 nsAtom* tag; 39 nsAtom* attr; 40 nsString value; 41 // Whether the class and style attribute should be perserved or discarded. 42 SpecifiedStyle specifiedStyle; 43 PropItemPropItem44 PropItem() 45 : tag(nullptr), attr(nullptr), specifiedStyle(SpecifiedStyle::Preserve) { 46 MOZ_COUNT_CTOR(PropItem); 47 } PropItemPropItem48 PropItem(nsAtom* aTag, nsAtom* aAttr, const nsAString& aValue) 49 : tag(aTag), 50 attr(aAttr != nsGkAtoms::_empty ? aAttr : nullptr), 51 value(aValue), 52 specifiedStyle(SpecifiedStyle::Preserve) { 53 MOZ_COUNT_CTOR(PropItem); 54 } 55 MOZ_COUNTED_DTOR(PropItem) 56 }; 57 58 class StyleCache final { 59 public: 60 StyleCache() = delete; StyleCache(nsStaticAtom * aTag,nsStaticAtom * aAttribute,const nsAString & aValue)61 StyleCache(nsStaticAtom* aTag, nsStaticAtom* aAttribute, 62 const nsAString& aValue) 63 : mTag(aTag), mAttribute(aAttribute), mValue(aValue) { 64 MOZ_ASSERT(mTag); 65 } 66 Tag()67 nsStaticAtom* Tag() const { return mTag; } GetAttribute()68 nsStaticAtom* GetAttribute() const { return mAttribute; } Value()69 const nsString& Value() const { return mValue; } 70 71 private: 72 nsStaticAtom* mTag; 73 nsStaticAtom* mAttribute; 74 nsString mValue; 75 }; 76 77 class MOZ_STACK_CLASS AutoStyleCacheArray final 78 : public AutoTArray<StyleCache, 21> { 79 public: IndexOf(const nsStaticAtom * aTag,const nsStaticAtom * aAttribute)80 index_type IndexOf(const nsStaticAtom* aTag, 81 const nsStaticAtom* aAttribute) const { 82 for (index_type index = 0; index < Length(); ++index) { 83 const StyleCache& styleCache = ElementAt(index); 84 if (styleCache.Tag() == aTag && styleCache.GetAttribute() == aAttribute) { 85 return index; 86 } 87 } 88 return NoIndex; 89 } 90 }; 91 92 class TypeInState final { 93 public: 94 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TypeInState) 95 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TypeInState) 96 97 TypeInState(); 98 void Reset(); 99 100 nsresult UpdateSelState(dom::Selection& aSelection); 101 102 /** 103 * PreHandleMouseEvent() is called when `HTMLEditorEventListener` receives 104 * "mousedown" and "mouseup" events. Note that `aMouseDownOrUpEvent` may not 105 * be acceptable event for the `HTMLEditor`, but this is called even in 106 * the case because the event may cause a following `OnSelectionChange()` 107 * call. 108 */ 109 void PreHandleMouseEvent(const dom::MouseEvent& aMouseDownOrUpEvent); 110 111 void PreHandleSelectionChangeCommand(Command aCommand); 112 void PostHandleSelectionChangeCommand(const HTMLEditor& aHTMLEditor, 113 Command aCommand); 114 115 void OnSelectionChange(const HTMLEditor& aHTMLEditor, int16_t aReason); 116 117 void SetProp(nsAtom* aProp, nsAtom* aAttr, const nsAString& aValue); 118 119 void ClearAllProps(); 120 void ClearProp(nsAtom* aProp, nsAtom* aAttr); 121 void ClearLinkPropAndDiscardItsSpecifiedStyle(); 122 123 /** 124 * TakeClearProperty() hands back next property item on the clear list. 125 * Caller assumes ownership of PropItem and must delete it. 126 */ 127 UniquePtr<PropItem> TakeClearProperty(); 128 129 /** 130 * TakeSetProperty() hands back next property item on the set list. 131 * Caller assumes ownership of PropItem and must delete it. 132 */ 133 UniquePtr<PropItem> TakeSetProperty(); 134 135 /** 136 * TakeRelativeFontSize() hands back relative font value, which is then 137 * cleared out. 138 */ 139 int32_t TakeRelativeFontSize(); 140 141 void GetTypingState(bool& isSet, bool& theSetting, nsAtom* aProp, 142 nsAtom* aAttr = nullptr, nsString* outValue = nullptr); 143 144 static bool FindPropInList(nsAtom* aProp, nsAtom* aAttr, nsAString* outValue, 145 const nsTArray<PropItem*>& aList, 146 int32_t& outIndex); 147 148 protected: 149 virtual ~TypeInState(); 150 151 void RemovePropFromSetList(nsAtom* aProp, nsAtom* aAttr); 152 void RemovePropFromClearedList(nsAtom* aProp, nsAtom* aAttr); 153 bool IsPropSet(nsAtom* aProp, nsAtom* aAttr, nsAString* outValue); 154 bool IsPropSet(nsAtom* aProp, nsAtom* aAttr, nsAString* outValue, 155 int32_t& outIndex); 156 bool IsPropCleared(nsAtom* aProp, nsAtom* aAttr); 157 bool IsPropCleared(nsAtom* aProp, nsAtom* aAttr, int32_t& outIndex); 158 IsLinkStyleSet()159 bool IsLinkStyleSet() const { 160 int32_t unusedIndex = -1; 161 return FindPropInList(nsGkAtoms::a, nullptr, nullptr, mSetArray, 162 unusedIndex); 163 } IsExplicitlyLinkStyleCleared()164 bool IsExplicitlyLinkStyleCleared() const { 165 int32_t unusedIndex = -1; 166 return FindPropInList(nsGkAtoms::a, nullptr, nullptr, mClearedArray, 167 unusedIndex); 168 } IsOnlyLinkStyleCleared()169 bool IsOnlyLinkStyleCleared() const { 170 return mClearedArray.Length() == 1 && IsExplicitlyLinkStyleCleared(); 171 } AreAllStylesCleared()172 bool AreAllStylesCleared() const { 173 int32_t unusedIndex = -1; 174 return FindPropInList(nullptr, nullptr, nullptr, mClearedArray, 175 unusedIndex); 176 } AreSomeStylesSet()177 bool AreSomeStylesSet() const { return !mSetArray.IsEmpty(); } AreSomeStylesCleared()178 bool AreSomeStylesCleared() const { return !mClearedArray.IsEmpty(); } 179 180 nsTArray<PropItem*> mSetArray; 181 nsTArray<PropItem*> mClearedArray; 182 EditorDOMPoint mLastSelectionPoint; 183 int32_t mRelativeFontSize; 184 Command mLastSelectionCommand; 185 bool mMouseDownFiredInLinkElement; 186 bool mMouseUpFiredInLinkElement; 187 }; 188 189 } // namespace mozilla 190 191 #endif // #ifndef mozilla_TypeInState_h 192