[geany/geany] 788a57: Merge branch 'scintilla-update'
Colomban Wendling
git-noreply at xxxxx
Wed May 22 01:38:38 UTC 2013
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Wed, 22 May 2013 01:38:38 UTC
Commit: 788a57f6fcf6bdb152847aedfaaf09aadc7cce43
https://github.com/geany/geany/commit/788a57f6fcf6bdb152847aedfaaf09aadc7cce43
Log Message:
-----------
Merge branch 'scintilla-update'
Modified Paths:
--------------
data/filetypes.c
data/filetypes.haskell
scintilla/gtk/PlatGTK.cxx
scintilla/gtk/ScintillaGTK.cxx
scintilla/include/SciLexer.h
scintilla/include/Scintilla.h
scintilla/include/Scintilla.iface
scintilla/lexers/LexCPP.cxx
scintilla/lexers/LexHaskell.cxx
scintilla/lexers/LexLaTeX.cxx
scintilla/lexers/LexOthers.cxx
scintilla/lexlib/LexerModule.cxx
scintilla/lexlib/PropSetSimple.cxx
scintilla/lexlib/PropSetSimple.h
scintilla/lexlib/StyleContext.h
scintilla/lexlib/WordList.cxx
scintilla/lexlib/WordList.h
scintilla/scintilla_changes.patch
scintilla/src/CallTip.cxx
scintilla/src/CallTip.h
scintilla/src/CellBuffer.cxx
scintilla/src/CellBuffer.h
scintilla/src/ContractionState.cxx
scintilla/src/Decoration.cxx
scintilla/src/Document.cxx
scintilla/src/Document.h
scintilla/src/Editor.cxx
scintilla/src/Editor.h
scintilla/src/Indicator.cxx
scintilla/src/KeyMap.cxx
scintilla/src/KeyMap.h
scintilla/src/PerLine.cxx
scintilla/src/PerLine.h
scintilla/src/PositionCache.cxx
scintilla/src/PositionCache.h
scintilla/src/RESearch.cxx
scintilla/src/RESearch.h
scintilla/src/RunStyles.cxx
scintilla/src/RunStyles.h
scintilla/src/Selection.cxx
scintilla/src/SplitVector.h
scintilla/src/Style.cxx
scintilla/src/Style.h
scintilla/src/ViewStyle.cxx
scintilla/src/ViewStyle.h
scintilla/src/XPM.cxx
scintilla/src/XPM.h
scintilla/version.txt
src/highlighting.c
src/highlightingmappings.h
Modified: data/filetypes.c
1 files changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -6,6 +6,7 @@
commentline=comment_line
commentdoc=comment_doc
preprocessorcomment=comment
+preprocessorcommentdoc=comment_doc
number=number_1
word=keyword_1
word2=keyword_2
Modified: data/filetypes.haskell
4 files changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -20,6 +20,10 @@ module=function
data=number_2
pragma=preprocessor
preprocessor=preprocessor
+stringeol=string_eol
+reserved_operator=operator
+literate_comment=comment
+literate_codedelim=other
[keywords]
# all items must be in one line
Modified: scintilla/gtk/PlatGTK.cxx
122 files changed, 58 insertions(+), 64 deletions(-)
===================================================================
@@ -9,6 +9,7 @@
#include <stddef.h>
#include <math.h>
+#include <string>
#include <vector>
#include <map>
@@ -259,6 +260,7 @@ class FontCached : Font {
public:
static FontID FindOrCreate(const FontParameters &fp);
static void ReleaseId(FontID fid_);
+ static void ReleaseAll();
};
FontCached *FontCached::first = 0;
@@ -299,11 +301,9 @@ FontID FontCached::FindOrCreate(const FontParameters &fp) {
}
if (ret == 0) {
FontCached *fc = new FontCached(fp);
- if (fc) {
- fc->next = first;
- first = fc;
- ret = fc->fid;
- }
+ fc->next = first;
+ first = fc;
+ ret = fc->fid;
}
FontMutexUnlock();
return ret;
@@ -328,6 +328,12 @@ void FontCached::ReleaseId(FontID fid_) {
FontMutexUnlock();
}
+void FontCached::ReleaseAll() {
+ while (first) {
+ ReleaseId(first->GetID());
+ }
+}
+
FontID FontCached::CreateNewFont(const FontParameters &fp) {
PangoFontDescription *pfd = pango_font_description_new();
if (pfd) {
@@ -831,8 +837,8 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
}
}
-char *UTF8FromLatin1(const char *s, int &len) {
- char *utfForm = new char[len*2+1];
+std::string UTF8FromLatin1(const char *s, int len) {
+ std::string utfForm(len*2 + 1, '\0');
size_t lenU = 0;
for (int i=0;i<len;i++) {
unsigned int uch = static_cast<unsigned char>(s[i]);
@@ -843,27 +849,26 @@ char *UTF8FromLatin1(const char *s, int &len) {
utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
}
}
- utfForm[lenU] = '\0';
- len = lenU;
+ utfForm.resize(lenU);
return utfForm;
}
-static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) {
+static std::string UTF8FromIconv(const Converter &conv, const char *s, int len) {
if (conv) {
- char *utfForm = new char[len*3+1];
+ std::string utfForm(len*3+1, '\0');
char *pin = const_cast<char *>(s);
size_t inLeft = len;
- char *pout = utfForm;
+ char *putf = &utfForm[0];
+ char *pout = putf;
size_t outLeft = len*3+1;
size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
if (conversions != ((size_t)(-1))) {
*pout = '\0';
- len = pout - utfForm;
+ utfForm.resize(pout - putf);
return utfForm;
}
- delete []utfForm;
}
- return 0;
+ return std::string();
}
// Work out how many bytes are in a character by trying to convert using iconv,
@@ -901,18 +906,16 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, con
if (context) {
XYPOSITION xText = rc.left;
if (PFont(font_)->pfd) {
- char *utfForm = 0;
+ std::string utfForm;
if (et == UTF8) {
pango_layout_set_text(layout, s, len);
} else {
- if (!utfForm) {
- SetConverter(PFont(font_)->characterSet);
- utfForm = UTF8FromIconv(conv, s, len);
- }
- if (!utfForm) { // iconv failed so treat as Latin1
+ SetConverter(PFont(font_)->characterSet);
+ utfForm = UTF8FromIconv(conv, s, len);
+ if (utfForm.empty()) { // iconv failed so treat as Latin1
utfForm = UTF8FromLatin1(s, len);
}
- pango_layout_set_text(layout, utfForm, len);
+ pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
}
pango_layout_set_font_description(layout, PFont(font_)->pfd);
pango_cairo_update_layout(context, layout);
@@ -923,7 +926,6 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, con
#endif
cairo_move_to(context, xText, ybase);
pango_cairo_show_layout_line(context, pll);
- delete []utfForm;
}
}
}
@@ -1020,20 +1022,20 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
int positionsCalculated = 0;
if (et == dbcs) {
SetConverter(PFont(font_)->characterSet);
- char *utfForm = UTF8FromIconv(conv, s, len);
- if (utfForm) {
+ std::string utfForm = UTF8FromIconv(conv, s, len);
+ if (!utfForm.empty()) {
// Convert to UTF-8 so can ask Pango for widths, then
// Loop through UTF-8 and DBCS forms, taking account of different
// character byte lengths.
Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
- pango_layout_set_text(layout, utfForm, strlen(utfForm));
+ pango_layout_set_text(layout, utfForm.c_str(), strlen(utfForm.c_str()));
int i = 0;
int clusterStart = 0;
- ClusterIterator iti(layout, strlen(utfForm));
+ ClusterIterator iti(layout, strlen(utfForm.c_str()));
while (!iti.finished) {
iti.Next();
int clusterEnd = iti.curIndex;
- int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
+ int places = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
int place = 1;
while (clusterStart < clusterEnd) {
size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
@@ -1041,38 +1043,36 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
positions[i++] = iti.position - (places - place) * iti.distance / places;
positionsCalculated++;
}
- clusterStart += UTF8CharLength(utfForm+clusterStart);
+ clusterStart += UTF8CharLength(utfForm.c_str()+clusterStart);
place++;
}
}
- delete []utfForm;
PLATFORM_ASSERT(i == lenPositions);
}
}
if (positionsCalculated < 1 ) {
// Either Latin1 or DBCS conversion failed so treat as Latin1.
SetConverter(PFont(font_)->characterSet);
- char *utfForm = UTF8FromIconv(conv, s, len);
- if (!utfForm) {
+ std::string utfForm = UTF8FromIconv(conv, s, len);
+ if (utfForm.empty()) {
utfForm = UTF8FromLatin1(s, len);
}
- pango_layout_set_text(layout, utfForm, len);
+ pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
int i = 0;
int clusterStart = 0;
// Each Latin1 input character may take 1 or 2 bytes in UTF-8
// and groups of up to 3 may be represented as ligatures.
- ClusterIterator iti(layout, strlen(utfForm));
+ ClusterIterator iti(layout, utfForm.length());
while (!iti.finished) {
iti.Next();
int clusterEnd = iti.curIndex;
- int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
+ int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
for (int charInLig=0; charInLig<ligatureLength; charInLig++) {
positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength;
}
clusterStart = clusterEnd;
}
- delete []utfForm;
PLATFORM_ASSERT(i == lenPositions);
}
}
@@ -1092,20 +1092,18 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID()) {
if (PFont(font_)->pfd) {
- char *utfForm = 0;
+ std::string utfForm;
pango_layout_set_font_description(layout, PFont(font_)->pfd);
PangoRectangle pos;
if (et == UTF8) {
pango_layout_set_text(layout, s, len);
} else {
- if (!utfForm) { // use iconv
- SetConverter(PFont(font_)->characterSet);
- utfForm = UTF8FromIconv(conv, s, len);
- }
- if (!utfForm) { // iconv failed so treat as Latin1
+ SetConverter(PFont(font_)->characterSet);
+ utfForm = UTF8FromIconv(conv, s, len);
+ if (utfForm.empty()) { // iconv failed so treat as Latin1
utfForm = UTF8FromLatin1(s, len);
}
- pango_layout_set_text(layout, utfForm, len);
+ pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
}
#ifdef PANGO_VERSION
PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0);
@@ -1113,7 +1111,6 @@ XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0);
#endif
pango_layout_line_get_extents(pangoLine, NULL, &pos);
- delete []utfForm;
return doubleFromPangoUnits(pos.width);
}
return 1;
@@ -1883,30 +1880,26 @@ void ListBoxX::ClearRegisteredImages() {
void ListBoxX::SetList(const char *listText, char separator, char typesep) {
Clear();
int count = strlen(listText) + 1;
- char *words = new char[count];
- if (words) {
- memcpy(words, listText, count);
- char *startword = words;
- char *numword = NULL;
- int i = 0;
- for (; words[i]; i++) {
- if (words[i] == separator) {
- words[i] = '\0';
- if (numword)
- *numword = '\0';
- Append(startword, numword?atoi(numword + 1):-1);
- startword = words + i + 1;
- numword = NULL;
- } else if (words[i] == typesep) {
- numword = words + i;
- }
- }
- if (startword) {
+ std::vector<char> words(listText, listText+count);
+ char *startword = words.data();
+ char *numword = NULL;
+ int i = 0;
+ for (; words[i]; i++) {
+ if (words[i] == separator) {
+ words[i] = '\0';
if (numword)
*numword = '\0';
Append(startword, numword?atoi(numword + 1):-1);
+ startword = words.data() + i + 1;
+ numword = NULL;
+ } else if (words[i] == typesep) {
+ numword = words.data() + i;
}
- delete []words;
+ }
+ if (startword) {
+ if (numword)
+ *numword = '\0';
+ Append(startword, numword?atoi(numword + 1):-1);
}
}
@@ -2165,5 +2158,6 @@ void Platform_Initialise() {
}
void Platform_Finalise() {
+ FontCached::ReleaseAll();
FontMutexFree();
}
Modified: scintilla/gtk/ScintillaGTK.cxx
236 files changed, 84 insertions(+), 152 deletions(-)
===================================================================
@@ -30,7 +30,6 @@
#ifdef SCI_LEXER
#include "SciLexer.h"
#endif
-#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
@@ -109,7 +108,7 @@ static GdkWindow *PWindow(const Window &w) {
using namespace Scintilla;
#endif
-extern char *UTF8FromLatin1(const char *s, int &len);
+extern std::string UTF8FromLatin1(const char *s, int len);
class ScintillaGTK : public ScintillaBase {
_ScintillaObject *sci;
@@ -186,7 +185,6 @@ class ScintillaGTK : public ScintillaBase {
virtual bool PaintContains(PRectangle rc);
void FullPaint();
virtual PRectangle GetClientRectangle();
- void SyncPaint(PRectangle rc);
virtual void ScrollText(int linesToMove);
virtual void SetVerticalScrollPos();
virtual void SetHorizontalScrollPos();
@@ -280,7 +278,6 @@ class ScintillaGTK : public ScintillaBase {
static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
guint info, guint time);
static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
- static void DragBegin(GtkWidget *widget, GdkDragContext *context);
gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, guint dragtime);
@@ -373,12 +370,12 @@ static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
#endif
#if PLAT_GTK_WIN32
- // There does not seem to be a real standard for indicating that the clipboard
+ // There does not seem to be a real standard for indicating that the clipboard
// contains a rectangular selection, so copy Developer Studio.
cfColumnSelect = static_cast<CLIPFORMAT>(
::RegisterClipboardFormat("MSDEVColumnSelect"));
- // Get intellimouse parameters when running on win32; otherwise use
+ // Get intellimouse parameters when running on win32; otherwise use
// reasonable default
#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES 104
@@ -837,37 +834,34 @@ void ScintillaGTK::StartDrag() {
reinterpret_cast<GdkEvent *>(&evbtn));
}
-static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
+static std::string ConvertText(char *s, size_t len, const char *charSetDest,
const char *charSetSource, bool transliterations, bool silent=false) {
// s is not const because of different versions of iconv disagreeing about const
- *lenResult = 0;
- char *destForm = 0;
+ std::string destForm;
Converter conv(charSetDest, charSetSource, transliterations);
if (conv) {
- destForm = new char[len*3+1];
+ size_t outLeft = len*3+1;
+ destForm = std::string(outLeft, '\0');
char *pin = s;
size_t inLeft = len;
- char *pout = destForm;
- size_t outLeft = len*3+1;
+ char *putf = &destForm[0];
+ char *pout = putf;
size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
if (conversions == ((size_t)(-1))) {
- if (!silent)
- fprintf(stderr, "iconv %s->%s failed for %s\n",
- charSetSource, charSetDest, static_cast<char *>(s));
- delete []destForm;
- destForm = 0;
+ if (!silent) {
+ if (len == 1)
+ fprintf(stderr, "iconv %s->%s failed for %0x '%s'\n",
+ charSetSource, charSetDest, (unsigned char)(*s), static_cast<char *>(s));
+ else
+ fprintf(stderr, "iconv %s->%s failed for %s\n",
+ charSetSource, charSetDest, static_cast<char *>(s));
+ }
+ destForm = std::string();
} else {
-//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
- *pout = '\0';
- *lenResult = pout - destForm;
+ destForm.resize(pout - putf);
}
} else {
-fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
- }
- if (!destForm) {
- destForm = new char[1];
- destForm[0] = '\0';
- *lenResult = 0;
+ fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
}
return destForm;
}
@@ -884,26 +878,18 @@ int ScintillaGTK::TargetAsUTF8(char *text) {
// Need to convert
const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) {
-//~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
- char *s = new char[targetLength];
- if (s) {
- pdoc->GetCharRange(s, targetStart, targetLength);
-//~ fprintf(stderr, " \"%s\"\n", s);
- if (text) {
- char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
- memcpy(text, tmputf, targetLength);
- delete []tmputf;
-//~ fprintf(stderr, " \"%s\"\n", text);
- }
- delete []s;
+ std::string s = RangeText(targetStart, targetEnd);
+ std::string tmputf = ConvertText(&s[0], targetLength, "UTF-8", charSetBuffer, false);
+ if (text) {
+ memcpy(text, tmputf.c_str(), tmputf.length());
}
+ return tmputf.length();
} else {
if (text) {
pdoc->GetCharRange(text, targetStart, targetLength);
}
}
}
-//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
return targetLength;
}
@@ -920,15 +906,11 @@ int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
// Need to convert
const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) {
- int outLength = 0;
- char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
- if (tmpEncoded) {
- if (encoded) {
- memcpy(encoded, tmpEncoded, outLength);
- }
- delete []tmpEncoded;
+ std::string tmpEncoded = ConvertText(utf8, inputLength, charSetBuffer, "UTF-8", true);
+ if (encoded) {
+ memcpy(encoded, tmpEncoded.c_str(), tmpEncoded.length());
}
- return outLength;
+ return tmpEncoded.length();
} else {
if (encoded) {
memcpy(encoded, utf8, inputLength);
@@ -966,7 +948,7 @@ sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
#ifdef SCI_LEXER
case SCI_LOADLEXERLIBRARY:
- LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
+ LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
break;
#endif
case SCI_TARGETASUTF8:
@@ -1109,30 +1091,6 @@ PRectangle ScintillaGTK::GetClientRectangle() {
return rc;
}
-// Synchronously paint a rectangle of the window.
-void ScintillaGTK::SyncPaint(PRectangle rc) {
- paintState = painting;
- rcPaint = rc;
- PRectangle rcClient = GetClientRectangle();
- paintingAllText = rcPaint.Contains(rcClient);
- if (PWindow(wText)) {
- Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
- if (sw) {
- cairo_t *cr = gdk_cairo_create(PWindow(wText));
- sw->Init(cr, PWidget(wText));
- Paint(sw, rc);
- sw->Release();
- delete sw;
- cairo_destroy(cr);
- }
- }
- if (paintState == paintAbandoned) {
- // Painting area was insufficient to cover new styling or brace highlight positions
- FullPaint();
- }
- paintState = notPainting;
-}
-
void ScintillaGTK::ScrollText(int linesToMove) {
int diff = vs.lineHeight * -linesToMove;
//Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
@@ -1301,11 +1259,10 @@ class CaseFolderDBCS : public CaseFolderTable {
folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
return 1;
} else if (*charSet) {
- int convertedLength = lenMixed;
- char *sUTF8 = ConvertText(&convertedLength, const_cast<char *>(mixed), lenMixed,
+ std::string sUTF8 = ConvertText(const_cast<char *>(mixed), lenMixed,
"UTF-8", charSet, false);
- if (sUTF8) {
- gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
+ if (!sUTF8.empty()) {
+ gchar *mapped = g_utf8_casefold(sUTF8.c_str(), sUTF8.length());
size_t lenMapped = strlen(mapped);
if (lenMapped < sizeFolded) {
memcpy(folded, mapped, lenMapped);
@@ -1314,7 +1271,6 @@ class CaseFolderDBCS : public CaseFolderTable {
lenMapped = 1;
}
g_free(mapped);
- delete []sUTF8;
return lenMapped;
}
}
@@ -1337,23 +1293,20 @@ CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
for (int i=0x80; i<0x100; i++) {
char sCharacter[2] = "A";
sCharacter[0] = i;
- int convertedLength = 1;
- const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1,
- "UTF-8", charSetBuffer, false);
- if (sUTF8) {
- gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
+ // Silent as some bytes have no assigned character
+ std::string sUTF8 = ConvertText(sCharacter, 1,
+ "UTF-8", charSetBuffer, false, true);
+ if (!sUTF8.empty()) {
+ gchar *mapped = g_utf8_casefold(sUTF8.c_str(), sUTF8.length());
if (mapped) {
- int mappedLength = strlen(mapped);
- const char *mappedBack = ConvertText(&mappedLength, mapped,
- mappedLength, charSetBuffer, "UTF-8", false, true);
- if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
+ std::string mappedBack = ConvertText(mapped, strlen(mapped),
+ charSetBuffer, "UTF-8", false, true);
+ if ((mappedBack.length() == 1) && (mappedBack[0] != sCharacter[0])) {
pcf->SetTranslation(sCharacter[0], mappedBack[0]);
}
- delete []mappedBack;
g_free(mapped);
}
}
- delete []sUTF8;
}
return pcf;
} else {
@@ -1364,6 +1317,24 @@ CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
}
}
+namespace {
+
+struct CaseMapper {
+ gchar *mapped; // Must be freed with g_free
+ CaseMapper(const std::string &sUTF8, bool toUpperCase) {
+ if (toUpperCase) {
+ mapped = g_utf8_strup(sUTF8.c_str(), sUTF8.length());
+ } else {
+ mapped = g_utf8_strdown(sUTF8.c_str(), sUTF8.length());
+ }
+ }
+ ~CaseMapper() {
+ g_free(mapped);
+ }
+};
+
+}
+
std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
if (s.size() == 0)
return std::string();
@@ -1371,43 +1342,18 @@ CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
if (caseMapping == cmSame)
return s;
- const char *needsFree1 = 0; // Must be freed with delete []
const char *charSetBuffer = CharacterSetID();
- const char *sUTF8 = s.c_str();
- int rangeBytes = s.size();
- int convertedLength = rangeBytes;
- // Change text to UTF-8
- if (!IsUnicodeMode()) {
- // Need to convert
- if (*charSetBuffer) {
- sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
- "UTF-8", charSetBuffer, false);
- needsFree1 = sUTF8;
- }
- }
- gchar *mapped; // Must be freed with g_free
- if (caseMapping == cmUpper) {
- mapped = g_utf8_strup(sUTF8, convertedLength);
+ if (IsUnicodeMode() || !*charSetBuffer) {
+ CaseMapper mapper(s, caseMapping == cmUpper);
+ return std::string(mapper.mapped, strlen(mapper.mapped));
} else {
- mapped = g_utf8_strdown(sUTF8, convertedLength);
- }
- int mappedLength = strlen(mapped);
- char *mappedBack = mapped;
-
- char *needsFree2 = 0; // Must be freed with delete []
- if (!IsUnicodeMode()) {
- if (*charSetBuffer) {
- mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
- needsFree2 = mappedBack;
- }
+ // Change text to UTF-8
+ std::string sUTF8 = ConvertText(const_cast<char *>(s.c_str()), s.length(),
+ "UTF-8", charSetBuffer, false);
+ CaseMapper mapper(sUTF8, caseMapping == cmUpper);
+ return ConvertText(mapper.mapped, strlen(mapper.mapped), charSetBuffer, "UTF-8", false);
}
-
- std::string ret(mappedBack, mappedLength);
- g_free(mapped);
- delete []needsFree1;
- delete []needsFree2;
- return ret;
}
int ScintillaGTK::KeyDefault(int key, int modifiers) {
@@ -1528,9 +1474,7 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
// Return empty string if selection is not a string
if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
- char *empty = new char[1];
- empty[0] = '\0';
- selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
+ selText.Copy("", 0, SC_CP_UTF8, 0, false, false);
return;
}
@@ -1544,28 +1488,24 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
len--; // Forget the extra '\0'
#endif
- char *dest;
+ std::string dest = Document::TransformLineEnds(data, len, pdoc->eolMode);
if (selectionTypeData == GDK_TARGET_STRING) {
- dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
if (IsUnicodeMode()) {
// Unknown encoding so assume in Latin1
- char *destPrevious = dest;
- dest = UTF8FromLatin1(dest, len);
- selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
- delete []destPrevious;
+ dest = UTF8FromLatin1(dest.c_str(), len);
+ selText.Copy(dest.c_str(), dest.length(), SC_CP_UTF8, 0, selText.rectangular, false);
} else {
// Assume buffer is in same encoding as selection
- selText.Set(dest, len, pdoc->dbcsCodePage,
+ selText.Copy(dest.c_str(), dest.length(), pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
}
} else { // UTF-8
- dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
- selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
+ selText.Copy(dest.c_str(), dest.length(), SC_CP_UTF8, 0, isRectangular, false);
const char *charSetBuffer = CharacterSetID();
if (!IsUnicodeMode() && *charSetBuffer) {
// Convert to locale
- dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
- selText.Set(dest, len, pdoc->dbcsCodePage,
+ dest = ConvertText(selText.s, selText.len, charSetBuffer, "UTF-8", true);
+ selText.Copy(dest.c_str(), dest.length(), pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
}
}
@@ -1611,11 +1551,10 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
dragWasDropped = true;
if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) {
- char *ptr = new char[LengthOfGSD(selection_data) + 1];
- ptr[LengthOfGSD(selection_data)] = '\0';
- memcpy(ptr, DataOfGSD(selection_data), LengthOfGSD(selection_data));
- NotifyURIDropped(ptr);
- delete []ptr;
+ const char *data = reinterpret_cast<const char *>(DataOfGSD(selection_data));
+ std::vector<char> drop(data, data + LengthOfGSD(selection_data));
+ drop.push_back('\0');
+ NotifyURIDropped(drop.data());
} else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) {
if (TypeOfGSD(selection_data) > 0) {
SelectionText selText;
@@ -1637,10 +1576,9 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
// from code below
SelectionText *newline_normalized = NULL;
{
- int tmpstr_len;
- char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
+ std::string tmpstr = Document::TransformLineEnds(text->s, text->len, SC_EOL_LF);
newline_normalized = new SelectionText();
- newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
+ newline_normalized->Copy(tmpstr.c_str(), tmpstr.length(), SC_CP_UTF8, 0, text->rectangular, false);
text = newline_normalized;
}
#endif
@@ -1650,10 +1588,9 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
const char *charSet = ::CharacterSetID(text->characterSet);
if (*charSet) {
- int new_len;
- char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
+ std::string tmputf = ConvertText(text->s, text->len, "UTF-8", charSet, false);
converted = new SelectionText();
- converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
+ converted->Copy(tmputf.c_str(), tmputf.length(), SC_CP_UTF8, 0, text->rectangular, false);
text = converted;
}
}
@@ -1923,8 +1860,7 @@ gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
// button4/5/6/7 events to the GTK app
-gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
- GdkEventScroll *event) {
+gint ScintillaGTK::ScrollEvent(GtkWidget *widget, GdkEventScroll *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget);
try {
@@ -2617,10 +2553,6 @@ gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selectio
return TRUE;
}
-void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
- //Platform::DebugPrintf("DragBegin\n");
-}
-
gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
gint x, gint y, guint dragtime) {
try {
Modified: scintilla/include/SciLexer.h
9 files changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -120,6 +120,7 @@
#define SCLEX_ECL 105
#define SCLEX_OSCRIPT 106
#define SCLEX_VISUALPROLOG 107
+#define SCLEX_LITERATEHASKELL 108
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
@@ -161,6 +162,7 @@
#define SCE_C_TRIPLEVERBATIM 21
#define SCE_C_HASHQUOTEDSTRING 22
#define SCE_C_PREPROCESSORCOMMENT 23
+#define SCE_C_PREPROCESSORCOMMENTDOC 24
#define SCE_D_DEFAULT 0
#define SCE_D_COMMENT 1
#define SCE_D_COMMENTLINE 2
@@ -1022,6 +1024,10 @@
#define SCE_HA_COMMENTBLOCK3 16
#define SCE_HA_PRAGMA 17
#define SCE_HA_PREPROCESSOR 18
+#define SCE_HA_STRINGEOL 19
+#define SCE_HA_RESERVED_OPERATOR 20
+#define SCE_HA_LITERATE_COMMENT 21
+#define SCE_HA_LITERATE_CODEDELIM 22
#define SCE_T3_DEFAULT 0
#define SCE_T3_X_DEFAULT 1
#define SCE_T3_PREPROCESSOR 2
@@ -1326,6 +1332,9 @@
#define SCE_POWERSHELL_FUNCTION 11
#define SCE_POWERSHELL_USER1 12
#define SCE_POWERSHELL_COMMENTSTREAM 13
+#define SCE_POWERSHELL_HERE_STRING 14
+#define SCE_POWERSHELL_HERE_CHARACTER 15
+#define SCE_POWERSHELL_COMMENTDOCKEYWORD 16
#define SCE_MYSQL_DEFAULT 0
#define SCE_MYSQL_COMMENT 1
#define SCE_MYSQL_COMMENTLINE 2
Modified: scintilla/include/Scintilla.h
13 files changed, 13 insertions(+), 0 deletions(-)
===================================================================
@@ -264,6 +264,7 @@
#define INDIC_SQUIGGLELOW 11
#define INDIC_DOTBOX 12
#define INDIC_SQUIGGLEPIXMAP 13
+#define INDIC_COMPOSITIONTHICK 14
#define INDIC_MAX 31
#define INDIC_CONTAINER 8
#define INDIC0_MASK 0x20
@@ -440,7 +441,19 @@
#define SCI_SETFOLDEXPANDED 2229
#define SCI_GETFOLDEXPANDED 2230
#define SCI_TOGGLEFOLD 2231
+#define SC_FOLDACTION_CONTRACT 0
+#define SC_FOLDACTION_EXPAND 1
+#define SC_FOLDACTION_TOGGLE 2
+#define SCI_FOLDLINE 2237
+#define SCI_FOLDCHILDREN 2238
+#define SCI_EXPANDCHILDREN 2239
+#define SCI_FOLDALL 2662
#define SCI_ENSUREVISIBLE 2232
+#define SC_AUTOMATICFOLD_SHOW 0x0001
+#define SC_AUTOMATICFOLD_CLICK 0x0002
+#define SC_AUTOMATICFOLD_CHANGE 0x0004
+#define SCI_SETAUTOMATICFOLD 2663
+#define SCI_GETAUTOMATICFOLD 2664
#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008
Modified: scintilla/include/Scintilla.iface
38 files changed, 38 insertions(+), 0 deletions(-)
===================================================================
@@ -581,6 +581,7 @@ val INDIC_DOTS=10
val INDIC_SQUIGGLELOW=11
val INDIC_DOTBOX=12
val INDIC_SQUIGGLEPIXMAP=13
+val INDIC_COMPOSITIONTHICK=14
val INDIC_MAX=31
val INDIC_CONTAINER=8
val INDIC0_MASK=0x20
@@ -1109,9 +1110,37 @@ get bool GetFoldExpanded=2230(int line,)
# Switch a header line between expanded and contracted.
fun void ToggleFold=2231(int line,)
+enu FoldAction=SC_FOLDACTION
+val SC_FOLDACTION_CONTRACT=0
+val SC_FOLDACTION_EXPAND=1
+val SC_FOLDACTION_TOGGLE=2
+
+# Expand or contract a fold header.
+fun void FoldLine=2237(int line, int action)
+
+# Expand or contract a fold header and its children.
+fun void FoldChildren=2238(int line, int action)
+
+# Expand a fold header and all children. Use the level argument instead of the line's current level.
+fun void ExpandChildren=2239(int line, int level)
+
+# Expand or contract all fold headers.
+fun void FoldAll=2662(int action,)
+
# Ensure a particular line is visible by expanding any header line hiding it.
fun void EnsureVisible=2232(int line,)
+enu AutomaticFold=SC_AUTOMATICFOLD_
+val SC_AUTOMATICFOLD_SHOW=0x0001
+val SC_AUTOMATICFOLD_CLICK=0x0002
+val SC_AUTOMATICFOLD_CHANGE=0x0004
+
+# Set automatic folding behaviours.
+set void SetAutomaticFold=2663(int automaticFold,)
+
+# Get automatic folding behaviours.
+get int GetAutomaticFold=2664(,)
+
enu FoldFlag=SC_FOLDFLAG_
val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002
val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004
@@ -2549,6 +2578,7 @@ val SCLEX_AVS=104
val SCLEX_ECL=105
val SCLEX_OSCRIPT=106
val SCLEX_VISUALPROLOG=107
+val SCLEX_LITERATEHASKELL=108
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1.
@@ -2599,6 +2629,7 @@ val SCE_C_STRINGRAW=20
val SCE_C_TRIPLEVERBATIM=21
val SCE_C_HASHQUOTEDSTRING=22
val SCE_C_PREPROCESSORCOMMENT=23
+val SCE_C_PREPROCESSORCOMMENTDOC=24
# Lexical states for SCLEX_D
lex D=SCLEX_D SCE_D_
val SCE_D_DEFAULT=0
@@ -3583,6 +3614,10 @@ val SCE_HA_COMMENTBLOCK2=15
val SCE_HA_COMMENTBLOCK3=16
val SCE_HA_PRAGMA=17
val SCE_HA_PREPROCESSOR=18
+val SCE_HA_STRINGEOL=19
+val SCE_HA_RESERVED_OPERATOR=20
+val SCE_HA_LITERATE_COMMENT=21
+val SCE_HA_LITERATE_CODEDELIM=22
# Lexical states of SCLEX_TADS3
lex TADS3=SCLEX_TADS3 SCE_T3_
val SCE_T3_DEFAULT=0
@@ -3923,6 +3958,9 @@ val SCE_POWERSHELL_ALIAS=10
val SCE_POWERSHELL_FUNCTION=11
val SCE_POWERSHELL_USER1=12
val SCE_POWERSHELL_COMMENTSTREAM=13
+val SCE_POWERSHELL_HERE_STRING=14
+val SCE_POWERSHELL_HERE_CHARACTER=15
+val SCE_POWERSHELL_COMMENTDOCKEYWORD=16
# Lexical state for SCLEX_MYSQL
lex MySQL=SCLEX_MYSQL SCE_MYSQL_
val SCE_MYSQL_DEFAULT=0
Modified: scintilla/lexers/LexCPP.cxx
15 files changed, 10 insertions(+), 5 deletions(-)
===================================================================
@@ -455,9 +455,9 @@ int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
if (n == 4) {
// Rebuild preprocessorDefinitions
preprocessorDefinitionsStart.clear();
- for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) {
- char *cpDefinition = ppDefinitions.words[nDefinition];
- char *cpEquals = strchr(cpDefinition, '=');
+ for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) {
+ const char *cpDefinition = ppDefinitions.WordAt(nDefinition);
+ const char *cpEquals = strchr(cpDefinition, '=');
if (cpEquals) {
std::string name(cpDefinition, cpEquals - cpDefinition);
std::string val(cpEquals+1);
@@ -672,7 +672,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
sc.SetState(SCE_C_DEFAULT|activitySet);
}
break;
- case SCE_C_PREPROCESSOR:
+ case SCE_C_PREPROCESSOR:
if (options.stylingWithinPreprocessor) {
if (IsASpace(sc.ch)) {
sc.SetState(SCE_C_DEFAULT|activitySet);
@@ -683,7 +683,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
if ((isIncludePreprocessor && sc.Match('<')) || sc.Match('\"')) {
isStringInPreprocessor = true;
} else if (sc.Match('/', '*')) {
- sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet);
+ if (sc.Match("/**") || sc.Match("/*!")) {
+ sc.SetState(SCE_C_PREPROCESSORCOMMENTDOC|activitySet);
+ } else {
+ sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet);
+ }
sc.Forward(); // Eat the *
} else if (sc.Match('/', '/')) {
sc.SetState(SCE_C_DEFAULT|activitySet);
@@ -691,6 +695,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
}
break;
case SCE_C_PREPROCESSORCOMMENT:
+ case SCE_C_PREPROCESSORCOMMENTDOC:
if (sc.Match('*', '/')) {
sc.Forward();
sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet);
Modified: scintilla/lexers/LexHaskell.cxx
1063 files changed, 871 insertions(+), 192 deletions(-)
===================================================================
@@ -4,21 +4,20 @@
* A haskell lexer for the scintilla code control.
* Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
* External lexer stuff inspired from the caml external lexer.
+ * Folder copied from Python's.
*
* Written by Tobias Engvall - tumm at dtek dot chalmers dot se
*
* Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com
*
- * Improvements by kudah - kudahkukarek at gmail.com
+ * Improved by kudah <kudahkukarek at gmail.com>
*
* TODO:
- * * Implement a folder :)
- * * Nice Character-lexing (stuff inside '\''), LexPython has
- * this.
- *
+ * * A proper lexical folder to fold group declarations, comments, pragmas,
+ * #ifdefs, explicit layout, lists, tuples, quasi-quotes, splces, etc, etc,
+ * etc.
*
*****************************************************************/
-
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -26,6 +25,9 @@
#include <assert.h>
#include <ctype.h>
+#include <string>
+#include <map>
+
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@@ -37,195 +39,746 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
+#include "OptionSet.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
-#ifdef BUILD_AS_EXTERNAL_LEXER
+static int u_iswalpha(int);
+static int u_iswalnum(int);
+static int u_iswupper(int);
+static int u_IsHaskellSymbol(int);
-#include "ExternalLexer.h"
-#include "WindowAccessor.h"
+// #define HASKELL_UNICODE
-#define BUILD_EXTERNAL_LEXER 0
+#ifndef HASKELL_UNICODE
+
+// Stubs
+
+static int u_iswalpha(int) {
+ return 0;
+}
+
+static int u_iswalnum(int) {
+ return 0;
+}
+
+static int u_iswupper(int) {
+ return 0;
+}
+
+static int u_IsHaskellSymbol(int) {
+ return 0;
+}
#endif
-#define HA_MODE_DEFAULT 0
-#define HA_MODE_IMPORT1 1
-#define HA_MODE_IMPORT2 2
-#define HA_MODE_IMPORT3 3
-#define HA_MODE_MODULE 4
-#define HA_MODE_FFI 5
-#define HA_MODE_TYPE 6
+static inline bool IsHaskellLetter(const int ch) {
+ if (IsASCII(ch)) {
+ return (ch >= 'a' && ch <= 'z')
+ || (ch >= 'A' && ch <= 'Z');
+ } else {
+ return u_iswalpha(ch) != 0;
+ }
+}
+
+static inline bool IsHaskellAlphaNumeric(const int ch) {
+ if (IsASCII(ch)) {
+ return IsAlphaNumeric(ch);
+ } else {
+ return u_iswalnum(ch) != 0;
+ }
+}
+
+static inline bool IsHaskellUpperCase(const int ch) {
+ if (IsASCII(ch)) {
+ return ch >= 'A' && ch <= 'Z';
+ } else {
+ return u_iswupper(ch) != 0;
+ }
+}
-static inline bool IsAWordStart(const int ch) {
- return (IsLowerCase(ch) || IsUpperCase(ch) || ch == '_');
+static inline bool IsAnHaskellOperatorChar(const int ch) {
+ if (IsASCII(ch)) {
+ return
+ ( ch == '!' || ch == '#' || ch == '$' || ch == '%'
+ || ch == '&' || ch == '*' || ch == '+' || ch == '-'
+ || ch == '.' || ch == '/' || ch == ':' || ch == '<'
+ || ch == '=' || ch == '>' || ch == '?' || ch == '@'
+ || ch == '^' || ch == '|' || ch == '~' || ch == '\\');
+ } else {
+ return u_IsHaskellSymbol(ch) != 0;
+ }
}
-static inline bool IsAWordChar(const int ch, const bool magicHash) {
- return ( IsAlphaNumeric(ch)
+static inline bool IsAHaskellWordStart(const int ch) {
+ return IsHaskellLetter(ch) || ch == '_';
+}
+
+static inline bool IsAHaskellWordChar(const int ch) {
+ return ( IsHaskellAlphaNumeric(ch)
|| ch == '_'
- || ch == '\''
- || (magicHash && ch == '#'));
+ || 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 inline bool IsCommentBlockStyle(int style) {
+ return (style >= SCE_HA_COMMENTBLOCK && style <= SCE_HA_COMMENTBLOCK3);
}
-static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
- WordList *keywordlists[], Accessor &styler) {
+static inline bool IsCommentStyle(int style) {
+ return (style >= SCE_HA_COMMENTLINE && style <= SCE_HA_COMMENTBLOCK3)
+ || ( style == SCE_HA_LITERATE_COMMENT
+ || style == SCE_HA_LITERATE_CODEDELIM);
+}
- WordList &keywords = *keywordlists[0];
- WordList &ffi = *keywordlists[1];
+// styles which do not belong to Haskell, but to external tools
+static inline bool IsExternalStyle(int style) {
+ return ( style == SCE_HA_PREPROCESSOR
+ || style == SCE_HA_LITERATE_COMMENT
+ || style == SCE_HA_LITERATE_CODEDELIM);
+}
- // 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;
+static inline int CommentBlockStyleFromNestLevel(const unsigned int nestLevel) {
+ return SCE_HA_COMMENTBLOCK + (nestLevel % 3);
+}
- StyleContext sc(startPos, length, initStyle, styler);
+// Mangled version of lexlib/Accessor.cxx IndentAmount.
+// Modified to treat comment blocks as whitespace
+// plus special case for commentline/preprocessor.
+static int HaskellIndentAmount(Accessor &styler, const int line) {
+
+ // Determines the indentation level of the current line
+ // Comment blocks are treated as whitespace
+
+ int pos = styler.LineStart(line);
+ int eol_pos = styler.LineStart(line + 1) - 1;
+
+ char ch = styler[pos];
+ int style = styler.StyleAt(pos);
+
+ int indent = 0;
+ bool inPrevPrefix = line > 0;
+
+ int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
+
+ while (( ch == ' ' || ch == '\t'
+ || IsCommentBlockStyle(style)
+ || style == SCE_HA_LITERATE_CODEDELIM)
+ && (pos < eol_pos)) {
+ if (inPrevPrefix) {
+ char chPrev = styler[posPrev++];
+ if (chPrev != ' ' && chPrev != '\t') {
+ inPrevPrefix = false;
+ }
+ }
+ if (ch == '\t') {
+ indent = (indent / 8 + 1) * 8;
+ } else { // Space or comment block
+ indent++;
+ }
+ pos++;
+ ch = styler[pos];
+ style = styler.StyleAt(pos);
+ }
+
+ indent += SC_FOLDLEVELBASE;
+ // if completely empty line or the start of a comment or preprocessor...
+ if ( styler.LineStart(line) == styler.Length()
+ || ch == ' '
+ || ch == '\t'
+ || ch == '\n'
+ || ch == '\r'
+ || IsCommentStyle(style)
+ || style == SCE_HA_PREPROCESSOR)
+ return indent | SC_FOLDLEVELWHITEFLAG;
+ else
+ return indent;
+}
+
+struct OptionsHaskell {
+ bool magicHash;
+ bool allowQuotes;
+ bool implicitParams;
+ bool highlightSafe;
+ bool cpp;
+ bool stylingWithinPreprocessor;
+ bool fold;
+ bool foldComment;
+ bool foldCompact;
+ bool foldImports;
+ OptionsHaskell() {
+ magicHash = true; // Widespread use, enabled by default.
+ allowQuotes = true; // Widespread use, enabled by default.
+ implicitParams = false; // Fell out of favor, seldom used, disabled.
+ highlightSafe = true; // Moderately used, doesn't hurt to enable.
+ cpp = true; // Widespread use, enabled by default;
+ stylingWithinPreprocessor = false;
+ fold = false;
+ foldComment = false;
+ foldCompact = false;
+ foldImports = false;
+ }
+};
+
+static const char * const haskellWordListDesc[] = {
+ "Keywords",
+ "FFI",
+ "Reserved operators",
+ 0
+};
+
+struct OptionSetHaskell : public OptionSet<OptionsHaskell> {
+ OptionSetHaskell() {
+ DefineProperty("lexer.haskell.allow.hash", &OptionsHaskell::magicHash,
+ "Set to 0 to disallow the '#' character at the end of identifiers and "
+ "literals with the haskell lexer "
+ "(GHC -XMagicHash extension)");
+
+ DefineProperty("lexer.haskell.allow.quotes", &OptionsHaskell::allowQuotes,
+ "Set to 0 to disable highlighting of Template Haskell name quotations "
+ "and promoted constructors "
+ "(GHC -XTemplateHaskell and -XDataKinds extensions)");
+
+ DefineProperty("lexer.haskell.allow.questionmark", &OptionsHaskell::implicitParams,
+ "Set to 1 to allow the '?' character at the start of identifiers "
+ "with the haskell lexer "
+ "(GHC & Hugs -XImplicitParams extension)");
+
+ DefineProperty("lexer.haskell.import.safe", &OptionsHaskell::highlightSafe,
+ "Set to 0 to disallow \"safe\" keyword in imports "
+ "(GHC -XSafe, -XTrustworthy, -XUnsafe extensions)");
+
+ DefineProperty("lexer.haskell.cpp", &OptionsHaskell::cpp,
+ "Set to 0 to disable C-preprocessor highlighting "
+ "(-XCPP extension)");
+
+ DefineProperty("styling.within.preprocessor", &OptionsHaskell::stylingWithinPreprocessor,
+ "For Haskell code, determines whether all preprocessor code is styled in the "
+ "preprocessor style (0, the default) or only from the initial # to the end "
+ "of the command word(1)."
+ );
+
+ DefineProperty("fold", &OptionsHaskell::fold);
+
+ DefineProperty("fold.comment", &OptionsHaskell::foldComment);
+
+ DefineProperty("fold.compact", &OptionsHaskell::foldCompact);
+
+ DefineProperty("fold.haskell.imports", &OptionsHaskell::foldImports,
+ "Set to 1 to enable folding of import declarations");
+
+ DefineWordListSets(haskellWordListDesc);
+ }
+};
+
+class LexerHaskell : public ILexer {
+ bool literate;
+ int firstImportLine;
+ int firstImportIndent;
+ WordList keywords;
+ WordList ffi;
+ WordList reserved_operators;
+ OptionsHaskell options;
+ OptionSetHaskell osHaskell;
+
+ enum HashCount {
+ oneHash
+ ,twoHashes
+ ,unlimitedHashes
+ };
+
+ enum KeywordMode {
+ HA_MODE_DEFAULT = 0
+ ,HA_MODE_IMPORT1 = 1 // after "import", before "qualified" or "safe" or package name or module name.
+ ,HA_MODE_IMPORT2 = 2 // after module name, before "as" or "hiding".
+ ,HA_MODE_IMPORT3 = 3 // after "as", before "hiding"
+ ,HA_MODE_MODULE = 4 // after "module", before module name.
+ ,HA_MODE_FFI = 5 // after "foreign", before FFI keywords
+ ,HA_MODE_TYPE = 6 // after "type" or "data", before "family"
+ };
+
+ enum LiterateMode {
+ LITERATE_BIRD = 0 // if '>' is the first character on the line,
+ // color '>' as a codedelim and the rest of
+ // the line as code.
+ // else if "\begin{code}" is the only word on the
+ // line except whitespace, switch to LITERATE_BLOCK
+ // otherwise color the line as a literate comment.
+ ,LITERATE_BLOCK = 1 // if the string "\end{code}" is encountered at column
+ // 0 ignoring all later characters, color the line
+ // as a codedelim and switch to LITERATE_BIRD
+ // otherwise color the line as code.
+ };
+
+ struct HaskellLineInfo {
+ unsigned int nestLevel; // 22 bits ought to be enough for anybody
+ unsigned int nonexternalStyle; // 5 bits, widen if number of styles goes
+ // beyond 31.
+ bool pragma;
+ LiterateMode lmode;
+ KeywordMode mode;
+
+ HaskellLineInfo(int state) :
+ nestLevel (state >> 10)
+ , nonexternalStyle ((state >> 5) & 0x1F)
+ , pragma ((state >> 4) & 0x1)
+ , lmode (static_cast<LiterateMode>((state >> 3) & 0x1))
+ , mode (static_cast<KeywordMode>(state & 0x7))
+ {}
+
+ int ToLineState() {
+ return
+ (nestLevel << 10)
+ | (nonexternalStyle << 5)
+ | (pragma << 4)
+ | (lmode << 3)
+ | mode;
+ }
+ };
+
+ inline void skipMagicHash(StyleContext &sc, const HashCount hashes) const {
+ if (options.magicHash && sc.ch == '#') {
+ sc.Forward();
+ if (hashes == twoHashes && sc.ch == '#') {
+ sc.Forward();
+ } else if (hashes == unlimitedHashes) {
+ while (sc.ch == '#') {
+ sc.Forward();
+ }
+ }
+ }
+ }
+
+ bool LineContainsImport(const int line, Accessor &styler) const {
+ if (options.foldImports) {
+ int currentPos = styler.LineStart(line);
+ int style = styler.StyleAt(currentPos);
+
+ int eol_pos = styler.LineStart(line + 1) - 1;
+
+ while (currentPos < eol_pos) {
+ int ch = styler[currentPos];
+ style = styler.StyleAt(currentPos);
+
+ if (ch == ' ' || ch == '\t'
+ || IsCommentBlockStyle(style)
+ || style == SCE_HA_LITERATE_CODEDELIM) {
+ currentPos++;
+ } else {
+ break;
+ }
+ }
+
+ return (style == SCE_HA_KEYWORD
+ && styler.Match(currentPos, "import"));
+ } else {
+ return false;
+ }
+ }
+
+ inline int IndentAmountWithOffset(Accessor &styler, const int line) const {
+ const int indent = HaskellIndentAmount(styler, line);
+ const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK;
+ return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE)
+ ? indent
+ : (indentLevel + firstImportIndent) | (indent & ~SC_FOLDLEVELNUMBERMASK);
+ }
+
+ inline int IndentLevelRemoveIndentOffset(const int indentLevel) const {
+ return indentLevel <= ((firstImportIndent - 1) + SC_FOLDLEVELBASE)
+ ? indentLevel
+ : indentLevel - firstImportIndent;
+ }
+
+public:
+ LexerHaskell(bool literate_)
+ : literate(literate_)
+ , firstImportLine(-1)
+ , firstImportIndent(0)
+ {}
+ virtual ~LexerHaskell() {}
+
+ void SCI_METHOD Release() {
+ delete this;
+ }
+
+ int SCI_METHOD Version() const {
+ return lvOriginal;
+ }
+
+ const char * SCI_METHOD PropertyNames() {
+ return osHaskell.PropertyNames();
+ }
+
+ int SCI_METHOD PropertyType(const char *name) {
+ return osHaskell.PropertyType(name);
+ }
+
+ const char * SCI_METHOD DescribeProperty(const char *name) {
+ return osHaskell.DescribeProperty(name);
+ }
+
+ int SCI_METHOD PropertySet(const char *key, const char *val);
+
+ const char * SCI_METHOD DescribeWordListSets() {
+ return osHaskell.DescribeWordListSets();
+ }
+
+ int SCI_METHOD WordListSet(int n, const char *wl);
+
+ 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);
+
+ void * SCI_METHOD PrivateCall(int, void *) {
+ return 0;
+ }
+
+ static ILexer *LexerFactoryHaskell() {
+ return new LexerHaskell(false);
+ }
+
+ static ILexer *LexerFactoryLiterateHaskell() {
+ return new LexerHaskell(true);
+ }
+};
+
+int SCI_METHOD LexerHaskell::PropertySet(const char *key, const char *val) {
+ if (osHaskell.PropertySet(&options, key, val)) {
+ return 0;
+ }
+ return -1;
+}
+
+int SCI_METHOD LexerHaskell::WordListSet(int n, const char *wl) {
+ WordList *wordListN = 0;
+ switch (n) {
+ case 0:
+ wordListN = &keywords;
+ break;
+ case 1:
+ wordListN = &ffi;
+ break;
+ case 2:
+ wordListN = &reserved_operators;
+ break;
+ }
+ int firstModification = -1;
+ if (wordListN) {
+ WordList wlNew;
+ wlNew.Set(wl);
+ if (*wordListN != wlNew) {
+ wordListN->Set(wl);
+ firstModification = 0;
+ }
+ }
+ return firstModification;
+}
+
+void SCI_METHOD LexerHaskell::Lex(unsigned int startPos, int length, int initStyle
+ ,IDocument *pAccess) {
+ LexAccessor styler(pAccess);
int lineCurrent = styler.GetLine(startPos);
- int state = lineCurrent ? styler.GetLineState(lineCurrent-1)
- : HA_MODE_DEFAULT;
- int mode = state & 0xF;
- int xmode = state >> 4; // obscure parameter. Means different things in different modes.
+
+ HaskellLineInfo hs = HaskellLineInfo(lineCurrent ? styler.GetLineState(lineCurrent-1) : 0);
+
+ // Do not leak onto next line
+ if (initStyle == SCE_HA_STRINGEOL)
+ initStyle = SCE_HA_DEFAULT;
+ else if (initStyle == SCE_HA_LITERATE_CODEDELIM)
+ initStyle = hs.nonexternalStyle;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ int base = 10;
+ bool dot = false;
+
+ bool inDashes = false;
+ bool alreadyInTheMiddleOfOperator = false;
+
+ assert(!(IsCommentBlockStyle(initStyle) && hs.nestLevel == 0));
while (sc.More()) {
// Check for state end
+ if (!IsExternalStyle(sc.state)) {
+ hs.nonexternalStyle = sc.state;
+ }
+
+ // For lexer to work, states should unconditionally forward at least one
+ // character.
+ // If they don't, they should still check if they are at line end and
+ // forward if so.
+ // If a state forwards more than one character, it should check every time
+ // that it is not a line end and cease forwarding otherwise.
+ if (sc.atLineEnd) {
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, hs.ToLineState());
+ lineCurrent++;
+ }
+
+ // Handle line continuation generically.
+ if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r')
+ && ( sc.state == SCE_HA_STRING
+ || sc.state == SCE_HA_PREPROCESSOR)) {
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, hs.ToLineState());
+ lineCurrent++;
+
+ sc.Forward();
+ if (sc.ch == '\r' && sc.chNext == '\n') {
+ sc.Forward();
+ }
+ sc.Forward();
+
+ continue;
+ }
+
+ if (sc.atLineStart) {
+
+ if (sc.state == SCE_HA_STRING || sc.state == SCE_HA_CHARACTER) {
+ // Prevent SCE_HA_STRINGEOL from leaking back to previous line
+ sc.SetState(sc.state);
+ }
+
+ if (literate && hs.lmode == LITERATE_BIRD) {
+ if (!IsExternalStyle(sc.state)) {
+ sc.SetState(SCE_HA_LITERATE_COMMENT);
+ }
+ }
+ }
+
+ // External
+ // Literate
+ if ( literate && hs.lmode == LITERATE_BIRD && sc.atLineStart
+ && sc.ch == '>') {
+ sc.SetState(SCE_HA_LITERATE_CODEDELIM);
+ sc.ForwardSetState(hs.nonexternalStyle);
+ }
+ else if (literate && hs.lmode == LITERATE_BIRD && sc.atLineStart
+ && ( sc.ch == ' ' || sc.ch == '\t'
+ || sc.Match("\\begin{code}"))) {
+ sc.SetState(sc.state);
+
+ while ((sc.ch == ' ' || sc.ch == '\t') && sc.More())
+ sc.Forward();
+
+ if (sc.Match("\\begin{code}")) {
+ sc.Forward(static_cast<int>(strlen("\\begin{code}")));
+
+ bool correct = true;
+
+ while (!sc.atLineEnd && sc.More()) {
+ if (sc.ch != ' ' && sc.ch != '\t') {
+ correct = false;
+ }
+ sc.Forward();
+ }
+
+ if (correct) {
+ sc.ChangeState(SCE_HA_LITERATE_CODEDELIM); // color the line end
+ hs.lmode = LITERATE_BLOCK;
+ }
+ }
+ }
+ else if (literate && hs.lmode == LITERATE_BLOCK && sc.atLineStart
+ && sc.Match("\\end{code}")) {
+ sc.SetState(SCE_HA_LITERATE_CODEDELIM);
+
+ sc.Forward(static_cast<int>(strlen("\\end{code}")));
+
+ while (!sc.atLineEnd && sc.More()) {
+ sc.Forward();
+ }
+
+ sc.SetState(SCE_HA_LITERATE_COMMENT);
+ hs.lmode = LITERATE_BIRD;
+ }
+ // Preprocessor
+ else if (sc.atLineStart && sc.ch == '#' && options.cpp) {
+ sc.SetState(SCE_HA_PREPROCESSOR);
+ sc.Forward();
+ }
+ // Literate
+ else if (sc.state == SCE_HA_LITERATE_COMMENT) {
+ sc.Forward();
+ }
+ else if (sc.state == SCE_HA_LITERATE_CODEDELIM) {
+ sc.ForwardSetState(hs.nonexternalStyle);
+ }
+ // Preprocessor
+ else if (sc.state == SCE_HA_PREPROCESSOR) {
+ if (sc.atLineEnd) {
+ sc.SetState(options.stylingWithinPreprocessor
+ ? SCE_HA_DEFAULT
+ : hs.nonexternalStyle);
+ sc.Forward(); // prevent double counting a line
+ } else if (options.stylingWithinPreprocessor && !IsHaskellLetter(sc.ch)) {
+ sc.SetState(SCE_HA_DEFAULT);
+ } else {
+ sc.Forward();
+ }
+ }
+ // Haskell
// Operator
- if (sc.state == SCE_HA_OPERATOR) {
+ else if (sc.state == SCE_HA_OPERATOR) {
int style = SCE_HA_OPERATOR;
- if (sc.ch == ':' &&
+ if ( sc.ch == ':'
+ && !alreadyInTheMiddleOfOperator
// except "::"
- !(sc.chNext == ':' && !IsAnOperatorChar(sc.GetRelative(2)))) {
+ && !( sc.chNext == ':'
+ && !IsAnHaskellOperatorChar(sc.GetRelative(2)))) {
style = SCE_HA_CAPITAL;
}
- while(IsAnOperatorChar(sc.ch))
+ alreadyInTheMiddleOfOperator = false;
+
+ while (IsAnHaskellOperatorChar(sc.ch))
sc.Forward();
- styler.ColourTo(sc.currentPos - 1, style);
- sc.ChangeState(SCE_HA_DEFAULT);
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+
+ if (reserved_operators.InList(s))
+ style = SCE_HA_RESERVED_OPERATOR;
+
+ sc.ChangeState(style);
+ sc.SetState(SCE_HA_DEFAULT);
}
// String
else if (sc.state == SCE_HA_STRING) {
- if (sc.ch == '\"') {
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_HA_STRINGEOL);
+ sc.ForwardSetState(SCE_HA_DEFAULT);
+ } else if (sc.ch == '\"') {
sc.Forward();
+ skipMagicHash(sc, oneHash);
sc.SetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward(2);
- } else if (sc.atLineEnd) {
- sc.SetState(SCE_HA_DEFAULT);
} else {
sc.Forward();
}
}
// Char
else if (sc.state == SCE_HA_CHARACTER) {
- if (sc.ch == '\'') {
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_HA_STRINGEOL);
+ sc.ForwardSetState(SCE_HA_DEFAULT);
+ } else if (sc.ch == '\'') {
sc.Forward();
+ skipMagicHash(sc, oneHash);
sc.SetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward(2);
- } else if (sc.atLineEnd) {
- sc.SetState(SCE_HA_DEFAULT);
} else {
sc.Forward();
}
}
// Number
else if (sc.state == SCE_HA_NUMBER) {
- if (IsADigit(sc.ch, xmode) ||
- (sc.ch=='.' && IsADigit(sc.chNext, xmode))) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_HA_DEFAULT);
+ sc.Forward(); // prevent double counting a line
+ } else if (IsADigit(sc.ch, base)) {
sc.Forward();
- } else if ((xmode == 10) &&
+ } else if (sc.ch=='.' && dot && IsADigit(sc.chNext, base)) {
+ sc.Forward(2);
+ dot = false;
+ } else if ((base == 10) &&
(sc.ch == 'e' || sc.ch == 'E') &&
(IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) {
sc.Forward();
if (sc.ch == '+' || sc.ch == '-')
sc.Forward();
} else {
+ skipMagicHash(sc, twoHashes);
sc.SetState(SCE_HA_DEFAULT);
}
}
// Keyword or Identifier
else if (sc.state == SCE_HA_IDENTIFIER) {
+ int style = IsHaskellUpperCase(sc.ch) ? SCE_HA_CAPITAL : SCE_HA_IDENTIFIER;
+
+ assert(IsAHaskellWordStart(sc.ch));
+
+ sc.Forward();
+
while (sc.More()) {
- if (IsAWordChar(sc.ch, magicHash)) {
+ if (IsAHaskellWordChar(sc.ch)) {
sc.Forward();
- } else if (xmode == SCE_HA_CAPITAL && sc.ch=='.') {
- if (isupper(sc.chNext)) {
- xmode = SCE_HA_CAPITAL;
+ } else if (sc.ch == '.' && style == SCE_HA_CAPITAL) {
+ if (IsHaskellUpperCase(sc.chNext)) {
sc.Forward();
- } else if (IsAWordStart(sc.chNext)) {
- xmode = SCE_HA_IDENTIFIER;
+ style = SCE_HA_CAPITAL;
+ } else if (IsAHaskellWordStart(sc.chNext)) {
sc.Forward();
- } else if (IsAnOperatorChar(sc.chNext)) {
- xmode = SCE_HA_OPERATOR;
+ style = SCE_HA_IDENTIFIER;
+ } else if (IsAnHaskellOperatorChar(sc.chNext)) {
sc.Forward();
+ style = sc.ch == ':' ? SCE_HA_CAPITAL : SCE_HA_OPERATOR;
+ while (IsAnHaskellOperatorChar(sc.ch))
+ sc.Forward();
+ break;
} else {
break;
}
- } else if (xmode == SCE_HA_OPERATOR && IsAnOperatorChar(sc.ch)) {
- sc.Forward();
} else {
break;
}
}
+ skipMagicHash(sc, unlimitedHashes);
+
char s[100];
sc.GetCurrent(s, sizeof(s));
- int style = xmode;
-
- int new_mode = HA_MODE_DEFAULT;
+ KeywordMode 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) {
+ } else if (style == SCE_HA_CAPITAL) {
+ if (hs.mode == HA_MODE_IMPORT1 || hs.mode == HA_MODE_IMPORT3) {
style = SCE_HA_MODULE;
new_mode = HA_MODE_IMPORT2;
- } else if (mode == HA_MODE_MODULE) {
+ } else if (hs.mode == HA_MODE_MODULE) {
style = SCE_HA_MODULE;
}
- } else if (mode == HA_MODE_IMPORT1 &&
+ } else if (hs.mode == HA_MODE_IMPORT1 &&
strcmp(s,"qualified") == 0) {
style = SCE_HA_KEYWORD;
new_mode = HA_MODE_IMPORT1;
- } else if (mode == HA_MODE_IMPORT2) {
+ } else if (options.highlightSafe &&
+ hs.mode == HA_MODE_IMPORT1 &&
+ strcmp(s,"safe") == 0) {
+ style = SCE_HA_KEYWORD;
+ new_mode = HA_MODE_IMPORT1;
+ } else if (hs.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) {
+ } else if (hs.mode == HA_MODE_TYPE) {
if (strcmp(s,"family") == 0)
style = SCE_HA_KEYWORD;
}
- if (mode == HA_MODE_FFI) {
+ if (hs.mode == HA_MODE_FFI) {
if (ffi.InList(s)) {
style = SCE_HA_KEYWORD;
new_mode = HA_MODE_FFI;
}
}
- styler.ColourTo(sc.currentPos - 1, style);
+ sc.ChangeState(style);
+ sc.SetState(SCE_HA_DEFAULT);
- if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
+ if (strcmp(s,"import") == 0 && hs.mode != HA_MODE_FFI)
new_mode = HA_MODE_IMPORT1;
else if (strcmp(s,"module") == 0)
new_mode = HA_MODE_MODULE;
@@ -235,87 +788,88 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
|| strcmp(s,"data") == 0)
new_mode = HA_MODE_TYPE;
- xmode = 0;
- sc.ChangeState(SCE_HA_DEFAULT);
- mode = new_mode;
+ hs.mode = new_mode;
}
// Comments
// Oneliner
else if (sc.state == SCE_HA_COMMENTLINE) {
- if (xmode == 1 && sc.ch != '-') {
- xmode = 0;
- if (IsAnOperatorChar(sc.ch))
+ if (sc.atLineEnd) {
+ sc.SetState(hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT);
+ sc.Forward(); // prevent double counting a line
+ } else if (inDashes && sc.ch != '-' && !hs.pragma) {
+ inDashes = false;
+ if (IsAnHaskellOperatorChar(sc.ch)) {
+ alreadyInTheMiddleOfOperator = true;
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) {
+ else if (IsCommentBlockStyle(sc.state)) {
if (sc.Match('{','-')) {
+ sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel));
sc.Forward(2);
- xmode++;
- }
- else if (sc.Match('-','}')) {
+ hs.nestLevel++;
+ } else if (sc.Match('-','}')) {
sc.Forward(2);
- xmode--;
- if (xmode == 0) {
- sc.SetState(SCE_HA_DEFAULT);
- }
+ assert(hs.nestLevel > 0);
+ if (hs.nestLevel > 0)
+ hs.nestLevel--;
+ sc.SetState(
+ hs.nestLevel == 0
+ ? (hs.pragma ? SCE_HA_PRAGMA : SCE_HA_DEFAULT)
+ : CommentBlockStyleFromNestLevel(hs.nestLevel - 1));
} else {
- if (sc.atLineEnd) {
- // 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("#-}")) {
+ hs.pragma = false;
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) {
+ } else if (sc.Match('-','-')) {
+ sc.SetState(SCE_HA_COMMENTLINE);
sc.Forward(2);
- } else if (sc.atLineEnd) {
- sc.SetState(SCE_HA_DEFAULT);
+ inDashes = false;
+ } else if (sc.Match('{','-')) {
+ sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel));
+ sc.Forward(2);
+ hs.nestLevel = 1;
} else {
sc.Forward();
}
}
- // New state?
- if (sc.state == SCE_HA_DEFAULT) {
+ // New state?
+ else if (sc.state == SCE_HA_DEFAULT) {
// Digit
if (IsADigit(sc.ch)) {
+ hs.mode = HA_MODE_DEFAULT;
+
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);
+ base = 16;
+ dot = false;
} 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 "0o" or "0O", too
+ sc.Forward(2);
+ base = 8;
+ dot = false;
} else {
- sc.Forward();
- xmode = 10;
+ sc.Forward();
+ base = 10;
+ dot = true;
}
- mode = HA_MODE_DEFAULT;
}
// Pragma
else if (sc.Match("{-#")) {
+ hs.pragma = true;
sc.SetState(SCE_HA_PRAGMA);
sc.Forward(3);
}
@@ -323,33 +877,65 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
else if (sc.Match('-','-')) {
sc.SetState(SCE_HA_COMMENTLINE);
sc.Forward(2);
- xmode = 1;
+ inDashes = true;
}
// Comment block
else if (sc.Match('{','-')) {
- sc.SetState(SCE_HA_COMMENTBLOCK);
+ sc.SetState(CommentBlockStyleFromNestLevel(hs.nestLevel));
sc.Forward(2);
- xmode = 1;
+ hs.nestLevel = 1;
}
// String
- else if (sc.Match('\"')) {
+ else if (sc.ch == '\"') {
sc.SetState(SCE_HA_STRING);
sc.Forward();
}
- // Character
- else if (sc.Match('\'')) {
+ // Character or quoted name or promoted term
+ else if (sc.ch == '\'') {
+ hs.mode = HA_MODE_DEFAULT;
+
sc.SetState(SCE_HA_CHARACTER);
sc.Forward();
+
+ if (options.allowQuotes) {
+ // Quoted type ''T
+ if (sc.ch=='\'' && IsAHaskellWordStart(sc.chNext)) {
+ sc.Forward();
+ sc.ChangeState(SCE_HA_IDENTIFIER);
+ } else if (sc.chNext != '\'') {
+ // Quoted name 'n or promoted constructor 'N
+ if (IsAHaskellWordStart(sc.ch)) {
+ sc.ChangeState(SCE_HA_IDENTIFIER);
+ // Promoted constructor operator ':~>
+ } else if (sc.ch == ':') {
+ alreadyInTheMiddleOfOperator = false;
+ sc.ChangeState(SCE_HA_OPERATOR);
+ // Promoted list or tuple '[T]
+ } else if (sc.ch == '[' || sc.ch== '(') {
+ sc.ChangeState(SCE_HA_OPERATOR);
+ sc.ForwardSetState(SCE_HA_DEFAULT);
+ }
+ }
+ }
}
- // Preprocessor
- else if (sc.atLineStart && sc.ch == '#') {
- mode = HA_MODE_DEFAULT;
- sc.SetState(SCE_HA_PREPROCESSOR);
- sc.Forward();
+ // Operator starting with '?' or an implicit parameter
+ else if (sc.ch == '?') {
+ hs.mode = HA_MODE_DEFAULT;
+
+ alreadyInTheMiddleOfOperator = false;
+ sc.SetState(SCE_HA_OPERATOR);
+
+ if ( options.implicitParams
+ && IsAHaskellWordStart(sc.chNext)
+ && !IsHaskellUpperCase(sc.chNext)) {
+ sc.Forward();
+ sc.ChangeState(SCE_HA_IDENTIFIER);
+ }
}
// Operator
- else if (IsAnOperatorChar(sc.ch)) {
- mode = HA_MODE_DEFAULT;
+ else if (IsAnHaskellOperatorChar(sc.ch)) {
+ hs.mode = HA_MODE_DEFAULT;
+
sc.SetState(SCE_HA_OPERATOR);
}
// Braces and punctuation
@@ -358,78 +944,171 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
|| sc.ch == '[' || sc.ch == ']'
|| sc.ch == '{' || sc.ch == '}') {
sc.SetState(SCE_HA_OPERATOR);
- sc.Forward();
- sc.SetState(SCE_HA_DEFAULT);
+ sc.ForwardSetState(SCE_HA_DEFAULT);
}
// Keyword or Identifier
- else if (IsAWordStart(sc.ch)) {
- xmode = isupper(sc.ch) ? SCE_HA_CAPITAL : SCE_HA_IDENTIFIER;
+ else if (IsAHaskellWordStart(sc.ch)) {
sc.SetState(SCE_HA_IDENTIFIER);
- sc.Forward();
+ // Something we don't care about
} else {
- if (sc.atLineEnd) {
- // Remember the line state for future incremental lexing
- styler.SetLineState(lineCurrent, (xmode << 4) | mode);
- lineCurrent++;
- }
sc.Forward();
}
}
+ // This branch should never be reached.
+ else {
+ assert(false);
+ sc.Forward();
+ }
}
+ styler.SetLineState(lineCurrent, hs.ToLineState());
sc.Complete();
}
-// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
-// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
-#ifdef BUILD_EXTERNAL_LEXER
-static const char* LexerName = "haskell";
-
-void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
- char *words[], WindowID window, char *props)
-{
- PropSetSimple ps;
- ps.SetMultiple(props);
- WindowAccessor wa(window, ps);
-
- int nWL = 0;
- for (; words[nWL]; nWL++) ;
- WordList** wl = new WordList* [nWL + 1];
- int i = 0;
- for (; i<nWL; i++)
- {
- wl[i] = new WordList();
- wl[i]->Set(words[i]);
+void SCI_METHOD LexerHaskell::Fold(unsigned int startPos, int length, int // initStyle
+ ,IDocument *pAccess) {
+ if (!options.fold)
+ return;
+
+ Accessor styler(pAccess, NULL);
+
+ int lineCurrent = styler.GetLine(startPos);
+
+ if (lineCurrent <= firstImportLine) {
+ firstImportLine = -1; // readjust first import position
+ firstImportIndent = 0;
}
- wl[i] = 0;
- ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
- wa.Flush();
- for (i=nWL-1;i>=0;i--)
- delete wl[i];
- delete [] wl;
-}
+ const int maxPos = startPos + length;
+ const int maxLines =
+ maxPos == styler.Length()
+ ? styler.GetLine(maxPos)
+ : styler.GetLine(maxPos - 1); // Requested last line
+ const int docLines = styler.GetLine(styler.Length()); // Available last line
-void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
- char *words[], WindowID window, char *props)
-{
+ // Backtrack to previous non-blank line so we can determine indent level
+ // for any white space lines
+ // and so we can fix any preceding fold level (which is why we go back
+ // at least one line in all cases)
+ bool importHere = LineContainsImport(lineCurrent, styler);
+ int indentCurrent = IndentAmountWithOffset(styler, lineCurrent);
-}
+ while (lineCurrent > 0) {
+ lineCurrent--;
+ importHere = LineContainsImport(lineCurrent, styler);
+ indentCurrent = IndentAmountWithOffset(styler, lineCurrent);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG))
+ break;
+ }
-int EXT_LEXER_DECL GetLexerCount()
-{
- return 1;
-}
+ int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
-void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
-{
- if (buflength > 0) {
- buflength--;
- int n = strlen(LexerName);
- if (n > buflength)
- n = buflength;
- memcpy(name, LexerName, n), name[n] = '\0';
+ if (importHere) {
+ indentCurrentLevel = IndentLevelRemoveIndentOffset(indentCurrentLevel);
+ if (firstImportLine == -1) {
+ firstImportLine = lineCurrent;
+ firstImportIndent = (1 + indentCurrentLevel) - SC_FOLDLEVELBASE;
+ }
+ if (firstImportLine != lineCurrent) {
+ indentCurrentLevel++;
+ }
}
+
+ indentCurrent = indentCurrentLevel | (indentCurrent & ~SC_FOLDLEVELNUMBERMASK);
+
+ // Process all characters to end of requested range
+ //that hangs over the end of the range. Cap processing in all cases
+ // to end of document.
+ while (lineCurrent <= docLines && lineCurrent <= maxLines) {
+
+ // Gather info
+ int lineNext = lineCurrent + 1;
+ importHere = false;
+ int indentNext = indentCurrent;
+
+ if (lineNext <= docLines) {
+ // Information about next line is only available if not at end of document
+ importHere = LineContainsImport(lineNext, styler);
+ indentNext = IndentAmountWithOffset(styler, lineNext);
+ }
+ if (indentNext & SC_FOLDLEVELWHITEFLAG)
+ indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+ // Skip past any blank lines for next indent level info; we skip also
+ // comments (all comments, not just those starting in column 0)
+ // which effectively folds them into surrounding code rather
+ // than screwing up folding.
+
+ while (lineNext < docLines && (indentNext & SC_FOLDLEVELWHITEFLAG)) {
+ lineNext++;
+ importHere = LineContainsImport(lineNext, styler);
+ indentNext = IndentAmountWithOffset(styler, lineNext);
+ }
+
+ int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK;
+
+ if (importHere) {
+ indentNextLevel = IndentLevelRemoveIndentOffset(indentNextLevel);
+ if (firstImportLine == -1) {
+ firstImportLine = lineNext;
+ firstImportIndent = (1 + indentNextLevel) - SC_FOLDLEVELBASE;
+ }
+ if (firstImportLine != lineNext) {
+ indentNextLevel++;
+ }
+ }
+
+ indentNext = indentNextLevel | (indentNext & ~SC_FOLDLEVELNUMBERMASK);
+
+ const int levelBeforeComments = Maximum(indentCurrentLevel,indentNextLevel);
+
+ // Now set all the indent levels on the lines we skipped
+ // Do this from end to start. Once we encounter one line
+ // which is indented more than the line after the end of
+ // the comment-block, use the level of the block before
+
+ int skipLine = lineNext;
+ int skipLevel = indentNextLevel;
+
+ while (--skipLine > lineCurrent) {
+ int skipLineIndent = IndentAmountWithOffset(styler, skipLine);
+
+ if (options.foldCompact) {
+ if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel) {
+ skipLevel = levelBeforeComments;
+ }
+
+ int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+ styler.SetLevel(skipLine, skipLevel | whiteFlag);
+ } else {
+ if ( (skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel
+ && !(skipLineIndent & SC_FOLDLEVELWHITEFLAG)) {
+ skipLevel = levelBeforeComments;
+ }
+
+ styler.SetLevel(skipLine, skipLevel);
+ }
+ }
+
+ int lev = indentCurrent;
+
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+
+ // Set fold level for this line and move to next line
+ styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG);
+
+ indentCurrent = indentNext;
+ indentCurrentLevel = indentNextLevel;
+ lineCurrent = lineNext;
+ }
+
+ // NOTE: Cannot set level of last line here because indentCurrent doesn't have
+ // header flag set; the loop above is crafted to take care of this case!
+ //styler.SetLevel(lineCurrent, indentCurrent);
}
-#endif
-LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");
+LexerModule lmHaskell(SCLEX_HASKELL, LexerHaskell::LexerFactoryHaskell, "haskell", haskellWordListDesc);
+LexerModule lmLiterateHaskell(SCLEX_LITERATEHASKELL, LexerHaskell::LexerFactoryLiterateHaskell, "literatehaskell", haskellWordListDesc);
Modified: scintilla/lexers/LexLaTeX.cxx
6 files changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -224,7 +224,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR);
- } else {
+ } else if (isascii(chNext)) {
styler.ColourTo(i + 1, SCE_L_SHORTCMD);
if (chNext == '(') {
mode = 1;
@@ -340,7 +340,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR);
- } else {
+ } else if (isascii(chNext)) {
if (chNext == ')') {
mode = 0;
state = SCE_L_DEFAULT;
@@ -382,7 +382,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR);
- } else {
+ } else if (isascii(chNext)) {
if (chNext == ']') {
mode = 0;
state = SCE_L_DEFAULT;
Modified: scintilla/lexers/LexOthers.cxx
4 files changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1047,10 +1047,10 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
}
} else if (state == stCtagsStart) {
if ((lineBuffer[i - 1] == '\t') &&
- ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) {
+ ((ch == '/' && chNext == '^') || Is0To9(ch))) {
state = stCtags;
break;
- } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) {
+ } else if ((ch == '/') && (chNext == '^')) {
state = stCtagsStartString;
}
} else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
Modified: scintilla/lexlib/LexerModule.cxx
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -75,7 +75,7 @@ int LexerModule::GetNumWordLists() const {
const char *LexerModule::GetWordListDescription(int index) const {
assert(index < GetNumWordLists());
- if (index >= GetNumWordLists()) {
+ if (!wordListDescriptions || (index >= GetNumWordLists())) {
return "";
} else {
return wordListDescriptions[index];
Modified: scintilla/lexlib/PropSetSimple.cxx
23 files changed, 7 insertions(+), 16 deletions(-)
===================================================================
@@ -141,30 +141,21 @@ static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, i
return maxExpands;
}
-char *PropSetSimple::Expanded(const char *key) const {
+int PropSetSimple::GetExpanded(const char *key, char *result) const {
std::string val = Get(key);
ExpandAllInPlace(*this, val, 100, VarChain(key));
- char *ret = new char [val.size() + 1];
- strcpy(ret, val.c_str());
- return ret;
-}
-
-int PropSetSimple::GetExpanded(const char *key, char *result) const {
- char *val = Expanded(key);
- const int n = static_cast<int>(strlen(val));
+ const int n = static_cast<int>(val.size());
if (result) {
- strcpy(result, val);
+ strcpy(result, val.c_str());
}
- delete []val;
return n; // Not including NUL
}
int PropSetSimple::GetInt(const char *key, int defaultValue) const {
- char *val = Expanded(key);
- if (val) {
- int retVal = val[0] ? atoi(val) : defaultValue;
- delete []val;
- return retVal;
+ std::string val = Get(key);
+ ExpandAllInPlace(*this, val, 100, VarChain(key));
+ if (!val.empty()) {
+ return atoi(val.c_str());
}
return defaultValue;
}
Modified: scintilla/lexlib/PropSetSimple.h
1 files changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -21,7 +21,6 @@ class PropSetSimple {
void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1);
void SetMultiple(const char *);
const char *Get(const char *key) const;
- char *Expanded(const char *key) const;
int GetExpanded(const char *key, char *result) const;
int GetInt(const char *key, int defaultValue=0) const;
};
Modified: scintilla/lexlib/StyleContext.h
4 files changed, 3 insertions(+), 1 deletions(-)
===================================================================
@@ -76,7 +76,7 @@ class StyleContext {
// 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.
- if (lineStartNext < styler.Length())
+ if (currentLine < lineDocEnd)
atLineEnd = static_cast<int>(pos) >= (lineStartNext-1);
else // Last line
atLineEnd = static_cast<int>(pos) >= lineStartNext;
@@ -85,6 +85,7 @@ class StyleContext {
public:
unsigned int currentPos;
int currentLine;
+ int lineDocEnd;
int lineStartNext;
bool atLineStart;
bool atLineEnd;
@@ -112,6 +113,7 @@ class StyleContext {
lengthDocument = static_cast<unsigned int>(styler.Length());
if (endPos == lengthDocument)
endPos++;
+ lineDocEnd = styler.GetLine(lengthDocument);
atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
unsigned int pos = currentPos;
ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));
Modified: scintilla/lexlib/WordList.cxx
51 files changed, 34 insertions(+), 17 deletions(-)
===================================================================
@@ -45,29 +45,37 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa
prev = curr;
}
char **keywords = new char *[words + 1];
- if (keywords) {
- words = 0;
- prev = '\0';
- size_t slen = strlen(wordlist);
- for (size_t k = 0; k < slen; k++) {
- if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
- if (!prev) {
- keywords[words] = &wordlist[k];
- words++;
- }
- } else {
- wordlist[k] = '\0';
+ words = 0;
+ prev = '\0';
+ size_t slen = strlen(wordlist);
+ for (size_t k = 0; k < slen; k++) {
+ if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
+ if (!prev) {
+ keywords[words] = &wordlist[k];
+ words++;
}
- prev = wordlist[k];
+ } else {
+ wordlist[k] = '\0';
}
- keywords[words] = &wordlist[slen];
- *len = words;
- } else {
- *len = 0;
+ prev = wordlist[k];
}
+ keywords[words] = &wordlist[slen];
+ *len = words;
return keywords;
}
+WordList::WordList(bool onlyLineEnds_) :
+ words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
+}
+
+WordList::~WordList() {
+ Clear();
+}
+
+WordList::operator bool() const {
+ return len ? true : false;
+}
+
bool WordList::operator!=(const WordList &other) const {
if (len != other.len)
return true;
@@ -78,6 +86,10 @@ bool WordList::operator!=(const WordList &other) const {
return false;
}
+int WordList::Length() const {
+ return len;
+}
+
void WordList::Clear() {
if (words) {
delete []list;
@@ -217,3 +229,8 @@ bool WordList::InListAbbreviated(const char *s, const char marker) const {
}
return false;
}
+
+const char *WordList::WordAt(int n) const {
+ return words[n];
+}
+
Modified: scintilla/lexlib/WordList.h
12 files changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -15,23 +15,23 @@
/**
*/
class WordList {
-public:
// Each word contains at least one character - a empty word acts as sentinel at the end.
char **words;
char *list;
int len;
bool onlyLineEnds; ///< Delimited by any white space or only line ends
int starts[256];
- WordList(bool onlyLineEnds_ = false) :
- words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_)
- {}
- ~WordList() { Clear(); }
- operator bool() const { return len ? true : false; }
+public:
+ WordList(bool onlyLineEnds_ = false);
+ ~WordList();
+ operator bool() const;
bool operator!=(const WordList &other) const;
+ int Length() const;
void Clear();
void Set(const char *s);
bool InList(const char *s) const;
bool InListAbbreviated(const char *s, const char marker) const;
+ const char *WordAt(int n) const;
};
#ifdef SCI_NAMESPACE
Modified: scintilla/scintilla_changes.patch
3 files changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -31,7 +31,7 @@ diff --git b/scintilla/src/Catalogue.cxx a/scintilla/src/Catalogue.cxx
index 2f75247..a34f834 100644
+++ scintilla/src/Catalogue.cxx
--- scintilla/src/Catalogue.cxx
-@@ -81,108 +81,45 @@ int Scintilla_LinkLexers() {
+@@ -81,109 +81,45 @@ int Scintilla_LinkLexers() {
//++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
@@ -82,6 +82,7 @@ index 2f75247..a34f834 100644
- LINK_LEXER(lmKix);
LINK_LEXER(lmLatex);
LINK_LEXER(lmLISP);
+- LINK_LEXER(lmLiterateHaskell);
- LINK_LEXER(lmLot);
- LINK_LEXER(lmLout);
LINK_LEXER(lmLua);
Modified: scintilla/src/CallTip.cxx
22 files changed, 9 insertions(+), 13 deletions(-)
===================================================================
@@ -7,12 +7,14 @@
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
+
+#include <string>
#include "Platform.h"
#include "Scintilla.h"
#include "CallTip.h"
-#include <stdio.h>
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -22,7 +24,6 @@
wCallTip = 0;
inCallTipMode = false;
posStartCallTip = 0;
- val = 0;
rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0);
lineHeight = 1;
@@ -56,8 +57,6 @@
CallTip::~CallTip() {
font.Release();
wCallTip.Destroy();
- delete []val;
- val = 0;
}
// Although this test includes 0, we should never see a \0 character.
@@ -176,17 +175,17 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
// Draw the definition in three parts: before highlight, highlighted, after highlight
int ytext = rcClient.top + ascent + 1;
rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
- char *chunkVal = val;
+ const char *chunkVal = val.c_str();
bool moreChunks = true;
int maxWidth = 0;
while (moreChunks) {
- char *chunkEnd = strchr(chunkVal, '\n');
+ const char *chunkEnd = strchr(chunkVal, '\n');
if (chunkEnd == NULL) {
chunkEnd = chunkVal + strlen(chunkVal);
moreChunks = false;
}
- int chunkOffset = chunkVal - val;
+ int chunkOffset = chunkVal - val.c_str();
int chunkLength = chunkEnd - chunkVal;
int chunkEndOffset = chunkOffset + chunkLength;
int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
@@ -215,7 +214,7 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
}
void CallTip::PaintCT(Surface *surfaceWindow) {
- if (!val)
+ if (val.empty())
return;
PRectangle rcClientPos = wCallTip.GetClientPosition();
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
@@ -253,10 +252,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *
int codePage_, int characterSet,
int technology, Window &wParent) {
clickPlace = 0;
- delete []val;
- val = 0;
- val = new char[strlen(defn) + 1];
- strcpy(val, defn);
+ val = defn;
codePage = codePage_;
Surface *surfaceMeasure = Surface::Allocate(technology);
if (!surfaceMeasure)
@@ -275,7 +271,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *
// Only support \n here - simply means container must avoid \r!
int numLines = 1;
const char *newline;
- const char *look = val;
+ const char *look = val.c_str();
rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0);
offsetMain = insetX; // changed to right edge of any arrows
Modified: scintilla/src/CallTip.h
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -17,7 +17,7 @@
class CallTip {
int startHighlight; // character offset to start and...
int endHighlight; // ...end of highlighted text
- char *val;
+ std::string val;
Font font;
PRectangle rectUp; // rectangle of last up angle in the tip
PRectangle rectDown; // rectangle of last down arrow in the tip
Modified: scintilla/src/CellBuffer.cxx
24 files changed, 12 insertions(+), 12 deletions(-)
===================================================================
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <stdarg.h>
+#include <algorithm>
+
#include "Platform.h"
#include "Scintilla.h"
@@ -81,11 +83,15 @@ int LineVector::LineFromPosition(int pos) const {
Destroy();
}
-void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) {
+void Action::Create(actionType at_, int position_, const char *data_, int lenData_, bool mayCoalesce_) {
delete []data;
+ data = NULL;
position = position_;
at = at_;
- data = data_;
+ if (lenData_) {
+ data = new char[lenData_];
+ memcpy(data, data_, lenData_);
+ }
lenData = lenData_;
mayCoalesce = mayCoalesce_;
}
@@ -162,7 +168,7 @@ void UndoHistory::EnsureUndoRoom() {
}
}
-void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData,
+void UndoHistory::AppendAction(actionType at, int position, const char *data, int lengthData,
bool &startSequence, bool mayCoalesce) {
EnsureUndoRoom();
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
@@ -393,11 +399,7 @@ const char *CellBuffer::InsertString(int position, const char *s, int insertLeng
if (collectingUndo) {
// Save into the undo/redo stack, but only the characters - not the formatting
// This takes up about half load time
- data = new char[insertLength];
- for (int i = 0; i < insertLength; i++) {
- data[i] = s[i];
- }
- uh.AppendAction(insertAction, position, data, insertLength, startSequence);
+ uh.AppendAction(insertAction, position, s, insertLength, startSequence);
}
BasicInsertString(position, s, insertLength);
@@ -439,10 +441,8 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startS
if (!readOnly) {
if (collectingUndo) {
// Save into the undo/redo stack, but only the characters - not the formatting
- data = new char[deleteLength];
- for (int i = 0; i < deleteLength; i++) {
- data[i] = substance.ValueAt(position + i);
- }
+ // The gap would be moved to position anyway for the deletion so this doesn't cost extra
+ const char *data = substance.RangePointer(position, deleteLength);
uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
}
Modified: scintilla/src/CellBuffer.h
4 files changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -80,7 +80,7 @@ class Action {
Action();
~Action();
- void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true);
+ void Create(actionType at_, int position_=0, const char *data_=0, int lenData_=0, bool mayCoalesce_=true);
void Destroy();
void Grab(Action *source);
};
@@ -105,7 +105,7 @@ class UndoHistory {
UndoHistory();
~UndoHistory();
- void AppendAction(actionType at, int position, char *data, int length, bool &startSequence, bool mayCoalesce=true);
+ void AppendAction(actionType at, int position, const char *data, int length, bool &startSequence, bool mayCoalesce=true);
void BeginUndoAction();
void EndUndoAction();
Modified: scintilla/src/ContractionState.cxx
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -7,6 +7,8 @@
#include <string.h>
+#include <algorithm>
+
#include "Platform.h"
#include "SplitVector.h"
Modified: scintilla/src/Decoration.cxx
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -9,6 +9,8 @@
#include <stdlib.h>
#include <stdarg.h>
+#include <algorithm>
+
#include "Platform.h"
#include "Scintilla.h"
Modified: scintilla/src/Document.cxx
228 files changed, 66 insertions(+), 162 deletions(-)
===================================================================
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include <algorithm>
#include "Platform.h"
@@ -102,8 +103,6 @@ int LexInterface::LineEndTypesSupported() {
useTabs = true;
tabIndents = true;
backspaceUnindents = false;
- watchers = 0;
- lenWatchers = 0;
matchesValid = false;
regex = 0;
@@ -122,16 +121,13 @@ int LexInterface::LineEndTypesSupported() {
}
Document::~Document() {
- for (int i = 0; i < lenWatchers; i++) {
- watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
+ for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
+ it->watcher->NotifyDeleted(this, it->userData);
}
- delete []watchers;
for (int j=0; j<ldSize; j++) {
delete perLineData[j];
perLineData[j] = 0;
}
- watchers = 0;
- lenWatchers = 0;
delete regex;
regex = 0;
delete pli;
@@ -309,9 +305,9 @@ int SCI_METHOD Document::LineEnd(int line) const {
}
void SCI_METHOD Document::SetErrorStatus(int status) {
- // Tell the watchers the lexer has changed.
- for (int i = 0; i < lenWatchers; i++) {
- watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status);
+ // Tell the watchers an error has occurred.
+ for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
+ it->watcher->NotifyErrorOccurred(this, it->userData, status);
}
}
@@ -420,7 +416,7 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
int lookLine = line;
int lookLineLevel = level;
int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
- while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) ||
+ while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) ||
((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) {
lookLineLevel = GetLevel(--lookLine);
lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
@@ -453,8 +449,8 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
}
}
if (firstChangeableLineBefore == -1) {
- for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
- lookLine >= beginFoldBlock;
+ for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
+ lookLine >= beginFoldBlock;
lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) {
firstChangeableLineBefore = lookLine;
@@ -466,8 +462,8 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
firstChangeableLineBefore = beginFoldBlock - 1;
int firstChangeableLineAfter = -1;
- for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
- lookLine <= endFoldBlock;
+ for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
+ lookLine <= endFoldBlock;
lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) {
firstChangeableLineAfter = lookLine;
@@ -715,7 +711,7 @@ bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const {
// Shift_jis
return ((uch >= 0x81) && (uch <= 0x9F)) ||
((uch >= 0xE0) && (uch <= 0xFC));
- // Lead bytes F0 to FC may be a Microsoft addition.
+ // Lead bytes F0 to FC may be a Microsoft addition.
case 936:
// GBK
return (uch >= 0x81) && (uch <= 0xFE);
@@ -892,7 +888,7 @@ void * SCI_METHOD Document::ConvertToDocument() {
int Document::Undo() {
int newPos = -1;
CheckReadOnly();
- if (enteredModification == 0) {
+ if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++;
if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint();
@@ -977,7 +973,7 @@ int Document::Undo() {
int Document::Redo() {
int newPos = -1;
CheckReadOnly();
- if (enteredModification == 0) {
+ if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++;
if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint();
@@ -1050,11 +1046,6 @@ bool Document::InsertCString(int position, const char *s) {
return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0));
}
-void Document::ChangeChar(int pos, char ch) {
- DeleteChars(pos, 1);
- InsertChar(pos, ch);
-}
-
void Document::DelChar(int pos) {@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list