Add an UI to enable/disable specific overlay handlers.
[TortoiseGit.git] / ext / scintilla / src / LexR.cxx
blob1d10af97f133862d465b74ade88ac3537fd3fe20
1 // Scintilla source code edit control
2 /** @file Lexr.cxx
3 ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer).
4 **
5 **/
6 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
15 #include "Platform.h"
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
28 static inline bool IsAWordChar(const int ch) {
29 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
32 static inline bool IsAWordStart(const int ch) {
33 return (ch < 0x80) && (isalnum(ch) || ch == '_');
36 static inline bool IsAnOperator(const int ch) {
37 if (isascii(ch) && isalnum(ch))
38 return false;
39 // '.' left out as it is used to make up numbers
40 if (ch == '-' || ch == '+' || ch == '!' || ch == '~' ||
41 ch == '?' || ch == ':' || ch == '*' || ch == '/' ||
42 ch == '^' || ch == '<' || ch == '>' || ch == '=' ||
43 ch == '&' || ch == '|' || ch == '$' || ch == '(' ||
44 ch == ')' || ch == '}' || ch == '{' || ch == '[' ||
45 ch == ']')
46 return true;
47 return false;
50 static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
51 Accessor &styler) {
53 WordList &keywords = *keywordlists[0];
54 WordList &keywords2 = *keywordlists[1];
55 WordList &keywords3 = *keywordlists[2];
58 // Do not leak onto next line
59 if (initStyle == SCE_R_INFIXEOL)
60 initStyle = SCE_R_DEFAULT;
63 StyleContext sc(startPos, length, initStyle, styler);
65 for (; sc.More(); sc.Forward()) {
67 if (sc.atLineStart && (sc.state == SCE_R_STRING)) {
68 // Prevent SCE_R_STRINGEOL from leaking back to previous line
69 sc.SetState(SCE_R_STRING);
72 // Determine if the current state should terminate.
73 if (sc.state == SCE_R_OPERATOR) {
74 sc.SetState(SCE_R_DEFAULT);
75 } else if (sc.state == SCE_R_NUMBER) {
76 if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
77 sc.SetState(SCE_R_DEFAULT);
79 } else if (sc.state == SCE_R_IDENTIFIER) {
80 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
81 char s[100];
82 sc.GetCurrentLowered(s, sizeof(s));
83 if (keywords.InList(s)) {
84 sc.ChangeState(SCE_R_KWORD);
85 } else if (keywords2.InList(s)) {
86 sc.ChangeState(SCE_R_BASEKWORD);
87 } else if (keywords3.InList(s)) {
88 sc.ChangeState(SCE_R_OTHERKWORD);
90 sc.SetState(SCE_R_DEFAULT);
92 } else if (sc.state == SCE_R_COMMENT) {
93 if (sc.ch == '\r' || sc.ch == '\n') {
94 sc.SetState(SCE_R_DEFAULT);
96 } else if (sc.state == SCE_R_STRING) {
97 if (sc.ch == '\\') {
98 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
99 sc.Forward();
101 } else if (sc.ch == '\"') {
102 sc.ForwardSetState(SCE_R_DEFAULT);
104 } else if (sc.state == SCE_R_INFIX) {
105 if (sc.ch == '%') {
106 sc.ForwardSetState(SCE_R_DEFAULT);
107 } else if (sc.atLineEnd) {
108 sc.ChangeState(SCE_R_INFIXEOL);
109 sc.ForwardSetState(SCE_R_DEFAULT);
111 }else if (sc.state == SCE_R_STRING2) {
112 if (sc.ch == '\\') {
113 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
114 sc.Forward();
116 } else if (sc.ch == '\'') {
117 sc.ForwardSetState(SCE_R_DEFAULT);
121 // Determine if a new state should be entered.
122 if (sc.state == SCE_R_DEFAULT) {
123 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
124 sc.SetState(SCE_R_NUMBER);
125 } else if (IsAWordStart(sc.ch) ) {
126 sc.SetState(SCE_R_IDENTIFIER);
127 } else if (sc.Match('#')) {
128 sc.SetState(SCE_R_COMMENT);
129 } else if (sc.ch == '\"') {
130 sc.SetState(SCE_R_STRING);
131 } else if (sc.ch == '%') {
132 sc.SetState(SCE_R_INFIX);
133 } else if (sc.ch == '\'') {
134 sc.SetState(SCE_R_STRING2);
135 } else if (IsAnOperator(sc.ch)) {
136 sc.SetState(SCE_R_OPERATOR);
140 sc.Complete();
143 // Store both the current line's fold level and the next lines in the
144 // level store to make it easy to pick up with each increment
145 // and to make it possible to fiddle the current level for "} else {".
146 static void FoldRDoc(unsigned int startPos, int length, int, WordList *[],
147 Accessor &styler) {
148 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
149 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
150 unsigned int endPos = startPos + length;
151 int visibleChars = 0;
152 int lineCurrent = styler.GetLine(startPos);
153 int levelCurrent = SC_FOLDLEVELBASE;
154 if (lineCurrent > 0)
155 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
156 int levelMinCurrent = levelCurrent;
157 int levelNext = levelCurrent;
158 char chNext = styler[startPos];
159 int styleNext = styler.StyleAt(startPos);
160 for (unsigned int i = startPos; i < endPos; i++) {
161 char ch = chNext;
162 chNext = styler.SafeGetCharAt(i + 1);
163 int style = styleNext;
164 styleNext = styler.StyleAt(i + 1);
165 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
166 if (style == SCE_R_OPERATOR) {
167 if (ch == '{') {
168 // Measure the minimum before a '{' to allow
169 // folding on "} else {"
170 if (levelMinCurrent > levelNext) {
171 levelMinCurrent = levelNext;
173 levelNext++;
174 } else if (ch == '}') {
175 levelNext--;
178 if (atEOL) {
179 int levelUse = levelCurrent;
180 if (foldAtElse) {
181 levelUse = levelMinCurrent;
183 int lev = levelUse | levelNext << 16;
184 if (visibleChars == 0 && foldCompact)
185 lev |= SC_FOLDLEVELWHITEFLAG;
186 if (levelUse < levelNext)
187 lev |= SC_FOLDLEVELHEADERFLAG;
188 if (lev != styler.LevelAt(lineCurrent)) {
189 styler.SetLevel(lineCurrent, lev);
191 lineCurrent++;
192 levelCurrent = levelNext;
193 levelMinCurrent = levelCurrent;
194 visibleChars = 0;
196 if (!isspacechar(ch))
197 visibleChars++;
202 static const char * const RWordLists[] = {
203 "Language Keywords",
204 "Base / Default package function",
205 "Other Package Functions",
206 "Unused",
207 "Unused",
213 LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists);