mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-31 01:34:58 +02:00
Release 5.5.2 ( https://www.scintilla.org/scintilla552.zip ) Released 21 August 2024. Add SCI_SETCOPYSEPARATOR for separator between parts of a multiple selection when copied to the clipboard. Feature #1530. Add SCI_GETUNDOSEQUENCE to determine whether an undo sequence is active and its nesting depth. Add SCI_STYLESETSTRETCH to support condensed and expanded text styles. Add SCI_LINEINDENT and SCI_LINEDEDENT. Feature #1524. Fix bug on Cocoa where double-click stopped working when system had been running for a long time. On Cocoa implement more values of font weight and stretch. Release 5.4.0 ( https://www.scintilla.org/lexilla540.zip ) Released 21 August 2024. Inside Lexilla, LexerModule instances are now const. This will require changes to applications that modify Lexilla.cxx, which may be done to add custom lexers. Lexer added for TOML "toml". Bash: Handle backslash in heredoc delimiter. Issue #257. Progress: Fix lexing of nested comments. Pull request #258. Force lower-casing of case-insensitive keyword lists so keywords match in some lexers. Issue #259. Close #15564
368 lines
8.7 KiB
C++
368 lines
8.7 KiB
C++
// Scintilla source code edit control
|
|
/** @file LexDMIS.cxx
|
|
** Lexer for DMIS.
|
|
**/
|
|
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
|
|
// Copyright 2013-2014 by Andreas Tscharner <andy@vis.ethz.ch>
|
|
// The License.txt file describes the conditions under which this software may be distributed.
|
|
|
|
|
|
#include <cstdlib>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <cctype>
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include "ILexer.h"
|
|
#include "Scintilla.h"
|
|
#include "SciLexer.h"
|
|
|
|
#include "WordList.h"
|
|
#include "LexAccessor.h"
|
|
#include "StyleContext.h"
|
|
#include "CharacterSet.h"
|
|
#include "LexerModule.h"
|
|
#include "DefaultLexer.h"
|
|
|
|
using namespace Lexilla;
|
|
|
|
|
|
static const char *const DMISWordListDesc[] = {
|
|
"DMIS Major Words",
|
|
"DMIS Minor Words",
|
|
"Unsupported DMIS Major Words",
|
|
"Unsupported DMIS Minor Words",
|
|
"Keywords for code folding start",
|
|
"Corresponding keywords for code folding end",
|
|
0
|
|
};
|
|
|
|
|
|
class LexerDMIS : public DefaultLexer
|
|
{
|
|
private:
|
|
char *m_wordListSets;
|
|
WordList m_majorWords;
|
|
WordList m_minorWords;
|
|
WordList m_unsupportedMajor;
|
|
WordList m_unsupportedMinor;
|
|
WordList m_codeFoldingStart;
|
|
WordList m_codeFoldingEnd;
|
|
|
|
char * SCI_METHOD UpperCase(char *item);
|
|
void SCI_METHOD InitWordListSets(void);
|
|
|
|
public:
|
|
LexerDMIS(void);
|
|
virtual ~LexerDMIS(void);
|
|
|
|
int SCI_METHOD Version() const override {
|
|
return Scintilla::lvRelease5;
|
|
}
|
|
|
|
void SCI_METHOD Release() override {
|
|
delete this;
|
|
}
|
|
|
|
const char * SCI_METHOD PropertyNames() override {
|
|
return NULL;
|
|
}
|
|
|
|
int SCI_METHOD PropertyType(const char *) override {
|
|
return -1;
|
|
}
|
|
|
|
const char * SCI_METHOD DescribeProperty(const char *) override {
|
|
return NULL;
|
|
}
|
|
|
|
Sci_Position SCI_METHOD PropertySet(const char *, const char *) override {
|
|
return -1;
|
|
}
|
|
|
|
const char * SCI_METHOD PropertyGet(const char *) override {
|
|
return NULL;
|
|
}
|
|
|
|
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
|
|
|
|
void * SCI_METHOD PrivateCall(int, void *) override {
|
|
return NULL;
|
|
}
|
|
|
|
static ILexer5 *LexerFactoryDMIS() {
|
|
return new LexerDMIS;
|
|
}
|
|
|
|
const char * SCI_METHOD DescribeWordListSets() override;
|
|
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess) override;
|
|
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess) override;
|
|
};
|
|
|
|
|
|
char * SCI_METHOD LexerDMIS::UpperCase(char *item)
|
|
{
|
|
char *itemStart;
|
|
|
|
|
|
itemStart = item;
|
|
while (item && *item) {
|
|
*item = toupper(*item);
|
|
item++;
|
|
};
|
|
return itemStart;
|
|
}
|
|
|
|
void SCI_METHOD LexerDMIS::InitWordListSets(void)
|
|
{
|
|
size_t totalLen = 0;
|
|
|
|
|
|
for (int i=0; DMISWordListDesc[i]; i++) {
|
|
totalLen += strlen(DMISWordListDesc[i]);
|
|
totalLen++;
|
|
};
|
|
|
|
totalLen++;
|
|
this->m_wordListSets = new char[totalLen];
|
|
memset(this->m_wordListSets, 0, totalLen);
|
|
|
|
for (int i=0; DMISWordListDesc[i]; i++) {
|
|
strcat(this->m_wordListSets, DMISWordListDesc[i]);
|
|
strcat(this->m_wordListSets, "\n");
|
|
};
|
|
}
|
|
|
|
|
|
LexerDMIS::LexerDMIS(void) : DefaultLexer("DMIS", SCLEX_DMIS) {
|
|
this->InitWordListSets();
|
|
|
|
this->m_majorWords.Clear();
|
|
this->m_minorWords.Clear();
|
|
this->m_unsupportedMajor.Clear();
|
|
this->m_unsupportedMinor.Clear();
|
|
this->m_codeFoldingStart.Clear();
|
|
this->m_codeFoldingEnd.Clear();
|
|
}
|
|
|
|
LexerDMIS::~LexerDMIS(void) {
|
|
delete[] this->m_wordListSets;
|
|
}
|
|
|
|
Sci_Position SCI_METHOD LexerDMIS::WordListSet(int n, const char *wl)
|
|
{
|
|
switch (n) {
|
|
case 0:
|
|
this->m_majorWords.Clear();
|
|
this->m_majorWords.Set(wl);
|
|
break;
|
|
case 1:
|
|
this->m_minorWords.Clear();
|
|
this->m_minorWords.Set(wl);
|
|
break;
|
|
case 2:
|
|
this->m_unsupportedMajor.Clear();
|
|
this->m_unsupportedMajor.Set(wl);
|
|
break;
|
|
case 3:
|
|
this->m_unsupportedMinor.Clear();
|
|
this->m_unsupportedMinor.Set(wl);
|
|
break;
|
|
case 4:
|
|
this->m_codeFoldingStart.Clear();
|
|
this->m_codeFoldingStart.Set(wl);
|
|
break;
|
|
case 5:
|
|
this->m_codeFoldingEnd.Clear();
|
|
this->m_codeFoldingEnd.Set(wl);
|
|
break;
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char * SCI_METHOD LexerDMIS::DescribeWordListSets()
|
|
{
|
|
return this->m_wordListSets;
|
|
}
|
|
|
|
void SCI_METHOD LexerDMIS::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, Scintilla::IDocument *pAccess)
|
|
{
|
|
const Sci_PositionU MAX_STR_LEN = 100;
|
|
|
|
LexAccessor styler(pAccess);
|
|
StyleContext scCTX(startPos, lengthDoc, initStyle, styler);
|
|
CharacterSet setDMISNumber(CharacterSet::setDigits, ".-+eE");
|
|
CharacterSet setDMISWordStart(CharacterSet::setAlpha, "-234", 0x80, true);
|
|
CharacterSet setDMISWord(CharacterSet::setAlpha);
|
|
|
|
|
|
bool isIFLine = false;
|
|
|
|
for (; scCTX.More(); scCTX.Forward()) {
|
|
if (scCTX.atLineEnd) {
|
|
isIFLine = false;
|
|
};
|
|
|
|
switch (scCTX.state) {
|
|
case SCE_DMIS_DEFAULT:
|
|
if (scCTX.Match('$', '$')) {
|
|
scCTX.SetState(SCE_DMIS_COMMENT);
|
|
scCTX.Forward();
|
|
};
|
|
if (scCTX.Match('\'')) {
|
|
scCTX.SetState(SCE_DMIS_STRING);
|
|
};
|
|
if (IsADigit(scCTX.ch) || ((scCTX.Match('-') || scCTX.Match('+')) && IsADigit(scCTX.chNext))) {
|
|
scCTX.SetState(SCE_DMIS_NUMBER);
|
|
break;
|
|
};
|
|
if (setDMISWordStart.Contains(scCTX.ch)) {
|
|
scCTX.SetState(SCE_DMIS_KEYWORD);
|
|
};
|
|
if (scCTX.Match('(') && (!isIFLine)) {
|
|
scCTX.SetState(SCE_DMIS_LABEL);
|
|
};
|
|
break;
|
|
|
|
case SCE_DMIS_COMMENT:
|
|
if (scCTX.atLineEnd) {
|
|
scCTX.SetState(SCE_DMIS_DEFAULT);
|
|
};
|
|
break;
|
|
|
|
case SCE_DMIS_STRING:
|
|
if (scCTX.Match('\'')) {
|
|
scCTX.SetState(SCE_DMIS_DEFAULT);
|
|
};
|
|
break;
|
|
|
|
case SCE_DMIS_NUMBER:
|
|
if (!setDMISNumber.Contains(scCTX.ch)) {
|
|
scCTX.SetState(SCE_DMIS_DEFAULT);
|
|
};
|
|
break;
|
|
|
|
case SCE_DMIS_KEYWORD:
|
|
if (!setDMISWord.Contains(scCTX.ch)) {
|
|
char tmpStr[MAX_STR_LEN];
|
|
memset(tmpStr, 0, MAX_STR_LEN*sizeof(char));
|
|
scCTX.GetCurrent(tmpStr, (MAX_STR_LEN-1));
|
|
// The following strncpy is copying from a string back onto itself which is weird and causes warnings
|
|
// but is harmless so turn off the warning
|
|
#if defined(__GNUC__) && !defined(__clang__)
|
|
// Disable warning for strncpy
|
|
#pragma GCC diagnostic ignored "-Wrestrict"
|
|
#endif
|
|
strncpy(tmpStr, this->UpperCase(tmpStr), (MAX_STR_LEN-1));
|
|
|
|
if (this->m_minorWords.InList(tmpStr)) {
|
|
scCTX.ChangeState(SCE_DMIS_MINORWORD);
|
|
};
|
|
if (this->m_majorWords.InList(tmpStr)) {
|
|
isIFLine = (strcmp(tmpStr, "IF") == 0);
|
|
scCTX.ChangeState(SCE_DMIS_MAJORWORD);
|
|
};
|
|
if (this->m_unsupportedMajor.InList(tmpStr)) {
|
|
scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MAJOR);
|
|
};
|
|
if (this->m_unsupportedMinor.InList(tmpStr)) {
|
|
scCTX.ChangeState(SCE_DMIS_UNSUPPORTED_MINOR);
|
|
};
|
|
|
|
if (scCTX.Match('(') && (!isIFLine)) {
|
|
scCTX.SetState(SCE_DMIS_LABEL);
|
|
} else {
|
|
scCTX.SetState(SCE_DMIS_DEFAULT);
|
|
};
|
|
};
|
|
break;
|
|
|
|
case SCE_DMIS_LABEL:
|
|
if (scCTX.Match(')')) {
|
|
scCTX.SetState(SCE_DMIS_DEFAULT);
|
|
};
|
|
break;
|
|
};
|
|
};
|
|
scCTX.Complete();
|
|
}
|
|
|
|
void SCI_METHOD LexerDMIS::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int, Scintilla::IDocument *pAccess)
|
|
{
|
|
const int MAX_STR_LEN = 100;
|
|
|
|
LexAccessor styler(pAccess);
|
|
Sci_PositionU endPos = startPos + lengthDoc;
|
|
char chNext = styler[startPos];
|
|
Sci_Position lineCurrent = styler.GetLine(startPos);
|
|
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
|
int levelCurrent = levelPrev;
|
|
int strPos = 0;
|
|
bool foldWordPossible = false;
|
|
CharacterSet setDMISFoldWord(CharacterSet::setAlpha);
|
|
char *tmpStr;
|
|
|
|
|
|
tmpStr = new char[MAX_STR_LEN];
|
|
memset(tmpStr, 0, MAX_STR_LEN*sizeof(char));
|
|
|
|
for (Sci_PositionU i=startPos; i<endPos; i++) {
|
|
char ch = chNext;
|
|
chNext = styler.SafeGetCharAt(i+1);
|
|
|
|
bool atEOL = ((ch == '\r' && chNext != '\n') || (ch == '\n'));
|
|
|
|
if (strPos >= (MAX_STR_LEN-1)) {
|
|
strPos = MAX_STR_LEN-1;
|
|
};
|
|
|
|
int style = styler.StyleAt(i);
|
|
bool noFoldPos = ((style == SCE_DMIS_COMMENT) || (style == SCE_DMIS_STRING));
|
|
|
|
if (foldWordPossible) {
|
|
if (setDMISFoldWord.Contains(ch)) {
|
|
tmpStr[strPos++] = ch;
|
|
} else {
|
|
tmpStr = this->UpperCase(tmpStr);
|
|
if (this->m_codeFoldingStart.InList(tmpStr) && (!noFoldPos)) {
|
|
levelCurrent++;
|
|
};
|
|
if (this->m_codeFoldingEnd.InList(tmpStr) && (!noFoldPos)) {
|
|
levelCurrent--;
|
|
};
|
|
memset(tmpStr, 0, MAX_STR_LEN*sizeof(char));
|
|
strPos = 0;
|
|
foldWordPossible = false;
|
|
};
|
|
} else {
|
|
if (setDMISFoldWord.Contains(ch)) {
|
|
tmpStr[strPos++] = ch;
|
|
foldWordPossible = true;
|
|
};
|
|
};
|
|
|
|
if (atEOL || (i == (endPos-1))) {
|
|
int lev = levelPrev;
|
|
|
|
if (levelCurrent > levelPrev) {
|
|
lev |= SC_FOLDLEVELHEADERFLAG;
|
|
};
|
|
if (lev != styler.LevelAt(lineCurrent)) {
|
|
styler.SetLevel(lineCurrent, lev);
|
|
};
|
|
lineCurrent++;
|
|
levelPrev = levelCurrent;
|
|
};
|
|
};
|
|
delete[] tmpStr;
|
|
}
|
|
|
|
|
|
extern const LexerModule lmDMIS(SCLEX_DMIS, LexerDMIS::LexerFactoryDMIS, "DMIS", DMISWordListDesc);
|