1/*
2 * This file is part of the DOM implementation for WebCore.
3 *
4 * Copyright (C) 2006 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef DocumentMarker_h
24#define DocumentMarker_h
25
26#include <wtf/Forward.h>
27#include <wtf/RefCounted.h>
28#include <wtf/RefPtr.h>
29#include <wtf/text/WTFString.h>
30
31namespace WebCore {
32
33class DocumentMarkerDetails;
34
35// A range of a node within a document that is "marked", such as the range of a misspelled word.
36// It optionally includes a description that could be displayed in the user interface.
37// It also optionally includes a flag specifying whether the match is active, which is ignored
38// for all types other than type TextMatch.
39class DocumentMarker {
40public:
41    enum MarkerType {
42        Spelling = 1 << 0,
43        Grammar = 1 << 1,
44        TextMatch = 1 << 2,
45        // Text has been modified by spell correction, reversion of spell correction or other type of substitution.
46        // On some platforms, this prevents the text from being autocorrected again. On post Snow Leopard Mac OS X,
47        // if a Replacement marker contains non-empty description, a reversion UI will be shown.
48        Replacement = 1 << 3,
49        // Renderer needs to add underline indicating that the text has been modified by spell
50        // correction. Text with Replacement marker doesn't necessarily has CorrectionIndicator
51        // marker. For instance, after some text has been corrected, it will have both Replacement
52        // and CorrectionIndicator. However, if user further modifies such text, we would remove
53        // CorrectionIndicator marker, but retain Replacement marker.
54        CorrectionIndicator = 1 << 4,
55        // Correction suggestion has been offered, but got rejected by user.
56        RejectedCorrection = 1 << 5,
57        // Text has been modified by autocorrection. The description of this marker is the original text before autocorrection.
58        Autocorrected = 1 << 6,
59        // On some platforms, this prevents the text from being spellchecked again.
60        SpellCheckingExemption = 1 << 7,
61        // This marker indicates user has deleted an autocorrection starting at the end of the
62        // range that bears this marker. In some platforms, if the user later inserts the same original
63        // word again at this position, it will not be autocorrected again. The description of this
64        // marker is the original word before autocorrection was applied.
65        DeletedAutocorrection = 1 << 8,
66        // This marker indicates that the range of text spanned by the marker is entered by voice dictation,
67        // and it has alternative text.
68        DictationAlternatives = 1 << 9
69    };
70
71    class MarkerTypes {
72    public:
73        // The constructor is intentionally implicit to allow conversion from the bit-wise sum of above types
74        MarkerTypes(unsigned mask) : m_mask(mask) { }
75
76        bool contains(MarkerType type) const { return m_mask & type; }
77        bool intersects(const MarkerTypes& types) const { return (m_mask & types.m_mask); }
78        bool operator==(const MarkerTypes& other) const { return m_mask == other.m_mask; }
79
80        void add(const MarkerTypes& types) { m_mask |= types.m_mask; }
81        void remove(const MarkerTypes& types) { m_mask &= ~types.m_mask; }
82
83    private:
84        unsigned m_mask;
85    };
86
87    class AllMarkers : public MarkerTypes {
88    public:
89        AllMarkers()
90            : MarkerTypes(Spelling | Grammar | TextMatch | Replacement | CorrectionIndicator | RejectedCorrection | Autocorrected | SpellCheckingExemption | DeletedAutocorrection | DictationAlternatives)
91        {
92        }
93    };
94
95    DocumentMarker();
96    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset);
97    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset, const String& description);
98    DocumentMarker(unsigned startOffset, unsigned endOffset, bool activeMatch);
99    DocumentMarker(MarkerType, unsigned startOffset, unsigned endOffset, PassRefPtr<DocumentMarkerDetails>);
100
101    MarkerType type() const { return m_type; }
102    unsigned startOffset() const { return m_startOffset; }
103    unsigned endOffset() const { return m_endOffset; }
104
105    const String& description() const;
106    bool activeMatch() const;
107    DocumentMarkerDetails* details() const;
108
109    void setActiveMatch(bool);
110    void clearDetails() { m_details.clear(); }
111
112    // Offset modifications are done by DocumentMarkerController.
113    // Other classes should not call following setters.
114    void setStartOffset(unsigned offset) { m_startOffset = offset; }
115    void setEndOffset(unsigned offset) { m_endOffset = offset; }
116    void shiftOffsets(int delta);
117
118    bool operator==(const DocumentMarker& o) const
119    {
120        return type() == o.type() && startOffset() == o.startOffset() && endOffset() == o.endOffset();
121    }
122
123    bool operator!=(const DocumentMarker& o) const
124    {
125        return !(*this == o);
126    }
127
128private:
129    MarkerType m_type;
130    unsigned m_startOffset;
131    unsigned m_endOffset;
132    RefPtr<DocumentMarkerDetails> m_details;
133};
134
135inline DocumentMarkerDetails* DocumentMarker::details() const
136{
137    return m_details.get();
138}
139
140class DocumentMarkerDetails : public RefCounted<DocumentMarkerDetails>
141{
142public:
143    DocumentMarkerDetails() { }
144    virtual ~DocumentMarkerDetails();
145    virtual bool isDescription() const { return false; }
146    virtual bool isTextMatch() const { return false; }
147};
148
149} // namespace WebCore
150
151#endif // DocumentMarker_h
152