]>
Commit | Line | Data |
---|---|---|
1 | // Scintilla source code edit control | |
2 | /** @file StyleContext.cxx | |
3 | ** Lexer infrastructure. | |
4 | **/ | |
5 | // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> | |
6 | // This file is in the public domain. | |
7 | ||
8 | #ifndef STYLECONTEXT_H | |
9 | #define STYLECONTEXT_H | |
10 | ||
11 | #ifdef SCI_NAMESPACE | |
12 | namespace Scintilla { | |
13 | #endif | |
14 | ||
15 | static inline int MakeLowerCase(int ch) { | |
16 | if (ch < 'A' || ch > 'Z') | |
17 | return ch; | |
18 | else | |
19 | return ch - 'A' + 'a'; | |
20 | } | |
21 | ||
22 | // All languages handled so far can treat all characters >= 0x80 as one class | |
23 | // which just continues the current token or starts an identifier if in default. | |
24 | // DBCS treated specially as the second character can be < 0x80 and hence | |
25 | // syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80 | |
26 | class StyleContext { | |
27 | LexAccessor &styler; | |
28 | unsigned int endPos; | |
29 | StyleContext &operator=(const StyleContext &); | |
30 | void GetNextChar(unsigned int pos) { | |
31 | chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1)); | |
32 | if (styler.IsLeadByte(static_cast<char>(chNext))) { | |
33 | chNext = chNext << 8; | |
34 | chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2)); | |
35 | } | |
36 | // End of line? | |
37 | // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) | |
38 | // or on LF alone (Unix). Avoid triggering two times on Dos/Win. | |
39 | atLineEnd = (ch == '\r' && chNext != '\n') || | |
40 | (ch == '\n') || | |
41 | (currentPos >= endPos); | |
42 | } | |
43 | ||
44 | public: | |
45 | unsigned int currentPos; | |
46 | bool atLineStart; | |
47 | bool atLineEnd; | |
48 | int state; | |
49 | int chPrev; | |
50 | int ch; | |
51 | int chNext; | |
52 | ||
53 | StyleContext(unsigned int startPos, unsigned int length, | |
54 | int initStyle, LexAccessor &styler_, char chMask=31) : | |
55 | styler(styler_), | |
56 | endPos(startPos + length), | |
57 | currentPos(startPos), | |
58 | atLineEnd(false), | |
59 | state(initStyle & chMask), // Mask off all bits which aren't in the chMask. | |
60 | chPrev(0), | |
61 | ch(0), | |
62 | chNext(0) { | |
63 | styler.StartAt(startPos, chMask); | |
64 | styler.StartSegment(startPos); | |
65 | atLineStart = static_cast<unsigned int>(styler.LineStart(styler.GetLine(startPos))) == startPos; | |
66 | unsigned int pos = currentPos; | |
67 | ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos)); | |
68 | if (styler.IsLeadByte(static_cast<char>(ch))) { | |
69 | pos++; | |
70 | ch = ch << 8; | |
71 | ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos)); | |
72 | } | |
73 | GetNextChar(pos); | |
74 | } | |
75 | void Complete() { | |
76 | styler.ColourTo(currentPos - 1, state); | |
77 | styler.Flush(); | |
78 | } | |
79 | bool More() const { | |
80 | return currentPos < endPos; | |
81 | } | |
82 | void Forward() { | |
83 | if (currentPos < endPos) { | |
84 | atLineStart = atLineEnd; | |
85 | chPrev = ch; | |
86 | currentPos++; | |
87 | if (ch >= 0x100) | |
88 | currentPos++; | |
89 | ch = chNext; | |
90 | GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0)); | |
91 | } else { | |
92 | atLineStart = false; | |
93 | chPrev = ' '; | |
94 | ch = ' '; | |
95 | chNext = ' '; | |
96 | atLineEnd = true; | |
97 | } | |
98 | } | |
99 | void Forward(int nb) { | |
100 | for (int i = 0; i < nb; i++) { | |
101 | Forward(); | |
102 | } | |
103 | } | |
104 | void ChangeState(int state_) { | |
105 | state = state_; | |
106 | } | |
107 | void SetState(int state_) { | |
108 | styler.ColourTo(currentPos - 1, state); | |
109 | state = state_; | |
110 | } | |
111 | void ForwardSetState(int state_) { | |
112 | Forward(); | |
113 | styler.ColourTo(currentPos - 1, state); | |
114 | state = state_; | |
115 | } | |
116 | int LengthCurrent() { | |
117 | return currentPos - styler.GetStartSegment(); | |
118 | } | |
119 | int GetRelative(int n) { | |
120 | return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n)); | |
121 | } | |
122 | bool Match(char ch0) const { | |
123 | return ch == static_cast<unsigned char>(ch0); | |
124 | } | |
125 | bool Match(char ch0, char ch1) const { | |
126 | return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1)); | |
127 | } | |
128 | bool Match(const char *s) { | |
129 | if (ch != static_cast<unsigned char>(*s)) | |
130 | return false; | |
131 | s++; | |
132 | if (!*s) | |
133 | return true; | |
134 | if (chNext != static_cast<unsigned char>(*s)) | |
135 | return false; | |
136 | s++; | |
137 | for (int n=2; *s; n++) { | |
138 | if (*s != styler.SafeGetCharAt(currentPos+n)) | |
139 | return false; | |
140 | s++; | |
141 | } | |
142 | return true; | |
143 | } | |
144 | bool MatchIgnoreCase(const char *s) { | |
145 | if (MakeLowerCase(ch) != static_cast<unsigned char>(*s)) | |
146 | return false; | |
147 | s++; | |
148 | if (MakeLowerCase(chNext) != static_cast<unsigned char>(*s)) | |
149 | return false; | |
150 | s++; | |
151 | for (int n=2; *s; n++) { | |
152 | if (static_cast<unsigned char>(*s) != | |
153 | MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n)))) | |
154 | return false; | |
155 | s++; | |
156 | } | |
157 | return true; | |
158 | } | |
159 | // Non-inline | |
160 | void GetCurrent(char *s, unsigned int len); | |
161 | void GetCurrentLowered(char *s, unsigned int len); | |
162 | }; | |
163 | ||
164 | #ifdef SCI_NAMESPACE | |
165 | } | |
166 | #endif | |
167 | ||
168 | #endif |