1
// Scintilla source code edit control
2
/** @file LexFlagShip.cxx
4
** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.)
6
// Copyright 2005 by Randy Butler
7
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
8
// The License.txt file describes the conditions under which this software may be distributed.
20
#include "StyleContext.h"
22
#include "Scintilla.h"
25
static bool IsFlagShipComment(Accessor &styler, int pos, int len) {
26
return len>0 && styler[pos]=='\'';
29
static inline bool IsTypeCharacter(int ch) {
30
return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
33
// Extended to accept accented characters
34
static inline bool IsAWordChar(int ch) {
36
(isalnum(ch) || ch == '.' || ch == '_');
39
static inline bool IsAWordStart(int ch) {
41
(isalnum(ch) || ch == '_');
44
static inline bool IsADateCharacter(const int ch) {
46
(isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
50
static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,
51
WordList *keywordlists[], Accessor &styler) {
53
//bool FSScriptSyntax = true;
54
WordList &keywords = *keywordlists[0];
55
WordList &keywords2 = *keywordlists[1];
56
WordList &keywords3 = *keywordlists[2];
57
WordList &keywords4 = *keywordlists[3];
59
styler.StartAt(startPos);
63
StyleContext sc(startPos, length, initStyle, styler);
65
for (; sc.More(); sc.Forward()) {
67
if (sc.state == SCE_FS_OPERATOR) {
68
sc.SetState(SCE_FS_DEFAULT);
69
} else if (sc.state == SCE_FS_IDENTIFIER) {
70
if (!IsAWordChar(sc.ch)) {
72
sc.GetCurrentLowered(s, sizeof(s));
73
if (keywords.InList(s)) {
74
sc.ChangeState(SCE_FS_KEYWORD);
75
} else if (keywords2.InList(s)) {
76
sc.ChangeState(SCE_FS_KEYWORD2);
77
} else if (keywords3.InList(s)) {
78
sc.ChangeState(SCE_FS_KEYWORD3);
79
} else if (keywords4.InList(s)) {
80
sc.ChangeState(SCE_FS_KEYWORD4);
81
}// Else, it is really an identifier...
82
sc.SetState(SCE_FS_DEFAULT);
84
} else if (sc.state == SCE_FS_NUMBER) {
85
if (!IsAWordChar(sc.ch)) {
86
sc.SetState(SCE_FS_DEFAULT);
88
} else if (sc.state == SCE_FS_STRING) {
89
// VB doubles quotes to preserve them, so just end this string
90
// state now as a following quote will start again
92
if (tolower(sc.chNext) == 'c') {
95
sc.ForwardSetState(SCE_FS_DEFAULT);
96
} else if (sc.atLineEnd) {
97
sc.ChangeState(SCE_FS_STRINGEOL);
98
sc.ForwardSetState(SCE_FS_DEFAULT);
100
} else if (sc.state == SCE_FS_COMMENT) {
101
if (sc.Match('*', '/')) { // new code
103
sc.ForwardSetState(SCE_FS_DEFAULT);
104
//if (sc.atLineEnd) { // old code
105
// sc.SetState(SCE_FS_DEFAULT);
107
} else if (sc.state == SCE_FS_COMMENTLINE) { //new code
108
if (sc.ch == '\r' || sc.ch == '\n') {
109
sc.SetState(SCE_FS_DEFAULT);
112
} else if (sc.state == SCE_FS_PREPROCESSOR) {
114
sc.SetState(SCE_FS_DEFAULT);
116
} else if (sc.state == SCE_FS_DATE) {
117
if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
118
sc.ForwardSetState(SCE_FS_DEFAULT);
122
// Determine if a new state should be entered.
123
if (sc.state == SCE_FS_DEFAULT) {
124
if (sc.Match('/', '*')) { // New code
125
sc.SetState(SCE_FS_COMMENT);
126
sc.Forward(); // Eat the * so it isn't used for the end of the comment
127
//if (sc.ch == '\'') { // Old code
128
// sc.SetState(SCE_FS_COMMENT); // old code
129
} else if (sc.Match('/', '/')) { // New code
130
sc.SetState(SCE_FS_COMMENTLINE);
131
} else if (sc.ch == '\"') {
132
sc.SetState(SCE_FS_STRING);
133
} else if (sc.ch == '#' && visibleChars == 0) {
134
// Preprocessor commands are alone on their line
135
sc.SetState(SCE_FS_PREPROCESSOR);
136
} else if (sc.ch == '#') {
139
while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
140
chSeek = sc.GetRelative(n);
143
if (IsADigit(chSeek)) {
144
sc.SetState(SCE_FS_DATE);
146
sc.SetState(SCE_FS_OPERATOR);
148
} else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
149
sc.SetState(SCE_FS_NUMBER);
150
} else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
151
sc.SetState(SCE_FS_NUMBER);
152
} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
153
sc.SetState(SCE_FS_NUMBER);
154
} else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
155
sc.SetState(SCE_FS_IDENTIFIER);
156
} else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
157
sc.SetState(SCE_FS_OPERATOR);
164
if (!IsASpace(sc.ch)) {
171
static void FoldFlagShipDoc(unsigned int startPos, int length, int,
172
WordList *[], Accessor &styler) {
174
int endPos = startPos + length;
176
// Backtrack to previous line in case need to fix its fold status
177
int lineCurrent = styler.GetLine(startPos);
179
if (lineCurrent > 0) {
181
startPos = styler.LineStart(lineCurrent);
185
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment);
186
char chNext = styler[startPos];
187
for (int i = startPos; i < endPos; i++) {
189
chNext = styler.SafeGetCharAt(i + 1);
191
if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
192
int lev = indentCurrent;
193
int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment);
194
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
195
// Only non whitespace lines can be headers
196
if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
197
lev |= SC_FOLDLEVELHEADERFLAG;
198
} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
199
// Line after is blank so check the next - maybe should continue further?
201
int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment);
202
if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
203
lev |= SC_FOLDLEVELHEADERFLAG;
207
indentCurrent = indentNext;
208
styler.SetLevel(lineCurrent, lev);
215
static const char * const FSWordListDesc[] = {
223
LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);