| 1 | // Scintilla source code edit control |
|---|---|
| 2 | /** @file Accessor.cxx |
| 3 | ** Interfaces between Scintilla and lexers. |
| 4 | **/ |
| 5 | // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> |
| 6 | // The License.txt file describes the conditions under which this software may be distributed. |
| 7 | |
| 8 | #include <cstdlib> |
| 9 | #include <cassert> |
| 10 | |
| 11 | #include <string> |
| 12 | #include <string_view> |
| 13 | |
| 14 | #include "ILexer.h" |
| 15 | #include "Scintilla.h" |
| 16 | #include "SciLexer.h" |
| 17 | |
| 18 | #include "PropSetSimple.h" |
| 19 | #include "WordList.h" |
| 20 | #include "LexAccessor.h" |
| 21 | #include "Accessor.h" |
| 22 | |
| 23 | using namespace Lexilla; |
| 24 | |
| 25 | Accessor::Accessor(Scintilla::IDocument *pAccess_, PropSetSimple *pprops_) : LexAccessor(pAccess_), pprops(pprops_) { |
| 26 | } |
| 27 | |
| 28 | int Accessor::GetPropertyInt(std::string_view key, int defaultValue) const { |
| 29 | return pprops->GetInt(key, defaultValue); |
| 30 | } |
| 31 | |
| 32 | int Accessor::IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { |
| 33 | const Sci_Position end = Length(); |
| 34 | int spaceFlags = 0; |
| 35 | |
| 36 | // Determines the indentation level of the current line and also checks for consistent |
| 37 | // indentation compared to the previous line. |
| 38 | // Indentation is judged consistent when the indentation whitespace of each line lines |
| 39 | // the same or the indentation of one line is a prefix of the other. |
| 40 | |
| 41 | Sci_Position pos = LineStart(line); |
| 42 | char ch = (*this)[pos]; |
| 43 | int indent = 0; |
| 44 | bool inPrevPrefix = line > 0; |
| 45 | Sci_Position posPrev = inPrevPrefix ? LineStart(line-1) : 0; |
| 46 | while ((ch == ' ' || ch == '\t') && (pos < end)) { |
| 47 | if (inPrevPrefix) { |
| 48 | const char chPrev = (*this)[posPrev++]; |
| 49 | if (chPrev == ' ' || chPrev == '\t') { |
| 50 | if (chPrev != ch) |
| 51 | spaceFlags |= wsInconsistent; |
| 52 | } else { |
| 53 | inPrevPrefix = false; |
| 54 | } |
| 55 | } |
| 56 | if (ch == ' ') { |
| 57 | spaceFlags |= wsSpace; |
| 58 | indent++; |
| 59 | } else { // Tab |
| 60 | spaceFlags |= wsTab; |
| 61 | if (spaceFlags & wsSpace) |
| 62 | spaceFlags |= wsSpaceTab; |
| 63 | indent = (indent / 8 + 1) * 8; |
| 64 | } |
| 65 | ch = (*this)[++pos]; |
| 66 | } |
| 67 | |
| 68 | *flags = spaceFlags; |
| 69 | indent += SC_FOLDLEVELBASE; |
| 70 | // if completely empty line or the start of a comment... |
| 71 | if ((LineStart(line) == Length()) || (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') || |
| 72 | (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos))) |
| 73 | return indent | SC_FOLDLEVELWHITEFLAG; |
| 74 | else |
| 75 | return indent; |
| 76 | } |
| 77 |