You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
notepad-plus-plus/lexilla/lexers/LexGui4Cli.cxx

316 lines
8.8 KiB

// Scintilla source code edit control
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// @file LexGui4Cli.cxx
/*
This is the Lexer for Gui4Cli, included in SciLexer.dll
- by d. Keletsekis, 2/10/2003
To add to SciLexer.dll:
1. Add the values below to INCLUDE\Scintilla.iface
2. Run the scripts/HFacer.py script
3. Run the scripts/LexGen.py script
val SCE_GC_DEFAULT=0
val SCE_GC_COMMENTLINE=1
val SCE_GC_COMMENTBLOCK=2
val SCE_GC_GLOBAL=3
val SCE_GC_EVENT=4
val SCE_GC_ATTRIBUTE=5
val SCE_GC_CONTROL=6
val SCE_GC_COMMAND=7
val SCE_GC_STRING=8
val SCE_GC_OPERATOR=9
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string>
#include <string_view>
#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"
using namespace Lexilla;
#define debug Platform::DebugPrintf
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
}
inline bool isGCOperator(int ch)
{ if (isalnum(ch))
return false;
// '.' left out as it is used to make up numbers
if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
ch == '(' || ch == ')' || ch == '=' || ch == '%' ||
ch == '[' || ch == ']' || ch == '<' || ch == '>' ||
ch == ',' || ch == ';' || ch == ':')
return true;
return false;
}
#define isSpace(x) ((x)==' ' || (x)=='\t')
#define isNL(x) ((x)=='\n' || (x)=='\r')
#define isSpaceOrNL(x) (isSpace(x) || isNL(x))
#define BUFFSIZE 500
#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
StyleContext *sc, char *buff, Sci_Position length, Sci_Position)
{
Sci_Position c = 0;
while (sc->More() && isSpaceOrNL(sc->ch))
{ sc->Forward();
}
styler.ColourTo(sc->currentPos - 1, sc->state);
if (!IsAWordChar(sc->ch)) // comment, marker, etc..
return;
while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
{ buff[c] = static_cast<char>(sc->ch);
++c; sc->Forward();
}
buff[c] = '\0';
char *p = buff;
while (*p) // capitalize..
{ if (islower(*p)) *p = static_cast<char>(toupper(*p));
++p;
}
WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user
WordList &kEvent = *keywordlists[1];
WordList &kAttribute = *keywordlists[2];
WordList &kControl = *keywordlists[3];
WordList &kCommand = *keywordlists[4];
int state = 0;
// int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
// debug ("line = %d, level = %d", line, level);
if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL;
else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE;
else if (kControl.InList(buff)) state = SCE_GC_CONTROL;
else if (kCommand.InList(buff)) state = SCE_GC_COMMAND;
else if (kEvent.InList(buff)) state = SCE_GC_EVENT;
if (state)
{ sc->ChangeState(state);
styler.ColourTo(sc->currentPos - 1, sc->state);
sc->ChangeState(SCE_GC_DEFAULT);
}
else
{ sc->ChangeState(SCE_GC_DEFAULT);
styler.ColourTo(sc->currentPos - 1, sc->state);
}
}
// Main colorizing function called by Scintilla
static void
ColouriseGui4CliDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *keywordlists[], Accessor &styler)
{
styler.StartAt(startPos);
Sci_Position currentline = styler.GetLine(startPos);
int quotestart = 0, oldstate;
styler.StartSegment(startPos);
bool noforward;
char buff[BUFFSIZE+1]; // buffer for command name
StyleContext sc(startPos, length, initStyle, styler);
buff[0] = '\0'; // cbuff = 0;
if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
while (sc.More())
{ noforward = 0;
switch (sc.ch)
{
case '/':
if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
break;
if (sc.chNext == '/') // line comment
{ sc.SetState (SCE_GC_COMMENTLINE);
sc.Forward();
styler.ColourTo(sc.currentPos, sc.state);
}
else if (sc.chNext == '*') // block comment
{ sc.SetState(SCE_GC_COMMENTBLOCK);
sc.Forward();
styler.ColourTo(sc.currentPos, sc.state);
}
else
styler.ColourTo(sc.currentPos, sc.state);
break;
case '*': // end of comment block, or operator..
if (sc.state == SCE_GC_STRING)
break;
if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
{ sc.Forward();
styler.ColourTo(sc.currentPos, sc.state);
sc.ChangeState (SCE_GC_DEFAULT);
}
else
styler.ColourTo(sc.currentPos, sc.state);
break;
case '\'': case '\"': // strings..
if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
break;
if (sc.state == SCE_GC_STRING)
{ if (sc.ch == quotestart) // match same quote char..
{ styler.ColourTo(sc.currentPos, sc.state);
sc.ChangeState(SCE_GC_DEFAULT);
quotestart = 0;
} }
else
{ styler.ColourTo(sc.currentPos - 1, sc.state);
sc.ChangeState(SCE_GC_STRING);
quotestart = sc.ch;
}
break;
case ';': // end of commandline character
if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
sc.state != SCE_GC_STRING)
{
styler.ColourTo(sc.currentPos - 1, sc.state);
styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
sc.ChangeState(SCE_GC_DEFAULT);
sc.Forward();
colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
noforward = 1; // don't move forward - already positioned at next char..
}
break;
case '+': case '-': case '=': case '!': // operators..
case '<': case '>': case '&': case '|': case '$':
if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
sc.state != SCE_GC_STRING)
{
styler.ColourTo(sc.currentPos - 1, sc.state);
styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
sc.ChangeState(SCE_GC_DEFAULT);
}
break;
case '\\': // escape - same as operator, but also mark in strings..
if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
{
oldstate = sc.state;
styler.ColourTo(sc.currentPos - 1, sc.state);
sc.Forward(); // mark also the next char..
styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
sc.ChangeState(oldstate);
}
break;
case '\n': case '\r':
++currentline;
if (sc.state == SCE_GC_COMMENTLINE)
{ styler.ColourTo(sc.currentPos, sc.state);
sc.ChangeState (SCE_GC_DEFAULT);
}
else if (sc.state != SCE_GC_COMMENTBLOCK)
{ colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
noforward = 1; // don't move forward - already positioned at next char..
}
break;
// case ' ': case '\t':
// default :
}
if (!noforward) sc.Forward();
}
sc.Complete();
}
// Main folding function called by Scintilla - (based on props (.ini) files function)
static void FoldGui4Cli(Sci_PositionU startPos, Sci_Position length, int,
WordList *[], Accessor &styler)
{
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
bool headerPoint = false;
for (Sci_PositionU 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_GC_EVENT || style == SCE_GC_GLOBAL)
{ headerPoint = true; // fold at events and globals
}
if (atEOL)
{ int lev = SC_FOLDLEVELBASE+1;
if (headerPoint)
lev = SC_FOLDLEVELBASE;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (headerPoint)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
{ styler.SetLevel(lineCurrent, lev);
}
lineCurrent++; // re-initialize our flags
visibleChars = 0;
headerPoint = false;
}
if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
visibleChars++;
}
int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, lev | flagsNext);
}
// I have no idea what these are for.. probably accessible by some message.
static const char * const gui4cliWordListDesc[] = {
"Globals", "Events", "Attributes", "Control", "Commands",
0
};
// Declare language & pass our function pointers to Scintilla
extern const LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
#undef debug