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