Christian Grasser e85c354135 Update to scintilla 5.5.7 & Lexilla 5.4.5
Release 5.5.7 (https://www.scintilla.org/scintilla557.zip)

Released 8 June 2025

1. Add SCI_SCROLLVERTICAL method to restore view position and maintain it while performing line wrapping.
2. Add SC_UNDO_SELECTION_HISTORY_SCROLL flag to SCI_SETUNDOSELECTIONHISTORY which controls whether undo and redo restore vertical scroll position.
3. Tweak SC_MARK_BAR to be slightly wider by using next higher whole pixel instead of next lower for margin width / 3.
4. Scale images in autocompletion lists with SCI_AUTOCSETIMAGESCALE to match high DPI screens. Initially only on GTK and Qt.
5. Fix wrapping bug for UTF-8 where \r\n could wrap between the characters. Notepad++ Pull Request #16373.
6. Fix crash during painting when scroll bars changed. Bug #2481.
7. On GTK, reset vertical scroll bar synchronously in SCI_SETDOCPOINTER to fix bug where scroll position not restored in non-wrap mode. Bug #2416.
8. On GTK, fix IME problem when tentative composition interfered with delete surrounding. Feature #1476.
9. On GTK, update IME cursor position inside retrieve surrounding to better position candidate window. Feature #1488.

Release 5.4.5 (https://www.scintilla.org/lexilla545.zip)

Released 8 June 2025

1. Dart: Add error state SCE_DART_STRINGEOL for unterminated string. Pull request #315.
2. Makefile: Add a keyword list to makefile lexer to highlight GNU Make directives like 'ifdef' and 'vpath' as SCE_MAKE_PREPROCESSOR since these are similar to NMAKE directives like '!IFDEF'.
3. Nix: Add error state SCE_NIX_STRINGEOL for unterminated string. Pull request #315.
4. TOML: Add error state SCE_TOML_STRINGEOL for unterminated string. Pull request #315.
5. Zig: Add error state SCE_ZIG_STRINGEOL for unterminated string. Pull request #315.

Close #16649
2025-06-13 15:12:33 +02:00

236 lines
6.7 KiB
C++

// 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 <cstdlib>
#include <cassert>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <cstdarg>
#include <string>
#include <string_view>
#include <map>
#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"
#include "OptionSet.h"
#include "DefaultLexer.h"
using namespace Scintilla;
using namespace Lexilla;
namespace {
// Options used for LexerMakeFile
struct OptionsMake {
};
const char *const makeWordListDescription[] = {
"Directives",
nullptr
};
struct OptionSetMake : public OptionSet<OptionsMake> {
OptionSetMake() {
DefineWordListSets(makeWordListDescription);
}
};
const LexicalClass lexicalClasses[] = {
// Lexer makefile SCLEX_MAKEFILE SCE_MAKE_
0, "SCE_MAKE_DEFAULT", "default", "White space",
1, "SCE_MAKE_COMMENT", "comment", "Comment",
2, "SCE_MAKE_PREPROCESSOR", "preprocessor", "Preprocessor",
3, "SCE_MAKE_IDENTIFIER", "identifier", "Identifiers",
4, "SCE_MAKE_OPERATOR", "operator", "Operator",
5, "SCE_MAKE_TARGET", "identifier", "Identifiers",
9, "SCE_MAKE_IDEOL", "error identifier", "Incomplete identifier reference",
};
bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}
class LexerMakeFile : public DefaultLexer {
WordList directives;
OptionsMake options;
OptionSetMake osMake;
public:
LexerMakeFile() :
DefaultLexer("makefile", SCLEX_MAKEFILE, lexicalClasses, std::size(lexicalClasses)) {
}
const char *SCI_METHOD PropertyNames() override {
return osMake.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osMake.PropertyType(name);
}
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osMake.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char *SCI_METHOD PropertyGet(const char *key) override {
return osMake.PropertyGet(key);
}
const char *SCI_METHOD DescribeWordListSets() override {
return osMake.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
void ColouriseMakeLine(std::string_view lineBuffer,
Sci_PositionU startLine, Sci_PositionU endPos, Accessor &styler);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
static ILexer5 *LexerFactoryMakeFile() {
return new LexerMakeFile();
}
};
Sci_Position SCI_METHOD LexerMakeFile::PropertySet(const char *key, const char *val) {
if (osMake.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerMakeFile::WordListSet(int n, const char *wl) {
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &directives;
break;
default:
break;
}
Sci_Position firstModification = -1;
if (wordListN && wordListN->Set(wl)) {
firstModification = 0;
}
return firstModification;
}
void LexerMakeFile::ColouriseMakeLine(
const std::string_view lineBuffer,
Sci_PositionU startLine,
Sci_PositionU endPos,
Accessor &styler) {
const Sci_PositionU lengthLine = lineBuffer.length();
Sci_PositionU i = 0;
Sci_Position lastNonSpace = -1;
unsigned int state = SCE_MAKE_DEFAULT;
bool bSpecial = false;
// check for a tab character in column 0 indicating a command
const bool bCommand = StartsWith(lineBuffer, '\t');
// 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;
}
if (IsUpperOrLowerCase(lineBuffer[i]) &&
(lineBuffer.find_first_of(":=") == std::string::npos)) {
const std::string_view firstWord(lineBuffer.substr(i));
size_t endWord = 0;
while ((endWord < firstWord.length()) && IsUpperOrLowerCase(firstWord[endWord])) {
endWord++;
}
if (directives.InList(firstWord.substr(0, endWord))) {
styler.ColourTo(startLine + i + endWord - 1, SCE_MAKE_PREPROCESSOR);
i += endWord;
}
}
}
int varCount = 0;
while (i < lengthLine) {
if (lineBuffer.substr(i, 2) == "$(") {
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 && AnyOf(lineBuffer[i], ':', '=')) {
// Three cases:
// : target
// := immediate assignment
// = lazy assignment
const bool colon = lineBuffer[i] == ':';
const bool immediate = colon && ((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=');
const Sci_PositionU lengthOperator = immediate ? 1 : 0;
if (lastNonSpace >= 0) {
const int attribute = (colon && !immediate) ? SCE_MAKE_TARGET : SCE_MAKE_IDENTIFIER;
styler.ColourTo(startLine + lastNonSpace, attribute);
}
styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
styler.ColourTo(startLine + i + lengthOperator, SCE_MAKE_OPERATOR);
bSpecial = true; // Only react to the first ':' or '=' 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);
}
}
void LexerMakeFile::Lex(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, IDocument *pAccess) {
Accessor styler(pAccess, nullptr);
std::string lineBuffer;
styler.StartAt(startPos);
styler.StartSegment(startPos);
Sci_PositionU startLine = startPos;
for (Sci_PositionU i = startPos; i < startPos + length; i++) {
lineBuffer.push_back(styler[i]);
if (AtEOL(styler, i)) {
// End of line (or of line buffer) met, colourise it
ColouriseMakeLine(lineBuffer, startLine, i, styler);
lineBuffer.clear();
startLine = i + 1;
}
}
if (!lineBuffer.empty()) { // Last line does not have ending characters
ColouriseMakeLine(lineBuffer, startLine, startPos + length - 1, styler);
}
styler.Flush();
}
}
extern const LexerModule lmMake(SCLEX_MAKEFILE, LexerMakeFile::LexerFactoryMakeFile, "makefile", makeWordListDescription);