[geany/geany] d77fe4: Update Scintilla to 3.5.0 pre-release
Colomban Wendling
git-noreply at xxxxx
Sun Aug 10 00:17:32 UTC 2014
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Sun, 10 Aug 2014 00:17:32 UTC
Commit: d77fe4c6b78f1b3d6f7650370d2f46eaec0e6f8d
https://github.com/geany/geany/commit/d77fe4c6b78f1b3d6f7650370d2f46eaec0e6f8d
Log Message:
-----------
Update Scintilla to 3.5.0 pre-release
Modified Paths:
--------------
scintilla/Makefile.am
scintilla/gtk/PlatGTK.cxx
scintilla/gtk/ScintillaGTK.cxx
scintilla/include/SciLexer.h
scintilla/include/Scintilla.h
scintilla/include/Scintilla.iface
scintilla/lexers/LexHTML.cxx
scintilla/lexers/LexMatlab.cxx
scintilla/lexers/LexRuby.cxx
scintilla/lexers/LexRust.cxx
scintilla/lexlib/LexerModule.h
scintilla/makefile.win32
scintilla/scintilla_changes.patch
scintilla/src/CellBuffer.cxx
scintilla/src/CellBuffer.h
scintilla/src/ContractionState.cxx
scintilla/src/ContractionState.h
scintilla/src/Document.cxx
scintilla/src/Document.h
scintilla/src/EditModel.cxx
scintilla/src/EditModel.h
scintilla/src/EditView.cxx
scintilla/src/EditView.h
scintilla/src/Editor.cxx
scintilla/src/Editor.h
scintilla/src/LineMarker.cxx
scintilla/src/MarginView.cxx
scintilla/src/MarginView.h
scintilla/src/PerLine.cxx
scintilla/src/PerLine.h
scintilla/src/PositionCache.cxx
scintilla/src/PositionCache.h
scintilla/src/RESearch.cxx
scintilla/src/RESearch.h
scintilla/src/ScintillaBase.cxx
scintilla/src/ScintillaBase.h
scintilla/src/Selection.cxx
scintilla/src/Selection.h
scintilla/src/ViewStyle.cxx
scintilla/src/ViewStyle.h
scintilla/version.txt
Modified: scintilla/Makefile.am
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -97,6 +97,10 @@ src/Document.cxx \
src/Document.h \
src/Editor.cxx \
src/Editor.h \
+src/EditModel.cxx \
+src/EditModel.h \
+src/EditView.cxx \
+src/EditView.h \
src/ExternalLexer.cxx \
src/ExternalLexer.h \
src/FontQuality.h \
@@ -106,6 +110,8 @@ src/KeyMap.cxx \
src/KeyMap.h \
src/LineMarker.cxx \
src/LineMarker.h \
+src/MarginView.cxx \
+src/MarginView.h \
src/Partitioning.h \
src/PerLine.cxx \
src/PerLine.h \
Modified: scintilla/gtk/PlatGTK.cxx
12 lines changed, 10 insertions(+), 2 deletions(-)
===================================================================
@@ -527,6 +527,7 @@ void SurfaceImpl::Release() {
}
bool SurfaceImpl::Initialised() {
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 8, 0)
if (inited && context) {
if (cairo_status(context) == CAIRO_STATUS_SUCCESS) {
// Even when status is success, the target surface may have been
@@ -543,6 +544,7 @@ bool SurfaceImpl::Initialised() {
}
return cairo_status(context) == CAIRO_STATUS_SUCCESS;
}
+#endif
return inited;
}
@@ -1086,6 +1088,10 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
}
clusterStart = clusterEnd;
}
+ while (i < lenPositions) {
+ // If something failed, fill in rest of the positions
+ positions[i++] = clusterStart;
+ }
PLATFORM_ASSERT(i == lenPositions);
}
}
@@ -1799,6 +1805,7 @@ void ListBoxX::Select(int n) {
}
int ListBoxX::GetSelection() {
+ int index = -1;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
@@ -1808,9 +1815,10 @@ int ListBoxX::GetSelection() {
int *indices = gtk_tree_path_get_indices(path);
// Don't free indices.
if (indices)
- return indices[0];
+ index = indices[0];
+ gtk_tree_path_free(path);
}
- return -1;
+ return index;
}
int ListBoxX::Find(const char *prefix) {
Modified: scintilla/gtk/ScintillaGTK.cxx
284 lines changed, 208 insertions(+), 76 deletions(-)
===================================================================
@@ -57,9 +57,13 @@
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
#include "ScintillaBase.h"
+#include "UnicodeFromUTF8.h"
#ifdef SCI_LEXER
#include "ExternalLexer.h"
@@ -186,13 +190,23 @@ class ScintillaGTK : public ScintillaBase {
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
private:
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
- virtual void SetTicking(bool on);
+ struct TimeThunk {
+ TickReason reason;
+ ScintillaGTK *scintilla;
+ guint timer;
+ TimeThunk() : reason(tickCaret), scintilla(NULL), timer(0) {}
+ };
+ TimeThunk timers[tickDwell+1];
+ virtual bool FineTickerAvailable();
+ virtual bool FineTickerRunning(TickReason reason);
+ virtual void FineTickerStart(TickReason reason, int millis, int tolerance);
+ virtual void FineTickerCancel(TickReason reason);
virtual bool SetIdle(bool on);
virtual void SetMouseCapture(bool on);
virtual bool HaveMouseCapture();
virtual bool PaintContains(PRectangle rc);
void FullPaint();
- virtual PRectangle GetClientRectangle();
+ virtual PRectangle GetClientRectangle() const;
virtual void ScrollText(int linesToMove);
virtual void SetVerticalScrollPos();
virtual void SetHorizontalScrollPos();
@@ -280,6 +294,9 @@ class ScintillaGTK : public ScintillaBase {
static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
void PreeditChangedThis();
static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
+
+ bool KoreanIME();
+
static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
static void RealizeText(GtkWidget *widget, void*);
static void Destroy(GObject *object);
@@ -300,7 +317,7 @@ class ScintillaGTK : public ScintillaBase {
gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
GtkSelectionData *selection_data, guint info, guint time);
- static gboolean TimeOut(ScintillaGTK *sciThis);
+ static gboolean TimeOut(TimeThunk *tt);
static gboolean IdleCallback(ScintillaGTK *sciThis);
static gboolean StyleIdle(ScintillaGTK *sciThis);
virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo);
@@ -624,22 +641,37 @@ void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internal
}
}
+namespace {
+
+class PreEditString {
+public:
+ gchar *str;
+ gint cursor_pos;
+ PangoAttrList *attrs;
+
+ PreEditString(GtkIMContext *im_context) {
+ gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
+ }
+ ~PreEditString() {
+ g_free(str);
+ pango_attr_list_unref(attrs);
+ }
+};
+
+}
+
gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
try {
SetFocusState(true);
if (im_context != NULL) {
- gchar *str = NULL;
- gint cursor_pos;
-
- gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos);
+ PreEditString pes(im_context);
if (PWidget(wPreedit) != NULL) {
- if (strlen(str) > 0) {
+ if (strlen(pes.str) > 0) {
gtk_widget_show(PWidget(wPreedit));
} else {
gtk_widget_hide(PWidget(wPreedit));
}
}
- g_free(str);
gtk_im_context_focus_in(im_context);
}
@@ -829,11 +861,16 @@ void ScintillaGTK::Initialise() {
caret.period = 0;
}
- SetTicking(true);
+ for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast<TickReason>(tr + 1)) {
+ timers[tr].reason = tr;
+ timers[tr].scintilla = this;
+ }
}
void ScintillaGTK::Finalise() {
- SetTicking(false);
+ for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast<TickReason>(tr + 1)) {
+ FineTickerCancel(tr);
+ }
ScintillaBase::Finalise();
}
@@ -1024,17 +1061,27 @@ sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
return 0;
}
-void ScintillaGTK::SetTicking(bool on) {
- if (timer.ticking != on) {
- timer.ticking = on;
- if (timer.ticking) {
- timer.tickerID = reinterpret_cast<TickerID>(g_timeout_add(timer.tickSize,
- reinterpret_cast<GSourceFunc>(TimeOut), this));
- } else {
- g_source_remove(GPOINTER_TO_UINT(timer.tickerID));
- }
+/**
+* Report that this Editor subclass has a working implementation of FineTickerStart.
+*/
+bool ScintillaGTK::FineTickerAvailable() {
+ return true;
+}
+
+bool ScintillaGTK::FineTickerRunning(TickReason reason) {
+ return timers[reason].timer != 0;
+}
+
+void ScintillaGTK::FineTickerStart(TickReason reason, int millis, int /* tolerance */) {
+ FineTickerCancel(reason);
+ timers[reason].timer = g_timeout_add(millis, reinterpret_cast<GSourceFunc>(TimeOut), &timers[reason]);
+}
+
+void ScintillaGTK::FineTickerCancel(TickReason reason) {
+ if (timers[reason].timer) {
+ g_source_remove(timers[reason].timer);
+ timers[reason].timer = 0;
}
- timer.ticksToWait = caret.period;
}
bool ScintillaGTK::SetIdle(bool on) {
@@ -1121,8 +1168,9 @@ void ScintillaGTK::FullPaint() {
wText.InvalidateAll();
}
-PRectangle ScintillaGTK::GetClientRectangle() {
- PRectangle rc = wMain.GetClientPosition();
+PRectangle ScintillaGTK::GetClientRectangle() const {
+ Window &win = const_cast<Window &>(wMain);
+ PRectangle rc = win.GetClientPosition();
if (verticalScrollBarVisible)
rc.right -= verticalScrollBarWidth;
if (horizontalScrollBarVisible && !Wrapping())
@@ -2220,19 +2268,13 @@ gboolean ScintillaGTK::KeyRelease(GtkWidget *widget, GdkEventKey *event) {
gboolean ScintillaGTK::DrawPreeditThis(GtkWidget *widget, cairo_t *cr) {
try {
- gchar *str;
- gint cursor_pos;
- PangoAttrList *attrs;
-
- gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
- PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
- pango_layout_set_attributes(layout, attrs);
+ PreEditString pes(im_context);
+ PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), pes.str);
+ pango_layout_set_attributes(layout, pes.attrs);
cairo_move_to(cr, 0, 0);
pango_cairo_show_layout(cr, layout);
- g_free(str);
- pango_attr_list_unref(attrs);
g_object_unref(layout);
} catch (...) {
errorStatus = SC_STATUS_FAILURE;
@@ -2248,20 +2290,14 @@ gboolean ScintillaGTK::DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK
gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
try {
- gchar *str;
- gint cursor_pos;
- PangoAttrList *attrs;
-
- gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
- PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
- pango_layout_set_attributes(layout, attrs);
+ PreEditString pes(im_context);
+ PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), pes.str);
+ pango_layout_set_attributes(layout, pes.attrs);
cairo_t *context = gdk_cairo_create(reinterpret_cast<GdkDrawable *>(WindowFromWidget(widget)));
cairo_move_to(context, 0, 0);
pango_cairo_show_layout(context, layout);
cairo_destroy(context);
- g_free(str);
- pango_attr_list_unref(attrs);
g_object_unref(layout);
} catch (...) {
errorStatus = SC_STATUS_FAILURE;
@@ -2275,9 +2311,43 @@ gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, Sci
#endif
+bool ScintillaGTK::KoreanIME() {
+ // Warn : for KoreanIME use only.
+ if (pdoc->TentativeActive()) {
+ return true;
+ }
+
+ bool koreanIME = false;
+ PreEditString utfval(im_context);
+
+ // Only need to check if the first preedit char is Korean.
+ // The rest will be handled in TentativeActive()
+ // which can handle backspace and CJK commons and so forth.
+
+ if (strlen(utfval.str) == 3) { // One hangul char has 3byte.
+ int unicode = UnicodeFromUTF8(reinterpret_cast<unsigned char *>(utfval.str));
+ // Korean character ranges which are used for the first preedit chars.
+ // http://www.programminginkorean.com/programming/hangul-in-unicode/
+ bool HangulJamo = (0x1100 <= unicode && unicode <= 0x11FF);
+ bool HangulCompatibleJamo = (0x3130 <= unicode && unicode <= 0x318F);
+ bool HangulJamoExtendedA = (0xA960 <= unicode && unicode <= 0xA97F);
+ bool HangulJamoExtendedB = (0xD7B0 <= unicode && unicode <= 0xD7FF);
+ bool HangulSyllable = (0xAC00 <= unicode && unicode <= 0xD7A3);
+ koreanIME = (HangulJamo | HangulCompatibleJamo | HangulSyllable
+ | HangulJamoExtendedA | HangulJamoExtendedB);
+ }
+ return koreanIME;
+}
+
void ScintillaGTK::CommitThis(char *utfVal) {
try {
//~ fprintf(stderr, "Commit '%s'\n", utfVal);
+ if (pdoc->TentativeActive()) {
+ pdoc->TentativeUndo();
+ }
+
+ view.imeCaretBlockOverride = false;
+
if (IsUnicodeMode()) {
AddCharUTF(utfVal, strlen(utfVal));
} else {
@@ -2285,7 +2355,7 @@ void ScintillaGTK::CommitThis(char *utfVal) {
if (*source) {
Converter conv(source, "UTF-8", true);
if (conv) {
- char localeVal[4] = "\0\0\0";
+ char localeVal[maxLenInputIME * 2];
char *pin = utfVal;
size_t inLeft = strlen(utfVal);
char *pout = localeVal;
@@ -2293,15 +2363,14 @@ void ScintillaGTK::CommitThis(char *utfVal) {
size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
if (conversions != ((size_t)(-1))) {
*pout = '\0';
- for (int i = 0; localeVal[i]; i++) {
- AddChar(localeVal[i]);
- }
+ AddCharUTF(localeVal, strlen(localeVal));
} else {
fprintf(stderr, "Conversion failed '%s'\n", utfVal);
}
}
}
}
+ ShowCaretAtCurrentPosition();
} catch (...) {
errorStatus = SC_STATUS_FAILURE;
}
@@ -2313,36 +2382,99 @@ void ScintillaGTK::Commit(GtkIMContext *, char *str, ScintillaGTK *sciThis) {
void ScintillaGTK::PreeditChangedThis() {
try {
- gchar *str;
- PangoAttrList *attrs;
- gint cursor_pos;
- gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
- if (strlen(str) > 0) {
- PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
- pango_layout_set_attributes(layout, attrs);
-
- gint w, h;
- pango_layout_get_pixel_size(layout, &w, &h);
- g_object_unref(layout);
-
- gint x, y;
- gdk_window_get_origin(PWindow(wText), &x, &y);
-
- Point pt = PointMainCaret();
- if (pt.x < 0)
- pt.x = 0;
- if (pt.y < 0)
- pt.y = 0;
-
- gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
- gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
- gtk_widget_show(PWidget(wPreedit));
- gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
- } else {
- gtk_widget_hide(PWidget(wPreedit));
+ if (KoreanIME()) {
+ // Copy & paste by johnsonj.
+ // Great thanks to
+ // jiniya from http://www.jiniya.net/tt/494 for DBCS input with AddCharUTF().
+ // BLUEnLIVE from http://zockr.tistory.com/1118 for UNDO and inOverstrike.
+ view.imeCaretBlockOverride = false; // If backspace.
+
+ if (pdoc->TentativeActive()) {
+ pdoc->TentativeUndo();
+ } else {
+ // No tentative undo means start of this composition so
+ // fill in any virtual spaces.
+ bool tmpOverstrike = inOverstrike;
+ inOverstrike = false; // Not allowed to be deleted twice.
+ AddCharUTF("", 0);
+ inOverstrike = tmpOverstrike;
+ }
+
+ PreEditString utfval(im_context);
+
+ if (strlen(utfval.str) > maxLenInputIME * 3) {
+ return; // Do not allow over 200 chars.
+ }
+
+ char localeVal[maxLenInputIME * 2];
+ char *hanval = (char *)"";
+
+ if (IsUnicodeMode()) {
+ hanval = utfval.str;
+ } else {
+ const char *source = CharacterSetID();
+ if (*source) {
+ Converter conv(source, "UTF-8", true);
+ if (conv) {
+ char *pin = utfval.str;
+ size_t inLeft = strlen(utfval.str);
+ char *pout = localeVal;
+ size_t outLeft = sizeof(localeVal);
+ size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
+ if (conversions != ((size_t)(-1))) {
+ *pout = '\0';
+ hanval = localeVal;
+ } else {
+ fprintf(stderr, "Conversion failed '%s'\n", utfval.str);
+ }
+ }
+ }
+ }
+
+ if (!pdoc->TentativeActive()) {
+ pdoc->TentativeStart();
+ }
+
+ bool tmpRecordingMacro = recordingMacro;
+ recordingMacro = false;
+ int hanlen = strlen(hanval);
+ AddCharUTF(hanval, hanlen);
+ recordingMacro = tmpRecordingMacro;
+
+ // For block caret which means KoreanIME is in composition.
+ view.imeCaretBlockOverride = true;
+ for (size_t r = 0; r < sel.Count(); r++) {
+ int positionInsert = sel.Range(r).Start().Position();
+ sel.Range(r).caret.SetPosition(positionInsert - hanlen);
+ sel.Range(r).anchor.SetPosition(positionInsert - hanlen);
+ }
+ } else { // Original code follows for other IMEs.
+ PreEditString pes(im_context);
+ if (strlen(pes.str) > 0) {
+ PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), pes.str);
+ pango_layout_set_attributes(layout, pes.attrs);
+
+ gint w, h;
+ pango_layout_get_pixel_size(layout, &w, &h);
+ g_object_unref(layout);
+
+ gint x, y;
+ gdk_window_get_origin(PWindow(wText), &x, &y);
+
+ Point pt = PointMainCaret();
+ if (pt.x < 0)
+ pt.x = 0;
+ if (pt.y < 0)
+ pt.y = 0;
+
+ gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
+ gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
+ gtk_widget_show(PWidget(wPreedit));
+ gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
+ } else {
+ gtk_widget_hide(PWidget(wPreedit));
+ }
}
- g_free(str);
- pango_attr_list_unref(attrs);
} catch (...) {
errorStatus = SC_STATUS_FAILURE;
}
@@ -2711,8 +2843,8 @@ void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
}
}
-int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
- sciThis->Tick();
+int ScintillaGTK::TimeOut(TimeThunk *tt) {
+ tt->scintilla->TickFor(tt->reason);
return 1;
}
Modified: scintilla/include/SciLexer.h
18 lines changed, 18 insertions(+), 0 deletions(-)
===================================================================
@@ -127,6 +127,7 @@
#define SCLEX_DMAP 112
#define SCLEX_AS 113
#define SCLEX_DMIS 114
+#define SCLEX_REGISTRY 115
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
@@ -906,6 +907,7 @@
#define SCE_KIX_KEYWORD 7
#define SCE_KIX_FUNCTIONS 8
#define SCE_KIX_OPERATOR 9
+#define SCE_KIX_COMMENTSTREAM 10
#define SCE_KIX_IDENTIFIER 31
#define SCE_GC_DEFAULT 0
#define SCE_GC_COMMENTLINE 1
@@ -1692,6 +1694,9 @@
#define SCE_RUST_LIFETIME 18
#define SCE_RUST_MACRO 19
#define SCE_RUST_LEXERROR 20
+#define SCE_RUST_BYTESTRING 21
+#define SCE_RUST_BYTESTRINGR 22
+#define SCE_RUST_BYTECHARACTER 23
#define SCE_DMAP_DEFAULT 0
#define SCE_DMAP_COMMENT 1
#define SCE_DMAP_NUMBER 2
@@ -1713,6 +1718,19 @@
#define SCE_DMIS_UNSUPPORTED_MAJOR 7
#define SCE_DMIS_UNSUPPORTED_MINOR 8
#define SCE_DMIS_LABEL 9
+#define SCE_REG_DEFAULT 0
+#define SCE_REG_COMMENT 1
+#define SCE_REG_VALUENAME 2
+#define SCE_REG_STRING 3
+#define SCE_REG_HEXDIGIT 4
+#define SCE_REG_VALUETYPE 5
+#define SCE_REG_ADDEDKEY 6
+#define SCE_REG_DELETEDKEY 7
+#define SCE_REG_ESCAPED 8
+#define SCE_REG_KEYPATH_GUID 9
+#define SCE_REG_STRING_GUID 10
+#define SCE_REG_PARAMETER 11
+#define SCE_REG_OPERATOR 12
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif
Modified: scintilla/include/Scintilla.h
15 lines changed, 12 insertions(+), 3 deletions(-)
===================================================================
@@ -18,9 +18,9 @@ extern "C" {
#if defined(_WIN32)
/* Return false on failure: */
int Scintilla_RegisterClasses(void *hInstance);
-int Scintilla_ReleaseResources();
+int Scintilla_ReleaseResources(void);
#endif
-int Scintilla_LinkLexers();
+int Scintilla_LinkLexers(void);
#ifdef __cplusplus
}
@@ -92,6 +92,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETBUFFEREDDRAW 2035
#define SCI_SETTABWIDTH 2036
#define SCI_GETTABWIDTH 2121
+#define SCI_CLEARTABSTOPS 2675
+#define SCI_ADDTABSTOP 2676
+#define SCI_GETNEXTTABSTOP 2677
#define SC_CP_UTF8 65001
#define SCI_SETCODEPAGE 2037
#define MARKER_MAX 31
@@ -517,6 +520,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_APPENDTEXT 2282
#define SCI_GETTWOPHASEDRAW 2283
#define SCI_SETTWOPHASEDRAW 2284
+#define SC_PHASES_ONE 0
+#define SC_PHASES_TWO 1
+#define SC_PHASES_MULTIPLE 2
+#define SCI_GETPHASESDRAW 2673
+#define SCI_SETPHASESDRAW 2674
#define SC_EFF_QUALITY_MASK 0xF
#define SC_EFF_QUALITY_DEFAULT 0
#define SC_EFF_QUALITY_NON_ANTIALIASED 1
@@ -952,7 +960,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_MOD_CONTAINER 0x40000
#define SC_MOD_LEXERSTATE 0x80000
#define SC_MOD_INSERTCHECK 0x100000
-#define SC_MODEVENTMASKALL 0x1FFFFF
+#define SC_MOD_CHANGETABSTOPS 0x200000
+#define SC_MODEVENTMASKALL 0x3FFFFF
#define SC_UPDATE_CONTENT 0x1
#define SC_UPDATE_SELECTION 0x2
#define SC_UPDATE_V_SCROLL 0x4
Modified: scintilla/include/Scintilla.iface
48 lines changed, 46 insertions(+), 2 deletions(-)
===================================================================
@@ -226,6 +226,15 @@ set void SetTabWidth=2036(int tabWidth,)
# Retrieve the visible size of a tab.
get int GetTabWidth=2121(,)
+# Clear explicit tabstops on a line.
+fun void ClearTabStops=2675(int line,)
+
+# Add an explicit tab stop for a line.
+fun void AddTabStop=2676(int line, int x)
+
+# Find the next explicit tab stop position on a line after a position.
+fun int GetNextTabStop=2677(int line, int x)
+
# The SC_CP_UTF8 value can be used to enter Unicode mode.
# This is the same value as CP_UTF8 in Windows
val SC_CP_UTF8=65001
@@ -1291,13 +1300,27 @@ get bool GetVScrollBar=2281(,)
# Append a string to the end of the document without changing the selection.
fun void AppendText=2282(int length, string text)
-# Is drawing done in two phases with backgrounds drawn before faoregrounds?
+# Is drawing done in two phases with backgrounds drawn before foregrounds?
get bool GetTwoPhaseDraw=2283(,)
# In twoPhaseDraw mode, drawing is performed in two phases, first the background
# and then the foreground. This avoids chopping off characters that overlap the next run.
set void SetTwoPhaseDraw=2284(bool twoPhase,)
+enu FontQuality=SC_PHASES_
+val SC_PHASES_ONE=0
+val SC_PHASES_TWO=1
+val SC_PHASES_MULTIPLE=2
+
+# How many phases is drawing done in?
+get int GetPhasesDraw=2673(,)
+
+# In one phase draw, text is drawn in a series of rectangular blocks with no overlap.
+# In two phase draw, text is drawn in a series of lines allowing runs to overlap horizontally.
+# In multiple phase draw, each element is drawn over the whole drawing area, allowing text
+# to overlap from one line to the next.
+set void SetPhasesDraw=2674(int phases,)
+
# Control font anti-aliasing.
enu FontQuality=SC_EFF_
@@ -2509,7 +2532,8 @@ val SC_MOD_CHANGEANNOTATION=0x20000
val SC_MOD_CONTAINER=0x40000
val SC_MOD_LEXERSTATE=0x80000
val SC_MOD_INSERTCHECK=0x100000
-val SC_MODEVENTMASKALL=0x1FFFFF
+val SC_MOD_CHANGETABSTOPS=0x200000
+val SC_MODEVENTMASKALL=0x3FFFFF
enu Update=SC_UPDATE_
val SC_UPDATE_CONTENT=0x1
@@ -2675,6 +2699,7 @@ val SCLEX_RUST=111
val SCLEX_DMAP=112
val SCLEX_AS=113
val SCLEX_DMIS=114
+val SCLEX_REGISTRY=115
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1.
@@ -3567,6 +3592,7 @@ val SCE_KIX_MACRO=6
val SCE_KIX_KEYWORD=7
val SCE_KIX_FUNCTIONS=8
val SCE_KIX_OPERATOR=9
+val SCE_KIX_COMMENTSTREAM=10
val SCE_KIX_IDENTIFIER=31
# Lexical states for SCLEX_GUI4CLI
lex Gui4Cli=SCLEX_GUI4CLI SCE_GC_
@@ -4443,6 +4469,9 @@ val SCE_RUST_IDENTIFIER=17
val SCE_RUST_LIFETIME=18
val SCE_RUST_MACRO=19
val SCE_RUST_LEXERROR=20
+val SCE_RUST_BYTESTRING=21
+val SCE_RUST_BYTESTRINGR=22
+val SCE_RUST_BYTECHARACTER=23
# Lexical states for SCLEX_DMAP
lex DMAP=SCLEX_DMAP SCE_DMAP_
val SCE_DMAP_DEFAULT=0
@@ -4468,6 +4497,21 @@ val SCE_DMIS_MINORWORD=6
val SCE_DMIS_UNSUPPORTED_MAJOR=7
val SCE_DMIS_UNSUPPORTED_MINOR=8
val SCE_DMIS_LABEL=9
+# Lexical states for SCLEX_REGISTRY
+lex REG=SCLEX_REGISTRY SCE_REG_
+val SCE_REG_DEFAULT=0
+val SCE_REG_COMMENT=1
+val SCE_REG_VALUENAME=2
+val SCE_REG_STRING=3
+val SCE_REG_HEXDIGIT=4
+val SCE_REG_VALUETYPE=5
+val SCE_REG_ADDEDKEY=6
+val SCE_REG_DELETEDKEY=7
+val SCE_REG_ESCAPED=8
+val SCE_REG_KEYPATH_GUID=9
+val SCE_REG_STRING_GUID=10
+val SCE_REG_PARAMETER=11
+val SCE_REG_OPERATOR=12
# Events
Modified: scintilla/lexers/LexHTML.cxx
12 lines changed, 10 insertions(+), 2 deletions(-)
===================================================================
@@ -822,19 +822,27 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
// handle start of Mako comment line
if (isMako && ch == '#' && chNext == '#') {
makoComment = 1;
+ state = SCE_HP_COMMENTLINE;
}
// handle end of Mako comment line
else if (isMako && makoComment && (ch == '\r' || ch == '\n')) {
makoComment = 0;
- styler.ColourTo(i, SCE_HP_COMMENTLINE);
- state = SCE_HP_DEFAULT;
+ styler.ColourTo(i, StateToPrint);
+ if (scriptLanguage == eScriptPython) {
+ state = SCE_HP_DEFAULT;
+ } else {
+ state = SCE_H_DEFAULT;
+ }
}
// Allow falling through to mako handling code if newline is going to end a block
if (((ch == '\r' && chNext != '\n') || (ch == '\n')) &&
(!isMako || (0 != strcmp(makoBlockType, "%")))) {
}
+ // Ignore everything in mako comment until the line ends
+ else if (isMako && makoComment) {
+ }
// generic end of script processing
else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) {
Modified: scintilla/lexers/LexMatlab.cxx
5 lines changed, 4 insertions(+), 1 deletions(-)
===================================================================
@@ -12,6 +12,9 @@
** - added ... displayed as a comment
** - removed unused IsAWord functions
** - added some comments
+ **
+ ** Changes by John Donoghue 2014/08/01
+ ** - fix allowed transpose ' after {} operator
**/
// Copyright 1998-2001 by Neil Hodgson <neilh at scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
@@ -218,7 +221,7 @@ static void ColouriseMatlabOctaveDoc(
} else if (isalpha(sc.ch)) {
sc.SetState(SCE_MATLAB_KEYWORD);
} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
- if (sc.ch == ')' || sc.ch == ']') {
+ if (sc.ch == ')' || sc.ch == ']' || sc.ch == '}') {
transpose = true;
} else {
transpose = false;
Modified: scintilla/lexers/LexRuby.cxx
36 lines changed, 35 insertions(+), 1 deletions(-)
===================================================================
@@ -882,6 +882,31 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
preferRE = false;
} else if (isSafeWordcharOrHigh(chNext)) {
state = SCE_RB_SYMBOL;
+ } else if ((chNext == '@' || chNext == '$') &&
+ isSafeWordcharOrHigh(chNext2)) {
+ // instance and global variable followed by an identifier
+ advance_char(i, ch, chNext, chNext2);
+ state = SCE_RB_SYMBOL;
+ } else if (((chNext == '@' && chNext2 == '@') ||
+ (chNext == '$' && chNext2 == '-')) &&
+ isSafeWordcharOrHigh(styler.SafeGetCharAt(i+3))) {
+ // class variables and special global variable "$-IDENTCHAR"
+ state = SCE_RB_SYMBOL;
+ // $-IDENTCHAR doesn't continue past the IDENTCHAR
+ if (chNext == '$') {
+ styler.ColourTo(i+3, SCE_RB_SYMBOL);
+ state = SCE_RB_DEFAULT;
+ }
+ i += 3;
+ ch = styler.SafeGetCharAt(i);
+ chNext = styler.SafeGetCharAt(i+1);
+ } else if (chNext == '$' && strchr("_~*$?!@/\\;,.=:<>\"&`'+", chNext2)) {
+ // single-character special global variables
+ i += 2;
+ ch = chNext2;
+ chNext = styler.SafeGetCharAt(i+1);
+ styler.ColourTo(i, SCE_RB_SYMBOL);
+ state = SCE_RB_DEFAULT;
} else if (strchr("[*!~+-*/%=<>&^|", chNext)) {
// Do the operator analysis in-line, looking ahead
// Based on the table in pickaxe 2nd ed., page 339
@@ -1260,7 +1285,16 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
} else if (state == SCE_RB_CLASS_VAR
|| state == SCE_RB_INSTANCE_VAR
|| state == SCE_RB_SYMBOL) {
- if (!isSafeWordcharOrHigh(ch)) {
+ if (state == SCE_RB_SYMBOL &&
+ // FIDs suffices '?' and '!'
+ (((ch == '!' || ch == '?') && chNext != '=') ||
+ // identifier suffix '='
+ (ch == '=' && (chNext != '~' && chNext != '>' &&
+ (chNext != '=' || chNext2 == '>'))))) {
+ styler.ColourTo(i, state);
+ state = SCE_RB_DEFAULT;
+ preferRE = false;
+ } else if (!isSafeWordcharOrHigh(ch)) {
styler.ColourTo(i - 1, state);
redo_char(i, ch, chNext, chNext2, state); // pass by ref
preferRE = false;
Modified: scintilla/lexers/LexRust.cxx
105 lines changed, 69 insertions(+), 36 deletions(-)
===================================================================
@@ -230,7 +230,9 @@ static void ScanIdentifier(Accessor& styler, int& pos, WordList *keywords) {
}
}
-static void ScanDigits(Accessor& styler, int& pos, int base) {
+/* Scans a sequence of digits, returning true if it found any. */
+static bool ScanDigits(Accessor& styler, int& pos, int base) {
+ int old_pos = pos;
for (;;) {
int c = styler.SafeGetCharAt(pos, '\0');
if (IsADigit(c, base) || c == '_')
@@ -238,13 +240,17 @@ static void ScanDigits(Accessor& styler, int& pos, int base) {
else
break;
}
+ return old_pos != pos;
}
+/* Scans an integer and floating point literals. */
static void ScanNumber(Accessor& styler, int& pos) {
int base = 10;
int c = styler.SafeGetCharAt(pos, '\0');
int n = styler.SafeGetCharAt(pos + 1, '\0');
bool error = false;
+ /* Scan the prefix, thus determining the base.
+ * 10 is default if there's no prefix. */
if (c == '0' && n == 'x') {
pos += 2;
base = 16;
@@ -255,8 +261,11 @@ static void ScanNumber(Accessor& styler, int& pos) {
pos += 2;
base = 8;
}
- int old_pos = pos;
- ScanDigits(styler, pos, base);
+
+ /* Scan initial digits. The literal is malformed if there are none. */
+ error |= !ScanDigits(styler, pos, base);
+ /* See if there's an integer suffix. We mimic the Rust's lexer
+ * and munch it even if there was an error above. */
c = styler.SafeGetCharAt(pos, '\0');
if (c == 'u' || c == 'i') {
pos++;
@@ -271,14 +280,22 @@ static void ScanNumber(Accessor& styler, int& pos) {
} else if (c == '6' && n == '4') {
pos += 2;
}
- } else {
+ /* See if it's a floating point literal. These literals have to be base 10.
+ */
+ } else if (!error) {
+ /* If there's a period, it's a floating point literal unless it's
+ * followed by an identifier (meaning this is a method call, e.g.
+ * `1.foo()`) or another period, in which case it's a range (e.g. 1..2)
+ */
n = styler.SafeGetCharAt(pos + 1, '\0');
if (c == '.' && !(IsIdentifierStart(n) || n == '.')) {
error |= base != 10;
pos++;
+ /* It's ok to have no digits after the period. */
ScanDigits(styler, pos, 10);
}
+ /* Look for the exponentiation. */
c = styler.SafeGetCharAt(pos, '\0');
if (c == 'e' || c == 'E') {
error |= base != 10;
@@ -286,13 +303,11 @@ static void ScanNumber(Accessor& styler, int& pos) {
c = styler.SafeGetCharAt(pos, '\0');
if (c == '-' || c == '+')
pos++;
- int old_pos = pos;
- ScanDigits(styler, pos, 10);
- if (old_pos == pos) {
- error = true;
- }
+ /* It is invalid to have no digits in the exponent. */
+ error |= !ScanDigits(styler, pos, 10);
}
+ /* Scan the floating point suffix. */
c = styler.SafeGetCharAt(pos, '\0');
if (c == 'f') {
error |= base != 10;
@@ -308,9 +323,7 @@ static void ScanNumber(Accessor& styler, int& pos) {
}
}
}
- if (old_pos == pos) {
- error = true;
- }
+
if (error)
styler.ColourTo(pos - 1, SCE_RUST_LEXERROR);
else
@@ -351,7 +364,7 @@ static bool IsValidCharacterEscape(int c) {
}
static bool IsValidStringEscape(int c) {
- return IsValidCharacterEscape(c) || c == '\n';
+ return IsValidCharacterEscape(c) || c == '\n' || c == '\r';
}
static bool ScanNumericEscape(Accessor &styler, int& pos, int num_digits, bool stop_asap) {
@@ -373,12 +386,12 @@ static bool ScanNumericEscape(Accessor &styler, int& pos, int num_digits, bool s
/* This is overly permissive for character literals in order to accept UTF-8 encoded
* character literals. */
-static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) {
+static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos, bool ascii_only) {
pos++;
int c = styler.SafeGetCharAt(pos, '\0');
int n = styler.SafeGetCharAt(pos + 1, '\0');
bool done = false;
- bool valid_lifetime = IsIdentifierStart(c);
+ bool valid_lifetime = !ascii_only && IsIdentifierStart(c);
bool valid_char = true;
bool first = true;
while (!done) {
@@ -390,10 +403,10 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) {
} else if (n == 'x') {
pos += 2;
valid_char = ScanNumericEscape(styler, pos, 2, false);
- } else if (n == 'u') {
+ } else if (n == 'u' && !ascii_only) {
pos += 2;
valid_char = ScanNumericEscape(styler, pos, 4, false);
- } else if (n == 'U') {
+ } else if (n == 'U' && !ascii_only) {
pos += 2;
valid_char = ScanNumericEscape(styler, pos, 8, false);
} else {
@@ -412,7 +425,10 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) {
done = true;
break;
default:
- if (!IsIdentifierContinue(c) && !first) {
+ if (ascii_only && !IsASCII((char)c)) {
+ done = true;
+ valid_char = false;
+ } else if (!IsIdentifierContinue(c) && !first) {
done = true;
} else {
pos++;
@@ -433,7 +449,7 @@ static void ScanCharacterLiteralOrLifetime(Accessor &styler, int& pos) {
styler.ColourTo(pos - 1, SCE_RUST_LIFETIME);
} else if (valid_char) {
pos++;
- styler.ColourTo(pos - 1, SCE_RUST_CHARACTER);
+ styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTECHARACTER : SCE_RUST_CHARACTER);
} else {
styler.ColourTo(pos - 1, SCE_RUST_LEXERROR);
}
@@ -542,7 +558,7 @@ static void ScanComments(Accessor &styler, int& pos, int max) {
ResumeBlockComment(styler, pos, max, UnknownComment, 1);
}
-static void ResumeString(Accessor &styler, int& pos, int max) {
+static void ResumeString(Accessor &styler, int& pos, int max, bool ascii_only) {
int c = styler.SafeGetCharAt(pos, '\0');
bool error = false;
while (c != '"' && !error) {
@@ -559,10 +575,10 @@ static void ResumeString(Accessor &styler, int& pos, int max) {
} else if (n == 'x') {
pos += 2;
error = !ScanNumericEscape(styler, pos, 2, true);
- } else if (n == 'u') {
+ } else if (n == 'u' && !ascii_only) {
pos += 2;
error = !ScanNumericEscape(styler, pos, 4, true);
- } else if (n == 'U') {
+ } else if (n == 'U' && !ascii_only) {
pos += 2;
error = !ScanNumericEscape(styler, pos, 8, true);
} else {
@@ -570,16 +586,19 @@ static void ResumeString(Accessor &styler, int& pos, int max) {
error = true;
}
} else {
- pos++;
+ if (ascii_only && !IsASCII((char)c))
+ error = true;
+ else
+ pos++;
}
c = styler.SafeGetCharAt(pos, '\0');
}
if (!error)
pos++;
- styler.ColourTo(pos - 1, SCE_RUST_STRING);
+ styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTESTRING : SCE_RUST_STRING);
}
-static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes) {
+static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes, bool ascii_only) {
for (;;) {
if (pos == styler.LineEnd(styler.GetLine(pos)))
styler.SetLineState(styler.GetLine(pos), num_hashes);
@@ -594,19 +613,20 @@ static void ResumeRawString(Accessor &styler, int& pos, int max, int num_hashes)
}
if (trailing_num_hashes == num_hashes) {
styler.SetLineState(styler.GetLine(pos), 0);
- styler.ColourTo(pos - 1, SCE_RUST_STRINGR);
break;
}
} else if (pos >= max) {
- styler.ColourTo(pos - 1, SCE_RUST_STRINGR);
break;
- } else {
+ } else {
+ if (ascii_only && !IsASCII((char)c))
+ break;
pos++;
}
}
+ styler.ColourTo(pos - 1, ascii_only ? SCE_RUST_BYTESTRINGR : SCE_RUST_STRINGR);
}
-static void ScanRawString(Accessor &styler, int& pos, int max) {
+static void ScanRawString(Accessor &styler, int& pos, int max, bool ascii_only) {
pos++;
int num_hashes = 0;
while (styler.SafeGetCharAt(pos, '\0') == '#') {
@@ -617,7 +637,7 @@ static void ScanRawString(Accessor &styler, int& pos, int max) {
styler.ColourTo(pos - 1, SCE_RUST_LEXERROR);
} else {
pos++;
- ResumeRawString(styler, pos, max, num_hashes);
+ ResumeRawString(styler, pos, max, num_hashes, ascii_only);
}
}
@@ -635,9 +655,13 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle,
} else if (initStyle == SCE_RUST_COMMENTLINE || initStyle == SCE_RUST_COMMENTLINEDOC) {
ResumeLineComment(styler, pos, max, initStyle == SCE_RUST_COMMENTLINEDOC ? DocComment : NotDocComment);
} else if (initStyle == SCE_RUST_STRING) {
- ResumeString(styler, pos, max);
+ ResumeString(styler, pos, max, false);
+ } else if (initStyle == SCE_RUST_BYTESTRING) {
+ ResumeString(styler, pos, max, true);
} else if (initStyle == SCE_RUST_STRINGR) {
- ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1));
+ ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1), false);
+ } else if (initStyle == SCE_RUST_BYTESTRINGR) {
+ ResumeRawString(styler, pos, max, styler.GetLineState(styler.GetLine(pos) - 1), true);
}
while (pos < max) {
@@ -645,7 +669,7 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle,
int n = styler.SafeGetCharAt(pos + 1, '\0');
int n2 = styler.SafeGetCharAt(pos + 2, '\0');
- if (pos == 0 && c == '#' && n == '!') {
+ if (pos == 0 && c == '#' && n == '!' && n2 != '[') {
pos += 2;
ResumeLineComment(styler, pos, max, NotDocComment);
} else if (IsWhitespace(c)) {
@@ -653,7 +677,16 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle,
} else if (c == '/' && (n == '/' || n == '*')) {
ScanComments(styler, pos, max);
} else if (c == 'r' && (n == '#' || n == '"')) {
- ScanRawString(styler, pos, max);
+ ScanRawString(styler, pos, max, false);
+ } else if (c == 'b' && n == 'r' && (n2 == '#' || n2 == '"')) {
+ pos++;
+ ScanRawString(styler, pos, max, true);
+ } else if (c == 'b' && n == '"') {
+ pos += 2;
+ ResumeString(styler, pos, max, true);
+ } else if (c == 'b' && n == '\'') {
+ pos++;
+ ScanCharacterLiteralOrLifetime(styler, pos, true);
} else if (IsIdentifierStart(c)) {
ScanIdentifier(styler, pos, keywords);
} else if (IsADigit(c)) {
@@ -668,10 +701,10 @@ void SCI_METHOD LexerRust::Lex(unsigned int startPos, int length, int initStyle,
pos++;
styler.ColourTo(pos - 1, SCE_RUST_OPERATOR);
} else if (c == '\'') {
- ScanCharacterLiteralOrLifetime(styler, pos);
+ ScanCharacterLiteralOrLifetime(styler, pos, false);
} else if (c == '"') {
pos++;
- ResumeString(styler, pos, max);
+ ResumeString(styler, pos, max, false);
} else {
pos++;
styler.ColourTo(pos - 1, SCE_RUST_LEXERROR);
Modified: scintilla/lexlib/LexerModule.h
7 lines changed, 6 insertions(+), 1 deletions(-)
===================================================================
@@ -67,7 +67,12 @@ inline int Maximum(int a, int b) {
// Shut up annoying Visual C++ warnings:
#ifdef _MSC_VER
-#pragma warning(disable: 4244 4309)
+#pragma warning(disable: 4244 4309 4456 4457)
+#endif
+
+// Turn off shadow warnings for lexers as may be maintained by others
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wshadow"
#endif
#ifdef SCI_NAMESPACE
Modified: scintilla/makefile.win32
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -130,10 +130,13 @@ SRCOBJS=\
Decoration.o \
Document.o \
Editor.o \
+ EditModel.o \
+ EditView.o \
ExternalLexer.o \
Indicator.o \
KeyMap.o \
LineMarker.o \
+ MarginView.o \
PerLine.o \
PositionCache.o \
RESearch.o \
Modified: scintilla/scintilla_changes.patch
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -31,7 +31,7 @@ diff --git b/scintilla/src/Catalogue.cxx a/scintilla/src/Catalogue.cxx
index 41d5d54..70ce3bc 100644
--- scintilla/src/Catalogue.cxx
+++ scintilla/src/Catalogue.cxx
-@@ -76,115 +76,48 @@ int Scintilla_LinkLexers() {
+@@ -76,116 +76,48 @@ int Scintilla_LinkLexers() {
//++Autogenerated -- run scripts/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
@@ -123,6 +123,7 @@ index 41d5d54..70ce3bc 100644
LINK_LEXER(lmPython);
LINK_LEXER(lmR);
- LINK_LEXER(lmREBOL);
+- LINK_LEXER(lmRegistry);
LINK_LEXER(lmRuby);
LINK_LEXER(lmRust);
- LINK_LEXER(lmScriptol);
Modified: scintilla/src/CellBuffer.cxx
40 lines changed, 39 insertions(+), 1 deletions(-)
===================================================================
@@ -144,6 +144,7 @@ UndoHistory::UndoHistory() {
currentAction = 0;
undoSequenceDepth = 0;
savePoint = 0;
+ tentativePoint = -1;
actions[currentAction].Create(startAction);
}
@@ -194,7 +195,7 @@ const char *UndoHistory::AppendAction(actionType at, int position, const char *d
// Visual Studio 2013 Code Analysis wrongly believes actions can be NULL at its next reference
__analysis_assume(actions);
#endif
- if (currentAction == savePoint) {
+ if ((currentAction == savePoint) || (currentAction == tentativePoint)) {
currentAction++;
} else if (!actions[currentAction].mayCoalesce) {
// Not allowed to coalesce if this set
@@ -282,6 +283,7 @@ void UndoHistory::DeleteUndoHistory() {
currentAction = 0;
actions[currentAction].Create(startAction);
savePoint = 0;
+ tentativePoint = -1;
}
void UndoHistory::SetSavePoint() {
@@ -292,6 +294,26 @@ bool UndoHistory::IsSavePoint() const {
return savePoint == currentAction;
}
+void UndoHistory::TentativeStart() {
+ tentativePoint = currentAction;
+}
+
+void UndoHistory::TentativeCommit() {
+ tentativePoint = -1;
+ // Truncate undo history
+ maxAction = currentAction;
+}
+
+int UndoHistory::TentativeSteps() {
+ // Drop any trailing startAction
+ if (actions[currentAction].at == startAction && currentAction > 0)
+ currentAction--;
+ if (tentativePoint >= 0)
+ return currentAction - tentativePoint;
+ else
+ return -1;
+}
+
bool UndoHistory::CanUndo() const {
return (currentAction > 0) && (maxAction > 0);
}
@@ -505,6 +527,22 @@ bool CellBuffer::IsSavePoint() const {
return uh.IsSavePoint();
}
+void CellBuffer::TentativeStart() {
+ uh.TentativeStart();
+}
+
+void CellBuffer::TentativeCommit() {
+ uh.TentativeCommit();
+}
+
+int CellBuffer::TentativeSteps() {
+ return uh.TentativeSteps();
+}
+
+bool CellBuffer::TentativeActive() const {
+ return uh.TentativeActive();
+}
+
// Without undo
void CellBuffer::InsertLine(int line, int position, bool lineStart) {
Modified: scintilla/src/CellBuffer.h
12 lines changed, 12 insertions(+), 0 deletions(-)
===================================================================
@@ -95,6 +95,7 @@ class UndoHistory {
int currentAction;
int undoSequenceDepth;
int savePoint;
+ int tentativePoint;
void EnsureUndoRoom();
@@ -117,6 +118,12 @@ class UndoHistory {
void SetSavePoint();
bool IsSavePoint() const;
+ // Tentative actions are used for input composition so that it can be undone cleanly
+ void TentativeStart();
+ void TentativeCommit();
+ bool TentativeActive() const { return tentativePoint >= 0; }
+ int TentativeSteps();
+
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
/// called that many times. Similarly for redo.
bool CanUndo() const;
@@ -193,6 +200,11 @@ class CellBuffer {
void SetSavePoint();
bool IsSavePoint() const;
+ void TentativeStart();
+ void TentativeCommit();
+ bool TentativeActive() const;
+ int TentativeSteps();
+
bool SetUndoCollection(bool collectUndo);
bool IsCollectingUndo() const;
void BeginUndoAction();
Modified: scintilla/src/ContractionState.cxx
18 lines changed, 9 insertions(+), 9 deletions(-)
===================================================================
@@ -150,8 +150,8 @@ bool ContractionState::GetVisible(int lineDoc) const {
}
}
-bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
- if (OneToOne() && visible_) {
+bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool isVisible) {
+ if (OneToOne() && isVisible) {
return false;
} else {
EnsureData();
@@ -159,9 +159,9 @@ bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible
Check();
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
for (int line = lineDocStart; line <= lineDocEnd; line++) {
- if (GetVisible(line) != visible_) {
- int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
- visible->SetValueAt(line, visible_ ? 1 : 0);
+ if (GetVisible(line) != isVisible) {
+ int difference = isVisible ? heights->ValueAt(line) : -heights->ValueAt(line);
+ visible->SetValueAt(line, isVisible ? 1 : 0);
displayLines->InsertText(line, difference);
delta += difference;
}
@@ -191,13 +191,13 @@ bool ContractionState::GetExpanded(int lineDoc) const {
}
}
-bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
- if (OneToOne() && expanded_) {
+bool ContractionState::SetExpanded(int lineDoc, bool isExpanded) {
+ if (OneToOne() && isExpanded) {
return false;
} else {
EnsureData();
- if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
- expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
+ if (isExpanded != (expanded->ValueAt(lineDoc) == 1)) {
+ expanded->SetValueAt(lineDoc, isExpanded ? 1 : 0);
Check();
return true;
} else {
Modified: scintilla/src/ContractionState.h
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -48,11 +48,11 @@ class ContractionState {
void DeleteLines(int lineDoc, int lineCount);
bool GetVisible(int lineDoc) const;
- bool SetVisible(int lineDocStart, int lineDocEnd, bool visible);
+ bool SetVisible(int lineDocStart, int lineDocEnd, bool isVisible);
bool HiddenLines() const;
bool GetExpanded(int lineDoc) const;
- bool SetExpanded(int lineDoc, bool expanded);
+ bool SetExpanded(int lineDoc, bool isExpanded);
int ContractedNext(int lineDocStart) const;
int GetHeight(int lineDoc) const;
Modified: scintilla/src/Document.cxx
59 lines changed, 59 insertions(+), 0 deletions(-)
===================================================================
@@ -209,6 +209,65 @@ void Document::SetSavePoint() {
NotifySavePoint(true);
}
+void Document::TentativeUndo() {
+ CheckReadOnly();
+ if (enteredModification == 0) {
+ enteredModification++;
+ if (!cb.IsReadOnly()) {
+ bool startSavePoint = cb.IsSavePoint();
+ bool multiLine = false;
+ int steps = cb.TentativeSteps();
+ //Platform::DebugPrintf("Steps=%d\n", steps);
+ for (int step = 0; step < steps; step++) {
+ const int prevLinesTotal = LinesTotal();
+ const Action &action = cb.GetUndoStep();
+ if (action.at == removeAction) {
+ NotifyModified(DocModification(
+ SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
+ } else if (action.at == containerAction) {
+ DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO);
+ dm.token = action.position;
+ NotifyModified(dm);
+ } else {
+ NotifyModified(DocModification(
+ SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
+ }
+ cb.PerformUndoStep();
+ if (action.at != containerAction) {
+ ModifiedAt(action.position);
+ }
+
+ int modFlags = SC_PERFORMED_UNDO;
+ // With undo, an insertion action becomes a deletion notification
+ if (action.at == removeAction) {
+ modFlags |= SC_MOD_INSERTTEXT;
+ } else if (action.at == insertAction) {
+ modFlags |= SC_MOD_DELETETEXT;
+ }
+ if (steps > 1)
+ modFlags |= SC_MULTISTEPUNDOREDO;
+ const int linesAdded = LinesTotal() - prevLinesTotal;
+ if (linesAdded != 0)
+ multiLine = true;
+ if (step == steps - 1) {
+ modFlags |= SC_LASTSTEPINUNDOREDO;
+ if (multiLine)
+ modFlags |= SC_MULTILINEUNDOREDO;
+ }
+ NotifyModified(DocModification(modFlags, action.position, action.lenData,
+ linesAdded, action.data));
+ }
+
+ bool endSavePoint = cb.IsSavePoint();
+ if (startSavePoint != endSavePoint)
+ NotifySavePoint(endSavePoint);
+
+ cb.TentativeCommit();
+ }
+ enteredModification--;
+ }
+}
+
int Document::GetMark(int line) {
return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkValue(line);
}
Modified: scintilla/src/Document.h
8 lines changed, 7 insertions(+), 1 deletions(-)
===================================================================
@@ -303,6 +303,12 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
void SetSavePoint();
bool IsSavePoint() const { return cb.IsSavePoint(); }
+
+ void TentativeStart() { cb.TentativeStart(); }
+ void TentativeCommit() { cb.TentativeCommit(); }
+ void TentativeUndo();
+ bool TentativeActive() const { return cb.TentativeActive(); }
+
const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); }
const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); }
int GapPosition() const { return cb.GapPosition(); }
@@ -368,7 +374,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
void SetDefaultCharClasses(bool includeWordClass);
void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
- int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer);
+ int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer);
void SCI_METHOD StartStyling(int position, char mask);
bool SCI_METHOD SetStyleFor(int length, char style);
bool SCI_METHOD SetStyles(int length, const char *styles);
Modified: scintilla/src/EditModel.cxx
74 lines changed, 74 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,74 @@
+// Scintilla source code edit control
+/** @file EditModel.cxx
+ ** Defines the editor state that must be visible to EditorView.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh at scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "StringCopy.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "EditModel.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+Caret::Caret() :
+ active(false), on(false), period(500) {}
+
+EditModel::EditModel() {
+ inOverstrike = false;
+ xOffset = 0;
+ trackLineWidth = false;
+ posDrag = SelectionPosition(invalidPosition);
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+ bracesMatchStyle = STYLE_BRACEBAD;
+ highlightGuideColumn = 0;
+ primarySelection = true;
+ foldFlags = 0;
+ hotspot = Range(invalidPosition);
+ wrapWidth = LineLayout::wrapWidthInfinite;
+ pdoc = new Document();
+ pdoc->AddRef();
+}
+
+EditModel::~EditModel() {
+ pdoc->Release();
+ pdoc = 0;
+}
Modified: scintilla/src/EditModel.h
67 lines changed, 67 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,67 @@
+// Scintilla source code edit control
+/** @file EditModel.h
+ ** Defines the editor state that must be visible to EditorView.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh at scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EDITMODEL_H
+#define EDITMODEL_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+*/
+class Caret {
+public:
+ bool active;
+ bool on;
+ int period;
+
+ Caret();
+};
+
+class EditModel {
+ // Private so EditModel objects can not be copied
+ EditModel(const EditModel &);
+ EditModel &operator=(const EditModel &);
+
+public:
+ bool inOverstrike;
+ int xOffset; ///< Horizontal scrolled amount in pixels
+ bool trackLineWidth;
+
+ SpecialRepresentations reprs;
+ Caret caret;
+ SelectionPosition posDrag;
+ Position braces[2];
+ int bracesMatchStyle;
+ int highlightGuideColumn;
+ Selection sel;
+ bool primarySelection;
+
+ int foldFlags;
+ ContractionState cs;
+ // Hotspot support
+ Range hotspot;
+
+ // Wrapping support
+ int wrapWidth;
+
+ Document *pdoc;
+
+ EditModel();
+ virtual ~EditModel();
+ virtual int TopLineOfMain() const = 0;
+ virtual Point GetVisibleOriginInMain() const = 0;
+ virtual int LinesOnScreen() const = 0;
+ virtual Range GetHotSpotRange() const = 0;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
Modified: scintilla/src/EditView.cxx
2072 lines changed, 2072 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,2072 @@
+// Scintilla source code edit control
+/** @file Editor.cxx
+ ** Defines the appearance of the main text area of the editor window.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh at scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "StringCopy.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "PerLine.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsControlCharacter(int ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+PrintParameters::PrintParameters() {
+ magnification = 0;
+ colourMode = SC_PRINT_NORMAL;
+ wrapState = eWrapWord;
+}
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) {
+ if (st.multipleStyles) {
+ for (size_t iStyle = 0; iStyle<st.length; iStyle++) {
+ if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
+ return false;
+ }
+ } else {
+ if (!vs.ValidStyle(styleOffset + st.style))
+ return false;
+ }
+ return true;
+}
+
+static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset,
+ const char *text, const unsigned char *styles, size_t len) {
+ int width = 0;
+ size_t start = 0;
+ while (start < len) {
+ size_t style = styles[start];
+ size_t endSegment = start;
+ while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style))
+ endSegment++;
+ FontAlias fontText = vs.styles[style + styleOffset].font;
+ width += static_cast<int>(surface->WidthText(fontText, text + start,
+ static_cast<int>(endSegment - start + 1)));
+ start = endSegment + 1;
+ }
+ return width;
+}
+
+int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) {
+ int widthMax = 0;
+ size_t start = 0;
+ while (start < st.length) {
+ size_t lenLine = st.LineLength(start);
+ int widthSubLine;
+ if (st.multipleStyles) {
+ widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
+ } else {
+ FontAlias fontText = vs.styles[styleOffset + st.style].font;
+ widthSubLine = static_cast<int>(surface->WidthText(fontText,
+ st.text + start, static_cast<int>(lenLine)));
+ }
+ if (widthSubLine > widthMax)
+ widthMax = widthSubLine;
+ start += lenLine + 1;
+ }
+ return widthMax;
+}
+
+void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase,
+ const char *s, int len, DrawPhase phase) {
+ FontAlias fontText = style.font;
+ if (phase & drawBack) {
+ if (phase & drawText) {
+ // Drawing both
+ surface->DrawTextNoClip(rc, fontText, ybase, s, len,
+ style.fore, style.back);
+ } else {
+ surface->FillRectangle(rc, style.back);
+ }
+ } else if (phase & drawText) {
+ surface->DrawTextTransparent(rc, fontText, ybase, s, len, style.fore);
+ }
+}
+
+void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
+ const StyledText &st, size_t start, size_t length, DrawPhase phase) {
+
+ if (st.multipleStyles) {
+ int x = static_cast<int>(rcText.left);
+ size_t i = 0;
+ while (i < length) {
+ size_t end = i;
+ size_t style = st.styles[i + start];
+ while (end < length - 1 && st.styles[start + end + 1] == style)
+ end++;
+ style += styleOffset;
+ FontAlias fontText = vs.styles[style].font;
+ const int width = static_cast<int>(surface->WidthText(fontText,
+ st.text + start + i, static_cast<int>(end - i + 1)));
+ PRectangle rcSegment = rcText;
+ rcSegment.left = static_cast<XYPOSITION>(x);
+ rcSegment.right = static_cast<XYPOSITION>(x + width + 1);
+ DrawTextNoClipPhase(surface, rcSegment, vs.styles[style],
+ rcText.top + vs.maxAscent, st.text + start + i,
+ static_cast<int>(end - i + 1), phase);
+ x += width;
+ i = end + 1;
+ }
+ } else {
+ const size_t style = st.style + styleOffset;
+ DrawTextNoClipPhase(surface, rcText, vs.styles[style],
+ rcText.top + vs.maxAscent, st.text + start,
+ static_cast<int>(length), phase);
+ }
+}
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues
+
+EditView::EditView() {
+ ldTabstops = NULL;
+ hideSelection = false;
+ drawOverstrikeCaret = true;
+ bufferedDraw = true;
+ phasesDraw = phasesTwo;
+ lineWidthMaxSeen = 0;
+ additionalCaretsBlink = true;
+ additionalCaretsVisible = true;
+ imeCaretBlockOverride = false;
+ pixmapLine = 0;
+ pixmapIndentGuide = 0;
+ pixmapIndentGuideHighlight = 0;
+ llc.SetLevel(LineLayoutCache::llcCaret);
+ posCache.SetSize(0x400);
+}
+
+EditView::~EditView() {
+ delete ldTabstops;
+ ldTabstops = NULL;
+}
+
+bool EditView::SetTwoPhaseDraw(bool twoPhaseDraw) {
+ const PhasesDraw phasesDrawNew = twoPhaseDraw ? phasesTwo : phasesOne;
+ const bool redraw = phasesDraw != phasesDrawNew;
+ phasesDraw = phasesDrawNew;
+ return redraw;
+}
+
+bool EditView::SetPhasesDraw(int phases) {
+ const PhasesDraw phasesDrawNew = static_cast<PhasesDraw>(phases);
+ const bool redraw = phasesDraw != phasesDrawNew;
+ phasesDraw = phasesDrawNew;
+ return redraw;
+}
+
+bool EditView::LinesOverlap() const {
+ return phasesDraw == phasesMultiple;
+}
+
+void EditView::ClearAllTabstops() {
+ delete ldTabstops;
+ ldTabstops = 0;
+}
+
+int EditView::NextTabstopPos(int line, int x, int tabWidth) const {
+ int next = GetNextTabstop(line, x);
+ if (next > 0)
+ return next;
+ return ((((x + 2) / tabWidth) + 1) * tabWidth);
+}
+
+bool EditView::ClearTabstops(int line) {
+ LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops);
+ return lt && lt->ClearTabstops(line);
+}
+
+bool EditView::AddTabstop(int line, int x) {
+ if (!ldTabstops) {
+ ldTabstops = new LineTabstops();
+ }
+ LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops);
+ return lt && lt->AddTabstop(line, x);
+}
+
+int EditView::GetNextTabstop(int line, int x) const {
+ LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops);
+ if (lt) {
+ return lt->GetNextTabstop(line, x);
+ } else {
+ return 0;
+ }
+}
+
+void EditView::LinesAddedOrRemoved(int lineOfPos, int linesAdded) {
+ if (ldTabstops) {
+ if (linesAdded > 0) {
+ for (int line = lineOfPos; line < lineOfPos + linesAdded; line++) {
+ ldTabstops->InsertLine(line);
+ }
+ } else {
+ for (int line = (lineOfPos + -linesAdded) - 1; line >= lineOfPos; line--) {
+ ldTabstops->RemoveLine(line);
+ }
+ }
+ }
+}
+
+void EditView::DropGraphics(bool freeObjects) {
+ if (freeObjects) {
+ delete pixmapLine;
+ pixmapLine = 0;
+ delete pixmapIndentGuide;
+ pixmapIndentGuide = 0;
+ delete pixmapIndentGuideHighlight;
+ pixmapIndentGuideHighlight = 0;
+ } else {
+ if (pixmapLine)
+ pixmapLine->Release();
+ if (pixmapIndentGuide)
+ pixmapIndentGuide->Release();
+ if (pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight->Release();
+ }
+}
+
+void EditView::AllocateGraphics(const ViewStyle &vsDraw) {
+ if (!pixmapLine)
+ pixmapLine = Surface::Allocate(vsDraw.technology);
+ if (!pixmapIndentGuide)
+ pixmapIndentGuide = Surface::Allocate(vsDraw.technology);
+ if (!pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology);
+}
+
+const char *ControlCharacterString(unsigned char ch) {
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ if (ch < ELEMENTS(reps)) {
+ return reps[ch];
+ } else {
+ return "BAD";
+ }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+ int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2;
+ int xhead = static_cast<int>(rcTab.right) - 1 - ydiff;
+ if (xhead <= rcTab.left) {
+ ydiff -= static_cast<int>(rcTab.left) - xhead - 1;
+ xhead = static_cast<int>(rcTab.left) - 1;
+ }
+ if ((rcTab.left + 2) < (rcTab.right - 1))
+ surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid);
+ else
+ surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+}
+
+void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
+ if (!pixmapIndentGuide->Initialised()) {
+ // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
+ pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
+ pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
+ PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight);
+ pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back);
+ pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back);
+ pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore);
+ for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) {
+ PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1);
+ pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore);
+ }
+ }
+}
+
+LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) {
+ int posLineStart = model.pdoc->LineStart(lineNumber);
+ int posLineEnd = model.pdoc->LineStart(lineNumber + 1);
+ PLATFORM_ASSERT(posLineEnd >= posLineStart);
+ int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret());
+ return llc.Retrieve(lineNumber, lineCaret,
+ posLineEnd - posLineStart, model.pdoc->GetStyleClock(),
+ model.LinesOnScreen() + 1, model.pdoc->LinesTotal());
+}
+
+/**
+* Fill in the LineLayout data for the given line.
+* Copy the given @a line and its styles from the document into local arrays.
+* Also determine the x position at which each character starts.
+*/
+void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, int width) {
+ if (!ll)
+ return;
+
+ PLATFORM_ASSERT(line < model.pdoc->LinesTotal());
+ PLATFORM_ASSERT(ll->chars != NULL);
+ int posLineStart = model.pdoc->LineStart(line);
+ int posLineEnd = model.pdoc->LineStart(line + 1);
+ // If the line is very long, limit the treatment to a length that should fit in the viewport
+ if (posLineEnd >(posLineStart + ll->maxLineLength)) {
+ posLineEnd = posLineStart + ll->maxLineLength;
+ }
+ if (ll->validity == LineLayout::llCheckTextAndStyle) {
+ int lineLength = posLineEnd - posLineStart;
+ if (!vstyle.viewEOL) {
+ lineLength = model.pdoc->LineEnd(line) - posLineStart;
+ }
+ if (lineLength == ll->numCharsInLine) {
+ // See if chars, styles, indicators, are all the same
+ bool allSame = true;
+ // Check base line layout
+ char styleByte = 0;
+ int numCharsInLine = 0;
+ while (numCharsInLine < lineLength) {
+ int charInDoc = numCharsInLine + posLineStart;
+ char chDoc = model.pdoc->CharAt(charInDoc);
+ styleByte = model.pdoc->StyleAt(charInDoc);
+ allSame = allSame &&
+ (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte));
+ if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == chDoc);
+ else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+ else // Style::caseUpper
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+ numCharsInLine++;
+ }
+ allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
+ if (allSame) {
+ ll->validity = LineLayout::llPositions;
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ }
+ if (ll->validity == LineLayout::llInvalid) {
+ ll->widthLine = LineLayout::wrapWidthInfinite;
+ ll->lines = 1;
+ if (vstyle.edgeState == EDGE_BACKGROUND) {
+ ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge);
+ if (ll->edgeColumn >= posLineStart) {
+ ll->edgeColumn -= posLineStart;
+ }
+ } else {
+ ll->edgeColumn = -1;
+ }
+
+ // Fill base line layout
+ const int lineLength = posLineEnd - posLineStart;
+ model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
+ model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
+ int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart;
+ const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
+ for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
+ const unsigned char styleByte = ll->styles[styleInLine];
+ ll->styles[styleInLine] = styleByte;
+ }
+ const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0;
+ if (vstyle.someStylesForceCase) {
+ for (int charInLine = 0; charInLine<lineLength; charInLine++) {
+ char chDoc = ll->chars[charInLine];
+ if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper)
+ ll->chars[charInLine] = static_cast<char>(toupper(chDoc));
+ else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower)
+ ll->chars[charInLine] = static_cast<char>(tolower(chDoc));
+ }
+ }
+ ll->xHighlightGuide = 0;
+ // Extra element at the end of the line to hold end x position and act as
+ ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character
+ ll->styles[numCharsInLine] = styleByteLast; // For eolFilled
+
+ // Layout the line, determining the position of each character,
+ // with an extra element at the end for the end of the line.
+ ll->positions[0] = 0;
+ bool lastSegItalics = false;
+
+ BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs);
+ while (bfLayout.More()) {
+
+ const TextSegment ts = bfLayout.Next();
+
+ std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f);
+ if (vstyle.styles[ll->styles[ts.start]].visible) {
+ if (ts.representation) {
+ XYPOSITION representationWidth = vstyle.controlCharWidth;
+ if (ll->chars[ts.start] == '\t') {
+ // Tab is a special case of representation, taking a variable amount of space
+ const int x = static_cast<int>(ll->positions[ts.start]);
+ const int tabWidth = static_cast<int>(vstyle.tabWidth);
+ representationWidth = static_cast<XYPOSITION>(NextTabstopPos(line, x, tabWidth) - ll->positions[ts.start]);
+ } else {
+ if (representationWidth <= 0.0) {
+ XYPOSITION positionsRepr[256]; // Should expand when needed
+ posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(),
+ static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, model.pdoc);
+ representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding;
+ }
+ }
+ for (int ii = 0; ii < ts.length; ii++)
+ ll->positions[ts.start + 1 + ii] = representationWidth;
+ } else {
+ if ((ts.length == 1) && (' ' == ll->chars[ts.start])) {
+ // Over half the segments are single characters and of these about half are space characters.
+ ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth;
+ } else {
+ posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start,
+ ts.length, ll->positions + ts.start + 1, model.pdoc);
+ }
+ }
+ lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic);
+ }
+
+ for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) {
+ ll->positions[posToIncrease] += ll->positions[ts.start];
+ }
+ }
+
+ // Small hack to make lines that end with italics not cut off the edge of the last character
+ if (lastSegItalics) {
+ ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset;
+ }
+ ll->numCharsInLine = numCharsInLine;
+ ll->numCharsBeforeEOL = numCharsBeforeEOL;
+ ll->validity = LineLayout::llPositions;
+ }
+ // Hard to cope when too narrow, so just assume there is space
+ if (width < 20) {
+ width = 20;
+ }
+ if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
+ ll->widthLine = width;
+ if (width == LineLayout::wrapWidthInfinite) {
+ ll->lines = 1;
+ } else if (width > ll->positions[ll->numCharsInLine]) {
+ // Simple common case where line does not need wrapping.
+ ll->lines = 1;
+ } else {
+ if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark
+ }
+ XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line
+ if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) {
+ wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth;
+ } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) {
+ wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth;
+ }
+ ll->wrapIndent = wrapAddIndent;
+ if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED)
+ for (int i = 0; i < ll->numCharsInLine; i++) {
+ if (!IsSpaceOrTab(ll->chars[i])) {
+ ll->wrapIndent += ll->positions[i]; // Add line indent
+ break;
+ }
+ }
+ // Check for text width minimum
+ if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
+ ll->wrapIndent = wrapAddIndent;
+ // Check for wrapIndent minimum
+ if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth))
+ ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
+ ll->lines = 0;
+ // Calculate line start positions based upon width.
+ int lastGoodBreak = 0;
+ int lastLineStart = 0;
+ XYACCUMULATOR startOffset = 0;
+ int p = 0;
+ while (p < ll->numCharsInLine) {
+ if ((ll->positions[p + 1] - startOffset) >= width) {
+ if (lastGoodBreak == lastLineStart) {
+ // Try moving to start of last character
+ if (p > 0) {
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ }
+ if (lastGoodBreak == lastLineStart) {
+ // Ensure at least one character on line.
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
+ - posLineStart;
+ }
+ }
+ lastLineStart = lastGoodBreak;
+ ll->lines++;
+ ll->SetLineStart(ll->lines, lastGoodBreak);
+ startOffset = ll->positions[lastGoodBreak];
+ // take into account the space for start wrap mark and indent
+ startOffset -= ll->wrapIndent;
+ p = lastGoodBreak + 1;
+ continue;
+ }
+ if (p > 0) {
+ if (vstyle.wrapState == eWrapChar) {
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
+ continue;
+ } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) {
+ lastGoodBreak = p;
+ } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
+ lastGoodBreak = p;
+ }
+ }
+ p++;
+ }
+ ll->lines++;
+ }
+ ll->validity = LineLayout::llLines;
+ }
+}
+
+Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs) {
+ Point pt;
+ if (pos.Position() == INVALID_POSITION)
+ return pt;
+ const int line = model.pdoc->LineFromPosition(pos.Position());
+ const int lineVisible = model.cs.DisplayFromDoc(line);
+ //Platform::DebugPrintf("line=%d\n", line);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
+ if (surface && ll) {
+ const int posLineStart = model.pdoc->LineStart(line);
+ LayoutLine(model, line, surface, vs, ll, model.wrapWidth);
+ const int posInLine = pos.Position() - posLineStart;
+ pt = ll->PointFromPosition(posInLine, vs.lineHeight);
+ pt.y += (lineVisible - topLine) * vs.lineHeight;
+ pt.x += vs.textStart - model.xOffset;
+ }
+ pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
+ return pt;
+}
+
+SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const ViewStyle &vs) {
+ pt.x = pt.x - vs.textStart;
+ int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight));
+ if (!canReturnInvalid && (visibleLine < 0))
+ visibleLine = 0;
+ const int lineDoc = model.cs.DocFromDisplay(visibleLine);
+ if (canReturnInvalid && (lineDoc < 0))
+ return SelectionPosition(INVALID_POSITION);
+ if (lineDoc >= model.pdoc->LinesTotal())
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length());
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth);
+ const int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
+ const int subLine = visibleLine - lineStartSet;
+ if (subLine < ll->lines) {
+ const Range rangeSubLine = ll->SubLineRange(subLine);
+ const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
+ if (subLine > 0) // Wrapped
+ pt.x -= ll->wrapIndent;
+ const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition);
+ if (positionInLine < rangeSubLine.end) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
+ }
+ if (virtualSpace) {
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ const int spaceOffset = static_cast<int>(
+ (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
+ return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
+ } else if (canReturnInvalid) {
+ if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1));
+ }
+ } else {
+ return SelectionPosition(rangeSubLine.end + posLineStart);
+ }
+ }
+ if (!canReturnInvalid)
+ return SelectionPosition(ll->numCharsInLine + posLineStart);
+ }
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart);
+}
+
+/**
+* Find the document position corresponding to an x coordinate on a particular document line.
+* Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
+* This method is used for rectangular selections and does not work on wrapped lines.
+*/
+SelectionPosition EditView::SPositionFromLineX(Surface *surface, const EditModel &model, int lineDoc, int x, const ViewStyle &vs) {
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth);
+ const Range rangeSubLine = ll->SubLineRange(0);
+ const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
+ const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false);
+ if (positionInLine < rangeSubLine.end) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
+ }
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ const int spaceOffset = static_cast<int>(
+ (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
+ return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
+ }
+ return SelectionPosition(0);
+}
+
+int EditView::DisplayFromPosition(Surface *surface, const EditModel &model, int pos, const ViewStyle &vs) {
+ int lineDoc = model.pdoc->LineFromPosition(pos);
+ int lineDisplay = model.cs.DisplayFromDoc(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth);
+ unsigned int posLineStart = model.pdoc->LineStart(lineDoc);
+ int posInLine = pos - posLineStart;
+ lineDisplay--; // To make up for first increment ahead.
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if (posInLine >= ll->LineStart(subLine)) {
+ lineDisplay++;
+ }
+ }
+ }
+ return lineDisplay;
+}
+
+int EditView::StartEndDisplayLine(Surface *surface, const EditModel &model, int pos, bool start, const ViewStyle &vs) {
+ int line = model.pdoc->LineFromPosition(pos);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
+ int posRet = INVALID_POSITION;
+ if (surface && ll) {
+ unsigned int posLineStart = model.pdoc->LineStart(line);
+ LayoutLine(model, line, surface, vs, ll, model.wrapWidth);
+ int posInLine = pos - posLineStart;
+ if (posInLine <= ll->maxLineLength) {
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ if (start) {
+ posRet = ll->LineStart(subLine) + posLineStart;
+ } else {
+ if (subLine == ll->lines - 1)
+ posRet = ll->LineStart(subLine + 1) + posLineStart;
+ else
+ posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
+ }
+ }
+ }
+ }
+ }
+ return posRet;
+}
+
+static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) {
+ return main ?
+ (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) :
+ vsDraw.selAdditionalBackground;
+}
+
+static ColourDesired TextBackground(const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i) {
+ if (inSelection == 1) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, true, model.primarySelection);
+ }
+ } else if (inSelection == 2) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, false, model.primarySelection);
+ }
+ } else {
+ if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
+ (i >= ll->edgeColumn) &&
+ (i < ll->numCharsBeforeEOL))
+ return vsDraw.edgecolour;
+ if (inHotspot && vsDraw.hotspotColours.back.isSet)
+ return vsDraw.hotspotColours.back;
+ }
+ if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
+ return background;
+ } else {
+ return vsDraw.styles[styleMain].back;
+ }
+}
+
+void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
+ Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
+ PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast<int>(rcSegment.top), start + 2, static_cast<int>(rcSegment.bottom));
+ surface->Copy(rcCopyArea, from,
+ highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
+}
+
+static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) {
+ if (alpha != SC_ALPHA_NOALPHA) {
+ surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
+ }
+}
+
+static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment,
+ const char *s, ColourDesired textBack, ColourDesired textFore, bool fillBackground) {
+ if (fillBackground) {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+ int normalCharHeight = static_cast<int>(surface->Ascent(ctrlCharsFont) -
+ surface->InternalLeading(ctrlCharsFont));
+ PRectangle rcCChar = rcSegment;
+ rcCChar.left = rcCChar.left + 1;
+ rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+ rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+ PRectangle rcCentral = rcCChar;
+ rcCentral.top++;
+ rcCentral.bottom--;
+ surface->FillRectangle(rcCentral, textFore);
+ PRectangle rcChar = rcCChar;
+ rcChar.left++;
+ rcChar.right--;
+ surface->DrawTextClipped(rcChar, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent, s, static_cast<int>(s ? strlen(s) : 0),
+ textBack, textFore);
+}
+
+void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ PRectangle rcLine, int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
+ ColourOptional background) {
+
+ const int posLineStart = model.pdoc->LineStart(line);
+ PRectangle rcSegment = rcLine;
+
+ const bool lastSubLine = subLine == (ll->lines - 1);
+ XYPOSITION virtualSpace = 0;
+ if (lastSubLine) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth;
+ }
+ XYPOSITION xEol = static_cast<XYPOSITION>(ll->positions[lineEnd] - subLineStart);
+
+ // Fill the virtual space and show selections within it
+ if (virtualSpace) {
+ rcSegment.left = xEol + xStart;
+ rcSegment.right = xEol + xStart + virtualSpace;
+ surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
+ SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))));
+ for (size_t r = 0; r<model.sel.Count(); r++) {
+ int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha == SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth;
+ rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
+ rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection));
+ }
+ }
+ }
+ }
+ }
+
+ int eolInSelection = 0;
+ int alpha = SC_ALPHA_NOALPHA;
+ if (!hideSelection) {
+ int posAfterLineEnd = model.pdoc->LineStart(line + 1);
+ eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ }
+
+ // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
+ XYPOSITION blobsWidth = 0;
+ if (lastSubLine) {
+ for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
+ rcSegment.left = xStart + ll->positions[eolPos] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
+ rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
+ blobsWidth += rcSegment.Width();
+ char hexits[4];
+ const char *ctrlChar;
+ unsigned char chEOL = ll->chars[eolPos];
+ int styleMain = ll->styles[eolPos];
+ ColourDesired textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, styleMain, eolPos);
+ if (UTF8IsAscii(chEOL)) {
+ ctrlChar = ControlCharacterString(chEOL);
+ } else {
+ const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos);
+ if (repr) {
+ ctrlChar = repr->stringRep.c_str();
+ eolPos = ll->numCharsInLine;
+ } else {
+ sprintf(hexits, "x%2X", chEOL);
+ ctrlChar = hexits;
+ }
+ }
+ ColourDesired textFore = vsDraw.styles[styleMain].fore;
+ if (eolInSelection && vsDraw.selColours.fore.isSet) {
+ textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) {
+ if (alpha == SC_ALPHA_NOALPHA) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, phasesDraw == phasesOne);
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+ }
+
+ // Draw the eol-is-selected rectangle
+ rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
+ rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
+
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ if (background.isSet) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (line < model.pdoc->LinesTotal() - 1) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+
+ // Fill the remainder of the line
+ rcSegment.left = rcSegment.right;
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ rcSegment.right = rcLine.right;
+
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ if (background.isSet) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+
+ bool drawWrapMarkEnd = false;
+
+ if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ if (subLine + 1 < ll->lines) {
+ drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
+ }
+ }
+
+ if (drawWrapMarkEnd) {
+ PRectangle rcPlace = rcSegment;
+
+ if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
+ rcPlace.left = xEol + xStart + virtualSpace;
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+ } else {
+ // rcLine is clipped to text area
+ rcPlace.right = rcLine.right;
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ }
+ DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
+ }
+}
+
+static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw,
+ const LineLayout *ll, int xStart, PRectangle rcLine, int subLine) {
+ const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
+ PRectangle rcIndic(
+ ll->positions[startPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll->positions[endPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine);
+}
+
+static void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int line, int xStart, PRectangle rcLine, int subLine, int lineEnd, bool under) {
+ // Draw decorators
+ const int posLineStart = model.pdoc->LineStart(line);
+ const int lineStart = ll->LineStart(subLine);
+ const int posLineEnd = posLineStart + lineEnd;
+
+ for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) {
+ if (under == vsDraw.indicators[deco->indicator].under) {
+ int startPos = posLineStart + lineStart;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
+ int endPos = deco->rs.EndRun(startPos);
+ if (endPos > posLineEnd)
+ endPos = posLineEnd;
+ DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
+ surface, vsDraw, ll, xStart, rcLine, subLine);
+ startPos = endPos;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ }
+ }
+ }
+
+ // Use indicators to highlight matching braces
+ if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) ||
+ (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) {
+ int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator;
+ if (under == vsDraw.indicators[braceIndicator].under) {
+ Range rangeLine(posLineStart + lineStart, posLineEnd);
+ if (rangeLine.ContainsCharacter(model.braces[0])) {
+ int braceOffset = model.braces[0] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine);
+ }
+ }
+ if (rangeLine.ContainsCharacter(model.braces[1])) {
+ int braceOffset = model.braces[1] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine);
+ }
+ }
+ }
+ }
+}
+
+void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
+ int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
+ PRectangle rcSegment = rcLine;
+ int annotationLine = subLine - ll->lines;
+ const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line);
+ if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
+ if (phase & drawBack) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
+ }
+ rcSegment.left = static_cast<XYPOSITION>(xStart);
+ if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
+ // Only care about calculating width if tracking or need to draw box
+ int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
+ }
+ if (widthAnnotation > lineWidthMaxSeen)
+ lineWidthMaxSeen = widthAnnotation;
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
+ rcSegment.right = rcSegment.left + widthAnnotation;
+ }
+ }
+ const int annotationLines = model.pdoc->AnnotationLines(line);
+ size_t start = 0;
+ size_t lengthAnnotation = stAnnotation.LineLength(start);
+ int lineInAnnotation = 0;
+ while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
+ start += lengthAnnotation + 1;
+ lengthAnnotation = stAnnotation.LineLength(start);
+ lineInAnnotation++;
+ }
+ PRectangle rcText = rcSegment;
+ if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
+ surface->FillRectangle(rcText,
+ vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
+ rcText.left += vsDraw.spaceWidth;
+ }
+ DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText,
+ stAnnotation, start, lengthAnnotation, phase);
+ if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
+ surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom));
+ surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom));
+ if (subLine == ll->lines) {
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ }
+ if (subLine == ll->lines + annotationLines - 1) {
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1));
+ }
+ }
+ }
+}
+
+static void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) {
+
+ int lineStart = ll->LineStart(subLine);
+ int posBefore = posCaret;
+ int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1);
+ int numCharsToDraw = posAfter - posCaret;
+
+ // Work out where the starting and ending offsets are. We need to
+ // see if the previous character shares horizontal space, such as a
+ // glyph / combining character. If so we'll need to draw that too.
+ int offsetFirstChar = offset;
+ int offsetLastChar = offset + (posAfter - posCaret);
+ while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) {
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ // Update posBefore to point to the prev char
+ posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1);
+ numCharsToDraw = posAfter - posBefore;
+ offsetFirstChar = offset - (posCaret - posBefore);
+ }
+
+ // See if the next character shares horizontal space, if so we'll
+ // need to draw that too.
+ if (offsetFirstChar < 0)
+ offsetFirstChar = 0;
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
+ // Update posAfter to point to the 2nd next char, this is where
+ // the next character ends, and 2nd next begins. We'll need
+ // to compare these two
+ posBefore = posAfter;
+ posAfter = model.pdoc->MovePositionOutsideChar(posAfter + 1, 1);
+ offsetLastChar = offset + (posAfter - posCaret);
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ }
+
+ // We now know what to draw, update the caret drawing rectangle
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
+ rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart;
+
+ // Adjust caret position to take into account any word wrapping symbols.
+ if ((ll->wrapIndent != 0) && (lineStart != 0)) {
+ XYPOSITION wordWrapCharWidth = ll->wrapIndent;
+ rcCaret.left += wordWrapCharWidth;
+ rcCaret.right += wordWrapCharWidth;
+ }
+
+ // This character is where the caret block is, we override the colours
+ // (inversed) for drawing the caret here.
+ int styleMain = ll->styles[offsetFirstChar];
+ FontAlias fontText = vsDraw.styles[styleMain].font;
+ surface->DrawTextClipped(rcCaret, fontText,
+ rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
+ numCharsToDraw, vsDraw.styles[styleMain].back,
+ caretColour);
+}
+
+void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ int lineDoc, int xStart, PRectangle rcLine, int subLine) const {
+ // When drag is active it is the only caret drawn
+ bool drawDrag = model.posDrag.IsValid();
+ if (hideSelection && !drawDrag)
+ return;
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ // For each selection draw
+ for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) {
+ const bool mainCaret = r == model.sel.Main();
+ const SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret);
+ const int offset = posCaret.Position() - posLineStart;
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
+ if (ll->InLine(offset, subLine) && offset <= ll->nu@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list