Update Scintilla to version 2.25.

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5682 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2011-04-03 16:16:52 +00:00
parent 4ffcfbba6c
commit c0b726a298
59 changed files with 1816 additions and 319 deletions

View File

@ -1,3 +1,9 @@
2011-04-03 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* scintilla/*:
Update Scintilla to version 2.25.
2011-04-03 Colomban Wendling <colomban(at)geany(dot)org> 2011-04-03 Colomban Wendling <colomban(at)geany(dot)org>
* src/main.c, src/prefs.c, src/tools.c: * src/main.c, src/prefs.c, src/tools.c:

View File

@ -61,6 +61,7 @@ lexlib/LexerSimple.h \
lexlib/OptionSet.h \ lexlib/OptionSet.h \
lexlib/PropSetSimple.cxx \ lexlib/PropSetSimple.cxx \
lexlib/PropSetSimple.h \ lexlib/PropSetSimple.h \
lexlib/SparseState.h \
lexlib/StyleContext.cxx \ lexlib/StyleContext.cxx \
lexlib/StyleContext.h \ lexlib/StyleContext.h \
lexlib/WordList.cxx \ lexlib/WordList.cxx \

View File

@ -7,6 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <math.h>
#include <glib.h> #include <glib.h>
#include <gmodule.h> #include <gmodule.h>
@ -39,6 +40,14 @@
#define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w)) #define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w))
#endif #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 #ifdef _MSC_VER
// Ignore unreferenced local functions in GTK+ headers // Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505) #pragma warning(disable: 4505)
@ -688,9 +697,14 @@ namespace Scintilla {
#endif #endif
class SurfaceImpl : public Surface { class SurfaceImpl : public Surface {
encodingType et; encodingType et;
#ifdef USE_CAIRO
cairo_t *context;
cairo_surface_t *psurf;
#else
GdkDrawable *drawable; GdkDrawable *drawable;
GdkGC *gc; GdkGC *gc;
GdkPixmap *ppixmap; GdkPixmap *ppixmap;
#endif
int x; int x;
int y; int y;
bool inited; 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) x(0), y(0), inited(false), createdGC(false)
, pcontext(0), layout(0), characterSet(-1) { , pcontext(0), layout(0), characterSet(-1) {
} }
@ -817,15 +839,28 @@ SurfaceImpl::~SurfaceImpl() {
void SurfaceImpl::Release() { void SurfaceImpl::Release() {
et = singleByte; et = singleByte;
#ifndef USE_CAIRO
drawable = 0; drawable = 0;
#endif
if (createdGC) { if (createdGC) {
createdGC = false; createdGC = false;
#ifdef USE_CAIRO
cairo_destroy(context);
#else
g_object_unref(gc); g_object_unref(gc);
#endif
} }
#ifdef USE_CAIRO
context = 0;
if (psurf)
cairo_surface_destroy(psurf);
psurf = 0;
#else
gc = 0; gc = 0;
if (ppixmap) if (ppixmap)
g_object_unref(ppixmap); g_object_unref(ppixmap);
ppixmap = 0; ppixmap = 0;
#endif
if (layout) if (layout)
g_object_unref(layout); g_object_unref(layout);
layout = 0; layout = 0;
@ -847,10 +882,28 @@ bool SurfaceImpl::Initialised() {
void SurfaceImpl::Init(WindowID wid) { void SurfaceImpl::Init(WindowID wid) {
Release(); Release();
PLATFORM_ASSERT(wid); 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)); pcontext = gtk_widget_create_pango_context(PWidget(wid));
PLATFORM_ASSERT(pcontext); PLATFORM_ASSERT(pcontext);
layout = pango_layout_new(pcontext); layout = pango_layout_new(pcontext);
PLATFORM_ASSERT(layout); PLATFORM_ASSERT(layout);
#endif
inited = true; inited = true;
} }
@ -859,12 +912,27 @@ void SurfaceImpl::Init(SurfaceID sid, WindowID wid) {
GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid); GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);
Release(); Release();
PLATFORM_ASSERT(wid); 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)); pcontext = gtk_widget_create_pango_context(PWidget(wid));
layout = pango_layout_new(pcontext); layout = pango_layout_new(pcontext);
drawable = drawable_; 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 // 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); gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
#endif
createdGC = true; createdGC = true;
inited = true; inited = true;
} }
@ -873,8 +941,23 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID
PLATFORM_ASSERT(surface_); PLATFORM_ASSERT(surface_);
Release(); Release();
SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_); SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
PLATFORM_ASSERT(surfImpl->drawable);
PLATFORM_ASSERT(wid); 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)); pcontext = gtk_widget_create_pango_context(PWidget(wid));
PLATFORM_ASSERT(pcontext); PLATFORM_ASSERT(pcontext);
layout = pango_layout_new(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) if (height > 0 && width > 0)
ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1); ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1);
drawable = ppixmap; 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 // 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); gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
#endif
createdGC = true; createdGC = true;
inited = true; inited = true;
} }
void SurfaceImpl::PenColour(ColourAllocated fore) { 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) { if (gc) {
GdkColor co; GdkColor co;
co.pixel = fore.AsLong(); co.pixel = fore.AsLong();
gdk_gc_set_foreground(gc, &co); gdk_gc_set_foreground(gc, &co);
} }
#endif
} }
int SurfaceImpl::LogPixelsY() { int SurfaceImpl::LogPixelsY() {
@ -911,18 +1017,71 @@ void SurfaceImpl::MoveTo(int x_, int y_) {
y = 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_) { 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) { if (drawable && gc) {
gdk_draw_line(drawable, gc, gdk_draw_line(drawable, gc,
x, y, x, y,
x_, y_); x_, y_);
} }
#endif
x = x_; x = x_;
y = y_; y = y_;
} }
void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore,
ColourAllocated back) { 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]; GdkPoint gpts[20];
if (npts < static_cast<int>((sizeof(gpts) / sizeof(gpts[0])))) { if (npts < static_cast<int>((sizeof(gpts) / sizeof(gpts[0])))) {
for (int i = 0;i < npts;i++) { for (int i = 0;i < npts;i++) {
@ -934,35 +1093,62 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore,
PenColour(fore); PenColour(fore);
gdk_draw_polygon(drawable, gc, 0, gpts, npts); gdk_draw_polygon(drawable, gc, 0, gpts, npts);
} }
#endif
} }
void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
#ifdef USE_CAIRO
if (context) {
#else
if (gc && drawable) { 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); PenColour(back);
gdk_draw_rectangle(drawable, gc, 1, gdk_draw_rectangle(drawable, gc, 1,
rc.left + 1, rc.top + 1, rc.left + 1, rc.top + 1,
rc.right - rc.left - 2, rc.bottom - rc.top - 2); rc.right - rc.left - 2, rc.bottom - rc.top - 2);
PenColour(fore); PenColour(fore);
// The subtraction of 1 off the width and height here shouldn't be needed but // 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 // otherwise a different rectangle is drawn than would be done if the fill parameter == 1
gdk_draw_rectangle(drawable, gc, 0, gdk_draw_rectangle(drawable, gc, 0,
rc.left, rc.top, rc.left, rc.top,
rc.right - rc.left - 1, rc.bottom - rc.top - 1); rc.right - rc.left - 1, rc.bottom - rc.top - 1);
#endif
} }
} }
void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
PenColour(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 if (drawable && (rc.left < maxCoordinate)) { // Protect against out of range
gdk_draw_rectangle(drawable, gc, 1, gdk_draw_rectangle(drawable, gc, 1,
rc.left, rc.top, rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top); rc.right - rc.left, rc.bottom - rc.top);
} }
#endif
} }
void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
if (static_cast<SurfaceImpl &>(surfacePattern).drawable) { SurfaceImpl &surfi = static_cast<SurfaceImpl &>(surfacePattern);
#ifdef USE_CAIRO
bool canDraw = surfi.psurf;
#else
bool canDraw = surfi.drawable;
#endif
if (canDraw) {
// Tile pattern over rectangle // Tile pattern over rectangle
// Currently assumes 8x8 pattern // Currently assumes 8x8 pattern
int widthPat = 8; int widthPat = 8;
@ -971,12 +1157,18 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat; int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) { for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
int heighty = (yTile + heightPat > rc.bottom) ? 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, gdk_draw_drawable(drawable,
gc, gc,
static_cast<SurfaceImpl &>(surfacePattern).drawable, static_cast<SurfaceImpl &>(surfacePattern).drawable,
0, 0, 0, 0,
xTile, yTile, xTile, yTile,
widthx, heighty); widthx, heighty);
#endif
} }
} }
} else { } 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 // 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) { static void AllFour(guint32 *pixels, int stride, int width, int height, int x, int y, guint32 val) {
pixels[y*stride+x] = 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; 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) { static guint32 u32FromRGBA(guint8 r, guint8 g, guint8 b, guint8 a) {
union { union {
guint8 pixVal[4]; guint8 pixVal[4];
@ -1037,8 +1232,41 @@ static guint32 u32FromRGBA(guint8 r, guint8 g, guint8 b, guint8 a) {
return converter.val; 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, void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int flags) { 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) { if (gc && drawable && rc.Width() > 0) {
int width = rc.Width(); int width = rc.Width();
int height = rc.Height(); int height = rc.Height();
@ -1078,10 +1306,18 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated
g_object_unref(pixalpha); g_object_unref(pixalpha);
} }
#endif
} }
void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(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, gdk_draw_arc(drawable, gc, 1,
rc.left + 1, rc.top + 1, rc.left + 1, rc.top + 1,
rc.right - rc.left - 2, rc.bottom - rc.top - 2, 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.left, rc.top,
rc.right - rc.left - 1, rc.bottom - rc.top - 1, rc.right - rc.left - 1, rc.bottom - rc.top - 1,
0, 32767); 0, 32767);
#endif
} }
void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
if (static_cast<SurfaceImpl &>(surfaceSource).drawable) { SurfaceImpl &surfi = static_cast<SurfaceImpl &>(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, gdk_draw_drawable(drawable,
gc, gc,
static_cast<SurfaceImpl &>(surfaceSource).drawable, static_cast<SurfaceImpl &>(surfaceSource).drawable,
from.x, from.y, from.x, from.y,
rc.left, rc.top, rc.left, rc.top,
rc.right - rc.left, rc.bottom - 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, void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len,
ColourAllocated fore) { ColourAllocated fore) {
PenColour(fore); PenColour(fore);
#ifdef USE_CAIRO
if (context) {
#else
if (gc && drawable) { if (gc && drawable) {
#endif
int xText = rc.left; int xText = rc.left;
if (PFont(font_)->pfd) { if (PFont(font_)->pfd) {
char *utfForm = 0; 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_text(layout, utfForm, len);
} }
pango_layout_set_font_description(layout, PFont(font_)->pfd); pango_layout_set_font_description(layout, PFont(font_)->pfd);
#ifdef USE_CAIRO
pango_cairo_update_layout(context, layout);
#endif
#ifdef PANGO_VERSION #ifdef PANGO_VERSION
PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0); PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0);
#else #else
PangoLayoutLine *pll = pango_layout_get_line(layout,0); PangoLayoutLine *pll = pango_layout_get_line(layout,0);
#endif #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); gdk_draw_layout_line(drawable, gc, xText, ybase, pll);
#endif
if (useGFree) { if (useGFree) {
g_free(utfForm); g_free(utfForm);
} else { } else {
@ -1717,9 +1979,14 @@ int SurfaceImpl::SetPalette(Palette *, bool) {
} }
void SurfaceImpl::SetClip(PRectangle rc) { 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, GdkRectangle area = {rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top}; rc.right - rc.left, rc.bottom - rc.top};
gdk_gc_set_clip_rectangle(gc, &area); gdk_gc_set_clip_rectangle(gc, &area);
#endif
} }
void SurfaceImpl::FlushCachedState() {} void SurfaceImpl::FlushCachedState() {}
@ -1875,7 +2142,6 @@ void Window::SetTitle(const char *s) {
gdk window coordinates */ gdk window coordinates */
PRectangle Window::GetMonitorRect(Point pt) { PRectangle Window::GetMonitorRect(Point pt) {
gint x_offset, y_offset; gint x_offset, y_offset;
pt = pt;
gdk_window_get_origin(PWidget(wid)->window, &x_offset, &y_offset); 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); return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
} }
#else #else
pt = pt;
return PRectangle(-x_offset, -y_offset, (-x_offset) + gdk_screen_width(), return PRectangle(-x_offset, -y_offset, (-x_offset) + gdk_screen_width(),
(-y_offset) + gdk_screen_height()); (-y_offset) + gdk_screen_height());
#endif #endif
@ -1936,7 +2203,7 @@ public:
CallBackAction doubleClickAction; CallBackAction doubleClickAction;
void *doubleClickActionData; void *doubleClickActionData;
ListBoxX() : list(0), pixhash(NULL), pixbuf_renderer(0), ListBoxX() : list(0), scroller(0), pixhash(NULL), pixbuf_renderer(0),
desiredVisibleRows(5), maxItemCharacters(0), desiredVisibleRows(5), maxItemCharacters(0),
aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) { aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) {
} }

