1 // Scintilla source code edit control 2 /** @file LexAccessor.h 3 ** Interfaces between Scintilla and lexers. 4 **/ 5 // Copyright 1998-2010 by Neil Hodgson <[email protected]> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #ifndef LEXACCESSOR_H 9 #define LEXACCESSOR_H 10 11 namespace Scintilla { 12 13 enum class EncodingType { eightBit, unicode, dbcs }; 14 15 class LexAccessor { 16 private: 17 IDocument *pAccess; 18 enum {extremePosition=0x7FFFFFFF}; 19 /** @a bufferSize is a trade off between time taken to copy the characters 20 * and retrieval overhead. 21 * @a slopSize positions the buffer before the desired position 22 * in case there is some backtracking. */ 23 enum {bufferSize=4000, slopSize=bufferSize/8}; 24 char buf[bufferSize+1]; 25 Sci_Position startPos; 26 Sci_Position endPos; 27 int codePage; 28 enum EncodingType encodingType; 29 Sci_Position lenDoc; 30 char styleBuf[bufferSize]; 31 Sci_Position validLen; 32 Sci_PositionU startSeg; 33 Sci_Position startPosStyling; 34 int documentVersion; 35 Fill(Sci_Position position)36 void Fill(Sci_Position position) { 37 startPos = position - slopSize; 38 if (startPos + bufferSize > lenDoc) 39 startPos = lenDoc - bufferSize; 40 if (startPos < 0) 41 startPos = 0; 42 endPos = startPos + bufferSize; 43 if (endPos > lenDoc) 44 endPos = lenDoc; 45 46 pAccess->GetCharRange(buf, startPos, endPos-startPos); 47 buf[endPos-startPos] = '\0'; 48 } 49 50 public: LexAccessor(IDocument * pAccess_)51 explicit LexAccessor(IDocument *pAccess_) : 52 pAccess(pAccess_), startPos(extremePosition), endPos(0), 53 codePage(pAccess->CodePage()), 54 encodingType(EncodingType::eightBit), 55 lenDoc(pAccess->Length()), 56 validLen(0), 57 startSeg(0), startPosStyling(0), 58 documentVersion(pAccess->Version()) { 59 // Prevent warnings by static analyzers about uninitialized buf and styleBuf. 60 buf[0] = 0; 61 styleBuf[0] = 0; 62 switch (codePage) { 63 case 65001: 64 encodingType = EncodingType::unicode; 65 break; 66 case 932: 67 case 936: 68 case 949: 69 case 950: 70 case 1361: 71 encodingType = EncodingType::dbcs; 72 } 73 } 74 char operator[](Sci_Position position) { 75 if (position < startPos || position >= endPos) { 76 Fill(position); 77 } 78 return buf[position - startPos]; 79 } MultiByteAccess()80 IDocument *MultiByteAccess() const noexcept { 81 return pAccess; 82 } 83 /** Safe version of operator[], returning a defined value for invalid position. */ 84 char SafeGetCharAt(Sci_Position position, char chDefault=' ') { 85 if (position < startPos || position >= endPos) { 86 Fill(position); 87 if (position < startPos || position >= endPos) { 88 // Position is outside range of document 89 return chDefault; 90 } 91 } 92 return buf[position - startPos]; 93 } IsLeadByte(char ch)94 bool IsLeadByte(char ch) const { 95 return pAccess->IsDBCSLeadByte(ch); 96 } Encoding()97 EncodingType Encoding() const noexcept { 98 return encodingType; 99 } Match(Sci_Position pos,const char * s)100 bool Match(Sci_Position pos, const char *s) { 101 for (int i=0; *s; i++) { 102 if (*s != SafeGetCharAt(pos+i)) 103 return false; 104 s++; 105 } 106 return true; 107 } StyleAt(Sci_Position position)108 char StyleAt(Sci_Position position) const { 109 return pAccess->StyleAt(position); 110 } GetLine(Sci_Position position)111 Sci_Position GetLine(Sci_Position position) const { 112 return pAccess->LineFromPosition(position); 113 } LineStart(Sci_Position line)114 Sci_Position LineStart(Sci_Position line) const { 115 return pAccess->LineStart(line); 116 } LineEnd(Sci_Position line)117 Sci_Position LineEnd(Sci_Position line) const { 118 return pAccess->LineEnd(line); 119 } LevelAt(Sci_Position line)120 int LevelAt(Sci_Position line) const { 121 return pAccess->GetLevel(line); 122 } Length()123 Sci_Position Length() const { 124 return lenDoc; 125 } Flush()126 void Flush() { 127 if (validLen > 0) { 128 pAccess->SetStyles(validLen, styleBuf); 129 startPosStyling += validLen; 130 validLen = 0; 131 } 132 } GetLineState(Sci_Position line)133 int GetLineState(Sci_Position line) const { 134 return pAccess->GetLineState(line); 135 } SetLineState(Sci_Position line,int state)136 int SetLineState(Sci_Position line, int state) { 137 return pAccess->SetLineState(line, state); 138 } 139 // Style setting StartAt(Sci_PositionU start)140 void StartAt(Sci_PositionU start) { 141 pAccess->StartStyling(start); 142 startPosStyling = start; 143 } GetStartSegment()144 Sci_PositionU GetStartSegment() const { 145 return startSeg; 146 } StartSegment(Sci_PositionU pos)147 void StartSegment(Sci_PositionU pos) { 148 startSeg = pos; 149 } ColourTo(Sci_PositionU pos,int chAttr)150 void ColourTo(Sci_PositionU pos, int chAttr) { 151 // Only perform styling if non empty range 152 if (pos != startSeg - 1) { 153 assert(pos >= startSeg); 154 if (pos < startSeg) { 155 return; 156 } 157 158 if (validLen + (pos - startSeg + 1) >= bufferSize) 159 Flush(); 160 const char attr = static_cast<char>(chAttr); 161 if (validLen + (pos - startSeg + 1) >= bufferSize) { 162 // Too big for buffer so send directly 163 pAccess->SetStyleFor(pos - startSeg + 1, attr); 164 } else { 165 for (Sci_PositionU i = startSeg; i <= pos; i++) { 166 assert((startPosStyling + validLen) < Length()); 167 styleBuf[validLen++] = attr; 168 } 169 } 170 } 171 startSeg = pos+1; 172 } SetLevel(Sci_Position line,int level)173 void SetLevel(Sci_Position line, int level) { 174 pAccess->SetLevel(line, level); 175 } IndicatorFill(Sci_Position start,Sci_Position end,int indicator,int value)176 void IndicatorFill(Sci_Position start, Sci_Position end, int indicator, int value) { 177 pAccess->DecorationSetCurrentIndicator(indicator); 178 pAccess->DecorationFillRange(start, value, end - start); 179 } 180 ChangeLexerState(Sci_Position start,Sci_Position end)181 void ChangeLexerState(Sci_Position start, Sci_Position end) { 182 pAccess->ChangeLexerState(start, end); 183 } 184 }; 185 186 struct LexicalClass { 187 int value; 188 const char *name; 189 const char *tags; 190 const char *description; 191 }; 192 193 } 194 195 #endif 196