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 
MakeLowerCase(int ch)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 &);
GetNextChar(unsigned int pos)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) :
styler(styler_)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 	}
Complete()75 	void Complete() {
76 		styler.ColourTo(currentPos - 1, state);
77 		styler.Flush();
78 	}
More()79 	bool More() const {
80 		return currentPos < endPos;
81 	}
Forward()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 	}
Forward(int nb)99 	void Forward(int nb) {
100 		for (int i = 0; i < nb; i++) {
101 			Forward();
102 		}
103 	}
ChangeState(int state_)104 	void ChangeState(int state_) {
105 		state = state_;
106 	}
SetState(int state_)107 	void SetState(int state_) {
108 		styler.ColourTo(currentPos - 1, state);
109 		state = state_;
110 	}
ForwardSetState(int state_)111 	void ForwardSetState(int state_) {
112 		Forward();
113 		styler.ColourTo(currentPos - 1, state);
114 		state = state_;
115 	}
LengthCurrent()116 	int LengthCurrent() {
117 		return currentPos - styler.GetStartSegment();
118 	}
GetRelative(int n)119 	int GetRelative(int n) {
120 		return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
121 	}
Match(char ch0)122 	bool Match(char ch0) const {
123 		return ch == static_cast<unsigned char>(ch0);
124 	}
Match(char ch0,char ch1)125 	bool Match(char ch0, char ch1) const {
126 		return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1));
127 	}
Match(const char * s)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 	}
MatchIgnoreCase(const char * s)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
169