From c0b726a298d17a8fedf1c6c91f79272cfd3e79c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrico=20Tr=C3=B6ger?= Date: Sun, 3 Apr 2011 16:16:52 +0000 Subject: [PATCH] Update Scintilla to version 2.25. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5682 ea778897-0a13-0410-b9d1-a72fbfd435f5 --- ChangeLog | 6 + scintilla/Makefile.am | 1 + scintilla/gtk/PlatGTK.cxx | 309 ++++++++++++++++-- scintilla/gtk/ScintillaGTK.cxx | 11 +- scintilla/gtk/scintilla-marshal.c | 8 +- scintilla/include/Platform.h | 8 +- scintilla/include/SciLexer.h | 42 +++ scintilla/include/Scintilla.h | 9 + scintilla/include/Scintilla.iface | 60 ++++ scintilla/lexers/LexAda.cxx | 1 - scintilla/lexers/LexAsm.cxx | 326 +++++++++++++++++-- scintilla/lexers/LexBash.cxx | 9 +- scintilla/lexers/LexCOBOL.cxx | 1 - scintilla/lexers/LexCPP.cxx | 123 +++++-- scintilla/lexers/LexCSS.cxx | 1 - scintilla/lexers/LexCmake.cxx | 1 - scintilla/lexers/LexD.cxx | 275 +++++++++++++--- scintilla/lexers/LexErlang.cxx | 1 - scintilla/lexers/LexForth.cxx | 1 - scintilla/lexers/LexFortran.cxx | 3 +- scintilla/lexers/LexHTML.cxx | 15 +- scintilla/lexers/LexLisp.cxx | 1 - scintilla/lexers/LexLua.cxx | 1 - scintilla/lexers/LexMarkdown.cxx | 1 - scintilla/lexers/LexMatlab.cxx | 1 - scintilla/lexers/LexNsis.cxx | 1 - scintilla/lexers/LexOthers.cxx | 7 +- scintilla/lexers/LexPascal.cxx | 1 - scintilla/lexers/LexPerl.cxx | 1 - scintilla/lexers/LexPython.cxx | 1 - scintilla/lexers/LexR.cxx | 1 - scintilla/lexers/LexSQL.cxx | 516 +++++++++++++++++++++++++----- scintilla/lexers/LexTCL.cxx | 1 - scintilla/lexers/LexTxt2tags.cxx | 1 - scintilla/lexers/LexVHDL.cxx | 1 - scintilla/lexers/LexVerilog.cxx | 1 - scintilla/lexers/LexYAML.cxx | 1 - scintilla/lexlib/CharacterSet.h | 4 +- scintilla/lexlib/LexerBase.h | 2 +- scintilla/lexlib/OptionSet.h | 2 + scintilla/lexlib/SparseState.h | 110 +++++++ scintilla/lexlib/WordList.cxx | 5 + scintilla/scintilla_changes.patch | 16 +- scintilla/src/AutoComplete.cxx | 2 +- scintilla/src/CallTip.cxx | 3 + scintilla/src/Document.cxx | 22 +- scintilla/src/Document.h | 2 +- scintilla/src/Editor.cxx | 173 +++++++--- scintilla/src/Editor.h | 10 +- scintilla/src/ExternalLexer.cxx | 1 - scintilla/src/ExternalLexer.h | 5 +- scintilla/src/Partitioning.h | 5 + scintilla/src/PositionCache.cxx | 2 + scintilla/src/RunStyles.cxx | 4 +- scintilla/src/Selection.cxx | 9 + scintilla/src/Selection.h | 5 +- scintilla/src/SplitVector.h | 2 +- scintilla/src/ViewStyle.cxx | 2 +- scintilla/src/ViewStyle.h | 1 + 59 files changed, 1816 insertions(+), 319 deletions(-) create mode 100644 scintilla/lexlib/SparseState.h diff --git a/ChangeLog b/ChangeLog index e7583697..d382fb71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-04-03 Enrico Tröger + + * scintilla/*: + Update Scintilla to version 2.25. + + 2011-04-03 Colomban Wendling * src/main.c, src/prefs.c, src/tools.c: diff --git a/scintilla/Makefile.am b/scintilla/Makefile.am index 4a92eb6a..92cca013 100644 --- a/scintilla/Makefile.am +++ b/scintilla/Makefile.am @@ -61,6 +61,7 @@ lexlib/LexerSimple.h \ lexlib/OptionSet.h \ lexlib/PropSetSimple.cxx \ lexlib/PropSetSimple.h \ +lexlib/SparseState.h \ lexlib/StyleContext.cxx \ lexlib/StyleContext.h \ lexlib/WordList.cxx \ diff --git a/scintilla/gtk/PlatGTK.cxx b/scintilla/gtk/PlatGTK.cxx index bcc965a6..651805e6 100644 --- a/scintilla/gtk/PlatGTK.cxx +++ b/scintilla/gtk/PlatGTK.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,14 @@ #define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w)) #endif +#if GTK_CHECK_VERSION(2,22,0) +#define USE_CAIRO 1 +#endif + +#ifdef USE_CAIRO +#define DISABLE_GDK_FONT 1 +#endif + #ifdef _MSC_VER // Ignore unreferenced local functions in GTK+ headers #pragma warning(disable: 4505) @@ -688,9 +697,14 @@ namespace Scintilla { #endif class SurfaceImpl : public Surface { encodingType et; +#ifdef USE_CAIRO + cairo_t *context; + cairo_surface_t *psurf; +#else GdkDrawable *drawable; GdkGC *gc; GdkPixmap *ppixmap; +#endif int x; int y; bool inited; @@ -806,7 +820,15 @@ void SurfaceImpl::SetConverter(int characterSet_) { } } -SurfaceImpl::SurfaceImpl() : et(singleByte), drawable(0), gc(0), ppixmap(0), +SurfaceImpl::SurfaceImpl() : et(singleByte), +#ifdef USE_CAIRO +context(0), +psurf(0), +#else +drawable(0), +gc(0), +ppixmap(0), +#endif x(0), y(0), inited(false), createdGC(false) , pcontext(0), layout(0), characterSet(-1) { } @@ -817,15 +839,28 @@ SurfaceImpl::~SurfaceImpl() { void SurfaceImpl::Release() { et = singleByte; +#ifndef USE_CAIRO drawable = 0; +#endif if (createdGC) { createdGC = false; +#ifdef USE_CAIRO + cairo_destroy(context); +#else g_object_unref(gc); +#endif } +#ifdef USE_CAIRO + context = 0; + if (psurf) + cairo_surface_destroy(psurf); + psurf = 0; +#else gc = 0; if (ppixmap) g_object_unref(ppixmap); ppixmap = 0; +#endif if (layout) g_object_unref(layout); layout = 0; @@ -847,10 +882,28 @@ bool SurfaceImpl::Initialised() { void SurfaceImpl::Init(WindowID wid) { Release(); PLATFORM_ASSERT(wid); +#ifdef USE_CAIRO + GdkDrawable *drawable_ = GDK_DRAWABLE(PWidget(wid)->window); + if (drawable_) { + context = gdk_cairo_create(drawable_); + PLATFORM_ASSERT(context); + } else { + // Shouldn't happen with valid window but may when calls made before + // window completely allocated and mapped. + psurf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1); + context = cairo_create(psurf); + } + createdGC = true; + pcontext = pango_cairo_create_context(context); + PLATFORM_ASSERT(pcontext); + layout = pango_cairo_create_layout(context); + PLATFORM_ASSERT(layout); +#else pcontext = gtk_widget_create_pango_context(PWidget(wid)); PLATFORM_ASSERT(pcontext); layout = pango_layout_new(pcontext); PLATFORM_ASSERT(layout); +#endif inited = true; } @@ -859,12 +912,27 @@ void SurfaceImpl::Init(SurfaceID sid, WindowID wid) { GdkDrawable *drawable_ = reinterpret_cast(sid); Release(); PLATFORM_ASSERT(wid); +#ifdef USE_CAIRO + context = gdk_cairo_create(drawable_); +#else + gc = gdk_gc_new(drawable_); +#endif +#ifdef USE_CAIRO + pcontext = pango_cairo_create_context(context); + PLATFORM_ASSERT(pcontext); + layout = pango_cairo_create_layout(context); + PLATFORM_ASSERT(layout); +#else pcontext = gtk_widget_create_pango_context(PWidget(wid)); layout = pango_layout_new(pcontext); drawable = drawable_; - gc = gdk_gc_new(drawable_); +#endif +#ifdef USE_CAIRO + cairo_set_line_width(context, 1); +#else // Ask for lines that do not paint the last pixel so is like Win32 gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); +#endif createdGC = true; inited = true; } @@ -873,8 +941,23 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID PLATFORM_ASSERT(surface_); Release(); SurfaceImpl *surfImpl = static_cast(surface_); - PLATFORM_ASSERT(surfImpl->drawable); PLATFORM_ASSERT(wid); +#ifdef USE_CAIRO + context = cairo_reference(surfImpl->context); +#else + PLATFORM_ASSERT(surfImpl->drawable); + gc = gdk_gc_new(surfImpl->drawable); +#endif +#ifdef USE_CAIRO + pcontext = pango_cairo_create_context(context); + PLATFORM_ASSERT(pcontext); + layout = pango_cairo_create_layout(context); + PLATFORM_ASSERT(layout); + if (height > 0 && width > 0) + psurf = gdk_window_create_similar_surface( + gtk_widget_get_window(PWidget(wid)), + CAIRO_CONTENT_COLOR_ALPHA, width, height); +#else pcontext = gtk_widget_create_pango_context(PWidget(wid)); PLATFORM_ASSERT(pcontext); layout = pango_layout_new(pcontext); @@ -882,19 +965,42 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID if (height > 0 && width > 0) ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1); drawable = ppixmap; - gc = gdk_gc_new(surfImpl->drawable); +#endif +#ifdef USE_CAIRO + cairo_destroy(context); + context = cairo_create(psurf); + cairo_rectangle(context, 0, 0, width, height); + cairo_set_source_rgb(context, 1.0, 0, 0); + cairo_fill(context); + // This produces sharp drawing more similar to GDK: + //cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE); +#endif +#ifdef USE_CAIRO + cairo_set_line_width(context, 1); +#else // Ask for lines that do not paint the last pixel so is like Win32 gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); +#endif createdGC = true; inited = true; } void SurfaceImpl::PenColour(ColourAllocated fore) { +#ifdef USE_CAIRO + if (context) { + ColourDesired cdFore(fore.AsLong()); + cairo_set_source_rgb(context, + cdFore.GetBlue() / 255.0, + cdFore.GetGreen() / 255.0, + cdFore.GetRed() / 255.0); + } +#else if (gc) { GdkColor co; co.pixel = fore.AsLong(); gdk_gc_set_foreground(gc, &co); } +#endif } int SurfaceImpl::LogPixelsY() { @@ -911,18 +1017,71 @@ void SurfaceImpl::MoveTo(int x_, int y_) { y = y_; } +#ifdef USE_CAIRO +static int Delta(int difference) { + if (difference < 0) + return -1; + else if (difference > 0) + return 1; + else + return 0; +} +#endif + void SurfaceImpl::LineTo(int x_, int y_) { +#ifdef USE_CAIRO + // cairo_line_to draws the end position, unlike Win32 or GDK with GDK_CAP_NOT_LAST. + // For simple cases, move back one pixel from end. + if (context) { + int xDiff = x_ - x; + int xDelta = Delta(xDiff); + int yDiff = y_ - y; + int yDelta = Delta(yDiff); + if ((xDiff == 0) || (yDiff == 0)) { + // Horizontal or vertical lines can be more precisely drawn as a filled rectangle + int xEnd = x_ - xDelta; + int left = Platform::Minimum(x, xEnd); + int width = abs(x - xEnd) + 1; + int yEnd = y_ - yDelta; + int top = Platform::Minimum(y, yEnd); + int height = abs(y - yEnd) + 1; + cairo_rectangle(context, left, top, width, height); + cairo_fill(context); + } else if ((abs(xDiff) == abs(yDiff))) { + // 45 degree slope + cairo_move_to(context, x + 0.5, y + 0.5); + cairo_line_to(context, x_ + 0.5 - xDelta, y_ + 0.5 - yDelta); + } else { + // Line has a different slope so difficult to avoid last pixel + cairo_move_to(context, x + 0.5, y + 0.5); + cairo_line_to(context, x_ + 0.5, y_ + 0.5); + } + cairo_stroke(context); + } +#else if (drawable && gc) { gdk_draw_line(drawable, gc, x, y, x_, y_); } +#endif x = x_; y = y_; } void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { +#ifdef USE_CAIRO + PenColour(back); + cairo_move_to(context, pts[0].x + 0.5, pts[0].y + 0.5); + for (int i = 1;i < npts;i++) { + cairo_line_to(context, pts[i].x + 0.5, pts[i].y + 0.5); + } + cairo_close_path(context); + cairo_fill_preserve(context); + PenColour(fore); + cairo_stroke(context); +#else GdkPoint gpts[20]; if (npts < static_cast((sizeof(gpts) / sizeof(gpts[0])))) { for (int i = 0;i < npts;i++) { @@ -934,35 +1093,62 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, PenColour(fore); gdk_draw_polygon(drawable, gc, 0, gpts, npts); } +#endif } void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { +#ifdef USE_CAIRO + if (context) { +#else if (gc && drawable) { +#endif +#ifdef USE_CAIRO + cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, + rc.right - rc.left - 1, rc.bottom - rc.top - 1); + PenColour(back); + cairo_fill_preserve(context); + PenColour(fore); + cairo_stroke(context); +#else PenColour(back); gdk_draw_rectangle(drawable, gc, 1, rc.left + 1, rc.top + 1, rc.right - rc.left - 2, rc.bottom - rc.top - 2); - PenColour(fore); // The subtraction of 1 off the width and height here shouldn't be needed but // otherwise a different rectangle is drawn than would be done if the fill parameter == 1 gdk_draw_rectangle(drawable, gc, 0, rc.left, rc.top, rc.right - rc.left - 1, rc.bottom - rc.top - 1); +#endif } } void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { PenColour(back); +#ifdef USE_CAIRO + if (context && (rc.left < maxCoordinate)) { // Protect against out of range + cairo_rectangle(context, rc.left, rc.top, + rc.right - rc.left, rc.bottom - rc.top); + cairo_fill(context); + } +#else if (drawable && (rc.left < maxCoordinate)) { // Protect against out of range gdk_draw_rectangle(drawable, gc, 1, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); } +#endif } void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { - if (static_cast(surfacePattern).drawable) { + SurfaceImpl &surfi = static_cast(surfacePattern); +#ifdef USE_CAIRO + bool canDraw = surfi.psurf; +#else + bool canDraw = surfi.drawable; +#endif + if (canDraw) { // Tile pattern over rectangle // Currently assumes 8x8 pattern int widthPat = 8; @@ -971,12 +1157,18 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat; for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) { int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat; +#ifdef USE_CAIRO + cairo_set_source_surface(context, surfi.psurf, xTile, yTile); + cairo_rectangle(context, xTile, yTile, widthx, heighty); + cairo_fill(context); +#else gdk_draw_drawable(drawable, gc, static_cast(surfacePattern).drawable, 0, 0, xTile, yTile, widthx, heighty); +#endif } } } else { @@ -1005,6 +1197,21 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl } } +#ifdef USE_CAIRO + +static void PathRoundRectangle(cairo_t *context, double left, double top, double width, double height, int radius) { + double degrees = M_PI / 180.0; + + cairo_new_sub_path(context); + cairo_arc(context, left + width - radius, top + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc(context, left + width - radius, top + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_arc(context, left + radius, top + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc(context, left + radius, top + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path(context); +} + +#else + // Plot a point into a guint32 buffer symetrically to all 4 qudrants static void AllFour(guint32 *pixels, int stride, int width, int height, int x, int y, guint32 val) { pixels[y*stride+x] = val; @@ -1013,18 +1220,6 @@ static void AllFour(guint32 *pixels, int stride, int width, int height, int x, i pixels[(height-1-y)*stride+width-1-x] = val; } -static unsigned int GetRValue(unsigned int co) { - return (co >> 16) & 0xff; -} - -static unsigned int GetGValue(unsigned int co) { - return (co >> 8) & 0xff; -} - -static unsigned int GetBValue(unsigned int co) { - return co & 0xff; -} - static guint32 u32FromRGBA(guint8 r, guint8 g, guint8 b, guint8 a) { union { guint8 pixVal[4]; @@ -1037,8 +1232,41 @@ static guint32 u32FromRGBA(guint8 r, guint8 g, guint8 b, guint8 a) { return converter.val; } +#endif + +static unsigned int GetRValue(unsigned int co) { + return (co >> 16) & 0xff; +} + +static unsigned int GetGValue(unsigned int co) { + return (co >> 8) & 0xff; +} + +static unsigned int GetBValue(unsigned int co) { + return co & 0xff; +} + void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, ColourAllocated outline, int alphaOutline, int flags) { +#ifdef USE_CAIRO + if (context && rc.Width() > 0) { + cairo_set_source_rgba(context, + GetRValue(fill.AsLong()) / 255.0, + GetGValue(fill.AsLong()) / 255.0, + GetBValue(fill.AsLong()) / 255.0, + alphaFill / 255.0); + PathRoundRectangle(context, rc.left + 1.0, rc.top+1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0, cornerSize); + cairo_fill(context); + + cairo_set_source_rgba(context, + GetRValue(outline.AsLong()) / 255.0, + GetGValue(outline.AsLong()) / 255.0, + GetBValue(outline.AsLong()) / 255.0, + alphaOutline / 255.0); + PathRoundRectangle(context, rc.left +0.5, rc.top+0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1, cornerSize); + cairo_stroke(context); + } +#else if (gc && drawable && rc.Width() > 0) { int width = rc.Width(); int height = rc.Height(); @@ -1078,10 +1306,18 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated g_object_unref(pixalpha); } +#endif } void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(back); +#ifdef USE_CAIRO + cairo_arc(context, (rc.left + rc.right) / 2 + 0.5, (rc.top + rc.bottom) / 2 + 0.5, + Platform::Minimum(rc.Width(), rc.Height()) / 2, 0, 2*M_PI); + cairo_fill_preserve(context); + PenColour(fore); + cairo_stroke(context); +#else gdk_draw_arc(drawable, gc, 1, rc.left + 1, rc.top + 1, rc.right - rc.left - 2, rc.bottom - rc.top - 2, @@ -1093,16 +1329,30 @@ void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated b rc.left, rc.top, rc.right - rc.left - 1, rc.bottom - rc.top - 1, 0, 32767); +#endif } void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { - if (static_cast(surfaceSource).drawable) { + SurfaceImpl &surfi = static_cast(surfaceSource); +#ifdef USE_CAIRO + bool canDraw = surfi.psurf; +#else + bool canDraw = surfi.drawable; +#endif + if (canDraw) { +#ifdef USE_CAIRO + cairo_set_source_surface(context, surfi.psurf, + rc.left - from.x, rc.top - from.y); + cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + cairo_fill(context); +#else gdk_draw_drawable(drawable, gc, static_cast(surfaceSource).drawable, from.x, from.y, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); +#endif } } @@ -1232,7 +1482,11 @@ const int maxLengthTextRun = 10000; void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) { PenColour(fore); +#ifdef USE_CAIRO + if (context) { +#else if (gc && drawable) { +#endif int xText = rc.left; if (PFont(font_)->pfd) { char *utfForm = 0; @@ -1256,12 +1510,20 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char pango_layout_set_text(layout, utfForm, len); } pango_layout_set_font_description(layout, PFont(font_)->pfd); +#ifdef USE_CAIRO + pango_cairo_update_layout(context, layout); +#endif #ifdef PANGO_VERSION PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0); #else PangoLayoutLine *pll = pango_layout_get_line(layout,0); #endif +#ifdef USE_CAIRO + cairo_move_to(context, xText, ybase); + pango_cairo_show_layout_line(context, pll); +#else gdk_draw_layout_line(drawable, gc, xText, ybase, pll); +#endif if (useGFree) { g_free(utfForm); } else { @@ -1717,9 +1979,14 @@ int SurfaceImpl::SetPalette(Palette *, bool) { } void SurfaceImpl::SetClip(PRectangle rc) { +#ifdef USE_CAIRO + cairo_rectangle(context, rc.left, rc.top, rc.right, rc.bottom); + cairo_clip(context); +#else GdkRectangle area = {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top}; gdk_gc_set_clip_rectangle(gc, &area); +#endif } void SurfaceImpl::FlushCachedState() {} @@ -1875,7 +2142,6 @@ void Window::SetTitle(const char *s) { gdk window coordinates */ PRectangle Window::GetMonitorRect(Point pt) { gint x_offset, y_offset; - pt = pt; gdk_window_get_origin(PWidget(wid)->window, &x_offset, &y_offset); @@ -1894,6 +2160,7 @@ PRectangle Window::GetMonitorRect(Point pt) { return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); } #else + pt = pt; return PRectangle(-x_offset, -y_offset, (-x_offset) + gdk_screen_width(), (-y_offset) + gdk_screen_height()); #endif @@ -1936,7 +2203,7 @@ public: CallBackAction doubleClickAction; void *doubleClickActionData; - ListBoxX() : list(0), pixhash(NULL), pixbuf_renderer(0), + ListBoxX() : list(0), scroller(0), pixhash(NULL), pixbuf_renderer(0), desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) { } diff --git a/scintilla/gtk/ScintillaGTK.cxx b/scintilla/gtk/ScintillaGTK.cxx index c2884886..873bc4c6 100644 --- a/scintilla/gtk/ScintillaGTK.cxx +++ b/scintilla/gtk/ScintillaGTK.cxx @@ -75,6 +75,10 @@ #define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w)) #endif +#if GTK_CHECK_VERSION(2,22,0) +#define USE_CAIRO 1 +#endif + #ifdef _MSC_VER // Constant conditional expressions are because of GTK+ headers #pragma warning(disable: 4127) @@ -531,7 +535,6 @@ void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internal gint ScintillaGTK::FocusInThis(GtkWidget *widget) { try { - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); SetFocusState(true); if (im_context != NULL) { gchar *str = NULL; @@ -562,7 +565,6 @@ gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) { gint ScintillaGTK::FocusOutThis(GtkWidget *widget) { try { - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); SetFocusState(false); if (PWidget(wPreedit) != NULL) @@ -1422,7 +1424,7 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) { UndoGroup ug(pdoc); if (selection_data->selection != GDK_SELECTION_PRIMARY) { - ClearSelection(); + ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH); } SelectionPosition selStart = sel.IsRectangular() ? sel.Rectangular().Start() : @@ -1983,6 +1985,7 @@ gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); pango_layout_set_attributes(layout, attrs); +#ifndef USE_CAIRO GdkGC *gc = gdk_gc_new(widget->window); GdkColor color[2] = { {0, 0x0000, 0x0000, 0x0000}, {0, 0xffff, 0xffff, 0xffff} @@ -1997,8 +2000,8 @@ gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) gdk_gc_set_foreground(gc, color); gdk_gc_set_background(gc, color + 1); gdk_draw_layout(widget->window, gc, 0, 0, layout); - g_object_unref(gc); +#endif g_free(str); pango_attr_list_unref(attrs); g_object_unref(layout); diff --git a/scintilla/gtk/scintilla-marshal.c b/scintilla/gtk/scintilla-marshal.c index be57b7c2..cee3e731 100644 --- a/scintilla/gtk/scintilla-marshal.c +++ b/scintilla/gtk/scintilla-marshal.c @@ -35,8 +35,8 @@ #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 #define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_int -#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong #define g_marshal_value_peek_float(v) (v)->data[0].v_float #define g_marshal_value_peek_double(v) (v)->data[0].v_double #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer @@ -50,10 +50,10 @@ /* NONE:INT,POINTER (scintilla-marshal.list:1) */ void scintilla_marshal_VOID__INT_POINTER (GClosure *closure, - GValue *return_value, + GValue *return_value G_GNUC_UNUSED, guint n_param_values, const GValue *param_values, - gpointer invocation_hint, + gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) { typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, diff --git a/scintilla/include/Platform.h b/scintilla/include/Platform.h index ea9f9729..b70ffc3c 100644 --- a/scintilla/include/Platform.h +++ b/scintilla/include/Platform.h @@ -255,8 +255,8 @@ class Palette { int allocatedLen; #endif // Private so Palette objects can not be copied - Palette(const Palette &) {} - Palette &operator=(const Palette &) { return *this; } + Palette(const Palette &); + Palette &operator=(const Palette &); public: #if PLAT_WIN void *hpal; @@ -288,8 +288,8 @@ protected: int ascent; #endif // Private so Font objects can not be copied - Font(const Font &) {} - Font &operator=(const Font &) { fid=0; return *this; } + Font(const Font &); + Font &operator=(const Font &); public: Font(); virtual ~Font(); diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index 3aa2c385..1d5b69ed 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.h @@ -112,6 +112,8 @@ #define SCLEX_SML 97 #define SCLEX_MARKDOWN 98 #define SCLEX_TXT2TAGS 99 +#define SCLEX_A68K 100 +#define SCLEX_MODULA 101 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -149,6 +151,8 @@ #define SCE_C_COMMENTDOCKEYWORD 17 #define SCE_C_COMMENTDOCKEYWORDERROR 18 #define SCE_C_GLOBALCLASS 19 +#define SCE_C_STRINGRAW 20 +#define SCE_C_TRIPLEVERBATIM 21 #define SCE_D_DEFAULT 0 #define SCE_D_COMMENT 1 #define SCE_D_COMMENTLINE 2 @@ -601,6 +605,7 @@ #define SCE_ASM_CHARACTER 12 #define SCE_ASM_STRINGEOL 13 #define SCE_ASM_EXTINSTRUCTION 14 +#define SCE_ASM_COMMENTDIRECTIVE 15 #define SCE_F_DEFAULT 0 #define SCE_F_COMMENT 1 #define SCE_F_NUMBER 2 @@ -1415,6 +1420,43 @@ #define SCE_TXT2TAGS_OPTION 23 #define SCE_TXT2TAGS_PREPROC 24 #define SCE_TXT2TAGS_POSTPROC 25 +#define SCE_A68K_DEFAULT 0 +#define SCE_A68K_COMMENT 1 +#define SCE_A68K_NUMBER_DEC 2 +#define SCE_A68K_NUMBER_BIN 3 +#define SCE_A68K_NUMBER_HEX 4 +#define SCE_A68K_STRING1 5 +#define SCE_A68K_OPERATOR 6 +#define SCE_A68K_CPUINSTRUCTION 7 +#define SCE_A68K_EXTINSTRUCTION 8 +#define SCE_A68K_REGISTER 9 +#define SCE_A68K_DIRECTIVE 10 +#define SCE_A68K_MACRO_ARG 11 +#define SCE_A68K_LABEL 12 +#define SCE_A68K_STRING2 13 +#define SCE_A68K_IDENTIFIER 14 +#define SCE_A68K_MACRO_DECLARATION 15 +#define SCE_A68K_COMMENT_WORD 16 +#define SCE_A68K_COMMENT_SPECIAL 17 +#define SCE_A68K_COMMENT_DOXYGEN 18 +#define SCE_MODULA_DEFAULT 0 +#define SCE_MODULA_COMMENT 1 +#define SCE_MODULA_DOXYCOMM 2 +#define SCE_MODULA_DOXYKEY 3 +#define SCE_MODULA_KEYWORD 4 +#define SCE_MODULA_RESERVED 5 +#define SCE_MODULA_NUMBER 6 +#define SCE_MODULA_BASENUM 7 +#define SCE_MODULA_FLOAT 8 +#define SCE_MODULA_STRING 9 +#define SCE_MODULA_STRSPEC 10 +#define SCE_MODULA_CHAR 11 +#define SCE_MODULA_CHARSPEC 12 +#define SCE_MODULA_PROC 13 +#define SCE_MODULA_PRAGMA 14 +#define SCE_MODULA_PRGKEY 15 +#define SCE_MODULA_OPERATOR 16 +#define SCE_MODULA_BADSTR 17 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h index 0e1159b5..ed110201 100644 --- a/scintilla/include/Scintilla.h +++ b/scintilla/include/Scintilla.h @@ -159,6 +159,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETMARGINMASKN 2245 #define SCI_SETMARGINSENSITIVEN 2246 #define SCI_GETMARGINSENSITIVEN 2247 +#define SCI_SETMARGINCURSORN 2248 +#define SCI_GETMARGINCURSORN 2249 #define STYLE_DEFAULT 32 #define STYLE_LINENUMBER 33 #define STYLE_BRACELIGHT 34 @@ -590,7 +592,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETMOUSEDOWNCAPTURES 2384 #define SCI_GETMOUSEDOWNCAPTURES 2385 #define SC_CURSORNORMAL -1 +#define SC_CURSORARROW 2 #define SC_CURSORWAIT 4 +#define SC_CURSORREVERSEARROW 7 #define SCI_SETCURSOR 2386 #define SCI_GETCURSOR 2387 #define SCI_SETCONTROLCHARSYMBOL 2388 @@ -832,6 +836,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_MOD_CONTAINER 0x40000 #define SC_MOD_LEXERSTATE 0x80000 #define SC_MODEVENTMASKALL 0xFFFFF +#define SC_UPDATE_CONTENT 0x1 +#define SC_UPDATE_SELECTION 0x2 +#define SC_UPDATE_V_SCROLL 0x4 +#define SC_UPDATE_H_SCROLL 0x8 #define SCEN_CHANGE 768 #define SCEN_SETFOCUS 512 #define SCEN_KILLFOCUS 256 @@ -971,6 +979,7 @@ struct SCNotification { int y; /* SCN_DWELLSTART, SCN_DWELLEND */ int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ int annotationLinesAdded; /* SC_MOD_CHANGEANNOTATION */ + int updated; /* SCN_UPDATEUI */ }; #ifdef SCI_NAMESPACE diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface index 61031398..0d3644d6 100644 --- a/scintilla/include/Scintilla.iface +++ b/scintilla/include/Scintilla.iface @@ -352,6 +352,12 @@ set void SetMarginSensitiveN=2246(int margin, bool sensitive) # Retrieve the mouse click sensitivity of a margin. get bool GetMarginSensitiveN=2247(int margin,) +# Set the cursor shown when the mouse is inside a margin. +set void SetMarginCursorN=2248(int margin, int cursor) + +# Retrieve the cursor shown in a margin. +get int GetMarginCursorN=2249(int margin,) + # Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles. # Style 39 is for future use. enu StylesCommon=STYLE_ @@ -1540,7 +1546,9 @@ get bool GetMouseDownCaptures=2385(,) enu CursorShape=SC_CURSOR val SC_CURSORNORMAL=-1 +val SC_CURSORARROW=2 val SC_CURSORWAIT=4 +val SC_CURSORREVERSEARROW=7 # Sets the cursor to one of the SC_CURSOR* values. set void SetCursor=2386(int cursorType,) # Get cursor type. @@ -2193,6 +2201,12 @@ val SC_MOD_CONTAINER=0x40000 val SC_MOD_LEXERSTATE=0x80000 val SC_MODEVENTMASKALL=0xFFFFF +enu Update=SC_UPDATE_ +val SC_UPDATE_CONTENT=0x1 +val SC_UPDATE_SELECTION=0x2 +val SC_UPDATE_V_SCROLL=0x4 +val SC_UPDATE_H_SCROLL=0x8 + # For compatibility, these go through the COMMAND notification rather than NOTIFY # and should have had exactly the same values as the EN_* constants. # Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_* @@ -2335,6 +2349,8 @@ val SCLEX_NIMROD=96 val SCLEX_SML=97 val SCLEX_MARKDOWN=98 val SCLEX_TXT2TAGS=99 +val SCLEX_A68K=100 +val SCLEX_MODULA=101 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -2381,6 +2397,8 @@ val SCE_C_WORD2=16 val SCE_C_COMMENTDOCKEYWORD=17 val SCE_C_COMMENTDOCKEYWORDERROR=18 val SCE_C_GLOBALCLASS=19 +val SCE_C_STRINGRAW=20 +val SCE_C_TRIPLEVERBATIM=21 # Lexical states for SCLEX_D lex D=SCLEX_D SCE_D_ val SCE_D_DEFAULT=0 @@ -2900,6 +2918,7 @@ val SCE_ASM_COMMENTBLOCK=11 val SCE_ASM_CHARACTER=12 val SCE_ASM_STRINGEOL=13 val SCE_ASM_EXTINSTRUCTION=14 +val SCE_ASM_COMMENTDIRECTIVE=15 # Lexical states for SCLEX_FORTRAN lex Fortran=SCLEX_FORTRAN SCE_F_ lex F77=SCLEX_F77 SCE_F_ @@ -3819,6 +3838,47 @@ val SCE_TXT2TAGS_COMMENT=22 val SCE_TXT2TAGS_OPTION=23 val SCE_TXT2TAGS_PREPROC=24 val SCE_TXT2TAGS_POSTPROC=25 +# Lexical states for SCLEX_A68K +lex A68k=SCLEX_A68K SCE_A68K_ +val SCE_A68K_DEFAULT=0 +val SCE_A68K_COMMENT=1 +val SCE_A68K_NUMBER_DEC=2 +val SCE_A68K_NUMBER_BIN=3 +val SCE_A68K_NUMBER_HEX=4 +val SCE_A68K_STRING1=5 +val SCE_A68K_OPERATOR=6 +val SCE_A68K_CPUINSTRUCTION=7 +val SCE_A68K_EXTINSTRUCTION=8 +val SCE_A68K_REGISTER=9 +val SCE_A68K_DIRECTIVE=10 +val SCE_A68K_MACRO_ARG=11 +val SCE_A68K_LABEL=12 +val SCE_A68K_STRING2=13 +val SCE_A68K_IDENTIFIER=14 +val SCE_A68K_MACRO_DECLARATION=15 +val SCE_A68K_COMMENT_WORD=16 +val SCE_A68K_COMMENT_SPECIAL=17 +val SCE_A68K_COMMENT_DOXYGEN=18 +# Lexical states for SCLEX_MODULA +lex Modula=SCLEX_MODULA SCE_MODULA_ +val SCE_MODULA_DEFAULT=0 +val SCE_MODULA_COMMENT=1 +val SCE_MODULA_DOXYCOMM=2 +val SCE_MODULA_DOXYKEY=3 +val SCE_MODULA_KEYWORD=4 +val SCE_MODULA_RESERVED=5 +val SCE_MODULA_NUMBER=6 +val SCE_MODULA_BASENUM=7 +val SCE_MODULA_FLOAT=8 +val SCE_MODULA_STRING=9 +val SCE_MODULA_STRSPEC=10 +val SCE_MODULA_CHAR=11 +val SCE_MODULA_CHARSPEC=12 +val SCE_MODULA_PROC=13 +val SCE_MODULA_PRAGMA=14 +val SCE_MODULA_PRGKEY=15 +val SCE_MODULA_OPERATOR=16 +val SCE_MODULA_BADSTR=17 # Events diff --git a/scintilla/lexers/LexAda.cxx b/scintilla/lexers/LexAda.cxx index 64c8d1c0..e109514c 100644 --- a/scintilla/lexers/LexAda.cxx +++ b/scintilla/lexers/LexAda.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexAsm.cxx b/scintilla/lexers/LexAsm.cxx index 8c0f998d..946d47a9 100644 --- a/scintilla/lexers/LexAsm.cxx +++ b/scintilla/lexers/LexAsm.cxx @@ -4,6 +4,7 @@ ** Written by The Black Horus ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" **/ // Copyright 1998-2003 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -15,17 +16,24 @@ #include #include +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include +#include +#include + #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 "OptionSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -54,15 +62,184 @@ static inline bool IsAsmOperator(const int ch) { return false; } -static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { +static bool IsStreamCommentStyle(int style) { + return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; +} - WordList &cpuInstruction = *keywordlists[0]; - WordList &mathInstruction = *keywordlists[1]; - WordList ®isters = *keywordlists[2]; - WordList &directive = *keywordlists[3]; - WordList &directiveOperand = *keywordlists[4]; - WordList &extInstruction = *keywordlists[5]; +static inline int LowerCase(int c) { + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerAsm +struct OptionsAsm { + std::string delimiter; + bool fold; + bool foldSyntaxBased; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsAsm() { + delimiter = ""; + fold = false; + foldSyntaxBased = true; + foldCommentMultiline = false; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const asmWordListDesc[] = { + "CPU instructions", + "FPU instructions", + "Registers", + "Directives", + "Directive operands", + "Extended instructions", + "Directives4Foldstart", + "Directives4Foldend", + 0 +}; + +struct OptionSetAsm : public OptionSet { + OptionSetAsm() { + DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, + "Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); + + DefineProperty("fold", &OptionsAsm::fold); + + DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, + "Set this property to 1 to enable folding multi-line comments."); + + DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, + "This option enables folding explicit fold points when using the Asm lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " + "at the end of a section that should fold."); + + DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{."); + + DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;}."); + + DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsAsm::foldCompact); + + DefineWordListSets(asmWordListDesc); + } +}; + +class LexerAsm : public ILexer { + WordList cpuInstruction; + WordList mathInstruction; + WordList registers; + WordList directive; + WordList directiveOperand; + WordList extInstruction; + WordList directives4foldstart; + WordList directives4foldend; + OptionsAsm options; + OptionSetAsm osAsm; +public: + LexerAsm() { + } + ~LexerAsm() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osAsm.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osAsm.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osAsm.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osAsm.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 *LexerFactoryAsm() { + return new LexerAsm(); + } +}; + +int SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) { + if (osAsm.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &cpuInstruction; + break; + case 1: + wordListN = &mathInstruction; + break; + case 2: + wordListN = ®isters; + break; + case 3: + wordListN = &directive; + break; + case 4: + wordListN = &directiveOperand; + break; + case 5: + wordListN = &extInstruction; + break; + case 6: + wordListN = &directives4foldstart; + break; + case 7: + wordListN = &directives4foldend; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); // Do not leak onto next line if (initStyle == SCE_ASM_STRINGEOL) @@ -96,7 +273,7 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo if (!IsAsmOperator(sc.ch)) { sc.SetState(SCE_ASM_DEFAULT); } - }else if (sc.state == SCE_ASM_NUMBER) { + } else if (sc.state == SCE_ASM_NUMBER) { if (!IsAWordChar(sc.ch)) { sc.SetState(SCE_ASM_DEFAULT); } @@ -104,6 +281,7 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo if (!IsAWordChar(sc.ch) ) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); + bool IsDirective = false; if (cpuInstruction.InList(s)) { sc.ChangeState(SCE_ASM_CPUINSTRUCTION); @@ -113,15 +291,32 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo sc.ChangeState(SCE_ASM_REGISTER); } else if (directive.InList(s)) { sc.ChangeState(SCE_ASM_DIRECTIVE); + IsDirective = true; } else if (directiveOperand.InList(s)) { sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); } else if (extInstruction.InList(s)) { sc.ChangeState(SCE_ASM_EXTINSTRUCTION); } sc.SetState(SCE_ASM_DEFAULT); + if (IsDirective && !strcmp(s, "comment")) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + if (sc.ch == delimiter) { + sc.SetState(SCE_ASM_COMMENTDIRECTIVE); + } + } } - } - else if (sc.state == SCE_ASM_COMMENT ) { + } else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + if (sc.ch == delimiter) { + while (!sc.atLineEnd) { + sc.Forward(); + } + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_COMMENT ) { if (sc.atLineEnd) { sc.SetState(SCE_ASM_DEFAULT); } @@ -170,15 +365,100 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo sc.Complete(); } -static const char * const asmWordListDesc[] = { - "CPU instructions", - "FPU instructions", - "Registers", - "Directives", - "Directive operands", - "Extended instructions", - 0 -}; +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "else". -LexerModule lmAsm(SCLEX_ASM, ColouriseAsmDoc, "asm", 0, asmWordListDesc); +void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char word[100]; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if (ch == ';') { + if (chNext == '{') { + levelNext++; + } else if (chNext == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { + word[wordlen++] = static_cast(LowerCase(ch)); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready + word[wordlen] = '\0'; + wordlen = 0; + if (directives4foldstart.InList(word)) { + levelNext++; + } else if (directives4foldend.InList(word)){ + levelNext--; + } + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); diff --git a/scintilla/lexers/LexBash.cxx b/scintilla/lexers/LexBash.cxx index 1c844a6f..165e1049 100644 --- a/scintilla/lexers/LexBash.cxx +++ b/scintilla/lexers/LexBash.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -640,6 +639,14 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], levelCurrent--; } } + // Here Document folding + if (style == SCE_SH_HERE_DELIM) { + if (ch == '<' && chNext == '<') { + levelCurrent++; + } + } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_PL_DEFAULT) { + levelCurrent--; + } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) diff --git a/scintilla/lexers/LexCOBOL.cxx b/scintilla/lexers/LexCOBOL.cxx index b9c8f4dc..a9a8f551 100644 --- a/scintilla/lexers/LexCOBOL.cxx +++ b/scintilla/lexers/LexCOBOL.cxx @@ -19,7 +19,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexCPP.cxx b/scintilla/lexers/LexCPP.cxx index bc7bb370..f573befa 100644 --- a/scintilla/lexers/LexCPP.cxx +++ b/scintilla/lexers/LexCPP.cxx @@ -1,6 +1,7 @@ // Scintilla source code edit control /** @file LexCPP.cxx ** Lexer for C++, C, Java, and JavaScript. + ** Further folding features and configuration properties added by "Udo Lechner" **/ // Copyright 1998-2005 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -15,10 +16,6 @@ #ifdef _MSC_VER #pragma warning(disable: 4786) #endif -#ifdef __BORLANDC__ -// Borland C++ displays warnings in vector header without this -#pragma option -w-ccc -w-rch -#endif #include #include @@ -29,7 +26,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -37,6 +33,7 @@ #include "CharacterSet.h" #include "LexerModule.h" #include "OptionSet.h" +#include "SparseState.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -212,8 +209,13 @@ struct OptionsCPP { bool trackPreprocessor; bool updatePreprocessor; bool fold; + bool foldSyntaxBased; bool foldComment; + bool foldCommentMultiline; bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; bool foldPreprocessor; bool foldCompact; bool foldAtElse; @@ -223,8 +225,13 @@ struct OptionsCPP { trackPreprocessor = true; updatePreprocessor = true; fold = false; + foldSyntaxBased = true; foldComment = false; + foldCommentMultiline = true; foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; foldPreprocessor = false; foldCompact = false; foldAtElse = false; @@ -258,14 +265,29 @@ struct OptionSetCPP : public OptionSet { DefineProperty("fold", &OptionsCPP::fold); + DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + DefineProperty("fold.comment", &OptionsCPP::foldComment, "This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " "Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} " "at the end of a section that should fold."); + DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit, "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor, "This option enables folding preprocessor directives when using the C++ lexer. " "Includes C#'s explicit #region and #endregion folding directives."); @@ -288,7 +310,6 @@ class LexerCPP : public ILexer { CharacterSet setLogicalOp; PPStates vlls; std::vector ppDefineHistory; - PropSetSimple props; WordList keywords; WordList keywords2; WordList keywords3; @@ -297,6 +318,7 @@ class LexerCPP : public ILexer { std::map preprocessorDefinitionsStart; OptionsCPP options; OptionSetCPP osCPP; + SparseState rawStringTerminators; public: LexerCPP(bool caseSensitive_) : caseSensitive(caseSensitive_), @@ -419,7 +441,6 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); if (options.identifiersAllowDollars) { setWordStart.Add('$'); @@ -483,16 +504,18 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } const int maskActivity = 0x3F; + std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); + SparseState rawSTNew(lineCurrent); int activitySet = preproc.IsInactive() ? 0x40 : 0; for (; sc.More(); sc.Forward()) { if (sc.atLineStart) { - if (sc.state == SCE_C_STRING) { + if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { // Prevent SCE_C_STRINGEOL from leaking back to previous line which // ends with a line continuation by locking in the state upto this position. - sc.SetState(SCE_C_STRING); + sc.SetState(sc.state); } // Reset states to begining of colourise so no surprises // if different sets of lines lexed. @@ -515,6 +538,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd) { lineCurrent++; vlls.Add(lineCurrent, preproc); + if (rawStringTerminator != "") { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } } // Handle line continuation generically. @@ -558,6 +584,23 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else if (keywords4.InList(s)) { sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); } + const bool literalString = sc.ch == '\"'; + if (literalString || sc.ch == '\'') { + size_t lenS = strlen(s); + const bool raw = literalString && sc.chPrev == 'R'; + if (raw) + s[lenS--] = '\0'; + bool valid = + (lenS == 0) || + ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || + ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); + if (valid) { + if (literalString) + sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet); + else + sc.ChangeState(SCE_C_CHARACTER|activitySet); + } + } sc.SetState(SCE_C_DEFAULT|activitySet); } break; @@ -642,6 +685,14 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, sc.ForwardSetState(SCE_C_DEFAULT|activitySet); } break; + case SCE_C_STRINGRAW: + if (sc.Match(rawStringTerminator.c_str())) { + for (size_t termPos=rawStringTerminator.size(); termPos; termPos--) + sc.Forward(); + sc.SetState(SCE_C_DEFAULT|activitySet); + rawStringTerminator = ""; + } + break; case SCE_C_CHARACTER: if (sc.atLineEnd) { sc.ChangeState(SCE_C_STRINGEOL|activitySet); @@ -682,6 +733,14 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } } break; + case SCE_C_TRIPLEVERBATIM: + if (sc.Match ("\"\"\"")) { + while (sc.Match('"')) { + sc.Forward(); + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; case SCE_C_UUID: if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { sc.SetState(SCE_C_DEFAULT|activitySet); @@ -699,6 +758,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.Match('@', '\"')) { sc.SetState(SCE_C_VERBATIM|activitySet); sc.Forward(); + } else if (sc.Match("\"\"\"")) { + sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet); + sc.Forward(2); } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (lastWordWasUUID) { sc.SetState(SCE_C_UUID|activitySet); @@ -733,7 +795,19 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, || !FollowsPostfixOperator(sc, styler))) { sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx } else if (sc.ch == '\"') { - sc.SetState(SCE_C_STRING|activitySet); + if (sc.chPrev == 'R') { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = ")"; + for (int termPos = sc.currentPos + 1;;termPos++) { + char chTerminator = styler.SafeGetCharAt(termPos, '('); + if (chTerminator == '(') + break; + rawStringTerminator += chTerminator; + } + rawStringTerminator += '\"'; + } else { + sc.SetState(SCE_C_STRING|activitySet); + } isIncludePreprocessor = false; // ensure that '>' won't end the string } else if (isIncludePreprocessor && sc.ch == '<') { sc.SetState(SCE_C_STRING|activitySet); @@ -828,10 +902,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } continuationLine = false; } - if (definitionsChanged) + const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent); + if (definitionsChanged || rawStringsChanged) styler.ChangeLexerState(startPos, startPos + length); sc.Complete(); - styler.Flush(); } // Store both the current line's fold level and the next lines in the @@ -856,6 +930,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -863,7 +938,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (options.foldComment && IsStreamCommentStyle(style)) { + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { @@ -871,14 +946,22 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, levelNext--; } } - if (options.foldComment && options.foldCommentExplicit && (style == SCE_C_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { levelNext++; - } else if (chNext2 == '}') { + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { levelNext--; } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } } } if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { @@ -894,7 +977,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, } } } - if (style == SCE_C_OPERATOR) { + if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { if (ch == '{') { // Measure the minimum before a '{' to allow // folding on "} else {" @@ -910,7 +993,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, visibleChars++; if (atEOL || (i == endPos-1)) { int levelUse = levelCurrent; - if (options.foldAtElse) { + if (options.foldSyntaxBased && options.foldAtElse) { levelUse = levelMinCurrent; } int lev = levelUse | levelNext << 16; diff --git a/scintilla/lexers/LexCSS.cxx b/scintilla/lexers/LexCSS.cxx index fba8dac1..8fbca384 100644 --- a/scintilla/lexers/LexCSS.cxx +++ b/scintilla/lexers/LexCSS.cxx @@ -18,7 +18,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexCmake.cxx b/scintilla/lexers/LexCmake.cxx index c43974d4..70e9dee9 100644 --- a/scintilla/lexers/LexCmake.cxx +++ b/scintilla/lexers/LexCmake.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexD.cxx b/scintilla/lexers/LexD.cxx index 78b23dcd..5b8f9e72 100644 --- a/scintilla/lexers/LexD.cxx +++ b/scintilla/lexers/LexD.cxx @@ -2,6 +2,7 @@ ** Lexer for D. ** ** Copyright (c) 2006 by Waldemar Augustyn + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" **/ // Copyright 1998-2005 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -13,17 +14,23 @@ #include #include +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include +#include + #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 "OptionSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -59,17 +66,187 @@ static bool IsStringSuffix(int ch) { return ch == 'c' || ch == 'w' || ch == 'd'; } +static bool IsStreamCommentStyle(int style) { + return style == SCE_D_COMMENT || + style == SCE_D_COMMENTDOC || + style == SCE_D_COMMENTDOCKEYWORD || + style == SCE_D_COMMENTDOCKEYWORDERROR; +} -static void ColouriseDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool caseSensitive) { +// An individual named option for use in an OptionSet - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; //doxygen - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; +// Options used for LexerD +struct OptionsD { + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + int foldAtElseInt; + bool foldAtElse; + OptionsD() { + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + foldAtElseInt = -1; + foldAtElse = false; + } +}; + +static const char * const dWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Type definitions and aliases", + "Keywords 5", + "Keywords 6", + "Keywords 7", + 0, + }; + +struct OptionSetD : public OptionSet { + OptionSetD() { + DefineProperty("fold", &OptionsD::fold); + + DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsD::foldComment); + + DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsD::foldCompact); + + DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, + "This option enables D folding on a \"} else {\" line of an if statement."); + + DefineProperty("fold.at.else", &OptionsD::foldAtElse); + + DefineWordListSets(dWordLists); + } +}; + +class LexerD : public ILexer { + bool caseSensitive; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList keywords6; + WordList keywords7; + OptionsD options; + OptionSetD osD; +public: + LexerD(bool caseSensitive_) : + caseSensitive(caseSensitive_) { + } + ~LexerD() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osD.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osD.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osD.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osD.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 *LexerFactoryD() { + return new LexerD(true); + } + static ILexer *LexerFactoryDInsensitive() { + return new LexerD(false); + } +}; + +int SCI_METHOD LexerD::PropertySet(const char *key, const char *val) { + if (osD.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerD::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &keywords6; + break; + case 6: + wordListN = &keywords7; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); int styleBeforeDCKeyword = SCE_D_DEFAULT; @@ -294,24 +471,17 @@ static void ColouriseDoc(unsigned int startPos, int length, int initStyle, sc.Complete(); } -static bool IsStreamCommentStyle(int style) { - return style == SCE_D_COMMENT || - style == SCE_D_COMMENTDOC || - style == SCE_D_COMMENTDOCKEYWORD || - style == SCE_D_COMMENTDOCKEYWORDERROR; -} - // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". -static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // property lexer.d.fold.at.else - // This option enables D folding on a "} else {" line of an if statement. - bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", - styler.GetPropertyInt("fold.at.else", 0)) != 0; +void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); @@ -323,6 +493,8 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; + bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -330,7 +502,7 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -338,7 +510,25 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & levelNext--; } } - if (style == SCE_D_OPERATOR) { + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) { if (ch == '{') { // Measure the minimum before a '{' to allow // folding on "} else {" @@ -350,19 +540,19 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & levelNext--; } } - if (atEOL) { - if (foldComment) { // Handle nested comments + if (atEOL || (i == endPos-1)) { + if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments int nc; nc = styler.GetLineState(lineCurrent); nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; levelNext += nc; } int levelUse = levelCurrent; - if (foldAtElse) { + if (options.foldSyntaxBased && foldAtElse) { levelUse = levelMinCurrent; } int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) + if (visibleChars == 0 && options.foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; @@ -379,25 +569,4 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & } } -static void FoldDDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldDoc(startPos, length, initStyle, styler); -} - -static const char * const dWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Type definitions and aliases", - "Keywords 5", - "Keywords 6", - "Keywords 7", - 0, - }; - -static void ColouriseDDoc(unsigned int startPos, int length, - int initStyle, WordList *keywordlists[], Accessor &styler) { - ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists); +LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists); diff --git a/scintilla/lexers/LexErlang.cxx b/scintilla/lexers/LexErlang.cxx index 00f18b56..5f522585 100644 --- a/scintilla/lexers/LexErlang.cxx +++ b/scintilla/lexers/LexErlang.cxx @@ -19,7 +19,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexForth.cxx b/scintilla/lexers/LexForth.cxx index da52338f..0e9875ce 100644 --- a/scintilla/lexers/LexForth.cxx +++ b/scintilla/lexers/LexForth.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexFortran.cxx b/scintilla/lexers/LexFortran.cxx index 67a58a0c..6c61c540 100644 --- a/scintilla/lexers/LexFortran.cxx +++ b/scintilla/lexers/LexFortran.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -267,7 +266,7 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 || strcmp(s, "endwhere") == 0 - || strcmp(s, "procedure") == 0 ) { // Take care of the module procedure statement + || (strcmp(s, "procedure") == 0 && strcmp(prevWord,"module")==0) ) { // Take care of the module procedure statement lev = -1; } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if lev = 0; diff --git a/scintilla/lexers/LexHTML.cxx b/scintilla/lexers/LexHTML.cxx index e025c2b3..546f5ad9 100644 --- a/scintilla/lexers/LexHTML.cxx +++ b/scintilla/lexers/LexHTML.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -745,8 +744,18 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { - if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { - levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1; + if (ch == '#') { + int j = i + 1; + while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*')) ) { + levelCurrent += ((ch == '{') || (ch == '/') ) ? 1 : -1; } } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { levelCurrent--; diff --git a/scintilla/lexers/LexLisp.cxx b/scintilla/lexers/LexLisp.cxx index 4c5f3a8d..08f765ad 100644 --- a/scintilla/lexers/LexLisp.cxx +++ b/scintilla/lexers/LexLisp.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexLua.cxx b/scintilla/lexers/LexLua.cxx index ac3d6d5a..a299d326 100644 --- a/scintilla/lexers/LexLua.cxx +++ b/scintilla/lexers/LexLua.cxx @@ -18,7 +18,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexMarkdown.cxx b/scintilla/lexers/LexMarkdown.cxx index e3ffa667..39371203 100644 --- a/scintilla/lexers/LexMarkdown.cxx +++ b/scintilla/lexers/LexMarkdown.cxx @@ -44,7 +44,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexMatlab.cxx b/scintilla/lexers/LexMatlab.cxx index af26ff9c..0d2064e8 100644 --- a/scintilla/lexers/LexMatlab.cxx +++ b/scintilla/lexers/LexMatlab.cxx @@ -21,7 +21,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexNsis.cxx b/scintilla/lexers/LexNsis.cxx index 820a5d12..cd74d540 100644 --- a/scintilla/lexers/LexNsis.cxx +++ b/scintilla/lexers/LexNsis.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexOthers.cxx b/scintilla/lexers/LexOthers.cxx index 3449f07f..2062b1b1 100644 --- a/scintilla/lexers/LexOthers.cxx +++ b/scintilla/lexers/LexOthers.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" @@ -510,7 +509,7 @@ static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { styler.ColourTo(endLine, SCE_DIFF_COMMAND); } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "---", 3)) { + } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { // In a context diff, --- appears in both the header and the position markers if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) styler.ColourTo(endLine, SCE_DIFF_POSITION); @@ -930,8 +929,8 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin // Command or return status return SCE_ERR_CMD; } else if (lineBuffer[0] == '<') { - // Diff removal, but not interested. Trapped to avoid hitting CTAG cases. - return SCE_ERR_DEFAULT; + // Diff removal. + return SCE_ERR_DIFF_DELETION; } else if (lineBuffer[0] == '!') { return SCE_ERR_DIFF_CHANGED; } else if (lineBuffer[0] == '+') { diff --git a/scintilla/lexers/LexPascal.cxx b/scintilla/lexers/LexPascal.cxx index 1243d382..867b00ea 100644 --- a/scintilla/lexers/LexPascal.cxx +++ b/scintilla/lexers/LexPascal.cxx @@ -118,7 +118,6 @@ contains requires #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexPerl.cxx b/scintilla/lexers/LexPerl.cxx index 9d768478..bc313a93 100644 --- a/scintilla/lexers/LexPerl.cxx +++ b/scintilla/lexers/LexPerl.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexPython.cxx b/scintilla/lexers/LexPython.cxx index 5e7c5b29..5020d71d 100644 --- a/scintilla/lexers/LexPython.cxx +++ b/scintilla/lexers/LexPython.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexR.cxx b/scintilla/lexers/LexR.cxx index 9947c723..d18fffb9 100644 --- a/scintilla/lexers/LexR.cxx +++ b/scintilla/lexers/LexR.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexSQL.cxx b/scintilla/lexers/LexSQL.cxx index 6ec32d04..ebcd72c0 100644 --- a/scintilla/lexers/LexSQL.cxx +++ b/scintilla/lexers/LexSQL.cxx @@ -2,7 +2,7 @@ /** @file LexSQL.cxx ** Lexer for SQL, including PL/SQL and SQL*Plus. **/ -// Copyright 1998-2005 by Neil Hodgson +// Copyright 1998-2011 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -12,24 +12,36 @@ #include #include +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include +#include +#include +#include + #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 "OptionSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); +static inline bool IsAWordChar(int ch, bool sqlAllowDottedWord) { + if (!sqlAllowDottedWord) + return (ch < 0x80) && (isalnum(ch) || ch == '_'); + else + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); } static inline bool IsAWordStart(int ch) { @@ -47,31 +59,289 @@ static inline bool IsANumberChar(int ch) { // Not exactly following number definition (several dots are seen as OK, etc.) // but probably enough in most cases. return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); } -static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &kw_pldoc = *keywordlists[2]; - WordList &kw_sqlplus = *keywordlists[3]; - WordList &kw_user1 = *keywordlists[4]; - WordList &kw_user2 = *keywordlists[5]; - WordList &kw_user3 = *keywordlists[6]; - WordList &kw_user4 = *keywordlists[7]; +class SQLStates { +public : + void Set(int lineNumber, unsigned short int sqlStatesLine) { + if (!sqlStatement.size() == 0 || !sqlStatesLine == 0) { + sqlStatement.resize(lineNumber + 1, 0); + sqlStatement[lineNumber] = sqlStatesLine; + } + } + unsigned short int IgnoreWhen (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_IGNORE_WHEN; + else + sqlStatesLine &= ~MASK_IGNORE_WHEN; + + return sqlStatesLine; + } + + unsigned short int IntoCondition (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_CONDITION; + else + sqlStatesLine &= ~MASK_INTO_CONDITION; + + return sqlStatesLine; + } + + unsigned short int IntoExceptionBlock (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_EXCEPTION; + else + sqlStatesLine &= ~MASK_INTO_EXCEPTION; + + return sqlStatesLine; + } + + unsigned short int IntoDeclareBlock (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_DECLARE; + else + sqlStatesLine &= ~MASK_INTO_DECLARE; + + return sqlStatesLine; + } + + unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) { + if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) { + sqlStatesLine++; + } + return sqlStatesLine; + } + + unsigned short int EndCaseBlock (unsigned short int sqlStatesLine) { + if ((sqlStatesLine & MASK_NESTED_CASES) > 0) { + sqlStatesLine--; + } + return sqlStatesLine; + } + + bool IsIgnoreWhen (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_IGNORE_WHEN) != 0; + } + + bool IsIntoCondition (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_CONDITION) != 0; + } + + bool IsIntoCaseBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_NESTED_CASES) != 0; + } + + bool IsIntoExceptionBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0; + } + + bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_DECLARE) != 0; + } + + unsigned short int ForLine(int lineNumber) { + if ((lineNumber > 0) && (sqlStatement.size() > static_cast(lineNumber))) { + return sqlStatement[lineNumber]; + } else { + return 0; + } + } + + SQLStates() {} + +private : + std::vector sqlStatement; + enum { + MASK_INTO_DECLARE = 0x1000, + MASK_INTO_EXCEPTION = 0x2000, + MASK_INTO_CONDITION = 0x4000, + MASK_IGNORE_WHEN = 0x8000, + MASK_NESTED_CASES = 0x0FFF + }; +}; + +// Options used for LexerSQL +struct OptionsSQL { + bool fold; + bool foldAtElse; + bool foldComment; + bool foldCompact; + bool foldOnlyBegin; + bool sqlBackticksIdentifier; + bool sqlNumbersignComment; + bool sqlBackslashEscapes; + bool sqlAllowDottedWord; + OptionsSQL() { + fold = false; + foldAtElse = false; + foldComment = false; + foldCompact = false; + foldOnlyBegin = false; + sqlBackticksIdentifier = false; + sqlNumbersignComment = false; + sqlBackslashEscapes = false; + sqlAllowDottedWord = false; + } +}; + +static const char * const sqlWordListDesc[] = { + "Keywords", + "Database Objects", + "PLDoc", + "SQL*Plus", + "User Keywords 1", + "User Keywords 2", + "User Keywords 3", + "User Keywords 4", + 0 +}; + +struct OptionSetSQL : public OptionSet { + OptionSetSQL() { + DefineProperty("fold", &OptionsSQL::fold); + + DefineProperty("lexer.sql.fold.at.else", &OptionsSQL::foldAtElse, + "This option enables SQL folding on a \"ELSE\" and \"ELSIF\"line of an IF statement."); + + DefineProperty("fold.comment", &OptionsSQL::foldComment); + + DefineProperty("fold.compact", &OptionsSQL::foldCompact); + + DefineProperty("fold.sql.only.begin", &OptionsSQL::foldOnlyBegin); + + DefineProperty("lexer.sql.backticks.identifier", &OptionsSQL::sqlBackticksIdentifier); + + DefineProperty("lexer.sql.numbersign.comment", &OptionsSQL::sqlNumbersignComment, + "If \"lexer.sql.numbersign.comment\" property is set to 0 a line beginning with '#' will not be a comment."); + + DefineProperty("sql.backslash.escapes", &OptionsSQL::sqlBackslashEscapes, + "Enables backslash as an escape character in SQL."); + + DefineProperty("lexer.sql.allow.dotted.word", &OptionsSQL::sqlAllowDottedWord, + "Set to 1 to colourise recognized words with dots " + "(recommended for Oracle PL/SQL objects)."); + + DefineWordListSets(sqlWordListDesc); + } +}; + +class LexerSQL : public ILexer { +public : + LexerSQL() {} + + int SCI_METHOD Version () const { + return lvOriginal; + } + + void SCI_METHOD Release() { + delete this; + } + + const char * SCI_METHOD PropertyNames() { + return osSQL.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char *name) { + return osSQL.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char *name) { + return osSQL.DescribeProperty(name); + } + + int SCI_METHOD PropertySet(const char *key, const char *val) { + if (osSQL.PropertySet(&options, key, val)) { + return 0; + } + return -1; + } + + const char * SCI_METHOD DescribeWordListSets() { + return osSQL.DescribeWordListSets(); + } + + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex (unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactorySQL() { + return new LexerSQL(); + } +private: + bool IsStreamCommentStyle(int style) { + return style == SCE_SQL_COMMENT || + style == SCE_SQL_COMMENTDOC || + style == SCE_SQL_COMMENTDOCKEYWORD || + style == SCE_SQL_COMMENTDOCKEYWORDERROR; + } + + OptionsSQL options; + OptionSetSQL osSQL; + SQLStates sqlStates; + + WordList keywords1; + WordList keywords2; + WordList kw_pldoc; + WordList kw_sqlplus; + WordList kw_user1; + WordList kw_user2; + WordList kw_user3; + WordList kw_user4; +}; + +int SCI_METHOD LexerSQL::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords1; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &kw_pldoc; + break; + case 3: + wordListN = &kw_sqlplus; + break; + case 4: + wordListN = &kw_user1; + break; + case 5: + wordListN = &kw_user2; + break; + case 6: + wordListN = &kw_user3; + break; + case 7: + wordListN = &kw_user4; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); StyleContext sc(startPos, length, initStyle, styler); - - // property sql.backslash.escapes - // Enables backslash as an escape character in SQL. - bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0; - - bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0; int styleBeforeDCKeyword = SCE_SQL_DEFAULT; - for (; sc.More(); sc.Forward()) { + int offset = 0; + for (; sc.More(); sc.Forward(), offset++) { // Determine if the current state should terminate. switch (sc.state) { case SCE_SQL_OPERATOR: @@ -84,7 +354,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo } break; case SCE_SQL_IDENTIFIER: - if (!IsAWordChar(sc.ch)) { + if (!IsAWordChar(sc.ch, options.sqlAllowDottedWord)) { int nextState = SCE_SQL_DEFAULT; char s[1000]; sc.GetCurrentLowered(s, sizeof(s)); @@ -161,7 +431,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo } break; case SCE_SQL_CHARACTER: - if (sqlBackslashEscapes && sc.ch == '\\') { + if (options.sqlBackslashEscapes && sc.ch == '\\') { sc.Forward(); } else if (sc.ch == '\'') { if (sc.chNext == '\"') { @@ -191,7 +461,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo sc.SetState(SCE_SQL_NUMBER); } else if (IsAWordStart(sc.ch)) { sc.SetState(SCE_SQL_IDENTIFIER); - } else if (sc.ch == 0x60 && sqlBackticksIdentifier) { + } else if (sc.ch == 0x60 && options.sqlBackticksIdentifier) { sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); } else if (sc.Match('/', '*')) { if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style @@ -204,9 +474,9 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo // MySQL requires a space or control char after -- // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html // Perhaps we should enforce that with proper property: -//~ } else if (sc.Match("-- ")) { + //~ } else if (sc.Match("-- ")) { sc.SetState(SCE_SQL_COMMENTLINE); - } else if (sc.ch == '#') { + } else if (sc.ch == '#' && options.sqlNumbersignComment) { sc.SetState(SCE_SQL_COMMENTLINEDOC); } else if (sc.ch == '\'') { sc.SetState(SCE_SQL_CHARACTER); @@ -220,25 +490,10 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo sc.Complete(); } -static bool IsStreamCommentStyle(int style) { - return style == SCE_SQL_COMMENT || - style == SCE_SQL_COMMENTDOC || - style == SCE_SQL_COMMENTDOCKEYWORD || - style == SCE_SQL_COMMENTDOCKEYWORDERROR; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment. -static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; - - // property fold.sql.exists - // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS". - bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 1) != 0; - +void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + if (!options.fold) + return; + LexAccessor styler(pAccess); unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); @@ -251,6 +506,14 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, int styleNext = styler.StyleAt(startPos); int style = initStyle; bool endFound = false; + bool isUnfoldingIgnored = false; + // this statementFound flag avoids to fold when the statement is on only one line by ignoring ELSE or ELSIF + // eg. "IF condition1 THEN ... ELSIF condition2 THEN ... ELSE ... END IF;" + bool statementFound = false; + unsigned short int sqlStatesCurrentLine = 0; + if (!options.foldOnlyBegin) { + sqlStatesCurrentLine = sqlStates.ForLine(lineCurrent); + } for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -258,7 +521,16 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { + if (atEOL || (ch == ';')) { + if (endFound) { + //Maybe this is the end of "EXCEPTION" BLOCK (eg. "BEGIN ... EXCEPTION ... END;") + sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, false); + } + // set endFound and isUnfoldingIgnored to false if EOL is reached or ';' is found + endFound = false; + isUnfoldingIgnored = false; + } + if (options.foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -266,7 +538,7 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, levelNext--; } } - if (foldComment && (style == SCE_SQL_COMMENTLINE)) { + if (options.foldComment && (style == SCE_SQL_COMMENTLINE)) { // MySQL needs -- comments to be followed by space or control char if ((ch == '-') && (chNext == '-')) { char chNext2 = styler.SafeGetCharAt(i + 2); @@ -280,14 +552,18 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, } if (style == SCE_SQL_OPERATOR) { if (ch == '(') { - levelNext++; + if (levelCurrent > levelNext) + levelCurrent--; + levelNext++; } else if (ch == ')') { levelNext--; + } else if ((!options.foldOnlyBegin) && ch == ';') { + sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, false); } } // If new keyword (cannot trigger on elseif or nullif, does less tests) if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { - const int MAX_KW_LEN = 6; // Maximum length of folding keywords + const int MAX_KW_LEN = 9; // Maximum length of folding keywords char s[MAX_KW_LEN + 2]; unsigned int j = 0; for (; j < MAX_KW_LEN + 1; j++) { @@ -302,33 +578,133 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, } else { s[j] = '\0'; } - if ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) { + + if (strcmp(s, "if") == 0) { if (endFound) { - // ignore endFound = false; + if (options.foldOnlyBegin && !isUnfoldingIgnored) { + // this end isn't for begin block, but for if block ("end if;") + // so ignore previous "end" by increment levelNext. + levelNext++; + } } else { - levelNext++; + if (!options.foldOnlyBegin) + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide IF (eg "END; IF") + levelCurrent = levelNext; + } } + } else if (!options.foldOnlyBegin && + strcmp(s, "then") == 0 && + sqlStates.IsIntoCondition(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, false); + if (!options.foldOnlyBegin) { + if (levelCurrent > levelNext) { + levelCurrent = levelNext; + } + if (!statementFound) + levelNext++; + + statementFound = true; + } else if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE") + levelCurrent = levelNext; + } + } else if (strcmp(s, "loop") == 0 || + strcmp(s, "case") == 0) { + if (endFound) { + endFound = false; + if (options.foldOnlyBegin && !isUnfoldingIgnored) { + // this end isn't for begin block, but for loop block ("end loop;") or case block ("end case;") + // so ignore previous "end" by increment levelNext. + levelNext++; + } + if ((!options.foldOnlyBegin) && strcmp(s, "case") == 0) { + sqlStatesCurrentLine = sqlStates.EndCaseBlock(sqlStatesCurrentLine); + levelNext--; //again for the "end case;" and block when + } + } else if (!options.foldOnlyBegin) { + if (strcmp(s, "case") == 0) { + sqlStatesCurrentLine = sqlStates.BeginCaseBlock(sqlStatesCurrentLine); + + //for case block increment 2 times + if (!statementFound) + levelNext++; + } + + if (levelCurrent > levelNext) { + levelCurrent = levelNext; + } + if (!statementFound) + levelNext++; + + statementFound = true; + } else if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE") + levelCurrent = levelNext; + } + } else if ((!options.foldOnlyBegin) && ( + // folding for ELSE and ELSIF block only if foldAtElse is set + // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound) + options.foldAtElse && !statementFound) && strcmp(s, "elsif") == 0) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + levelCurrent--; + levelNext--; + } else if ((!options.foldOnlyBegin) && ( + // folding for ELSE and ELSIF block only if foldAtElse is set + // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound) + options.foldAtElse && !statementFound) && strcmp(s, "else") == 0) { + // prevent also ELSE is on the same line (eg. "ELSE ... END IF;") + statementFound = true; + // we are in same case "} ELSE {" in C language + levelCurrent--; + } else if (strcmp(s, "begin") == 0) { levelNext++; + sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false); } else if ((strcmp(s, "end") == 0) || -// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS - (foldSqlExists && (strcmp(s, "exists") == 0)) || -// // SQL Anywhere permits IF ... ELSE ... ENDIF -// // will only be active if "endif" appears in the -// // keyword list. - (strcmp(s, "endif") == 0)) { + // SQL Anywhere permits IF ... ELSE ... ENDIF + // will only be active if "endif" appears in the + // keyword list. + (strcmp(s, "endif") == 0)) { endFound = true; levelNext--; if (levelNext < SC_FOLDLEVELBASE) { levelNext = SC_FOLDLEVELBASE; + isUnfoldingIgnored = true; } + } else if ((!options.foldOnlyBegin) && + strcmp(s, "when") == 0 && + !sqlStates.IsIgnoreWhen(sqlStatesCurrentLine) && + !sqlStates.IsIntoExceptionBlock(sqlStatesCurrentLine) && + sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + + // Don't foldind when CASE and WHEN are on the same line (with flag statementFound) (eg. "CASE selector WHEN expression1 THEN sequence_of_statements1;\n") + if (!statementFound) { + levelCurrent--; + levelNext--; + } + } else if ((!options.foldOnlyBegin) && strcmp(s, "exit") == 0) { + sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && !sqlStates.IsIntoDeclareBlock(sqlStatesCurrentLine) && strcmp(s, "exception") == 0) { + sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && + (strcmp(s, "declare") == 0 || + strcmp(s, "function") == 0 || + strcmp(s, "procedure") == 0 || + strcmp(s, "package") == 0)) { + sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, true); } } if (atEOL) { int levelUse = levelCurrent; int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) + if (visibleChars == 0 && options.foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; @@ -338,7 +714,9 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, lineCurrent++; levelCurrent = levelNext; visibleChars = 0; - endFound = false; + statementFound = false; + if (!options.foldOnlyBegin) + sqlStates.Set(lineCurrent, sqlStatesCurrentLine); } if (!isspacechar(ch)) { visibleChars++; @@ -346,16 +724,4 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, } } -static const char * const sqlWordListDesc[] = { - "Keywords", - "Database Objects", - "PLDoc", - "SQL*Plus", - "User Keywords 1", - "User Keywords 2", - "User Keywords 3", - "User Keywords 4", - 0 -}; - -LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc); +LexerModule lmSQL(SCLEX_SQL, LexerSQL::LexerFactorySQL, "sql", sqlWordListDesc); diff --git a/scintilla/lexers/LexTCL.cxx b/scintilla/lexers/LexTCL.cxx index 0e196cb7..de309f2a 100644 --- a/scintilla/lexers/LexTCL.cxx +++ b/scintilla/lexers/LexTCL.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexTxt2tags.cxx b/scintilla/lexers/LexTxt2tags.cxx index 3bed55b1..8f8e181b 100644 --- a/scintilla/lexers/LexTxt2tags.cxx +++ b/scintilla/lexers/LexTxt2tags.cxx @@ -27,7 +27,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexVHDL.cxx b/scintilla/lexers/LexVHDL.cxx index fc4d1def..58bcd1a5 100644 --- a/scintilla/lexers/LexVHDL.cxx +++ b/scintilla/lexers/LexVHDL.cxx @@ -21,7 +21,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexVerilog.cxx b/scintilla/lexers/LexVerilog.cxx index a73edfb7..8de04ff7 100644 --- a/scintilla/lexers/LexVerilog.cxx +++ b/scintilla/lexers/LexVerilog.cxx @@ -17,7 +17,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexers/LexYAML.cxx b/scintilla/lexers/LexYAML.cxx index 8e2ff742..727e8af8 100644 --- a/scintilla/lexers/LexYAML.cxx +++ b/scintilla/lexers/LexYAML.cxx @@ -16,7 +16,6 @@ #include "Scintilla.h" #include "SciLexer.h" -#include "PropSetSimple.h" #include "WordList.h" #include "LexAccessor.h" #include "Accessor.h" diff --git a/scintilla/lexlib/CharacterSet.h b/scintilla/lexlib/CharacterSet.h index 18cb0aa9..72405606 100644 --- a/scintilla/lexlib/CharacterSet.h +++ b/scintilla/lexlib/CharacterSet.h @@ -50,8 +50,8 @@ public: assert(val < size); bset[val] = true; } - void AddString(const char *CharacterSet) { - for (const char *cp=CharacterSet; *cp; cp++) { + void AddString(const char *setToAdd) { + for (const char *cp=setToAdd; *cp; cp++) { int val = static_cast(*cp); assert(val >= 0); assert(val < size); diff --git a/scintilla/lexlib/LexerBase.h b/scintilla/lexlib/LexerBase.h index 02fc34dc..2998d244 100644 --- a/scintilla/lexlib/LexerBase.h +++ b/scintilla/lexlib/LexerBase.h @@ -20,7 +20,7 @@ protected: WordList *keyWordLists[numWordLists+1]; public: LexerBase(); - ~LexerBase(); + virtual ~LexerBase(); void SCI_METHOD Release(); int SCI_METHOD Version() const; const char * SCI_METHOD PropertyNames(); diff --git a/scintilla/lexlib/OptionSet.h b/scintilla/lexlib/OptionSet.h index 277ca7a3..873ac8b6 100644 --- a/scintilla/lexlib/OptionSet.h +++ b/scintilla/lexlib/OptionSet.h @@ -80,6 +80,8 @@ class OptionSet { names += name; } public: + virtual ~OptionSet() { + } void DefineProperty(const char *name, plcob pb, std::string description="") { nameToDef[name] = Option(pb, description); AppendName(name); diff --git a/scintilla/lexlib/SparseState.h b/scintilla/lexlib/SparseState.h new file mode 100644 index 00000000..94aa929e --- /dev/null +++ b/scintilla/lexlib/SparseState.h @@ -0,0 +1,110 @@ +// Scintilla source code edit control +/** @file SparseState.h + ** Hold lexer state that may change rarely. + ** This is often per-line state such as whether a particular type of section has been entered. + ** A state continues until it is changed. + **/ +// Copyright 2011 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef SPARSESTATE_H +#define SPARSESTATE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +template +class SparseState { + struct State { + int position; + T value; + State(int position_, T value_) : position(position_), value(value_) { + } + inline bool operator<(const State &other) const { + return position < other.position; + } + inline bool operator==(const State &other) const { + return (position == other.position) && (value == other.value); + } + }; + int positionFirst; + typedef std::vector stateVector; + stateVector states; + + typename stateVector::iterator Find(int position) { + State searchValue(position, T()); + return std::lower_bound(states.begin(), states.end(), searchValue); + } + +public: + SparseState(int positionFirst_=-1) { + positionFirst = positionFirst_; + } + void Set(int position, T value) { + Delete(position); + if ((states.size() == 0) || (value != states[states.size()-1].value)) { + states.push_back(State(position, value)); + } + } + T ValueAt(int position) { + if (!states.size()) + return T(); + if (position < states[0].position) + return T(); + typename stateVector::iterator low = Find(position); + if (low == states.end()) { + return states[states.size()-1].value; + } else { + if (low->position > position) { + --low; + } + return low->value; + } + } + bool Delete(int position) { + typename stateVector::iterator low = Find(position); + if (low != states.end()) { + states.erase(low, states.end()); + return true; + } + return false; + } + size_t size() const { + return states.size(); + } + + // Returns true if Merge caused a significant change + bool Merge(const SparseState &other, int ignoreAfter) { + // Changes caused beyond ignoreAfter are not significant + Delete(ignoreAfter+1); + + bool different = true; + bool changed = false; + typename stateVector::iterator low = Find(other.positionFirst); + if (static_cast(states.end() - low) == other.states.size()) { + // Same number in other as after positionFirst in this + different = !std::equal(low, states.end(), other.states.begin()); + } + if (different) { + if (low != states.end()) { + states.erase(low, states.end()); + changed = true; + } + typename stateVector::const_iterator startOther = other.states.begin(); + if (!states.empty() && states.back().value == startOther->value) + ++startOther; + if (startOther != other.states.end()) { + states.insert(states.end(), startOther, other.states.end()); + changed = true; + } + } + return changed; + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/scintilla/lexlib/WordList.cxx b/scintilla/lexlib/WordList.cxx index b50c6949..cda35ece 100644 --- a/scintilla/lexlib/WordList.cxx +++ b/scintilla/lexlib/WordList.cxx @@ -110,6 +110,11 @@ void WordList::Set(const char *s) { } } +/** Check whether a string is in the list. + * List elements are either exact matches or prefixes. + * Prefix elements start with '^' and match all strings that start with the rest of the element + * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'. + */ bool WordList::InList(const char *s) const { if (0 == words) return false; diff --git a/scintilla/scintilla_changes.patch b/scintilla/scintilla_changes.patch index 7e82d389..9ba54fa2 100644 --- a/scintilla/scintilla_changes.patch +++ b/scintilla/scintilla_changes.patch @@ -1,8 +1,8 @@ -A patch to Scintilla 2.22 containing our changes to Scintilla +A patch to Scintilla 2.25 containing our changes to Scintilla (removing unused lexers and an updated marshallers file). diff -Naur scintilla_orig/gtk/scintilla-marshal.c scintilla/gtk/scintilla-marshal.c ---- scintilla_orig/gtk/scintilla-marshal.c 2010-09-04 12:03:35.000000000 +0200 -+++ scintilla/gtk/scintilla-marshal.c 2008-12-06 12:11:33.000000000 +0100 +--- scintilla_orig/gtk/scintilla-marshal.c 2010-10-27 23:15:45.000000000 +0200 ++++ scintilla/gtk/scintilla-marshal.c 2011-04-03 17:42:59.000000000 +0200 @@ -35,8 +35,8 @@ #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 @@ -28,12 +28,13 @@ diff -Naur scintilla_orig/gtk/scintilla-marshal.c scintilla/gtk/scintilla-marsha { typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx ---- scintilla_orig/src/Catalogue.cxx 2010-09-04 12:03:35.000000000 +0200 -+++ scintilla/src/Catalogue.cxx 2010-11-21 18:00:07.000000000 +0100 -@@ -81,98 +81,41 @@ +--- scintilla_orig/src/Catalogue.cxx 2011-03-17 23:41:24.000000000 +0100 ++++ scintilla/src/Catalogue.cxx 2011-04-03 17:43:45.000000000 +0200 +@@ -81,100 +81,42 @@ //++Autogenerated -- run src/LexGen.py to regenerate //**\(\tLINK_LEXER(\*);\n\) +- LINK_LEXER(lmA68k); - LINK_LEXER(lmAbaqus); LINK_LEXER(lmAda); - LINK_LEXER(lmAns1); @@ -51,7 +52,7 @@ diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx - LINK_LEXER(lmClw); - LINK_LEXER(lmClwNoCase); LINK_LEXER(lmCmake); -- LINK_LEXER(lmCOBOL); + LINK_LEXER(lmCOBOL); - LINK_LEXER(lmConf); LINK_LEXER(lmCPP); - LINK_LEXER(lmCPPNoCase); @@ -86,6 +87,7 @@ diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx - LINK_LEXER(lmMatlab); - LINK_LEXER(lmMETAPOST); - LINK_LEXER(lmMMIXAL); +- LINK_LEXER(lmModula); - LINK_LEXER(lmMSSQL); - LINK_LEXER(lmMySQL); - LINK_LEXER(lmNimrod); diff --git a/scintilla/src/AutoComplete.cxx b/scintilla/src/AutoComplete.cxx index 32cf7b2e..f6a291fe 100644 --- a/scintilla/src/AutoComplete.cxx +++ b/scintilla/src/AutoComplete.cxx @@ -129,11 +129,11 @@ void AutoComplete::Select(const char *word) { size_t lenWord = strlen(word); int location = -1; const int maxItemLen=1000; - char item[maxItemLen]; int start = 0; // lower bound of the api array block to search int end = lb->Length() - 1; // upper bound of the api array block to search while ((start <= end) && (location == -1)) { // Binary searching loop int pivot = (start + end) / 2; + char item[maxItemLen]; lb->GetValue(pivot, item, maxItemLen); int cond; if (ignoreCase) diff --git a/scintilla/src/CallTip.cxx b/scintilla/src/CallTip.cxx index 18a52475..604304bf 100644 --- a/scintilla/src/CallTip.cxx +++ b/scintilla/src/CallTip.cxx @@ -29,6 +29,7 @@ CallTip::CallTip() { rectUp = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0); lineHeight = 1; + offsetMain = 0; startHighlight = 0; endHighlight = 0; tabSize = 0; @@ -45,6 +46,8 @@ CallTip::CallTip() { colourSel.desired = ColourDesired(0, 0, 0x80); colourShade.desired = ColourDesired(0, 0, 0); colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0); + codePage = 0; + clickPlace = 0; } CallTip::~CallTip() { diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx index bae33b97..34e6a99f 100644 --- a/scintilla/src/Document.cxx +++ b/scintilla/src/Document.cxx @@ -14,14 +14,6 @@ #include #include -// With Borland C++ 5.5, including includes Windows.h leading to defining -// FindText to FindTextA which makes calls here to Document::FindText fail. -#ifdef __BORLANDC__ -#ifdef FindText -#undef FindText -#endif -#endif - #include "Platform.h" #include "ILexer.h" @@ -95,7 +87,7 @@ void LexInterface::Colourise(int start, int end) { Document::Document() { refCount = 0; -#ifdef unix +#ifdef __unix__ eolMode = SC_EOL_LF; #else eolMode = SC_EOL_CRLF; @@ -552,7 +544,7 @@ int Document::NextPosition(int pos, int moveDir) const { // See http://msdn.microsoft.com/en-us/library/cc194792%28v=MSDN.10%29.aspx // http://msdn.microsoft.com/en-us/library/cc194790.aspx if ((pos - 1) <= posStartLine) { - return posStartLine - 1; + return pos - 1; } else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) { // Must actually be trail byte return pos - 2; @@ -1317,7 +1309,11 @@ long Document::FindText(int minPos, int maxPos, const char *search, //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); const int limitPos = Platform::Maximum(startPos, endPos); - int pos = forward ? startPos : (startPos - 1); + int pos = startPos; + if (!forward) { + // Back all of a character + pos = NextPosition(pos, increment); + } if (caseSensitive) { while (forward ? (pos < endSearch) : (pos >= endSearch)) { bool found = (pos + lengthFind) <= limitPos; @@ -1526,8 +1522,8 @@ void Document::EnsureStyledTo(int pos) { IncrementStyleClock(); if (pli && !pli->UseContainerLexing()) { int lineEndStyled = LineFromPosition(GetEndStyled()); - int endStyled = LineStart(lineEndStyled); - pli->Colourise(endStyled, pos); + int endStyledTo = LineStart(lineEndStyled); + pli->Colourise(endStyledTo, pos); } else { // Ask the watchers to style, and stop as soon as one responds. for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { diff --git a/scintilla/src/Document.h b/scintilla/src/Document.h index 78f00a76..ecdf5ff6 100644 --- a/scintilla/src/Document.h +++ b/scintilla/src/Document.h @@ -357,6 +357,7 @@ public: const WatcherWithUserData *GetWatchers() const { return watchers; } int GetLenWatchers() const { return lenWatchers; } + CharClassify::cc WordCharClass(unsigned char ch); bool IsWordPartSeparator(char ch); int WordPartLeft(int pos); int WordPartRight(int pos); @@ -368,7 +369,6 @@ public: int BraceMatch(int position, int maxReStyle); private: - CharClassify::cc WordCharClass(unsigned char ch); bool IsWordStartAt(int pos); bool IsWordEndAt(int pos); bool IsWordAt(int start, int end); diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index 46080557..bc5e80cc 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -16,14 +16,6 @@ #include #include -// With Borland C++ 5.5, including includes Windows.h leading to defining -// FindText to FindTextA which makes calls here to Document::FindText fail. -#ifdef __BORLANDC__ -#ifdef FindText -#undef FindText -#endif -#endif - #include "Platform.h" #include "ILexer.h" @@ -141,6 +133,9 @@ Editor::Editor() { lastXChosen = 0; lineAnchor = 0; originalAnchorPos = 0; + wordSelectAnchorStartPos = 0; + wordSelectAnchorEndPos = 0; + wordSelectInitialCaretPos = -1; primarySelection = true; @@ -183,7 +178,8 @@ Editor::Editor() { lengthForEncode = -1; - needUpdateUI = true; + needUpdateUI = 0; + ContainerNeedsUpdate(SC_UPDATE_CONTENT); braces[0] = invalidPosition; braces[1] = invalidPosition; bracesMatchStyle = STYLE_BRACEBAD; @@ -442,7 +438,10 @@ int Editor::LineFromLocation(Point pt) { } void Editor::SetTopLine(int topLineNew) { - topLine = topLineNew; + if (topLine != topLineNew) { + topLine = topLineNew; + ContainerNeedsUpdate(SC_UPDATE_V_SCROLL); + } posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); } @@ -706,17 +705,17 @@ void Editor::SetRectangularRange() { if (sel.selType == Selection::selThin) { xCaret = xAnchor; } - int lineAnchor = pdoc->LineFromPosition(sel.Rectangular().anchor.Position()); + int lineAnchorRect = pdoc->LineFromPosition(sel.Rectangular().anchor.Position()); int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position()); - int increment = (lineCaret > lineAnchor) ? 1 : -1; - for (int line=lineAnchor; line != lineCaret+increment; line += increment) { + int increment = (lineCaret > lineAnchorRect) ? 1 : -1; + for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) { SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor)); if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0) range.ClearVirtualSpace(); - if (line == lineAnchor) + if (line == lineAnchorRect) sel.SetSelection(range); else - sel.AddSelection(range); + sel.AddSelectionWithoutTrim(range); } } } @@ -749,7 +748,7 @@ void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSel lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position()); } } - needUpdateUI = true; + ContainerNeedsUpdate(SC_UPDATE_SELECTION); InvalidateRange(firstAffected, lastAffected); } @@ -990,6 +989,7 @@ void Editor::HorizontalScrollTo(int xPos) { xPos = 0; if ((wrapState == eWrapNone) && (xOffset != xPos)) { xOffset = xPos; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); SetHorizontalScrollPos(); RedrawRect(GetClientRectangle()); } @@ -1299,6 +1299,7 @@ void Editor::SetXYScroll(XYScrollPosition newXY) { } if (newXY.xOffset != xOffset) { xOffset = newXY.xOffset; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); if (newXY.xOffset > 0) { PRectangle rcText = GetTextRectangle(); if (horizontalScrollBarVisible && @@ -2042,7 +2043,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll->edgeColumn = -1; } - char styleByte = 0; + char styleByte; const int styleMask = pdoc->stylingBitsMask; ll->styleBitsSet = 0; // Fill base line layout @@ -3043,7 +3044,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } // Draw any translucent whole line states - rcSegment.left = xStart; + rcSegment.left = 0; rcSegment.right = rcLine.right - 1; if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) { SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha); @@ -3165,11 +3166,11 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { } pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); - pixmapSelPattern->PenColour(colourFMStripes); - for (int stripe = 0; stripe < patternSize; stripe++) { - // Alternating 1 pixel stripes is same as checkerboard. - pixmapSelPattern->MoveTo(0, stripe * 2); - pixmapSelPattern->LineTo(patternSize, stripe * 2 - patternSize); + 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); + } } } @@ -3183,10 +3184,9 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) { - pixmapIndentGuide->MoveTo(0, stripe); - pixmapIndentGuide->LineTo(2, stripe); - pixmapIndentGuideHighlight->MoveTo(0, stripe); - pixmapIndentGuideHighlight->LineTo(2, stripe); + PRectangle rcPixel(0, stripe, 1, stripe+1); + pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore.allocated); + pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore.allocated); } } @@ -3316,7 +3316,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { surfaceWindow->SetPalette(&palTemp, true); NotifyUpdateUI(); - needUpdateUI = false; + needUpdateUI = 0; RefreshStyleData(); RefreshPixMaps(surfaceWindow); @@ -3921,8 +3921,8 @@ void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) } } -void Editor::ClearSelection() { - if (!sel.IsRectangular()) +void Editor::ClearSelection(bool retainMultipleSelections) { + if (!sel.IsRectangular() && !retainMultipleSelections) FilterSelections(); UndoGroup ug(pdoc); for (size_t r=0; r 1); - SelectionPosition last; const char *eol = ""; int eolLen = 0; if (forLine) { @@ -5131,6 +5136,7 @@ int Editor::KeyCommand(unsigned int iMessage) { inOverstrike = !inOverstrike; DropCaret(); ShowCaretAtCurrentPosition(); + ContainerNeedsUpdate(SC_UPDATE_CONTENT); NotifyUpdateUI(); break; case SCI_CANCEL: // Cancel any modes - handled in subclass @@ -5230,6 +5236,7 @@ int Editor::KeyCommand(unsigned int iMessage) { UndoGroup ug(pdoc); sel.RangeMain().caret = SelectionPosition( InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); + sel.RangeMain().anchor = sel.RangeMain().caret; int endWord = pdoc->NextWordStart(sel.MainCaret(), 1); pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); } @@ -5836,6 +5843,16 @@ bool Editor::PointInSelMargin(Point pt) { } } +Window::Cursor Editor::GetMarginCursor(Point pt) { + int x = 0; + for (int margin = 0; margin < ViewStyle::margins; margin++) { + if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width)) + return static_cast(vs.ms[margin].cursor); + x += vs.ms[margin].width; + } + return Window::cursorReverseArrow; +} + void Editor::LineSelection(int lineCurrent_, int lineAnchor_) { if (lineAnchor_ < lineCurrent_) { SetSelection(pdoc->LineStart(lineCurrent_ + 1), @@ -5849,6 +5866,30 @@ void Editor::LineSelection(int lineCurrent_, int lineAnchor_) { } } +void Editor::WordSelection(int pos) { + if (pos < wordSelectAnchorStartPos) { + // Extend backward to the word containing pos. + // Skip ExtendWordSelect if the line is empty or if pos is after the last character. + // This ensures that a series of empty lines isn't counted as a single "word". + if (!pdoc->IsLineEndPosition(pos)) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1); + SetSelection(pos, wordSelectAnchorEndPos); + } else if (pos > wordSelectAnchorEndPos) { + // Extend forward to the word containing the character to the left of pos. + // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line. + // This ensures that a series of empty lines isn't counted as a single "word". + if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos))) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1); + SetSelection(pos, wordSelectAnchorStartPos); + } else { + // Select only the anchored word + if (pos >= originalAnchorPos) + SetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos); + else + SetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos); + } +} + void Editor::DwellEnd(bool mouseMoved) { if (mouseMoved) ticksToDwell = dwellDelay; @@ -5910,13 +5951,33 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b } if (selectionType == selWord) { - if (sel.MainCaret() >= originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); + int charPos = originalAnchorPos; + if (sel.MainCaret() == originalAnchorPos) { + charPos = PositionFromLocation(pt, false, true); + charPos = MovePositionOutsideChar(charPos, -1); } + + int startWord, endWord; + if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) { + startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1); + endWord = pdoc->ExtendWordSelect(charPos, 1); + } else { + // Selecting backwards, or anchor beyond last character on line. In these cases, + // we select the word containing the character to the *left* of the anchor. + if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) { + startWord = pdoc->ExtendWordSelect(charPos, -1); + endWord = pdoc->ExtendWordSelect(startWord, 1); + } else { + // Anchor at start of line; select nothing to begin with. + startWord = charPos; + endWord = charPos; + } + } + + wordSelectAnchorStartPos = startWord; + wordSelectAnchorEndPos = endWord; + wordSelectInitialCaretPos = sel.MainCaret(); + WordSelection(wordSelectInitialCaretPos); } else if (selectionType == selLine) { lineAnchor = LineFromLocation(pt); SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor)); @@ -5981,7 +6042,8 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b InvalidateSelection(SelectionRange(newPos), true); if (sel.Count() > 1) Redraw(); - sel.Clear(); + if ((sel.Count() > 1) || (sel.selType != Selection::selStream)) + sel.Clear(); sel.selType = alt ? Selection::selRectangle : Selection::selStream; SetSelection(newPos, newPos); } @@ -6098,7 +6160,7 @@ void Editor::ButtonMove(Point pt) { } } else if (selectionType == selWord) { // Continue selecting by word - if (movePos.Position() == originalAnchorPos) { // Didn't move + if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move // No need to do anything. Previously this case was lumped // in with "Moved forward", but that can be harmful in this // case: a handler for the NotifyDoubleClick re-adjusts @@ -6108,12 +6170,9 @@ void Editor::ButtonMove(Point pt) { // the ButtonMove() called via Tick() for auto-scrolling // could result in the fancier word selection adjustment // being unmade. - } else if (movePos.Position() > originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); + } else { + wordSelectInitialCaretPos = -1; + WordSelection(movePos.Position()); } } else { // Continue selecting by line @@ -6151,7 +6210,7 @@ void Editor::ButtonMove(Point pt) { } else { if (vs.fixedColumnWidth > 0) { // There is a margin if (PointInSelMargin(pt)) { - DisplayCursor(Window::cursorReverseArrow); + DisplayCursor(GetMarginCursor(pt)); SetHotSpotRange(NULL); return; // No need to test for selection } @@ -6177,6 +6236,8 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { if (inDragDrop == ddInitial) { inDragDrop = ddNone; SetEmptySelection(newPos.Position()); + selectionType = selChar; + originalAnchorPos = sel.MainCaret(); } if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) { hotSpotClickPos = INVALID_POSITION; @@ -6184,7 +6245,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { } if (HaveMouseCapture()) { if (PointInSelMargin(pt)) { - DisplayCursor(Window::cursorReverseArrow); + DisplayCursor(GetMarginCursor(pt)); } else { DisplayCursor(Window::cursorText); SetHotSpotRange(NULL); @@ -6344,7 +6405,7 @@ void Editor::IdleStyling() { if (needUpdateUI) { NotifyUpdateUI(); - needUpdateUI = false; + needUpdateUI = 0; } styleNeeded.Reset(); } @@ -7001,6 +7062,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETXOFFSET: xOffset = wParam; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); SetHorizontalScrollPos(); Redraw(); break; @@ -7315,7 +7377,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GOTOPOS: SetEmptySelection(wParam); EnsureCaretVisible(); - Redraw(); break; case SCI_GETCURLINE: { @@ -7466,6 +7527,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; } xOffset = 0; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); InvalidateStyleRedraw(); ReconfigureScrollBars(); break; @@ -7786,6 +7848,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { else return 0; + case SCI_SETMARGINCURSORN: + if (ValidMargin(wParam)) + vs.ms[wParam].cursor = lParam; + break; + + case SCI_GETMARGINCURSORN: + if (ValidMargin(wParam)) + return vs.ms[wParam].cursor; + else + return 0; + case SCI_STYLECLEARALL: vs.ClearStyles(); InvalidateStyleRedraw(); diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index 50948e2e..db8a36aa 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -201,6 +201,9 @@ protected: // ScintillaBase subclass needs access to much of Editor int lastXChosen; int lineAnchor; int originalAnchorPos; + int wordSelectAnchorStartPos; + int wordSelectAnchorEndPos; + int wordSelectInitialCaretPos; int targetStart; int targetEnd; int searchFlags; @@ -208,7 +211,7 @@ protected: // ScintillaBase subclass needs access to much of Editor int posTopLine; int lengthForEncode; - bool needUpdateUI; + int needUpdateUI; Position braces[2]; int bracesMatchStyle; int highlightGuideColumn; @@ -391,7 +394,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void AddChar(char ch); virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); void InsertPaste(SelectionPosition selStart, const char *text, int len); - void ClearSelection(); + void ClearSelection(bool retainMultipleSelections=false); void ClearAll(); void ClearDocumentStyle(); void Cut(); @@ -438,6 +441,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void NotifyErrorOccurred(Document *doc, void *userData, int status); void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + void ContainerNeedsUpdate(int flags); void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false); enum { cmSame, cmUpper, cmLower } caseMap; virtual std::string CaseMapString(const std::string &s, int caseMapping); @@ -479,7 +483,9 @@ protected: // ScintillaBase subclass needs access to much of Editor bool PositionInSelection(int pos); bool PointInSelection(Point pt); bool PointInSelMargin(Point pt); + Window::Cursor GetMarginCursor(Point pt); void LineSelection(int lineCurrent_, int lineAnchor_); + void WordSelection(int pos); void DwellEnd(bool mouseMoved); void MouseLeave(); virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); diff --git a/scintilla/src/ExternalLexer.cxx b/scintilla/src/ExternalLexer.cxx index 02b7eaa8..bb484649 100644 --- a/scintilla/src/ExternalLexer.cxx +++ b/scintilla/src/ExternalLexer.cxx @@ -38,7 +38,6 @@ LexerManager *LexerManager::theInstance = NULL; void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { fneFactory = fFactory; fnFactory = fFactory(index); - externalLanguage = index; } //------------------------------------------ diff --git a/scintilla/src/ExternalLexer.h b/scintilla/src/ExternalLexer.h index 98d543ef..bf175a63 100644 --- a/scintilla/src/ExternalLexer.h +++ b/scintilla/src/ExternalLexer.h @@ -27,11 +27,12 @@ typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned i class ExternalLexerModule : public LexerModule { protected: GetLexerFactoryFunction fneFactory; - int externalLanguage; char name[100]; public: ExternalLexerModule(int language_, LexerFunction fnLexer_, - const char *languageName_=0, LexerFunction fnFolder_=0) : LexerModule(language_, fnLexer_, 0, fnFolder_) { + const char *languageName_=0, LexerFunction fnFolder_=0) : + LexerModule(language_, fnLexer_, 0, fnFolder_), + fneFactory(0) { strncpy(name, languageName_, sizeof(name)); name[sizeof(name)-1] = '\0'; languageName = name; diff --git a/scintilla/src/Partitioning.h b/scintilla/src/Partitioning.h index 17925b92..07f3c5d7 100644 --- a/scintilla/src/Partitioning.h +++ b/scintilla/src/Partitioning.h @@ -42,6 +42,10 @@ public: /// Divide an interval into multiple partitions. /// Useful for breaking a document down into sections such as lines. +/// A 0 length interval has a single 0 length partition, numbered 0 +/// If interval not 0 length then each partition non-zero length +/// When needed, positions after the interval are considered part of the last partition +/// but the end of the last partition can be found with PositionFromPartition(last+1). class Partitioning { private: @@ -153,6 +157,7 @@ public: return pos; } + /// Return value in range [0 .. Partitions() - 1] even for arguments outside interval int PartitionFromPosition(int pos) const { if (body->Length() <= 1) return 0; diff --git a/scintilla/src/PositionCache.cxx b/scintilla/src/PositionCache.cxx index 548b4d94..2ed15245 100644 --- a/scintilla/src/PositionCache.cxx +++ b/scintilla/src/PositionCache.cxx @@ -68,6 +68,8 @@ LineLayout::LineLayout(int maxLineLength_) : widthLine(wrapWidthInfinite), lines(1), wrapIndent(0) { + bracePreviousStyles[0] = 0; + bracePreviousStyles[1] = 0; Resize(maxLineLength_); } diff --git a/scintilla/src/RunStyles.cxx b/scintilla/src/RunStyles.cxx index ae32c738..460d5d24 100644 --- a/scintilla/src/RunStyles.cxx +++ b/scintilla/src/RunStyles.cxx @@ -147,8 +147,10 @@ bool RunStyles::FillRange(int &position, int value, int &fillLength) { runEnd = RunFromPosition(end); RemoveRunIfSameAsPrevious(runEnd); RemoveRunIfSameAsPrevious(runStart); + return true; + } else { + return false; } - return true; } void RunStyles::SetValueAt(int position, int value) { diff --git a/scintilla/src/Selection.cxx b/scintilla/src/Selection.cxx index 6f3267df..305d7219 100644 --- a/scintilla/src/Selection.cxx +++ b/scintilla/src/Selection.cxx @@ -20,6 +20,9 @@ using namespace Scintilla; #endif void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) { + if (position == startChange) { + virtualSpace = 0; + } if (insertion) { if (position > startChange) { position += length; @@ -31,6 +34,7 @@ void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int position -= length; } else { position = startChange; + virtualSpace = 0; } } } @@ -291,6 +295,11 @@ void Selection::AddSelection(SelectionRange range) { mainRange = ranges.size() - 1; } +void Selection::AddSelectionWithoutTrim(SelectionRange range) { + ranges.push_back(range); + mainRange = ranges.size() - 1; +} + void Selection::TentativeSelection(SelectionRange range) { if (!tentativeMain) { rangesSaved = ranges; diff --git a/scintilla/src/Selection.h b/scintilla/src/Selection.h index bb292664..d7c7d79a 100644 --- a/scintilla/src/Selection.h +++ b/scintilla/src/Selection.h @@ -60,7 +60,7 @@ public: struct SelectionSegment { SelectionPosition start; SelectionPosition end; - SelectionSegment() { + SelectionSegment() : start(), end() { } SelectionSegment(SelectionPosition a, SelectionPosition b) { if (a < b) { @@ -86,7 +86,7 @@ struct SelectionRange { SelectionPosition caret; SelectionPosition anchor; - SelectionRange() { + SelectionRange() : caret(), anchor() { } SelectionRange(SelectionPosition single) : caret(single), anchor(single) { } @@ -166,6 +166,7 @@ public: void TrimSelection(SelectionRange range); void SetSelection(SelectionRange range); void AddSelection(SelectionRange range); + void AddSelectionWithoutTrim(SelectionRange range); void TentativeSelection(SelectionRange range); void CommitTentative(); int CharacterInSelection(int posCharacter) const; diff --git a/scintilla/src/SplitVector.h b/scintilla/src/SplitVector.h index 2e17ba3d..44d5ddc0 100644 --- a/scintilla/src/SplitVector.h +++ b/scintilla/src/SplitVector.h @@ -238,7 +238,7 @@ public: DeleteRange(0, lengthBody); } - // Retrieve a range of elemetns into an array + // Retrieve a range of elements into an array void GetRange(T *buffer, int position, int retrieveLength) const { // Split into up to 2 ranges, before and after the split then use memcpy on each. int range1Length = 0; diff --git a/scintilla/src/ViewStyle.cxx b/scintilla/src/ViewStyle.cxx index 1b315d17..78ba1f78 100644 --- a/scintilla/src/ViewStyle.cxx +++ b/scintilla/src/ViewStyle.cxx @@ -24,7 +24,7 @@ using namespace Scintilla; #endif MarginStyle::MarginStyle() : - style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false) { + style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) { } // A list of the fontnames - avoids wasting space in each style diff --git a/scintilla/src/ViewStyle.h b/scintilla/src/ViewStyle.h index cd6dc1a2..6ca488df 100644 --- a/scintilla/src/ViewStyle.h +++ b/scintilla/src/ViewStyle.h @@ -20,6 +20,7 @@ public: int width; int mask; bool sensitive; + int cursor; MarginStyle(); };