View File

@ -75,6 +75,10 @@
#define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w)) #define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w))
#endif #endif
#if GTK_CHECK_VERSION(2,22,0)
#define USE_CAIRO 1
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
// Constant conditional expressions are because of GTK+ headers // Constant conditional expressions are because of GTK+ headers
#pragma warning(disable: 4127) #pragma warning(disable: 4127)
@ -531,7 +535,6 @@ void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internal
gint ScintillaGTK::FocusInThis(GtkWidget *widget) { gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
try { try {
GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
SetFocusState(true); SetFocusState(true);
if (im_context != NULL) { if (im_context != NULL) {
gchar *str = NULL; gchar *str = NULL;
@ -562,7 +565,6 @@ gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
gint ScintillaGTK::FocusOutThis(GtkWidget *widget) { gint ScintillaGTK::FocusOutThis(GtkWidget *widget) {
try { try {
GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
SetFocusState(false); SetFocusState(false);
if (PWidget(wPreedit) != NULL) if (PWidget(wPreedit) != NULL)
@ -1422,7 +1424,7 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
UndoGroup ug(pdoc); UndoGroup ug(pdoc);
if (selection_data->selection != GDK_SELECTION_PRIMARY) { if (selection_data->selection != GDK_SELECTION_PRIMARY) {
ClearSelection(); ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
} }
SelectionPosition selStart = sel.IsRectangular() ? SelectionPosition selStart = sel.IsRectangular() ?
sel.Rectangular().Start() : sel.Rectangular().Start() :
@ -1983,6 +1985,7 @@ gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose)
PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str); PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
pango_layout_set_attributes(layout, attrs); pango_layout_set_attributes(layout, attrs);
#ifndef USE_CAIRO
GdkGC *gc = gdk_gc_new(widget->window); GdkGC *gc = gdk_gc_new(widget->window);
GdkColor color[2] = { {0, 0x0000, 0x0000, 0x0000}, GdkColor color[2] = { {0, 0x0000, 0x0000, 0x0000},
{0, 0xffff, 0xffff, 0xffff} {0, 0xffff, 0xffff, 0xffff}
@ -1997,8 +2000,8 @@ gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose)
gdk_gc_set_foreground(gc, color); gdk_gc_set_foreground(gc, color);
gdk_gc_set_background(gc, color + 1); gdk_gc_set_background(gc, color + 1);
gdk_draw_layout(widget->window, gc, 0, 0, layout); gdk_draw_layout(widget->window, gc, 0, 0, layout);
g_object_unref(gc); g_object_unref(gc);
#endif
g_free(str); g_free(str);
pango_attr_list_unref(attrs); pango_attr_list_unref(attrs);
g_object_unref(layout); g_object_unref(layout);

View File

@ -35,8 +35,8 @@
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong #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_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 #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_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint #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_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double #define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
@ -50,10 +50,10 @@
/* NONE:INT,POINTER (scintilla-marshal.list:1) */ /* NONE:INT,POINTER (scintilla-marshal.list:1) */
void void
scintilla_marshal_VOID__INT_POINTER (GClosure *closure, scintilla_marshal_VOID__INT_POINTER (GClosure *closure,
GValue *return_value, GValue *return_value G_GNUC_UNUSED,
guint n_param_values, guint n_param_values,
const GValue *param_values, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint G_GNUC_UNUSED,
gpointer marshal_data) gpointer marshal_data)
{ {
typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1,

View File

@ -255,8 +255,8 @@ class Palette {
int allocatedLen; int allocatedLen;
#endif #endif
// Private so Palette objects can not be copied // Private so Palette objects can not be copied
Palette(const Palette &) {} Palette(const Palette &);
Palette &operator=(const Palette &) { return *this; } Palette &operator=(const Palette &);
public: public:
#if PLAT_WIN #if PLAT_WIN
void *hpal; void *hpal;
@ -288,8 +288,8 @@ protected:
int ascent; int ascent;
#endif #endif
// Private so Font objects can not be copied // Private so Font objects can not be copied
Font(const Font &) {} Font(const Font &);
Font &operator=(const Font &) { fid=0; return *this; } Font &operator=(const Font &);
public: public:
Font(); Font();
virtual ~Font(); virtual ~Font();

View File

@ -112,6 +112,8 @@
#define SCLEX_SML 97 #define SCLEX_SML 97
#define SCLEX_MARKDOWN 98 #define SCLEX_MARKDOWN 98
#define SCLEX_TXT2TAGS 99 #define SCLEX_TXT2TAGS 99
#define SCLEX_A68K 100
#define SCLEX_MODULA 101
#define SCLEX_AUTOMATIC 1000 #define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0 #define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1 #define SCE_P_COMMENTLINE 1
@ -149,6 +151,8 @@
#define SCE_C_COMMENTDOCKEYWORD 17 #define SCE_C_COMMENTDOCKEYWORD 17
#define SCE_C_COMMENTDOCKEYWORDERROR 18 #define SCE_C_COMMENTDOCKEYWORDERROR 18
#define SCE_C_GLOBALCLASS 19 #define SCE_C_GLOBALCLASS 19
#define SCE_C_STRINGRAW 20
#define SCE_C_TRIPLEVERBATIM 21
#define SCE_D_DEFAULT 0 #define SCE_D_DEFAULT 0
#define SCE_D_COMMENT 1 #define SCE_D_COMMENT 1
#define SCE_D_COMMENTLINE 2 #define SCE_D_COMMENTLINE 2
@ -601,6 +605,7 @@
#define SCE_ASM_CHARACTER 12 #define SCE_ASM_CHARACTER 12
#define SCE_ASM_STRINGEOL 13 #define SCE_ASM_STRINGEOL 13
#define SCE_ASM_EXTINSTRUCTION 14 #define SCE_ASM_EXTINSTRUCTION 14
#define SCE_ASM_COMMENTDIRECTIVE 15
#define SCE_F_DEFAULT 0 #define SCE_F_DEFAULT 0
#define SCE_F_COMMENT 1 #define SCE_F_COMMENT 1
#define SCE_F_NUMBER 2 #define SCE_F_NUMBER 2
@ -1415,6 +1420,43 @@
#define SCE_TXT2TAGS_OPTION 23 #define SCE_TXT2TAGS_OPTION 23
#define SCE_TXT2TAGS_PREPROC 24 #define SCE_TXT2TAGS_PREPROC 24
#define SCE_TXT2TAGS_POSTPROC 25 #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 */ /* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif #endif

View File

@ -159,6 +159,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETMARGINMASKN 2245 #define SCI_GETMARGINMASKN 2245
#define SCI_SETMARGINSENSITIVEN 2246 #define SCI_SETMARGINSENSITIVEN 2246
#define SCI_GETMARGINSENSITIVEN 2247 #define SCI_GETMARGINSENSITIVEN 2247
#define SCI_SETMARGINCURSORN 2248
#define SCI_GETMARGINCURSORN 2249
#define STYLE_DEFAULT 32 #define STYLE_DEFAULT 32
#define STYLE_LINENUMBER 33 #define STYLE_LINENUMBER 33
#define STYLE_BRACELIGHT 34 #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_SETMOUSEDOWNCAPTURES 2384
#define SCI_GETMOUSEDOWNCAPTURES 2385 #define SCI_GETMOUSEDOWNCAPTURES 2385
#define SC_CURSORNORMAL -1 #define SC_CURSORNORMAL -1
#define SC_CURSORARROW 2
#define SC_CURSORWAIT 4 #define SC_CURSORWAIT 4
#define SC_CURSORREVERSEARROW 7
#define SCI_SETCURSOR 2386 #define SCI_SETCURSOR 2386
#define SCI_GETCURSOR 2387 #define SCI_GETCURSOR 2387
#define SCI_SETCONTROLCHARSYMBOL 2388 #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_CONTAINER 0x40000
#define SC_MOD_LEXERSTATE 0x80000 #define SC_MOD_LEXERSTATE 0x80000
#define SC_MODEVENTMASKALL 0xFFFFF #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_CHANGE 768
#define SCEN_SETFOCUS 512 #define SCEN_SETFOCUS 512
#define SCEN_KILLFOCUS 256 #define SCEN_KILLFOCUS 256
@ -971,6 +979,7 @@ struct SCNotification {
int y; /* SCN_DWELLSTART, SCN_DWELLEND */ int y; /* SCN_DWELLSTART, SCN_DWELLEND */
int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */
int annotationLinesAdded; /* SC_MOD_CHANGEANNOTATION */ int annotationLinesAdded; /* SC_MOD_CHANGEANNOTATION */
int updated; /* SCN_UPDATEUI */
}; };
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE

View File

@ -352,6 +352,12 @@ set void SetMarginSensitiveN=2246(int margin, bool sensitive)
# Retrieve the mouse click sensitivity of a margin. # Retrieve the mouse click sensitivity of a margin.
get bool GetMarginSensitiveN=2247(int 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. # 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. # Style 39 is for future use.
enu StylesCommon=STYLE_ enu StylesCommon=STYLE_
@ -1540,7 +1546,9 @@ get bool GetMouseDownCaptures=2385(,)
enu CursorShape=SC_CURSOR enu CursorShape=SC_CURSOR
val SC_CURSORNORMAL=-1 val SC_CURSORNORMAL=-1
val SC_CURSORARROW=2
val SC_CURSORWAIT=4 val SC_CURSORWAIT=4
val SC_CURSORREVERSEARROW=7
# Sets the cursor to one of the SC_CURSOR* values. # Sets the cursor to one of the SC_CURSOR* values.
set void SetCursor=2386(int cursorType,) set void SetCursor=2386(int cursorType,)
# Get cursor type. # Get cursor type.
@ -2193,6 +2201,12 @@ val SC_MOD_CONTAINER=0x40000
val SC_MOD_LEXERSTATE=0x80000 val SC_MOD_LEXERSTATE=0x80000
val SC_MODEVENTMASKALL=0xFFFFF 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 # For compatibility, these go through the COMMAND notification rather than NOTIFY
# and should have had exactly the same values as the EN_* constants. # and should have had exactly the same values as the EN_* constants.
# Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_* # Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_*
@ -2335,6 +2349,8 @@ val SCLEX_NIMROD=96
val SCLEX_SML=97 val SCLEX_SML=97
val SCLEX_MARKDOWN=98 val SCLEX_MARKDOWN=98
val SCLEX_TXT2TAGS=99 val SCLEX_TXT2TAGS=99
val SCLEX_A68K=100
val SCLEX_MODULA=101
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1. # 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_COMMENTDOCKEYWORD=17
val SCE_C_COMMENTDOCKEYWORDERROR=18 val SCE_C_COMMENTDOCKEYWORDERROR=18
val SCE_C_GLOBALCLASS=19 val SCE_C_GLOBALCLASS=19
val SCE_C_STRINGRAW=20
val SCE_C_TRIPLEVERBATIM=21
# Lexical states for SCLEX_D # Lexical states for SCLEX_D
lex D=SCLEX_D SCE_D_ lex D=SCLEX_D SCE_D_
val SCE_D_DEFAULT=0 val SCE_D_DEFAULT=0
@ -2900,6 +2918,7 @@ val SCE_ASM_COMMENTBLOCK=11
val SCE_ASM_CHARACTER=12 val SCE_ASM_CHARACTER=12
val SCE_ASM_STRINGEOL=13 val SCE_ASM_STRINGEOL=13
val SCE_ASM_EXTINSTRUCTION=14 val SCE_ASM_EXTINSTRUCTION=14
val SCE_ASM_COMMENTDIRECTIVE=15
# Lexical states for SCLEX_FORTRAN # Lexical states for SCLEX_FORTRAN
lex Fortran=SCLEX_FORTRAN SCE_F_ lex Fortran=SCLEX_FORTRAN SCE_F_
lex F77=SCLEX_F77 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_OPTION=23
val SCE_TXT2TAGS_PREPROC=24 val SCE_TXT2TAGS_PREPROC=24
val SCE_TXT2TAGS_POSTPROC=25 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 # Events

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -4,6 +4,7 @@
** Written by The Black Horus ** Written by The Black Horus
** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10
** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring ** 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" <dlchnr(at)gmx(dot)net>
**/ **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
@ -15,17 +16,24 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <string>
#include <map>
#include <set>
#include "ILexer.h" #include "ILexer.h"
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h" #include "StyleContext.h"
#include "CharacterSet.h" #include "CharacterSet.h"
#include "LexerModule.h" #include "LexerModule.h"
#include "OptionSet.h"
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
@ -54,15 +62,184 @@ static inline bool IsAsmOperator(const int ch) {
return false; return false;
} }
static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], static bool IsStreamCommentStyle(int style) {
Accessor &styler) { return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK;
}
WordList &cpuInstruction = *keywordlists[0]; static inline int LowerCase(int c) {
WordList &mathInstruction = *keywordlists[1]; if (c >= 'A' && c <= 'Z')
WordList &registers = *keywordlists[2]; return 'a' + c - 'A';
WordList &directive = *keywordlists[3]; return c;
WordList &directiveOperand = *keywordlists[4]; }
WordList &extInstruction = *keywordlists[5];
// 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<OptionsAsm> {
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 = &registers;
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 // Do not leak onto next line
if (initStyle == SCE_ASM_STRINGEOL) if (initStyle == SCE_ASM_STRINGEOL)
@ -96,7 +273,7 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo
if (!IsAsmOperator(sc.ch)) { if (!IsAsmOperator(sc.ch)) {
sc.SetState(SCE_ASM_DEFAULT); sc.SetState(SCE_ASM_DEFAULT);
} }
}else if (sc.state == SCE_ASM_NUMBER) { } else if (sc.state == SCE_ASM_NUMBER) {
if (!IsAWordChar(sc.ch)) { if (!IsAWordChar(sc.ch)) {
sc.SetState(SCE_ASM_DEFAULT); sc.SetState(SCE_ASM_DEFAULT);
} }
@ -104,6 +281,7 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo
if (!IsAWordChar(sc.ch) ) { if (!IsAWordChar(sc.ch) ) {
char s[100]; char s[100];
sc.GetCurrentLowered(s, sizeof(s)); sc.GetCurrentLowered(s, sizeof(s));
bool IsDirective = false;
if (cpuInstruction.InList(s)) { if (cpuInstruction.InList(s)) {
sc.ChangeState(SCE_ASM_CPUINSTRUCTION); 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); sc.ChangeState(SCE_ASM_REGISTER);
} else if (directive.InList(s)) { } else if (directive.InList(s)) {
sc.ChangeState(SCE_ASM_DIRECTIVE); sc.ChangeState(SCE_ASM_DIRECTIVE);
IsDirective = true;
} else if (directiveOperand.InList(s)) { } else if (directiveOperand.InList(s)) {
sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND);
} else if (extInstruction.InList(s)) { } else if (extInstruction.InList(s)) {
sc.ChangeState(SCE_ASM_EXTINSTRUCTION); sc.ChangeState(SCE_ASM_EXTINSTRUCTION);
} }
sc.SetState(SCE_ASM_DEFAULT); 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_COMMENTDIRECTIVE) {
else if (sc.state == SCE_ASM_COMMENT ) { 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) { if (sc.atLineEnd) {
sc.SetState(SCE_ASM_DEFAULT); sc.SetState(SCE_ASM_DEFAULT);
} }
@ -170,15 +365,100 @@ static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, Wo
sc.Complete(); sc.Complete();
} }
static const char * const asmWordListDesc[] = { // Store both the current line's fold level and the next lines in the
"CPU instructions", // level store to make it easy to pick up with each increment
"FPU instructions", // and to make it possible to fiddle the current level for "else".
"Registers",
"Directives",
"Directive operands",
"Extended instructions",
0
};
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<char>(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<unsigned int>(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);

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"
@ -640,6 +639,14 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
levelCurrent--; 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) { if (atEOL) {
int lev = levelPrev; int lev = levelPrev;
if (visibleChars == 0 && foldCompact) if (visibleChars == 0 && foldCompact)

View File

@ -19,7 +19,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -1,6 +1,7 @@
// Scintilla source code edit control // Scintilla source code edit control
/** @file LexCPP.cxx /** @file LexCPP.cxx
** Lexer for C++, C, Java, and JavaScript. ** Lexer for C++, C, Java, and JavaScript.
** Further folding features and configuration properties added by "Udo Lechner" <dlchnr(at)gmx(dot)net>
**/ **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
@ -15,10 +16,6 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable: 4786) #pragma warning(disable: 4786)
#endif #endif
#ifdef __BORLANDC__
// Borland C++ displays warnings in vector header without this
#pragma option -w-ccc -w-rch
#endif
#include <string> #include <string>
#include <vector> #include <vector>
@ -29,7 +26,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"
@ -37,6 +33,7 @@
#include "CharacterSet.h" #include "CharacterSet.h"
#include "LexerModule.h" #include "LexerModule.h"
#include "OptionSet.h" #include "OptionSet.h"
#include "SparseState.h"
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
@ -212,8 +209,13 @@ struct OptionsCPP {
bool trackPreprocessor; bool trackPreprocessor;
bool updatePreprocessor; bool updatePreprocessor;
bool fold; bool fold;
bool foldSyntaxBased;
bool foldComment; bool foldComment;
bool foldCommentMultiline;
bool foldCommentExplicit; bool foldCommentExplicit;
std::string foldExplicitStart;
std::string foldExplicitEnd;
bool foldExplicitAnywhere;
bool foldPreprocessor; bool foldPreprocessor;
bool foldCompact; bool foldCompact;
bool foldAtElse; bool foldAtElse;
@ -223,8 +225,13 @@ struct OptionsCPP {
trackPreprocessor = true; trackPreprocessor = true;
updatePreprocessor = true; updatePreprocessor = true;
fold = false; fold = false;
foldSyntaxBased = true;
foldComment = false; foldComment = false;
foldCommentMultiline = true;
foldCommentExplicit = true; foldCommentExplicit = true;
foldExplicitStart = "";
foldExplicitEnd = "";
foldExplicitAnywhere = false;
foldPreprocessor = false; foldPreprocessor = false;
foldCompact = false; foldCompact = false;
foldAtElse = false; foldAtElse = false;
@ -258,14 +265,29 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> {
DefineProperty("fold", &OptionsCPP::fold); 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, DefineProperty("fold.comment", &OptionsCPP::foldComment,
"This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " "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 //} " "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."); "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, DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit,
"Set this property to 0 to disable folding explicit fold points when fold.comment=1."); "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, DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor,
"This option enables folding preprocessor directives when using the C++ lexer. " "This option enables folding preprocessor directives when using the C++ lexer. "
"Includes C#'s explicit #region and #endregion folding directives."); "Includes C#'s explicit #region and #endregion folding directives.");
@ -288,7 +310,6 @@ class LexerCPP : public ILexer {
CharacterSet setLogicalOp; CharacterSet setLogicalOp;
PPStates vlls; PPStates vlls;
std::vector<PPDefinition> ppDefineHistory; std::vector<PPDefinition> ppDefineHistory;
PropSetSimple props;
WordList keywords; WordList keywords;
WordList keywords2; WordList keywords2;
WordList keywords3; WordList keywords3;
@ -297,6 +318,7 @@ class LexerCPP : public ILexer {
std::map<std::string, std::string> preprocessorDefinitionsStart; std::map<std::string, std::string> preprocessorDefinitionsStart;
OptionsCPP options; OptionsCPP options;
OptionSetCPP osCPP; OptionSetCPP osCPP;
SparseState<std::string> rawStringTerminators;
public: public:
LexerCPP(bool caseSensitive_) : LexerCPP(bool caseSensitive_) :
caseSensitive(caseSensitive_), caseSensitive(caseSensitive_),
@ -419,7 +441,6 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
if (options.identifiersAllowDollars) { if (options.identifiersAllowDollars) {
setWordStart.Add('$'); setWordStart.Add('$');
@ -483,16 +504,18 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
} }
const int maskActivity = 0x3F; const int maskActivity = 0x3F;
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
SparseState<std::string> rawSTNew(lineCurrent);
int activitySet = preproc.IsInactive() ? 0x40 : 0; int activitySet = preproc.IsInactive() ? 0x40 : 0;
for (; sc.More(); sc.Forward()) { for (; sc.More(); sc.Forward()) {
if (sc.atLineStart) { 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 // Prevent SCE_C_STRINGEOL from leaking back to previous line which
// ends with a line continuation by locking in the state upto this position. // 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 // Reset states to begining of colourise so no surprises
// if different sets of lines lexed. // 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) { if (sc.atLineEnd) {
lineCurrent++; lineCurrent++;
vlls.Add(lineCurrent, preproc); vlls.Add(lineCurrent, preproc);
if (rawStringTerminator != "") {
rawSTNew.Set(lineCurrent-1, rawStringTerminator);
}
} }
// Handle line continuation generically. // 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)) { } else if (keywords4.InList(s)) {
sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); 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); sc.SetState(SCE_C_DEFAULT|activitySet);
} }
break; break;
@ -642,6 +685,14 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
sc.ForwardSetState(SCE_C_DEFAULT|activitySet); sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
} }
break; 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: case SCE_C_CHARACTER:
if (sc.atLineEnd) { if (sc.atLineEnd) {
sc.ChangeState(SCE_C_STRINGEOL|activitySet); sc.ChangeState(SCE_C_STRINGEOL|activitySet);
@ -682,6 +733,14 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
} }
} }
break; break;
case SCE_C_TRIPLEVERBATIM:
if (sc.Match ("\"\"\"")) {
while (sc.Match('"')) {
sc.Forward();
}
sc.SetState(SCE_C_DEFAULT|activitySet);
}
break;
case SCE_C_UUID: case SCE_C_UUID:
if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
sc.SetState(SCE_C_DEFAULT|activitySet); 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('@', '\"')) { if (sc.Match('@', '\"')) {
sc.SetState(SCE_C_VERBATIM|activitySet); sc.SetState(SCE_C_VERBATIM|activitySet);
sc.Forward(); 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))) { } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
if (lastWordWasUUID) { if (lastWordWasUUID) {
sc.SetState(SCE_C_UUID|activitySet); 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))) { || !FollowsPostfixOperator(sc, styler))) {
sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx
} else if (sc.ch == '\"') { } 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 isIncludePreprocessor = false; // ensure that '>' won't end the string
} else if (isIncludePreprocessor && sc.ch == '<') { } else if (isIncludePreprocessor && sc.ch == '<') {
sc.SetState(SCE_C_STRING|activitySet); sc.SetState(SCE_C_STRING|activitySet);
@ -828,10 +902,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
} }
continuationLine = false; continuationLine = false;
} }
if (definitionsChanged) const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent);
if (definitionsChanged || rawStringsChanged)
styler.ChangeLexerState(startPos, startPos + length); styler.ChangeLexerState(startPos, startPos + length);
sc.Complete(); sc.Complete();
styler.Flush();
} }
// Store both the current line's fold level and the next lines in the // 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]; char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos); int styleNext = styler.StyleAt(startPos);
int style = initStyle; int style = initStyle;
const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
for (unsigned int i = startPos; i < endPos; i++) { for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext; char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
@ -863,7 +938,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
style = styleNext; style = styleNext;
styleNext = styler.StyleAt(i + 1); styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); 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)) { if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) {
levelNext++; levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { } 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--; levelNext--;
} }
} }
if (options.foldComment && options.foldCommentExplicit && (style == SCE_C_COMMENTLINE)) { if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) {
if ((ch == '/') && (chNext == '/')) { if (userDefinedFoldMarkers) {
char chNext2 = styler.SafeGetCharAt(i + 2); if (styler.Match(i, options.foldExplicitStart.c_str())) {
if (chNext2 == '{') {
levelNext++; levelNext++;
} else if (chNext2 == '}') { } else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
levelNext--; 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)) { 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 == '{') { if (ch == '{') {
// Measure the minimum before a '{' to allow // Measure the minimum before a '{' to allow
// folding on "} else {" // folding on "} else {"
@ -910,7 +993,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
visibleChars++; visibleChars++;
if (atEOL || (i == endPos-1)) { if (atEOL || (i == endPos-1)) {
int levelUse = levelCurrent; int levelUse = levelCurrent;
if (options.foldAtElse) { if (options.foldSyntaxBased && options.foldAtElse) {
levelUse = levelMinCurrent; levelUse = levelMinCurrent;
} }
int lev = levelUse | levelNext << 16; int lev = levelUse | levelNext << 16;

View File

@ -18,7 +18,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -2,6 +2,7 @@
** Lexer for D. ** Lexer for D.
** **
** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com> ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com>
** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>
**/ **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
@ -13,17 +14,23 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <string>
#include <map>
#include "ILexer.h" #include "ILexer.h"
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h" #include "StyleContext.h"
#include "CharacterSet.h" #include "CharacterSet.h"
#include "LexerModule.h" #include "LexerModule.h"
#include "OptionSet.h"
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
@ -59,17 +66,187 @@ static bool IsStringSuffix(int ch) {
return ch == 'c' || ch == 'w' || ch == 'd'; 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, // An individual named option for use in an OptionSet
WordList *keywordlists[], Accessor &styler, bool caseSensitive) {
WordList &keywords = *keywordlists[0]; // Options used for LexerD
WordList &keywords2 = *keywordlists[1]; struct OptionsD {
WordList &keywords3 = *keywordlists[2]; //doxygen bool fold;
WordList &keywords4 = *keywordlists[3]; bool foldSyntaxBased;
WordList &keywords5 = *keywordlists[4]; bool foldComment;
WordList &keywords6 = *keywordlists[5]; bool foldCommentMultiline;
WordList &keywords7 = *keywordlists[6]; 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<OptionsD> {
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; int styleBeforeDCKeyword = SCE_D_DEFAULT;
@ -294,24 +471,17 @@ static void ColouriseDoc(unsigned int startPos, int length, int initStyle,
sc.Complete(); 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 // 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 // level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {". // 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 void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
// This option enables D folding on a "} else {" line of an if statement.
bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", if (!options.fold)
styler.GetPropertyInt("fold.at.else", 0)) != 0; return;
LexAccessor styler(pAccess);
unsigned int endPos = startPos + length; unsigned int endPos = startPos + length;
int visibleChars = 0; int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos); int lineCurrent = styler.GetLine(startPos);
@ -323,6 +493,8 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &
char chNext = styler[startPos]; char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos); int styleNext = styler.StyleAt(startPos);
int style = initStyle; 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++) { for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext; char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
@ -330,7 +502,7 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &
style = styleNext; style = styleNext;
styleNext = styler.StyleAt(i + 1); styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (foldComment && IsStreamCommentStyle(style)) { if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) { if (!IsStreamCommentStyle(stylePrev)) {
levelNext++; levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
@ -338,7 +510,25 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &
levelNext--; 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 == '{') { if (ch == '{') {
// Measure the minimum before a '{' to allow // Measure the minimum before a '{' to allow
// folding on "} else {" // folding on "} else {"
@ -350,19 +540,19 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &
levelNext--; levelNext--;
} }
} }
if (atEOL) { if (atEOL || (i == endPos-1)) {
if (foldComment) { // Handle nested comments if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments
int nc; int nc;
nc = styler.GetLineState(lineCurrent); nc = styler.GetLineState(lineCurrent);
nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;
levelNext += nc; levelNext += nc;
} }
int levelUse = levelCurrent; int levelUse = levelCurrent;
if (foldAtElse) { if (options.foldSyntaxBased && foldAtElse) {
levelUse = levelMinCurrent; levelUse = levelMinCurrent;
} }
int lev = levelUse | levelNext << 16; int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && foldCompact) if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG; lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext) if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG; 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, LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists);
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);

View File

@ -19,7 +19,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.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, "endmodule") == 0 || strcmp(s, "endprogram") == 0
|| strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0
|| strcmp(s, "endwhere") == 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; lev = -1;
} else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if
lev = 0; lev = 0;

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.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))) { 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); //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 ((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 == '*'))) { if (ch == '#') {
levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1; 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 == '/')) { } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) {
levelCurrent--; levelCurrent--;

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -18,7 +18,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -44,7 +44,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -21,7 +21,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"
@ -510,7 +509,7 @@ static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
styler.ColourTo(endLine, SCE_DIFF_COMMAND); styler.ColourTo(endLine, SCE_DIFF_COMMAND);
} else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff
styler.ColourTo(endLine, SCE_DIFF_COMMAND); 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 // In a context diff, --- appears in both the header and the position markers
if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/'))
styler.ColourTo(endLine, SCE_DIFF_POSITION); styler.ColourTo(endLine, SCE_DIFF_POSITION);
@ -930,8 +929,8 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
// Command or return status // Command or return status
return SCE_ERR_CMD; return SCE_ERR_CMD;
} else if (lineBuffer[0] == '<') { } else if (lineBuffer[0] == '<') {
// Diff removal, but not interested. Trapped to avoid hitting CTAG cases. // Diff removal.
return SCE_ERR_DEFAULT; return SCE_ERR_DIFF_DELETION;
} else if (lineBuffer[0] == '!') { } else if (lineBuffer[0] == '!') {
return SCE_ERR_DIFF_CHANGED; return SCE_ERR_DIFF_CHANGED;
} else if (lineBuffer[0] == '+') { } else if (lineBuffer[0] == '+') {

View File

@ -118,7 +118,6 @@ contains requires
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -2,7 +2,7 @@
/** @file LexSQL.cxx /** @file LexSQL.cxx
** Lexer for SQL, including PL/SQL and SQL*Plus. ** Lexer for SQL, including PL/SQL and SQL*Plus.
**/ **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h> #include <stdlib.h>
@ -12,24 +12,36 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include "ILexer.h" #include "ILexer.h"
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"
#include "StyleContext.h" #include "StyleContext.h"
#include "CharacterSet.h" #include "CharacterSet.h"
#include "LexerModule.h" #include "LexerModule.h"
#include "OptionSet.h"
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
#endif #endif
static inline bool IsAWordChar(int ch) { static inline bool IsAWordChar(int ch, bool sqlAllowDottedWord) {
return (ch < 0x80) && (isalnum(ch) || ch == '_'); if (!sqlAllowDottedWord)
return (ch < 0x80) && (isalnum(ch) || ch == '_');
else
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
} }
static inline bool IsAWordStart(int 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.) // Not exactly following number definition (several dots are seen as OK, etc.)
// but probably enough in most cases. // but probably enough in most cases.
return (ch < 0x80) && return (ch < 0x80) &&
(isdigit(ch) || toupper(ch) == 'E' || (isdigit(ch) || toupper(ch) == 'E' ||
ch == '.' || ch == '-' || ch == '+'); ch == '.' || ch == '-' || ch == '+');
} }
static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
Accessor &styler) {
WordList &keywords1 = *keywordlists[0]; class SQLStates {
WordList &keywords2 = *keywordlists[1]; public :
WordList &kw_pldoc = *keywordlists[2]; void Set(int lineNumber, unsigned short int sqlStatesLine) {
WordList &kw_sqlplus = *keywordlists[3]; if (!sqlStatement.size() == 0 || !sqlStatesLine == 0) {
WordList &kw_user1 = *keywordlists[4]; sqlStatement.resize(lineNumber + 1, 0);
WordList &kw_user2 = *keywordlists[5]; sqlStatement[lineNumber] = sqlStatesLine;
WordList &kw_user3 = *keywordlists[6]; }
WordList &kw_user4 = *keywordlists[7]; }
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<size_t>(lineNumber))) {
return sqlStatement[lineNumber];
} else {
return 0;
}
}
SQLStates() {}
private :
std::vector <unsigned short int> 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<OptionsSQL> {
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); 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; 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. // Determine if the current state should terminate.
switch (sc.state) { switch (sc.state) {
case SCE_SQL_OPERATOR: case SCE_SQL_OPERATOR:
@ -84,7 +354,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
} }
break; break;
case SCE_SQL_IDENTIFIER: case SCE_SQL_IDENTIFIER:
if (!IsAWordChar(sc.ch)) { if (!IsAWordChar(sc.ch, options.sqlAllowDottedWord)) {
int nextState = SCE_SQL_DEFAULT; int nextState = SCE_SQL_DEFAULT;
char s[1000]; char s[1000];
sc.GetCurrentLowered(s, sizeof(s)); sc.GetCurrentLowered(s, sizeof(s));
@ -161,7 +431,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
} }
break; break;
case SCE_SQL_CHARACTER: case SCE_SQL_CHARACTER:
if (sqlBackslashEscapes && sc.ch == '\\') { if (options.sqlBackslashEscapes && sc.ch == '\\') {
sc.Forward(); sc.Forward();
} else if (sc.ch == '\'') { } else if (sc.ch == '\'') {
if (sc.chNext == '\"') { if (sc.chNext == '\"') {
@ -191,7 +461,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
sc.SetState(SCE_SQL_NUMBER); sc.SetState(SCE_SQL_NUMBER);
} else if (IsAWordStart(sc.ch)) { } else if (IsAWordStart(sc.ch)) {
sc.SetState(SCE_SQL_IDENTIFIER); sc.SetState(SCE_SQL_IDENTIFIER);
} else if (sc.ch == 0x60 && sqlBackticksIdentifier) { } else if (sc.ch == 0x60 && options.sqlBackticksIdentifier) {
sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
} else if (sc.Match('/', '*')) { } else if (sc.Match('/', '*')) {
if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style 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 -- // MySQL requires a space or control char after --
// http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
// Perhaps we should enforce that with proper property: // Perhaps we should enforce that with proper property:
//~ } else if (sc.Match("-- ")) { //~ } else if (sc.Match("-- ")) {
sc.SetState(SCE_SQL_COMMENTLINE); sc.SetState(SCE_SQL_COMMENTLINE);
} else if (sc.ch == '#') { } else if (sc.ch == '#' && options.sqlNumbersignComment) {
sc.SetState(SCE_SQL_COMMENTLINEDOC); sc.SetState(SCE_SQL_COMMENTLINEDOC);
} else if (sc.ch == '\'') { } else if (sc.ch == '\'') {
sc.SetState(SCE_SQL_CHARACTER); sc.SetState(SCE_SQL_CHARACTER);
@ -220,25 +490,10 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
sc.Complete(); sc.Complete();
} }
static bool IsStreamCommentStyle(int style) { void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
return style == SCE_SQL_COMMENT || if (!options.fold)
style == SCE_SQL_COMMENTDOC || return;
style == SCE_SQL_COMMENTDOCKEYWORD || LexAccessor styler(pAccess);
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;
unsigned int endPos = startPos + length; unsigned int endPos = startPos + length;
int visibleChars = 0; int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos); 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 styleNext = styler.StyleAt(startPos);
int style = initStyle; int style = initStyle;
bool endFound = false; 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++) { for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext; char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
@ -258,7 +521,16 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
style = styleNext; style = styleNext;
styleNext = styler.StyleAt(i + 1); styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); 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)) { if (!IsStreamCommentStyle(stylePrev)) {
levelNext++; levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
@ -266,7 +538,7 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
levelNext--; 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 // MySQL needs -- comments to be followed by space or control char
if ((ch == '-') && (chNext == '-')) { if ((ch == '-') && (chNext == '-')) {
char chNext2 = styler.SafeGetCharAt(i + 2); 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 (style == SCE_SQL_OPERATOR) {
if (ch == '(') { if (ch == '(') {
levelNext++; if (levelCurrent > levelNext)
levelCurrent--;
levelNext++;
} else if (ch == ')') { } else if (ch == ')') {
levelNext--; levelNext--;
} else if ((!options.foldOnlyBegin) && ch == ';') {
sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, false);
} }
} }
// If new keyword (cannot trigger on elseif or nullif, does less tests) // If new keyword (cannot trigger on elseif or nullif, does less tests)
if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { 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]; char s[MAX_KW_LEN + 2];
unsigned int j = 0; unsigned int j = 0;
for (; j < MAX_KW_LEN + 1; j++) { for (; j < MAX_KW_LEN + 1; j++) {
@ -302,33 +578,133 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
} else { } else {
s[j] = '\0'; s[j] = '\0';
} }
if ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) {
if (strcmp(s, "if") == 0) {
if (endFound) { if (endFound) {
// ignore
endFound = false; 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 { } 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) { } else if (strcmp(s, "begin") == 0) {
levelNext++; levelNext++;
sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false);
} else if ((strcmp(s, "end") == 0) || } else if ((strcmp(s, "end") == 0) ||
// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS // SQL Anywhere permits IF ... ELSE ... ENDIF
(foldSqlExists && (strcmp(s, "exists") == 0)) || // will only be active if "endif" appears in the
// // SQL Anywhere permits IF ... ELSE ... ENDIF // keyword list.
// // will only be active if "endif" appears in the (strcmp(s, "endif") == 0)) {
// // keyword list.
(strcmp(s, "endif") == 0)) {
endFound = true; endFound = true;
levelNext--; levelNext--;
if (levelNext < SC_FOLDLEVELBASE) { if (levelNext < SC_FOLDLEVELBASE) {
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) { if (atEOL) {
int levelUse = levelCurrent; int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16; int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && foldCompact) if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG; lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext) if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG; lev |= SC_FOLDLEVELHEADERFLAG;
@ -338,7 +714,9 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
lineCurrent++; lineCurrent++;
levelCurrent = levelNext; levelCurrent = levelNext;
visibleChars = 0; visibleChars = 0;
endFound = false; statementFound = false;
if (!options.foldOnlyBegin)
sqlStates.Set(lineCurrent, sqlStatesCurrentLine);
} }
if (!isspacechar(ch)) { if (!isspacechar(ch)) {
visibleChars++; visibleChars++;
@ -346,16 +724,4 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
} }
} }
static const char * const sqlWordListDesc[] = { LexerModule lmSQL(SCLEX_SQL, LexerSQL::LexerFactorySQL, "sql", 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);

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -27,7 +27,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -21,7 +21,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -17,7 +17,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -16,7 +16,6 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.h" #include "SciLexer.h"
#include "PropSetSimple.h"
#include "WordList.h" #include "WordList.h"
#include "LexAccessor.h" #include "LexAccessor.h"
#include "Accessor.h" #include "Accessor.h"

View File

@ -50,8 +50,8 @@ public:
assert(val < size); assert(val < size);
bset[val] = true; bset[val] = true;
} }
void AddString(const char *CharacterSet) { void AddString(const char *setToAdd) {
for (const char *cp=CharacterSet; *cp; cp++) { for (const char *cp=setToAdd; *cp; cp++) {
int val = static_cast<unsigned char>(*cp); int val = static_cast<unsigned char>(*cp);
assert(val >= 0); assert(val >= 0);
assert(val < size); assert(val < size);

View File

@ -20,7 +20,7 @@ protected:
WordList *keyWordLists[numWordLists+1]; WordList *keyWordLists[numWordLists+1];
public: public:
LexerBase(); LexerBase();
~LexerBase(); virtual ~LexerBase();
void SCI_METHOD Release(); void SCI_METHOD Release();
int SCI_METHOD Version() const; int SCI_METHOD Version() const;
const char * SCI_METHOD PropertyNames(); const char * SCI_METHOD PropertyNames();

View File

@ -80,6 +80,8 @@ class OptionSet {
names += name; names += name;
} }
public: public:
virtual ~OptionSet() {
}
void DefineProperty(const char *name, plcob pb, std::string description="") { void DefineProperty(const char *name, plcob pb, std::string description="") {
nameToDef[name] = Option(pb, description); nameToDef[name] = Option(pb, description);
AppendName(name); AppendName(name);

View File

@ -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 <neilh@scintilla.org>
// 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 <typename T>
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<State> 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<T> &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<size_t>(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

View File

@ -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 { bool WordList::InList(const char *s) const {
if (0 == words) if (0 == words)
return false; return false;

View File

@ -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). (removing unused lexers and an updated marshallers file).
diff -Naur scintilla_orig/gtk/scintilla-marshal.c scintilla/gtk/scintilla-marshal.c 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_orig/gtk/scintilla-marshal.c 2010-10-27 23:15:45.000000000 +0200
+++ scintilla/gtk/scintilla-marshal.c 2008-12-06 12:11:33.000000000 +0100 +++ scintilla/gtk/scintilla-marshal.c 2011-04-03 17:42:59.000000000 +0200
@@ -35,8 +35,8 @@ @@ -35,8 +35,8 @@
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong #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_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, typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1,
diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx 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_orig/src/Catalogue.cxx 2011-03-17 23:41:24.000000000 +0100
+++ scintilla/src/Catalogue.cxx 2010-11-21 18:00:07.000000000 +0100 +++ scintilla/src/Catalogue.cxx 2011-04-03 17:43:45.000000000 +0200
@@ -81,98 +81,41 @@ @@ -81,100 +81,42 @@
//++Autogenerated -- run src/LexGen.py to regenerate //++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\) //**\(\tLINK_LEXER(\*);\n\)
- LINK_LEXER(lmA68k);
- LINK_LEXER(lmAbaqus); - LINK_LEXER(lmAbaqus);
LINK_LEXER(lmAda); LINK_LEXER(lmAda);
- LINK_LEXER(lmAns1); - LINK_LEXER(lmAns1);
@ -51,7 +52,7 @@ diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx
- LINK_LEXER(lmClw); - LINK_LEXER(lmClw);
- LINK_LEXER(lmClwNoCase); - LINK_LEXER(lmClwNoCase);
LINK_LEXER(lmCmake); LINK_LEXER(lmCmake);
- LINK_LEXER(lmCOBOL); LINK_LEXER(lmCOBOL);
- LINK_LEXER(lmConf); - LINK_LEXER(lmConf);
LINK_LEXER(lmCPP); LINK_LEXER(lmCPP);
- LINK_LEXER(lmCPPNoCase); - LINK_LEXER(lmCPPNoCase);
@ -86,6 +87,7 @@ diff -Naur scintilla_orig/src/Catalogue.cxx scintilla/src/Catalogue.cxx
- LINK_LEXER(lmMatlab); - LINK_LEXER(lmMatlab);
- LINK_LEXER(lmMETAPOST); - LINK_LEXER(lmMETAPOST);
- LINK_LEXER(lmMMIXAL); - LINK_LEXER(lmMMIXAL);
- LINK_LEXER(lmModula);
- LINK_LEXER(lmMSSQL); - LINK_LEXER(lmMSSQL);
- LINK_LEXER(lmMySQL); - LINK_LEXER(lmMySQL);
- LINK_LEXER(lmNimrod); - LINK_LEXER(lmNimrod);

View File

@ -129,11 +129,11 @@ void AutoComplete::Select(const char *word) {
size_t lenWord = strlen(word); size_t lenWord = strlen(word);
int location = -1; int location = -1;
const int maxItemLen=1000; const int maxItemLen=1000;
char item[maxItemLen];
int start = 0; // lower bound of the api array block to search 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 int end = lb->Length() - 1; // upper bound of the api array block to search
while ((start <= end) && (location == -1)) { // Binary searching loop while ((start <= end) && (location == -1)) { // Binary searching loop
int pivot = (start + end) / 2; int pivot = (start + end) / 2;
char item[maxItemLen];
lb->GetValue(pivot, item, maxItemLen); lb->GetValue(pivot, item, maxItemLen);
int cond; int cond;
if (ignoreCase) if (ignoreCase)

View File

@ -29,6 +29,7 @@ CallTip::CallTip() {
rectUp = PRectangle(0,0,0,0); rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0);
lineHeight = 1; lineHeight = 1;
offsetMain = 0;
startHighlight = 0; startHighlight = 0;
endHighlight = 0; endHighlight = 0;
tabSize = 0; tabSize = 0;
@ -45,6 +46,8 @@ CallTip::CallTip() {
colourSel.desired = ColourDesired(0, 0, 0x80); colourSel.desired = ColourDesired(0, 0, 0x80);
colourShade.desired = ColourDesired(0, 0, 0); colourShade.desired = ColourDesired(0, 0, 0);
colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0); colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
codePage = 0;
clickPlace = 0;
} }
CallTip::~CallTip() { CallTip::~CallTip() {

View File

@ -14,14 +14,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
// With Borland C++ 5.5, including <string> 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 "Platform.h"
#include "ILexer.h" #include "ILexer.h"
@ -95,7 +87,7 @@ void LexInterface::Colourise(int start, int end) {
Document::Document() { Document::Document() {
refCount = 0; refCount = 0;
#ifdef unix #ifdef __unix__
eolMode = SC_EOL_LF; eolMode = SC_EOL_LF;
#else #else
eolMode = SC_EOL_CRLF; 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 // See http://msdn.microsoft.com/en-us/library/cc194792%28v=MSDN.10%29.aspx
// http://msdn.microsoft.com/en-us/library/cc194790.aspx // http://msdn.microsoft.com/en-us/library/cc194790.aspx
if ((pos - 1) <= posStartLine) { if ((pos - 1) <= posStartLine) {
return posStartLine - 1; return pos - 1;
} else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) { } else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) {
// Must actually be trail byte // Must actually be trail byte
return pos - 2; 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); //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
const int limitPos = Platform::Maximum(startPos, endPos); 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) { if (caseSensitive) {
while (forward ? (pos < endSearch) : (pos >= endSearch)) { while (forward ? (pos < endSearch) : (pos >= endSearch)) {
bool found = (pos + lengthFind) <= limitPos; bool found = (pos + lengthFind) <= limitPos;
@ -1526,8 +1522,8 @@ void Document::EnsureStyledTo(int pos) {
IncrementStyleClock(); IncrementStyleClock();
if (pli && !pli->UseContainerLexing()) { if (pli && !pli->UseContainerLexing()) {
int lineEndStyled = LineFromPosition(GetEndStyled()); int lineEndStyled = LineFromPosition(GetEndStyled());
int endStyled = LineStart(lineEndStyled); int endStyledTo = LineStart(lineEndStyled);
pli->Colourise(endStyled, pos); pli->Colourise(endStyledTo, pos);
} else { } else {
// Ask the watchers to style, and stop as soon as one responds. // Ask the watchers to style, and stop as soon as one responds.
for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) {

View File

@ -357,6 +357,7 @@ public:
const WatcherWithUserData *GetWatchers() const { return watchers; } const WatcherWithUserData *GetWatchers() const { return watchers; }
int GetLenWatchers() const { return lenWatchers; } int GetLenWatchers() const { return lenWatchers; }
CharClassify::cc WordCharClass(unsigned char ch);
bool IsWordPartSeparator(char ch); bool IsWordPartSeparator(char ch);
int WordPartLeft(int pos); int WordPartLeft(int pos);
int WordPartRight(int pos); int WordPartRight(int pos);
@ -368,7 +369,6 @@ public:
int BraceMatch(int position, int maxReStyle); int BraceMatch(int position, int maxReStyle);
private: private:
CharClassify::cc WordCharClass(unsigned char ch);
bool IsWordStartAt(int pos); bool IsWordStartAt(int pos);
bool IsWordEndAt(int pos); bool IsWordEndAt(int pos);
bool IsWordAt(int start, int end); bool IsWordAt(int start, int end);

View File

@ -16,14 +16,6 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
// With Borland C++ 5.5, including <string> 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 "Platform.h"
#include "ILexer.h" #include "ILexer.h"
@ -141,6 +133,9 @@ Editor::Editor() {
lastXChosen = 0; lastXChosen = 0;
lineAnchor = 0; lineAnchor = 0;
originalAnchorPos = 0; originalAnchorPos = 0;
wordSelectAnchorStartPos = 0;
wordSelectAnchorEndPos = 0;
wordSelectInitialCaretPos = -1;
primarySelection = true; primarySelection = true;
@ -183,7 +178,8 @@ Editor::Editor() {
lengthForEncode = -1; lengthForEncode = -1;
needUpdateUI = true; needUpdateUI = 0;
ContainerNeedsUpdate(SC_UPDATE_CONTENT);
braces[0] = invalidPosition; braces[0] = invalidPosition;
braces[1] = invalidPosition; braces[1] = invalidPosition;
bracesMatchStyle = STYLE_BRACEBAD; bracesMatchStyle = STYLE_BRACEBAD;
@ -442,7 +438,10 @@ int Editor::LineFromLocation(Point pt) {
} }
void Editor::SetTopLine(int topLineNew) { void Editor::SetTopLine(int topLineNew) {
topLine = topLineNew; if (topLine != topLineNew) {
topLine = topLineNew;
ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
}
posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
} }
@ -706,17 +705,17 @@ void Editor::SetRectangularRange() {
if (sel.selType == Selection::selThin) { if (sel.selType == Selection::selThin) {
xCaret = xAnchor; 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 lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position());
int increment = (lineCaret > lineAnchor) ? 1 : -1; int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
for (int line=lineAnchor; line != lineCaret+increment; line += increment) { for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) {
SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor)); SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor));
if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0) if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
range.ClearVirtualSpace(); range.ClearVirtualSpace();
if (line == lineAnchor) if (line == lineAnchorRect)
sel.SetSelection(range); sel.SetSelection(range);
else 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()); lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position());
} }
} }
needUpdateUI = true; ContainerNeedsUpdate(SC_UPDATE_SELECTION);
InvalidateRange(firstAffected, lastAffected); InvalidateRange(firstAffected, lastAffected);
} }
@ -990,6 +989,7 @@ void Editor::HorizontalScrollTo(int xPos) {
xPos = 0; xPos = 0;
if ((wrapState == eWrapNone) && (xOffset != xPos)) { if ((wrapState == eWrapNone) && (xOffset != xPos)) {
xOffset = xPos; xOffset = xPos;
ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
SetHorizontalScrollPos(); SetHorizontalScrollPos();
RedrawRect(GetClientRectangle()); RedrawRect(GetClientRectangle());
} }
@ -1299,6 +1299,7 @@ void Editor::SetXYScroll(XYScrollPosition newXY) {
} }
if (newXY.xOffset != xOffset) { if (newXY.xOffset != xOffset) {
xOffset = newXY.xOffset; xOffset = newXY.xOffset;
ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
if (newXY.xOffset > 0) { if (newXY.xOffset > 0) {
PRectangle rcText = GetTextRectangle(); PRectangle rcText = GetTextRectangle();
if (horizontalScrollBarVisible && if (horizontalScrollBarVisible &&
@ -2042,7 +2043,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
ll->edgeColumn = -1; ll->edgeColumn = -1;
} }
char styleByte = 0; char styleByte;
const int styleMask = pdoc->stylingBitsMask; const int styleMask = pdoc->stylingBitsMask;
ll->styleBitsSet = 0; ll->styleBitsSet = 0;
// Fill base line layout // 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 // Draw any translucent whole line states
rcSegment.left = xStart; rcSegment.left = 0;
rcSegment.right = rcLine.right - 1; rcSegment.right = rcLine.right - 1;
if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) { if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) {
SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha); SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha);
@ -3165,11 +3166,11 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
} }
pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
pixmapSelPattern->PenColour(colourFMStripes); for (int y = 0; y < patternSize; y++) {
for (int stripe = 0; stripe < patternSize; stripe++) { for (int x = y % 2; x < patternSize; x+=2) {
// Alternating 1 pixel stripes is same as checkerboard. PRectangle rcPixel(x, y, x+1, y+1);
pixmapSelPattern->MoveTo(0, stripe * 2); pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
pixmapSelPattern->LineTo(patternSize, stripe * 2 - patternSize); }
} }
} }
@ -3183,10 +3184,9 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated);
pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated);
for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) { for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) {
pixmapIndentGuide->MoveTo(0, stripe); PRectangle rcPixel(0, stripe, 1, stripe+1);
pixmapIndentGuide->LineTo(2, stripe); pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore.allocated);
pixmapIndentGuideHighlight->MoveTo(0, stripe); pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore.allocated);
pixmapIndentGuideHighlight->LineTo(2, stripe);
} }
} }
@ -3316,7 +3316,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
surfaceWindow->SetPalette(&palTemp, true); surfaceWindow->SetPalette(&palTemp, true);
NotifyUpdateUI(); NotifyUpdateUI();
needUpdateUI = false; needUpdateUI = 0;
RefreshStyleData(); RefreshStyleData();
RefreshPixMaps(surfaceWindow); RefreshPixMaps(surfaceWindow);
@ -3921,8 +3921,8 @@ void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len)
} }
} }
void Editor::ClearSelection() { void Editor::ClearSelection(bool retainMultipleSelections) {
if (!sel.IsRectangular()) if (!sel.IsRectangular() && !retainMultipleSelections)
FilterSelections(); FilterSelections();
UndoGroup ug(pdoc); UndoGroup ug(pdoc);
for (size_t r=0; r<sel.Count(); r++) { for (size_t r=0; r<sel.Count(); r++) {
@ -4222,6 +4222,7 @@ void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool
void Editor::NotifyUpdateUI() { void Editor::NotifyUpdateUI() {
SCNotification scn = {0}; SCNotification scn = {0};
scn.nmhdr.code = SCN_UPDATEUI; scn.nmhdr.code = SCN_UPDATEUI;
scn.updated = needUpdateUI;
NotifyParent(scn); NotifyParent(scn);
} }
@ -4338,7 +4339,7 @@ static inline int MovePositionForDeletion(int position, int startDeletion, int l
} }
void Editor::NotifyModified(Document *, DocModification mh, void *) { void Editor::NotifyModified(Document *, DocModification mh, void *) {
needUpdateUI = true; ContainerNeedsUpdate(SC_UPDATE_CONTENT);
if (paintState == painting) { if (paintState == painting) {
CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length)); CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
} }
@ -4620,6 +4621,11 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lPar
NotifyParent(scn); NotifyParent(scn);
} }
// Something has changed that the container should know about
void Editor::ContainerNeedsUpdate(int flags) {
needUpdateUI |= flags;
}
/** /**
* Force scroll and keep position relative to top of window. * Force scroll and keep position relative to top of window.
* *
@ -4727,7 +4733,6 @@ void Editor::Duplicate(bool forLine) {
forLine = true; forLine = true;
} }
UndoGroup ug(pdoc, sel.Count() > 1); UndoGroup ug(pdoc, sel.Count() > 1);
SelectionPosition last;
const char *eol = ""; const char *eol = "";
int eolLen = 0; int eolLen = 0;
if (forLine) { if (forLine) {
@ -5131,6 +5136,7 @@ int Editor::KeyCommand(unsigned int iMessage) {
inOverstrike = !inOverstrike; inOverstrike = !inOverstrike;
DropCaret(); DropCaret();
ShowCaretAtCurrentPosition(); ShowCaretAtCurrentPosition();
ContainerNeedsUpdate(SC_UPDATE_CONTENT);
NotifyUpdateUI(); NotifyUpdateUI();
break; break;
case SCI_CANCEL: // Cancel any modes - handled in subclass case SCI_CANCEL: // Cancel any modes - handled in subclass
@ -5230,6 +5236,7 @@ int Editor::KeyCommand(unsigned int iMessage) {
UndoGroup ug(pdoc); UndoGroup ug(pdoc);
sel.RangeMain().caret = SelectionPosition( sel.RangeMain().caret = SelectionPosition(
InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
sel.RangeMain().anchor = sel.RangeMain().caret;
int endWord = pdoc->NextWordStart(sel.MainCaret(), 1); int endWord = pdoc->NextWordStart(sel.MainCaret(), 1);
pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); 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<Window::Cursor>(vs.ms[margin].cursor);
x += vs.ms[margin].width;
}
return Window::cursorReverseArrow;
}
void Editor::LineSelection(int lineCurrent_, int lineAnchor_) { void Editor::LineSelection(int lineCurrent_, int lineAnchor_) {
if (lineAnchor_ < lineCurrent_) { if (lineAnchor_ < lineCurrent_) {
SetSelection(pdoc->LineStart(lineCurrent_ + 1), 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) { void Editor::DwellEnd(bool mouseMoved) {
if (mouseMoved) if (mouseMoved)
ticksToDwell = dwellDelay; ticksToDwell = dwellDelay;
@ -5910,13 +5951,33 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
} }
if (selectionType == selWord) { if (selectionType == selWord) {
if (sel.MainCaret() >= originalAnchorPos) { // Moved forward int charPos = originalAnchorPos;
SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), 1), if (sel.MainCaret() == originalAnchorPos) {
pdoc->ExtendWordSelect(originalAnchorPos, -1)); charPos = PositionFromLocation(pt, false, true);
} else { // Moved backward charPos = MovePositionOutsideChar(charPos, -1);
SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), -1),
pdoc->ExtendWordSelect(originalAnchorPos, 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) { } else if (selectionType == selLine) {
lineAnchor = LineFromLocation(pt); lineAnchor = LineFromLocation(pt);
SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor)); 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); InvalidateSelection(SelectionRange(newPos), true);
if (sel.Count() > 1) if (sel.Count() > 1)
Redraw(); Redraw();
sel.Clear(); if ((sel.Count() > 1) || (sel.selType != Selection::selStream))
sel.Clear();
sel.selType = alt ? Selection::selRectangle : Selection::selStream; sel.selType = alt ? Selection::selRectangle : Selection::selStream;
SetSelection(newPos, newPos); SetSelection(newPos, newPos);
} }
@ -6098,7 +6160,7 @@ void Editor::ButtonMove(Point pt) {
} }
} else if (selectionType == selWord) { } else if (selectionType == selWord) {
// Continue selecting by word // 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 // No need to do anything. Previously this case was lumped
// in with "Moved forward", but that can be harmful in this // in with "Moved forward", but that can be harmful in this
// case: a handler for the NotifyDoubleClick re-adjusts // 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 // the ButtonMove() called via Tick() for auto-scrolling
// could result in the fancier word selection adjustment // could result in the fancier word selection adjustment
// being unmade. // being unmade.
} else if (movePos.Position() > originalAnchorPos) { // Moved forward } else {
SetSelection(pdoc->ExtendWordSelect(movePos.Position(), 1), wordSelectInitialCaretPos = -1;
pdoc->ExtendWordSelect(originalAnchorPos, -1)); WordSelection(movePos.Position());
} else { // Moved backward
SetSelection(pdoc->ExtendWordSelect(movePos.Position(), -1),
pdoc->ExtendWordSelect(originalAnchorPos, 1));
} }
} else { } else {
// Continue selecting by line // Continue selecting by line
@ -6151,7 +6210,7 @@ void Editor::ButtonMove(Point pt) {
} else { } else {
if (vs.fixedColumnWidth > 0) { // There is a margin if (vs.fixedColumnWidth > 0) { // There is a margin
if (PointInSelMargin(pt)) { if (PointInSelMargin(pt)) {
DisplayCursor(Window::cursorReverseArrow); DisplayCursor(GetMarginCursor(pt));
SetHotSpotRange(NULL); SetHotSpotRange(NULL);
return; // No need to test for selection return; // No need to test for selection
} }
@ -6177,6 +6236,8 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
if (inDragDrop == ddInitial) { if (inDragDrop == ddInitial) {
inDragDrop = ddNone; inDragDrop = ddNone;
SetEmptySelection(newPos.Position()); SetEmptySelection(newPos.Position());
selectionType = selChar;
originalAnchorPos = sel.MainCaret();
} }
if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) { if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) {
hotSpotClickPos = INVALID_POSITION; hotSpotClickPos = INVALID_POSITION;
@ -6184,7 +6245,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
} }
if (HaveMouseCapture()) { if (HaveMouseCapture()) {
if (PointInSelMargin(pt)) { if (PointInSelMargin(pt)) {
DisplayCursor(Window::cursorReverseArrow); DisplayCursor(GetMarginCursor(pt));
} else { } else {
DisplayCursor(Window::cursorText); DisplayCursor(Window::cursorText);
SetHotSpotRange(NULL); SetHotSpotRange(NULL);
@ -6344,7 +6405,7 @@ void Editor::IdleStyling() {
if (needUpdateUI) { if (needUpdateUI) {
NotifyUpdateUI(); NotifyUpdateUI();
needUpdateUI = false; needUpdateUI = 0;
} }
styleNeeded.Reset(); styleNeeded.Reset();
} }
@ -7001,6 +7062,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_SETXOFFSET: case SCI_SETXOFFSET:
xOffset = wParam; xOffset = wParam;
ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
SetHorizontalScrollPos(); SetHorizontalScrollPos();
Redraw(); Redraw();
break; break;
@ -7315,7 +7377,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_GOTOPOS: case SCI_GOTOPOS:
SetEmptySelection(wParam); SetEmptySelection(wParam);
EnsureCaretVisible(); EnsureCaretVisible();
Redraw();
break; break;
case SCI_GETCURLINE: { case SCI_GETCURLINE: {
@ -7466,6 +7527,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break; break;
} }
xOffset = 0; xOffset = 0;
ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
InvalidateStyleRedraw(); InvalidateStyleRedraw();
ReconfigureScrollBars(); ReconfigureScrollBars();
break; break;
@ -7786,6 +7848,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
else else
return 0; 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: case SCI_STYLECLEARALL:
vs.ClearStyles(); vs.ClearStyles();
InvalidateStyleRedraw(); InvalidateStyleRedraw();

View File

@ -201,6 +201,9 @@ protected: // ScintillaBase subclass needs access to much of Editor
int lastXChosen; int lastXChosen;
int lineAnchor; int lineAnchor;
int originalAnchorPos; int originalAnchorPos;
int wordSelectAnchorStartPos;
int wordSelectAnchorEndPos;
int wordSelectInitialCaretPos;
int targetStart; int targetStart;
int targetEnd; int targetEnd;
int searchFlags; int searchFlags;
@ -208,7 +211,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
int posTopLine; int posTopLine;
int lengthForEncode; int lengthForEncode;
bool needUpdateUI; int needUpdateUI;
Position braces[2]; Position braces[2];
int bracesMatchStyle; int bracesMatchStyle;
int highlightGuideColumn; int highlightGuideColumn;
@ -391,7 +394,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void AddChar(char ch); void AddChar(char ch);
virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
void InsertPaste(SelectionPosition selStart, const char *text, int len); void InsertPaste(SelectionPosition selStart, const char *text, int len);
void ClearSelection(); void ClearSelection(bool retainMultipleSelections=false);
void ClearAll(); void ClearAll();
void ClearDocumentStyle(); void ClearDocumentStyle();
void Cut(); void Cut();
@ -438,6 +441,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void NotifyErrorOccurred(Document *doc, void *userData, int status); void NotifyErrorOccurred(Document *doc, void *userData, int status);
void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); 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); void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false);
enum { cmSame, cmUpper, cmLower } caseMap; enum { cmSame, cmUpper, cmLower } caseMap;
virtual std::string CaseMapString(const std::string &s, int caseMapping); 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 PositionInSelection(int pos);
bool PointInSelection(Point pt); bool PointInSelection(Point pt);
bool PointInSelMargin(Point pt); bool PointInSelMargin(Point pt);
Window::Cursor GetMarginCursor(Point pt);
void LineSelection(int lineCurrent_, int lineAnchor_); void LineSelection(int lineCurrent_, int lineAnchor_);
void WordSelection(int pos);
void DwellEnd(bool mouseMoved); void DwellEnd(bool mouseMoved);
void MouseLeave(); void MouseLeave();
virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);

View File

@ -38,7 +38,6 @@ LexerManager *LexerManager::theInstance = NULL;
void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
fneFactory = fFactory; fneFactory = fFactory;
fnFactory = fFactory(index); fnFactory = fFactory(index);
externalLanguage = index;
} }
//------------------------------------------ //------------------------------------------

View File

@ -27,11 +27,12 @@ typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned i
class ExternalLexerModule : public LexerModule { class ExternalLexerModule : public LexerModule {
protected: protected:
GetLexerFactoryFunction fneFactory; GetLexerFactoryFunction fneFactory;
int externalLanguage;
char name[100]; char name[100];
public: public:
ExternalLexerModule(int language_, LexerFunction fnLexer_, 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)); strncpy(name, languageName_, sizeof(name));
name[sizeof(name)-1] = '\0'; name[sizeof(name)-1] = '\0';
languageName = name; languageName = name;

View File

@ -42,6 +42,10 @@ public:
/// Divide an interval into multiple partitions. /// Divide an interval into multiple partitions.
/// Useful for breaking a document down into sections such as lines. /// 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 { class Partitioning {
private: private:
@ -153,6 +157,7 @@ public:
return pos; return pos;
} }
/// Return value in range [0 .. Partitions() - 1] even for arguments outside interval
int PartitionFromPosition(int pos) const { int PartitionFromPosition(int pos) const {
if (body->Length() <= 1) if (body->Length() <= 1)
return 0; return 0;

View File

@ -68,6 +68,8 @@ LineLayout::LineLayout(int maxLineLength_) :
widthLine(wrapWidthInfinite), widthLine(wrapWidthInfinite),
lines(1), lines(1),
wrapIndent(0) { wrapIndent(0) {
bracePreviousStyles[0] = 0;
bracePreviousStyles[1] = 0;
Resize(maxLineLength_); Resize(maxLineLength_);
} }

View File

@ -147,8 +147,10 @@ bool RunStyles::FillRange(int &position, int value, int &fillLength) {
runEnd = RunFromPosition(end); runEnd = RunFromPosition(end);
RemoveRunIfSameAsPrevious(runEnd); RemoveRunIfSameAsPrevious(runEnd);
RemoveRunIfSameAsPrevious(runStart); RemoveRunIfSameAsPrevious(runStart);
return true;
} else {
return false;
} }
return true;
} }
void RunStyles::SetValueAt(int position, int value) { void RunStyles::SetValueAt(int position, int value) {

View File

@ -20,6 +20,9 @@ using namespace Scintilla;
#endif #endif
void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) { void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
if (position == startChange) {
virtualSpace = 0;
}
if (insertion) { if (insertion) {
if (position > startChange) { if (position > startChange) {
position += length; position += length;
@ -31,6 +34,7 @@ void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int
position -= length; position -= length;
} else { } else {
position = startChange; position = startChange;
virtualSpace = 0;
} }
} }
} }
@ -291,6 +295,11 @@ void Selection::AddSelection(SelectionRange range) {
mainRange = ranges.size() - 1; mainRange = ranges.size() - 1;
} }
void Selection::AddSelectionWithoutTrim(SelectionRange range) {
ranges.push_back(range);
mainRange = ranges.size() - 1;
}
void Selection::TentativeSelection(SelectionRange range) { void Selection::TentativeSelection(SelectionRange range) {
if (!tentativeMain) { if (!tentativeMain) {
rangesSaved = ranges; rangesSaved = ranges;

View File

@ -60,7 +60,7 @@ public:
struct SelectionSegment { struct SelectionSegment {
SelectionPosition start; SelectionPosition start;
SelectionPosition end; SelectionPosition end;
SelectionSegment() { SelectionSegment() : start(), end() {
} }
SelectionSegment(SelectionPosition a, SelectionPosition b) { SelectionSegment(SelectionPosition a, SelectionPosition b) {
if (a < b) { if (a < b) {
@ -86,7 +86,7 @@ struct SelectionRange {
SelectionPosition caret; SelectionPosition caret;
SelectionPosition anchor; SelectionPosition anchor;
SelectionRange() { SelectionRange() : caret(), anchor() {
} }
SelectionRange(SelectionPosition single) : caret(single), anchor(single) { SelectionRange(SelectionPosition single) : caret(single), anchor(single) {
} }
@ -166,6 +166,7 @@ public:
void TrimSelection(SelectionRange range); void TrimSelection(SelectionRange range);
void SetSelection(SelectionRange range); void SetSelection(SelectionRange range);
void AddSelection(SelectionRange range); void AddSelection(SelectionRange range);
void AddSelectionWithoutTrim(SelectionRange range);
void TentativeSelection(SelectionRange range); void TentativeSelection(SelectionRange range);
void CommitTentative(); void CommitTentative();
int CharacterInSelection(int posCharacter) const; int CharacterInSelection(int posCharacter) const;

View File

@ -238,7 +238,7 @@ public:
DeleteRange(0, lengthBody); 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 { 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. // Split into up to 2 ranges, before and after the split then use memcpy on each.
int range1Length = 0; int range1Length = 0;

View File

@ -24,7 +24,7 @@ using namespace Scintilla;
#endif #endif
MarginStyle::MarginStyle() : 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 // A list of the fontnames - avoids wasting space in each style

View File

@ -20,6 +20,7 @@ public:
int width; int width;
int mask; int mask;
bool sensitive; bool sensitive;
int cursor;
MarginStyle(); MarginStyle();
}; };