LexAccessor.h 5.4 KB

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