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