Update Scintilla to version 3.3.1
This commit is contained in:
parent
2dd389a14a
commit
e88c03d266
@ -22,6 +22,7 @@ lexers/LexForth.cxx \
|
||||
lexers/LexFortran.cxx \
|
||||
lexers/LexHTML.cxx \
|
||||
lexers/LexHaskell.cxx \
|
||||
lexers/LexLaTeX.cxx \
|
||||
lexers/LexLisp.cxx \
|
||||
lexers/LexLua.cxx \
|
||||
lexers/LexMarkdown.cxx \
|
||||
|
@ -105,9 +105,11 @@ struct LOGFONT {
|
||||
static GMutex *fontMutex = NULL;
|
||||
|
||||
static void InitializeGLIBThreads() {
|
||||
#if !GLIB_CHECK_VERSION(2,31,0)
|
||||
if (!g_thread_supported()) {
|
||||
g_thread_init(NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -115,7 +117,12 @@ static void FontMutexAllocate() {
|
||||
#if USE_LOCK
|
||||
if (!fontMutex) {
|
||||
InitializeGLIBThreads();
|
||||
#if GLIB_CHECK_VERSION(2,31,0)
|
||||
fontMutex = g_new(GMutex, 1);
|
||||
g_mutex_init(fontMutex);
|
||||
#else
|
||||
fontMutex = g_mutex_new();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -123,7 +130,12 @@ static void FontMutexAllocate() {
|
||||
static void FontMutexFree() {
|
||||
#if USE_LOCK
|
||||
if (fontMutex) {
|
||||
#if GLIB_CHECK_VERSION(2,31,0)
|
||||
g_mutex_clear(fontMutex);
|
||||
g_free(fontMutex);
|
||||
#else
|
||||
g_mutex_free(fontMutex);
|
||||
#endif
|
||||
fontMutex = NULL;
|
||||
}
|
||||
#endif
|
||||
@ -143,8 +155,7 @@ static void FontMutexUnlock() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a
|
||||
// PangoFontDescription*.
|
||||
// Holds a PangoFontDescription*.
|
||||
class FontHandle {
|
||||
XYPOSITION width[128];
|
||||
encodingType et;
|
||||
|
@ -296,7 +296,7 @@ private:
|
||||
static gboolean TimeOut(ScintillaGTK *sciThis);
|
||||
static gboolean IdleCallback(ScintillaGTK *sciThis);
|
||||
static gboolean StyleIdle(ScintillaGTK *sciThis);
|
||||
virtual void QueueStyling(int upTo);
|
||||
virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo);
|
||||
static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis);
|
||||
|
||||
#if GTK_CHECK_VERSION(3,0,0)
|
||||
@ -1138,6 +1138,7 @@ void ScintillaGTK::ScrollText(int linesToMove) {
|
||||
//Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
|
||||
// rc.left, rc.top, rc.right, rc.bottom);
|
||||
GtkWidget *wi = PWidget(wText);
|
||||
NotifyUpdateUI();
|
||||
|
||||
if (IS_WIDGET_REALIZED(wi)) {
|
||||
gdk_window_scroll(WindowFromWidget(wi), 0, -diff);
|
||||
@ -2740,7 +2741,9 @@ int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
|
||||
gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
|
||||
// Idler will be automatically stopped, if there is nothing
|
||||
// to do while idle.
|
||||
#ifndef GDK_VERSION_3_6
|
||||
gdk_threads_enter();
|
||||
#endif
|
||||
bool ret = sciThis->Idle();
|
||||
if (ret == false) {
|
||||
// FIXME: This will remove the idler from GTK, we don't want to
|
||||
@ -2748,23 +2751,29 @@ gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
|
||||
// returns false (although, it should be harmless).
|
||||
sciThis->SetIdle(false);
|
||||
}
|
||||
#ifndef GDK_VERSION_3_6
|
||||
gdk_threads_leave();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) {
|
||||
#ifndef GDK_VERSION_3_6
|
||||
gdk_threads_enter();
|
||||
sciThis->IdleStyling();
|
||||
#endif
|
||||
sciThis->IdleWork();
|
||||
#ifndef GDK_VERSION_3_6
|
||||
gdk_threads_leave();
|
||||
#endif
|
||||
// Idler will be automatically stopped
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ScintillaGTK::QueueStyling(int upTo) {
|
||||
Editor::QueueStyling(upTo);
|
||||
if (!styleNeeded.active) {
|
||||
void ScintillaGTK::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
|
||||
Editor::QueueIdleWork(items, upTo);
|
||||
if (!workNeeded.active) {
|
||||
// Only allow one style needed to be queued
|
||||
styleNeeded.active = true;
|
||||
workNeeded.active = true;
|
||||
g_idle_add_full(G_PRIORITY_HIGH_IDLE,
|
||||
reinterpret_cast<GSourceFunc>(StyleIdle), this, NULL);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace Scintilla {
|
||||
#define SCI_METHOD
|
||||
#endif
|
||||
|
||||
enum { dvOriginal=0 };
|
||||
enum { dvOriginal=0, dvLineEnd=1 };
|
||||
|
||||
class IDocument {
|
||||
public:
|
||||
@ -45,7 +45,12 @@ public:
|
||||
virtual int SCI_METHOD GetLineIndentation(int line) = 0;
|
||||
};
|
||||
|
||||
enum { lvOriginal=0 };
|
||||
class IDocumentWithLineEnd : public IDocument {
|
||||
public:
|
||||
virtual int SCI_METHOD LineEnd(int line) const = 0;
|
||||
};
|
||||
|
||||
enum { lvOriginal=0, lvSubStyles=1 };
|
||||
|
||||
class ILexer {
|
||||
public:
|
||||
@ -62,6 +67,18 @@ public:
|
||||
virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0;
|
||||
};
|
||||
|
||||
class ILexerWithSubStyles : public ILexer {
|
||||
public:
|
||||
virtual int SCI_METHOD LineEndTypesSupported() = 0;
|
||||
virtual int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) = 0;
|
||||
virtual int SCI_METHOD SubStylesStart(int styleBase) = 0;
|
||||
virtual int SCI_METHOD SubStylesLength(int styleBase) = 0;
|
||||
virtual void SCI_METHOD FreeSubStyles() = 0;
|
||||
virtual void SCI_METHOD SetIdentifiers(int style, const char *identifiers) = 0;
|
||||
virtual int SCI_METHOD DistanceToSecondaryStyles() = 0;
|
||||
virtual const char * SCI_METHOD GetSubStyleBases() = 0;
|
||||
};
|
||||
|
||||
class ILoader {
|
||||
public:
|
||||
virtual int SCI_METHOD Release() = 0;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define PLAT_WX 0
|
||||
#define PLAT_QT 0
|
||||
#define PLAT_FOX 0
|
||||
#define PLAT_NCURSES 0
|
||||
#define PLAT_CURSES 0
|
||||
|
||||
#if defined(FOX)
|
||||
#undef PLAT_FOX
|
||||
@ -32,9 +32,9 @@
|
||||
#undef PLAT_WX
|
||||
#define PLAT_WX 1
|
||||
|
||||
#elif defined(NCURSES)
|
||||
#undef PLAT_NCURSES
|
||||
#define PLAT_NCURSES 1
|
||||
#elif defined(CURSES)
|
||||
#undef PLAT_CURSES
|
||||
#define PLAT_CURSES 1
|
||||
|
||||
#elif defined(SCINTILLA_QT)
|
||||
#undef PLAT_QT
|
||||
|
@ -477,6 +477,7 @@
|
||||
#define SCE_ERR_TIDY 19
|
||||
#define SCE_ERR_JAVA_STACK 20
|
||||
#define SCE_ERR_VALUE 21
|
||||
#define SCE_ERR_GCC_INCLUDED_FROM 22
|
||||
#define SCE_BAT_DEFAULT 0
|
||||
#define SCE_BAT_COMMENT 1
|
||||
#define SCE_BAT_WORD 2
|
||||
@ -1019,6 +1020,8 @@
|
||||
#define SCE_HA_COMMENTBLOCK 14
|
||||
#define SCE_HA_COMMENTBLOCK2 15
|
||||
#define SCE_HA_COMMENTBLOCK3 16
|
||||
#define SCE_HA_PRAGMA 17
|
||||
#define SCE_HA_PREPROCESSOR 18
|
||||
#define SCE_T3_DEFAULT 0
|
||||
#define SCE_T3_X_DEFAULT 1
|
||||
#define SCE_T3_PREPROCESSOR 2
|
||||
@ -1345,6 +1348,7 @@
|
||||
#define SCE_MYSQL_USER2 19
|
||||
#define SCE_MYSQL_USER3 20
|
||||
#define SCE_MYSQL_HIDDENCOMMAND 21
|
||||
#define SCE_MYSQL_PLACEHOLDER 22
|
||||
#define SCE_PO_DEFAULT 0
|
||||
#define SCE_PO_COMMENT 1
|
||||
#define SCE_PO_MSGID 2
|
||||
|
@ -148,6 +148,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SCI_MARKERDEFINEPIXMAP 2049
|
||||
#define SCI_MARKERADDSET 2466
|
||||
#define SCI_MARKERSETALPHA 2476
|
||||
#define SC_MAX_MARGIN 4
|
||||
#define SC_MARGIN_SYMBOL 0
|
||||
#define SC_MARGIN_NUMBER 1
|
||||
#define SC_MARGIN_BACK 2
|
||||
@ -381,6 +382,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SCI_POSITIONFROMLINE 2167
|
||||
#define SCI_LINESCROLL 2168
|
||||
#define SCI_SCROLLCARET 2169
|
||||
#define SCI_SCROLLRANGE 2569
|
||||
#define SCI_REPLACESEL 2170
|
||||
#define SCI_SETREADONLY 2171
|
||||
#define SCI_NULL 2172
|
||||
@ -696,6 +698,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1
|
||||
#define SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR 2634
|
||||
#define SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR 2635
|
||||
#define SC_ORDER_PRESORTED 0
|
||||
#define SC_ORDER_PERFORMSORT 1
|
||||
#define SC_ORDER_CUSTOM 2
|
||||
#define SCI_AUTOCSETORDER 2660
|
||||
#define SCI_AUTOCGETORDER 2661
|
||||
#define SCI_ALLOCATE 2446
|
||||
#define SCI_TARGETASUTF8 2447
|
||||
#define SCI_SETLENGTHFORENCODE 2448
|
||||
@ -775,6 +782,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SCI_ANNOTATIONGETVISIBLE 2549
|
||||
#define SCI_ANNOTATIONSETSTYLEOFFSET 2550
|
||||
#define SCI_ANNOTATIONGETSTYLEOFFSET 2551
|
||||
#define SCI_RELEASEALLEXTENDEDSTYLES 2552
|
||||
#define SCI_ALLOCATEEXTENDEDSTYLES 2553
|
||||
#define UNDO_MAY_COALESCE 1
|
||||
#define SCI_ADDUNDOACTION 2560
|
||||
#define SCI_CHARPOSITIONFROMPOINT 2561
|
||||
@ -853,6 +862,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SCI_FINDINDICATORHIDE 2642
|
||||
#define SCI_VCHOMEDISPLAY 2652
|
||||
#define SCI_VCHOMEDISPLAYEXTEND 2653
|
||||
#define SCI_GETCARETLINEVISIBLEALWAYS 2654
|
||||
#define SCI_SETCARETLINEVISIBLEALWAYS 2655
|
||||
#define SCI_STARTRECORD 3001
|
||||
#define SCI_STOPRECORD 3002
|
||||
#define SCI_SETLEXER 4001
|
||||
@ -957,6 +968,21 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
|
||||
#define SCN_AUTOCCANCELLED 2025
|
||||
#define SCN_AUTOCCHARDELETED 2026
|
||||
#define SCN_HOTSPOTRELEASECLICK 2027
|
||||
#ifndef SCI_DISABLE_PROVISIONAL
|
||||
#define SC_LINE_END_TYPE_DEFAULT 0
|
||||
#define SC_LINE_END_TYPE_UNICODE 1
|
||||
#define SCI_SETLINEENDTYPESALLOWED 2656
|
||||
#define SCI_GETLINEENDTYPESALLOWED 2657
|
||||
#define SCI_GETLINEENDTYPESACTIVE 2658
|
||||
#define SCI_GETLINEENDTYPESSUPPORTED 4018
|
||||
#define SCI_ALLOCATESUBSTYLES 4020
|
||||
#define SCI_GETSUBSTYLESSTART 4021
|
||||
#define SCI_GETSUBSTYLESLENGTH 4022
|
||||
#define SCI_FREESUBSTYLES 4023
|
||||
#define SCI_SETIDENTIFIERS 4024
|
||||
#define SCI_DISTANCETOSECONDARYSTYLES 4025
|
||||
#define SCI_GETSUBSTYLEBASES 4026
|
||||
#endif
|
||||
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
|
||||
|
||||
/* These structures are defined to be exactly the same shape as the Win32
|
||||
|
@ -326,6 +326,8 @@ fun void MarkerAddSet=2466(int line, int set)
|
||||
# Set the alpha used for a marker that is drawn in the text area, not the margin.
|
||||
set void MarkerSetAlpha=2476(int markerNumber, int alpha)
|
||||
|
||||
val SC_MAX_MARGIN=4
|
||||
|
||||
enu MarginType=SC_MARGIN_
|
||||
val SC_MARGIN_SYMBOL=0
|
||||
val SC_MARGIN_NUMBER=1
|
||||
@ -922,6 +924,11 @@ fun void LineScroll=2168(int columns, int lines)
|
||||
# Ensure the caret is visible.
|
||||
fun void ScrollCaret=2169(,)
|
||||
|
||||
# Scroll the argument positions and the range between them into view giving
|
||||
# priority to the primary position then the secondary position.
|
||||
# This may be used to make a search match visible.
|
||||
fun void ScrollRange=2569(position secondary, position primary)
|
||||
|
||||
# Replace the selected text with the argument text.
|
||||
fun void ReplaceSel=2170(, string text)
|
||||
|
||||
@ -1835,6 +1842,17 @@ set void AutoCSetCaseInsensitiveBehaviour=2634(int behaviour,)
|
||||
# Get auto-completion case insensitive behaviour.
|
||||
get int AutoCGetCaseInsensitiveBehaviour=2635(,)
|
||||
|
||||
enu Ordering=SC_ORDER_
|
||||
val SC_ORDER_PRESORTED=0
|
||||
val SC_ORDER_PERFORMSORT=1
|
||||
val SC_ORDER_CUSTOM=2
|
||||
|
||||
# Set the way autocompletion lists are ordered.
|
||||
set void AutoCSetOrder=2660(int order,)
|
||||
|
||||
# Get the way autocompletion lists are ordered.
|
||||
get int AutoCGetOrder=2661(,)
|
||||
|
||||
# Enlarge the document to a particular size of text bytes.
|
||||
fun void Allocate=2446(int bytes,)
|
||||
|
||||
@ -2062,6 +2080,12 @@ set void AnnotationSetStyleOffset=2550(int style,)
|
||||
# Get the start of the range of style numbers used for annotations
|
||||
get int AnnotationGetStyleOffset=2551(,)
|
||||
|
||||
# Release all extended (>255) style numbers
|
||||
fun void ReleaseAllExtendedStyles=2552(,)
|
||||
|
||||
# Allocate some extended (>255) style numbers and return the start of the range
|
||||
fun int AllocateExtendedStyles=2553(int numberStyles,)
|
||||
|
||||
val UNDO_MAY_COALESCE=1
|
||||
|
||||
# Add a container action to the undo stack
|
||||
@ -2267,6 +2291,12 @@ fun void VCHomeDisplay=2652(,)
|
||||
# Like VCHomeDisplay but extending selection to new caret position.
|
||||
fun void VCHomeDisplayExtend=2653(,)
|
||||
|
||||
# Is the caret line always visible?
|
||||
get bool GetCaretLineVisibleAlways=2654(,)
|
||||
|
||||
# Sets the caret line to always visible.
|
||||
set void SetCaretLineVisibleAlways=2655(bool alwaysVisible,)
|
||||
|
||||
# Start notifying the container of all key presses and commands.
|
||||
fun void StartRecord=3001(,)
|
||||
|
||||
@ -2922,6 +2952,7 @@ val SCE_ERR_ABSF=18
|
||||
val SCE_ERR_TIDY=19
|
||||
val SCE_ERR_JAVA_STACK=20
|
||||
val SCE_ERR_VALUE=21
|
||||
val SCE_ERR_GCC_INCLUDED_FROM=22
|
||||
# Lexical states for SCLEX_BATCH
|
||||
lex Batch=SCLEX_BATCH SCE_BAT_
|
||||
val SCE_BAT_DEFAULT=0
|
||||
@ -3405,6 +3436,7 @@ val SCE_KIX_FUNCTIONS=8
|
||||
val SCE_KIX_OPERATOR=9
|
||||
val SCE_KIX_IDENTIFIER=31
|
||||
# Lexical states for SCLEX_GUI4CLI
|
||||
lex Gui4Cli=SCLEX_GUI4CLI SCE_GC_
|
||||
val SCE_GC_DEFAULT=0
|
||||
val SCE_GC_COMMENTLINE=1
|
||||
val SCE_GC_COMMENTBLOCK=2
|
||||
@ -3549,6 +3581,8 @@ val SCE_HA_COMMENTLINE=13
|
||||
val SCE_HA_COMMENTBLOCK=14
|
||||
val SCE_HA_COMMENTBLOCK2=15
|
||||
val SCE_HA_COMMENTBLOCK3=16
|
||||
val SCE_HA_PRAGMA=17
|
||||
val SCE_HA_PREPROCESSOR=18
|
||||
# Lexical states of SCLEX_TADS3
|
||||
lex TADS3=SCLEX_TADS3 SCE_T3_
|
||||
val SCE_T3_DEFAULT=0
|
||||
@ -3913,6 +3947,7 @@ val SCE_MYSQL_USER1=18
|
||||
val SCE_MYSQL_USER2=19
|
||||
val SCE_MYSQL_USER3=20
|
||||
val SCE_MYSQL_HIDDENCOMMAND=21
|
||||
val SCE_MYSQL_PLACEHOLDER=22
|
||||
# Lexical state for SCLEX_PO
|
||||
lex Po=SCLEX_PO SCE_PO_
|
||||
val SCE_PO_DEFAULT=0
|
||||
@ -4242,6 +4277,50 @@ evt void AutoCCancelled=2025(void)
|
||||
evt void AutoCCharDeleted=2026(void)
|
||||
evt void HotSpotReleaseClick=2027(int modifiers, int position)
|
||||
|
||||
cat Provisional
|
||||
|
||||
# Line end types which may be used in addition to LF, CR, and CRLF
|
||||
# SC_LINE_END_TYPE_UNICODE includes U+2028 Line Separator,
|
||||
# U+2029 Paragraph Separator, and U+0085 Next Line
|
||||
enu LineEndType=SC_LINE_END_TYPE_
|
||||
val SC_LINE_END_TYPE_DEFAULT=0
|
||||
val SC_LINE_END_TYPE_UNICODE=1
|
||||
|
||||
# Set the line end types that the application wants to use. May not be used if incompatible with lexer or encoding.
|
||||
set void SetLineEndTypesAllowed=2656(int lineEndBitSet,)
|
||||
|
||||
# Get the line end types currently allowed.
|
||||
get int GetLineEndTypesAllowed=2657(,)
|
||||
|
||||
# Get the line end types currently recognised. May be a subset of the allowed types due to lexer limitation.
|
||||
get int GetLineEndTypesActive=2658(,)
|
||||
|
||||
# Bit set of LineEndType enumertion for which line ends beyond the standard
|
||||
# LF, CR, and CRLF are supported by the lexer.
|
||||
get int GetLineEndTypesSupported=4018(,)
|
||||
|
||||
# Allocate a set of sub styles for a particular base style, returning start of range
|
||||
fun int AllocateSubStyles=4020(int styleBase, int numberStyles)
|
||||
|
||||
# The starting style number for the sub styles associated with a base style
|
||||
get int GetSubStylesStart=4021(int styleBase,)
|
||||
|
||||
# The number of sub styles associated with a base style
|
||||
get int GetSubStylesLength=4022(int styleBase,)
|
||||
|
||||
# Free allocated sub styles
|
||||
fun void FreeSubStyles=4023(,)
|
||||
|
||||
# Set the identifiers that are shown in a particular style
|
||||
set void SetIdentifiers=4024(int style, string identifiers)
|
||||
|
||||
# Where styles are duplicated by a feature such as active/inactive code
|
||||
# return the distance between the two types.
|
||||
get int DistanceToSecondaryStyles=4025(,)
|
||||
|
||||
# Get the set of base styles that can be extended with sub styles
|
||||
get int GetSubStyleBases=4026(, stringresult styles)
|
||||
|
||||
cat Deprecated
|
||||
|
||||
# Deprecated in 2.21
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "LexerModule.h"
|
||||
#include "OptionSet.h"
|
||||
#include "SparseState.h"
|
||||
#include "SubStyles.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
@ -65,9 +66,8 @@ static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) {
|
||||
int pos = (int) sc.currentPos;
|
||||
int currentLine = styler.GetLine(pos);
|
||||
int lineStartPos = styler.LineStart(currentLine);
|
||||
char ch;
|
||||
while (--pos > lineStartPos) {
|
||||
ch = styler.SafeGetCharAt(pos);
|
||||
char ch = styler.SafeGetCharAt(pos);
|
||||
if (ch != ' ' && ch != '\t') {
|
||||
break;
|
||||
}
|
||||
@ -87,11 +87,15 @@ static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace
|
||||
std::string restOfLine;
|
||||
int i =0;
|
||||
char ch = styler.SafeGetCharAt(start, '\n');
|
||||
while ((ch != '\r') && (ch != '\n')) {
|
||||
int endLine = styler.LineEnd(styler.GetLine(start));
|
||||
while (((start+i) < endLine) && (ch != '\r')) {
|
||||
char chNext = styler.SafeGetCharAt(start + i + 1, '\n');
|
||||
if (ch == '/' && (chNext == '/' || chNext == '*'))
|
||||
break;
|
||||
if (allowSpace || (ch != ' '))
|
||||
restOfLine += ch;
|
||||
i++;
|
||||
ch = styler.SafeGetCharAt(start + i, '\n');
|
||||
ch = chNext;
|
||||
}
|
||||
return restOfLine;
|
||||
}
|
||||
@ -127,8 +131,9 @@ struct PPDefinition {
|
||||
int line;
|
||||
std::string key;
|
||||
std::string value;
|
||||
PPDefinition(int line_, const std::string &key_, const std::string &value_) :
|
||||
line(line_), key(key_), value(value_) {
|
||||
bool isUndef;
|
||||
PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false) :
|
||||
line(line_), key(key_), value(value_), isUndef(isUndef_) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -307,7 +312,9 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> {
|
||||
}
|
||||
};
|
||||
|
||||
class LexerCPP : public ILexer {
|
||||
static const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0};
|
||||
|
||||
class LexerCPP : public ILexerWithSubStyles {
|
||||
bool caseSensitive;
|
||||
CharacterSet setWord;
|
||||
CharacterSet setNegationOp;
|
||||
@ -326,6 +333,8 @@ class LexerCPP : public ILexer {
|
||||
OptionSetCPP osCPP;
|
||||
SparseState<std::string> rawStringTerminators;
|
||||
enum { activeFlag = 0x40 };
|
||||
enum { ssIdentifier, ssDocKeyword };
|
||||
SubStyles subStyles;
|
||||
public:
|
||||
LexerCPP(bool caseSensitive_) :
|
||||
caseSensitive(caseSensitive_),
|
||||
@ -333,7 +342,8 @@ public:
|
||||
setNegationOp(CharacterSet::setNone, "!"),
|
||||
setArithmethicOp(CharacterSet::setNone, "+-/*%"),
|
||||
setRelOp(CharacterSet::setNone, "=!<>"),
|
||||
setLogicalOp(CharacterSet::setNone, "|&") {
|
||||
setLogicalOp(CharacterSet::setNone, "|&"),
|
||||
subStyles(styleSubable, 0x80, 0x40, activeFlag) {
|
||||
}
|
||||
virtual ~LexerCPP() {
|
||||
}
|
||||
@ -341,7 +351,7 @@ public:
|
||||
delete this;
|
||||
}
|
||||
int SCI_METHOD Version() const {
|
||||
return lvOriginal;
|
||||
return lvSubStyles;
|
||||
}
|
||||
const char * SCI_METHOD PropertyNames() {
|
||||
return osCPP.PropertyNames();
|
||||
@ -364,6 +374,32 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SCI_METHOD LineEndTypesSupported() {
|
||||
return SC_LINE_END_TYPE_UNICODE;
|
||||
};
|
||||
|
||||
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
|
||||
return subStyles.Allocate(styleBase, numberStyles);
|
||||
}
|
||||
int SCI_METHOD SubStylesStart(int styleBase) {
|
||||
return subStyles.Start(styleBase);
|
||||
}
|
||||
int SCI_METHOD SubStylesLength(int styleBase) {
|
||||
return subStyles.Length(styleBase);
|
||||
}
|
||||
void SCI_METHOD FreeSubStyles() {
|
||||
subStyles.Free();
|
||||
}
|
||||
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
|
||||
subStyles.SetIdentifiers(style, identifiers);
|
||||
}
|
||||
int SCI_METHOD DistanceToSecondaryStyles() {
|
||||
return activeFlag;
|
||||
}
|
||||
const char * SCI_METHOD GetSubStyleBases() {
|
||||
return styleSubable;
|
||||
}
|
||||
|
||||
static ILexer *LexerFactoryCPP() {
|
||||
return new LexerCPP(true);
|
||||
}
|
||||
@ -457,6 +493,8 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
|
||||
|
||||
CharacterSet setInvalidRawFirst(CharacterSet::setNone, " )\\\t\v\f\n");
|
||||
|
||||
if (options.identifiersAllowDollars) {
|
||||
setWordStart.Add('$');
|
||||
}
|
||||
@ -468,6 +506,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
bool continuationLine = false;
|
||||
bool isIncludePreprocessor = false;
|
||||
bool isStringInPreprocessor = false;
|
||||
bool inRERange = false;
|
||||
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
if ((MaskActive(initStyle) == SCE_C_PREPROCESSOR) ||
|
||||
@ -475,15 +514,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
(MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) {
|
||||
// Set continuationLine if last character of previous line is '\'
|
||||
if (lineCurrent > 0) {
|
||||
int chBack = styler.SafeGetCharAt(startPos-1, 0);
|
||||
int chBack2 = styler.SafeGetCharAt(startPos-2, 0);
|
||||
int lineEndChar = '!';
|
||||
if (chBack2 == '\r' && chBack == '\n') {
|
||||
lineEndChar = styler.SafeGetCharAt(startPos-3, 0);
|
||||
} else if (chBack == '\n' || chBack == '\r') {
|
||||
lineEndChar = chBack2;
|
||||
int endLinePrevious = styler.LineEnd(lineCurrent - 1);
|
||||
if (endLinePrevious > 0) {
|
||||
continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
|
||||
}
|
||||
continuationLine = lineEndChar == '\\';
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,7 +531,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
}
|
||||
}
|
||||
|
||||
StyleContext sc(startPos, length, initStyle, styler, 0x7f);
|
||||
StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(0xff));
|
||||
LinePPState preproc = vlls.ForLine(lineCurrent);
|
||||
|
||||
bool definitionsChanged = false;
|
||||
@ -515,7 +549,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
std::map<std::string, std::string> preprocessorDefinitions = preprocessorDefinitionsStart;
|
||||
for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
|
||||
preprocessorDefinitions[itDef->key] = itDef->value;
|
||||
if (itDef->isUndef)
|
||||
preprocessorDefinitions.erase(itDef->key);
|
||||
else
|
||||
preprocessorDefinitions[itDef->key] = itDef->value;
|
||||
}
|
||||
|
||||
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
|
||||
@ -523,6 +560,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
int activitySet = preproc.IsInactive() ? activeFlag : 0;
|
||||
|
||||
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
|
||||
const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);
|
||||
|
||||
int lineEndNext = styler.LineEnd(lineCurrent);
|
||||
|
||||
for (; sc.More();) {
|
||||
|
||||
if (sc.atLineStart) {
|
||||
@ -541,6 +583,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
visibleChars = 0;
|
||||
lastWordWasUUID = false;
|
||||
isIncludePreprocessor = false;
|
||||
inRERange = false;
|
||||
if (preproc.IsInactive()) {
|
||||
activitySet = activeFlag;
|
||||
sc.SetState(sc.state | activitySet);
|
||||
@ -549,6 +592,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
if (sc.atLineEnd) {
|
||||
lineCurrent++;
|
||||
lineEndNext = styler.LineEnd(lineCurrent);
|
||||
vlls.Add(lineCurrent, preproc);
|
||||
if (rawStringTerminator != "") {
|
||||
rawSTNew.Set(lineCurrent-1, rawStringTerminator);
|
||||
@ -557,11 +601,13 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
// Handle line continuation generically.
|
||||
if (sc.ch == '\\') {
|
||||
if (sc.chNext == '\n' || sc.chNext == '\r') {
|
||||
if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) {
|
||||
lineCurrent++;
|
||||
lineEndNext = styler.LineEnd(lineCurrent);
|
||||
vlls.Add(lineCurrent, preproc);
|
||||
sc.Forward();
|
||||
if (sc.ch == '\r' && sc.chNext == '\n') {
|
||||
// Even in UTF-8, \r and \n are separate
|
||||
sc.Forward();
|
||||
}
|
||||
continuationLine = true;
|
||||
@ -586,7 +632,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
}
|
||||
break;
|
||||
case SCE_C_IDENTIFIER:
|
||||
if (!setWord.Contains(sc.ch) || (sc.ch == '.')) {
|
||||
if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) {
|
||||
char s[1000];
|
||||
if (caseSensitive) {
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
@ -600,11 +646,16 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
sc.ChangeState(SCE_C_WORD2|activitySet);
|
||||
} else if (keywords4.InList(s)) {
|
||||
sc.ChangeState(SCE_C_GLOBALCLASS|activitySet);
|
||||
} else {
|
||||
int subStyle = classifierIdentifiers.ValueFor(s);
|
||||
if (subStyle >= 0) {
|
||||
sc.ChangeState(subStyle|activitySet);
|
||||
}
|
||||
}
|
||||
const bool literalString = sc.ch == '\"';
|
||||
if (literalString || sc.ch == '\'') {
|
||||
size_t lenS = strlen(s);
|
||||
const bool raw = literalString && sc.chPrev == 'R';
|
||||
const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext);
|
||||
if (raw)
|
||||
s[lenS--] = '\0';
|
||||
bool valid =
|
||||
@ -692,8 +743,15 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
} else {
|
||||
sc.GetCurrentLowered(s, sizeof(s));
|
||||
}
|
||||
if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
|
||||
if (!IsASpace(sc.ch)) {
|
||||
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
|
||||
} else if (!keywords3.InList(s + 1)) {
|
||||
int subStyleCDKW = classifierDocKeyWords.ValueFor(s+1);
|
||||
if (subStyleCDKW >= 0) {
|
||||
sc.ChangeState(subStyleCDKW|activitySet);
|
||||
} else {
|
||||
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
|
||||
}
|
||||
}
|
||||
sc.SetState(styleBeforeDCKeyword|activitySet);
|
||||
}
|
||||
@ -745,16 +803,18 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
case SCE_C_REGEX:
|
||||
if (sc.atLineStart) {
|
||||
sc.SetState(SCE_C_DEFAULT|activitySet);
|
||||
} else if (sc.ch == '/') {
|
||||
} else if (! inRERange && sc.ch == '/') {
|
||||
sc.Forward();
|
||||
while ((sc.ch < 0x80) && islower(sc.ch))
|
||||
sc.Forward(); // gobble regex flags
|
||||
sc.SetState(SCE_C_DEFAULT|activitySet);
|
||||
} else if (sc.ch == '\\') {
|
||||
// Gobble up the quoted character
|
||||
if (sc.chNext == '\\' || sc.chNext == '/') {
|
||||
sc.Forward();
|
||||
}
|
||||
} else if (sc.ch == '\\' && (static_cast<int>(sc.currentPos+1) < lineEndNext)) {
|
||||
// Gobble up the escaped character
|
||||
sc.Forward();
|
||||
} else if (sc.ch == '[') {
|
||||
inRERange = true;
|
||||
} else if (sc.ch == ']') {
|
||||
inRERange = false;
|
||||
}
|
||||
break;
|
||||
case SCE_C_STRINGEOL:
|
||||
@ -780,7 +840,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
}
|
||||
break;
|
||||
case SCE_C_UUID:
|
||||
if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
|
||||
if (sc.atLineEnd || sc.ch == ')') {
|
||||
sc.SetState(SCE_C_DEFAULT|activitySet);
|
||||
}
|
||||
}
|
||||
@ -788,6 +848,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
if (sc.atLineEnd && !atLineEndBeforeSwitch) {
|
||||
// State exit processing consumed characters up to end of line.
|
||||
lineCurrent++;
|
||||
lineEndNext = styler.LineEnd(lineCurrent);
|
||||
vlls.Add(lineCurrent, preproc);
|
||||
}
|
||||
|
||||
@ -809,7 +870,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
} else {
|
||||
sc.SetState(SCE_C_NUMBER|activitySet);
|
||||
}
|
||||
} else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
|
||||
} else if (!sc.atLineEnd && (setWordStart.Contains(sc.ch) || (sc.ch == '@'))) {
|
||||
if (lastWordWasUUID) {
|
||||
sc.SetState(SCE_C_UUID|activitySet);
|
||||
lastWordWasUUID = false;
|
||||
@ -835,6 +896,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
&& (!setCouldBePostOp.Contains(chPrevNonWhite)
|
||||
|| !FollowsPostfixOperator(sc, styler))) {
|
||||
sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx
|
||||
inRERange = false;
|
||||
} else if (sc.ch == '\"') {
|
||||
if (sc.chPrev == 'R') {
|
||||
styler.Flush();
|
||||
@ -934,10 +996,22 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sc.Match("undef")) {
|
||||
if (options.updatePreprocessor && !preproc.IsInactive()) {
|
||||
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true);
|
||||
std::vector<std::string> tokens = Tokenize(restOfLine);
|
||||
std::string key;
|
||||
if (tokens.size() >= 1) {
|
||||
key = tokens[0];
|
||||
preprocessorDefinitions.erase(key);
|
||||
ppDefineHistory.push_back(PPDefinition(lineCurrent, key, "", true));
|
||||
definitionsChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isoperator(static_cast<char>(sc.ch))) {
|
||||
} else if (isoperator(sc.ch)) {
|
||||
sc.SetState(SCE_C_OPERATOR|activitySet);
|
||||
}
|
||||
}
|
||||
@ -968,10 +1042,12 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
|
||||
|
||||
unsigned int endPos = startPos + length;
|
||||
int visibleChars = 0;
|
||||
bool inLineComment = false;
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
int levelCurrent = SC_FOLDLEVELBASE;
|
||||
if (lineCurrent > 0)
|
||||
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
|
||||
unsigned int lineStartNext = styler.LineStart(lineCurrent+1);
|
||||
int levelMinCurrent = levelCurrent;
|
||||
int levelNext = levelCurrent;
|
||||
char chNext = styler[startPos];
|
||||
@ -984,11 +1060,13 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
|
||||
int stylePrev = style;
|
||||
style = styleNext;
|
||||
styleNext = MaskActive(styler.StyleAt(i + 1));
|
||||
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
|
||||
if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) {
|
||||
if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) {
|
||||
bool atEOL = i == (lineStartNext-1);
|
||||
if ((style == SCE_C_COMMENTLINE) || (style == SCE_C_COMMENTLINEDOC))
|
||||
inLineComment = true;
|
||||
if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style) && !inLineComment) {
|
||||
if (!IsStreamCommentStyle(stylePrev)) {
|
||||
levelNext++;
|
||||
} else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) {
|
||||
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
|
||||
// Comments don't end at end of line and the next character may be unstyled.
|
||||
levelNext--;
|
||||
}
|
||||
@ -1052,6 +1130,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
lineCurrent++;
|
||||
lineStartNext = styler.LineStart(lineCurrent+1);
|
||||
levelCurrent = levelNext;
|
||||
levelMinCurrent = levelCurrent;
|
||||
if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
|
||||
@ -1059,6 +1138,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
|
||||
styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
|
||||
}
|
||||
visibleChars = 0;
|
||||
inLineComment = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1172,7 +1252,7 @@ bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map<std::s
|
||||
std::vector<std::string> tokens;
|
||||
const char *cp = expr.c_str();
|
||||
for (;;) {
|
||||
if (setWord.Contains(*cp)) {
|
||||
if (setWord.Contains(static_cast<unsigned char>(*cp))) {
|
||||
word += *cp;
|
||||
} else {
|
||||
std::map<std::string, std::string>::const_iterator it = preprocessorDefinitions.find(word);
|
||||
@ -1187,13 +1267,13 @@ bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map<std::s
|
||||
}
|
||||
if ((*cp != ' ') && (*cp != '\t')) {
|
||||
std::string op(cp, 1);
|
||||
if (setRelOp.Contains(*cp)) {
|
||||
if (setRelOp.Contains(cp[1])) {
|
||||
if (setRelOp.Contains(static_cast<unsigned char>(*cp))) {
|
||||
if (setRelOp.Contains(static_cast<unsigned char>(cp[1]))) {
|
||||
op += cp[1];
|
||||
cp++;
|
||||
}
|
||||
} else if (setLogicalOp.Contains(*cp)) {
|
||||
if (setLogicalOp.Contains(cp[1])) {
|
||||
} else if (setLogicalOp.Contains(static_cast<unsigned char>(*cp))) {
|
||||
if (setLogicalOp.Contains(static_cast<unsigned char>(cp[1]))) {
|
||||
op += cp[1];
|
||||
cp++;
|
||||
}
|
||||
|
@ -445,11 +445,6 @@ static int StateForScript(script_type scriptLanguage) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
static inline bool ishtmlwordchar(int ch) {
|
||||
return !isascii(ch) ||
|
||||
(isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#');
|
||||
}
|
||||
|
||||
static inline bool issgmlwordchar(int ch) {
|
||||
return !isascii(ch) ||
|
||||
(isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
|
||||
@ -484,10 +479,6 @@ static bool isLineEnd(int ch) {
|
||||
return ch == '\r' || ch == '\n';
|
||||
}
|
||||
|
||||
static bool isOKBeforeRE(int ch) {
|
||||
return (ch == '(') || (ch == '=') || (ch == ',');
|
||||
}
|
||||
|
||||
static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) {
|
||||
if (strlen(blockType) == 0) {
|
||||
return ((ch == '%') && (chNext == '>'));
|
||||
@ -691,6 +682,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
|
||||
const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
|
||||
const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
|
||||
const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
|
||||
// TODO: also handle + and - (except if they're part of ++ or --) and return keywords
|
||||
const CharacterSet setOKBeforeJSRE(CharacterSet::setNone, "([{=,:;!%^&*|?~");
|
||||
|
||||
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
||||
int levelCurrent = levelPrev;
|
||||
@ -905,7 +898,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
|
||||
!IsScriptCommentState(state)) {
|
||||
beforeLanguage = scriptLanguage;
|
||||
scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP);
|
||||
if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
|
||||
if ((scriptLanguage != eScriptPHP) && (isStringState(state) || (state==SCE_H_COMMENT))) continue;
|
||||
styler.ColourTo(i - 1, StateToPrint);
|
||||
beforePreProc = state;
|
||||
i++;
|
||||
@ -1592,7 +1585,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
|
||||
} else if (ch == '/' && chNext == '/') {
|
||||
styler.ColourTo(i - 1, StateToPrint);
|
||||
state = SCE_HJ_COMMENTLINE;
|
||||
} else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
|
||||
} else if (ch == '/' && setOKBeforeJSRE.Contains(chPrevNonWhite)) {
|
||||
styler.ColourTo(i - 1, StateToPrint);
|
||||
state = SCE_HJ_REGEX;
|
||||
} else if (ch == '\"') {
|
||||
|
@ -9,6 +9,8 @@
|
||||
*
|
||||
* Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com
|
||||
*
|
||||
* Improvements by kudah - kudahkukarek at gmail.com
|
||||
*
|
||||
* TODO:
|
||||
* * Implement a folder :)
|
||||
* * Nice Character-lexing (stuff inside '\''), LexPython has
|
||||
@ -57,22 +59,24 @@ using namespace Scintilla;
|
||||
#define HA_MODE_FFI 5
|
||||
#define HA_MODE_TYPE 6
|
||||
|
||||
static inline bool IsNewline(const int ch) {
|
||||
return (ch == '\n' || ch == '\r');
|
||||
}
|
||||
|
||||
static inline bool IsWhitespace(const int ch) {
|
||||
return ( ch == ' '
|
||||
|| ch == '\t'
|
||||
|| IsNewline(ch) );
|
||||
}
|
||||
|
||||
static inline bool IsAWordStart(const int ch) {
|
||||
return (ch < 0x80) && (isalnum(ch) || ch == '_');
|
||||
return (IsLowerCase(ch) || IsUpperCase(ch) || ch == '_');
|
||||
}
|
||||
|
||||
static inline bool IsAWordChar(const int ch) {
|
||||
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
|
||||
static inline bool IsAWordChar(const int ch, const bool magicHash) {
|
||||
return ( IsAlphaNumeric(ch)
|
||||
|| ch == '_'
|
||||
|| ch == '\''
|
||||
|| (magicHash && ch == '#'));
|
||||
}
|
||||
|
||||
static inline bool IsAnOperatorChar(const int ch) {
|
||||
return
|
||||
( ch == '!' || ch == '#' || ch == '$' || ch == '%'
|
||||
|| ch == '&' || ch == '*' || ch == '+' || ch == '-'
|
||||
|| ch == '.' || ch == '/' || ch == ':' || ch == '<'
|
||||
|| ch == '=' || ch == '>' || ch == '?' || ch == '@'
|
||||
|| ch == '\\' || ch == '^' || ch == '|' || ch == '~');
|
||||
}
|
||||
|
||||
static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
|
||||
@ -81,230 +85,293 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
|
||||
WordList &keywords = *keywordlists[0];
|
||||
WordList &ffi = *keywordlists[1];
|
||||
|
||||
// property lexer.haskell.allow.hash
|
||||
// Set to 1 to allow the # character in identifiers with the haskell lexer.
|
||||
// (GHC -XMagicHash extension)
|
||||
const bool magicHash = styler.GetPropertyInt("lexer.haskell.allow.hash") != 0;
|
||||
const bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
|
||||
|
||||
StyleContext sc(startPos, length, initStyle, styler);
|
||||
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
int state = lineCurrent ? styler.GetLineState(lineCurrent-1)
|
||||
: HA_MODE_DEFAULT;
|
||||
int mode = state & 0xF;
|
||||
int xmode = state >> 4;
|
||||
int xmode = state >> 4; // obscure parameter. Means different things in different modes.
|
||||
|
||||
while (sc.More()) {
|
||||
// Check for state end
|
||||
|
||||
// Operator
|
||||
if (sc.state == SCE_HA_OPERATOR) {
|
||||
if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
|
||||
sc.Forward();
|
||||
} else {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
int style = SCE_HA_OPERATOR;
|
||||
|
||||
if (sc.ch == ':' &&
|
||||
// except "::"
|
||||
!(sc.chNext == ':' && !IsAnOperatorChar(sc.GetRelative(2)))) {
|
||||
style = SCE_HA_CAPITAL;
|
||||
}
|
||||
|
||||
while(IsAnOperatorChar(sc.ch))
|
||||
sc.Forward();
|
||||
|
||||
styler.ColourTo(sc.currentPos - 1, style);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
}
|
||||
// String
|
||||
else if (sc.state == SCE_HA_STRING) {
|
||||
if (sc.ch == '\"') {
|
||||
sc.Forward();
|
||||
styler.ColourTo(sc.currentPos-1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
sc.Forward();
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else if (sc.ch == '\\') {
|
||||
sc.Forward(2);
|
||||
} else if (sc.atLineEnd) {
|
||||
styler.ColourTo(sc.currentPos-1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// Char
|
||||
else if (sc.state == SCE_HA_CHARACTER) {
|
||||
if (sc.ch == '\'') {
|
||||
sc.Forward();
|
||||
styler.ColourTo(sc.currentPos-1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
sc.Forward();
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else if (sc.ch == '\\') {
|
||||
sc.Forward(2);
|
||||
} else if (sc.atLineEnd) {
|
||||
styler.ColourTo(sc.currentPos-1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// Number
|
||||
else if (sc.state == SCE_HA_NUMBER) {
|
||||
if (IsADigit(sc.ch, xmode)) {
|
||||
if (IsADigit(sc.ch, xmode) ||
|
||||
(sc.ch=='.' && IsADigit(sc.chNext, xmode))) {
|
||||
sc.Forward();
|
||||
} else if ((xmode == 10) &&
|
||||
(sc.ch == 'e' || sc.ch == 'E') &&
|
||||
(IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) {
|
||||
sc.Forward();
|
||||
if (sc.ch == '+' || sc.ch == '-')
|
||||
sc.Forward();
|
||||
sc.Forward();
|
||||
if (sc.ch == '+' || sc.ch == '-')
|
||||
sc.Forward();
|
||||
} else {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
}
|
||||
}
|
||||
// Identifier
|
||||
// Keyword or Identifier
|
||||
else if (sc.state == SCE_HA_IDENTIFIER) {
|
||||
if (IsAWordChar(sc.ch)) {
|
||||
sc.Forward();
|
||||
} else {
|
||||
char s[100];
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
int style = sc.state;
|
||||
int new_mode = 0;
|
||||
if (keywords.InList(s)) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
} else if (isupper(s[0])) {
|
||||
if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) {
|
||||
style = SCE_HA_MODULE;
|
||||
new_mode = HA_MODE_IMPORT2;
|
||||
} else if (mode == HA_MODE_MODULE)
|
||||
style = SCE_HA_MODULE;
|
||||
else
|
||||
style = SCE_HA_CAPITAL;
|
||||
} else if (mode == HA_MODE_IMPORT1 &&
|
||||
strcmp(s,"qualified") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_IMPORT1;
|
||||
} else if (mode == HA_MODE_IMPORT2) {
|
||||
if (strcmp(s,"as") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_IMPORT3;
|
||||
} else if (strcmp(s,"hiding") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
}
|
||||
} else if (mode == HA_MODE_FFI) {
|
||||
if (ffi.InList(s)) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_FFI;
|
||||
while (sc.More()) {
|
||||
if (IsAWordChar(sc.ch, magicHash)) {
|
||||
sc.Forward();
|
||||
} else if (xmode == SCE_HA_CAPITAL && sc.ch=='.') {
|
||||
if (isupper(sc.chNext)) {
|
||||
xmode = SCE_HA_CAPITAL;
|
||||
sc.Forward();
|
||||
} else if (IsAWordStart(sc.chNext)) {
|
||||
xmode = SCE_HA_IDENTIFIER;
|
||||
sc.Forward();
|
||||
} else if (IsAnOperatorChar(sc.chNext)) {
|
||||
xmode = SCE_HA_OPERATOR;
|
||||
sc.Forward();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (xmode == SCE_HA_OPERATOR && IsAnOperatorChar(sc.ch)) {
|
||||
sc.Forward();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
else if (mode == HA_MODE_TYPE) {
|
||||
if (strcmp(s,"family") == 0)
|
||||
style = SCE_HA_KEYWORD;
|
||||
}
|
||||
styler.ColourTo(sc.currentPos - 1, style);
|
||||
if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
|
||||
new_mode = HA_MODE_IMPORT1;
|
||||
else if (strcmp(s,"module") == 0)
|
||||
new_mode = HA_MODE_MODULE;
|
||||
else if (strcmp(s,"foreign") == 0)
|
||||
new_mode = HA_MODE_FFI;
|
||||
else if (strcmp(s,"type") == 0)
|
||||
new_mode = HA_MODE_TYPE;
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
mode = new_mode;
|
||||
}
|
||||
|
||||
char s[100];
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
|
||||
int style = xmode;
|
||||
|
||||
int new_mode = HA_MODE_DEFAULT;
|
||||
|
||||
if (keywords.InList(s)) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
} else if (isupper(s[0])) {
|
||||
if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) {
|
||||
style = SCE_HA_MODULE;
|
||||
new_mode = HA_MODE_IMPORT2;
|
||||
} else if (mode == HA_MODE_MODULE) {
|
||||
style = SCE_HA_MODULE;
|
||||
}
|
||||
} else if (mode == HA_MODE_IMPORT1 &&
|
||||
strcmp(s,"qualified") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_IMPORT1;
|
||||
} else if (mode == HA_MODE_IMPORT2) {
|
||||
if (strcmp(s,"as") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_IMPORT3;
|
||||
} else if (strcmp(s,"hiding") == 0) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
}
|
||||
} else if (mode == HA_MODE_TYPE) {
|
||||
if (strcmp(s,"family") == 0)
|
||||
style = SCE_HA_KEYWORD;
|
||||
}
|
||||
|
||||
if (mode == HA_MODE_FFI) {
|
||||
if (ffi.InList(s)) {
|
||||
style = SCE_HA_KEYWORD;
|
||||
new_mode = HA_MODE_FFI;
|
||||
}
|
||||
}
|
||||
|
||||
styler.ColourTo(sc.currentPos - 1, style);
|
||||
|
||||
if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
|
||||
new_mode = HA_MODE_IMPORT1;
|
||||
else if (strcmp(s,"module") == 0)
|
||||
new_mode = HA_MODE_MODULE;
|
||||
else if (strcmp(s,"foreign") == 0)
|
||||
new_mode = HA_MODE_FFI;
|
||||
else if (strcmp(s,"type") == 0
|
||||
|| strcmp(s,"data") == 0)
|
||||
new_mode = HA_MODE_TYPE;
|
||||
|
||||
xmode = 0;
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
mode = new_mode;
|
||||
}
|
||||
|
||||
// Comments
|
||||
// Oneliner
|
||||
else if (sc.state == SCE_HA_COMMENTLINE) {
|
||||
if (sc.atLineEnd) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
if (xmode == 1 && sc.ch != '-') {
|
||||
xmode = 0;
|
||||
if (IsAnOperatorChar(sc.ch))
|
||||
sc.ChangeState(SCE_HA_OPERATOR);
|
||||
} else if (sc.atLineEnd) {
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// Nested
|
||||
else if (sc.state == SCE_HA_COMMENTBLOCK) {
|
||||
if (sc.Match("{-")) {
|
||||
if (sc.Match('{','-')) {
|
||||
sc.Forward(2);
|
||||
xmode++;
|
||||
}
|
||||
else if (sc.Match("-}")) {
|
||||
else if (sc.Match('-','}')) {
|
||||
sc.Forward(2);
|
||||
xmode--;
|
||||
if (xmode == 0) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.ChangeState(SCE_HA_DEFAULT);
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
}
|
||||
} else {
|
||||
if (sc.atLineEnd) {
|
||||
// Remember the line state for future incremental lexing
|
||||
styler.SetLineState(lineCurrent, (xmode << 4) | mode);
|
||||
lineCurrent++;
|
||||
}
|
||||
// Remember the line state for future incremental lexing
|
||||
styler.SetLineState(lineCurrent, (xmode << 4) | mode);
|
||||
lineCurrent++;
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// Pragma
|
||||
else if (sc.state == SCE_HA_PRAGMA) {
|
||||
if (sc.Match("#-}")) {
|
||||
sc.Forward(3);
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// Preprocessor
|
||||
else if (sc.state == SCE_HA_PREPROCESSOR) {
|
||||
if (stylingWithinPreprocessor && !IsAWordStart(sc.ch)) {
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else if (sc.ch == '\\' && !stylingWithinPreprocessor) {
|
||||
sc.Forward(2);
|
||||
} else if (sc.atLineEnd) {
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
// New state?
|
||||
if (sc.state == SCE_HA_DEFAULT) {
|
||||
// Digit
|
||||
if (IsADigit(sc.ch) ||
|
||||
(sc.ch == '.' && IsADigit(sc.chNext)) ||
|
||||
(sc.ch == '-' && IsADigit(sc.chNext))) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.ChangeState(SCE_HA_NUMBER);
|
||||
if (IsADigit(sc.ch)) {
|
||||
sc.SetState(SCE_HA_NUMBER);
|
||||
if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) {
|
||||
// Match anything starting with "0x" or "0X", too
|
||||
sc.Forward(2);
|
||||
xmode = 16;
|
||||
// Match anything starting with "0x" or "0X", too
|
||||
sc.Forward(2);
|
||||
xmode = 16;
|
||||
} else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) {
|
||||
// Match anything starting with "0x" or "0X", too
|
||||
sc.Forward(2);
|
||||
xmode = 8;
|
||||
// Match anything starting with "0x" or "0X", too
|
||||
sc.Forward(2);
|
||||
xmode = 8;
|
||||
} else {
|
||||
sc.Forward();
|
||||
xmode = 10;
|
||||
}
|
||||
sc.Forward();
|
||||
xmode = 10;
|
||||
}
|
||||
mode = HA_MODE_DEFAULT;
|
||||
}
|
||||
// Comment line
|
||||
else if (sc.Match("--")) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.Forward(2);
|
||||
sc.ChangeState(SCE_HA_COMMENTLINE);
|
||||
// Comment block
|
||||
// Pragma
|
||||
else if (sc.Match("{-#")) {
|
||||
sc.SetState(SCE_HA_PRAGMA);
|
||||
sc.Forward(3);
|
||||
}
|
||||
else if (sc.Match("{-")) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
// Comment line
|
||||
else if (sc.Match('-','-')) {
|
||||
sc.SetState(SCE_HA_COMMENTLINE);
|
||||
sc.Forward(2);
|
||||
xmode = 1;
|
||||
}
|
||||
// Comment block
|
||||
else if (sc.Match('{','-')) {
|
||||
sc.SetState(SCE_HA_COMMENTBLOCK);
|
||||
sc.Forward(2);
|
||||
sc.ChangeState(SCE_HA_COMMENTBLOCK);
|
||||
xmode = 1;
|
||||
}
|
||||
// String
|
||||
else if (sc.Match('\"')) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.SetState(SCE_HA_STRING);
|
||||
sc.Forward();
|
||||
sc.ChangeState(SCE_HA_STRING);
|
||||
}
|
||||
// Character
|
||||
else if (sc.Match('\'')) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.SetState(SCE_HA_CHARACTER);
|
||||
sc.Forward();
|
||||
sc.ChangeState(SCE_HA_CHARACTER);
|
||||
}
|
||||
else if (sc.ch == '(' || sc.ch == ')' ||
|
||||
sc.ch == '{' || sc.ch == '}' ||
|
||||
sc.ch == '[' || sc.ch == ']') {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.Forward();
|
||||
styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR);
|
||||
mode = HA_MODE_DEFAULT;
|
||||
}
|
||||
// Operator
|
||||
else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.Forward();
|
||||
sc.ChangeState(SCE_HA_OPERATOR);
|
||||
// Preprocessor
|
||||
else if (sc.atLineStart && sc.ch == '#') {
|
||||
mode = HA_MODE_DEFAULT;
|
||||
}
|
||||
// Keyword
|
||||
else if (IsAWordStart(sc.ch)) {
|
||||
styler.ColourTo(sc.currentPos - 1, sc.state);
|
||||
sc.SetState(SCE_HA_PREPROCESSOR);
|
||||
sc.Forward();
|
||||
}
|
||||
// Operator
|
||||
else if (IsAnOperatorChar(sc.ch)) {
|
||||
mode = HA_MODE_DEFAULT;
|
||||
sc.SetState(SCE_HA_OPERATOR);
|
||||
}
|
||||
// Braces and punctuation
|
||||
else if (sc.ch == ',' || sc.ch == ';'
|
||||
|| sc.ch == '(' || sc.ch == ')'
|
||||
|| sc.ch == '[' || sc.ch == ']'
|
||||
|| sc.ch == '{' || sc.ch == '}') {
|
||||
sc.SetState(SCE_HA_OPERATOR);
|
||||
sc.Forward();
|
||||
sc.SetState(SCE_HA_DEFAULT);
|
||||
}
|
||||
// Keyword or Identifier
|
||||
else if (IsAWordStart(sc.ch)) {
|
||||
xmode = isupper(sc.ch) ? SCE_HA_CAPITAL : SCE_HA_IDENTIFIER;
|
||||
sc.SetState(SCE_HA_IDENTIFIER);
|
||||
sc.Forward();
|
||||
sc.ChangeState(SCE_HA_IDENTIFIER);
|
||||
} else {
|
||||
if (sc.atLineEnd) {
|
||||
// Remember the line state for future incremental lexing
|
||||
styler.SetLineState(lineCurrent, (xmode << 4) | mode);
|
||||
lineCurrent++;
|
||||
}
|
||||
// Remember the line state for future incremental lexing
|
||||
styler.SetLineState(lineCurrent, (xmode << 4) | mode);
|
||||
lineCurrent++;
|
||||
}
|
||||
sc.Forward();
|
||||
}
|
||||
}
|
||||
|
539
scintilla/lexers/LexLaTeX.cxx
Normal file
539
scintilla/lexers/LexLaTeX.cxx
Normal file
@ -0,0 +1,539 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexLaTeX.cxx
|
||||
** Lexer for LaTeX2e.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
// Modified by G. HU in 2013. Added folding, syntax highting inside math environments, and changed some minor behaviors.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <vector>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
#include "LexerBase.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct latexFoldSave {
|
||||
latexFoldSave() : structLev(0) {
|
||||
for (int i = 0; i < 8; ++i) openBegins[i] = 0;
|
||||
}
|
||||
latexFoldSave(const latexFoldSave &save) : structLev(save.structLev) {
|
||||
for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i];
|
||||
}
|
||||
int openBegins[8];
|
||||
int structLev;
|
||||
};
|
||||
|
||||
class LexerLaTeX : public LexerBase {
|
||||
private:
|
||||
vector<int> modes;
|
||||
void setMode(int line, int mode) {
|
||||
if (line >= static_cast<int>(modes.size())) modes.resize(line + 1, 0);
|
||||
modes[line] = mode;
|
||||
}
|
||||
int getMode(int line) {
|
||||
if (line >= 0 && line < static_cast<int>(modes.size())) return modes[line];
|
||||
return 0;
|
||||
}
|
||||
void truncModes(int numLines) {
|
||||
if (static_cast<int>(modes.size()) > numLines * 2 + 256)
|
||||
modes.resize(numLines + 128);
|
||||
}
|
||||
|
||||
vector<latexFoldSave> saves;
|
||||
void setSave(int line, const latexFoldSave &save) {
|
||||
if (line >= static_cast<int>(saves.size())) saves.resize(line + 1);
|
||||
saves[line] = save;
|
||||
}
|
||||
void getSave(int line, latexFoldSave &save) {
|
||||
if (line >= 0 && line < static_cast<int>(saves.size())) save = saves[line];
|
||||
else {
|
||||
save.structLev = 0;
|
||||
for (int i = 0; i < 8; ++i) save.openBegins[i] = 0;
|
||||
}
|
||||
}
|
||||
void truncSaves(int numLines) {
|
||||
if (static_cast<int>(saves.size()) > numLines * 2 + 256)
|
||||
saves.resize(numLines + 128);
|
||||
}
|
||||
public:
|
||||
static ILexer *LexerFactoryLaTeX() {
|
||||
return new LexerLaTeX();
|
||||
}
|
||||
void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
|
||||
void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
|
||||
};
|
||||
|
||||
static bool latexIsSpecial(int ch) {
|
||||
return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') ||
|
||||
(ch == '{') || (ch == '}') || (ch == ' ');
|
||||
}
|
||||
|
||||
static bool latexIsBlank(int ch) {
|
||||
return (ch == ' ') || (ch == '\t');
|
||||
}
|
||||
|
||||
static bool latexIsBlankAndNL(int ch) {
|
||||
return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
|
||||
}
|
||||
|
||||
static bool latexIsLetter(int ch) {
|
||||
return isascii(ch) && isalpha(ch);
|
||||
}
|
||||
|
||||
static bool latexIsTagValid(int &i, int l, Accessor &styler) {
|
||||
while (i < l) {
|
||||
if (styler.SafeGetCharAt(i) == '{') {
|
||||
while (i < l) {
|
||||
i++;
|
||||
if (styler.SafeGetCharAt(i) == '}') {
|
||||
return true;
|
||||
} else if (!latexIsLetter(styler.SafeGetCharAt(i)) &&
|
||||
styler.SafeGetCharAt(i)!='*') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (!latexIsBlank(styler.SafeGetCharAt(i))) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool latexNextNotBlankIs(int i, Accessor &styler, char needle) {
|
||||
char ch;
|
||||
while (i < styler.Length()) {
|
||||
ch = styler.SafeGetCharAt(i);
|
||||
if (!latexIsBlankAndNL(ch) && ch != '*') {
|
||||
if (ch == needle)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool latexLastWordIs(int start, Accessor &styler, const char *needle) {
|
||||
unsigned int i = 0;
|
||||
unsigned int l = static_cast<unsigned int>(strlen(needle));
|
||||
int ini = start-l+1;
|
||||
char s[32];
|
||||
|
||||
while (i < l && i < 31) {
|
||||
s[i] = styler.SafeGetCharAt(ini + i);
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
|
||||
return (strcmp(s, needle) == 0);
|
||||
}
|
||||
|
||||
static bool latexLastWordIsMathEnv(int pos, Accessor &styler) {
|
||||
int i, j;
|
||||
char s[32];
|
||||
const char *mathEnvs[] = { "align", "alignat", "flalign", "gather",
|
||||
"multiline", "displaymath", "eqnarray", "equation" };
|
||||
if (styler.SafeGetCharAt(pos) != '}') return false;
|
||||
for (i = pos - 1; i >= 0; --i) {
|
||||
if (styler.SafeGetCharAt(i) == '{') break;
|
||||
if (pos - i >= 20) return false;
|
||||
}
|
||||
if (i < 0 || i == pos - 1) return false;
|
||||
++i;
|
||||
for (j = 0; i + j < pos; ++j)
|
||||
s[j] = styler.SafeGetCharAt(i + j);
|
||||
s[j] = '\0';
|
||||
if (j == 0) return false;
|
||||
if (s[j - 1] == '*') s[--j] = '\0';
|
||||
for (i = 0; i < static_cast<int>(sizeof(mathEnvs) / sizeof(const char *)); ++i)
|
||||
if (strcmp(s, mathEnvs[i]) == 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void latexStateReset(int &mode, int &state) {
|
||||
switch (mode) {
|
||||
case 1: state = SCE_L_MATH; break;
|
||||
case 2: state = SCE_L_MATH2; break;
|
||||
default: state = SCE_L_DEFAULT; break;
|
||||
}
|
||||
}
|
||||
|
||||
// There are cases not handled correctly, like $abcd\textrm{what is $x+y$}z+w$.
|
||||
// But I think it's already good enough.
|
||||
void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
|
||||
// startPos is assumed to be the first character of a line
|
||||
Accessor styler(pAccess, &props);
|
||||
styler.StartAt(startPos);
|
||||
int mode = getMode(styler.GetLine(startPos) - 1);
|
||||
int state = initStyle;
|
||||
if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL) // should not happen
|
||||
latexStateReset(mode, state);
|
||||
|
||||
char chNext = styler.SafeGetCharAt(startPos);
|
||||
char chVerbatimDelim = '\0';
|
||||
styler.StartSegment(startPos);
|
||||
int lengthDoc = startPos + length;
|
||||
|
||||
for (int i = startPos; i < lengthDoc; i++) {
|
||||
char ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
|
||||
if (styler.IsLeadByte(ch)) {
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '\r' || ch == '\n')
|
||||
setMode(styler.GetLine(i), mode);
|
||||
|
||||
switch (state) {
|
||||
case SCE_L_DEFAULT :
|
||||
switch (ch) {
|
||||
case '\\' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (latexIsLetter(chNext)) {
|
||||
state = SCE_L_COMMAND;
|
||||
} else if (latexIsSpecial(chNext)) {
|
||||
styler.ColourTo(i + 1, SCE_L_SPECIAL);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
} else if (chNext == '\r' || chNext == '\n') {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
} else {
|
||||
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
|
||||
if (chNext == '(') {
|
||||
mode = 1;
|
||||
state = SCE_L_MATH;
|
||||
} else if (chNext == '[') {
|
||||
mode = 2;
|
||||
state = SCE_L_MATH2;
|
||||
}
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
}
|
||||
break;
|
||||
case '$' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (chNext == '$') {
|
||||
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
|
||||
mode = 2;
|
||||
state = SCE_L_MATH2;
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
} else {
|
||||
styler.ColourTo(i, SCE_L_SHORTCMD);
|
||||
mode = 1;
|
||||
state = SCE_L_MATH;
|
||||
}
|
||||
break;
|
||||
case '%' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMENT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// These 3 will never be reached.
|
||||
case SCE_L_ERROR:
|
||||
case SCE_L_SPECIAL:
|
||||
case SCE_L_SHORTCMD:
|
||||
break;
|
||||
case SCE_L_COMMAND :
|
||||
if (!latexIsLetter(chNext)) {
|
||||
styler.ColourTo(i, state);
|
||||
if (latexNextNotBlankIs(i + 1, styler, '[' )) {
|
||||
state = SCE_L_CMDOPT;
|
||||
} else if (latexLastWordIs(i, styler, "\\begin")) {
|
||||
state = SCE_L_TAG;
|
||||
} else if (latexLastWordIs(i, styler, "\\end")) {
|
||||
state = SCE_L_TAG2;
|
||||
} else if (latexLastWordIs(i, styler, "\\verb") && chNext != '*' && chNext != ' ') {
|
||||
chVerbatimDelim = chNext;
|
||||
state = SCE_L_VERBATIM;
|
||||
} else {
|
||||
latexStateReset(mode, state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCE_L_CMDOPT :
|
||||
if (ch == ']') {
|
||||
styler.ColourTo(i, state);
|
||||
latexStateReset(mode, state);
|
||||
}
|
||||
break;
|
||||
case SCE_L_TAG :
|
||||
if (latexIsTagValid(i, lengthDoc, styler)) {
|
||||
styler.ColourTo(i, state);
|
||||
latexStateReset(mode, state);
|
||||
if (latexLastWordIs(i, styler, "{verbatim}")) {
|
||||
state = SCE_L_VERBATIM;
|
||||
} else if (latexLastWordIs(i, styler, "{comment}")) {
|
||||
state = SCE_L_COMMENT2;
|
||||
} else if (latexLastWordIs(i, styler, "{math}") && mode == 0) {
|
||||
mode = 1;
|
||||
state = SCE_L_MATH;
|
||||
} else if (latexLastWordIsMathEnv(i, styler) && mode == 0) {
|
||||
mode = 2;
|
||||
state = SCE_L_MATH2;
|
||||
}
|
||||
} else {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
latexStateReset(mode, state);
|
||||
ch = styler.SafeGetCharAt(i);
|
||||
if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
|
||||
}
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
break;
|
||||
case SCE_L_TAG2 :
|
||||
if (latexIsTagValid(i, lengthDoc, styler)) {
|
||||
styler.ColourTo(i, state);
|
||||
latexStateReset(mode, state);
|
||||
} else {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
latexStateReset(mode, state);
|
||||
ch = styler.SafeGetCharAt(i);
|
||||
if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
|
||||
}
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
break;
|
||||
case SCE_L_MATH :
|
||||
switch (ch) {
|
||||
case '\\' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (latexIsLetter(chNext)) {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{math}"))
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
state = SCE_L_COMMAND;
|
||||
} else if (latexIsSpecial(chNext)) {
|
||||
styler.ColourTo(i + 1, SCE_L_SPECIAL);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
} else if (chNext == '\r' || chNext == '\n') {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
} else {
|
||||
if (chNext == ')') {
|
||||
mode = 0;
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
}
|
||||
break;
|
||||
case '$' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
styler.ColourTo(i, SCE_L_SHORTCMD);
|
||||
mode = 0;
|
||||
state = SCE_L_DEFAULT;
|
||||
break;
|
||||
case '%' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMENT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCE_L_MATH2 :
|
||||
switch (ch) {
|
||||
case '\\' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (latexIsLetter(chNext)) {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIsMathEnv(match, styler))
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
state = SCE_L_COMMAND;
|
||||
} else if (latexIsSpecial(chNext)) {
|
||||
styler.ColourTo(i + 1, SCE_L_SPECIAL);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
} else if (chNext == '\r' || chNext == '\n') {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
} else {
|
||||
if (chNext == ']') {
|
||||
mode = 0;
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
}
|
||||
break;
|
||||
case '$' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (chNext == '$') {
|
||||
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
mode = 0;
|
||||
state = SCE_L_DEFAULT;
|
||||
} else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation}
|
||||
styler.ColourTo(i, SCE_L_SHORTCMD);
|
||||
}
|
||||
break;
|
||||
case '%' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMENT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCE_L_COMMENT :
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
styler.ColourTo(i - 1, state);
|
||||
latexStateReset(mode, state);
|
||||
}
|
||||
break;
|
||||
case SCE_L_COMMENT2 :
|
||||
if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{comment}")) {
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCE_L_VERBATIM :
|
||||
if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{verbatim}")) {
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (chNext == chVerbatimDelim) {
|
||||
styler.ColourTo(i + 1, state);
|
||||
latexStateReset(mode, state);
|
||||
chVerbatimDelim = '\0';
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
} else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
latexStateReset(mode, state);
|
||||
chVerbatimDelim = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lengthDoc == styler.Length()) truncModes(styler.GetLine(lengthDoc - 1));
|
||||
styler.ColourTo(lengthDoc - 1, state);
|
||||
styler.Flush();
|
||||
}
|
||||
|
||||
static int latexFoldSaveToInt(const latexFoldSave &save) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i <= save.structLev; ++i)
|
||||
sum += save.openBegins[i];
|
||||
return ((sum + save.structLev + SC_FOLDLEVELBASE) & SC_FOLDLEVELNUMBERMASK);
|
||||
}
|
||||
|
||||
// Change folding state while processing a line
|
||||
// Return the level before the first relevant command
|
||||
void SCI_METHOD LexerLaTeX::Fold(unsigned int startPos, int length, int, IDocument *pAccess) {
|
||||
const char *structWords[7] = {"part", "chapter", "section", "subsection",
|
||||
"subsubsection", "paragraph", "subparagraph"};
|
||||
Accessor styler(pAccess, &props);
|
||||
unsigned int endPos = startPos + length;
|
||||
int curLine = styler.GetLine(startPos);
|
||||
latexFoldSave save;
|
||||
getSave(curLine - 1, save);
|
||||
do {
|
||||
char ch, buf[16];
|
||||
int i, j, lev = -1;
|
||||
bool needFold = false;
|
||||
for (i = static_cast<int>(startPos); i < static_cast<int>(endPos); ++i) {
|
||||
ch = styler.SafeGetCharAt(i);
|
||||
if (ch == '\r' || ch == '\n') break;
|
||||
if (ch != '\\' || styler.StyleAt(i) != SCE_L_COMMAND) continue;
|
||||
for (j = 0; j < 15 && i + 1 < static_cast<int>(endPos); ++j, ++i) {
|
||||
buf[j] = styler.SafeGetCharAt(i + 1);
|
||||
if (!latexIsLetter(buf[j])) break;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
if (strcmp(buf, "begin") == 0) {
|
||||
if (lev < 0) lev = latexFoldSaveToInt(save);
|
||||
++save.openBegins[save.structLev];
|
||||
needFold = true;
|
||||
}
|
||||
else if (strcmp(buf, "end") == 0) {
|
||||
while (save.structLev > 0 && save.openBegins[save.structLev] == 0)
|
||||
--save.structLev;
|
||||
if (lev < 0) lev = latexFoldSaveToInt(save);
|
||||
if (save.openBegins[save.structLev] > 0) --save.openBegins[save.structLev];
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < 7; ++j)
|
||||
if (strcmp(buf, structWords[j]) == 0) break;
|
||||
if (j >= 7) continue;
|
||||
save.structLev = j; // level before the command
|
||||
for (j = save.structLev + 1; j < 8; ++j) {
|
||||
save.openBegins[save.structLev] += save.openBegins[j];
|
||||
save.openBegins[j] = 0;
|
||||
}
|
||||
if (lev < 0) lev = latexFoldSaveToInt(save);
|
||||
++save.structLev; // level after the command
|
||||
needFold = true;
|
||||
}
|
||||
}
|
||||
if (lev < 0) lev = latexFoldSaveToInt(save);
|
||||
if (needFold) lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
styler.SetLevel(curLine, lev);
|
||||
setSave(curLine, save);
|
||||
++curLine;
|
||||
startPos = styler.LineStart(curLine);
|
||||
if (static_cast<int>(startPos) == styler.Length()) {
|
||||
lev = latexFoldSaveToInt(save);
|
||||
styler.SetLevel(curLine, lev);
|
||||
setSave(curLine, save);
|
||||
truncSaves(curLine);
|
||||
}
|
||||
} while (startPos < endPos);
|
||||
styler.Flush();
|
||||
}
|
||||
|
||||
static const char *const emptyWordListDesc[] = {
|
||||
0
|
||||
};
|
||||
|
||||
LexerModule lmLatex(SCLEX_LATEX, LexerLaTeX::LexerFactoryLaTeX, "latex", emptyWordListDesc);
|
@ -6,6 +6,12 @@
|
||||
** Changes by Christoph Dalitz 2003/12/04:
|
||||
** - added support for Octave
|
||||
** - Strings can now be included both in single or double quotes
|
||||
**
|
||||
** Changes by John Donoghue 2012/04/02
|
||||
** - added block comment (and nested block comments)
|
||||
** - added ... displayed as a comment
|
||||
** - removed unused IsAWord functions
|
||||
** - added some comments
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
@ -48,14 +54,6 @@ static bool IsOctaveComment(Accessor &styler, int pos, int len) {
|
||||
return len > 0 && IsOctaveCommentChar(styler[pos]) ;
|
||||
}
|
||||
|
||||
static inline bool IsAWordChar(const int ch) {
|
||||
return (ch < 0x80) && (isalnum(ch) || ch == '_');
|
||||
}
|
||||
|
||||
static inline bool IsAWordStart(const int ch) {
|
||||
return (ch < 0x80) && (isalnum(ch) || ch == '_');
|
||||
}
|
||||
|
||||
static void ColouriseMatlabOctaveDoc(
|
||||
unsigned int startPos, int length, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler,
|
||||
@ -65,12 +63,41 @@ static void ColouriseMatlabOctaveDoc(
|
||||
|
||||
styler.StartAt(startPos);
|
||||
|
||||
// boolean for when the ' is allowed to be transpose vs the start/end
|
||||
// of a string
|
||||
bool transpose = false;
|
||||
|
||||
// approximate position of first non space character in a line
|
||||
int nonSpaceColumn = -1;
|
||||
// approximate column position of the current character in a line
|
||||
int column = 0;
|
||||
|
||||
// use the line state of each line to store the block comment depth
|
||||
int curLine = styler.GetLine(startPos);
|
||||
int commentDepth = curLine > 0 ? styler.GetLineState(curLine-1) : 0;
|
||||
|
||||
|
||||
StyleContext sc(startPos, length, initStyle, styler);
|
||||
|
||||
for (; sc.More(); sc.Forward()) {
|
||||
for (; sc.More(); sc.Forward(), column++) {
|
||||
|
||||
if(sc.atLineStart) {
|
||||
// set the line state to the current commentDepth
|
||||
curLine = styler.GetLine(sc.currentPos);
|
||||
styler.SetLineState(curLine, commentDepth);
|
||||
|
||||
// reset the column to 0, nonSpace to -1 (not set)
|
||||
column = 0;
|
||||
nonSpaceColumn = -1;
|
||||
}
|
||||
|
||||
// save the column position of first non space character in a line
|
||||
if((nonSpaceColumn == -1) && (! IsASpace(sc.ch)))
|
||||
{
|
||||
nonSpaceColumn = column;
|
||||
}
|
||||
|
||||
// check for end of states
|
||||
if (sc.state == SCE_MATLAB_OPERATOR) {
|
||||
if (sc.chPrev == '.') {
|
||||
if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
|
||||
@ -79,6 +106,10 @@ static void ColouriseMatlabOctaveDoc(
|
||||
} else if (sc.ch == '\'') {
|
||||
sc.ForwardSetState(SCE_MATLAB_DEFAULT);
|
||||
transpose = true;
|
||||
} else if(sc.ch == '.' && sc.chNext == '.') {
|
||||
// we werent an operator, but a '...'
|
||||
sc.ChangeState(SCE_MATLAB_COMMENT);
|
||||
transpose = false;
|
||||
} else {
|
||||
sc.SetState(SCE_MATLAB_DEFAULT);
|
||||
}
|
||||
@ -121,15 +152,51 @@ static void ColouriseMatlabOctaveDoc(
|
||||
} else if (sc.ch == '\"') {
|
||||
sc.ForwardSetState(SCE_MATLAB_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) {
|
||||
} else if (sc.state == SCE_MATLAB_COMMAND) {
|
||||
if (sc.atLineEnd) {
|
||||
sc.SetState(SCE_MATLAB_DEFAULT);
|
||||
transpose = false;
|
||||
}
|
||||
} else if (sc.state == SCE_MATLAB_COMMENT) {
|
||||
// end or start of a nested a block comment?
|
||||
if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) {
|
||||
if(commentDepth > 0) commentDepth --;
|
||||
|
||||
curLine = styler.GetLine(sc.currentPos);
|
||||
styler.SetLineState(curLine, commentDepth);
|
||||
sc.Forward();
|
||||
|
||||
if (commentDepth == 0) {
|
||||
sc.ForwardSetState(SCE_D_DEFAULT);
|
||||
transpose = false;
|
||||
}
|
||||
}
|
||||
else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column)
|
||||
{
|
||||
commentDepth ++;
|
||||
|
||||
curLine = styler.GetLine(sc.currentPos);
|
||||
styler.SetLineState(curLine, commentDepth);
|
||||
sc.Forward();
|
||||
transpose = false;
|
||||
|
||||
} else if(commentDepth == 0) {
|
||||
// single line comment
|
||||
if (sc.atLineEnd || sc.ch == '\r' || sc.ch == '\n') {
|
||||
sc.SetState(SCE_MATLAB_DEFAULT);
|
||||
transpose = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check start of a new state
|
||||
if (sc.state == SCE_MATLAB_DEFAULT) {
|
||||
if (IsCommentChar(sc.ch)) {
|
||||
// ncrement depth if we are a block comment
|
||||
if(sc.chNext == '{' && nonSpaceColumn == column)
|
||||
commentDepth ++;
|
||||
curLine = styler.GetLine(sc.currentPos);
|
||||
styler.SetLineState(curLine, commentDepth);
|
||||
sc.SetState(SCE_MATLAB_COMMENT);
|
||||
} else if (sc.ch == '!' && sc.chNext != '=' ) {
|
||||
sc.SetState(SCE_MATLAB_COMMAND);
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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 <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
@ -943,6 +942,10 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
|
||||
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>
|
||||
@ -1109,301 +1112,6 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi
|
||||
}
|
||||
}
|
||||
|
||||
static bool latexIsSpecial(int ch) {
|
||||
return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') ||
|
||||
(ch == '{') || (ch == '}') || (ch == ' ');
|
||||
}
|
||||
|
||||
static bool latexIsBlank(int ch) {
|
||||
return (ch == ' ') || (ch == '\t');
|
||||
}
|
||||
|
||||
static bool latexIsBlankAndNL(int ch) {
|
||||
return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
|
||||
}
|
||||
|
||||
static bool latexIsLetter(int ch) {
|
||||
return isascii(ch) && isalpha(ch);
|
||||
}
|
||||
|
||||
static bool latexIsTagValid(int &i, int l, Accessor &styler) {
|
||||
while (i < l) {
|
||||
if (styler.SafeGetCharAt(i) == '{') {
|
||||
while (i < l) {
|
||||
i++;
|
||||
if (styler.SafeGetCharAt(i) == '}') {
|
||||
return true;
|
||||
} else if (!latexIsLetter(styler.SafeGetCharAt(i)) &&
|
||||
styler.SafeGetCharAt(i)!='*') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (!latexIsBlank(styler.SafeGetCharAt(i))) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool latexNextNotBlankIs(int i, int l, Accessor &styler, char needle) {
|
||||
char ch;
|
||||
while (i < l) {
|
||||
ch = styler.SafeGetCharAt(i);
|
||||
if (!latexIsBlankAndNL(ch) && ch != '*') {
|
||||
if (ch == needle)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool latexLastWordIs(int start, Accessor &styler, const char *needle) {
|
||||
unsigned int i = 0;
|
||||
unsigned int l = static_cast<unsigned int>(strlen(needle));
|
||||
int ini = start-l+1;
|
||||
char s[32];
|
||||
|
||||
while (i < l && i < 32) {
|
||||
s[i] = styler.SafeGetCharAt(ini + i);
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
|
||||
return (strcmp(s, needle) == 0);
|
||||
}
|
||||
|
||||
static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
|
||||
WordList *[], Accessor &styler) {
|
||||
|
||||
styler.StartAt(startPos);
|
||||
|
||||
int state = initStyle;
|
||||
char chNext = styler.SafeGetCharAt(startPos);
|
||||
styler.StartSegment(startPos);
|
||||
int lengthDoc = startPos + length;
|
||||
char chVerbatimDelim = '\0';
|
||||
|
||||
for (int i = startPos; i < lengthDoc; i++) {
|
||||
char ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
|
||||
if (styler.IsLeadByte(ch)) {
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case SCE_L_DEFAULT :
|
||||
switch (ch) {
|
||||
case '\\' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
if (latexIsSpecial(chNext)) {
|
||||
state = SCE_L_SPECIAL;
|
||||
} else {
|
||||
if (latexIsLetter(chNext)) {
|
||||
state = SCE_L_COMMAND;
|
||||
} else {
|
||||
if (chNext == '(' || chNext == '[') {
|
||||
styler.ColourTo(i-1, state);
|
||||
styler.ColourTo(i+1, SCE_L_SHORTCMD);
|
||||
state = SCE_L_MATH;
|
||||
if (chNext == '[')
|
||||
state = SCE_L_MATH2;
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
} else {
|
||||
state = SCE_L_SHORTCMD;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '$' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_MATH;
|
||||
if (chNext == '$') {
|
||||
state = SCE_L_MATH2;
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
}
|
||||
break;
|
||||
case '%' :
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_COMMENT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCE_L_ERROR:
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
break;
|
||||
case SCE_L_SPECIAL:
|
||||
case SCE_L_SHORTCMD:
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
break;
|
||||
case SCE_L_COMMAND :
|
||||
if (!latexIsLetter(chNext)) {
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
if (latexNextNotBlankIs(i+1, lengthDoc, styler, '[' )) {
|
||||
state = SCE_L_CMDOPT;
|
||||
} else if (latexLastWordIs(i, styler, "\\begin")) {
|
||||
state = SCE_L_TAG;
|
||||
} else if (latexLastWordIs(i, styler, "\\end")) {
|
||||
state = SCE_L_TAG2;
|
||||
} else if (latexLastWordIs(i, styler, "\\verb") &&
|
||||
chNext != '*' && chNext != ' ') {
|
||||
chVerbatimDelim = chNext;
|
||||
state = SCE_L_VERBATIM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCE_L_CMDOPT :
|
||||
if (ch == ']') {
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
break;
|
||||
case SCE_L_TAG :
|
||||
if (latexIsTagValid(i, lengthDoc, styler)) {
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
if (latexLastWordIs(i, styler, "{verbatim}")) {
|
||||
state = SCE_L_VERBATIM;
|
||||
} else if (latexLastWordIs(i, styler, "{comment}")) {
|
||||
state = SCE_L_COMMENT2;
|
||||
} else if (latexLastWordIs(i, styler, "{math}")) {
|
||||
state = SCE_L_MATH;
|
||||
} else if (latexLastWordIs(i, styler, "{displaymath}")) {
|
||||
state = SCE_L_MATH2;
|
||||
} else if (latexLastWordIs(i, styler, "{equation}")) {
|
||||
state = SCE_L_MATH2;
|
||||
}
|
||||
} else {
|
||||
state = SCE_L_ERROR;
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
break;
|
||||
case SCE_L_TAG2 :
|
||||
if (latexIsTagValid(i, lengthDoc, styler)) {
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
} else {
|
||||
state = SCE_L_ERROR;
|
||||
}
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
break;
|
||||
case SCE_L_MATH :
|
||||
if (ch == '$') {
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
} else if (ch == '\\' && chNext == ')') {
|
||||
styler.ColourTo(i-1, state);
|
||||
styler.ColourTo(i+1, SCE_L_SHORTCMD);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
state = SCE_L_DEFAULT;
|
||||
} else if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{math}")) {
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SCE_L_MATH2 :
|
||||
if (ch == '$') {
|
||||
if (chNext == '$') {
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
styler.ColourTo(i, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
} else {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
} else if (ch == '\\' && chNext == ']') {
|
||||
styler.ColourTo(i-1, state);
|
||||
styler.ColourTo(i+1, SCE_L_SHORTCMD);
|
||||
i++;
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
state = SCE_L_DEFAULT;
|
||||
} else if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{displaymath}")) {
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
} else if (latexLastWordIs(match, styler, "{equation}")) {
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCE_L_COMMENT :
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
styler.ColourTo(i - 1, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
}
|
||||
break;
|
||||
case SCE_L_COMMENT2 :
|
||||
if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{comment}")) {
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCE_L_VERBATIM :
|
||||
if (ch == '\\') {
|
||||
int match = i + 3;
|
||||
if (latexLastWordIs(match, styler, "\\end")) {
|
||||
match++;
|
||||
if (latexIsTagValid(match, lengthDoc, styler)) {
|
||||
if (latexLastWordIs(match, styler, "{verbatim}")) {
|
||||
styler.ColourTo(i-1, state);
|
||||
state = SCE_L_COMMAND;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (chNext == chVerbatimDelim) {
|
||||
styler.ColourTo(i+1, state);
|
||||
state = SCE_L_DEFAULT;
|
||||
chVerbatimDelim = '\0';
|
||||
} else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) {
|
||||
styler.ColourTo(i, SCE_L_ERROR);
|
||||
state = SCE_L_DEFAULT;
|
||||
chVerbatimDelim = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
styler.ColourTo(lengthDoc-1, state);
|
||||
}
|
||||
|
||||
static const char *const batchWordListDesc[] = {
|
||||
"Internal Commands",
|
||||
"External Commands",
|
||||
@ -1429,5 +1137,4 @@ LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordL
|
||||
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 lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
|
||||
LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");
|
||||
|
@ -98,6 +98,12 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor
|
||||
// forward to the first non-white character on the line
|
||||
bool atLineStart = sc.atLineStart;
|
||||
if (atLineStart) {
|
||||
// reset line state if it is set to comment state so empty lines don't get
|
||||
// comment line state, and the folding code folds comments separately,
|
||||
// and anyway the styling don't use line state for comments
|
||||
if (curLineState == SCE_PO_COMMENT)
|
||||
curLineState = SCE_PO_DEFAULT;
|
||||
|
||||
while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch))
|
||||
sc.Forward();
|
||||
}
|
||||
@ -142,8 +148,66 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
static int FindNextNonEmptyLineState(unsigned int startPos, Accessor &styler) {
|
||||
unsigned int length = styler.Length();
|
||||
for (unsigned int i = startPos; i < length; i++) {
|
||||
if (! isspacechar(styler[i])) {
|
||||
return styler.GetLineState(styler.GetLine(i));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
|
||||
if (! styler.GetPropertyInt("fold"))
|
||||
return;
|
||||
bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;
|
||||
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
|
||||
|
||||
unsigned int endPos = startPos + length;
|
||||
int curLine = styler.GetLine(startPos);
|
||||
int lineState = styler.GetLineState(curLine);
|
||||
int nextLineState;
|
||||
int level = styler.LevelAt(curLine) & SC_FOLDLEVELNUMBERMASK;
|
||||
int nextLevel;
|
||||
int visible = 0;
|
||||
int chNext = styler[startPos];
|
||||
|
||||
for (unsigned int i = startPos; i < endPos; i++) {
|
||||
int ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i+1);
|
||||
|
||||
if (! isspacechar(ch)) {
|
||||
visible++;
|
||||
} else if ((ch == '\r' && chNext != '\n') || ch == '\n' || i+1 >= endPos) {
|
||||
int lvl = level;
|
||||
int nextLine = curLine + 1;
|
||||
|
||||
nextLineState = styler.GetLineState(nextLine);
|
||||
if ((lineState != SCE_PO_COMMENT || foldComment) &&
|
||||
nextLineState == lineState &&
|
||||
FindNextNonEmptyLineState(i, styler) == lineState)
|
||||
nextLevel = SC_FOLDLEVELBASE + 1;
|
||||
else
|
||||
nextLevel = SC_FOLDLEVELBASE;
|
||||
|
||||
if (nextLevel > level)
|
||||
lvl |= SC_FOLDLEVELHEADERFLAG;
|
||||
if (visible == 0 && foldCompact)
|
||||
lvl |= SC_FOLDLEVELWHITEFLAG;
|
||||
|
||||
styler.SetLevel(curLine, lvl);
|
||||
|
||||
lineState = nextLineState;
|
||||
curLine = nextLine;
|
||||
level = nextLevel;
|
||||
visible = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *const poWordListDesc[] = {
|
||||
0
|
||||
};
|
||||
|
||||
LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", 0, poWordListDesc);
|
||||
LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", FoldPODoc, poWordListDesc);
|
||||
|
@ -119,7 +119,7 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor
|
||||
chAttr = SCE_RB_MODULE_NAME;
|
||||
else if (0 == strcmp(prevWord, "def"))
|
||||
chAttr = SCE_RB_DEFNAME;
|
||||
else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
|
||||
else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) {
|
||||
if (keywordIsAmbiguous(s)
|
||||
&& keywordIsModifier(s, start, styler)) {
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
enum EncodingType { enc8bit, encUnicode, encDBCS };
|
||||
|
||||
class LexAccessor {
|
||||
private:
|
||||
IDocument *pAccess;
|
||||
@ -25,6 +27,7 @@ private:
|
||||
int startPos;
|
||||
int endPos;
|
||||
int codePage;
|
||||
enum EncodingType encodingType;
|
||||
int lenDoc;
|
||||
int mask;
|
||||
char styleBuf[bufferSize];
|
||||
@ -33,6 +36,7 @@ private:
|
||||
char chWhile;
|
||||
unsigned int startSeg;
|
||||
int startPosStyling;
|
||||
int documentVersion;
|
||||
|
||||
void Fill(int position) {
|
||||
startPos = position - slopSize;
|
||||
@ -51,9 +55,23 @@ private:
|
||||
public:
|
||||
LexAccessor(IDocument *pAccess_) :
|
||||
pAccess(pAccess_), startPos(extremePosition), endPos(0),
|
||||
codePage(pAccess->CodePage()), lenDoc(pAccess->Length()),
|
||||
codePage(pAccess->CodePage()),
|
||||
encodingType(enc8bit),
|
||||
lenDoc(pAccess->Length()),
|
||||
mask(127), validLen(0), chFlags(0), chWhile(0),
|
||||
startSeg(0), startPosStyling(0) {
|
||||
startSeg(0), startPosStyling(0),
|
||||
documentVersion(pAccess->Version()) {
|
||||
switch (codePage) {
|
||||
case 65001:
|
||||
encodingType = encUnicode;
|
||||
break;
|
||||
case 932:
|
||||
case 936:
|
||||
case 949:
|
||||
case 950:
|
||||
case 1361:
|
||||
encodingType = encDBCS;
|
||||
}
|
||||
}
|
||||
char operator[](int position) {
|
||||
if (position < startPos || position >= endPos) {
|
||||
@ -75,7 +93,9 @@ public:
|
||||
bool IsLeadByte(char ch) {
|
||||
return pAccess->IsDBCSLeadByte(ch);
|
||||
}
|
||||
|
||||
EncodingType Encoding() const {
|
||||
return encodingType;
|
||||
}
|
||||
bool Match(int pos, const char *s) {
|
||||
for (int i=0; *s; i++) {
|
||||
if (*s != SafeGetCharAt(pos+i))
|
||||
@ -93,6 +113,19 @@ public:
|
||||
int LineStart(int line) {
|
||||
return pAccess->LineStart(line);
|
||||
}
|
||||
int LineEnd(int line) {
|
||||
if (documentVersion >= dvLineEnd) {
|
||||
return (static_cast<IDocumentWithLineEnd *>(pAccess))->LineEnd(line);
|
||||
} else {
|
||||
// Old interface means only '\r', '\n' and '\r\n' line ends.
|
||||
int startNext = pAccess->LineStart(line+1);
|
||||
char chLineEnd = SafeGetCharAt(startNext-1);
|
||||
if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2) == '\r'))
|
||||
return startNext - 2;
|
||||
else
|
||||
return startNext - 1;
|
||||
}
|
||||
}
|
||||
int LevelAt(int line) {
|
||||
return pAccess->GetLevel(line);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerSimple.cxx
|
||||
/** @file LexerBase.cxx
|
||||
** A simple lexer with no state.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
|
@ -74,11 +74,9 @@ int LexerModule::GetNumWordLists() const {
|
||||
}
|
||||
|
||||
const char *LexerModule::GetWordListDescription(int index) const {
|
||||
static const char *emptyStr = "";
|
||||
|
||||
assert(index < GetNumWordLists());
|
||||
if (index >= GetNumWordLists()) {
|
||||
return emptyStr;
|
||||
return "";
|
||||
} else {
|
||||
return wordListDescriptions[index];
|
||||
}
|
||||
|
@ -19,6 +19,30 @@ static inline int MakeLowerCase(int ch) {
|
||||
return ch - 'A' + 'a';
|
||||
}
|
||||
|
||||
inline int UnicodeCodePoint(const unsigned char *us) {
|
||||
if (us[0] < 0xC2) {
|
||||
return us[0];
|
||||
} else if (us[0] < 0xE0) {
|
||||
return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
|
||||
} else if (us[0] < 0xF0) {
|
||||
return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
|
||||
} else if (us[0] < 0xF5) {
|
||||
return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
|
||||
}
|
||||
return us[0];
|
||||
}
|
||||
|
||||
inline int BytesInUnicodeCodePoint(int codePoint) {
|
||||
if (codePoint < 0x80)
|
||||
return 1;
|
||||
else if (codePoint < 0x800)
|
||||
return 2;
|
||||
else if (codePoint < 0x10000)
|
||||
return 3;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
|
||||
// All languages handled so far can treat all characters >= 0x80 as one class
|
||||
// which just continues the current token or starts an identifier if in default.
|
||||
// DBCS treated specially as the second character can be < 0x80 and hence
|
||||
@ -26,23 +50,42 @@ static inline int MakeLowerCase(int ch) {
|
||||
class StyleContext {
|
||||
LexAccessor &styler;
|
||||
unsigned int endPos;
|
||||
unsigned int lengthDocument;
|
||||
StyleContext &operator=(const StyleContext &);
|
||||
|
||||
void GetNextChar(unsigned int pos) {
|
||||
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1));
|
||||
if (styler.IsLeadByte(static_cast<char>(chNext))) {
|
||||
chNext = chNext << 8;
|
||||
chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2));
|
||||
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1, 0));
|
||||
if (styler.Encoding() == encUnicode) {
|
||||
if (chNext >= 0x80) {
|
||||
unsigned char bytes[4] = { static_cast<unsigned char>(chNext), 0, 0, 0 };
|
||||
for (int trail=1; trail<3; trail++) {
|
||||
bytes[trail] = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1+trail, 0));
|
||||
if (!((bytes[trail] >= 0x80) && (bytes[trail] < 0xc0))) {
|
||||
bytes[trail] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
chNext = UnicodeCodePoint(bytes);
|
||||
}
|
||||
} else if (styler.Encoding() == encDBCS) {
|
||||
if (styler.IsLeadByte(static_cast<char>(chNext))) {
|
||||
chNext = chNext << 8;
|
||||
chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2, 0));
|
||||
}
|
||||
}
|
||||
// End of line?
|
||||
// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win)
|
||||
// or on LF alone (Unix). Avoid triggering two times on Dos/Win.
|
||||
atLineEnd = (ch == '\r' && chNext != '\n') ||
|
||||
(ch == '\n') ||
|
||||
(currentPos >= endPos);
|
||||
if (lineStartNext < styler.Length())
|
||||
atLineEnd = static_cast<int>(pos) >= (lineStartNext-1);
|
||||
else // Last line
|
||||
atLineEnd = static_cast<int>(pos) >= lineStartNext;
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned int currentPos;
|
||||
int currentLine;
|
||||
int lineStartNext;
|
||||
bool atLineStart;
|
||||
bool atLineEnd;
|
||||
int state;
|
||||
@ -55,6 +98,8 @@ public:
|
||||
styler(styler_),
|
||||
endPos(startPos + length),
|
||||
currentPos(startPos),
|
||||
currentLine(-1),
|
||||
lineStartNext(-1),
|
||||
atLineEnd(false),
|
||||
state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
|
||||
chPrev(0),
|
||||
@ -62,18 +107,30 @@ public:
|
||||
chNext(0) {
|
||||
styler.StartAt(startPos, chMask);
|
||||
styler.StartSegment(startPos);
|
||||
atLineStart = static_cast<unsigned int>(styler.LineStart(styler.GetLine(startPos))) == startPos;
|
||||
currentLine = styler.GetLine(startPos);
|
||||
lineStartNext = styler.LineStart(currentLine+1);
|
||||
lengthDocument = static_cast<unsigned int>(styler.Length());
|
||||
if (endPos == lengthDocument)
|
||||
endPos++;
|
||||
atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
|
||||
unsigned int pos = currentPos;
|
||||
ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
|
||||
if (styler.IsLeadByte(static_cast<char>(ch))) {
|
||||
pos++;
|
||||
ch = ch << 8;
|
||||
ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos));
|
||||
ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));
|
||||
if (styler.Encoding() == encUnicode) {
|
||||
// Get the current char
|
||||
GetNextChar(pos-1);
|
||||
ch = chNext;
|
||||
pos += BytesInUnicodeCodePoint(ch) - 1;
|
||||
} else if (styler.Encoding() == encDBCS) {
|
||||
if (styler.IsLeadByte(static_cast<char>(ch))) {
|
||||
pos++;
|
||||
ch = ch << 8;
|
||||
ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));
|
||||
}
|
||||
}
|
||||
GetNextChar(pos);
|
||||
}
|
||||
void Complete() {
|
||||
styler.ColourTo(currentPos - 1, state);
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
styler.Flush();
|
||||
}
|
||||
bool More() const {
|
||||
@ -82,12 +139,28 @@ public:
|
||||
void Forward() {
|
||||
if (currentPos < endPos) {
|
||||
atLineStart = atLineEnd;
|
||||
if (atLineStart) {
|
||||
currentLine++;
|
||||
lineStartNext = styler.LineStart(currentLine+1);
|
||||
}
|
||||
chPrev = ch;
|
||||
currentPos++;
|
||||
if (ch >= 0x100)
|
||||
if (styler.Encoding() == encUnicode) {
|
||||
currentPos += BytesInUnicodeCodePoint(ch);
|
||||
} else if (styler.Encoding() == encDBCS) {
|
||||
currentPos++;
|
||||
if (ch >= 0x100)
|
||||
currentPos++;
|
||||
} else {
|
||||
currentPos++;
|
||||
}
|
||||
ch = chNext;
|
||||
GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
|
||||
if (styler.Encoding() == encUnicode) {
|
||||
GetNextChar(currentPos + BytesInUnicodeCodePoint(ch)-1);
|
||||
} else if (styler.Encoding() == encDBCS) {
|
||||
GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
|
||||
} else {
|
||||
GetNextChar(currentPos);
|
||||
}
|
||||
} else {
|
||||
atLineStart = false;
|
||||
chPrev = ' ';
|
||||
@ -105,19 +178,19 @@ public:
|
||||
state = state_;
|
||||
}
|
||||
void SetState(int state_) {
|
||||
styler.ColourTo(currentPos - 1, state);
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
state = state_;
|
||||
}
|
||||
void ForwardSetState(int state_) {
|
||||
Forward();
|
||||
styler.ColourTo(currentPos - 1, state);
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
state = state_;
|
||||
}
|
||||
int LengthCurrent() {
|
||||
return currentPos - styler.GetStartSegment();
|
||||
}
|
||||
int GetRelative(int n) {
|
||||
return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
|
||||
return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0));
|
||||
}
|
||||
bool Match(char ch0) const {
|
||||
return ch == static_cast<unsigned char>(ch0);
|
||||
@ -135,7 +208,7 @@ public:
|
||||
return false;
|
||||
s++;
|
||||
for (int n=2; *s; n++) {
|
||||
if (*s != styler.SafeGetCharAt(currentPos+n))
|
||||
if (*s != styler.SafeGetCharAt(currentPos+n, 0))
|
||||
return false;
|
||||
s++;
|
||||
}
|
||||
@ -150,7 +223,7 @@ public:
|
||||
s++;
|
||||
for (int n=2; *s; n++) {
|
||||
if (static_cast<unsigned char>(*s) !=
|
||||
MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
|
||||
MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0))))
|
||||
return false;
|
||||
s++;
|
||||
}
|
||||
|
162
scintilla/lexlib/SubStyles.h
Normal file
162
scintilla/lexlib/SubStyles.h
Normal file
@ -0,0 +1,162 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file SubStyles.h
|
||||
** Manage substyles for a lexer.
|
||||
**/
|
||||
// Copyright 2012 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SUBSTYLES_H
|
||||
#define SUBSTYLES_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class WordClassifier {
|
||||
int firstStyle;
|
||||
int lenStyles;
|
||||
std::map<std::string, int> wordToStyle;
|
||||
|
||||
public:
|
||||
|
||||
WordClassifier() : firstStyle(0), lenStyles(0) {
|
||||
}
|
||||
|
||||
void Allocate(int firstStyle_, int lenStyles_) {
|
||||
firstStyle = firstStyle_;
|
||||
lenStyles = lenStyles_;
|
||||
wordToStyle.clear();
|
||||
}
|
||||
|
||||
int Start() const {
|
||||
return firstStyle;
|
||||
}
|
||||
|
||||
int Length() const {
|
||||
return lenStyles;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
firstStyle = 0;
|
||||
lenStyles = 0;
|
||||
wordToStyle.clear();
|
||||
}
|
||||
|
||||
int ValueFor(const std::string &s) const {
|
||||
std::map<std::string, int>::const_iterator it = wordToStyle.find(s);
|
||||
if (it != wordToStyle.end())
|
||||
return it->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IncludesStyle(int style) const {
|
||||
return (style >= firstStyle) && (style < (firstStyle + lenStyles));
|
||||
}
|
||||
|
||||
void SetIdentifiers(int style, const char *identifiers) {
|
||||
while (*identifiers) {
|
||||
const char *cpSpace = identifiers;
|
||||
while (*cpSpace && *cpSpace != ' ')
|
||||
cpSpace++;
|
||||
std::string word(identifiers, cpSpace - identifiers);
|
||||
wordToStyle[word] = style;
|
||||
identifiers = cpSpace;
|
||||
if (*identifiers)
|
||||
identifiers++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SubStyles {
|
||||
int classifications;
|
||||
const char *baseStyles;
|
||||
int styleFirst;
|
||||
int stylesAvailable;
|
||||
int secondaryDistance;
|
||||
int allocated;
|
||||
std::vector<WordClassifier> classifiers;
|
||||
|
||||
int BlockFromBaseStyle(int baseStyle) const {
|
||||
for (int b=0; b < classifications; b++) {
|
||||
if (baseStyle == baseStyles[b])
|
||||
return b;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BlockFromStyle(int style) const {
|
||||
int b = 0;
|
||||
for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) {
|
||||
if (it->IncludesStyle(style))
|
||||
return b;
|
||||
b++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) :
|
||||
classifications(0),
|
||||
baseStyles(baseStyles_),
|
||||
styleFirst(styleFirst_),
|
||||
stylesAvailable(stylesAvailable_),
|
||||
secondaryDistance(secondaryDistance_),
|
||||
allocated(0) {
|
||||
while (baseStyles[classifications]) {
|
||||
classifications++;
|
||||
classifiers.push_back(WordClassifier());
|
||||
}
|
||||
}
|
||||
|
||||
int Allocate(int styleBase, int numberStyles) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
if (block >= 0) {
|
||||
if ((allocated + numberStyles) > stylesAvailable)
|
||||
return -1;
|
||||
int startBlock = styleFirst + allocated;
|
||||
allocated += numberStyles;
|
||||
classifiers[block].Allocate(startBlock, numberStyles);
|
||||
return startBlock;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int Start(int styleBase) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
return (block >= 0) ? classifiers[block].Start() : -1;
|
||||
}
|
||||
|
||||
int Length(int styleBase) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
return (block >= 0) ? classifiers[block].Length() : 0;
|
||||
}
|
||||
|
||||
int DistanceToSecondaryStyles() const {
|
||||
return secondaryDistance;
|
||||
}
|
||||
|
||||
void SetIdentifiers(int style, const char *identifiers) {
|
||||
int block = BlockFromStyle(style);
|
||||
if (block >= 0)
|
||||
classifiers[block].SetIdentifiers(style, identifiers);
|
||||
}
|
||||
|
||||
void Free() {
|
||||
allocated = 0;
|
||||
for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it)
|
||||
it->Clear();
|
||||
}
|
||||
|
||||
const WordClassifier &Classifier(int baseStyle) const {
|
||||
return classifiers[BlockFromBaseStyle(baseStyle)];
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -89,6 +89,7 @@ LexVerilog.o \
|
||||
LexMarkdown.o \
|
||||
LexMatlab.o \
|
||||
LexD.o \
|
||||
LexLaTeX.o \
|
||||
LexLisp.o \
|
||||
LexLua.o \
|
||||
LexHaskell.o \
|
||||
|
@ -10,7 +10,9 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
@ -36,7 +38,8 @@ AutoComplete::AutoComplete() :
|
||||
dropRestOfWord(false),
|
||||
ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE),
|
||||
widthLBDefault(100),
|
||||
heightLBDefault(100) {
|
||||
heightLBDefault(100),
|
||||
autoSort(SC_ORDER_PRESORTED) {
|
||||
lb = ListBox::Allocate();
|
||||
stopChars[0] = '\0';
|
||||
fillUpChars[0] = '\0';
|
||||
@ -101,8 +104,91 @@ char AutoComplete::GetTypesep() const {
|
||||
return typesep;
|
||||
}
|
||||
|
||||
struct Sorter {
|
||||
AutoComplete *ac;
|
||||
const char *list;
|
||||
std::vector<int> indices;
|
||||
|
||||
Sorter(AutoComplete *ac_, const char *list_) : ac(ac_), list(list_) {
|
||||
int i = 0;
|
||||
while (list[i]) {
|
||||
indices.push_back(i); // word start
|
||||
while (list[i] != ac->GetTypesep() && list[i] != ac->GetSeparator() && list[i])
|
||||
++i;
|
||||
indices.push_back(i); // word end
|
||||
if (list[i] == ac->GetTypesep()) {
|
||||
while (list[i] != ac->GetSeparator() && list[i])
|
||||
++i;
|
||||
}
|
||||
if (list[i] == ac->GetSeparator()) {
|
||||
++i;
|
||||
// preserve trailing separator as blank entry
|
||||
if (!list[i]) {
|
||||
indices.push_back(i);
|
||||
indices.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
indices.push_back(i); // index of last position
|
||||
}
|
||||
|
||||
bool operator()(int a, int b) {
|
||||
int lenA = indices[a * 2 + 1] - indices[a * 2];
|
||||
int lenB = indices[b * 2 + 1] - indices[b * 2];
|
||||
int len = std::min(lenA, lenB);
|
||||
int cmp;
|
||||
if (ac->ignoreCase)
|
||||
cmp = CompareNCaseInsensitive(list + indices[a * 2], list + indices[b * 2], len);
|
||||
else
|
||||
cmp = strncmp(list + indices[a * 2], list + indices[b * 2], len);
|
||||
if (cmp == 0)
|
||||
cmp = lenA - lenB;
|
||||
return cmp < 0;
|
||||
}
|
||||
};
|
||||
|
||||
void AutoComplete::SetList(const char *list) {
|
||||
lb->SetList(list, separator, typesep);
|
||||
if (autoSort == SC_ORDER_PRESORTED) {
|
||||
lb->SetList(list, separator, typesep);
|
||||
sortMatrix.clear();
|
||||
for (int i = 0; i < lb->Length(); ++i)
|
||||
sortMatrix.push_back(i);
|
||||
return;
|
||||
}
|
||||
|
||||
Sorter IndexSort(this, list);
|
||||
sortMatrix.clear();
|
||||
for (int i = 0; i < (int)IndexSort.indices.size() / 2; ++i)
|
||||
sortMatrix.push_back(i);
|
||||
std::sort(sortMatrix.begin(), sortMatrix.end(), IndexSort);
|
||||
if (autoSort == SC_ORDER_CUSTOM || sortMatrix.size() < 2) {
|
||||
lb->SetList(list, separator, typesep);
|
||||
PLATFORM_ASSERT(lb->Length() == static_cast<int>(sortMatrix.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string sortedList;
|
||||
char item[maxItemLen];
|
||||
for (size_t i = 0; i < sortMatrix.size(); ++i) {
|
||||
int wordLen = IndexSort.indices[sortMatrix[i] * 2 + 2] - IndexSort.indices[sortMatrix[i] * 2];
|
||||
strncpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen);
|
||||
if ((i+1) == sortMatrix.size()) {
|
||||
// Last item so remove separator if present
|
||||
if ((wordLen > 0) && (item[wordLen-1] == separator))
|
||||
wordLen--;
|
||||
} else {
|
||||
// Item before last needs a separator
|
||||
if ((wordLen == 0) || (item[wordLen-1] != separator)) {
|
||||
item[wordLen] = separator;
|
||||
wordLen++;
|
||||
}
|
||||
}
|
||||
item[wordLen] = '\0';
|
||||
sortedList += item;
|
||||
}
|
||||
for (int i = 0; i < (int)sortMatrix.size(); ++i)
|
||||
sortMatrix[i] = i;
|
||||
lb->SetList(sortedList.c_str(), separator, typesep);
|
||||
}
|
||||
|
||||
int AutoComplete::GetSelection() const {
|
||||
@ -149,7 +235,7 @@ void AutoComplete::Select(const char *word) {
|
||||
while ((start <= end) && (location == -1)) { // Binary searching loop
|
||||
int pivot = (start + end) / 2;
|
||||
char item[maxItemLen];
|
||||
lb->GetValue(pivot, item, maxItemLen);
|
||||
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
|
||||
int cond;
|
||||
if (ignoreCase)
|
||||
cond = CompareNCaseInsensitive(word, item, lenWord);
|
||||
@ -158,7 +244,7 @@ void AutoComplete::Select(const char *word) {
|
||||
if (!cond) {
|
||||
// Find first match
|
||||
while (pivot > start) {
|
||||
lb->GetValue(pivot-1, item, maxItemLen);
|
||||
lb->GetValue(sortMatrix[pivot-1], item, maxItemLen);
|
||||
if (ignoreCase)
|
||||
cond = CompareNCaseInsensitive(word, item, lenWord);
|
||||
else
|
||||
@ -172,7 +258,7 @@ void AutoComplete::Select(const char *word) {
|
||||
&& ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) {
|
||||
// Check for exact-case match
|
||||
for (; pivot <= end; pivot++) {
|
||||
lb->GetValue(pivot, item, maxItemLen);
|
||||
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
|
||||
if (!strncmp(word, item, lenWord)) {
|
||||
location = pivot;
|
||||
break;
|
||||
@ -187,9 +273,24 @@ void AutoComplete::Select(const char *word) {
|
||||
start = pivot + 1;
|
||||
}
|
||||
}
|
||||
if (location == -1 && autoHide)
|
||||
Cancel();
|
||||
else
|
||||
lb->Select(location);
|
||||
if (location == -1) {
|
||||
if (autoHide)
|
||||
Cancel();
|
||||
else
|
||||
lb->Select(-1);
|
||||
} else {
|
||||
if (autoSort == SC_ORDER_CUSTOM) {
|
||||
// Check for a logically earlier match
|
||||
char item[maxItemLen];
|
||||
for (int i = location + 1; i <= end; ++i) {
|
||||
lb->GetValue(sortMatrix[i], item, maxItemLen);
|
||||
if (CompareNCaseInsensitive(word, item, lenWord))
|
||||
break;
|
||||
if (sortMatrix[i] < sortMatrix[location] && !strncmp(word, item, lenWord))
|
||||
location = i;
|
||||
}
|
||||
}
|
||||
lb->Select(sortMatrix[location]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ class AutoComplete {
|
||||
char separator;
|
||||
char typesep; // Type seperator
|
||||
enum { maxItemLen=1000 };
|
||||
std::vector<int> sortMatrix;
|
||||
|
||||
public:
|
||||
|
||||
@ -36,6 +37,11 @@ public:
|
||||
unsigned int ignoreCaseBehaviour;
|
||||
int widthLBDefault;
|
||||
int heightLBDefault;
|
||||
/** SC_ORDER_PRESORTED: Assume the list is presorted; selection will fail if it is not alphabetical<br />
|
||||
* SC_ORDER_PERFORMSORT: Sort the list alphabetically; start up performance cost for sorting<br />
|
||||
* SC_ORDER_CUSTOM: Handle non-alphabetical entries; start up performance cost for generating a sorted lookup table
|
||||
*/
|
||||
int autoSort;
|
||||
|
||||
AutoComplete();
|
||||
~AutoComplete();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "UniConversion.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
@ -331,6 +332,7 @@ void UndoHistory::CompletedRedoStep() {
|
||||
|
||||
CellBuffer::CellBuffer() {
|
||||
readOnly = false;
|
||||
utf8LineEnds = 0;
|
||||
collectingUndo = true;
|
||||
}
|
||||
|
||||
@ -458,6 +460,13 @@ void CellBuffer::Allocate(int newSize) {
|
||||
style.ReAllocate(newSize);
|
||||
}
|
||||
|
||||
void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
|
||||
if (utf8LineEnds != utf8LineEnds_) {
|
||||
utf8LineEnds = utf8LineEnds_;
|
||||
ResetLineEnds();
|
||||
}
|
||||
}
|
||||
|
||||
void CellBuffer::SetPerLine(PerLine *pl) {
|
||||
lv.SetPerLine(pl);
|
||||
}
|
||||
@ -501,11 +510,63 @@ void CellBuffer::RemoveLine(int line) {
|
||||
lv.RemoveLine(line);
|
||||
}
|
||||
|
||||
bool CellBuffer::UTF8LineEndOverlaps(int position) const {
|
||||
unsigned char bytes[] = {
|
||||
static_cast<unsigned char>(substance.ValueAt(position-2)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position-1)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position+1)),
|
||||
};
|
||||
return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1);
|
||||
}
|
||||
|
||||
void CellBuffer::ResetLineEnds() {
|
||||
// Reinitialize line data -- too much work to preserve
|
||||
lv.Init();
|
||||
|
||||
int position = 0;
|
||||
int length = Length();
|
||||
int lineInsert = 1;
|
||||
bool atLineStart = true;
|
||||
lv.InsertText(lineInsert-1, length);
|
||||
unsigned char chBeforePrev = 0;
|
||||
unsigned char chPrev = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
unsigned char ch = substance.ValueAt(position + i);
|
||||
if (ch == '\r') {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
} else if (ch == '\n') {
|
||||
if (chPrev == '\r') {
|
||||
// Patch up what was end of line
|
||||
lv.SetLineStart(lineInsert - 1, (position + i) + 1);
|
||||
} else {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, ch};
|
||||
if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
|
||||
if (insertLength == 0)
|
||||
return;
|
||||
PLATFORM_ASSERT(insertLength > 0);
|
||||
|
||||
unsigned char chAfter = substance.ValueAt(position);
|
||||
bool breakingUTF8LineEnd = false;
|
||||
if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
|
||||
breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
|
||||
}
|
||||
|
||||
substance.InsertFromArray(position, s, 0, insertLength);
|
||||
style.InsertValue(position, insertLength, 0);
|
||||
|
||||
@ -513,14 +574,17 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
|
||||
bool atLineStart = lv.LineStart(lineInsert-1) == position;
|
||||
// Point all the lines after the insertion point further along in the buffer
|
||||
lv.InsertText(lineInsert-1, insertLength);
|
||||
char chPrev = substance.ValueAt(position - 1);
|
||||
char chAfter = substance.ValueAt(position + insertLength);
|
||||
unsigned char chBeforePrev = substance.ValueAt(position - 2);
|
||||
unsigned char chPrev = substance.ValueAt(position - 1);
|
||||
if (chPrev == '\r' && chAfter == '\n') {
|
||||
// Splitting up a crlf pair at position
|
||||
InsertLine(lineInsert, position, false);
|
||||
lineInsert++;
|
||||
}
|
||||
char ch = ' ';
|
||||
if (breakingUTF8LineEnd) {
|
||||
RemoveLine(lineInsert);
|
||||
}
|
||||
unsigned char ch = ' ';
|
||||
for (int i = 0; i < insertLength; i++) {
|
||||
ch = s[i];
|
||||
if (ch == '\r') {
|
||||
@ -534,7 +598,14 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, ch};
|
||||
if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = ch;
|
||||
}
|
||||
// Joining two lines where last insertion is cr and following substance starts with lf
|
||||
@ -543,6 +614,22 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
|
||||
// End of line already in buffer so drop the newly created one
|
||||
RemoveLine(lineInsert - 1);
|
||||
}
|
||||
} else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
|
||||
// May have end of UTF-8 line end in buffer and start in insertion
|
||||
for (int j = 0; j < UTF8SeparatorLength-1; j++) {
|
||||
unsigned char chAt = substance.ValueAt(position + insertLength + j);
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
|
||||
if (UTF8IsSeparator(back3)) {
|
||||
InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
if ((j == 0) && UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = chAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,9 +647,9 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
|
||||
|
||||
int lineRemove = lv.LineFromPosition(position) + 1;
|
||||
lv.InsertText(lineRemove-1, - (deleteLength));
|
||||
char chPrev = substance.ValueAt(position - 1);
|
||||
char chBefore = chPrev;
|
||||
char chNext = substance.ValueAt(position);
|
||||
unsigned char chPrev = substance.ValueAt(position - 1);
|
||||
unsigned char chBefore = chPrev;
|
||||
unsigned char chNext = substance.ValueAt(position);
|
||||
bool ignoreNL = false;
|
||||
if (chPrev == '\r' && chNext == '\n') {
|
||||
// Move back one
|
||||
@ -570,8 +657,13 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
|
||||
lineRemove++;
|
||||
ignoreNL = true; // First \n is not real deletion
|
||||
}
|
||||
if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
|
||||
if (UTF8LineEndOverlaps(position)) {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
}
|
||||
|
||||
char ch = chNext;
|
||||
unsigned char ch = chNext;
|
||||
for (int i = 0; i < deleteLength; i++) {
|
||||
chNext = substance.ValueAt(position + i + 1);
|
||||
if (ch == '\r') {
|
||||
@ -584,6 +676,14 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
|
||||
} else {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
if (!UTF8IsAscii(ch)) {
|
||||
unsigned char next3[3] = {ch, chNext,
|
||||
static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
|
||||
if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ch = chNext;
|
||||
|
@ -98,6 +98,9 @@ class UndoHistory {
|
||||
|
||||
void EnsureUndoRoom();
|
||||
|
||||
// Private so UndoHistory objects can not be copied
|
||||
UndoHistory(const UndoHistory &);
|
||||
|
||||
public:
|
||||
UndoHistory();
|
||||
~UndoHistory();
|
||||
@ -136,12 +139,15 @@ private:
|
||||
SplitVector<char> substance;
|
||||
SplitVector<char> style;
|
||||
bool readOnly;
|
||||
int utf8LineEnds;
|
||||
|
||||
bool collectingUndo;
|
||||
UndoHistory uh;
|
||||
|
||||
LineVector lv;
|
||||
|
||||
bool UTF8LineEndOverlaps(int position) const;
|
||||
void ResetLineEnds();
|
||||
/// Actions without undo
|
||||
void BasicInsertString(int position, const char *s, int insertLength);
|
||||
void BasicDeleteChars(int position, int deleteLength);
|
||||
@ -162,6 +168,8 @@ public:
|
||||
|
||||
int Length() const;
|
||||
void Allocate(int newSize);
|
||||
int GetLineEndTypes() const { return utf8LineEnds; }
|
||||
void SetLineEndTypes(int utf8LineEnds_);
|
||||
void SetPerLine(PerLine *pl);
|
||||
int Lines() const;
|
||||
int LineStart(int line) const;
|
||||
|
@ -66,7 +66,7 @@ int ContractionState::LinesDisplayed() const {
|
||||
|
||||
int ContractionState::DisplayFromDoc(int lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return lineDoc;
|
||||
return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
|
||||
} else {
|
||||
if (lineDoc > displayLines->Partitions())
|
||||
lineDoc = displayLines->Partitions();
|
||||
|
@ -67,6 +67,17 @@ void LexInterface::Colourise(int start, int end) {
|
||||
}
|
||||
}
|
||||
|
||||
int LexInterface::LineEndTypesSupported() {
|
||||
if (instance) {
|
||||
int interfaceVersion = instance->Version();
|
||||
if (interfaceVersion >= lvSubStyles) {
|
||||
ILexerWithSubStyles *ssinstance = static_cast<ILexerWithSubStyles *>(instance);
|
||||
return ssinstance->LineEndTypesSupported();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Document::Document() {
|
||||
refCount = 0;
|
||||
pcf = NULL;
|
||||
@ -76,6 +87,7 @@ Document::Document() {
|
||||
eolMode = SC_EOL_LF;
|
||||
#endif
|
||||
dbcsCodePage = 0;
|
||||
lineEndBitSet = SC_LINE_END_TYPE_DEFAULT;
|
||||
stylingBits = 5;
|
||||
stylingBitsMask = 0x1F;
|
||||
stylingMask = 0;
|
||||
@ -135,16 +147,40 @@ void Document::Init() {
|
||||
}
|
||||
}
|
||||
|
||||
int Document::LineEndTypesSupported() const {
|
||||
if ((SC_CP_UTF8 == dbcsCodePage) && pli)
|
||||
return pli->LineEndTypesSupported();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Document::SetDBCSCodePage(int dbcsCodePage_) {
|
||||
if (dbcsCodePage != dbcsCodePage_) {
|
||||
dbcsCodePage = dbcsCodePage_;
|
||||
SetCaseFolder(NULL);
|
||||
cb.SetLineEndTypes(lineEndBitSet & LineEndTypesSupported());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::SetLineEndTypesAllowed(int lineEndBitSet_) {
|
||||
if (lineEndBitSet != lineEndBitSet_) {
|
||||
lineEndBitSet = lineEndBitSet_;
|
||||
int lineEndBitSetActive = lineEndBitSet & LineEndTypesSupported();
|
||||
if (lineEndBitSetActive != cb.GetLineEndTypes()) {
|
||||
ModifiedAt(0);
|
||||
cb.SetLineEndTypes(lineEndBitSetActive);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Document::InsertLine(int line) {
|
||||
for (int j=0; j<ldSize; j++) {
|
||||
if (perLineData[j])
|
||||
@ -245,11 +281,25 @@ int SCI_METHOD Document::LineStart(int line) const {
|
||||
return cb.LineStart(line);
|
||||
}
|
||||
|
||||
int Document::LineEnd(int line) const {
|
||||
int SCI_METHOD Document::LineEnd(int line) const {
|
||||
if (line == LinesTotal() - 1) {
|
||||
return LineStart(line + 1);
|
||||
} else {
|
||||
int position = LineStart(line + 1) - 1;
|
||||
int position = LineStart(line + 1);
|
||||
if (SC_CP_UTF8 == dbcsCodePage) {
|
||||
unsigned char bytes[] = {
|
||||
static_cast<unsigned char>(cb.CharAt(position-3)),
|
||||
static_cast<unsigned char>(cb.CharAt(position-2)),
|
||||
static_cast<unsigned char>(cb.CharAt(position-1)),
|
||||
};
|
||||
if (UTF8IsSeparator(bytes)) {
|
||||
return position - UTF8SeparatorLength;
|
||||
}
|
||||
if (UTF8IsNEL(bytes+1)) {
|
||||
return position - UTF8NELLength;
|
||||
}
|
||||
}
|
||||
position--; // Back over CR or LF
|
||||
// When line terminator is CR+LF, may need to go back one more
|
||||
if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
|
||||
position--;
|
||||
@ -277,6 +327,10 @@ bool Document::IsLineEndPosition(int position) const {
|
||||
return LineEnd(LineFromPosition(position)) == position;
|
||||
}
|
||||
|
||||
bool Document::IsPositionInLineEnd(int position) const {
|
||||
return position >= LineEnd(LineFromPosition(position));
|
||||
}
|
||||
|
||||
int Document::VCHomePosition(int position) const {
|
||||
int line = LineFromPosition(position);
|
||||
int startPosition = LineStart(line);
|
||||
|
@ -186,6 +186,7 @@ public:
|
||||
virtual ~LexInterface() {
|
||||
}
|
||||
void Colourise(int start, int end);
|
||||
int LineEndTypesSupported();
|
||||
bool UseContainerLexing() const {
|
||||
return instance == 0;
|
||||
}
|
||||
@ -193,7 +194,7 @@ public:
|
||||
|
||||
/**
|
||||
*/
|
||||
class Document : PerLine, public IDocument, public ILoader {
|
||||
class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
|
||||
|
||||
public:
|
||||
/** Used to pair watcher pointer with user data. */
|
||||
@ -240,6 +241,7 @@ public:
|
||||
int eolMode;
|
||||
/// Can also be SC_CP_UTF8 to enable UTF-8 mode
|
||||
int dbcsCodePage;
|
||||
int lineEndBitSet;
|
||||
int tabInChars;
|
||||
int indentInChars;
|
||||
int actualIndentInChars;
|
||||
@ -256,12 +258,16 @@ public:
|
||||
int SCI_METHOD Release();
|
||||
|
||||
virtual void Init();
|
||||
int LineEndTypesSupported() const;
|
||||
bool SetDBCSCodePage(int dbcsCodePage_);
|
||||
int GetLineEndTypesAllowed() { return cb.GetLineEndTypes(); }
|
||||
bool SetLineEndTypesAllowed(int lineEndBitSet_);
|
||||
int GetLineEndTypesActive() { return cb.GetLineEndTypes(); }
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
int SCI_METHOD Version() const {
|
||||
return dvOriginal;
|
||||
return dvLineEnd;
|
||||
}
|
||||
|
||||
void SCI_METHOD SetErrorStatus(int status);
|
||||
@ -338,9 +344,10 @@ public:
|
||||
void DeleteAllMarks(int markerNum);
|
||||
int LineFromHandle(int markerHandle);
|
||||
int SCI_METHOD LineStart(int line) const;
|
||||
int LineEnd(int line) const;
|
||||
int SCI_METHOD LineEnd(int line) const;
|
||||
int LineEndPosition(int position) const;
|
||||
bool IsLineEndPosition(int position) const;
|
||||
bool IsPositionInLineEnd(int position) const;
|
||||
int VCHomePosition(int position) const;
|
||||
|
||||
int SCI_METHOD SetLevel(int line, int level);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
@ -174,6 +175,7 @@ Editor::Editor() {
|
||||
pixmapLine = 0;
|
||||
pixmapSelMargin = 0;
|
||||
pixmapSelPattern = 0;
|
||||
pixmapSelPatternOffset1 = 0;
|
||||
pixmapIndentGuide = 0;
|
||||
pixmapIndentGuideHighlight = 0;
|
||||
|
||||
@ -249,6 +251,8 @@ void Editor::DropGraphics(bool freeObjects) {
|
||||
pixmapSelMargin = 0;
|
||||
delete pixmapSelPattern;
|
||||
pixmapSelPattern = 0;
|
||||
delete pixmapSelPatternOffset1;
|
||||
pixmapSelPatternOffset1 = 0;
|
||||
delete pixmapIndentGuide;
|
||||
pixmapIndentGuide = 0;
|
||||
delete pixmapIndentGuideHighlight;
|
||||
@ -260,6 +264,8 @@ void Editor::DropGraphics(bool freeObjects) {
|
||||
pixmapSelMargin->Release();
|
||||
if (pixmapSelPattern)
|
||||
pixmapSelPattern->Release();
|
||||
if (pixmapSelPatternOffset1)
|
||||
pixmapSelPatternOffset1->Release();
|
||||
if (pixmapIndentGuide)
|
||||
pixmapIndentGuide->Release();
|
||||
if (pixmapIndentGuideHighlight)
|
||||
@ -274,6 +280,8 @@ void Editor::AllocateGraphics() {
|
||||
pixmapSelMargin = Surface::Allocate(technology);
|
||||
if (!pixmapSelPattern)
|
||||
pixmapSelPattern = Surface::Allocate(technology);
|
||||
if (!pixmapSelPatternOffset1)
|
||||
pixmapSelPatternOffset1 = Surface::Allocate(technology);
|
||||
if (!pixmapIndentGuide)
|
||||
pixmapIndentGuide = Surface::Allocate(technology);
|
||||
if (!pixmapIndentGuideHighlight)
|
||||
@ -307,13 +315,37 @@ void Editor::RefreshStyleData() {
|
||||
}
|
||||
}
|
||||
|
||||
Point Editor::GetVisibleOriginInMain() {
|
||||
return Point(0,0);
|
||||
}
|
||||
|
||||
Point Editor::DocumentPointFromView(Point ptView) {
|
||||
Point ptDocument = ptView;
|
||||
if (wMargin.GetID()) {
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
ptDocument.x += ptOrigin.x;
|
||||
ptDocument.y += ptOrigin.y;
|
||||
} else {
|
||||
ptDocument.x += xOffset;
|
||||
ptDocument.y += topLine * vs.lineHeight;
|
||||
}
|
||||
return ptDocument;
|
||||
}
|
||||
|
||||
int Editor::TopLineOfMain() {
|
||||
if (wMargin.GetID())
|
||||
return 0;
|
||||
else
|
||||
return topLine;
|
||||
}
|
||||
|
||||
PRectangle Editor::GetClientRectangle() {
|
||||
return wMain.GetClientPosition();
|
||||
}
|
||||
|
||||
PRectangle Editor::GetTextRectangle() {
|
||||
PRectangle rc = GetClientRectangle();
|
||||
rc.left += vs.fixedColumnWidth;
|
||||
rc.left += vs.textStart;
|
||||
rc.right -= vs.rightMarginWidth;
|
||||
return rc;
|
||||
}
|
||||
@ -436,7 +468,7 @@ Point Editor::LocationFromPosition(SelectionPosition pos) {
|
||||
pt.y += vs.lineHeight;
|
||||
}
|
||||
}
|
||||
pt.x += vs.fixedColumnWidth - xOffset;
|
||||
pt.x += vs.textStart - xOffset;
|
||||
}
|
||||
pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
|
||||
return pt;
|
||||
@ -448,12 +480,12 @@ Point Editor::LocationFromPosition(int pos) {
|
||||
|
||||
int Editor::XFromPosition(int pos) {
|
||||
Point pt = LocationFromPosition(pos);
|
||||
return pt.x - vs.fixedColumnWidth + xOffset;
|
||||
return pt.x - vs.textStart + xOffset;
|
||||
}
|
||||
|
||||
int Editor::XFromPosition(SelectionPosition sp) {
|
||||
Point pt = LocationFromPosition(sp);
|
||||
return pt.x - vs.fixedColumnWidth + xOffset;
|
||||
return pt.x - vs.textStart + xOffset;
|
||||
}
|
||||
|
||||
int Editor::LineFromLocation(Point pt) {
|
||||
@ -461,7 +493,7 @@ int Editor::LineFromLocation(Point pt) {
|
||||
}
|
||||
|
||||
void Editor::SetTopLine(int topLineNew) {
|
||||
if (topLine != topLineNew) {
|
||||
if ((topLine != topLineNew) && (topLineNew >= 0)) {
|
||||
topLine = topLineNew;
|
||||
ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
|
||||
}
|
||||
@ -474,16 +506,14 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid,
|
||||
PRectangle rcClient = GetTextRectangle();
|
||||
if (!rcClient.Contains(pt))
|
||||
return SelectionPosition(INVALID_POSITION);
|
||||
if (pt.x < vs.fixedColumnWidth)
|
||||
if (pt.x < vs.textStart)
|
||||
return SelectionPosition(INVALID_POSITION);
|
||||
if (pt.y < 0)
|
||||
return SelectionPosition(INVALID_POSITION);
|
||||
}
|
||||
pt.x = pt.x - vs.fixedColumnWidth + xOffset;
|
||||
int visibleLine = pt.y / vs.lineHeight + topLine;
|
||||
if (pt.y < 0) { // Division rounds towards 0
|
||||
visibleLine = (static_cast<int>(pt.y) - (vs.lineHeight - 1)) / vs.lineHeight + topLine;
|
||||
}
|
||||
pt = DocumentPointFromView(pt);
|
||||
pt.x = pt.x - vs.textStart;
|
||||
int visibleLine = floor(pt.y / vs.lineHeight);
|
||||
if (!canReturnInvalid && (visibleLine < 0))
|
||||
visibleLine = 0;
|
||||
int lineDoc = cs.DocFromDisplay(visibleLine);
|
||||
@ -622,6 +652,8 @@ void Editor::Redraw() {
|
||||
//Platform::DebugPrintf("Redraw all\n");
|
||||
PRectangle rcClient = GetClientRectangle();
|
||||
wMain.InvalidateRectangle(rcClient);
|
||||
if (wMargin.GetID())
|
||||
wMargin.InvalidateAll();
|
||||
//wMain.InvalidateAll();
|
||||
}
|
||||
|
||||
@ -631,7 +663,7 @@ void Editor::RedrawSelMargin(int line, bool allAfter) {
|
||||
Redraw();
|
||||
} else {
|
||||
PRectangle rcSelMargin = GetClientRectangle();
|
||||
rcSelMargin.right = vs.fixedColumnWidth;
|
||||
rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;
|
||||
if (line != -1) {
|
||||
int position = pdoc->LineStart(line);
|
||||
PRectangle rcLine = RectangleFromRange(position, position);
|
||||
@ -651,7 +683,13 @@ void Editor::RedrawSelMargin(int line, bool allAfter) {
|
||||
if (!allAfter)
|
||||
rcSelMargin.bottom = rcLine.bottom;
|
||||
}
|
||||
wMain.InvalidateRectangle(rcSelMargin);
|
||||
if (wMargin.GetID()) {
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y);
|
||||
wMargin.InvalidateRectangle(rcSelMargin);
|
||||
} else {
|
||||
wMain.InvalidateRectangle(rcSelMargin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -669,15 +707,12 @@ PRectangle Editor::RectangleFromRange(int start, int end) {
|
||||
PRectangle rcClient = GetTextRectangle();
|
||||
PRectangle rc;
|
||||
const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
|
||||
rc.left = vs.fixedColumnWidth - leftTextOverlap;
|
||||
rc.top = (minLine - topLine) * vs.lineHeight;
|
||||
if (rc.top < 0)
|
||||
rc.top = 0;
|
||||
rc.left = vs.textStart - leftTextOverlap;
|
||||
rc.top = (minLine - TopLineOfMain()) * vs.lineHeight;
|
||||
if (rc.top < rcClient.top)
|
||||
rc.top = rcClient.top;
|
||||
rc.right = rcClient.right;
|
||||
rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
|
||||
// Ensure PRectangle is within 16 bit space
|
||||
rc.top = Platform::Clamp(rc.top, -32000, 32000);
|
||||
rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
|
||||
rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -782,6 +817,7 @@ void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition ancho
|
||||
if (highlightDelimiter.NeedsDrawing(currentLine)) {
|
||||
RedrawSelMargin();
|
||||
}
|
||||
QueueIdleWork(WorkNeeded::workUpdateUI);
|
||||
}
|
||||
|
||||
void Editor::SetSelection(int currentPos_, int anchor_) {
|
||||
@ -808,6 +844,7 @@ void Editor::SetSelection(SelectionPosition currentPos_) {
|
||||
if (highlightDelimiter.NeedsDrawing(currentLine)) {
|
||||
RedrawSelMargin();
|
||||
}
|
||||
QueueIdleWork(WorkNeeded::workUpdateUI);
|
||||
}
|
||||
|
||||
void Editor::SetSelection(int currentPos_) {
|
||||
@ -828,6 +865,7 @@ void Editor::SetEmptySelection(SelectionPosition currentPos_) {
|
||||
if (highlightDelimiter.NeedsDrawing(currentLine)) {
|
||||
RedrawSelMargin();
|
||||
}
|
||||
QueueIdleWork(WorkNeeded::workUpdateUI);
|
||||
}
|
||||
|
||||
void Editor::SetEmptySelection(int currentPos_) {
|
||||
@ -924,7 +962,8 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b
|
||||
// In case in need of wrapping to ensure DisplayFromDoc works.
|
||||
if (currentLine >= wrapStart)
|
||||
WrapLines(true, -1);
|
||||
XYScrollPosition newXY = XYScrollToMakeVisible(true, true, true);
|
||||
XYScrollPosition newXY = XYScrollToMakeVisible(
|
||||
SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);
|
||||
if (simpleCaret && (newXY.xOffset == xOffset)) {
|
||||
// simple vertical scroll then invalidate
|
||||
ScrollTo(newXY.topLine);
|
||||
@ -1195,17 +1234,22 @@ slop | strict | jumps | even | Caret can go to the margin | When
|
||||
1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
|
||||
*/
|
||||
|
||||
Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz) {
|
||||
Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {
|
||||
PRectangle rcClient = GetTextRectangle();
|
||||
const SelectionPosition posCaret = posDrag.IsValid() ? posDrag : sel.RangeMain().caret;
|
||||
const Point pt = LocationFromPosition(posCaret);
|
||||
Point pt = LocationFromPosition(range.caret);
|
||||
Point ptAnchor = LocationFromPosition(range.anchor);
|
||||
const Point ptOrigin = GetVisibleOriginInMain();
|
||||
pt.x += ptOrigin.x;
|
||||
pt.y += ptOrigin.y;
|
||||
ptAnchor.x += ptOrigin.x;
|
||||
ptAnchor.y += ptOrigin.y;
|
||||
const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
|
||||
const int lineCaret = DisplayFromPosition(posCaret.Position());
|
||||
|
||||
XYScrollPosition newXY(xOffset, topLine);
|
||||
|
||||
// Vertical positioning
|
||||
if (vert && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
|
||||
if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
|
||||
const int lineCaret = DisplayFromPosition(range.caret.Position());
|
||||
const int linesOnScreen = LinesOnScreen();
|
||||
const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
|
||||
const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
|
||||
@ -1219,7 +1263,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con
|
||||
int yMoveT, yMoveB;
|
||||
if (bStrict) {
|
||||
int yMarginT, yMarginB;
|
||||
if (!useMargin) {
|
||||
if (!(options & xysUseMargin)) {
|
||||
// In drag mode, avoid moves
|
||||
// otherwise, a double click will select several lines.
|
||||
yMarginT = yMarginB = 0;
|
||||
@ -1289,11 +1333,23 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(range.caret == range.anchor)) {
|
||||
const int lineAnchor = DisplayFromPosition(range.anchor.Position());
|
||||
if (lineAnchor < lineCaret) {
|
||||
// Shift up to show anchor or as much of range as possible
|
||||
newXY.topLine = std::min(newXY.topLine, lineAnchor);
|
||||
newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
|
||||
} else {
|
||||
// Shift down to show anchor or as much of range as possible
|
||||
newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
|
||||
newXY.topLine = std::min(newXY.topLine, lineCaret);
|
||||
}
|
||||
}
|
||||
newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
|
||||
}
|
||||
|
||||
// Horizontal positioning
|
||||
if (horiz && (wrapState == eWrapNone)) {
|
||||
if ((options & xysHorizontal) && (wrapState == eWrapNone)) {
|
||||
const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
|
||||
const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
|
||||
const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
|
||||
@ -1304,7 +1360,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con
|
||||
int xMoveL, xMoveR;
|
||||
if (bStrict) {
|
||||
int xMarginL, xMarginR;
|
||||
if (!useMargin) {
|
||||
if (!(options & xysUseMargin)) {
|
||||
// In drag mode, avoid moves unless very near of the margin
|
||||
// otherwise, a simple click will select text.
|
||||
xMarginL = xMarginR = 2;
|
||||
@ -1393,6 +1449,21 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con
|
||||
newXY.xOffset += static_cast<int>(vs.aveCharWidth);
|
||||
}
|
||||
}
|
||||
if (!(range.caret == range.anchor)) {
|
||||
if (ptAnchor.x < pt.x) {
|
||||
// Shift to left to show anchor or as much of range as possible
|
||||
int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1;
|
||||
int minOffset = pt.x + xOffset - rcClient.right + 1;
|
||||
newXY.xOffset = std::min(newXY.xOffset, maxOffset);
|
||||
newXY.xOffset = std::max(newXY.xOffset, minOffset);
|
||||
} else {
|
||||
// Shift to right to show anchor or as much of range as possible
|
||||
int minOffset = ptAnchor.x + xOffset - rcClient.right + 1;
|
||||
int maxOffset = pt.x + xOffset - rcClient.left - 1;
|
||||
newXY.xOffset = std::max(newXY.xOffset, minOffset);
|
||||
newXY.xOffset = std::min(newXY.xOffset, maxOffset);
|
||||
}
|
||||
}
|
||||
if (newXY.xOffset < 0) {
|
||||
newXY.xOffset = 0;
|
||||
}
|
||||
@ -1425,8 +1496,13 @@ void Editor::SetXYScroll(XYScrollPosition newXY) {
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::ScrollRange(SelectionRange range) {
|
||||
SetXYScroll(XYScrollToMakeVisible(range, xysDefault));
|
||||
}
|
||||
|
||||
void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
|
||||
SetXYScroll(XYScrollToMakeVisible(useMargin, vert, horiz));
|
||||
SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
|
||||
static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));
|
||||
}
|
||||
|
||||
void Editor::ShowCaretAtCurrentPosition() {
|
||||
@ -1542,8 +1618,8 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
|
||||
int lineDocTop = cs.DocFromDisplay(topLine);
|
||||
int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
|
||||
PRectangle rcTextArea = GetClientRectangle();
|
||||
rcTextArea.left = vs.fixedColumnWidth;
|
||||
rcTextArea.right -= vs.rightMarginWidth;
|
||||
rcTextArea.left = vs.textStart;
|
||||
rcTextArea.right -= vs.textStart;
|
||||
wrapWidth = rcTextArea.Width();
|
||||
RefreshStyleData();
|
||||
AutoSurface surface(this);
|
||||
@ -1606,7 +1682,7 @@ void Editor::LinesJoin() {
|
||||
UndoGroup ug(pdoc);
|
||||
bool prevNonWS = true;
|
||||
for (int pos = targetStart; pos < targetEnd; pos++) {
|
||||
if (IsEOLChar(pdoc->CharAt(pos))) {
|
||||
if (pdoc->IsPositionInLineEnd(pos)) {
|
||||
targetEnd -= pdoc->LenChar(pos);
|
||||
pdoc->DelChar(pos);
|
||||
if (prevNonWS) {
|
||||
@ -1753,7 +1829,12 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
|
||||
if (vs.fixedColumnWidth == 0)
|
||||
return;
|
||||
|
||||
RefreshPixMaps(surfWindow);
|
||||
|
||||
PRectangle rcMargin = GetClientRectangle();
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
rcMargin.Move(0, -ptOrigin.y);
|
||||
rcMargin.left = 0;
|
||||
rcMargin.right = vs.fixedColumnWidth;
|
||||
|
||||
if (!rc.Intersects(rcMargin))
|
||||
@ -1774,18 +1855,24 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
|
||||
|
||||
PRectangle rcSelMargin = rcMargin;
|
||||
rcSelMargin.right = rcMargin.left;
|
||||
if (rcSelMargin.bottom < rc.bottom)
|
||||
rcSelMargin.bottom = rc.bottom;
|
||||
|
||||
for (int margin = 0; margin < vs.margins; margin++) {
|
||||
for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
if (vs.ms[margin].width > 0) {
|
||||
|
||||
rcSelMargin.left = rcSelMargin.right;
|
||||
rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
|
||||
|
||||
if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
|
||||
if (vs.ms[margin].mask & SC_MASK_FOLDERS)
|
||||
if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
|
||||
// Required because of special way brush is created for selection margin
|
||||
surface->FillRectangle(rcSelMargin, *pixmapSelPattern);
|
||||
else {
|
||||
// Ensure patterns line up when scrolling with separate margin view
|
||||
// by choosing correctly aligned variant.
|
||||
bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
|
||||
surface->FillRectangle(rcSelMargin,
|
||||
invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
|
||||
} else {
|
||||
ColourDesired colour;
|
||||
switch (vs.ms[margin].style) {
|
||||
case SC_MARGIN_BACK:
|
||||
@ -1804,9 +1891,9 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
|
||||
surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
|
||||
}
|
||||
|
||||
const int lineStartPaint = rcMargin.top / vs.lineHeight;
|
||||
int visibleLine = topLine + lineStartPaint;
|
||||
int yposScreen = lineStartPaint * vs.lineHeight;
|
||||
const int lineStartPaint = (rcMargin.top + ptOrigin.y) / vs.lineHeight;
|
||||
int visibleLine = TopLineOfMain() + lineStartPaint;
|
||||
int yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
|
||||
// Work out whether the top line is whitespace located after a
|
||||
// lessening of fold level which implies a 'fold tail' but which should not
|
||||
// be displayed until the last of a sequence of whitespace.
|
||||
@ -1837,7 +1924,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
|
||||
int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
|
||||
SC_MARKNUM_FOLDER);
|
||||
|
||||
while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) {
|
||||
while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) {
|
||||
|
||||
PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
|
||||
int lineDoc = cs.DocFromDisplay(visibleLine);
|
||||
@ -1947,8 +2034,9 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
|
||||
rcMarker.bottom = yposScreen + vs.lineHeight;
|
||||
if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
|
||||
if (firstSubLine) {
|
||||
char number[100];
|
||||
sprintf(number, "%d", lineDoc + 1);
|
||||
char number[100] = "";
|
||||
if (lineDoc >= 0)
|
||||
sprintf(number, "%d", lineDoc + 1);
|
||||
if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
|
||||
int lev = pdoc->GetLevel(lineDoc);
|
||||
sprintf(number, "%c%c %03X %03X",
|
||||
@ -2193,7 +2281,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
|
||||
bool isBadUTF = isBadUTFNext;
|
||||
isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
|
||||
if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
|
||||
isControl || isControlNext || isBadUTF || isBadUTFNext) {
|
||||
isControl || isControlNext || isBadUTF || isBadUTFNext || ((charInLine+1) >= numCharsBeforeEOL)) {
|
||||
ll->positions[startseg] = 0;
|
||||
if (vstyle.styles[ll->styles[charInLine]].visible) {
|
||||
if (isControl) {
|
||||
@ -2213,7 +2301,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
|
||||
ll->positions + startseg + 1);
|
||||
}
|
||||
lastSegItalics = false;
|
||||
} else if (isBadUTF) {
|
||||
} else if ((isBadUTF) || (charInLine >= numCharsBeforeEOL)) {
|
||||
char hexits[4];
|
||||
sprintf(hexits, "x%2X", ll->chars[charInLine] & 0xff);
|
||||
ll->positions[charInLine + 1] =
|
||||
@ -2504,7 +2592,15 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin
|
||||
rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
|
||||
rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
|
||||
blobsWidth += rcSegment.Width();
|
||||
const char *ctrlChar = ControlCharacterString(ll->chars[eolPos]);
|
||||
char hexits[4];
|
||||
const char *ctrlChar;
|
||||
unsigned char chEOL = ll->chars[eolPos];
|
||||
if (UTF8IsAscii(chEOL)) {
|
||||
ctrlChar = ControlCharacterString(chEOL);
|
||||
} else {
|
||||
sprintf(hexits, "x%2X", chEOL);
|
||||
ctrlChar = hexits;
|
||||
}
|
||||
int styleMain = ll->styles[eolPos];
|
||||
ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll);
|
||||
ColourDesired textFore = vsDraw.styles[styleMain].fore;
|
||||
@ -2743,7 +2839,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
|
||||
// the color for the highest numbered one is used.
|
||||
bool overrideBackground = false;
|
||||
ColourDesired background;
|
||||
if (caret.active && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
|
||||
if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
|
||||
overrideBackground = true;
|
||||
background = vsDraw.caretLineBackground;
|
||||
}
|
||||
@ -2989,12 +3085,6 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
|
||||
textBack = vsDraw.whitespaceBackground;
|
||||
surface->FillRectangle(rcSegment, textBack);
|
||||
}
|
||||
if ((vsDraw.viewWhitespace != wsInvisible) ||
|
||||
(inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
|
||||
if (vsDraw.whitespaceForegroundSet)
|
||||
textFore = vsDraw.whitespaceForeground;
|
||||
surface->PenColour(textFore);
|
||||
}
|
||||
if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
|
||||
for (int indentCount = (ll->positions[i] + epsilon) / indentWidth;
|
||||
indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
|
||||
@ -3008,6 +3098,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
|
||||
}
|
||||
if (vsDraw.viewWhitespace != wsInvisible) {
|
||||
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
|
||||
if (vsDraw.whitespaceForegroundSet)
|
||||
textFore = vsDraw.whitespaceForeground;
|
||||
surface->PenColour(textFore);
|
||||
PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
|
||||
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
|
||||
DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
|
||||
@ -3193,7 +3286,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
|
||||
|
||||
// Draw any translucent whole line states
|
||||
rcSegment = rcLine;
|
||||
if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) {
|
||||
if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
|
||||
SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
|
||||
}
|
||||
marks = pdoc->GetMark(line);
|
||||
@ -3289,6 +3382,7 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
|
||||
if (!pixmapSelPattern->Initialised()) {
|
||||
const int patternSize = 8;
|
||||
pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
|
||||
pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
|
||||
// This complex procedure is to reproduce the checkerboard dithered pattern used by windows
|
||||
// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
|
||||
// way between the chrome colour and the chrome highlight colour making a nice transition
|
||||
@ -3315,10 +3409,12 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
|
||||
}
|
||||
|
||||
pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
|
||||
pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
|
||||
for (int y = 0; y < patternSize; y++) {
|
||||
for (int x = y % 2; x < patternSize; x+=2) {
|
||||
PRectangle rcPixel(x, y, x+1, y+1);
|
||||
pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
|
||||
pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3446,22 +3542,20 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
StyleToPositionInView(PositionAfterArea(rcArea));
|
||||
|
||||
PRectangle rcClient = GetClientRectangle();
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
//Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
|
||||
// rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
|
||||
|
||||
int screenLinePaintFirst = rcArea.top / vs.lineHeight;
|
||||
|
||||
int xStart = vs.fixedColumnWidth - xOffset;
|
||||
int xStart = vs.textStart - xOffset + ptOrigin.x;
|
||||
int ypos = 0;
|
||||
if (!bufferedDraw)
|
||||
ypos += screenLinePaintFirst * vs.lineHeight;
|
||||
int yposScreen = screenLinePaintFirst * vs.lineHeight;
|
||||
|
||||
bool paintAbandonedByStyling = paintState == paintAbandoned;
|
||||
if (needUpdateUI) {
|
||||
NotifyUpdateUI();
|
||||
needUpdateUI = 0;
|
||||
|
||||
if (NotifyUpdateUI()) {
|
||||
RefreshStyleData();
|
||||
RefreshPixMaps(surfaceWindow);
|
||||
}
|
||||
@ -3486,12 +3580,20 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
surfaceWindow->SetClip(rcArea);
|
||||
|
||||
if (paintState != paintAbandoned) {
|
||||
PaintSelMargin(surfaceWindow, rcArea);
|
||||
|
||||
PRectangle rcRightMargin = rcClient;
|
||||
rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
|
||||
if (rcArea.Intersects(rcRightMargin)) {
|
||||
surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
|
||||
if (vs.marginInside) {
|
||||
PaintSelMargin(surfaceWindow, rcArea);
|
||||
PRectangle rcRightMargin = rcClient;
|
||||
rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
|
||||
if (rcArea.Intersects(rcRightMargin)) {
|
||||
surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
|
||||
}
|
||||
} else { // Else separate view so separate paint event but leftMargin included to allow overlap
|
||||
PRectangle rcLeftMargin = rcArea;
|
||||
rcLeftMargin.left = 0;
|
||||
rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
|
||||
if (rcArea.Intersects(rcLeftMargin)) {
|
||||
surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3515,7 +3617,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
|
||||
|
||||
// Do the painting
|
||||
if (rcArea.right > vs.fixedColumnWidth - leftTextOverlap) {
|
||||
if (rcArea.right > vs.textStart - leftTextOverlap) {
|
||||
|
||||
Surface *surface = surfaceWindow;
|
||||
if (bufferedDraw) {
|
||||
@ -3525,7 +3627,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
surface->SetUnicodeMode(IsUnicodeMode());
|
||||
surface->SetDBCSMode(CodePage());
|
||||
|
||||
int visibleLine = topLine + screenLinePaintFirst;
|
||||
int visibleLine = TopLineOfMain() + screenLinePaintFirst;
|
||||
|
||||
SelectionPosition posCaret = sel.RangeMain().caret;
|
||||
if (posDrag.IsValid())
|
||||
@ -3533,12 +3635,16 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
int lineCaret = pdoc->LineFromPosition(posCaret.Position());
|
||||
|
||||
PRectangle rcTextArea = rcClient;
|
||||
rcTextArea.left = vs.fixedColumnWidth;
|
||||
rcTextArea.right -= vs.rightMarginWidth;
|
||||
if (vs.marginInside) {
|
||||
rcTextArea.left += vs.textStart;
|
||||
rcTextArea.right -= vs.rightMarginWidth;
|
||||
} else {
|
||||
rcTextArea = rcArea;
|
||||
}
|
||||
|
||||
// Remove selection margin from drawing area so text will not be drawn
|
||||
// on it in unbuffered mode.
|
||||
if (!bufferedDraw) {
|
||||
if (!bufferedDraw && vs.marginInside) {
|
||||
PRectangle rcClipText = rcTextArea;
|
||||
rcClipText.left -= leftTextOverlap;
|
||||
surfaceWindow->SetClip(rcClipText);
|
||||
@ -3632,8 +3738,8 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);
|
||||
|
||||
if (bufferedDraw) {
|
||||
Point from(vs.fixedColumnWidth-leftTextOverlap, 0);
|
||||
PRectangle rcCopyArea(vs.fixedColumnWidth-leftTextOverlap, yposScreen,
|
||||
Point from(vs.textStart-leftTextOverlap, 0);
|
||||
PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen,
|
||||
rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight);
|
||||
surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
|
||||
}
|
||||
@ -3657,10 +3763,10 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
|
||||
// durPaint = 0.00000001;
|
||||
|
||||
// Right column limit indicator
|
||||
PRectangle rcBeyondEOF = rcClient;
|
||||
rcBeyondEOF.left = vs.fixedColumnWidth;
|
||||
rcBeyondEOF.right = rcBeyondEOF.right - vs.rightMarginWidth;
|
||||
rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
|
||||
PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea;
|
||||
rcBeyondEOF.left = vs.textStart;
|
||||
rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0);
|
||||
rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight;
|
||||
if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
|
||||
surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back);
|
||||
if (vs.edgeState == EDGE_LINE) {
|
||||
@ -3718,7 +3824,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
|
||||
// Modify the view style for printing as do not normally want any of the transient features to be printed
|
||||
// Printing supports only the line number margin.
|
||||
int lineNumberIndex = -1;
|
||||
for (int margin = 0; margin < ViewStyle::margins; margin++) {
|
||||
for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
|
||||
lineNumberIndex = margin;
|
||||
} else {
|
||||
@ -3738,6 +3844,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
|
||||
vsPrint.whitespaceBackgroundSet = false;
|
||||
vsPrint.whitespaceForegroundSet = false;
|
||||
vsPrint.showCaretLineBackground = false;
|
||||
vsPrint.alwaysShowCaretLineBackground = false;
|
||||
// Don't highlight matching braces using indicators
|
||||
vsPrint.braceHighlightIndicatorSet = false;
|
||||
vsPrint.braceBadLightIndicatorSet = false;
|
||||
@ -3813,7 +3920,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
|
||||
|
||||
// Copy this line and its styles from the document into local arrays
|
||||
// and determine the x position at which each character starts.
|
||||
LineLayout ll(8000);
|
||||
LineLayout ll(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1);
|
||||
LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);
|
||||
|
||||
ll.containsCaret = false;
|
||||
@ -3929,7 +4036,7 @@ void Editor::ChangeSize() {
|
||||
SetScrollBars();
|
||||
if (wrapState != eWrapNone) {
|
||||
PRectangle rcTextArea = GetClientRectangle();
|
||||
rcTextArea.left = vs.fixedColumnWidth;
|
||||
rcTextArea.left = vs.textStart;
|
||||
rcTextArea.right -= vs.rightMarginWidth;
|
||||
if (wrapWidth != rcTextArea.Width()) {
|
||||
NeedWrapping();
|
||||
@ -3994,7 +4101,7 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
|
||||
}
|
||||
} else if (inOverstrike) {
|
||||
if (positionInsert < pdoc->Length()) {
|
||||
if (!IsEOLChar(pdoc->CharAt(positionInsert))) {
|
||||
if (!pdoc->IsPositionInLineEnd(positionInsert)) {
|
||||
pdoc->DelChar(positionInsert);
|
||||
currentSel->ClearVirtualSpace();
|
||||
}
|
||||
@ -4239,7 +4346,7 @@ void Editor::Clear() {
|
||||
else
|
||||
sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
|
||||
}
|
||||
if ((sel.Count() == 1) || !IsEOLChar(pdoc->CharAt(sel.Range(r).caret.Position()))) {
|
||||
if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
|
||||
pdoc->DelChar(sel.Range(r).caret.Position());
|
||||
sel.Range(r).ClearVirtualSpace();
|
||||
} // else multiple selection so don't eat line ends
|
||||
@ -4417,11 +4524,16 @@ void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool
|
||||
NotifyParent(scn);
|
||||
}
|
||||
|
||||
void Editor::NotifyUpdateUI() {
|
||||
SCNotification scn = {0};
|
||||
scn.nmhdr.code = SCN_UPDATEUI;
|
||||
scn.updated = needUpdateUI;
|
||||
NotifyParent(scn);
|
||||
bool Editor::NotifyUpdateUI() {
|
||||
if (needUpdateUI) {
|
||||
SCNotification scn = {0};
|
||||
scn.nmhdr.code = SCN_UPDATEUI;
|
||||
scn.updated = needUpdateUI;
|
||||
NotifyParent(scn);
|
||||
needUpdateUI = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Editor::NotifyPainted() {
|
||||
@ -4444,8 +4556,8 @@ void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctr
|
||||
|
||||
bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
|
||||
int marginClicked = -1;
|
||||
int x = 0;
|
||||
for (int margin = 0; margin < ViewStyle::margins; margin++) {
|
||||
int x = vs.textStart - vs.fixedColumnWidth;
|
||||
for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
|
||||
marginClicked = margin;
|
||||
x += vs.ms[margin].width;
|
||||
@ -4629,18 +4741,13 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {
|
||||
}
|
||||
}
|
||||
|
||||
//Platform::DebugPrintf("** %x Doc Changed\n", this);
|
||||
// TODO: could invalidate from mh.startModification to end of screen
|
||||
//InvalidateRange(mh.position, mh.position + mh.length);
|
||||
if (paintState == notPainting && !CanDeferToLastStep(mh)) {
|
||||
QueueStyling(pdoc->Length());
|
||||
QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
|
||||
Redraw();
|
||||
}
|
||||
} else {
|
||||
//Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
|
||||
// mh.position, mh.position + mh.length);
|
||||
if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
|
||||
QueueStyling(mh.position + mh.length);
|
||||
QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
|
||||
InvalidateRange(mh.position, mh.position + mh.length);
|
||||
}
|
||||
}
|
||||
@ -5168,6 +5275,8 @@ int Editor::KeyCommand(unsigned int iMessage) {
|
||||
SelectionPosition spCaret = sel.RangeMain().caret;
|
||||
spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
|
||||
MovePositionTo(spCaret);
|
||||
} else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
|
||||
MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1));
|
||||
} else {
|
||||
MovePositionTo(MovePositionSoVisible(
|
||||
SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1));
|
||||
@ -5203,6 +5312,8 @@ int Editor::KeyCommand(unsigned int iMessage) {
|
||||
SelectionPosition spCaret = sel.RangeMain().caret;
|
||||
spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
|
||||
MovePositionTo(spCaret);
|
||||
} else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
|
||||
MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1));
|
||||
} else {
|
||||
MovePositionTo(MovePositionSoVisible(
|
||||
SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1));
|
||||
@ -6099,7 +6210,8 @@ bool Editor::PointInSelMargin(Point pt) {
|
||||
// Really means: "Point in a margin"
|
||||
if (vs.fixedColumnWidth > 0) { // There is a margin
|
||||
PRectangle rcSelMargin = GetClientRectangle();
|
||||
rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
|
||||
rcSelMargin.right = vs.textStart - vs.leftMarginWidth;
|
||||
rcSelMargin.left = vs.textStart - vs.fixedColumnWidth;
|
||||
return rcSelMargin.Contains(pt);
|
||||
} else {
|
||||
return false;
|
||||
@ -6108,7 +6220,7 @@ bool Editor::PointInSelMargin(Point pt) {
|
||||
|
||||
Window::Cursor Editor::GetMarginCursor(Point pt) {
|
||||
int x = 0;
|
||||
for (int margin = 0; margin < ViewStyle::margins; margin++) {
|
||||
for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
|
||||
return static_cast<Window::Cursor>(vs.ms[margin].cursor);
|
||||
x += vs.ms[margin].width;
|
||||
@ -6489,6 +6601,8 @@ void Editor::ButtonMove(Point pt) {
|
||||
|
||||
// Autoscroll
|
||||
PRectangle rcClient = GetClientRectangle();
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
rcClient.Move(0, -ptOrigin.y);
|
||||
int lineMove = DisplayFromPosition(movePos.Position());
|
||||
if (pt.y > rcClient.bottom) {
|
||||
ScrollTo(lineMove - LinesOnScreen() + 1);
|
||||
@ -6688,7 +6802,7 @@ int Editor::PositionAfterArea(PRectangle rcArea) {
|
||||
// Style to a position within the view. If this causes a change at end of last line then
|
||||
// affects later lines so style all the viewed text.
|
||||
void Editor::StyleToPositionInView(Position pos) {
|
||||
int endWindow = PositionAfterArea(GetClientRectangle());
|
||||
int endWindow = (vs.marginInside) ? (PositionAfterArea(GetClientRectangle())) : (pdoc->Length());
|
||||
if (pos > endWindow)
|
||||
pos = endWindow;
|
||||
int styleAtEnd = pdoc->StyleAt(pos-1);
|
||||
@ -6700,20 +6814,18 @@ void Editor::StyleToPositionInView(Position pos) {
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::IdleStyling() {
|
||||
void Editor::IdleWork() {
|
||||
// Style the line after the modification as this allows modifications that change just the
|
||||
// line of the modification to heal instead of propagating to the rest of the window.
|
||||
StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(styleNeeded.upTo) + 2));
|
||||
if (workNeeded.items & WorkNeeded::workStyle)
|
||||
StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));
|
||||
|
||||
if (needUpdateUI) {
|
||||
NotifyUpdateUI();
|
||||
needUpdateUI = 0;
|
||||
}
|
||||
styleNeeded.Reset();
|
||||
NotifyUpdateUI();
|
||||
workNeeded.Reset();
|
||||
}
|
||||
|
||||
void Editor::QueueStyling(int upTo) {
|
||||
styleNeeded.NeedUpTo(upTo);
|
||||
void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
|
||||
workNeeded.Need(items, upTo);
|
||||
}
|
||||
|
||||
bool Editor::PaintContains(PRectangle rc) {
|
||||
@ -6725,8 +6837,13 @@ bool Editor::PaintContains(PRectangle rc) {
|
||||
}
|
||||
|
||||
bool Editor::PaintContainsMargin() {
|
||||
if (wMargin.GetID()) {
|
||||
// With separate margin view, paint of text view
|
||||
// never contains margin.
|
||||
return false;
|
||||
}
|
||||
PRectangle rcSelMargin = GetClientRectangle();
|
||||
rcSelMargin.right = vs.fixedColumnWidth;
|
||||
rcSelMargin.right = vs.textStart;
|
||||
return PaintContains(rcSelMargin);
|
||||
}
|
||||
|
||||
@ -6811,6 +6928,8 @@ void Editor::SetDocPointer(Document *document) {
|
||||
braces[0] = invalidPosition;
|
||||
braces[1] = invalidPosition;
|
||||
|
||||
vs.ReleaseAllExtendedStyles();
|
||||
|
||||
// Reset the contraction state to fully shown.
|
||||
cs.Clear();
|
||||
cs.InsertLines(0, pdoc->LinesTotal() - 1);
|
||||
@ -6922,12 +7041,17 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
|
||||
WrapLines(true, -1);
|
||||
|
||||
if (!cs.GetVisible(lineDoc)) {
|
||||
// Back up to find a non-blank line
|
||||
int lookLine = lineDoc;
|
||||
int lookLineLevel = pdoc->GetLevel(lookLine);
|
||||
while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
|
||||
lookLineLevel = pdoc->GetLevel(--lookLine);
|
||||
}
|
||||
int lineParent = pdoc->GetFoldParent(lookLine);
|
||||
if (lineParent < 0) {
|
||||
// Backed up to a top level line, so try to find parent of initial line
|
||||
lineParent = pdoc->GetFoldParent(lineDoc);
|
||||
}
|
||||
if (lineParent >= 0) {
|
||||
if (lineDoc != lineParent)
|
||||
EnsureLineVisible(lineParent, enforcePolicy);
|
||||
@ -7040,7 +7164,7 @@ void Editor::AddStyledText(char *buffer, int appendLength) {
|
||||
}
|
||||
|
||||
static bool ValidMargin(unsigned long wParam) {
|
||||
return wParam < ViewStyle::margins;
|
||||
return wParam <= SC_MAX_MARGIN;
|
||||
}
|
||||
|
||||
static char *CharPtrFromSPtr(sptr_t lParam) {
|
||||
@ -7398,7 +7522,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
|
||||
case SCI_LINESCROLL:
|
||||
ScrollTo(topLine + lParam);
|
||||
HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
|
||||
HorizontalScrollTo(xOffset + static_cast<int>(wParam) * vs.spaceWidth);
|
||||
return 1;
|
||||
|
||||
case SCI_SETXOFFSET:
|
||||
@ -7434,7 +7558,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
return 0;
|
||||
} else {
|
||||
Point pt = LocationFromPosition(lParam);
|
||||
return pt.x;
|
||||
// Convert to view-relative
|
||||
return pt.x - vs.textStart + vs.fixedColumnWidth;
|
||||
}
|
||||
|
||||
case SCI_POINTYFROMPOSITION:
|
||||
@ -7771,6 +7896,21 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
pdoc->eolMode = wParam;
|
||||
break;
|
||||
|
||||
case SCI_SETLINEENDTYPESALLOWED:
|
||||
if (pdoc->SetLineEndTypesAllowed(wParam)) {
|
||||
cs.Clear();
|
||||
cs.InsertLines(0, pdoc->LinesTotal() - 1);
|
||||
SetAnnotationHeights(0, pdoc->LinesTotal());
|
||||
InvalidateStyleRedraw();
|
||||
}
|
||||
break;
|
||||
|
||||
case SCI_GETLINEENDTYPESALLOWED:
|
||||
return pdoc->GetLineEndTypesAllowed();
|
||||
|
||||
case SCI_GETLINEENDTYPESACTIVE:
|
||||
return pdoc->GetLineEndTypesActive();
|
||||
|
||||
case SCI_STARTSTYLING:
|
||||
pdoc->StartStyling(wParam, static_cast<char>(lParam));
|
||||
break;
|
||||
@ -8037,6 +8177,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
verticalScrollBarVisible = wParam != 0;
|
||||
SetScrollBars();
|
||||
ReconfigureScrollBars();
|
||||
if (verticalScrollBarVisible)
|
||||
SetVerticalScrollPos();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -8067,6 +8209,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
case SCI_SETCODEPAGE:
|
||||
if (ValidCodePage(wParam)) {
|
||||
if (pdoc->SetDBCSCodePage(wParam)) {
|
||||
cs.Clear();
|
||||
cs.InsertLines(0, pdoc->LinesTotal() - 1);
|
||||
SetAnnotationHeights(0, pdoc->LinesTotal());
|
||||
InvalidateStyleRedraw();
|
||||
}
|
||||
}
|
||||
@ -8321,6 +8466,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
vs.showCaretLineBackground = wParam != 0;
|
||||
InvalidateStyleRedraw();
|
||||
break;
|
||||
case SCI_GETCARETLINEVISIBLEALWAYS:
|
||||
return vs.alwaysShowCaretLineBackground;
|
||||
case SCI_SETCARETLINEVISIBLEALWAYS:
|
||||
vs.alwaysShowCaretLineBackground = wParam != 0;
|
||||
InvalidateStyleRedraw();
|
||||
break;
|
||||
|
||||
case SCI_GETCARETLINEBACK:
|
||||
return vs.caretLineBackground.AsLong();
|
||||
case SCI_SETCARETLINEBACK:
|
||||
@ -8409,6 +8561,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
EnsureLineVisible(wParam, true);
|
||||
break;
|
||||
|
||||
case SCI_SCROLLRANGE:
|
||||
ScrollRange(SelectionRange(lParam, wParam));
|
||||
break;
|
||||
|
||||
case SCI_SEARCHANCHOR:
|
||||
SearchAnchor();
|
||||
break;
|
||||
@ -9123,6 +9279,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
|
||||
case SCI_ANNOTATIONGETSTYLEOFFSET:
|
||||
return vs.annotationStyleOffset;
|
||||
|
||||
case SCI_RELEASEALLEXTENDEDSTYLES:
|
||||
vs.ReleaseAllExtendedStyles();
|
||||
break;
|
||||
|
||||
case SCI_ALLOCATEEXTENDEDSTYLES:
|
||||
return vs.AllocateExtendedStyles(wParam);
|
||||
|
||||
case SCI_ADDUNDOACTION:
|
||||
pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
|
||||
break;
|
||||
|
@ -47,21 +47,30 @@ public:
|
||||
|
||||
/**
|
||||
* When platform has a way to generate an event before painting,
|
||||
* accumulate needed styling range in StyleNeeded to avoid unnecessary work.
|
||||
* accumulate needed styling range and other work items in
|
||||
* WorkNeeded to avoid unnecessary work inside paint handler
|
||||
*/
|
||||
class StyleNeeded {
|
||||
class WorkNeeded {
|
||||
public:
|
||||
enum workItems {
|
||||
workNone=0,
|
||||
workStyle=1,
|
||||
workUpdateUI=2
|
||||
};
|
||||
bool active;
|
||||
enum workItems items;
|
||||
Position upTo;
|
||||
|
||||
StyleNeeded() : active(false), upTo(0) {}
|
||||
WorkNeeded() : active(false), items(workNone), upTo(0) {}
|
||||
void Reset() {
|
||||
active = false;
|
||||
items = workNone;
|
||||
upTo = 0;
|
||||
}
|
||||
void NeedUpTo(Position pos) {
|
||||
if (upTo < pos)
|
||||
void Need(workItems items_, Position pos) {
|
||||
if ((items_ & workStyle) && (upTo < pos))
|
||||
upTo = pos;
|
||||
items = static_cast<workItems>(items | items_);
|
||||
}
|
||||
};
|
||||
|
||||
@ -95,6 +104,7 @@ public:
|
||||
characterSet = characterSet_;
|
||||
rectangular = rectangular_;
|
||||
lineCopy = lineCopy_;
|
||||
FixSelectionForClipboard();
|
||||
}
|
||||
void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
|
||||
delete []s;
|
||||
@ -108,10 +118,22 @@ public:
|
||||
characterSet = characterSet_;
|
||||
rectangular = rectangular_;
|
||||
lineCopy = lineCopy_;
|
||||
FixSelectionForClipboard();
|
||||
}
|
||||
void Copy(const SelectionText &other) {
|
||||
Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
|
||||
}
|
||||
|
||||
private:
|
||||
void FixSelectionForClipboard() {
|
||||
// Replace null characters by spaces.
|
||||
// To avoid that the content of the clipboard is truncated in the paste operation
|
||||
// when the clipboard contains null characters.
|
||||
for (int i = 0; i < len - 1; ++i) {
|
||||
if (s[i] == '\0')
|
||||
s[i] = ' ';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -126,6 +148,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
/** On GTK+, Scintilla is a container widget holding two scroll bars
|
||||
* whereas on Windows there is just one window with both scroll bars turned on. */
|
||||
Window wMain; ///< The Scintilla parent window
|
||||
Window wMargin; ///< May be separate when using a scroll view for wMain
|
||||
|
||||
/** Style resources may be expensive to allocate so are cached between uses.
|
||||
* When a style attribute is changed, this cache is flushed. */
|
||||
@ -177,6 +200,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
Surface *pixmapLine;
|
||||
Surface *pixmapSelMargin;
|
||||
Surface *pixmapSelPattern;
|
||||
Surface *pixmapSelPatternOffset1;
|
||||
Surface *pixmapIndentGuide;
|
||||
Surface *pixmapIndentGuideHighlight;
|
||||
|
||||
@ -228,7 +252,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
PRectangle rcPaint;
|
||||
bool paintingAllText;
|
||||
bool willRedrawAll;
|
||||
StyleNeeded styleNeeded;
|
||||
WorkNeeded workNeeded;
|
||||
|
||||
int modEventMask;
|
||||
|
||||
@ -286,6 +310,11 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
void DropGraphics(bool freeObjects);
|
||||
void AllocateGraphics();
|
||||
|
||||
// The top left visible point in main window coordinates. Will be 0,0 except for
|
||||
// scroll views where it will be equivalent to the current scroll position.
|
||||
virtual Point GetVisibleOriginInMain();
|
||||
Point DocumentPointFromView(Point ptView); // Convert a point from view space to document
|
||||
int TopLineOfMain(); // Return the line at Main's y coordinate 0
|
||||
virtual PRectangle GetClientRectangle();
|
||||
PRectangle GetTextRectangle();
|
||||
|
||||
@ -352,10 +381,19 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
int xOffset;
|
||||
int topLine;
|
||||
XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {}
|
||||
bool operator==(const XYScrollPosition &other) const {
|
||||
return (xOffset == other.xOffset) && (topLine == other.topLine);
|
||||
}
|
||||
};
|
||||
XYScrollPosition XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz);
|
||||
enum XYScrollOptions {
|
||||
xysUseMargin=0x1,
|
||||
xysVertical=0x2,
|
||||
xysHorizontal=0x4,
|
||||
xysDefault=xysUseMargin|xysVertical|xysHorizontal};
|
||||
XYScrollPosition XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options);
|
||||
void SetXYScroll(XYScrollPosition newXY);
|
||||
void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
|
||||
void ScrollRange(SelectionRange range);
|
||||
void ShowCaretAtCurrentPosition();
|
||||
void DropCaret();
|
||||
void InvalidateCaret();
|
||||
@ -439,7 +477,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
|
||||
void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
|
||||
void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt);
|
||||
void NotifyUpdateUI();
|
||||
bool NotifyUpdateUI();
|
||||
void NotifyPainted();
|
||||
void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt);
|
||||
bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
|
||||
@ -518,8 +556,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
||||
|
||||
int PositionAfterArea(PRectangle rcArea);
|
||||
void StyleToPositionInView(Position pos);
|
||||
void IdleStyling();
|
||||
virtual void QueueStyling(int upTo);
|
||||
virtual void IdleWork();
|
||||
virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0);
|
||||
|
||||
virtual bool PaintContains(PRectangle rc);
|
||||
bool PaintContainsMargin();
|
||||
|
@ -6,6 +6,7 @@
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -112,8 +113,8 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
|
||||
rc.bottom--;
|
||||
int minDim = Platform::Minimum(rc.Width(), rc.Height());
|
||||
minDim--; // Ensure does not go beyond edge
|
||||
int centreX = (rc.right + rc.left) / 2;
|
||||
int centreY = (rc.bottom + rc.top) / 2;
|
||||
int centreX = floor((rc.right + rc.left) / 2.0);
|
||||
int centreY = floor((rc.bottom + rc.top) / 2.0);
|
||||
int dimOn2 = minDim / 2;
|
||||
int dimOn4 = minDim / 4;
|
||||
int blobSize = dimOn2-1;
|
||||
|
@ -130,6 +130,8 @@ class BreakFinder {
|
||||
int subBreak;
|
||||
Document *pdoc;
|
||||
void Insert(int val);
|
||||
// Private so BreakFinder objects can not be copied
|
||||
BreakFinder(const BreakFinder &);
|
||||
public:
|
||||
// If a whole run is longer than lengthStartSubdivision then subdivide
|
||||
// into smaller runs at spaces or punctuation.
|
||||
@ -148,6 +150,8 @@ class PositionCache {
|
||||
size_t size;
|
||||
unsigned int clock;
|
||||
bool allClear;
|
||||
// Private so PositionCache objects can not be copied
|
||||
PositionCache(const PositionCache &);
|
||||
public:
|
||||
PositionCache();
|
||||
~PositionCache();
|
||||
|
@ -23,6 +23,8 @@ private:
|
||||
void RemoveRun(int run);
|
||||
void RemoveRunIfEmpty(int run);
|
||||
void RemoveRunIfSameAsPrevious(int run);
|
||||
// Private so RunStyles objects can not be copied
|
||||
RunStyles(const RunStyles &);
|
||||
public:
|
||||
RunStyles();
|
||||
~RunStyles();
|
||||
|
@ -193,6 +193,13 @@ void ScintillaBase::AutoCompleteDoubleClick(void *p) {
|
||||
sci->AutoCompleteCompleted();
|
||||
}
|
||||
|
||||
void ScintillaBase::AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen) {
|
||||
UndoGroup ug(pdoc);
|
||||
pdoc->DeleteChars(startPos, removeLen);
|
||||
pdoc->InsertString(startPos, text, textLen);
|
||||
SetEmptySelection(startPos + textLen);
|
||||
}
|
||||
|
||||
void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
|
||||
//Platform::DebugPrintf("AutoComplete %s\n", list);
|
||||
ct.CallTipCancel();
|
||||
@ -203,15 +210,10 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
|
||||
int lenInsert = typeSep ?
|
||||
static_cast<int>(typeSep-list) : static_cast<int>(strlen(list));
|
||||
if (ac.ignoreCase) {
|
||||
SetEmptySelection(sel.MainCaret() - lenEntered);
|
||||
pdoc->DeleteChars(sel.MainCaret(), lenEntered);
|
||||
SetEmptySelection(sel.MainCaret());
|
||||
pdoc->InsertString(sel.MainCaret(), list, lenInsert);
|
||||
SetEmptySelection(sel.MainCaret() + lenInsert);
|
||||
// May need to convert the case before invocation, so remove lenEntered characters
|
||||
AutoCompleteInsert(sel.MainCaret() - lenEntered, lenEntered, list, lenInsert);
|
||||
} else {
|
||||
SetEmptySelection(sel.MainCaret());
|
||||
pdoc->InsertString(sel.MainCaret(), list + lenEntered, lenInsert - lenEntered);
|
||||
SetEmptySelection(sel.MainCaret() + lenInsert - lenEntered);
|
||||
AutoCompleteInsert(sel.MainCaret(), 0, list + lenEntered, lenInsert - lenEntered);
|
||||
}
|
||||
ac.Cancel();
|
||||
return;
|
||||
@ -233,6 +235,11 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
|
||||
Redraw();
|
||||
pt = PointMainCaret();
|
||||
}
|
||||
if (wMargin.GetID()) {
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
pt.x += ptOrigin.x;
|
||||
pt.y += ptOrigin.y;
|
||||
}
|
||||
PRectangle rcac;
|
||||
rcac.left = pt.x - ac.lb->CaretFromEdge();
|
||||
if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below.
|
||||
@ -356,15 +363,7 @@ void ScintillaBase::AutoCompleteCompleted() {
|
||||
endPos = pdoc->ExtendWordSelect(endPos, 1, true);
|
||||
if (endPos < firstPos)
|
||||
return;
|
||||
UndoGroup ug(pdoc);
|
||||
if (endPos != firstPos) {
|
||||
pdoc->DeleteChars(firstPos, endPos - firstPos);
|
||||
}
|
||||
SetEmptySelection(ac.posStart);
|
||||
if (item != -1) {
|
||||
pdoc->InsertCString(firstPos, selected.c_str());
|
||||
SetEmptySelection(firstPos + static_cast<int>(selected.length()));
|
||||
}
|
||||
AutoCompleteInsert(firstPos, endPos - firstPos, selected.c_str(), static_cast<int>(selected.length()));
|
||||
SetLastXChosen();
|
||||
}
|
||||
|
||||
@ -398,6 +397,11 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
|
||||
if (ct.UseStyleCallTip()) {
|
||||
ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back);
|
||||
}
|
||||
if (wMargin.GetID()) {
|
||||
Point ptOrigin = GetVisibleOriginInMain();
|
||||
pt.x += ptOrigin.x;
|
||||
pt.y += ptOrigin.y;
|
||||
}
|
||||
PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
|
||||
vs.lineHeight,
|
||||
defn,
|
||||
@ -472,6 +476,7 @@ class LexState : public LexInterface {
|
||||
const LexerModule *lexCurrent;
|
||||
void SetLexerModule(const LexerModule *lex);
|
||||
PropSetSimple props;
|
||||
int interfaceVersion;
|
||||
public:
|
||||
int lexLanguage;
|
||||
|
||||
@ -491,6 +496,15 @@ public:
|
||||
const char *PropGet(const char *key) const;
|
||||
int PropGetInt(const char *key, int defaultValue=0) const;
|
||||
int PropGetExpanded(const char *key, char *result) const;
|
||||
|
||||
int LineEndTypesSupported();
|
||||
int AllocateSubStyles(int styleBase, int numberStyles);
|
||||
int SubStylesStart(int styleBase);
|
||||
int SubStylesLength(int styleBase);
|
||||
void FreeSubStyles();
|
||||
void SetIdentifiers(int style, const char *identifiers);
|
||||
int DistanceToSecondaryStyles();
|
||||
const char *GetSubStyleBases();
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
@ -500,6 +514,7 @@ public:
|
||||
LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) {
|
||||
lexCurrent = 0;
|
||||
performingStyle = false;
|
||||
interfaceVersion = lvOriginal;
|
||||
lexLanguage = SCLEX_CONTAINER;
|
||||
}
|
||||
|
||||
@ -523,9 +538,12 @@ void LexState::SetLexerModule(const LexerModule *lex) {
|
||||
instance->Release();
|
||||
instance = 0;
|
||||
}
|
||||
interfaceVersion = lvOriginal;
|
||||
lexCurrent = lex;
|
||||
if (lexCurrent)
|
||||
if (lexCurrent) {
|
||||
instance = lexCurrent->Create();
|
||||
interfaceVersion = instance->Version();
|
||||
}
|
||||
pdoc->LexerChanged();
|
||||
}
|
||||
}
|
||||
@ -630,6 +648,60 @@ int LexState::PropGetExpanded(const char *key, char *result) const {
|
||||
return props.GetExpanded(key, result);
|
||||
}
|
||||
|
||||
int LexState::LineEndTypesSupported() {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->LineEndTypesSupported();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LexState::AllocateSubStyles(int styleBase, int numberStyles) {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->AllocateSubStyles(styleBase, numberStyles);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LexState::SubStylesStart(int styleBase) {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->SubStylesStart(styleBase);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LexState::SubStylesLength(int styleBase) {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->SubStylesLength(styleBase);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LexState::FreeSubStyles() {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
static_cast<ILexerWithSubStyles *>(instance)->FreeSubStyles();
|
||||
}
|
||||
}
|
||||
|
||||
void LexState::SetIdentifiers(int style, const char *identifiers) {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
static_cast<ILexerWithSubStyles *>(instance)->SetIdentifiers(style, identifiers);
|
||||
}
|
||||
}
|
||||
|
||||
int LexState::DistanceToSecondaryStyles() {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->DistanceToSecondaryStyles();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *LexState::GetSubStyleBases() {
|
||||
if (instance && (interfaceVersion >= lvSubStyles)) {
|
||||
return static_cast<ILexerWithSubStyles *>(instance)->GetSubStyleBases();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
|
||||
@ -725,6 +797,13 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
|
||||
case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR:
|
||||
return ac.ignoreCaseBehaviour;
|
||||
|
||||
case SCI_AUTOCSETORDER:
|
||||
ac.autoSort = wParam;
|
||||
break;
|
||||
|
||||
case SCI_AUTOCGETORDER:
|
||||
return ac.autoSort;
|
||||
|
||||
case SCI_USERLISTSHOW:
|
||||
listType = wParam;
|
||||
AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
|
||||
@ -890,6 +969,31 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
|
||||
case SCI_DESCRIBEKEYWORDSETS:
|
||||
return StringResult(lParam, DocumentLexState()->DescribeWordListSets());
|
||||
|
||||
case SCI_GETLINEENDTYPESSUPPORTED:
|
||||
return DocumentLexState()->LineEndTypesSupported();
|
||||
|
||||
case SCI_ALLOCATESUBSTYLES:
|
||||
return DocumentLexState()->AllocateSubStyles(wParam, lParam);
|
||||
|
||||
case SCI_GETSUBSTYLESSTART:
|
||||
return DocumentLexState()->SubStylesStart(wParam);
|
||||
|
||||
case SCI_GETSUBSTYLESLENGTH:
|
||||
return DocumentLexState()->SubStylesLength(wParam);
|
||||
|
||||
case SCI_FREESUBSTYLES:
|
||||
DocumentLexState()->FreeSubStyles();
|
||||
break;
|
||||
|
||||
case SCI_SETIDENTIFIERS:
|
||||
DocumentLexState()->SetIdentifiers(wParam, reinterpret_cast<const char *>(lParam));
|
||||
break;
|
||||
|
||||
case SCI_DISTANCETOSECONDARYSTYLES:
|
||||
return DocumentLexState()->DistanceToSecondaryStyles();
|
||||
|
||||
case SCI_GETSUBSTYLEBASES:
|
||||
return StringResult(lParam, DocumentLexState()->GetSubStyleBases());
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@ -64,6 +64,7 @@ protected:
|
||||
virtual void CancelModes();
|
||||
virtual int KeyCommand(unsigned int iMessage);
|
||||
|
||||
void AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen);
|
||||
void AutoCompleteStart(int lenEntered, const char *list);
|
||||
void AutoCompleteCancel();
|
||||
void AutoCompleteMove(int delta);
|
||||
|
@ -26,3 +26,16 @@ inline bool UTF8IsAscii(int ch) {
|
||||
|
||||
enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 };
|
||||
int UTF8Classify(const unsigned char *us, int len);
|
||||
|
||||
// Line separator is U+2028 \xe2\x80\xa8
|
||||
// Paragraph separator is U+2029 \xe2\x80\xa9
|
||||
const int UTF8SeparatorLength = 3;
|
||||
inline bool UTF8IsSeparator(const unsigned char *us) {
|
||||
return (us[0] == 0xe2) && (us[1] == 0x80) && ((us[2] == 0xa8) || (us[2] == 0xa9));
|
||||
}
|
||||
|
||||
// NEL is U+0085 \xc2\x85
|
||||
const int UTF8NELLength = 2;
|
||||
inline bool UTF8IsNEL(const unsigned char *us) {
|
||||
return (us[0] == 0xc2) && (us[1] == 0x85);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -140,6 +141,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
|
||||
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
|
||||
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
|
||||
}
|
||||
nextExtendedStyle = source.nextExtendedStyle;
|
||||
for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
|
||||
markers[mrk] = source.markers[mrk];
|
||||
}
|
||||
@ -180,6 +182,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
|
||||
caretcolour = source.caretcolour;
|
||||
additionalCaretColour = source.additionalCaretColour;
|
||||
showCaretLineBackground = source.showCaretLineBackground;
|
||||
alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
|
||||
caretLineBackground = source.caretLineBackground;
|
||||
caretLineAlpha = source.caretLineAlpha;
|
||||
edgecolour = source.edgecolour;
|
||||
@ -190,11 +193,13 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
|
||||
someStylesForceCase = false;
|
||||
leftMarginWidth = source.leftMarginWidth;
|
||||
rightMarginWidth = source.rightMarginWidth;
|
||||
for (int i=0; i < margins; i++) {
|
||||
ms[i] = source.ms[i];
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
ms[margin] = source.ms[margin];
|
||||
}
|
||||
maskInLine = source.maskInLine;
|
||||
fixedColumnWidth = source.fixedColumnWidth;
|
||||
marginInside = source.marginInside;
|
||||
textStart = source.textStart;
|
||||
zoomLevel = source.zoomLevel;
|
||||
viewWhitespace = source.viewWhitespace;
|
||||
whitespaceSize = source.whitespaceSize;
|
||||
@ -224,6 +229,7 @@ void ViewStyle::Init(size_t stylesSize_) {
|
||||
stylesSize = 0;
|
||||
styles = NULL;
|
||||
AllocStyles(stylesSize_);
|
||||
nextExtendedStyle = 256;
|
||||
fontNames.Clear();
|
||||
ResetDefaultStyle();
|
||||
|
||||
@ -274,6 +280,7 @@ void ViewStyle::Init(size_t stylesSize_) {
|
||||
caretcolour = ColourDesired(0, 0, 0);
|
||||
additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
|
||||
showCaretLineBackground = false;
|
||||
alwaysShowCaretLineBackground = false;
|
||||
caretLineBackground = ColourDesired(0xff, 0xff, 0);
|
||||
caretLineAlpha = SC_ALPHA_NOALPHA;
|
||||
edgecolour = ColourDesired(0xc0, 0xc0, 0xc0);
|
||||
@ -301,13 +308,15 @@ void ViewStyle::Init(size_t stylesSize_) {
|
||||
ms[2].style = SC_MARGIN_SYMBOL;
|
||||
ms[2].width = 0;
|
||||
ms[2].mask = 0;
|
||||
fixedColumnWidth = leftMarginWidth;
|
||||
marginInside = true;
|
||||
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
|
||||
maskInLine = 0xffffffff;
|
||||
for (int margin=0; margin < margins; margin++) {
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
fixedColumnWidth += ms[margin].width;
|
||||
if (ms[margin].width > 0)
|
||||
maskInLine &= ~ms[margin].mask;
|
||||
}
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
zoomLevel = 0;
|
||||
viewWhitespace = wsInvisible;
|
||||
whitespaceSize = 1;
|
||||
@ -354,6 +363,7 @@ void ViewStyle::Refresh(Surface &surface) {
|
||||
CreateFont(styles[j]);
|
||||
}
|
||||
|
||||
assert(frFirst);
|
||||
frFirst->Realise(surface, zoomLevel, technology);
|
||||
|
||||
for (unsigned int k=0; k<stylesSize; k++) {
|
||||
@ -381,13 +391,14 @@ void ViewStyle::Refresh(Surface &surface) {
|
||||
aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
|
||||
spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
|
||||
|
||||
fixedColumnWidth = leftMarginWidth;
|
||||
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
|
||||
maskInLine = 0xffffffff;
|
||||
for (int margin=0; margin < margins; margin++) {
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
fixedColumnWidth += ms[margin].width;
|
||||
if (ms[margin].width > 0)
|
||||
maskInLine &= ~ms[margin].mask;
|
||||
}
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
}
|
||||
|
||||
void ViewStyle::AllocStyles(size_t sizeNew) {
|
||||
@ -409,6 +420,16 @@ void ViewStyle::AllocStyles(size_t sizeNew) {
|
||||
stylesSize = sizeNew;
|
||||
}
|
||||
|
||||
void ViewStyle::ReleaseAllExtendedStyles() {
|
||||
nextExtendedStyle = 256;
|
||||
}
|
||||
|
||||
int ViewStyle::AllocateExtendedStyles(int numberStyles) {
|
||||
int startRange = static_cast<int>(nextExtendedStyle);
|
||||
nextExtendedStyle += numberStyles;
|
||||
return startRange;
|
||||
}
|
||||
|
||||
void ViewStyle::EnsureStyle(size_t index) {
|
||||
if (index >= stylesSize) {
|
||||
size_t sizeNew = stylesSize * 2;
|
||||
@ -467,4 +488,3 @@ void ViewStyle::CalcLargestMarkerHeight() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@ private:
|
||||
int size;
|
||||
int max;
|
||||
|
||||
// Private so FontNames objects can not be copied
|
||||
FontNames(const FontNames &);
|
||||
public:
|
||||
FontNames();
|
||||
~FontNames();
|
||||
@ -65,6 +67,7 @@ public:
|
||||
FontRealised *frFirst;
|
||||
size_t stylesSize;
|
||||
Style *styles;
|
||||
size_t nextExtendedStyle;
|
||||
LineMarker markers[MARKER_MAX + 1];
|
||||
int largestMarkerHeight;
|
||||
Indicator indicators[INDIC_MAX + 1];
|
||||
@ -101,12 +104,13 @@ public:
|
||||
bool hotspotUnderline;
|
||||
bool hotspotSingleLine;
|
||||
/// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
|
||||
enum { margins=5 };
|
||||
int leftMarginWidth; ///< Spacing margin on left of text
|
||||
int rightMarginWidth; ///< Spacing margin on right of text
|
||||
int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
|
||||
MarginStyle ms[margins];
|
||||
int fixedColumnWidth;
|
||||
MarginStyle ms[SC_MAX_MARGIN+1];
|
||||
int fixedColumnWidth; ///< Total width of margins
|
||||
bool marginInside; ///< true: margin included in text view, false: separate views
|
||||
int textStart; ///< Starting x position of text within the view
|
||||
int zoomLevel;
|
||||
WhiteSpaceVisibility viewWhitespace;
|
||||
int whitespaceSize;
|
||||
@ -115,6 +119,7 @@ public:
|
||||
ColourDesired caretcolour;
|
||||
ColourDesired additionalCaretColour;
|
||||
bool showCaretLineBackground;
|
||||
bool alwaysShowCaretLineBackground;
|
||||
ColourDesired caretLineBackground;
|
||||
int caretLineAlpha;
|
||||
ColourDesired edgecolour;
|
||||
@ -141,6 +146,8 @@ public:
|
||||
void CreateFont(const FontSpecification &fs);
|
||||
void Refresh(Surface &surface);
|
||||
void AllocStyles(size_t sizeNew);
|
||||
void ReleaseAllExtendedStyles();
|
||||
int AllocateExtendedStyles(int numberStyles);
|
||||
void EnsureStyle(size_t index);
|
||||
void ResetDefaultStyle();
|
||||
void ClearStyles();
|
||||
|
@ -1 +1 @@
|
||||
323
|
||||
331
|
||||
|
Loading…
x
Reference in New Issue
Block a user