// Scintilla source code edit control /** @file LexOthers.cxx ** Lexers for batch files, diff results, properties files, make files and error lists. ** Also lexer for LaTeX documents. **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include "Platform.h" #include "CharClassify.h" #include "PropSet.h" #include "Accessor.h" #include "KeyWords.h" #include "Scintilla.h" #include "SciLexer.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 == '/') || (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(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(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+HTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="LexOthers.cxx" Content-Disposition: inline; filename="LexOthers.cxx" Content-Length: 44477 Content-Length: 44477 Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Date: Sun, 07 Dec 2025 15:14:01 UTC ETag: "c8f6ca9777a4e39dfec28209b8efc222e68c9a2f" ETag: "c8f6ca9777a4e39dfec28209b8efc222e68c9a2f" Expires: Wed, 05 Dec 2035 15:14:01 GMT Expires: Wed, 05 Dec 2035 15:14:01 GMT Last-Modified: Sun, 07 Dec 2025 15:14:01 GMT Last-Modified: Sun, 07 Dec 2025 15:14:01 GMT Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff // Scintilla source code edit control /** @file LexOthers.cxx ** Lexers for batch files, diff results, properties files, make files and error lists. ** Also lexer for LaTeX documents. **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include "Platform.h" #include "CharClassify.h" #include "PropSet.h" #include "Accessor.h" #include "KeyWords.h" #include "Scintilla.h" #include "SciLexer.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 == '/') || (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(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(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 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)) { // 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[1024]; styler.StartAt(startPos); styler.StartSegment(startPos); unsigned int linePos = 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'; ColouriseDiffLine(lineBuffer, i, styler); linePos = 0; } } if (linePos > 0) { // Last line does not have ending characters 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(startPos) + length > curLineStart); } static void ColourisePoLine( char *lineBuffer, unsigned int lengthLine, unsigned int startLine, unsigned int endPos, Accessor &styler) { unsigned int i = 0; static unsigned int state = SCE_PO_DEFAULT; unsigned int state_start = SCE_PO_DEFAULT; while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces i++; if (i < lengthLine) { if (lineBuffer[i] == '#') { // check if the comment contains any flags ("#, ") and // then whether the flags contain "fuzzy" if (strstart(lineBuffer, "#, ") && strstr(lineBuffer, "fuzzy")) styler.ColourTo(endPos, SCE_PO_FUZZY); else styler.ColourTo(endPos, SCE_PO_COMMENT); } else { if (lineBuffer[0] == '"') { // line continuation, use previous style styler.ColourTo(endPos, state); return; // this implicitly also matches "msgid_plural" } else if (strstart(lineBuffer, "msgid")) { state_start = SCE_PO_MSGID; state = SCE_PO_MSGID_TEXT; } else if (strstart(lineBuffer, "msgstr")) { state_start = SCE_PO_MSGSTR; state = SCE_PO_MSGSTR_TEXT; } else if (strstart(lineBuffer, "msgctxt")) { state_start = SCE_PO_MSGCTXT; state = SCE_PO_MSGCTXT_TEXT; } if (state_start != SCE_PO_DEFAULT) { // find the next space while ((i < lengthLine) && ! isspacechar(lineBuffer[i])) i++; styler.ColourTo(startLine + i - 1, state_start); styler.ColourTo(startLine + i, SCE_PO_DEFAULT); styler.ColourTo(endPos, state); } } } else { styler.ColourTo(endPos, SCE_PO_DEFAULT); } } static void ColourisePoDoc(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'; ColourisePoLine(lineBuffer, linePos, startLine, i, styler); linePos = 0; startLine = i + 1; } } if (linePos > 0) { // Last line does not have ending characters ColourisePoLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); } } 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[startP