diff options
author | Neil <nyamatongwe@gmail.com> | 2015-07-14 13:54:44 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2015-07-14 13:54:44 +1000 |
commit | e3190204cd27ddd4e09306090c5cf873a4db3c68 (patch) | |
tree | 143e53d52a3806a3c5be4b01d69fa808be0b212d | |
parent | e85ed0e10fd79847e406f8552b00f2d6af7ac06c (diff) | |
download | scintilla-mirror-e3190204cd27ddd4e09306090c5cf873a4db3c68.tar.gz |
Split LexOthers.cxx into separate files for each lexer: LexBatch, LexDiff,
LexErrorList, LexMake, LexNull, and LexProps.
-rw-r--r-- | cppcheck.suppress | 2 | ||||
-rw-r--r-- | lexers/LexBatch.cxx | 500 | ||||
-rw-r--r-- | lexers/LexDiff.cxx | 153 | ||||
-rw-r--r-- | lexers/LexErrorList.cxx | 308 | ||||
-rw-r--r-- | lexers/LexMake.cxx | 144 | ||||
-rw-r--r-- | lexers/LexNull.cxx | 40 | ||||
-rw-r--r-- | lexers/LexOthers.cxx | 1149 | ||||
-rw-r--r-- | lexers/LexProps.cxx | 189 | ||||
-rw-r--r-- | win32/scintilla.mak | 21 |
9 files changed, 1353 insertions, 1153 deletions
diff --git a/cppcheck.suppress b/cppcheck.suppress index 1be18206a..aea0ad98f 100644 --- a/cppcheck.suppress +++ b/cppcheck.suppress @@ -17,6 +17,7 @@ useInitializationList:scintilla/lexers/LexAsm.cxx useInitializationList:scintilla/lexers/LexBasic.cxx
noCopyConstructor:scintilla/lexers/LexBash.cxx
variableScope:scintilla/lexers/LexBash.cxx
+variableScope:scintilla/lexers/LexBatch.cxx
variableScope:scintilla/lexers/LexCmake.cxx
variableScope:scintilla/lexers/LexCSS.cxx
useInitializationList:scintilla/lexers/LexD.cxx
@@ -29,7 +30,6 @@ variableScope:scintilla/lexers/LexModula.cxx variableScope:scintilla/lexers/LexNimrod.cxx
variableScope:scintilla/lexers/LexNsis.cxx
variableScope:scintilla/lexers/LexOpal.cxx
-variableScope:scintilla/lexers/LexOthers.cxx
variableScope:scintilla/lexers/LexPB.cxx
noCopyConstructor:scintilla/lexers/LexPerl.cxx
variableScope:scintilla/lexers/LexRuby.cxx
diff --git a/lexers/LexBatch.cxx b/lexers/LexBatch.cxx new file mode 100644 index 000000000..04448b04a --- /dev/null +++ b/lexers/LexBatch.cxx @@ -0,0 +1,500 @@ +// Scintilla source code edit control +/** @file LexBatch.cxx + ** Lexer for batch files. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool Is0To9(char ch) { + return (ch >= '0') && (ch <= '9'); +} + +static bool IsAlphabetic(int ch) { + return IsASCII(ch) && isalpha(ch); +} + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +// Tests for BATCH Operators +static bool IsBOperator(char ch) { + return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || + (ch == '|') || (ch == '?') || (ch == '*'); +} + +// Tests for BATCH Separators +static bool IsBSeparator(char ch) { + return (ch == '\\') || (ch == '.') || (ch == ';') || + (ch == '\"') || (ch == '\'') || (ch == '/'); +} + +static void ColouriseBatchLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + WordList *keywordlists[], + Accessor &styler) { + + unsigned int offset = 0; // Line Buffer Offset + unsigned int cmdLoc; // External Command / Program Location + char wordBuffer[81]; // Word Buffer - large to catch long paths + unsigned int wbl; // Word Buffer Length + unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length + WordList &keywords = *keywordlists[0]; // Internal Commands + WordList &keywords2 = *keywordlists[1]; // External Commands (optional) + + // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords + // Toggling Regular Keyword Checking off improves readability + // Other Regular Keywords and External Commands / Programs might also benefit from toggling + // Need a more robust algorithm to properly toggle Regular Keyword Checking + bool continueProcessing = true; // Used to toggle Regular Keyword Checking + // Special Keywords are those that allow certain characters without whitespace after the command + // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= + // Special Keyword Buffer used to determine if the first n characters is a Keyword + char sKeywordBuffer[10]; // Special Keyword Buffer + bool sKeywordFound; // Exit Special Keyword for-loop if found + + // Skip initial spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + // Set External Command / Program Location + cmdLoc = offset; + + // Check for Fake Label (Comment) or Real Label - return if found + if (lineBuffer[offset] == ':') { + if (lineBuffer[offset + 1] == ':') { + // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm + styler.ColourTo(endPos, SCE_BAT_COMMENT); + } else { + // Colorize Real Label + styler.ColourTo(endPos, SCE_BAT_LABEL); + } + return; + // Check for Drive Change (Drive Change is internal command) - return if found + } else if ((IsAlphabetic(lineBuffer[offset])) && + (lineBuffer[offset + 1] == ':') && + ((isspacechar(lineBuffer[offset + 2])) || + (((lineBuffer[offset + 2] == '\\')) && + (isspacechar(lineBuffer[offset + 3]))))) { + // Colorize Regular Keyword + styler.ColourTo(endPos, SCE_BAT_WORD); + return; + } + + // Check for Hide Command (@ECHO OFF/ON) + if (lineBuffer[offset] == '@') { + styler.ColourTo(startLine + offset, SCE_BAT_HIDE); + offset++; + } + // Skip next spaces + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + + // Read remainder of line word-at-a-time or remainder-of-word-at-a-time + while (offset < lengthLine) { + if (offset > startLine) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Copy word from Line Buffer into Word Buffer + wbl = 0; + for (; offset < lengthLine && wbl < 80 && + !isspacechar(lineBuffer[offset]); wbl++, offset++) { + wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); + } + wordBuffer[wbl] = '\0'; + wbo = 0; + + // Check for Comment - return if found + if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { + styler.ColourTo(endPos, SCE_BAT_COMMENT); + return; + } + // Check for Separator + if (IsBSeparator(wordBuffer[0])) { + // Check for External Command / Program + if ((cmdLoc == offset - wbl) && + ((wordBuffer[0] == ':') || + (wordBuffer[0] == '\\') || + (wordBuffer[0] == '.'))) { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Reset External Command / Program Location + cmdLoc = offset; + } else { + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // Check for Regular Keyword in list + } else if ((keywords.InList(wordBuffer)) && + (continueProcessing)) { + // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking + if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || + (CompareCaseInsensitive(wordBuffer, "goto") == 0) || + (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || + (CompareCaseInsensitive(wordBuffer, "set") == 0)) { + continueProcessing = false; + } + // Identify External Command / Program Location for ERRORLEVEL, and EXIST + if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || + (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip comparison + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH + } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || + (CompareCaseInsensitive(wordBuffer, "do") == 0) || + (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || + (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + // Colorize Regular keyword + styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); + // No need to Reset Offset + // Check for Special Keyword in list, External Command / Program, or Default Text + } else if ((wordBuffer[0] != '%') && + (wordBuffer[0] != '!') && + (!IsBOperator(wordBuffer[0])) && + (continueProcessing)) { + // Check for Special Keyword + // Affected Commands are in Length range 2-6 + // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected + sKeywordFound = false; + for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { + wbo = 0; + // Copy Keyword Length from Word Buffer into Special Keyword Buffer + for (; wbo < keywordLength; wbo++) { + sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]); + } + sKeywordBuffer[wbo] = '\0'; + // Check for Special Keyword in list + if ((keywords.InList(sKeywordBuffer)) && + ((IsBOperator(wordBuffer[wbo])) || + (IsBSeparator(wordBuffer[wbo])))) { + sKeywordFound = true; + // ECHO requires no further Regular Keyword Checking + if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { + continueProcessing = false; + } + // Colorize Special Keyword as Regular Keyword + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for External Command / Program or Default Text + if (!sKeywordFound) { + wbo = 0; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Reset External Command / Program Location + cmdLoc = offset - (wbl - wbo); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // CHOICE requires no further Regular Keyword Checking + if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { + continueProcessing = false; + } + // Check for START (and its switches) - What follows is External Command \ Program + if (CompareCaseInsensitive(wordBuffer, "start") == 0) { + // Reset External Command / Program Location + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Reset External Command / Program Location if command switch detected + if (lineBuffer[cmdLoc] == '/') { + // Skip command switch + while ((cmdLoc < lengthLine) && + (!isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + } + } + // Colorize External Command / Program + if (!keywords2) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else if (keywords2.InList(wordBuffer)) { + styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); + } else { + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + } + // No need to Reset Offset + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + } + // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) + } else if (wordBuffer[0] == '%') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second % (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Check for Argument (%n) or (%*) + if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && + (wordBuffer[wbo] != '%')) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 2); + } + // Colorize Argument + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Expanded Argument (%~...) / Variable (%%~...) + } else if (((wbl > 1) && (wordBuffer[1] == '~')) || + ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Expanded Argument / Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Environment Variable (%x...%) + } else if ((wordBuffer[1] != '%') && + (wordBuffer[wbo] == '%')) { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + // Check for Local Variable (%%a) + } else if ( + (wbl > 2) && + (wordBuffer[1] == '%') && + (wordBuffer[2] != '%') && + (!IsBOperator(wordBuffer[2])) && + (!IsBSeparator(wordBuffer[2]))) { + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - 3); + } + // Colorize Local Variable + styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - 3); + } + // Check for Environment Variable (!x...!) + } else if (wordBuffer[0] == '!') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + wbo++; + // Search to end of word for second ! (can be a long path) + while ((wbo < wbl) && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + if (wordBuffer[wbo] == '!') { + wbo++; + // Check for External Command / Program + if (cmdLoc == offset - wbl) { + cmdLoc = offset - (wbl - wbo); + } + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Check for Operator + } else if (IsBOperator(wordBuffer[0])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); + // Check for Comparison Operator + if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { + // Identify External Command / Program Location for IF + cmdLoc = offset; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Comparison Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + // Check for Pipe Operator + } else if (wordBuffer[0] == '|') { + // Reset External Command / Program Location + cmdLoc = offset - wbl + 1; + // Skip next spaces + while ((cmdLoc < lengthLine) && + (isspacechar(lineBuffer[cmdLoc]))) { + cmdLoc++; + } + // Colorize Pipe Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Check for Other Operator + } else { + // Check for > Operator + if (wordBuffer[0] == '>') { + // Turn Keyword and External Command / Program checking back on + continueProcessing = true; + } + // Colorize Other Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + } + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && + (wordBuffer[wbo] != '%') && + (wordBuffer[wbo] != '!') && + (!IsBOperator(wordBuffer[wbo])) && + (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + // Skip next spaces - nothing happens if Offset was Reset + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + } + // Colorize Default Text for remainder of line - currently not lexed + styler.ColourTo(endPos, SCE_BAT_DEFAULT); +} + +static void ColouriseBatchDoc( + unsigned int startPos, + int length, + int /*initStyle*/, + WordList *keywordlists[], + Accessor &styler) { + + char lineBuffer[1024]; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + lineBuffer[linePos] = '\0'; + ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, + keywordlists, styler); + } +} + +static const char *const batchWordListDesc[] = { + "Internal Commands", + "External Commands", + 0 +}; + +LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); diff --git a/lexers/LexDiff.cxx b/lexers/LexDiff.cxx new file mode 100644 index 000000000..46e45263a --- /dev/null +++ b/lexers/LexDiff.cxx @@ -0,0 +1,153 @@ +// Scintilla source code edit control +/** @file LexDiff.cxx + ** Lexer for diff results. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +#define DIFF_BUFFER_START_SIZE 16 +// Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE +// characters of each line to classify the line. + +static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { + // It is needed to remember the current state to recognize starting + // comment lines before the first "diff " or "--- ". If a real + // difference starts then each line starting with ' ' is a whitespace + // otherwise it is considered a comment (Only in..., Binary file...) + if (0 == strncmp(lineBuffer, "diff ", 5)) { + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff + styler.ColourTo(endLine, SCE_DIFF_COMMAND); + } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { + // In a context diff, --- appears in both the header and the position markers + if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { + // I don't know of any diff where "+++ " is a position marker, but for + // consistency, do the same as with "--- " and "*** ". + if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "***", 3)) { + // In a context diff, *** appears in both the header and the position markers. + // Also ******** is a chunk header, but here it's treated as part of the + // position marker since there is no separate style for a chunk header. + if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else if (lineBuffer[3] == '*') + styler.ColourTo(endLine, SCE_DIFF_POSITION); + else + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib + styler.ColourTo(endLine, SCE_DIFF_HEADER); + } else if (lineBuffer[0] == '@') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { + styler.ColourTo(endLine, SCE_DIFF_POSITION); + } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { + styler.ColourTo(endLine, SCE_DIFF_DELETED); + } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { + styler.ColourTo(endLine, SCE_DIFF_ADDED); + } else if (lineBuffer[0] == '!') { + styler.ColourTo(endLine, SCE_DIFF_CHANGED); + } else if (lineBuffer[0] != ' ') { + styler.ColourTo(endLine, SCE_DIFF_COMMENT); + } else { + styler.ColourTo(endLine, SCE_DIFF_DEFAULT); + } +} + +static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[DIFF_BUFFER_START_SIZE] = ""; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + for (unsigned int i = startPos; i < startPos + length; i++) { + if (AtEOL(styler, i)) { + if (linePos < DIFF_BUFFER_START_SIZE) { + lineBuffer[linePos] = 0; + } + ColouriseDiffLine(lineBuffer, i, styler); + linePos = 0; + } else if (linePos < DIFF_BUFFER_START_SIZE - 1) { + lineBuffer[linePos++] = styler[i]; + } else if (linePos == DIFF_BUFFER_START_SIZE - 1) { + lineBuffer[linePos++] = 0; + } + } + if (linePos > 0) { // Last line does not have ending characters + if (linePos < DIFF_BUFFER_START_SIZE) { + lineBuffer[linePos] = 0; + } + ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); + } +} + +static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + int curLine = styler.GetLine(startPos); + int curLineStart = styler.LineStart(curLine); + int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; + int nextLevel; + + do { + int lineType = styler.StyleAt(curLineStart); + if (lineType == SCE_DIFF_COMMAND) + nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_HEADER) + nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; + else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') + nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; + else if (prevLevel & SC_FOLDLEVELHEADERFLAG) + nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; + else + nextLevel = prevLevel; + + if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) + styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); + + styler.SetLevel(curLine, nextLevel); + prevLevel = nextLevel; + + curLineStart = styler.LineStart(++curLine); + } while (static_cast<int>(startPos) + length > curLineStart); +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); diff --git a/lexers/LexErrorList.cxx b/lexers/LexErrorList.cxx new file mode 100644 index 000000000..f4a1db270 --- /dev/null +++ b/lexers/LexErrorList.cxx @@ -0,0 +1,308 @@ +// Scintilla source code edit control +/** @file LexErrorList.cxx + ** Lexer for error lists. Used for the output pane in SciTE. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool strstart(const char *haystack, const char *needle) { + return strncmp(haystack, needle, strlen(needle)) == 0; +} + +static bool Is0To9(char ch) { + return (ch >= '0') && (ch <= '9'); +} + +static bool Is1To9(char ch) { + return (ch >= '1') && (ch <= '9'); +} + +static bool IsAlphabetic(int ch) { + return IsASCII(ch) && isalpha(ch); +} + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) { + if (lineBuffer[0] == '>') { + // Command or return status + return SCE_ERR_CMD; + } else if (lineBuffer[0] == '<') { + // Diff removal. + return SCE_ERR_DIFF_DELETION; + } else if (lineBuffer[0] == '!') { + return SCE_ERR_DIFF_CHANGED; + } else if (lineBuffer[0] == '+') { + if (strstart(lineBuffer, "+++ ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_ADDITION; + } + } else if (lineBuffer[0] == '-') { + if (strstart(lineBuffer, "--- ")) { + return SCE_ERR_DIFF_MESSAGE; + } else { + return SCE_ERR_DIFF_DELETION; + } + } else if (strstart(lineBuffer, "cf90-")) { + // Absoft Pro Fortran 90/95 v8.2 error and/or warning message + return SCE_ERR_ABSF; + } else if (strstart(lineBuffer, "fortcom:")) { + // Intel Fortran Compiler v8.0 error/warning message + return SCE_ERR_IFORT; + } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { + return SCE_ERR_PYTHON; + } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { + return SCE_ERR_PHP; + } else if ((strstart(lineBuffer, "Error ") || + strstart(lineBuffer, "Warning ")) && + strstr(lineBuffer, " at (") && + strstr(lineBuffer, ") : ") && + (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { + // Intel Fortran Compiler error/warning message + return SCE_ERR_IFC; + } else if (strstart(lineBuffer, "Error ")) { + // Borland error message + return SCE_ERR_BORLAND; + } else if (strstart(lineBuffer, "Warning ")) { + // Borland warning message + return SCE_ERR_BORLAND; + } else if (strstr(lineBuffer, "at line ") && + (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, "file ") && + (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { + // Lua 4 error message + return SCE_ERR_LUA; + } else if (strstr(lineBuffer, " at ") && + (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && + strstr(lineBuffer, " line ") && + (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && + (strstr(lineBuffer, " at ") + 4 < (strstr(lineBuffer, " line ")))) { + // perl error message: + // <message> at <file> line <line> + return SCE_ERR_PERL; + } else if ((memcmp(lineBuffer, " at ", 6) == 0) && + strstr(lineBuffer, ":line ")) { + // A .NET traceback + return SCE_ERR_NET; + } else if (strstart(lineBuffer, "Line ") && + strstr(lineBuffer, ", file ")) { + // Essential Lahey Fortran error message + return SCE_ERR_ELF; + } else if (strstart(lineBuffer, "line ") && + strstr(lineBuffer, " column ")) { + // HTML tidy style: line 42 column 1 + return SCE_ERR_TIDY; + } else if (strstart(lineBuffer, "\tat ") && + strstr(lineBuffer, "(") && + strstr(lineBuffer, ".java:")) { + // Java stack back trace + return SCE_ERR_JAVA_STACK; + } else if (strstart(lineBuffer, "In file included from ") || + strstart(lineBuffer, " from ")) { + // GCC showing include path to following error + return SCE_ERR_GCC_INCLUDED_FROM; + } else { + // Look for one of the following formats: + // GCC: <filename>:<line>:<message> + // Microsoft: <filename>(<line>) :<message> + // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal + // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal + // Microsoft: <filename>(<line>,<column>)<message> + // CTags: <identifier>\t<filename>\t<message> + // Lua 5 traceback: \t<filename>:<line>:<message> + // Lua 5.1: <exe>: <filename>:<line>:<message> + bool initialTab = (lineBuffer[0] == '\t'); + bool initialColonPart = false; + bool canBeCtags = !initialTab; // For ctags must have an identifier with no spaces then a tab + enum { stInitial, + stGccStart, stGccDigit, stGccColumn, stGcc, + stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, + stCtagsStart, stCtagsFile, stCtagsStartString, stCtagsStringDollar, stCtags, + stUnrecognized + } state = stInitial; + for (unsigned int i = 0; i < lengthLine; i++) { + char ch = lineBuffer[i]; + char chNext = ' '; + if ((i + 1) < lengthLine) + chNext = lineBuffer[i + 1]; + if (state == stInitial) { + if (ch == ':') { + // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) + if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { + // This check is not completely accurate as may be on + // GTK+ with a file name that includes ':'. + state = stGccStart; + } else if (chNext == ' ') { // indicates a Lua 5.1 error message + initialColonPart = true; + } + } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { + // May be Microsoft + // Check against '0' often removes phone numbers + state = stMsStart; + } else if ((ch == '\t') && canBeCtags) { + // May be CTags + state = stCtagsStart; + } else if (ch == ' ') { + canBeCtags = false; + } + } else if (state == stGccStart) { // <filename>: + state = Is1To9(ch) ? stGccDigit : stUnrecognized; + } else if (state == stGccDigit) { // <filename>:<line> + if (ch == ':') { + state = stGccColumn; // :9.*: is GCC + startValue = i + 1; + } else if (!Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stGccColumn) { // <filename>:<line>:<column> + if (!Is0To9(ch)) { + state = stGcc; + if (ch == ':') + startValue = i + 1; + break; + } + } else if (state == stMsStart) { // <filename>( + state = Is0To9(ch) ? stMsDigit : stUnrecognized; + } else if (state == stMsDigit) { // <filename>(<line> + if (ch == ',') { + state = stMsDigitComma; + } else if (ch == ')') { + state = stMsBracket; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stMsBracket) { // <filename>(<line>) + if ((ch == ' ') && (chNext == ':')) { + state = stMsVc; + } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { + // Possibly Delphi.. don't test against chNext as it's one of the strings below. + char word[512]; + unsigned int j, chPos; + unsigned numstep; + chPos = 0; + if (ch == ' ') + numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. + else + numstep = 2; // otherwise add 2. + for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) + word[chPos++] = lineBuffer[j]; + word[chPos] = 0; + if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || + !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || + !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) { + state = stMsVc; + } else { + state = stUnrecognized; + } + } else { + state = stUnrecognized; + } + } else if (state == stMsDigitComma) { // <filename>(<line>, + if (ch == ')') { + state = stMsDotNet; + break; + } else if ((ch != ' ') && !Is0To9(ch)) { + state = stUnrecognized; + } + } else if (state == stCtagsStart) { + if (ch == '\t') { + state = stCtagsFile; + } + } else if (state == stCtagsFile) { + if ((lineBuffer[i - 1] == '\t') && + ((ch == '/' && chNext == '^') || Is0To9(ch))) { + state = stCtags; + break; + } else if ((ch == '/') && (chNext == '^')) { + state = stCtagsStartString; + } + } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { + state = stCtagsStringDollar; + break; + } + } + if (state == stGcc) { + return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; + } else if ((state == stMsVc) || (state == stMsDotNet)) { + return SCE_ERR_MS; + } else if ((state == stCtagsStringDollar) || (state == stCtags)) { + return SCE_ERR_CTAG; + } else { + return SCE_ERR_DEFAULT; + } + } +} + +static void ColouriseErrorListLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int endPos, + Accessor &styler, + bool valueSeparate) { + int startValue = -1; + int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue); + if (valueSeparate && (startValue >= 0)) { + styler.ColourTo(endPos - (lengthLine - startValue), style); + styler.ColourTo(endPos, SCE_ERR_VALUE); + } else { + styler.ColourTo(endPos, style); + } +} + +static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[10000]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + + // property lexer.errorlist.value.separate + // For lines in the output pane that are matches from Find in Files or GCC-style + // diagnostics, style the path and line number separately from the rest of the + // line with style 21 used for the rest of the line. + // This allows matched text to be more easily distinguished from its location. + bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate); + linePos = 0; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate); + } +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); diff --git a/lexers/LexMake.cxx b/lexers/LexMake.cxx new file mode 100644 index 000000000..3ab172682 --- /dev/null +++ b/lexers/LexMake.cxx @@ -0,0 +1,144 @@ +// Scintilla source code edit control +/** @file LexMake.cxx + ** Lexer for make files. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +static void ColouriseMakeLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler) { + + unsigned int i = 0; + int lastNonSpace = -1; + unsigned int state = SCE_MAKE_DEFAULT; + bool bSpecial = false; + + // check for a tab character in column 0 indicating a command + bool bCommand = false; + if ((lengthLine > 0) && (lineBuffer[0] == '\t')) + bCommand = true; + + // Skip initial spaces + while ((i < lengthLine) && isspacechar(lineBuffer[i])) { + i++; + } + if (i < lengthLine) { + if (lineBuffer[i] == '#') { // Comment + styler.ColourTo(endPos, SCE_MAKE_COMMENT); + return; + } + if (lineBuffer[i] == '!') { // Special directive + styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); + return; + } + } + int varCount = 0; + while (i < lengthLine) { + if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) { + styler.ColourTo(startLine + i - 1, state); + state = SCE_MAKE_IDENTIFIER; + varCount++; + } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { + if (--varCount == 0) { + styler.ColourTo(startLine + i, state); + state = SCE_MAKE_DEFAULT; + } + } + + // skip identifier and target styling if this is a command line + if (!bSpecial && !bCommand) { + if (lineBuffer[i] == ':') { + if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { + // it's a ':=', so style as an identifier + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); + } else { + // We should check that no colouring was made since the beginning of the line, + // to avoid colouring stuff like /OUT:file + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + } + bSpecial = true; // Only react to the first ':' of the line + state = SCE_MAKE_DEFAULT; + } else if (lineBuffer[i] == '=') { + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + bSpecial = true; // Only react to the first '=' of the line + state = SCE_MAKE_DEFAULT; + } + } + if (!isspacechar(lineBuffer[i])) { + lastNonSpace = i; + } + i++; + } + if (state == SCE_MAKE_IDENTIFIER) { + styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended + } else { + styler.ColourTo(endPos, SCE_MAKE_DEFAULT); + } +} + +static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); + } +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); diff --git a/lexers/LexNull.cxx b/lexers/LexNull.cxx new file mode 100644 index 000000000..d5b3b3046 --- /dev/null +++ b/lexers/LexNull.cxx @@ -0,0 +1,40 @@ +// Scintilla source code edit control +/** @file LexNull.cxx + ** Lexer for no language. Used for plain text and unrecognized files. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { + // Null language means all style bytes are 0 so just mark the end - no need to fill in. + if (length > 0) { + styler.StartAt(startPos + length - 1); + styler.StartSegment(startPos + length - 1); + styler.ColourTo(startPos + length - 1, 0); + } +} + +LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); diff --git a/lexers/LexOthers.cxx b/lexers/LexOthers.cxx deleted file mode 100644 index f1e828dc8..000000000 --- a/lexers/LexOthers.cxx +++ /dev/null @@ -1,1149 +0,0 @@ -// Scintilla source code edit control -/** @file LexOthers.cxx - ** Lexers for batch files, diff results, properties files, make files and error lists. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <assert.h> -#include <ctype.h> - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool strstart(const char *haystack, const char *needle) { - return strncmp(haystack, needle, strlen(needle)) == 0; -} - -static bool Is0To9(char ch) { - return (ch >= '0') && (ch <= '9'); -} - -static bool Is1To9(char ch) { - return (ch >= '1') && (ch <= '9'); -} - -static bool IsAlphabetic(int ch) { - return IsASCII(ch) && isalpha(ch); -} - -static inline bool AtEOL(Accessor &styler, unsigned int i) { - return (styler[i] == '\n') || - ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); -} - -// Tests for BATCH Operators -static bool IsBOperator(char ch) { - return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || - (ch == '|') || (ch == '?') || (ch == '*'); -} - -// Tests for BATCH Separators -static bool IsBSeparator(char ch) { - return (ch == '\\') || (ch == '.') || (ch == ';') || - (ch == '\"') || (ch == '\'') || (ch == '/'); -} - -static void ColouriseBatchLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - WordList *keywordlists[], - Accessor &styler) { - - unsigned int offset = 0; // Line Buffer Offset - unsigned int cmdLoc; // External Command / Program Location - char wordBuffer[81]; // Word Buffer - large to catch long paths - unsigned int wbl; // Word Buffer Length - unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length - WordList &keywords = *keywordlists[0]; // Internal Commands - WordList &keywords2 = *keywordlists[1]; // External Commands (optional) - - // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords - // Toggling Regular Keyword Checking off improves readability - // Other Regular Keywords and External Commands / Programs might also benefit from toggling - // Need a more robust algorithm to properly toggle Regular Keyword Checking - bool continueProcessing = true; // Used to toggle Regular Keyword Checking - // Special Keywords are those that allow certain characters without whitespace after the command - // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= - // Special Keyword Buffer used to determine if the first n characters is a Keyword - char sKeywordBuffer[10]; // Special Keyword Buffer - bool sKeywordFound; // Exit Special Keyword for-loop if found - - // Skip initial spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - // Set External Command / Program Location - cmdLoc = offset; - - // Check for Fake Label (Comment) or Real Label - return if found - if (lineBuffer[offset] == ':') { - if (lineBuffer[offset + 1] == ':') { - // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm - styler.ColourTo(endPos, SCE_BAT_COMMENT); - } else { - // Colorize Real Label - styler.ColourTo(endPos, SCE_BAT_LABEL); - } - return; - // Check for Drive Change (Drive Change is internal command) - return if found - } else if ((IsAlphabetic(lineBuffer[offset])) && - (lineBuffer[offset + 1] == ':') && - ((isspacechar(lineBuffer[offset + 2])) || - (((lineBuffer[offset + 2] == '\\')) && - (isspacechar(lineBuffer[offset + 3]))))) { - // Colorize Regular Keyword - styler.ColourTo(endPos, SCE_BAT_WORD); - return; - } - - // Check for Hide Command (@ECHO OFF/ON) - if (lineBuffer[offset] == '@') { - styler.ColourTo(startLine + offset, SCE_BAT_HIDE); - offset++; - } - // Skip next spaces - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - - // Read remainder of line word-at-a-time or remainder-of-word-at-a-time - while (offset < lengthLine) { - if (offset > startLine) { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Copy word from Line Buffer into Word Buffer - wbl = 0; - for (; offset < lengthLine && wbl < 80 && - !isspacechar(lineBuffer[offset]); wbl++, offset++) { - wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); - } - wordBuffer[wbl] = '\0'; - wbo = 0; - - // Check for Comment - return if found - if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { - styler.ColourTo(endPos, SCE_BAT_COMMENT); - return; - } - // Check for Separator - if (IsBSeparator(wordBuffer[0])) { - // Check for External Command / Program - if ((cmdLoc == offset - wbl) && - ((wordBuffer[0] == ':') || - (wordBuffer[0] == '\\') || - (wordBuffer[0] == '.'))) { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Reset External Command / Program Location - cmdLoc = offset; - } else { - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Colorize Default Text - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // Check for Regular Keyword in list - } else if ((keywords.InList(wordBuffer)) && - (continueProcessing)) { - // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking - if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || - (CompareCaseInsensitive(wordBuffer, "goto") == 0) || - (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || - (CompareCaseInsensitive(wordBuffer, "set") == 0)) { - continueProcessing = false; - } - // Identify External Command / Program Location for ERRORLEVEL, and EXIST - if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || - (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip comparison - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH - } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || - (CompareCaseInsensitive(wordBuffer, "do") == 0) || - (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || - (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - } - // Colorize Regular keyword - styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); - // No need to Reset Offset - // Check for Special Keyword in list, External Command / Program, or Default Text - } else if ((wordBuffer[0] != '%') && - (wordBuffer[0] != '!') && - (!IsBOperator(wordBuffer[0])) && - (continueProcessing)) { - // Check for Special Keyword - // Affected Commands are in Length range 2-6 - // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected - sKeywordFound = false; - for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { - wbo = 0; - // Copy Keyword Length from Word Buffer into Special Keyword Buffer - for (; wbo < keywordLength; wbo++) { - sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]); - } - sKeywordBuffer[wbo] = '\0'; - // Check for Special Keyword in list - if ((keywords.InList(sKeywordBuffer)) && - ((IsBOperator(wordBuffer[wbo])) || - (IsBSeparator(wordBuffer[wbo])))) { - sKeywordFound = true; - // ECHO requires no further Regular Keyword Checking - if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { - continueProcessing = false; - } - // Colorize Special Keyword as Regular Keyword - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - } - // Check for External Command / Program or Default Text - if (!sKeywordFound) { - wbo = 0; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Reset External Command / Program Location - cmdLoc = offset - (wbl - wbo); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // CHOICE requires no further Regular Keyword Checking - if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { - continueProcessing = false; - } - // Check for START (and its switches) - What follows is External Command \ Program - if (CompareCaseInsensitive(wordBuffer, "start") == 0) { - // Reset External Command / Program Location - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Reset External Command / Program Location if command switch detected - if (lineBuffer[cmdLoc] == '/') { - // Skip command switch - while ((cmdLoc < lengthLine) && - (!isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - } - } - // Colorize External Command / Program - if (!keywords2) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else if (keywords2.InList(wordBuffer)) { - styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); - } else { - styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); - } - // No need to Reset Offset - // Check for Default Text - } else { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - } - // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) - } else if (wordBuffer[0] == '%') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second % (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Check for Argument (%n) or (%*) - if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && - (wordBuffer[wbo] != '%')) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 2); - } - // Colorize Argument - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Expanded Argument (%~...) / Variable (%%~...) - } else if (((wbl > 1) && (wordBuffer[1] == '~')) || - ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Expanded Argument / Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Environment Variable (%x...%) - } else if ((wordBuffer[1] != '%') && - (wordBuffer[wbo] == '%')) { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - // Check for Local Variable (%%a) - } else if ( - (wbl > 2) && - (wordBuffer[1] == '%') && - (wordBuffer[2] != '%') && - (!IsBOperator(wordBuffer[2])) && - (!IsBSeparator(wordBuffer[2]))) { - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - 3); - } - // Colorize Local Variable - styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - 3); - } - // Check for Environment Variable (!x...!) - } else if (wordBuffer[0] == '!') { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - wbo++; - // Search to end of word for second ! (can be a long path) - while ((wbo < wbl) && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - if (wordBuffer[wbo] == '!') { - wbo++; - // Check for External Command / Program - if (cmdLoc == offset - wbl) { - cmdLoc = offset - (wbl - wbo); - } - // Colorize Environment Variable - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Check for Operator - } else if (IsBOperator(wordBuffer[0])) { - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); - // Check for Comparison Operator - if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { - // Identify External Command / Program Location for IF - cmdLoc = offset; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Colorize Comparison Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 2); - // Check for Pipe Operator - } else if (wordBuffer[0] == '|') { - // Reset External Command / Program Location - cmdLoc = offset - wbl + 1; - // Skip next spaces - while ((cmdLoc < lengthLine) && - (isspacechar(lineBuffer[cmdLoc]))) { - cmdLoc++; - } - // Colorize Pipe Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - // Check for Other Operator - } else { - // Check for > Operator - if (wordBuffer[0] == '>') { - // Turn Keyword and External Command / Program checking back on - continueProcessing = true; - } - // Colorize Other Operator - styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); - // Reset Offset to re-process remainder of word - offset -= (wbl - 1); - } - // Check for Default Text - } else { - // Read up to %, Operator or Separator - while ((wbo < wbl) && - (wordBuffer[wbo] != '%') && - (wordBuffer[wbo] != '!') && - (!IsBOperator(wordBuffer[wbo])) && - (!IsBSeparator(wordBuffer[wbo]))) { - wbo++; - } - // Colorize Default Text - styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); - // Reset Offset to re-process remainder of word - offset -= (wbl - wbo); - } - // Skip next spaces - nothing happens if Offset was Reset - while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { - offset++; - } - } - // Colorize Default Text for remainder of line - currently not lexed - styler.ColourTo(endPos, SCE_BAT_DEFAULT); -} - -static void ColouriseBatchDoc( - unsigned int startPos, - int length, - int /*initStyle*/, - WordList *keywordlists[], - Accessor &styler) { - - char lineBuffer[1024]; - - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - lineBuffer[linePos] = '\0'; - ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, - keywordlists, styler); - } -} - -#define DIFF_BUFFER_START_SIZE 16 -// Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE -// characters of each line to classify the line. - -static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { - // It is needed to remember the current state to recognize starting - // comment lines before the first "diff " or "--- ". If a real - // difference starts then each line starting with ' ' is a whitespace - // otherwise it is considered a comment (Only in..., Binary file...) - if (0 == strncmp(lineBuffer, "diff ", 5)) { - styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff - styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { - // In a context diff, --- appears in both the header and the position markers - if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { - // I don't know of any diff where "+++ " is a position marker, but for - // consistency, do the same as with "--- " and "*** ". - if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "***", 3)) { - // In a context diff, *** appears in both the header and the position markers. - // Also ******** is a chunk header, but here it's treated as part of the - // position marker since there is no separate style for a chunk header. - if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else if (lineBuffer[3] == '*') - styler.ColourTo(endLine, SCE_DIFF_POSITION); - else - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib - styler.ColourTo(endLine, SCE_DIFF_HEADER); - } else if (lineBuffer[0] == '@') { - styler.ColourTo(endLine, SCE_DIFF_POSITION); - } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { - styler.ColourTo(endLine, SCE_DIFF_POSITION); - } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { - styler.ColourTo(endLine, SCE_DIFF_DELETED); - } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { - styler.ColourTo(endLine, SCE_DIFF_ADDED); - } else if (lineBuffer[0] == '!') { - styler.ColourTo(endLine, SCE_DIFF_CHANGED); - } else if (lineBuffer[0] != ' ') { - styler.ColourTo(endLine, SCE_DIFF_COMMENT); - } else { - styler.ColourTo(endLine, SCE_DIFF_DEFAULT); - } -} - -static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[DIFF_BUFFER_START_SIZE] = ""; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - for (unsigned int i = startPos; i < startPos + length; i++) { - if (AtEOL(styler, i)) { - if (linePos < DIFF_BUFFER_START_SIZE) { - lineBuffer[linePos] = 0; - } - ColouriseDiffLine(lineBuffer, i, styler); - linePos = 0; - } else if (linePos < DIFF_BUFFER_START_SIZE - 1) { - lineBuffer[linePos++] = styler[i]; - } else if (linePos == DIFF_BUFFER_START_SIZE - 1) { - lineBuffer[linePos++] = 0; - } - } - if (linePos > 0) { // Last line does not have ending characters - if (linePos < DIFF_BUFFER_START_SIZE) { - lineBuffer[linePos] = 0; - } - ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); - } -} - -static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - int curLine = styler.GetLine(startPos); - int curLineStart = styler.LineStart(curLine); - int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; - int nextLevel; - - do { - int lineType = styler.StyleAt(curLineStart); - if (lineType == SCE_DIFF_COMMAND) - nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; - else if (lineType == SCE_DIFF_HEADER) - nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; - else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') - nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; - else if (prevLevel & SC_FOLDLEVELHEADERFLAG) - nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; - else - nextLevel = prevLevel; - - if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) - styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); - - styler.SetLevel(curLine, nextLevel); - prevLevel = nextLevel; - - curLineStart = styler.LineStart(++curLine); - } while (static_cast<int>(startPos) + length > curLineStart); -} - -static inline bool isassignchar(unsigned char ch) { - return (ch == '=') || (ch == ':'); -} - -static void ColourisePropsLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - Accessor &styler, - bool allowInitialSpaces) { - - unsigned int i = 0; - if (allowInitialSpaces) { - while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces - i++; - } else { - if (isspacechar(lineBuffer[i])) // don't allow initial spaces - i = lengthLine; - } - - if (i < lengthLine) { - if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') { - styler.ColourTo(endPos, SCE_PROPS_COMMENT); - } else if (lineBuffer[i] == '[') { - styler.ColourTo(endPos, SCE_PROPS_SECTION); - } else if (lineBuffer[i] == '@') { - styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL); - if (isassignchar(lineBuffer[i++])) - styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } else { - // Search for the '=' character - while ((i < lengthLine) && !isassignchar(lineBuffer[i])) - i++; - if ((i < lengthLine) && isassignchar(lineBuffer[i])) { - styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY); - styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } else { - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } - } - } else { - styler.ColourTo(endPos, SCE_PROPS_DEFAULT); - } -} - -static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - - // property lexer.props.allow.initial.spaces - // For properties files, set to 0 to style all lines that start with whitespace in the default style. - // This is not suitable for SciTE .properties files which use indentation for flow control but - // can be used for RFC2822 text where indentation is used for continuation lines. - bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; - - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces); - } -} - -// adaption by ksc, using the "} else {" trick of 1.53 -// 030721 -static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - bool headerPoint = false; - int lev; - - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler[i+1]; - - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - - if (style == SCE_PROPS_SECTION) { - headerPoint = true; - } - - if (atEOL) { - lev = SC_FOLDLEVELBASE; - - if (lineCurrent > 0) { - int levelPrevious = styler.LevelAt(lineCurrent - 1); - - if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { - lev = SC_FOLDLEVELBASE + 1; - } else { - lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; - } - } - - if (headerPoint) { - lev = SC_FOLDLEVELBASE; - } - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - - if (headerPoint) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - - lineCurrent++; - visibleChars = 0; - headerPoint = false; - } - if (!isspacechar(ch)) - visibleChars++; - } - - if (lineCurrent > 0) { - int levelPrevious = styler.LevelAt(lineCurrent - 1); - if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { - lev = SC_FOLDLEVELBASE + 1; - } else { - lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; - } - } else { - lev = SC_FOLDLEVELBASE; - } - int flagsNext = styler.LevelAt(lineCurrent); - styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); -} - -static void ColouriseMakeLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int startLine, - unsigned int endPos, - Accessor &styler) { - - unsigned int i = 0; - int lastNonSpace = -1; - unsigned int state = SCE_MAKE_DEFAULT; - bool bSpecial = false; - - // check for a tab character in column 0 indicating a command - bool bCommand = false; - if ((lengthLine > 0) && (lineBuffer[0] == '\t')) - bCommand = true; - - // Skip initial spaces - while ((i < lengthLine) && isspacechar(lineBuffer[i])) { - i++; - } - if (i < lengthLine) { - if (lineBuffer[i] == '#') { // Comment - styler.ColourTo(endPos, SCE_MAKE_COMMENT); - return; - } - if (lineBuffer[i] == '!') { // Special directive - styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); - return; - } - } - int varCount = 0; - while (i < lengthLine) { - if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) { - styler.ColourTo(startLine + i - 1, state); - state = SCE_MAKE_IDENTIFIER; - varCount++; - } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { - if (--varCount == 0) { - styler.ColourTo(startLine + i, state); - state = SCE_MAKE_DEFAULT; - } - } - - // skip identifier and target styling if this is a command line - if (!bSpecial && !bCommand) { - if (lineBuffer[i] == ':') { - if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { - // it's a ':=', so style as an identifier - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); - } else { - // We should check that no colouring was made since the beginning of the line, - // to avoid colouring stuff like /OUT:file - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); - } - bSpecial = true; // Only react to the first ':' of the line - state = SCE_MAKE_DEFAULT; - } else if (lineBuffer[i] == '=') { - if (lastNonSpace >= 0) - styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); - styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); - styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); - bSpecial = true; // Only react to the first '=' of the line - state = SCE_MAKE_DEFAULT; - } - } - if (!isspacechar(lineBuffer[i])) { - lastNonSpace = i; - } - i++; - } - if (state == SCE_MAKE_IDENTIFIER) { - styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended - } else { - styler.ColourTo(endPos, SCE_MAKE_DEFAULT); - } -} - -static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - unsigned int startLine = startPos; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); - linePos = 0; - startLine = i + 1; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); - } -} - -static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) { - if (lineBuffer[0] == '>') { - // Command or return status - return SCE_ERR_CMD; - } else if (lineBuffer[0] == '<') { - // Diff removal. - return SCE_ERR_DIFF_DELETION; - } else if (lineBuffer[0] == '!') { - return SCE_ERR_DIFF_CHANGED; - } else if (lineBuffer[0] == '+') { - if (strstart(lineBuffer, "+++ ")) { - return SCE_ERR_DIFF_MESSAGE; - } else { - return SCE_ERR_DIFF_ADDITION; - } - } else if (lineBuffer[0] == '-') { - if (strstart(lineBuffer, "--- ")) { - return SCE_ERR_DIFF_MESSAGE; - } else { - return SCE_ERR_DIFF_DELETION; - } - } else if (strstart(lineBuffer, "cf90-")) { - // Absoft Pro Fortran 90/95 v8.2 error and/or warning message - return SCE_ERR_ABSF; - } else if (strstart(lineBuffer, "fortcom:")) { - // Intel Fortran Compiler v8.0 error/warning message - return SCE_ERR_IFORT; - } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { - return SCE_ERR_PYTHON; - } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { - return SCE_ERR_PHP; - } else if ((strstart(lineBuffer, "Error ") || - strstart(lineBuffer, "Warning ")) && - strstr(lineBuffer, " at (") && - strstr(lineBuffer, ") : ") && - (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { - // Intel Fortran Compiler error/warning message - return SCE_ERR_IFC; - } else if (strstart(lineBuffer, "Error ")) { - // Borland error message - return SCE_ERR_BORLAND; - } else if (strstart(lineBuffer, "Warning ")) { - // Borland warning message - return SCE_ERR_BORLAND; - } else if (strstr(lineBuffer, "at line ") && - (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && - strstr(lineBuffer, "file ") && - (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { - // Lua 4 error message - return SCE_ERR_LUA; - } else if (strstr(lineBuffer, " at ") && - (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && - strstr(lineBuffer, " line ") && - (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && - (strstr(lineBuffer, " at ") + 4 < (strstr(lineBuffer, " line ")))) { - // perl error message: - // <message> at <file> line <line> - return SCE_ERR_PERL; - } else if ((memcmp(lineBuffer, " at ", 6) == 0) && - strstr(lineBuffer, ":line ")) { - // A .NET traceback - return SCE_ERR_NET; - } else if (strstart(lineBuffer, "Line ") && - strstr(lineBuffer, ", file ")) { - // Essential Lahey Fortran error message - return SCE_ERR_ELF; - } else if (strstart(lineBuffer, "line ") && - strstr(lineBuffer, " column ")) { - // HTML tidy style: line 42 column 1 - return SCE_ERR_TIDY; - } else if (strstart(lineBuffer, "\tat ") && - strstr(lineBuffer, "(") && - strstr(lineBuffer, ".java:")) { - // Java stack back trace - return SCE_ERR_JAVA_STACK; - } else if (strstart(lineBuffer, "In file included from ") || - strstart(lineBuffer, " from ")) { - // GCC showing include path to following error - return SCE_ERR_GCC_INCLUDED_FROM; - } else { - // Look for one of the following formats: - // GCC: <filename>:<line>:<message> - // Microsoft: <filename>(<line>) :<message> - // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal - // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal - // Microsoft: <filename>(<line>,<column>)<message> - // CTags: <identifier>\t<filename>\t<message> - // Lua 5 traceback: \t<filename>:<line>:<message> - // Lua 5.1: <exe>: <filename>:<line>:<message> - bool initialTab = (lineBuffer[0] == '\t'); - bool initialColonPart = false; - bool canBeCtags = !initialTab; // For ctags must have an identifier with no spaces then a tab - enum { stInitial, - stGccStart, stGccDigit, stGccColumn, stGcc, - stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, - stCtagsStart, stCtagsFile, stCtagsStartString, stCtagsStringDollar, stCtags, - stUnrecognized - } state = stInitial; - for (unsigned int i = 0; i < lengthLine; i++) { - char ch = lineBuffer[i]; - char chNext = ' '; - if ((i + 1) < lengthLine) - chNext = lineBuffer[i + 1]; - if (state == stInitial) { - if (ch == ':') { - // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) - if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { - // This check is not completely accurate as may be on - // GTK+ with a file name that includes ':'. - state = stGccStart; - } else if (chNext == ' ') { // indicates a Lua 5.1 error message - initialColonPart = true; - } - } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { - // May be Microsoft - // Check against '0' often removes phone numbers - state = stMsStart; - } else if ((ch == '\t') && canBeCtags) { - // May be CTags - state = stCtagsStart; - } else if (ch == ' ') { - canBeCtags = false; - } - } else if (state == stGccStart) { // <filename>: - state = Is1To9(ch) ? stGccDigit : stUnrecognized; - } else if (state == stGccDigit) { // <filename>:<line> - if (ch == ':') { - state = stGccColumn; // :9.*: is GCC - startValue = i + 1; - } else if (!Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stGccColumn) { // <filename>:<line>:<column> - if (!Is0To9(ch)) { - state = stGcc; - if (ch == ':') - startValue = i + 1; - break; - } - } else if (state == stMsStart) { // <filename>( - state = Is0To9(ch) ? stMsDigit : stUnrecognized; - } else if (state == stMsDigit) { // <filename>(<line> - if (ch == ',') { - state = stMsDigitComma; - } else if (ch == ')') { - state = stMsBracket; - } else if ((ch != ' ') && !Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stMsBracket) { // <filename>(<line>) - if ((ch == ' ') && (chNext == ':')) { - state = stMsVc; - } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { - // Possibly Delphi.. don't test against chNext as it's one of the strings below. - char word[512]; - unsigned int j, chPos; - unsigned numstep; - chPos = 0; - if (ch == ' ') - numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. - else - numstep = 2; // otherwise add 2. - for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) - word[chPos++] = lineBuffer[j]; - word[chPos] = 0; - if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || - !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || - !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) { - state = stMsVc; - } else { - state = stUnrecognized; - } - } else { - state = stUnrecognized; - } - } else if (state == stMsDigitComma) { // <filename>(<line>, - if (ch == ')') { - state = stMsDotNet; - break; - } else if ((ch != ' ') && !Is0To9(ch)) { - state = stUnrecognized; - } - } else if (state == stCtagsStart) { - if (ch == '\t') { - state = stCtagsFile; - } - } else if (state == stCtagsFile) { - if ((lineBuffer[i - 1] == '\t') && - ((ch == '/' && chNext == '^') || Is0To9(ch))) { - state = stCtags; - break; - } else if ((ch == '/') && (chNext == '^')) { - state = stCtagsStartString; - } - } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { - state = stCtagsStringDollar; - break; - } - } - if (state == stGcc) { - return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; - } else if ((state == stMsVc) || (state == stMsDotNet)) { - return SCE_ERR_MS; - } else if ((state == stCtagsStringDollar) || (state == stCtags)) { - return SCE_ERR_CTAG; - } else { - return SCE_ERR_DEFAULT; - } - } -} - -static void ColouriseErrorListLine( - char *lineBuffer, - unsigned int lengthLine, - unsigned int endPos, - Accessor &styler, - bool valueSeparate) { - int startValue = -1; - int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue); - if (valueSeparate && (startValue >= 0)) { - styler.ColourTo(endPos - (lengthLine - startValue), style); - styler.ColourTo(endPos, SCE_ERR_VALUE); - } else { - styler.ColourTo(endPos, style); - } -} - -static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[10000]; - styler.StartAt(startPos); - styler.StartSegment(startPos); - unsigned int linePos = 0; - - // property lexer.errorlist.value.separate - // For lines in the output pane that are matches from Find in Files or GCC-style - // diagnostics, style the path and line number separately from the rest of the - // line with style 21 used for the rest of the line. - // This allows matched text to be more easily distinguished from its location. - bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; - for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; - ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate); - linePos = 0; - } - } - if (linePos > 0) { // Last line does not have ending characters - ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate); - } -} - -static const char *const batchWordListDesc[] = { - "Internal Commands", - "External Commands", - 0 -}; - -static const char *const emptyWordListDesc[] = { - 0 -}; - -static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - // Null language means all style bytes are 0 so just mark the end - no need to fill in. - if (length > 0) { - styler.StartAt(startPos + length - 1); - styler.StartSegment(startPos + length - 1); - styler.ColourTo(startPos + length - 1, 0); - } -} - -LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); -LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); -LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); -LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); -LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); -LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); diff --git a/lexers/LexProps.cxx b/lexers/LexProps.cxx new file mode 100644 index 000000000..3a722506f --- /dev/null +++ b/lexers/LexProps.cxx @@ -0,0 +1,189 @@ +// Scintilla source code edit control +/** @file LexProps.cxx + ** Lexer for properties files. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +static inline bool isassignchar(unsigned char ch) { + return (ch == '=') || (ch == ':'); +} + +static void ColourisePropsLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler, + bool allowInitialSpaces) { + + unsigned int i = 0; + if (allowInitialSpaces) { + while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces + i++; + } else { + if (isspacechar(lineBuffer[i])) // don't allow initial spaces + i = lengthLine; + } + + if (i < lengthLine) { + if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') { + styler.ColourTo(endPos, SCE_PROPS_COMMENT); + } else if (lineBuffer[i] == '[') { + styler.ColourTo(endPos, SCE_PROPS_SECTION); + } else if (lineBuffer[i] == '@') { + styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL); + if (isassignchar(lineBuffer[i++])) + styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } else { + // Search for the '=' character + while ((i < lengthLine) && !isassignchar(lineBuffer[i])) + i++; + if ((i < lengthLine) && isassignchar(lineBuffer[i])) { + styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY); + styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } else { + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } + } + } else { + styler.ColourTo(endPos, SCE_PROPS_DEFAULT); + } +} + +static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + + // property lexer.props.allow.initial.spaces + // For properties files, set to 0 to style all lines that start with whitespace in the default style. + // This is not suitable for SciTE .properties files which use indentation for flow control but + // can be used for RFC2822 text where indentation is used for continuation lines. + bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; + + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces); + } +} + +// adaption by ksc, using the "} else {" trick of 1.53 +// 030721 +static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + bool headerPoint = false; + int lev; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler[i+1]; + + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (style == SCE_PROPS_SECTION) { + headerPoint = true; + } + + if (atEOL) { + lev = SC_FOLDLEVELBASE; + + if (lineCurrent > 0) { + int levelPrevious = styler.LevelAt(lineCurrent - 1); + + if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { + lev = SC_FOLDLEVELBASE + 1; + } else { + lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; + } + } + + if (headerPoint) { + lev = SC_FOLDLEVELBASE; + } + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + + if (headerPoint) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + + lineCurrent++; + visibleChars = 0; + headerPoint = false; + } + if (!isspacechar(ch)) + visibleChars++; + } + + if (lineCurrent > 0) { + int levelPrevious = styler.LevelAt(lineCurrent - 1); + if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { + lev = SC_FOLDLEVELBASE + 1; + } else { + lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; + } + } else { + lev = SC_FOLDLEVELBASE; + } + int flagsNext = styler.LevelAt(lineCurrent); + styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); diff --git a/win32/scintilla.mak b/win32/scintilla.mak index 5b4975ef3..762c5a0ca 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -113,6 +113,7 @@ LEXOBJS=\ $(DIR_O)\LexBaan.obj \ $(DIR_O)\LexBash.obj \ $(DIR_O)\LexBasic.obj \ + $(DIR_O)\LexBatch.obj \ $(DIR_O)\LexBibTeX.obj \ $(DIR_O)\LexBullant.obj \ $(DIR_O)\LexCaml.obj \ @@ -126,11 +127,13 @@ LEXOBJS=\ $(DIR_O)\LexCsound.obj \ $(DIR_O)\LexCSS.obj \ $(DIR_O)\LexD.obj \ + $(DIR_O)\LexDiff.obj \ $(DIR_O)\LexDMAP.obj \ $(DIR_O)\LexDMIS.obj \ $(DIR_O)\LexECL.obj \ $(DIR_O)\LexEiffel.obj \ $(DIR_O)\LexErlang.obj \ + $(DIR_O)\LexErrorList.obj \ $(DIR_O)\LexEScript.obj \ $(DIR_O)\LexFlagship.obj \ $(DIR_O)\LexForth.obj \ @@ -148,6 +151,7 @@ LEXOBJS=\ $(DIR_O)\LexLout.obj \ $(DIR_O)\LexLua.obj \ $(DIR_O)\LexMagik.obj \ + $(DIR_O)\LexMake.obj \ $(DIR_O)\LexMarkdown.obj \ $(DIR_O)\LexMatlab.obj \ $(DIR_O)\LexMetapost.obj \ @@ -158,9 +162,9 @@ LEXOBJS=\ $(DIR_O)\LexMySQL.obj \ $(DIR_O)\LexNimrod.obj \ $(DIR_O)\LexNsis.obj \ + $(DIR_O)\LexNull.obj \ $(DIR_O)\LexOpal.obj \ $(DIR_O)\LexOScript.obj \ - $(DIR_O)\LexOthers.obj \ $(DIR_O)\LexPascal.obj \ $(DIR_O)\LexPB.obj \ $(DIR_O)\LexPerl.obj \ @@ -170,6 +174,7 @@ LEXOBJS=\ $(DIR_O)\LexPowerPro.obj \ $(DIR_O)\LexPowerShell.obj \ $(DIR_O)\LexProgress.obj \ + $(DIR_O)\LexProps.obj \ $(DIR_O)\LexPS.obj \ $(DIR_O)\LexPython.obj \ $(DIR_O)\LexR.obj \ @@ -483,6 +488,8 @@ $(DIR_O)\LexBash.obj: ..\lexers\LexBash.cxx $(LEX_HEADERS) $(DIR_O)\LexBasic.obj: ..\lexers\LexBasic.cxx $(LEX_HEADERS) +$(DIR_O)\LexBatch.obj: ..\lexers\LexBatch.cxx $(LEX_HEADERS) + $(DIR_O)\LexBibTeX.obj: ..\lexers\LexBibTeX.cxx $(LEX_HEADERS) $(DIR_O)\LexBullant.obj: ..\lexers\LexBullant.cxx $(LEX_HEADERS) @@ -509,6 +516,8 @@ $(DIR_O)\LexCSS.obj: ..\lexers\LexCSS.cxx $(LEX_HEADERS) $(DIR_O)\LexD.obj: ..\lexers\LexD.cxx $(LEX_HEADERS) +$(DIR_O)\LexDiff.obj: ..\lexers\LexDiff.cxx $(LEX_HEADERS) + $(DIR_O)\LexDMAP.obj: ..\lexers\LexDMAP.cxx $(LEX_HEADERS) $(DIR_O)\LexDMIS.obj: ..\lexers\LexDMIS.cxx $(LEX_HEADERS) @@ -519,6 +528,8 @@ $(DIR_O)\LexEiffel.obj: ..\lexers\LexEiffel.cxx $(LEX_HEADERS) $(DIR_O)\LexErlang.obj: ..\lexers\LexErlang.cxx $(LEX_HEADERS) +$(DIR_O)\LexErrorList.obj: ..\lexers\LexErrorList.cxx $(LEX_HEADERS) + $(DIR_O)\LexEScript.obj: ..\lexers\LexEScript.cxx $(LEX_HEADERS) $(DIR_O)\LexFlagship.obj: ..\lexers\LexFlagship.cxx $(LEX_HEADERS) @@ -553,6 +564,8 @@ $(DIR_O)\LexLua.obj: ..\lexers\LexLua.cxx $(LEX_HEADERS) $(DIR_O)\LexMagik.obj: ..\lexers\LexMagik.cxx $(LEX_HEADERS) +$(DIR_O)\LexMake.obj: ..\lexers\LexMake.cxx $(LEX_HEADERS) + $(DIR_O)\LexMarkdown.obj: ..\lexers\LexMarkdown.cxx $(LEX_HEADERS) $(DIR_O)\LexMatlab.obj: ..\lexers\LexMatlab.cxx $(LEX_HEADERS) @@ -573,12 +586,12 @@ $(DIR_O)\LexNimrod.obj: ..\lexers\LexNimrod.cxx $(LEX_HEADERS) $(DIR_O)\LexNsis.obj: ..\lexers\LexNsis.cxx $(LEX_HEADERS) +$(DIR_O)\LexNull.obj: ..\lexers\LexNull.cxx $(LEX_HEADERS) + $(DIR_O)\LexOpal.obj: ..\lexers\LexOpal.cxx $(LEX_HEADERS) $(DIR_O)\LexOScript.obj: ..\lexers\LexOScript.cxx $(LEX_HEADERS) -$(DIR_O)\LexOthers.obj: ..\lexers\LexOthers.cxx $(LEX_HEADERS) - $(DIR_O)\LexPascal.obj: ..\lexers\LexPascal.cxx $(LEX_HEADERS) $(DIR_O)\LexPB.obj: ..\lexers\LexPB.cxx $(LEX_HEADERS) @@ -597,6 +610,8 @@ $(DIR_O)\LexPowerShell.obj: ..\lexers\LexPowerShell.cxx $(LEX_HEADERS) $(DIR_O)\LexProgress.obj: ..\lexers\LexProgress.cxx $(LEX_HEADERS) +$(DIR_O)\LexProps.obj: ..\lexers\LexProps.cxx $(LEX_HEADERS) + $(DIR_O)\LexPS.obj: ..\lexers\LexPS.cxx $(LEX_HEADERS) $(DIR_O)\LexPython.obj: ..\lexers\LexPython.cxx $(LEX_HEADERS) |