1 // Scintilla source code edit control 2 /** @file StyleContext.h 3 ** Lexer infrastructure. 4 **/ 5 // Copyright 1998-2004 by Neil Hodgson <[email protected]> 6 // This file is in the public domain. 7 8 #ifndef STYLECONTEXT_H 9 #define STYLECONTEXT_H 10 11 namespace Scintilla { 12 13 // All languages handled so far can treat all characters >= 0x80 as one class 14 // which just continues the current token or starts an identifier if in default. 15 // DBCS treated specially as the second character can be < 0x80 and hence 16 // syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80 17 class StyleContext { 18 LexAccessor &styler; 19 IDocument *multiByteAccess; 20 Sci_PositionU endPos; 21 Sci_PositionU lengthDocument; 22 23 // Used for optimizing GetRelativeCharacter 24 Sci_PositionU posRelative; 25 Sci_PositionU currentPosLastRelative; 26 Sci_Position offsetRelative; 27 GetNextChar()28 void GetNextChar() { 29 if (multiByteAccess) { 30 chNext = multiByteAccess->GetCharacterAndWidth(currentPos+width, &widthNext); 31 } else { 32 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+width, 0)); 33 widthNext = 1; 34 } 35 // End of line determined from line end position, allowing CR, LF, 36 // CRLF and Unicode line ends as set by document. 37 if (currentLine < lineDocEnd) 38 atLineEnd = static_cast<Sci_Position>(currentPos) >= (lineStartNext-1); 39 else // Last line 40 atLineEnd = static_cast<Sci_Position>(currentPos) >= lineStartNext; 41 } 42 43 public: 44 Sci_PositionU currentPos; 45 Sci_Position currentLine; 46 Sci_Position lineDocEnd; 47 Sci_Position lineStartNext; 48 bool atLineStart; 49 bool atLineEnd; 50 int state; 51 int chPrev; 52 int ch; 53 Sci_Position width; 54 int chNext; 55 Sci_Position widthNext; 56 57 StyleContext(Sci_PositionU startPos, Sci_PositionU length, 58 int initStyle, LexAccessor &styler_, char chMask='\377') : styler(styler_)59 styler(styler_), 60 multiByteAccess(nullptr), 61 endPos(startPos + length), 62 posRelative(0), 63 currentPosLastRelative(0x7FFFFFFF), 64 offsetRelative(0), 65 currentPos(startPos), 66 currentLine(-1), 67 lineStartNext(-1), 68 atLineEnd(false), 69 state(initStyle & chMask), // Mask off all bits which aren't in the chMask. 70 chPrev(0), 71 ch(0), 72 width(0), 73 chNext(0), 74 widthNext(1) { 75 if (styler.Encoding() != EncodingType::eightBit) { 76 multiByteAccess = styler.MultiByteAccess(); 77 } 78 styler.StartAt(startPos /*, chMask*/); 79 styler.StartSegment(startPos); 80 currentLine = styler.GetLine(startPos); 81 lineStartNext = styler.LineStart(currentLine+1); 82 lengthDocument = static_cast<Sci_PositionU>(styler.Length()); 83 if (endPos == lengthDocument) 84 endPos++; 85 lineDocEnd = styler.GetLine(lengthDocument); 86 atLineStart = static_cast<Sci_PositionU>(styler.LineStart(currentLine)) == startPos; 87 88 // Variable width is now 0 so GetNextChar gets the char at currentPos into chNext/widthNext 89 width = 0; 90 GetNextChar(); 91 ch = chNext; 92 width = widthNext; 93 94 GetNextChar(); 95 } 96 // Deleted so StyleContext objects can not be copied. 97 StyleContext(const StyleContext &) = delete; 98 StyleContext &operator=(const StyleContext &) = delete; Complete()99 void Complete() { 100 styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); 101 styler.Flush(); 102 } More()103 bool More() const noexcept { 104 return currentPos < endPos; 105 } Forward()106 void Forward() { 107 if (currentPos < endPos) { 108 atLineStart = atLineEnd; 109 if (atLineStart) { 110 currentLine++; 111 lineStartNext = styler.LineStart(currentLine+1); 112 } 113 chPrev = ch; 114 currentPos += width; 115 ch = chNext; 116 width = widthNext; 117 GetNextChar(); 118 } else { 119 atLineStart = false; 120 chPrev = ' '; 121 ch = ' '; 122 chNext = ' '; 123 atLineEnd = true; 124 } 125 } Forward(Sci_Position nb)126 void Forward(Sci_Position nb) { 127 for (Sci_Position i = 0; i < nb; i++) { 128 Forward(); 129 } 130 } ForwardBytes(Sci_Position nb)131 void ForwardBytes(Sci_Position nb) { 132 const Sci_PositionU forwardPos = currentPos + nb; 133 while (forwardPos > currentPos) { 134 const Sci_PositionU currentPosStart = currentPos; 135 Forward(); 136 if (currentPos == currentPosStart) { 137 // Reached end 138 return; 139 } 140 } 141 } ChangeState(int state_)142 void ChangeState(int state_) noexcept { 143 state = state_; 144 } SetState(int state_)145 void SetState(int state_) { 146 styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); 147 state = state_; 148 } ForwardSetState(int state_)149 void ForwardSetState(int state_) { 150 Forward(); 151 styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); 152 state = state_; 153 } LengthCurrent()154 Sci_Position LengthCurrent() const { 155 return currentPos - styler.GetStartSegment(); 156 } 157 int GetRelative(Sci_Position n, char chDefault='\0') { 158 return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, chDefault)); 159 } GetRelativeCharacter(Sci_Position n)160 int GetRelativeCharacter(Sci_Position n) { 161 if (n == 0) 162 return ch; 163 if (multiByteAccess) { 164 if ((currentPosLastRelative != currentPos) || 165 ((n > 0) && ((offsetRelative < 0) || (n < offsetRelative))) || 166 ((n < 0) && ((offsetRelative > 0) || (n > offsetRelative)))) { 167 posRelative = currentPos; 168 offsetRelative = 0; 169 } 170 const Sci_Position diffRelative = n - offsetRelative; 171 const Sci_Position posNew = multiByteAccess->GetRelativePosition(posRelative, diffRelative); 172 const int chReturn = multiByteAccess->GetCharacterAndWidth(posNew, nullptr); 173 posRelative = posNew; 174 currentPosLastRelative = currentPos; 175 offsetRelative = n; 176 return chReturn; 177 } else { 178 // fast version for single byte encodings 179 return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos + n, 0)); 180 } 181 } Match(char ch0)182 bool Match(char ch0) const { 183 return ch == static_cast<unsigned char>(ch0); 184 } Match(char ch0,char ch1)185 bool Match(char ch0, char ch1) const { 186 return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1)); 187 } Match(const char * s)188 bool Match(const char *s) { 189 if (ch != static_cast<unsigned char>(*s)) 190 return false; 191 s++; 192 if (!*s) 193 return true; 194 if (chNext != static_cast<unsigned char>(*s)) 195 return false; 196 s++; 197 for (int n=2; *s; n++) { 198 if (*s != styler.SafeGetCharAt(currentPos+n, 0)) 199 return false; 200 s++; 201 } 202 return true; 203 } 204 // Non-inline 205 bool MatchIgnoreCase(const char *s); 206 void GetCurrent(char *s, Sci_PositionU len); 207 void GetCurrentLowered(char *s, Sci_PositionU len); 208 }; 209 210 } 211 212 #endif 213