Update Scintilla to version 3.3.2

This commit is contained in:
Colomban Wendling 2013-05-22 03:23:57 +02:00
parent 55fe6d8b66
commit f5588043b7
46 changed files with 1770 additions and 1326 deletions

View File

@ -9,6 +9,7 @@
#include <stddef.h> #include <stddef.h>
#include <math.h> #include <math.h>
#include <string>
#include <vector> #include <vector>
#include <map> #include <map>
@ -259,6 +260,7 @@ class FontCached : Font {
public: public:
static FontID FindOrCreate(const FontParameters &fp); static FontID FindOrCreate(const FontParameters &fp);
static void ReleaseId(FontID fid_); static void ReleaseId(FontID fid_);
static void ReleaseAll();
}; };
FontCached *FontCached::first = 0; FontCached *FontCached::first = 0;
@ -299,11 +301,9 @@ FontID FontCached::FindOrCreate(const FontParameters &fp) {
} }
if (ret == 0) { if (ret == 0) {
FontCached *fc = new FontCached(fp); FontCached *fc = new FontCached(fp);
if (fc) { fc->next = first;
fc->next = first; first = fc;
first = fc; ret = fc->fid;
ret = fc->fid;
}
} }
FontMutexUnlock(); FontMutexUnlock();
return ret; return ret;
@ -328,6 +328,12 @@ void FontCached::ReleaseId(FontID fid_) {
FontMutexUnlock(); FontMutexUnlock();
} }
void FontCached::ReleaseAll() {
while (first) {
ReleaseId(first->GetID());
}
}
FontID FontCached::CreateNewFont(const FontParameters &fp) { FontID FontCached::CreateNewFont(const FontParameters &fp) {
PangoFontDescription *pfd = pango_font_description_new(); PangoFontDescription *pfd = pango_font_description_new();
if (pfd) { if (pfd) {
@ -831,8 +837,8 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
} }
} }
char *UTF8FromLatin1(const char *s, int &len) { std::string UTF8FromLatin1(const char *s, int len) {
char *utfForm = new char[len*2+1]; std::string utfForm(len*2 + 1, '\0');
size_t lenU = 0; size_t lenU = 0;
for (int i=0;i<len;i++) { for (int i=0;i<len;i++) {
unsigned int uch = static_cast<unsigned char>(s[i]); unsigned int uch = static_cast<unsigned char>(s[i]);
@ -843,27 +849,26 @@ char *UTF8FromLatin1(const char *s, int &len) {
utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f)); utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
} }
} }
utfForm[lenU] = '\0'; utfForm.resize(lenU);
len = lenU;
return utfForm; return utfForm;
} }
static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) { static std::string UTF8FromIconv(const Converter &conv, const char *s, int len) {
if (conv) { if (conv) {
char *utfForm = new char[len*3+1]; std::string utfForm(len*3+1, '\0');
char *pin = const_cast<char *>(s); char *pin = const_cast<char *>(s);
size_t inLeft = len; size_t inLeft = len;
char *pout = utfForm; char *putf = &utfForm[0];
char *pout = putf;
size_t outLeft = len*3+1; size_t outLeft = len*3+1;
size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
if (conversions != ((size_t)(-1))) { if (conversions != ((size_t)(-1))) {
*pout = '\0'; *pout = '\0';
len = pout - utfForm; utfForm.resize(pout - putf);
return utfForm; return utfForm;
} }
delete []utfForm;
} }
return 0; return std::string();
} }
// Work out how many bytes are in a character by trying to convert using iconv, // Work out how many bytes are in a character by trying to convert using iconv,
@ -901,18 +906,16 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, con
if (context) { if (context) {
XYPOSITION xText = rc.left; XYPOSITION xText = rc.left;
if (PFont(font_)->pfd) { if (PFont(font_)->pfd) {
char *utfForm = 0; std::string utfForm;
if (et == UTF8) { if (et == UTF8) {
pango_layout_set_text(layout, s, len); pango_layout_set_text(layout, s, len);
} else { } else {
if (!utfForm) { SetConverter(PFont(font_)->characterSet);
SetConverter(PFont(font_)->characterSet); utfForm = UTF8FromIconv(conv, s, len);
utfForm = UTF8FromIconv(conv, s, len); if (utfForm.empty()) { // iconv failed so treat as Latin1
}
if (!utfForm) { // iconv failed so treat as Latin1
utfForm = UTF8FromLatin1(s, len); utfForm = UTF8FromLatin1(s, len);
} }
pango_layout_set_text(layout, utfForm, len); pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
} }
pango_layout_set_font_description(layout, PFont(font_)->pfd); pango_layout_set_font_description(layout, PFont(font_)->pfd);
pango_cairo_update_layout(context, layout); pango_cairo_update_layout(context, layout);
@ -923,7 +926,6 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, con
#endif #endif
cairo_move_to(context, xText, ybase); cairo_move_to(context, xText, ybase);
pango_cairo_show_layout_line(context, pll); pango_cairo_show_layout_line(context, pll);
delete []utfForm;
} }
} }
} }
@ -1020,20 +1022,20 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
int positionsCalculated = 0; int positionsCalculated = 0;
if (et == dbcs) { if (et == dbcs) {
SetConverter(PFont(font_)->characterSet); SetConverter(PFont(font_)->characterSet);
char *utfForm = UTF8FromIconv(conv, s, len); std::string utfForm = UTF8FromIconv(conv, s, len);
if (utfForm) { if (!utfForm.empty()) {
// Convert to UTF-8 so can ask Pango for widths, then // Convert to UTF-8 so can ask Pango for widths, then
// Loop through UTF-8 and DBCS forms, taking account of different // Loop through UTF-8 and DBCS forms, taking account of different
// character byte lengths. // character byte lengths.
Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
pango_layout_set_text(layout, utfForm, strlen(utfForm)); pango_layout_set_text(layout, utfForm.c_str(), strlen(utfForm.c_str()));
int i = 0; int i = 0;
int clusterStart = 0; int clusterStart = 0;
ClusterIterator iti(layout, strlen(utfForm)); ClusterIterator iti(layout, strlen(utfForm.c_str()));
while (!iti.finished) { while (!iti.finished) {
iti.Next(); iti.Next();
int clusterEnd = iti.curIndex; int clusterEnd = iti.curIndex;
int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); int places = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
int place = 1; int place = 1;
while (clusterStart < clusterEnd) { while (clusterStart < clusterEnd) {
size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i); size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
@ -1041,38 +1043,36 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
positions[i++] = iti.position - (places - place) * iti.distance / places; positions[i++] = iti.position - (places - place) * iti.distance / places;
positionsCalculated++; positionsCalculated++;
} }
clusterStart += UTF8CharLength(utfForm+clusterStart); clusterStart += UTF8CharLength(utfForm.c_str()+clusterStart);
place++; place++;
} }
} }
delete []utfForm;
PLATFORM_ASSERT(i == lenPositions); PLATFORM_ASSERT(i == lenPositions);
} }
} }
if (positionsCalculated < 1 ) { if (positionsCalculated < 1 ) {
// Either Latin1 or DBCS conversion failed so treat as Latin1. // Either Latin1 or DBCS conversion failed so treat as Latin1.
SetConverter(PFont(font_)->characterSet); SetConverter(PFont(font_)->characterSet);
char *utfForm = UTF8FromIconv(conv, s, len); std::string utfForm = UTF8FromIconv(conv, s, len);
if (!utfForm) { if (utfForm.empty()) {
utfForm = UTF8FromLatin1(s, len); utfForm = UTF8FromLatin1(s, len);
} }
pango_layout_set_text(layout, utfForm, len); pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
int i = 0; int i = 0;
int clusterStart = 0; int clusterStart = 0;
// Each Latin1 input character may take 1 or 2 bytes in UTF-8 // Each Latin1 input character may take 1 or 2 bytes in UTF-8
// and groups of up to 3 may be represented as ligatures. // and groups of up to 3 may be represented as ligatures.
ClusterIterator iti(layout, strlen(utfForm)); ClusterIterator iti(layout, utfForm.length());
while (!iti.finished) { while (!iti.finished) {
iti.Next(); iti.Next();
int clusterEnd = iti.curIndex; int clusterEnd = iti.curIndex;
int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart); int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3); PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
for (int charInLig=0; charInLig<ligatureLength; charInLig++) { for (int charInLig=0; charInLig<ligatureLength; charInLig++) {
positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength; positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength;
} }
clusterStart = clusterEnd; clusterStart = clusterEnd;
} }
delete []utfForm;
PLATFORM_ASSERT(i == lenPositions); PLATFORM_ASSERT(i == lenPositions);
} }
} }
@ -1092,20 +1092,18 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION
XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID()) { if (font_.GetID()) {
if (PFont(font_)->pfd) { if (PFont(font_)->pfd) {
char *utfForm = 0; std::string utfForm;
pango_layout_set_font_description(layout, PFont(font_)->pfd); pango_layout_set_font_description(layout, PFont(font_)->pfd);
PangoRectangle pos; PangoRectangle pos;
if (et == UTF8) { if (et == UTF8) {
pango_layout_set_text(layout, s, len); pango_layout_set_text(layout, s, len);
} else { } else {
if (!utfForm) { // use iconv SetConverter(PFont(font_)->characterSet);
SetConverter(PFont(font_)->characterSet); utfForm = UTF8FromIconv(conv, s, len);
utfForm = UTF8FromIconv(conv, s, len); if (utfForm.empty()) { // iconv failed so treat as Latin1
}
if (!utfForm) { // iconv failed so treat as Latin1
utfForm = UTF8FromLatin1(s, len); utfForm = UTF8FromLatin1(s, len);
} }
pango_layout_set_text(layout, utfForm, len); pango_layout_set_text(layout, utfForm.c_str(), utfForm.length());
} }
#ifdef PANGO_VERSION #ifdef PANGO_VERSION
PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0); PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0);
@ -1113,7 +1111,6 @@ XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0); PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0);
#endif #endif
pango_layout_line_get_extents(pangoLine, NULL, &pos); pango_layout_line_get_extents(pangoLine, NULL, &pos);
delete []utfForm;
return doubleFromPangoUnits(pos.width); return doubleFromPangoUnits(pos.width);
} }
return 1; return 1;
@ -1883,30 +1880,26 @@ void ListBoxX::ClearRegisteredImages() {
void ListBoxX::SetList(const char *listText, char separator, char typesep) { void ListBoxX::SetList(const char *listText, char separator, char typesep) {
Clear(); Clear();
int count = strlen(listText) + 1; int count = strlen(listText) + 1;
char *words = new char[count]; std::vector<char> words(listText, listText+count);
if (words) { char *startword = words.data();
memcpy(words, listText, count); char *numword = NULL;
char *startword = words; int i = 0;
char *numword = NULL; for (; words[i]; i++) {
int i = 0; if (words[i] == separator) {
for (; words[i]; i++) { words[i] = '\0';
if (words[i] == separator) {
words[i] = '\0';
if (numword)
*numword = '\0';
Append(startword, numword?atoi(numword + 1):-1);
startword = words + i + 1;
numword = NULL;
} else if (words[i] == typesep) {
numword = words + i;
}
}
if (startword) {
if (numword) if (numword)
*numword = '\0'; *numword = '\0';
Append(startword, numword?atoi(numword + 1):-1); Append(startword, numword?atoi(numword + 1):-1);
startword = words.data() + i + 1;
numword = NULL;
} else if (words[i] == typesep) {
numword = words.data() + i;
} }
delete []words; }
if (startword) {
if (numword)
*numword = '\0';
Append(startword, numword?atoi(numword + 1):-1);
} }
} }
@ -2165,5 +2158,6 @@ void Platform_Initialise() {
} }
void Platform_Finalise() { void Platform_Finalise() {
FontCached::ReleaseAll();
FontMutexFree(); FontMutexFree();
} }

View File

@ -30,7 +30,6 @@
#ifdef SCI_LEXER #ifdef SCI_LEXER
#include "SciLexer.h" #include "SciLexer.h"
#endif #endif
#include "SVector.h"
#include "SplitVector.h" #include "SplitVector.h"
#include "Partitioning.h" #include "Partitioning.h"
#include "RunStyles.h" #include "RunStyles.h"
@ -109,7 +108,7 @@ static GdkWindow *PWindow(const Window &w) {
using namespace Scintilla; using namespace Scintilla;
#endif #endif
extern char *UTF8FromLatin1(const char *s, int &len); extern std::string UTF8FromLatin1(const char *s, int len);
class ScintillaGTK : public ScintillaBase { class ScintillaGTK : public ScintillaBase {
_ScintillaObject *sci; _ScintillaObject *sci;
@ -186,7 +185,6 @@ private:
virtual bool PaintContains(PRectangle rc); virtual bool PaintContains(PRectangle rc);
void FullPaint(); void FullPaint();
virtual PRectangle GetClientRectangle(); virtual PRectangle GetClientRectangle();
void SyncPaint(PRectangle rc);
virtual void ScrollText(int linesToMove); virtual void ScrollText(int linesToMove);
virtual void SetVerticalScrollPos(); virtual void SetVerticalScrollPos();
virtual void SetHorizontalScrollPos(); virtual void SetHorizontalScrollPos();
@ -280,7 +278,6 @@ private:
static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data, static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
guint info, guint time); guint info, guint time);
static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event); static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
static void DragBegin(GtkWidget *widget, GdkDragContext *context);
gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime); gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context, static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, guint dragtime); gint x, gint y, guint dragtime);
@ -373,12 +370,12 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
#endif #endif
#if PLAT_GTK_WIN32 #if PLAT_GTK_WIN32
// There does not seem to be a real standard for indicating that the clipboard // There does not seem to be a real standard for indicating that the clipboard
// contains a rectangular selection, so copy Developer Studio. // contains a rectangular selection, so copy Developer Studio.
cfColumnSelect = static_cast<CLIPFORMAT>( cfColumnSelect = static_cast<CLIPFORMAT>(
::RegisterClipboardFormat("MSDEVColumnSelect")); ::RegisterClipboardFormat("MSDEVColumnSelect"));
// Get intellimouse parameters when running on win32; otherwise use // Get intellimouse parameters when running on win32; otherwise use
// reasonable default // reasonable default
#ifndef SPI_GETWHEELSCROLLLINES #ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES 104 #define SPI_GETWHEELSCROLLLINES 104
@ -837,37 +834,34 @@ void ScintillaGTK::StartDrag() {
reinterpret_cast<GdkEvent *>(&evbtn)); reinterpret_cast<GdkEvent *>(&evbtn));
} }
static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest, static std::string ConvertText(char *s, size_t len, const char *charSetDest,
const char *charSetSource, bool transliterations, bool silent=false) { const char *charSetSource, bool transliterations, bool silent=false) {
// s is not const because of different versions of iconv disagreeing about const // s is not const because of different versions of iconv disagreeing about const
*lenResult = 0; std::string destForm;
char *destForm = 0;
Converter conv(charSetDest, charSetSource, transliterations); Converter conv(charSetDest, charSetSource, transliterations);
if (conv) { if (conv) {
destForm = new char[len*3+1]; size_t outLeft = len*3+1;
destForm = std::string(outLeft, '\0');
char *pin = s; char *pin = s;
size_t inLeft = len; size_t inLeft = len;
char *pout = destForm; char *putf = &destForm[0];
size_t outLeft = len*3+1; char *pout = putf;
size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft); size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
if (conversions == ((size_t)(-1))) { if (conversions == ((size_t)(-1))) {
if (!silent) if (!silent) {
fprintf(stderr, "iconv %s->%s failed for %s\n", if (len == 1)
charSetSource, charSetDest, static_cast<char *>(s)); fprintf(stderr, "iconv %s->%s failed for %0x '%s'\n",
delete []destForm; charSetSource, charSetDest, (unsigned char)(*s), static_cast<char *>(s));
destForm = 0; else
fprintf(stderr, "iconv %s->%s failed for %s\n",
charSetSource, charSetDest, static_cast<char *>(s));
}
destForm = std::string();
} else { } else {
//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm); destForm.resize(pout - putf);
*pout = '\0';
*lenResult = pout - destForm;
} }
} else { } else {
fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource); fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
}
if (!destForm) {
destForm = new char[1];
destForm[0] = '\0';
*lenResult = 0;
} }
return destForm; return destForm;
} }
@ -884,26 +878,18 @@ int ScintillaGTK::TargetAsUTF8(char *text) {
// Need to convert // Need to convert
const char *charSetBuffer = CharacterSetID(); const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) { if (*charSetBuffer) {
//~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd); std::string s = RangeText(targetStart, targetEnd);
char *s = new char[targetLength]; std::string tmputf = ConvertText(&s[0], targetLength, "UTF-8", charSetBuffer, false);
if (s) { if (text) {
pdoc->GetCharRange(s, targetStart, targetLength); memcpy(text, tmputf.c_str(), tmputf.length());
//~ fprintf(stderr, " \"%s\"\n", s);
if (text) {
char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
memcpy(text, tmputf, targetLength);
delete []tmputf;
//~ fprintf(stderr, " \"%s\"\n", text);
}
delete []s;
} }
return tmputf.length();
} else { } else {
if (text) { if (text) {
pdoc->GetCharRange(text, targetStart, targetLength); pdoc->GetCharRange(text, targetStart, targetLength);
} }
} }
} }
//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
return targetLength; return targetLength;
} }
@ -920,15 +906,11 @@ int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
// Need to convert // Need to convert
const char *charSetBuffer = CharacterSetID(); const char *charSetBuffer = CharacterSetID();
if (*charSetBuffer) { if (*charSetBuffer) {
int outLength = 0; std::string tmpEncoded = ConvertText(utf8, inputLength, charSetBuffer, "UTF-8", true);
char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true); if (encoded) {
if (tmpEncoded) { memcpy(encoded, tmpEncoded.c_str(), tmpEncoded.length());
if (encoded) {
memcpy(encoded, tmpEncoded, outLength);
}
delete []tmpEncoded;
} }
return outLength; return tmpEncoded.length();
} else { } else {
if (encoded) { if (encoded) {
memcpy(encoded, utf8, inputLength); memcpy(encoded, utf8, inputLength);
@ -966,7 +948,7 @@ sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
#ifdef SCI_LEXER #ifdef SCI_LEXER
case SCI_LOADLEXERLIBRARY: case SCI_LOADLEXERLIBRARY:
LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam)); LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
break; break;
#endif #endif
case SCI_TARGETASUTF8: case SCI_TARGETASUTF8:
@ -1109,30 +1091,6 @@ PRectangle ScintillaGTK::GetClientRectangle() {
return rc; return rc;
} }
// Synchronously paint a rectangle of the window.
void ScintillaGTK::SyncPaint(PRectangle rc) {
paintState = painting;
rcPaint = rc;
PRectangle rcClient = GetClientRectangle();
paintingAllText = rcPaint.Contains(rcClient);
if (PWindow(wText)) {
Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (sw) {
cairo_t *cr = gdk_cairo_create(PWindow(wText));
sw->Init(cr, PWidget(wText));
Paint(sw, rc);
sw->Release();
delete sw;
cairo_destroy(cr);
}
}
if (paintState == paintAbandoned) {
// Painting area was insufficient to cover new styling or brace highlight positions
FullPaint();
}
paintState = notPainting;
}
void ScintillaGTK::ScrollText(int linesToMove) { void ScintillaGTK::ScrollText(int linesToMove) {
int diff = vs.lineHeight * -linesToMove; int diff = vs.lineHeight * -linesToMove;
//Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff, //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
@ -1301,11 +1259,10 @@ public:
folded[0] = mapping[static_cast<unsigned char>(mixed[0])]; folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
return 1; return 1;
} else if (*charSet) { } else if (*charSet) {
int convertedLength = lenMixed; std::string sUTF8 = ConvertText(const_cast<char *>(mixed), lenMixed,
char *sUTF8 = ConvertText(&convertedLength, const_cast<char *>(mixed), lenMixed,
"UTF-8", charSet, false); "UTF-8", charSet, false);
if (sUTF8) { if (!sUTF8.empty()) {
gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); gchar *mapped = g_utf8_casefold(sUTF8.c_str(), sUTF8.length());
size_t lenMapped = strlen(mapped); size_t lenMapped = strlen(mapped);
if (lenMapped < sizeFolded) { if (lenMapped < sizeFolded) {
memcpy(folded, mapped, lenMapped); memcpy(folded, mapped, lenMapped);
@ -1314,7 +1271,6 @@ public:
lenMapped = 1; lenMapped = 1;
} }
g_free(mapped); g_free(mapped);
delete []sUTF8;
return lenMapped; return lenMapped;
} }
} }
@ -1337,23 +1293,20 @@ CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
for (int i=0x80; i<0x100; i++) { for (int i=0x80; i<0x100; i++) {
char sCharacter[2] = "A"; char sCharacter[2] = "A";
sCharacter[0] = i; sCharacter[0] = i;
int convertedLength = 1; // Silent as some bytes have no assigned character
const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1, std::string sUTF8 = ConvertText(sCharacter, 1,
"UTF-8", charSetBuffer, false); "UTF-8", charSetBuffer, false, true);
if (sUTF8) { if (!sUTF8.empty()) {
gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8)); gchar *mapped = g_utf8_casefold(sUTF8.c_str(), sUTF8.length());
if (mapped) { if (mapped) {
int mappedLength = strlen(mapped); std::string mappedBack = ConvertText(mapped, strlen(mapped),
const char *mappedBack = ConvertText(&mappedLength, mapped, charSetBuffer, "UTF-8", false, true);
mappedLength, charSetBuffer, "UTF-8", false, true); if ((mappedBack.length() == 1) && (mappedBack[0] != sCharacter[0])) {
if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
pcf->SetTranslation(sCharacter[0], mappedBack[0]); pcf->SetTranslation(sCharacter[0], mappedBack[0]);
} }
delete []mappedBack;
g_free(mapped); g_free(mapped);
} }
} }
delete []sUTF8;
} }
return pcf; return pcf;
} else { } else {
@ -1364,6 +1317,24 @@ CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
} }
} }
namespace {
struct CaseMapper {
gchar *mapped; // Must be freed with g_free
CaseMapper(const std::string &sUTF8, bool toUpperCase) {
if (toUpperCase) {
mapped = g_utf8_strup(sUTF8.c_str(), sUTF8.length());
} else {
mapped = g_utf8_strdown(sUTF8.c_str(), sUTF8.length());
}
}
~CaseMapper() {
g_free(mapped);
}
};
}
std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) { std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
if (s.size() == 0) if (s.size() == 0)
return std::string(); return std::string();
@ -1371,43 +1342,18 @@ std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
if (caseMapping == cmSame) if (caseMapping == cmSame)
return s; return s;
const char *needsFree1 = 0; // Must be freed with delete []
const char *charSetBuffer = CharacterSetID(); const char *charSetBuffer = CharacterSetID();
const char *sUTF8 = s.c_str();
int rangeBytes = s.size();
int convertedLength = rangeBytes; if (IsUnicodeMode() || !*charSetBuffer) {
// Change text to UTF-8 CaseMapper mapper(s, caseMapping == cmUpper);
if (!IsUnicodeMode()) { return std::string(mapper.mapped, strlen(mapper.mapped));
// Need to convert
if (*charSetBuffer) {
sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
"UTF-8", charSetBuffer, false);
needsFree1 = sUTF8;
}
}
gchar *mapped; // Must be freed with g_free
if (caseMapping == cmUpper) {
mapped = g_utf8_strup(sUTF8, convertedLength);
} else { } else {
mapped = g_utf8_strdown(sUTF8, convertedLength); // Change text to UTF-8
std::string sUTF8 = ConvertText(const_cast<char *>(s.c_str()), s.length(),
"UTF-8", charSetBuffer, false);
CaseMapper mapper(sUTF8, caseMapping == cmUpper);
return ConvertText(mapper.mapped, strlen(mapper.mapped), charSetBuffer, "UTF-8", false);
} }
int mappedLength = strlen(mapped);
char *mappedBack = mapped;
char *needsFree2 = 0; // Must be freed with delete []
if (!IsUnicodeMode()) {
if (*charSetBuffer) {
mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
needsFree2 = mappedBack;
}
}
std::string ret(mappedBack, mappedLength);
g_free(mapped);
delete []needsFree1;
delete []needsFree2;
return ret;
} }
int ScintillaGTK::KeyDefault(int key, int modifiers) { int ScintillaGTK::KeyDefault(int key, int modifiers) {
@ -1528,9 +1474,7 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
// Return empty string if selection is not a string // Return empty string if selection is not a string
if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) { if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
char *empty = new char[1]; selText.Copy("", 0, SC_CP_UTF8, 0, false, false);
empty[0] = '\0';
selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
return; return;
} }
@ -1544,28 +1488,24 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
len--; // Forget the extra '\0' len--; // Forget the extra '\0'
#endif #endif
char *dest; std::string dest = Document::TransformLineEnds(data, len, pdoc->eolMode);
if (selectionTypeData == GDK_TARGET_STRING) { if (selectionTypeData == GDK_TARGET_STRING) {
dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
if (IsUnicodeMode()) { if (IsUnicodeMode()) {
// Unknown encoding so assume in Latin1 // Unknown encoding so assume in Latin1
char *destPrevious = dest; dest = UTF8FromLatin1(dest.c_str(), len);
dest = UTF8FromLatin1(dest, len); selText.Copy(dest.c_str(), dest.length(), SC_CP_UTF8, 0, selText.rectangular, false);
selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
delete []destPrevious;
} else { } else {
// Assume buffer is in same encoding as selection // Assume buffer is in same encoding as selection
selText.Set(dest, len, pdoc->dbcsCodePage, selText.Copy(dest.c_str(), dest.length(), pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false); vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
} }
} else { // UTF-8 } else { // UTF-8
dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode); selText.Copy(dest.c_str(), dest.length(), SC_CP_UTF8, 0, isRectangular, false);
selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
const char *charSetBuffer = CharacterSetID(); const char *charSetBuffer = CharacterSetID();
if (!IsUnicodeMode() && *charSetBuffer) { if (!IsUnicodeMode() && *charSetBuffer) {
// Convert to locale // Convert to locale
dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true); dest = ConvertText(selText.s, selText.len, charSetBuffer, "UTF-8", true);
selText.Set(dest, len, pdoc->dbcsCodePage, selText.Copy(dest.c_str(), dest.length(), pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false); vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
} }
} }
@ -1611,11 +1551,10 @@ void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) { void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
dragWasDropped = true; dragWasDropped = true;
if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) { if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) {
char *ptr = new char[LengthOfGSD(selection_data) + 1]; const char *data = reinterpret_cast<const char *>(DataOfGSD(selection_data));
ptr[LengthOfGSD(selection_data)] = '\0'; std::vector<char> drop(data, data + LengthOfGSD(selection_data));
memcpy(ptr, DataOfGSD(selection_data), LengthOfGSD(selection_data)); drop.push_back('\0');
NotifyURIDropped(ptr); NotifyURIDropped(drop.data());
delete []ptr;
} else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) { } else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) {
if (TypeOfGSD(selection_data) > 0) { if (TypeOfGSD(selection_data) > 0) {
SelectionText selText; SelectionText selText;
@ -1637,10 +1576,9 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
// from code below // from code below
SelectionText *newline_normalized = NULL; SelectionText *newline_normalized = NULL;
{ {
int tmpstr_len; std::string tmpstr = Document::TransformLineEnds(text->s, text->len, SC_EOL_LF);
char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
newline_normalized = new SelectionText(); newline_normalized = new SelectionText();
newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false); newline_normalized->Copy(tmpstr.c_str(), tmpstr.length(), SC_CP_UTF8, 0, text->rectangular, false);
text = newline_normalized; text = newline_normalized;
} }
#endif #endif
@ -1650,10 +1588,9 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) { if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
const char *charSet = ::CharacterSetID(text->characterSet); const char *charSet = ::CharacterSetID(text->characterSet);
if (*charSet) { if (*charSet) {
int new_len; std::string tmputf = ConvertText(text->s, text->len, "UTF-8", charSet, false);
char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
converted = new SelectionText(); converted = new SelectionText();
converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false); converted->Copy(tmputf.c_str(), tmputf.length(), SC_CP_UTF8, 0, text->rectangular, false);
text = converted; text = converted;
} }
} }
@ -1923,8 +1860,7 @@ gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the // win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
// button4/5/6/7 events to the GTK app // button4/5/6/7 events to the GTK app
gint ScintillaGTK::ScrollEvent(GtkWidget *widget, gint ScintillaGTK::ScrollEvent(GtkWidget *widget, GdkEventScroll *event) {
GdkEventScroll *event) {
ScintillaGTK *sciThis = ScintillaFromWidget(widget); ScintillaGTK *sciThis = ScintillaFromWidget(widget);
try { try {
@ -2617,10 +2553,6 @@ gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selectio
return TRUE; return TRUE;
} }
void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
//Platform::DebugPrintf("DragBegin\n");
}
gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context, gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
gint x, gint y, guint dragtime) { gint x, gint y, guint dragtime) {
try { try {

View File

@ -120,6 +120,7 @@
#define SCLEX_ECL 105 #define SCLEX_ECL 105
#define SCLEX_OSCRIPT 106 #define SCLEX_OSCRIPT 106
#define SCLEX_VISUALPROLOG 107 #define SCLEX_VISUALPROLOG 107
#define SCLEX_LITERATEHASKELL 108
#define SCLEX_AUTOMATIC 1000 #define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0 #define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1 #define SCE_P_COMMENTLINE 1
@ -161,6 +162,7 @@
#define SCE_C_TRIPLEVERBATIM 21 #define SCE_C_TRIPLEVERBATIM 21
#define SCE_C_HASHQUOTEDSTRING 22 #define SCE_C_HASHQUOTEDSTRING 22
#define SCE_C_PREPROCESSORCOMMENT 23 #define SCE_C_PREPROCESSORCOMMENT 23
#define SCE_C_PREPROCESSORCOMMENTDOC 24
#define SCE_D_DEFAULT 0 #define SCE_D_DEFAULT 0
#define SCE_D_COMMENT 1 #define SCE_D_COMMENT 1
#define SCE_D_COMMENTLINE 2 #define SCE_D_COMMENTLINE 2
@ -1022,6 +1024,10 @@
#define SCE_HA_COMMENTBLOCK3 16 #define SCE_HA_COMMENTBLOCK3 16
#define SCE_HA_PRAGMA 17 #define SCE_HA_PRAGMA 17
#define SCE_HA_PREPROCESSOR 18 #define SCE_HA_PREPROCESSOR 18
#define SCE_HA_STRINGEOL 19
#define SCE_HA_RESERVED_OPERATOR 20
#define SCE_HA_LITERATE_COMMENT 21
#define SCE_HA_LITERATE_CODEDELIM 22
#define SCE_T3_DEFAULT 0 #define SCE_T3_DEFAULT 0
#define SCE_T3_X_DEFAULT 1 #define SCE_T3_X_DEFAULT 1
#define SCE_T3_PREPROCESSOR 2 #define SCE_T3_PREPROCESSOR 2
@ -1326,6 +1332,9 @@
#define SCE_POWERSHELL_FUNCTION 11 #define SCE_POWERSHELL_FUNCTION 11
#define SCE_POWERSHELL_USER1 12 #define SCE_POWERSHELL_USER1 12
#define SCE_POWERSHELL_COMMENTSTREAM 13 #define SCE_POWERSHELL_COMMENTSTREAM 13
#define SCE_POWERSHELL_HERE_STRING 14
#define SCE_POWERSHELL_HERE_CHARACTER 15
#define SCE_POWERSHELL_COMMENTDOCKEYWORD 16
#define SCE_MYSQL_DEFAULT 0 #define SCE_MYSQL_DEFAULT 0
#define SCE_MYSQL_COMMENT 1 #define SCE_MYSQL_COMMENT 1
#define SCE_MYSQL_COMMENTLINE 2 #define SCE_MYSQL_COMMENTLINE 2

View File

@ -264,6 +264,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define INDIC_SQUIGGLELOW 11 #define INDIC_SQUIGGLELOW 11
#define INDIC_DOTBOX 12 #define INDIC_DOTBOX 12
#define INDIC_SQUIGGLEPIXMAP 13 #define INDIC_SQUIGGLEPIXMAP 13
#define INDIC_COMPOSITIONTHICK 14
#define INDIC_MAX 31 #define INDIC_MAX 31
#define INDIC_CONTAINER 8 #define INDIC_CONTAINER 8
#define INDIC0_MASK 0x20 #define INDIC0_MASK 0x20
@ -440,7 +441,19 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETFOLDEXPANDED 2229 #define SCI_SETFOLDEXPANDED 2229
#define SCI_GETFOLDEXPANDED 2230 #define SCI_GETFOLDEXPANDED 2230
#define SCI_TOGGLEFOLD 2231 #define SCI_TOGGLEFOLD 2231
#define SC_FOLDACTION_CONTRACT 0
#define SC_FOLDACTION_EXPAND 1
#define SC_FOLDACTION_TOGGLE 2
#define SCI_FOLDLINE 2237
#define SCI_FOLDCHILDREN 2238
#define SCI_EXPANDCHILDREN 2239
#define SCI_FOLDALL 2662
#define SCI_ENSUREVISIBLE 2232 #define SCI_ENSUREVISIBLE 2232
#define SC_AUTOMATICFOLD_SHOW 0x0001
#define SC_AUTOMATICFOLD_CLICK 0x0002
#define SC_AUTOMATICFOLD_CHANGE 0x0004
#define SCI_SETAUTOMATICFOLD 2663
#define SCI_GETAUTOMATICFOLD 2664
#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002 #define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004 #define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008 #define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008

View File

@ -581,6 +581,7 @@ val INDIC_DOTS=10
val INDIC_SQUIGGLELOW=11 val INDIC_SQUIGGLELOW=11
val INDIC_DOTBOX=12 val INDIC_DOTBOX=12
val INDIC_SQUIGGLEPIXMAP=13 val INDIC_SQUIGGLEPIXMAP=13
val INDIC_COMPOSITIONTHICK=14
val INDIC_MAX=31 val INDIC_MAX=31
val INDIC_CONTAINER=8 val INDIC_CONTAINER=8
val INDIC0_MASK=0x20 val INDIC0_MASK=0x20
@ -1109,9 +1110,37 @@ get bool GetFoldExpanded=2230(int line,)
# Switch a header line between expanded and contracted. # Switch a header line between expanded and contracted.
fun void ToggleFold=2231(int line,) fun void ToggleFold=2231(int line,)
enu FoldAction=SC_FOLDACTION
val SC_FOLDACTION_CONTRACT=0
val SC_FOLDACTION_EXPAND=1
val SC_FOLDACTION_TOGGLE=2
# Expand or contract a fold header.
fun void FoldLine=2237(int line, int action)
# Expand or contract a fold header and its children.
fun void FoldChildren=2238(int line, int action)
# Expand a fold header and all children. Use the level argument instead of the line's current level.
fun void ExpandChildren=2239(int line, int level)
# Expand or contract all fold headers.
fun void FoldAll=2662(int action,)
# Ensure a particular line is visible by expanding any header line hiding it. # Ensure a particular line is visible by expanding any header line hiding it.
fun void EnsureVisible=2232(int line,) fun void EnsureVisible=2232(int line,)
enu AutomaticFold=SC_AUTOMATICFOLD_
val SC_AUTOMATICFOLD_SHOW=0x0001
val SC_AUTOMATICFOLD_CLICK=0x0002
val SC_AUTOMATICFOLD_CHANGE=0x0004
# Set automatic folding behaviours.
set void SetAutomaticFold=2663(int automaticFold,)
# Get automatic folding behaviours.
get int GetAutomaticFold=2664(,)
enu FoldFlag=SC_FOLDFLAG_ enu FoldFlag=SC_FOLDFLAG_
val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002 val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002
val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004 val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004
@ -2549,6 +2578,7 @@ val SCLEX_AVS=104
val SCLEX_ECL=105 val SCLEX_ECL=105
val SCLEX_OSCRIPT=106 val SCLEX_OSCRIPT=106
val SCLEX_VISUALPROLOG=107 val SCLEX_VISUALPROLOG=107
val SCLEX_LITERATEHASKELL=108
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1. # value assigned in sequence from SCLEX_AUTOMATIC+1.
@ -2599,6 +2629,7 @@ val SCE_C_STRINGRAW=20
val SCE_C_TRIPLEVERBATIM=21 val SCE_C_TRIPLEVERBATIM=21
val SCE_C_HASHQUOTEDSTRING=22 val SCE_C_HASHQUOTEDSTRING=22
val SCE_C_PREPROCESSORCOMMENT=23 val SCE_C_PREPROCESSORCOMMENT=23
val SCE_C_PREPROCESSORCOMMENTDOC=24
# Lexical states for SCLEX_D # Lexical states for SCLEX_D
lex D=SCLEX_D SCE_D_ lex D=SCLEX_D SCE_D_
val SCE_D_DEFAULT=0 val SCE_D_DEFAULT=0
@ -3583,6 +3614,10 @@ val SCE_HA_COMMENTBLOCK2=15
val SCE_HA_COMMENTBLOCK3=16 val SCE_HA_COMMENTBLOCK3=16
val SCE_HA_PRAGMA=17 val SCE_HA_PRAGMA=17
val SCE_HA_PREPROCESSOR=18 val SCE_HA_PREPROCESSOR=18
val SCE_HA_STRINGEOL=19
val SCE_HA_RESERVED_OPERATOR=20
val SCE_HA_LITERATE_COMMENT=21
val SCE_HA_LITERATE_CODEDELIM=22
# Lexical states of SCLEX_TADS3 # Lexical states of SCLEX_TADS3
lex TADS3=SCLEX_TADS3 SCE_T3_ lex TADS3=SCLEX_TADS3 SCE_T3_
val SCE_T3_DEFAULT=0 val SCE_T3_DEFAULT=0
@ -3923,6 +3958,9 @@ val SCE_POWERSHELL_ALIAS=10
val SCE_POWERSHELL_FUNCTION=11 val SCE_POWERSHELL_FUNCTION=11
val SCE_POWERSHELL_USER1=12 val SCE_POWERSHELL_USER1=12
val SCE_POWERSHELL_COMMENTSTREAM=13 val SCE_POWERSHELL_COMMENTSTREAM=13
val SCE_POWERSHELL_HERE_STRING=14
val SCE_POWERSHELL_HERE_CHARACTER=15
val SCE_POWERSHELL_COMMENTDOCKEYWORD=16
# Lexical state for SCLEX_MYSQL # Lexical state for SCLEX_MYSQL
lex MySQL=SCLEX_MYSQL SCE_MYSQL_ lex MySQL=SCLEX_MYSQL SCE_MYSQL_
val SCE_MYSQL_DEFAULT=0 val SCE_MYSQL_DEFAULT=0

View File

@ -455,9 +455,9 @@ int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
if (n == 4) { if (n == 4) {
// Rebuild preprocessorDefinitions // Rebuild preprocessorDefinitions
preprocessorDefinitionsStart.clear(); preprocessorDefinitionsStart.clear();
for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) { for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) {
char *cpDefinition = ppDefinitions.words[nDefinition]; const char *cpDefinition = ppDefinitions.WordAt(nDefinition);
char *cpEquals = strchr(cpDefinition, '='); const char *cpEquals = strchr(cpDefinition, '=');
if (cpEquals) { if (cpEquals) {
std::string name(cpDefinition, cpEquals - cpDefinition); std::string name(cpDefinition, cpEquals - cpDefinition);
std::string val(cpEquals+1); std::string val(cpEquals+1);
@ -672,7 +672,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
sc.SetState(SCE_C_DEFAULT|activitySet); sc.SetState(SCE_C_DEFAULT|activitySet);
} }
break; break;
case SCE_C_PREPROCESSOR: case SCE_C_PREPROCESSOR:
if (options.stylingWithinPreprocessor) { if (options.stylingWithinPreprocessor) {
if (IsASpace(sc.ch)) { if (IsASpace(sc.ch)) {
sc.SetState(SCE_C_DEFAULT|activitySet); sc.SetState(SCE_C_DEFAULT|activitySet);
@ -683,7 +683,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
if ((isIncludePreprocessor && sc.Match('<')) || sc.Match('\"')) { if ((isIncludePreprocessor && sc.Match('<')) || sc.Match('\"')) {
isStringInPreprocessor = true; isStringInPreprocessor = true;
} else if (sc.Match('/', '*')) { } else if (sc.Match('/', '*')) {
sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet); if (sc.Match("/**") || sc.Match("/*!")) {
sc.SetState(SCE_C_PREPROCESSORCOMMENTDOC|activitySet);
} else {
sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet);
}
sc.Forward(); // Eat the * sc.Forward(); // Eat the *
} else if (sc.Match('/', '/')) { } else if (sc.Match('/', '/')) {
sc.SetState(SCE_C_DEFAULT|activitySet); sc.SetState(SCE_C_DEFAULT|activitySet);
@ -691,6 +695,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
} }
break; break;
case SCE_C_PREPROCESSORCOMMENT: case SCE_C_PREPROCESSORCOMMENT:
case SCE_C_PREPROCESSORCOMMENTDOC:
if (sc.Match('*', '/')) { if (sc.Match('*', '/')) {
sc.Forward(); sc.Forward();
sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet); sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet);

File diff suppressed because it is too large Load Diff

View File

@ -224,7 +224,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') { } else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR); styler.ColourTo(i, SCE_L_ERROR);
} else { } else if (isascii(chNext)) {
styler.ColourTo(i + 1, SCE_L_SHORTCMD); styler.ColourTo(i + 1, SCE_L_SHORTCMD);
if (chNext == '(') { if (chNext == '(') {
mode = 1; mode = 1;
@ -340,7 +340,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') { } else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR); styler.ColourTo(i, SCE_L_ERROR);
} else { } else if (isascii(chNext)) {
if (chNext == ')') { if (chNext == ')') {
mode = 0; mode = 0;
state = SCE_L_DEFAULT; state = SCE_L_DEFAULT;
@ -382,7 +382,7 @@ void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
} else if (chNext == '\r' || chNext == '\n') { } else if (chNext == '\r' || chNext == '\n') {
styler.ColourTo(i, SCE_L_ERROR); styler.ColourTo(i, SCE_L_ERROR);
} else { } else if (isascii(chNext)) {
if (chNext == ']') { if (chNext == ']') {
mode = 0; mode = 0;
state = SCE_L_DEFAULT; state = SCE_L_DEFAULT;

View File

@ -1047,10 +1047,10 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
} }
} else if (state == stCtagsStart) { } else if (state == stCtagsStart) {
if ((lineBuffer[i - 1] == '\t') && if ((lineBuffer[i - 1] == '\t') &&
((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) { ((ch == '/' && chNext == '^') || Is0To9(ch))) {
state = stCtags; state = stCtags;
break; break;
} else if ((ch == '/') && (lineBuffer[i + 1] == '^')) { } else if ((ch == '/') && (chNext == '^')) {
state = stCtagsStartString; state = stCtagsStartString;
} }
} else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {

View File

@ -75,7 +75,7 @@ int LexerModule::GetNumWordLists() const {
const char *LexerModule::GetWordListDescription(int index) const { const char *LexerModule::GetWordListDescription(int index) const {
assert(index < GetNumWordLists()); assert(index < GetNumWordLists());
if (index >= GetNumWordLists()) { if (!wordListDescriptions || (index >= GetNumWordLists())) {
return ""; return "";
} else { } else {
return wordListDescriptions[index]; return wordListDescriptions[index];

View File

@ -141,30 +141,21 @@ static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, i
return maxExpands; return maxExpands;
} }
char *PropSetSimple::Expanded(const char *key) const { int PropSetSimple::GetExpanded(const char *key, char *result) const {
std::string val = Get(key); std::string val = Get(key);
ExpandAllInPlace(*this, val, 100, VarChain(key)); ExpandAllInPlace(*this, val, 100, VarChain(key));
char *ret = new char [val.size() + 1]; const int n = static_cast<int>(val.size());
strcpy(ret, val.c_str());
return ret;
}
int PropSetSimple::GetExpanded(const char *key, char *result) const {
char *val = Expanded(key);
const int n = static_cast<int>(strlen(val));
if (result) { if (result) {
strcpy(result, val); strcpy(result, val.c_str());
} }
delete []val;
return n; // Not including NUL return n; // Not including NUL
} }
int PropSetSimple::GetInt(const char *key, int defaultValue) const { int PropSetSimple::GetInt(const char *key, int defaultValue) const {
char *val = Expanded(key); std::string val = Get(key);
if (val) { ExpandAllInPlace(*this, val, 100, VarChain(key));
int retVal = val[0] ? atoi(val) : defaultValue; if (!val.empty()) {
delete []val; return atoi(val.c_str());
return retVal;
} }
return defaultValue; return defaultValue;
} }

View File

@ -21,7 +21,6 @@ public:
void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1); void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1);
void SetMultiple(const char *); void SetMultiple(const char *);
const char *Get(const char *key) const; const char *Get(const char *key) const;
char *Expanded(const char *key) const;
int GetExpanded(const char *key, char *result) const; int GetExpanded(const char *key, char *result) const;
int GetInt(const char *key, int defaultValue=0) const; int GetInt(const char *key, int defaultValue=0) const;
}; };

View File

@ -76,7 +76,7 @@ class StyleContext {
// End of line? // End of line?
// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win)
// or on LF alone (Unix). Avoid triggering two times on Dos/Win. // or on LF alone (Unix). Avoid triggering two times on Dos/Win.
if (lineStartNext < styler.Length()) if (currentLine < lineDocEnd)
atLineEnd = static_cast<int>(pos) >= (lineStartNext-1); atLineEnd = static_cast<int>(pos) >= (lineStartNext-1);
else // Last line else // Last line
atLineEnd = static_cast<int>(pos) >= lineStartNext; atLineEnd = static_cast<int>(pos) >= lineStartNext;
@ -85,6 +85,7 @@ class StyleContext {
public: public:
unsigned int currentPos; unsigned int currentPos;
int currentLine; int currentLine;
int lineDocEnd;
int lineStartNext; int lineStartNext;
bool atLineStart; bool atLineStart;
bool atLineEnd; bool atLineEnd;
@ -112,6 +113,7 @@ public:
lengthDocument = static_cast<unsigned int>(styler.Length()); lengthDocument = static_cast<unsigned int>(styler.Length());
if (endPos == lengthDocument) if (endPos == lengthDocument)
endPos++; endPos++;
lineDocEnd = styler.GetLine(lengthDocument);
atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos; atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
unsigned int pos = currentPos; unsigned int pos = currentPos;
ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0)); ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));

View File

@ -45,29 +45,37 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa
prev = curr; prev = curr;
} }
char **keywords = new char *[words + 1]; char **keywords = new char *[words + 1];
if (keywords) { words = 0;
words = 0; prev = '\0';
prev = '\0'; size_t slen = strlen(wordlist);
size_t slen = strlen(wordlist); for (size_t k = 0; k < slen; k++) {
for (size_t k = 0; k < slen; k++) { if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) { if (!prev) {
if (!prev) { keywords[words] = &wordlist[k];
keywords[words] = &wordlist[k]; words++;
words++;
}
} else {
wordlist[k] = '\0';
} }
prev = wordlist[k]; } else {
wordlist[k] = '\0';
} }
keywords[words] = &wordlist[slen]; prev = wordlist[k];
*len = words;
} else {
*len = 0;
} }
keywords[words] = &wordlist[slen];
*len = words;
return keywords; return keywords;
} }
WordList::WordList(bool onlyLineEnds_) :
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
}
WordList::~WordList() {
Clear();
}
WordList::operator bool() const {
return len ? true : false;
}
bool WordList::operator!=(const WordList &other) const { bool WordList::operator!=(const WordList &other) const {
if (len != other.len) if (len != other.len)
return true; return true;
@ -78,6 +86,10 @@ bool WordList::operator!=(const WordList &other) const {
return false; return false;
} }
int WordList::Length() const {
return len;
}
void WordList::Clear() { void WordList::Clear() {
if (words) { if (words) {
delete []list; delete []list;
@ -217,3 +229,8 @@ bool WordList::InListAbbreviated(const char *s, const char marker) const {
} }
return false; return false;
} }
const char *WordList::WordAt(int n) const {
return words[n];
}

View File

@ -15,23 +15,23 @@ namespace Scintilla {
/** /**
*/ */
class WordList { class WordList {
public:
// Each word contains at least one character - a empty word acts as sentinel at the end. // Each word contains at least one character - a empty word acts as sentinel at the end.
char **words; char **words;
char *list; char *list;
int len; int len;
bool onlyLineEnds; ///< Delimited by any white space or only line ends bool onlyLineEnds; ///< Delimited by any white space or only line ends
int starts[256]; int starts[256];
WordList(bool onlyLineEnds_ = false) : public:
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) WordList(bool onlyLineEnds_ = false);
{} ~WordList();
~WordList() { Clear(); } operator bool() const;
operator bool() const { return len ? true : false; }
bool operator!=(const WordList &other) const; bool operator!=(const WordList &other) const;
int Length() const;
void Clear(); void Clear();
void Set(const char *s); void Set(const char *s);
bool InList(const char *s) const; bool InList(const char *s) const;
bool InListAbbreviated(const char *s, const char marker) const; bool InListAbbreviated(const char *s, const char marker) const;
const char *WordAt(int n) const;
}; };
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE

View File

@ -31,7 +31,7 @@ diff --git b/scintilla/src/Catalogue.cxx a/scintilla/src/Catalogue.cxx
index 2f75247..a34f834 100644 index 2f75247..a34f834 100644
+++ scintilla/src/Catalogue.cxx +++ scintilla/src/Catalogue.cxx
--- scintilla/src/Catalogue.cxx --- scintilla/src/Catalogue.cxx
@@ -81,108 +81,45 @@ int Scintilla_LinkLexers() { @@ -81,109 +81,45 @@ int Scintilla_LinkLexers() {
//++Autogenerated -- run src/LexGen.py to regenerate //++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\) //**\(\tLINK_LEXER(\*);\n\)
@ -82,6 +82,7 @@ index 2f75247..a34f834 100644
- LINK_LEXER(lmKix); - LINK_LEXER(lmKix);
LINK_LEXER(lmLatex); LINK_LEXER(lmLatex);
LINK_LEXER(lmLISP); LINK_LEXER(lmLISP);
- LINK_LEXER(lmLiterateHaskell);
- LINK_LEXER(lmLot); - LINK_LEXER(lmLot);
- LINK_LEXER(lmLout); - LINK_LEXER(lmLout);
LINK_LEXER(lmLua); LINK_LEXER(lmLua);

View File

@ -7,12 +7,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <string>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
#include "CallTip.h" #include "CallTip.h"
#include <stdio.h>
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
@ -22,7 +24,6 @@ CallTip::CallTip() {
wCallTip = 0; wCallTip = 0;
inCallTipMode = false; inCallTipMode = false;
posStartCallTip = 0; posStartCallTip = 0;
val = 0;
rectUp = PRectangle(0,0,0,0); rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0);
lineHeight = 1; lineHeight = 1;
@ -56,8 +57,6 @@ CallTip::CallTip() {
CallTip::~CallTip() { CallTip::~CallTip() {
font.Release(); font.Release();
wCallTip.Destroy(); wCallTip.Destroy();
delete []val;
val = 0;
} }
// Although this test includes 0, we should never see a \0 character. // Although this test includes 0, we should never see a \0 character.
@ -176,17 +175,17 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
// Draw the definition in three parts: before highlight, highlighted, after highlight // Draw the definition in three parts: before highlight, highlighted, after highlight
int ytext = rcClient.top + ascent + 1; int ytext = rcClient.top + ascent + 1;
rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1; rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
char *chunkVal = val; const char *chunkVal = val.c_str();
bool moreChunks = true; bool moreChunks = true;
int maxWidth = 0; int maxWidth = 0;
while (moreChunks) { while (moreChunks) {
char *chunkEnd = strchr(chunkVal, '\n'); const char *chunkEnd = strchr(chunkVal, '\n');
if (chunkEnd == NULL) { if (chunkEnd == NULL) {
chunkEnd = chunkVal + strlen(chunkVal); chunkEnd = chunkVal + strlen(chunkVal);
moreChunks = false; moreChunks = false;
} }
int chunkOffset = chunkVal - val; int chunkOffset = chunkVal - val.c_str();
int chunkLength = chunkEnd - chunkVal; int chunkLength = chunkEnd - chunkVal;
int chunkEndOffset = chunkOffset + chunkLength; int chunkEndOffset = chunkOffset + chunkLength;
int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset); int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
@ -215,7 +214,7 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
} }
void CallTip::PaintCT(Surface *surfaceWindow) { void CallTip::PaintCT(Surface *surfaceWindow) {
if (!val) if (val.empty())
return; return;
PRectangle rcClientPos = wCallTip.GetClientPosition(); PRectangle rcClientPos = wCallTip.GetClientPosition();
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left, PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
@ -253,10 +252,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *
int codePage_, int characterSet, int codePage_, int characterSet,
int technology, Window &wParent) { int technology, Window &wParent) {
clickPlace = 0; clickPlace = 0;
delete []val; val = defn;
val = 0;
val = new char[strlen(defn) + 1];
strcpy(val, defn);
codePage = codePage_; codePage = codePage_;
Surface *surfaceMeasure = Surface::Allocate(technology); Surface *surfaceMeasure = Surface::Allocate(technology);
if (!surfaceMeasure) if (!surfaceMeasure)
@ -275,7 +271,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *
// Only support \n here - simply means container must avoid \r! // Only support \n here - simply means container must avoid \r!
int numLines = 1; int numLines = 1;
const char *newline; const char *newline;
const char *look = val; const char *look = val.c_str();
rectUp = PRectangle(0,0,0,0); rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0);
offsetMain = insetX; // changed to right edge of any arrows offsetMain = insetX; // changed to right edge of any arrows

View File

@ -17,7 +17,7 @@ namespace Scintilla {
class CallTip { class CallTip {
int startHighlight; // character offset to start and... int startHighlight; // character offset to start and...
int endHighlight; // ...end of highlighted text int endHighlight; // ...end of highlighted text
char *val; std::string val;
Font font; Font font;
PRectangle rectUp; // rectangle of last up angle in the tip PRectangle rectUp; // rectangle of last up angle in the tip
PRectangle rectDown; // rectangle of last down arrow in the tip PRectangle rectDown; // rectangle of last down arrow in the tip

View File

@ -10,6 +10,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <algorithm>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
@ -81,11 +83,15 @@ Action::~Action() {
Destroy(); Destroy();
} }
void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) { void Action::Create(actionType at_, int position_, const char *data_, int lenData_, bool mayCoalesce_) {
delete []data; delete []data;
data = NULL;
position = position_; position = position_;
at = at_; at = at_;
data = data_; if (lenData_) {
data = new char[lenData_];
memcpy(data, data_, lenData_);
}
lenData = lenData_; lenData = lenData_;
mayCoalesce = mayCoalesce_; mayCoalesce = mayCoalesce_;
} }
@ -162,7 +168,7 @@ void UndoHistory::EnsureUndoRoom() {
} }
} }
void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData, void UndoHistory::AppendAction(actionType at, int position, const char *data, int lengthData,
bool &startSequence, bool mayCoalesce) { bool &startSequence, bool mayCoalesce) {
EnsureUndoRoom(); EnsureUndoRoom();
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction); //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
@ -393,11 +399,7 @@ const char *CellBuffer::InsertString(int position, const char *s, int insertLeng
if (collectingUndo) { if (collectingUndo) {
// Save into the undo/redo stack, but only the characters - not the formatting // Save into the undo/redo stack, but only the characters - not the formatting
// This takes up about half load time // This takes up about half load time
data = new char[insertLength]; uh.AppendAction(insertAction, position, s, insertLength, startSequence);
for (int i = 0; i < insertLength; i++) {
data[i] = s[i];
}
uh.AppendAction(insertAction, position, data, insertLength, startSequence);
} }
BasicInsertString(position, s, insertLength); BasicInsertString(position, s, insertLength);
@ -439,10 +441,8 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startS
if (!readOnly) { if (!readOnly) {
if (collectingUndo) { if (collectingUndo) {
// Save into the undo/redo stack, but only the characters - not the formatting // Save into the undo/redo stack, but only the characters - not the formatting
data = new char[deleteLength]; // The gap would be moved to position anyway for the deletion so this doesn't cost extra
for (int i = 0; i < deleteLength; i++) { const char *data = substance.RangePointer(position, deleteLength);
data[i] = substance.ValueAt(position + i);
}
uh.AppendAction(removeAction, position, data, deleteLength, startSequence); uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
} }

View File

@ -80,7 +80,7 @@ public:
Action(); Action();
~Action(); ~Action();
void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true); void Create(actionType at_, int position_=0, const char *data_=0, int lenData_=0, bool mayCoalesce_=true);
void Destroy(); void Destroy();
void Grab(Action *source); void Grab(Action *source);
}; };
@ -105,7 +105,7 @@ public:
UndoHistory(); UndoHistory();
~UndoHistory(); ~UndoHistory();
void AppendAction(actionType at, int position, char *data, int length, bool &startSequence, bool mayCoalesce=true); void AppendAction(actionType at, int position, const char *data, int length, bool &startSequence, bool mayCoalesce=true);
void BeginUndoAction(); void BeginUndoAction();
void EndUndoAction(); void EndUndoAction();

View File

@ -7,6 +7,8 @@
#include <string.h> #include <string.h>
#include <algorithm>
#include "Platform.h" #include "Platform.h"
#include "SplitVector.h" #include "SplitVector.h"

View File

@ -9,6 +9,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <algorithm>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"

View File

@ -13,6 +13,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <algorithm>
#include "Platform.h" #include "Platform.h"
@ -102,8 +103,6 @@ Document::Document() {
useTabs = true; useTabs = true;
tabIndents = true; tabIndents = true;
backspaceUnindents = false; backspaceUnindents = false;
watchers = 0;
lenWatchers = 0;
matchesValid = false; matchesValid = false;
regex = 0; regex = 0;
@ -122,16 +121,13 @@ Document::Document() {
} }
Document::~Document() { Document::~Document() {
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifyDeleted(this, watchers[i].userData); it->watcher->NotifyDeleted(this, it->userData);
} }
delete []watchers;
for (int j=0; j<ldSize; j++) { for (int j=0; j<ldSize; j++) {
delete perLineData[j]; delete perLineData[j];
perLineData[j] = 0; perLineData[j] = 0;
} }
watchers = 0;
lenWatchers = 0;
delete regex; delete regex;
regex = 0; regex = 0;
delete pli; delete pli;
@ -309,9 +305,9 @@ int SCI_METHOD Document::LineEnd(int line) const {
} }
void SCI_METHOD Document::SetErrorStatus(int status) { void SCI_METHOD Document::SetErrorStatus(int status) {
// Tell the watchers the lexer has changed. // Tell the watchers an error has occurred.
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status); it->watcher->NotifyErrorOccurred(this, it->userData, status);
} }
} }
@ -420,7 +416,7 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
int lookLine = line; int lookLine = line;
int lookLineLevel = level; int lookLineLevel = level;
int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) ||
((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) { ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) {
lookLineLevel = GetLevel(--lookLine); lookLineLevel = GetLevel(--lookLine);
lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
@ -453,8 +449,8 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
} }
} }
if (firstChangeableLineBefore == -1) { if (firstChangeableLineBefore == -1) {
for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
lookLine >= beginFoldBlock; lookLine >= beginFoldBlock;
lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) { if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) {
firstChangeableLineBefore = lookLine; firstChangeableLineBefore = lookLine;
@ -466,8 +462,8 @@ void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, in
firstChangeableLineBefore = beginFoldBlock - 1; firstChangeableLineBefore = beginFoldBlock - 1;
int firstChangeableLineAfter = -1; int firstChangeableLineAfter = -1;
for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
lookLine <= endFoldBlock; lookLine <= endFoldBlock;
lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) { if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) {
firstChangeableLineAfter = lookLine; firstChangeableLineAfter = lookLine;
@ -715,7 +711,7 @@ bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const {
// Shift_jis // Shift_jis
return ((uch >= 0x81) && (uch <= 0x9F)) || return ((uch >= 0x81) && (uch <= 0x9F)) ||
((uch >= 0xE0) && (uch <= 0xFC)); ((uch >= 0xE0) && (uch <= 0xFC));
// Lead bytes F0 to FC may be a Microsoft addition. // Lead bytes F0 to FC may be a Microsoft addition.
case 936: case 936:
// GBK // GBK
return (uch >= 0x81) && (uch <= 0xFE); return (uch >= 0x81) && (uch <= 0xFE);
@ -892,7 +888,7 @@ void * SCI_METHOD Document::ConvertToDocument() {
int Document::Undo() { int Document::Undo() {
int newPos = -1; int newPos = -1;
CheckReadOnly(); CheckReadOnly();
if (enteredModification == 0) { if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++; enteredModification++;
if (!cb.IsReadOnly()) { if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint(); bool startSavePoint = cb.IsSavePoint();
@ -977,7 +973,7 @@ int Document::Undo() {
int Document::Redo() { int Document::Redo() {
int newPos = -1; int newPos = -1;
CheckReadOnly(); CheckReadOnly();
if (enteredModification == 0) { if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++; enteredModification++;
if (!cb.IsReadOnly()) { if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint(); bool startSavePoint = cb.IsSavePoint();
@ -1050,11 +1046,6 @@ bool Document::InsertCString(int position, const char *s) {
return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0)); return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0));
} }
void Document::ChangeChar(int pos, char ch) {
DeleteChars(pos, 1);
InsertChar(pos, ch);
}
void Document::DelChar(int pos) { void Document::DelChar(int pos) {
DeleteChars(pos, LenChar(pos)); DeleteChars(pos, LenChar(pos));
} }
@ -1212,32 +1203,25 @@ void Document::Indent(bool forwards, int lineBottom, int lineTop) {
// Convert line endings for a piece of text to a particular mode. // Convert line endings for a piece of text to a particular mode.
// Stop at len or when a NUL is found. // Stop at len or when a NUL is found.
// Caller must delete the returned pointer. std::string Document::TransformLineEnds(const char *s, size_t len, int eolModeWanted) {
char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted) { std::string dest;
char *dest = new char[2 * len + 1]; for (size_t i = 0; (i < len) && (s[i]); i++) {
const char *sptr = s; if (s[i] == '\n' || s[i] == '\r') {
char *dptr = dest;
for (size_t i = 0; (i < len) && (*sptr != '\0'); i++) {
if (*sptr == '\n' || *sptr == '\r') {
if (eolModeWanted == SC_EOL_CR) { if (eolModeWanted == SC_EOL_CR) {
*dptr++ = '\r'; dest.push_back('\r');
} else if (eolModeWanted == SC_EOL_LF) { } else if (eolModeWanted == SC_EOL_LF) {
*dptr++ = '\n'; dest.push_back('\n');
} else { // eolModeWanted == SC_EOL_CRLF } else { // eolModeWanted == SC_EOL_CRLF
*dptr++ = '\r'; dest.push_back('\r');
*dptr++ = '\n'; dest.push_back('\n');
} }
if ((*sptr == '\r') && (i+1 < len) && (*(sptr+1) == '\n')) { if ((s[i] == '\r') && (i+1 < len) && (s[i+1] == '\n')) {
i++; i++;
sptr++;
} }
sptr++;
} else { } else {
*dptr++ = *sptr++; dest.push_back(s[i]);
} }
} }
*dptr++ = '\0';
*pLenOut = (dptr - dest) - 1;
return dest; return dest;
} }
@ -1667,25 +1651,6 @@ int Document::LinesTotal() const {
return cb.Lines(); return cb.Lines();
} }
void Document::ChangeCase(Range r, bool makeUpperCase) {
for (int pos = r.start; pos < r.end;) {
int len = LenChar(pos);
if (len == 1) {
char ch = CharAt(pos);
if (makeUpperCase) {
if (IsLowerCase(ch)) {
ChangeChar(pos, static_cast<char>(MakeUpperCase(ch)));
}
} else {
if (IsUpperCase(ch)) {
ChangeChar(pos, static_cast<char>(MakeLowerCase(ch)));
}
}
}
pos += len;
}
}
void Document::SetDefaultCharClasses(bool includeWordClass) { void Document::SetDefaultCharClasses(bool includeWordClass) {
charClass.SetDefaultCharClasses(includeWordClass); charClass.SetDefaultCharClasses(includeWordClass);
} }
@ -1763,8 +1728,9 @@ void Document::EnsureStyledTo(int pos) {
pli->Colourise(endStyledTo, pos); pli->Colourise(endStyledTo, pos);
} else { } else {
// Ask the watchers to style, and stop as soon as one responds. // Ask the watchers to style, and stop as soon as one responds.
for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin();
watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); (pos > GetEndStyled()) && (it != watchers.end()); ++it) {
it->watcher->NotifyStyleNeeded(this, it->userData, pos);
} }
} }
} }
@ -1772,8 +1738,8 @@ void Document::EnsureStyledTo(int pos) {
void Document::LexerChanged() { void Document::LexerChanged() {
// Tell the watchers the lexer has changed. // Tell the watchers the lexer has changed.
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifyLexerChanged(this, watchers[i].userData); it->watcher->NotifyLexerChanged(this, it->userData);
} }
} }
@ -1821,10 +1787,6 @@ void Document::MarginSetStyles(int line, const unsigned char *styles) {
NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line)); NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line));
} }
int Document::MarginLength(int line) const {
return static_cast<LineAnnotation *>(perLineData[ldMargin])->Length(line);
}
void Document::MarginClearAll() { void Document::MarginClearAll() {
int maxEditorLine = LinesTotal(); int maxEditorLine = LinesTotal();
for (int l=0; l<maxEditorLine; l++) for (int l=0; l<maxEditorLine; l++)
@ -1833,10 +1795,6 @@ void Document::MarginClearAll() {
static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll(); static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll();
} }
bool Document::AnnotationAny() const {
return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->AnySet();
}
StyledText Document::AnnotationStyledText(int line) { StyledText Document::AnnotationStyledText(int line) {
LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]); LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]);
return StyledText(pla->Length(line), pla->Text(line), return StyledText(pla->Length(line), pla->Text(line),
@ -1866,10 +1824,6 @@ void Document::AnnotationSetStyles(int line, const unsigned char *styles) {
} }
} }
int Document::AnnotationLength(int line) const {
return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Length(line);
}
int Document::AnnotationLines(int line) const { int Document::AnnotationLines(int line) const {
return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Lines(line); return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Lines(line);
} }
@ -1895,54 +1849,34 @@ void SCI_METHOD Document::DecorationFillRange(int position, int value, int fillL
} }
bool Document::AddWatcher(DocWatcher *watcher, void *userData) { bool Document::AddWatcher(DocWatcher *watcher, void *userData) {
for (int i = 0; i < lenWatchers; i++) { WatcherWithUserData wwud(watcher, userData);
if ((watchers[i].watcher == watcher) && std::vector<WatcherWithUserData>::iterator it =
(watchers[i].userData == userData)) std::find(watchers.begin(), watchers.end(), wwud);
return false; if (it != watchers.end())
} return false;
WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers + 1]; watchers.push_back(wwud);
for (int j = 0; j < lenWatchers; j++)
pwNew[j] = watchers[j];
pwNew[lenWatchers].watcher = watcher;
pwNew[lenWatchers].userData = userData;
delete []watchers;
watchers = pwNew;
lenWatchers++;
return true; return true;
} }
bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) { bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) {
for (int i = 0; i < lenWatchers; i++) { std::vector<WatcherWithUserData>::iterator it =
if ((watchers[i].watcher == watcher) && std::find(watchers.begin(), watchers.end(), WatcherWithUserData(watcher, userData));
(watchers[i].userData == userData)) { if (it != watchers.end()) {
if (lenWatchers == 1) { watchers.erase(it);
delete []watchers; return true;
watchers = 0;
lenWatchers = 0;
} else {
WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers];
for (int j = 0; j < lenWatchers - 1; j++) {
pwNew[j] = (j < i) ? watchers[j] : watchers[j + 1];
}
delete []watchers;
watchers = pwNew;
lenWatchers--;
}
return true;
}
} }
return false; return false;
} }
void Document::NotifyModifyAttempt() { void Document::NotifyModifyAttempt() {
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifyModifyAttempt(this, watchers[i].userData); it->watcher->NotifyModifyAttempt(this, it->userData);
} }
} }
void Document::NotifySavePoint(bool atSavePoint) { void Document::NotifySavePoint(bool atSavePoint) {
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifySavePoint(this, watchers[i].userData, atSavePoint); it->watcher->NotifySavePoint(this, it->userData, atSavePoint);
} }
} }
@ -1952,8 +1886,8 @@ void Document::NotifyModified(DocModification mh) {
} else if (mh.modificationType & SC_MOD_DELETETEXT) { } else if (mh.modificationType & SC_MOD_DELETETEXT) {
decorations.DeleteRange(mh.position, mh.length); decorations.DeleteRange(mh.position, mh.length);
} }
for (int i = 0; i < lenWatchers; i++) { for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData); it->watcher->NotifyModified(this, mh, it->userData);
} }
} }
@ -2127,10 +2061,9 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) {
*/ */
class BuiltinRegex : public RegexSearchBase { class BuiltinRegex : public RegexSearchBase {
public: public:
BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {} BuiltinRegex(CharClassify *charClassTable) : search(charClassTable) {}
virtual ~BuiltinRegex() { virtual ~BuiltinRegex() {
delete substituted;
} }
virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
@ -2141,7 +2074,7 @@ public:
private: private:
RESearch search; RESearch search;
char *substituted; std::string substituted;
}; };
// Define a way for the Regular Expression code to access the document // Define a way for the Regular Expression code to access the document
@ -2236,6 +2169,8 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s
int success = search.Execute(di, startOfLine, endOfLine); int success = search.Execute(di, startOfLine, endOfLine);
if (success) { if (success) {
pos = search.bopat[0]; pos = search.bopat[0];
// Ensure only whole characters selected
search.eopat[0] = doc->MovePositionOutsideChar(search.eopat[0], 1, false);
lenRet = search.eopat[0] - search.bopat[0]; lenRet = search.eopat[0] - search.bopat[0];
// There can be only one start of a line, so no need to look for last match in line // There can be only one start of a line, so no need to look for last match in line
if ((increment == -1) && (s[0] != '^')) { if ((increment == -1) && (s[0] != '^')) {
@ -2261,86 +2196,55 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s
} }
const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) { const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) {
delete []substituted; substituted.clear();
substituted = 0;
DocumentIndexer di(doc, doc->Length()); DocumentIndexer di(doc, doc->Length());
if (!search.GrabMatches(di)) search.GrabMatches(di);
return 0;
unsigned int lenResult = 0;
for (int i = 0; i < *length; i++) {
if (text[i] == '\\') {
if (text[i + 1] >= '0' && text[i + 1] <= '9') {
unsigned int patNum = text[i + 1] - '0';
lenResult += search.eopat[patNum] - search.bopat[patNum];
i++;
} else {
switch (text[i + 1]) {
case 'a':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
case 'v':
case '\\':
i++;
}
lenResult++;
}
} else {
lenResult++;
}
}
substituted = new char[lenResult + 1];
char *o = substituted;
for (int j = 0; j < *length; j++) { for (int j = 0; j < *length; j++) {
if (text[j] == '\\') { if (text[j] == '\\') {
if (text[j + 1] >= '0' && text[j + 1] <= '9') { if (text[j + 1] >= '0' && text[j + 1] <= '9') {
unsigned int patNum = text[j + 1] - '0'; unsigned int patNum = text[j + 1] - '0';
unsigned int len = search.eopat[patNum] - search.bopat[patNum]; unsigned int len = search.eopat[patNum] - search.bopat[patNum];
if (search.pat[patNum]) // Will be null if try for a match that did not occur if (!search.pat[patNum].empty()) // Will be null if try for a match that did not occur
memcpy(o, search.pat[patNum], len); substituted.append(search.pat[patNum].c_str(), len);
o += len;
j++; j++;
} else { } else {
j++; j++;
switch (text[j]) { switch (text[j]) {
case 'a': case 'a':
*o++ = '\a'; substituted.push_back('\a');
break; break;
case 'b': case 'b':
*o++ = '\b'; substituted.push_back('\b');
break; break;
case 'f': case 'f':
*o++ = '\f'; substituted.push_back('\f');
break; break;
case 'n': case 'n':
*o++ = '\n'; substituted.push_back('\n');
break; break;
case 'r': case 'r':
*o++ = '\r'; substituted.push_back('\r');
break; break;
case 't': case 't':
*o++ = '\t'; substituted.push_back('\t');
break; break;
case 'v': case 'v':
*o++ = '\v'; substituted.push_back('\v');
break; break;
case '\\': case '\\':
*o++ = '\\'; substituted.push_back('\\');
break; break;
default: default:
*o++ = '\\'; substituted.push_back('\\');
j--; j--;
} }
} }
} else { } else {
*o++ = text[j]; substituted.push_back(text[j]);
} }
} }
*o = '\0'; *length = static_cast<int>(substituted.length());
*length = lenResult; return substituted.c_str();
return substituted;
} }
#ifndef SCI_OWNREGEX #ifndef SCI_OWNREGEX

View File

@ -198,17 +198,17 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
public: public:
/** Used to pair watcher pointer with user data. */ /** Used to pair watcher pointer with user data. */
class WatcherWithUserData { struct WatcherWithUserData {
public:
DocWatcher *watcher; DocWatcher *watcher;
void *userData; void *userData;
WatcherWithUserData() { WatcherWithUserData(DocWatcher *watcher_=0, void *userData_=0) :
watcher = 0; watcher(watcher_), userData(userData_) {
userData = 0; }
bool operator==(const WatcherWithUserData &other) {
return (watcher == other.watcher) && (userData == other.userData);
} }
}; };
enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation };
private: private:
int refCount; int refCount;
CellBuffer cb; CellBuffer cb;
@ -221,8 +221,7 @@ private:
int enteredStyling; int enteredStyling;
int enteredReadOnlyCount; int enteredReadOnlyCount;
WatcherWithUserData *watchers; std::vector<WatcherWithUserData> watchers;
int lenWatchers;
// ldSize is not real data - it is for dimensions and loops // ldSize is not real data - it is for dimensions and loops
enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
@ -316,14 +315,13 @@ public:
int CountCharacters(int startPos, int endPos); int CountCharacters(int startPos, int endPos);
int FindColumn(int line, int column); int FindColumn(int line, int column);
void Indent(bool forwards, int lineBottom, int lineTop); void Indent(bool forwards, int lineBottom, int lineTop);
static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted); static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted);
void ConvertLineEnds(int eolModeSet); void ConvertLineEnds(int eolModeSet);
void SetReadOnly(bool set) { cb.SetReadOnly(set); } void SetReadOnly(bool set) { cb.SetReadOnly(set); }
bool IsReadOnly() { return cb.IsReadOnly(); } bool IsReadOnly() { return cb.IsReadOnly(); }
bool InsertChar(int pos, char ch); bool InsertChar(int pos, char ch);
bool InsertCString(int position, const char *s); bool InsertCString(int position, const char *s);
void ChangeChar(int pos, char ch);
void DelChar(int pos); void DelChar(int pos);
void DelCharBack(int pos); void DelCharBack(int pos);
@ -371,8 +369,6 @@ public:
const char *SubstituteByPosition(const char *text, int *length); const char *SubstituteByPosition(const char *text, int *length);
int LinesTotal() const; int LinesTotal() const;
void ChangeCase(Range r, bool makeUpperCase);
void SetDefaultCharClasses(bool includeWordClass); void SetDefaultCharClasses(bool includeWordClass);
void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass); void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer); int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer);
@ -399,22 +395,17 @@ public:
void MarginSetStyle(int line, int style); void MarginSetStyle(int line, int style);
void MarginSetStyles(int line, const unsigned char *styles); void MarginSetStyles(int line, const unsigned char *styles);
void MarginSetText(int line, const char *text); void MarginSetText(int line, const char *text);
int MarginLength(int line) const;
void MarginClearAll(); void MarginClearAll();
bool AnnotationAny() const;
StyledText AnnotationStyledText(int line); StyledText AnnotationStyledText(int line);
void AnnotationSetText(int line, const char *text); void AnnotationSetText(int line, const char *text);
void AnnotationSetStyle(int line, int style); void AnnotationSetStyle(int line, int style);
void AnnotationSetStyles(int line, const unsigned char *styles); void AnnotationSetStyles(int line, const unsigned char *styles);
int AnnotationLength(int line) const;
int AnnotationLines(int line) const; int AnnotationLines(int line) const;
void AnnotationClearAll(); void AnnotationClearAll();
bool AddWatcher(DocWatcher *watcher, void *userData); bool AddWatcher(DocWatcher *watcher, void *userData);
bool RemoveWatcher(DocWatcher *watcher, void *userData); bool RemoveWatcher(DocWatcher *watcher, void *userData);
const WatcherWithUserData *GetWatchers() const { return watchers; }
int GetLenWatchers() const { return lenWatchers; }
CharClassify::cc WordCharClass(unsigned char ch); CharClassify::cc WordCharClass(unsigned char ch);
bool IsWordPartSeparator(char ch); bool IsWordPartSeparator(char ch);

View File

@ -106,7 +106,7 @@ Editor::Editor() {
stylesValid = false; stylesValid = false;
technology = SC_TECHNOLOGY_DEFAULT; technology = SC_TECHNOLOGY_DEFAULT;
scaleRGBAImage = 100; scaleRGBAImage = 100;
printMagnification = 0; printMagnification = 0;
printColourMode = SC_PRINT_NORMAL; printColourMode = SC_PRINT_NORMAL;
printWrapState = eWrapWord; printWrapState = eWrapWord;
@ -149,7 +149,7 @@ Editor::Editor() {
caretYPolicy = CARET_EVEN; caretYPolicy = CARET_EVEN;
caretYSlop = 0; caretYSlop = 0;
visiblePolicy = 0; visiblePolicy = 0;
visibleSlop = 0; visibleSlop = 0;
@ -208,6 +208,7 @@ Editor::Editor() {
recordingMacro = false; recordingMacro = false;
foldFlags = 0; foldFlags = 0;
foldAutomatic = 0;
wrapState = eWrapNone; wrapState = eWrapNone;
wrapWidth = LineLayout::wrapWidthInfinite; wrapWidth = LineLayout::wrapWidthInfinite;
@ -1246,6 +1247,9 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange rang
const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1); const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
XYScrollPosition newXY(xOffset, topLine); XYScrollPosition newXY(xOffset, topLine);
if (rcClient.Empty()) {
return newXY;
}
// Vertical positioning // Vertical positioning
if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
@ -1764,7 +1768,7 @@ static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset,
size_t endSegment = start; size_t endSegment = start;
while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style)) while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style))
endSegment++; endSegment++;
width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, width += surface->WidthText(vs.styles[style+styleOffset].font, text + start,
static_cast<int>(endSegment - start + 1)); static_cast<int>(endSegment - start + 1));
start = endSegment + 1; start = endSegment + 1;
} }
@ -2286,7 +2290,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
if (vstyle.styles[ll->styles[charInLine]].visible) { if (vstyle.styles[ll->styles[charInLine]].visible) {
if (isControl) { if (isControl) {
if (ll->chars[charInLine] == '\t') { if (ll->chars[charInLine] == '\t') {
ll->positions[charInLine + 1] = ll->positions[charInLine + 1] =
((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx; ((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx;
} else if (controlCharSymbol < 32) { } else if (controlCharSymbol < 32) {
if (ctrlCharWidth[ll->chars[charInLine]] == 0) { if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
@ -3850,7 +3854,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
vsPrint.braceBadLightIndicatorSet = false; vsPrint.braceBadLightIndicatorSet = false;
// Set colours for printing according to users settings // Set colours for printing according to users settings
for (size_t sty = 0; sty < vsPrint.stylesSize; sty++) { for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
if (printColourMode == SC_PRINT_INVERTLIGHT) { if (printColourMode == SC_PRINT_INVERTLIGHT) {
vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
@ -4143,7 +4147,7 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
if (treatAsDBCS) { if (treatAsDBCS) {
NotifyChar((static_cast<unsigned char>(s[0]) << 8) | NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
static_cast<unsigned char>(s[1])); static_cast<unsigned char>(s[1]));
} else { } else if (len > 0) {
int byte = static_cast<unsigned char>(s[0]); int byte = static_cast<unsigned char>(s[0]);
if ((byte < 0xC0) || (1 == len)) { if ((byte < 0xC0) || (1 == len)) {
// Handles UTF-8 characters between 0x01 and 0x7F and single byte // Handles UTF-8 characters between 0x01 and 0x7F and single byte
@ -4443,7 +4447,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
void Editor::NotifyFocus(bool) {} void Editor::NotifyFocus(bool) {}
void Editor::SetCtrlID(int identifier) { void Editor::SetCtrlID(int identifier) {
ctrlID = identifier; ctrlID = identifier;
} }
void Editor::NotifyStyleToNeeded(int endStyleNeeded) { void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
@ -4563,11 +4567,32 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
x += vs.ms[margin].width; x += vs.ms[margin].width;
} }
if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) { if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
int position = pdoc->LineStart(LineFromLocation(pt));
if ((vs.ms[marginClicked].mask & SC_MASK_FOLDERS) && (foldAutomatic & SC_AUTOMATICFOLD_CLICK)) {
int lineClick = pdoc->LineFromPosition(position);
if (shift && ctrl) {
FoldAll(SC_FOLDACTION_TOGGLE);
} else {
int levelClick = pdoc->GetLevel(lineClick);
if (levelClick & SC_FOLDLEVELHEADERFLAG) {
if (shift) {
// Ensure all children visible
FoldExpand(lineClick, SC_FOLDACTION_EXPAND, levelClick);
} else if (ctrl) {
FoldExpand(lineClick, SC_FOLDACTION_TOGGLE, levelClick);
} else {
// Toggle this line
FoldLine(lineClick, SC_FOLDACTION_TOGGLE);
}
}
}
return true;
}
SCNotification scn = {0}; SCNotification scn = {0};
scn.nmhdr.code = SCN_MARGINCLICK; scn.nmhdr.code = SCN_MARGINCLICK;
scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
(alt ? SCI_ALT : 0); (alt ? SCI_ALT : 0);
scn.position = pdoc->LineStart(LineFromLocation(pt)); scn.position = position;
scn.margin = marginClicked; scn.margin = marginClicked;
NotifyParent(scn); NotifyParent(scn);
return true; return true;
@ -4706,11 +4731,11 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {
insertingNewLine = true; insertingNewLine = true;
} }
if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos))) if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos)))
NotifyNeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position); NeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position);
else else
NotifyNeedShown(mh.position, 0); NeedShown(mh.position, 0);
} else if (mh.modificationType & SC_MOD_BEFOREDELETE) { } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
NotifyNeedShown(mh.position, mh.length); NeedShown(mh.position, mh.length);
} }
} }
if (mh.linesAdded != 0) { if (mh.linesAdded != 0) {
@ -4767,6 +4792,9 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {
} }
} }
} }
if ((mh.modificationType & SC_MOD_CHANGEFOLD) && (foldAutomatic & SC_AUTOMATICFOLD_CHANGE)) {
FoldChanged(mh.line, mh.foldLevelNow, mh.foldLevelPrev);
}
// NOW pay the piper WRT "deferred" visual updates // NOW pay the piper WRT "deferred" visual updates
if (IsLastStep(mh)) { if (IsLastStep(mh)) {
@ -4989,10 +5017,9 @@ void Editor::ChangeCaseOfSelection(int caseMapping) {
SelectionRange current = sel.Range(r); SelectionRange current = sel.Range(r);
SelectionRange currentNoVS = current; SelectionRange currentNoVS = current;
currentNoVS.ClearVirtualSpace(); currentNoVS.ClearVirtualSpace();
char *text = CopyRange(currentNoVS.Start().Position(), currentNoVS.End().Position());
size_t rangeBytes = currentNoVS.Length(); size_t rangeBytes = currentNoVS.Length();
if (rangeBytes > 0) { if (rangeBytes > 0) {
std::string sText(text, rangeBytes); std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position());
std::string sMapped = CaseMapString(sText, caseMapping); std::string sMapped = CaseMapString(sText, caseMapping);
@ -5015,7 +5042,6 @@ void Editor::ChangeCaseOfSelection(int caseMapping) {
sel.Range(r) = current; sel.Range(r) = current;
} }
} }
delete []text;
} }
} }
@ -5027,17 +5053,15 @@ void Editor::LineTranspose() {
int endPrev = pdoc->LineEnd(line - 1); int endPrev = pdoc->LineEnd(line - 1);
int start = pdoc->LineStart(line); int start = pdoc->LineStart(line);
int end = pdoc->LineEnd(line); int end = pdoc->LineEnd(line);
char *line1 = CopyRange(startPrev, endPrev); std::string line1 = RangeText(startPrev, endPrev);
int len1 = endPrev - startPrev; int len1 = endPrev - startPrev;
char *line2 = CopyRange(start, end); std::string line2 = RangeText(start, end);
int len2 = end - start; int len2 = end - start;
pdoc->DeleteChars(start, len2); pdoc->DeleteChars(start, len2);
pdoc->DeleteChars(startPrev, len1); pdoc->DeleteChars(startPrev, len1);
pdoc->InsertString(startPrev, line2, len2); pdoc->InsertString(startPrev, line2.c_str(), len2);
pdoc->InsertString(start - len1 + len2, line1, len1); pdoc->InsertString(start - len1 + len2, line1.c_str(), len1);
MovePositionTo(SelectionPosition(start - len1 + len2)); MovePositionTo(SelectionPosition(start - len1 + len2));
delete []line1;
delete []line2;
} }
} }
@ -5060,11 +5084,10 @@ void Editor::Duplicate(bool forLine) {
start = SelectionPosition(pdoc->LineStart(line)); start = SelectionPosition(pdoc->LineStart(line));
end = SelectionPosition(pdoc->LineEnd(line)); end = SelectionPosition(pdoc->LineEnd(line));
} }
char *text = CopyRange(start.Position(), end.Position()); std::string text = RangeText(start.Position(), end.Position());
if (forLine) if (forLine)
pdoc->InsertString(end.Position(), eol, eolLen); pdoc->InsertString(end.Position(), eol, eolLen);
pdoc->InsertString(end.Position() + eolLen, text, SelectionRange(end, start).Length()); pdoc->InsertString(end.Position() + eolLen, text.c_str(), SelectionRange(end, start).Length());
delete []text;
} }
if (sel.Count() && sel.IsRectangular()) { if (sel.Count() && sel.IsRectangular()) {
SelectionPosition last = sel.Last(); SelectionPosition last = sel.Last();
@ -5975,19 +5998,6 @@ static bool Close(Point pt1, Point pt2) {
return true; return true;
} }
char *Editor::CopyRange(int start, int end) {
char *text = 0;
if (start < end) {
int len = end - start;
text = new char[len + 1];
for (int i = 0; i < len; i++) {
text[i] = pdoc->CharAt(start + i);
}
text[len] = '\0';
}
return text;
}
std::string Editor::RangeText(int start, int end) const { std::string Editor::RangeText(int start, int end) const {
if (start < end) { if (start < end) {
int len = end - start; int len = end - start;
@ -6007,21 +6017,13 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
int start = pdoc->LineStart(currentLine); int start = pdoc->LineStart(currentLine);
int end = pdoc->LineEnd(currentLine); int end = pdoc->LineEnd(currentLine);
char *text = CopyRange(start, end); std::string text = RangeText(start, end);
size_t textLen = text ? strlen(text) : 0;
// include room for \r\n\0
textLen += 3;
char *textWithEndl = new char[textLen];
textWithEndl[0] = '\0';
if (text)
strcat(textWithEndl, text);
if (pdoc->eolMode != SC_EOL_LF) if (pdoc->eolMode != SC_EOL_LF)
strcat(textWithEndl, "\r"); text.append("\r");
if (pdoc->eolMode != SC_EOL_CR) if (pdoc->eolMode != SC_EOL_CR)
strcat(textWithEndl, "\n"); text.append("\n");
ss->Set(textWithEndl, static_cast<int>(strlen(textWithEndl) + 1), ss->Copy(text.c_str(), static_cast<int>(text.length() + 1),
pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true); pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true);
delete []text;
} }
} else { } else {
int delimiterLength = 0; int delimiterLength = 0;
@ -6033,7 +6035,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
} }
} }
size_t size = sel.Length() + delimiterLength * sel.Count(); size_t size = sel.Length() + delimiterLength * sel.Count();
char *text = new char[size + 1]; std::string text(size+1, '\0');
int j = 0; int j = 0;
std::vector<SelectionRange> rangesInOrder = sel.RangesCopy(); std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
if (sel.selType == Selection::selRectangle) if (sel.selType == Selection::selRectangle)
@ -6055,7 +6057,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
} }
} }
text[size] = '\0'; text[size] = '\0';
ss->Set(text, static_cast<int>(size + 1), pdoc->dbcsCodePage, ss->Copy(&text[0], static_cast<int>(size + 1), pdoc->dbcsCodePage,
vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines); vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
} }
} }
@ -6064,7 +6066,8 @@ void Editor::CopyRangeToClipboard(int start, int end) {
start = pdoc->ClampPositionIntoDocument(start); start = pdoc->ClampPositionIntoDocument(start);
end = pdoc->ClampPositionIntoDocument(end); end = pdoc->ClampPositionIntoDocument(end);
SelectionText selectedText; SelectionText selectedText;
selectedText.Set(CopyRange(start, end), end - start + 1, std::string text = RangeText(start, end);
selectedText.Copy(text.c_str(), end - start + 1,
pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false); pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
CopyToClipboard(selectedText); CopyToClipboard(selectedText);
} }
@ -6349,7 +6352,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
if (inSelMargin) { if (inSelMargin) {
// Inside margin selection type should be either selSubLine or selWholeLine. // Inside margin selection type should be either selSubLine or selWholeLine.
if (selectionType == selSubLine) { if (selectionType == selSubLine) {
// If it is selSubLine, we're inside a *double* click and word wrap is enabled, // If it is selSubLine, we're inside a *double* click and word wrap is enabled,
// so we switch to selWholeLine in order to select whole line. // so we switch to selWholeLine in order to select whole line.
selectionType = selWholeLine; selectionType = selWholeLine;
} else if (selectionType != selSubLine && selectionType != selWholeLine) { } else if (selectionType != selSubLine && selectionType != selWholeLine) {
@ -6361,7 +6364,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
selectionType = selWord; selectionType = selWord;
doubleClick = true; doubleClick = true;
} else if (selectionType == selWord) { } else if (selectionType == selWord) {
// Since we ended up here, we're inside a *triple* click, which should always select // Since we ended up here, we're inside a *triple* click, which should always select
// whole line irregardless of word wrap being enabled or not. // whole line irregardless of word wrap being enabled or not.
selectionType = selWholeLine; selectionType = selWholeLine;
} else { } else {
@ -6426,7 +6429,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
lineAnchorPos = sel.MainAnchor() - 1; lineAnchorPos = sel.MainAnchor() - 1;
else else
lineAnchorPos = sel.MainAnchor(); lineAnchorPos = sel.MainAnchor();
// Reset selection type if there is an empty selection. // Reset selection type if there is an empty selection.
// This ensures that we don't end up stuck in previous selection mode, which is no longer valid. // This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
// Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine. // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine.
// This ensures that we continue selecting in the same selection mode. // This ensures that we continue selecting in the same selection mode.
@ -6962,34 +6965,42 @@ void Editor::SetAnnotationVisible(int visible) {
/** /**
* Recursively expand a fold, making lines visible except where they have an unexpanded parent. * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
*/ */
void Editor::Expand(int &line, bool doExpand) { int Editor::ExpandLine(int line) {
int lineMaxSubord = pdoc->GetLastChild(line); int lineMaxSubord = pdoc->GetLastChild(line);
line++; line++;
while (line <= lineMaxSubord) { while (line <= lineMaxSubord) {
if (doExpand) cs.SetVisible(line, line, true);
cs.SetVisible(line, line, true);
int level = pdoc->GetLevel(line); int level = pdoc->GetLevel(line);
if (level & SC_FOLDLEVELHEADERFLAG) { if (level & SC_FOLDLEVELHEADERFLAG) {
if (doExpand && cs.GetExpanded(line)) { if (cs.GetExpanded(line)) {
Expand(line, true); line = ExpandLine(line);
} else { } else {
Expand(line, false); line = pdoc->GetLastChild(line);
} }
} else {
line++;
} }
line++;
}
return lineMaxSubord;
}
void Editor::SetFoldExpanded(int lineDoc, bool expanded) {
if (cs.SetExpanded(lineDoc, expanded)) {
RedrawSelMargin();
} }
} }
void Editor::ToggleContraction(int line) { void Editor::FoldLine(int line, int action) {
if (line >= 0) { if (line >= 0) {
if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) { if (action == SC_FOLDACTION_TOGGLE) {
line = pdoc->GetFoldParent(line); if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
if (line < 0) line = pdoc->GetFoldParent(line);
return; if (line < 0)
return;
}
action = (cs.GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND;
} }
if (cs.GetExpanded(line)) { if (action == SC_FOLDACTION_CONTRACT) {
int lineMaxSubord = pdoc->GetLastChild(line); int lineMaxSubord = pdoc->GetLastChild(line);
if (lineMaxSubord > line) { if (lineMaxSubord > line) {
cs.SetExpanded(line, 0); cs.SetExpanded(line, 0);
@ -7000,9 +7011,6 @@ void Editor::ToggleContraction(int line) {
// This does not re-expand the fold // This does not re-expand the fold
EnsureCaretVisible(); EnsureCaretVisible();
} }
SetScrollBars();
Redraw();
} }
} else { } else {
@ -7011,13 +7019,37 @@ void Editor::ToggleContraction(int line) {
GoToLine(line); GoToLine(line);
} }
cs.SetExpanded(line, 1); cs.SetExpanded(line, 1);
Expand(line, true); ExpandLine(line);
SetScrollBars();
Redraw();
} }
SetScrollBars();
Redraw();
} }
} }
void Editor::FoldExpand(int line, int action, int level) {
bool expanding = action == SC_FOLDACTION_EXPAND;
if (action == SC_FOLDACTION_TOGGLE) {
expanding = !cs.GetExpanded(line);
}
SetFoldExpanded(line, expanding);
if (expanding && (cs.HiddenLines() == 0))
// Nothing to do
return;
int lineMaxSubord = pdoc->GetLastChild(line, level & SC_FOLDLEVELNUMBERMASK);
line++;
cs.SetVisible(line, lineMaxSubord, expanding);
while (line <= lineMaxSubord) {
int levelLine = pdoc->GetLevel(line);
if (levelLine & SC_FOLDLEVELHEADERFLAG) {
SetFoldExpanded(line, expanding);
}
line++;
}
SetScrollBars();
Redraw();
}
int Editor::ContractedFoldNext(int lineStart) { int Editor::ContractedFoldNext(int lineStart) {
for (int line = lineStart; line<pdoc->LinesTotal();) { for (int line = lineStart; line<pdoc->LinesTotal();) {
if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG)) if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG))
@ -7041,7 +7073,7 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
WrapLines(true, -1); WrapLines(true, -1);
if (!cs.GetVisible(lineDoc)) { if (!cs.GetVisible(lineDoc)) {
// Back up to find a non-blank line // Back up to find a non-blank line
int lookLine = lineDoc; int lookLine = lineDoc;
int lookLineLevel = pdoc->GetLevel(lookLine); int lookLineLevel = pdoc->GetLevel(lookLine);
while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) { while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
@ -7049,7 +7081,7 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
} }
int lineParent = pdoc->GetFoldParent(lookLine); int lineParent = pdoc->GetFoldParent(lookLine);
if (lineParent < 0) { if (lineParent < 0) {
// Backed up to a top level line, so try to find parent of initial line // Backed up to a top level line, so try to find parent of initial line
lineParent = pdoc->GetFoldParent(lineDoc); lineParent = pdoc->GetFoldParent(lineDoc);
} }
if (lineParent >= 0) { if (lineParent >= 0) {
@ -7057,7 +7089,7 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
EnsureLineVisible(lineParent, enforcePolicy); EnsureLineVisible(lineParent, enforcePolicy);
if (!cs.GetExpanded(lineParent)) { if (!cs.GetExpanded(lineParent)) {
cs.SetExpanded(lineParent, 1); cs.SetExpanded(lineParent, 1);
Expand(lineParent, true); ExpandLine(lineParent);
} }
} }
SetScrollBars(); SetScrollBars();
@ -7086,6 +7118,89 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
} }
} }
void Editor::FoldAll(int action) {
pdoc->EnsureStyledTo(pdoc->Length());
int maxLine = pdoc->LinesTotal();
bool expanding = action == SC_FOLDACTION_EXPAND;
if (action == SC_FOLDACTION_TOGGLE) {
// Discover current state
for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) {
if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) {
expanding = !cs.GetExpanded(lineSeek);
break;
}
}
}
if (expanding) {
cs.SetVisible(0, maxLine-1, true);
for (int line = 0; line < maxLine; line++) {
int levelLine = pdoc->GetLevel(line);
if (levelLine & SC_FOLDLEVELHEADERFLAG) {
SetFoldExpanded(line, true);
}
}
} else {
for (int line = 0; line < maxLine; line++) {
int level = pdoc->GetLevel(line);
if ((level & SC_FOLDLEVELHEADERFLAG) &&
(SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) {
SetFoldExpanded(line, false);
int lineMaxSubord = pdoc->GetLastChild(line, -1);
if (lineMaxSubord > line) {
cs.SetVisible(line + 1, lineMaxSubord, false);
}
}
}
}
SetScrollBars();
Redraw();
}
void Editor::FoldChanged(int line, int levelNow, int levelPrev) {
if (levelNow & SC_FOLDLEVELHEADERFLAG) {
if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
// Adding a fold point.
if (cs.SetExpanded(line, true)) {
RedrawSelMargin();
}
FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
}
} else if (levelPrev & SC_FOLDLEVELHEADERFLAG) {
if (!cs.GetExpanded(line)) {
// Removing the fold from one that has been contracted so should expand
// otherwise lines are left invisible with no way to make them visible
if (cs.SetExpanded(line, true)) {
RedrawSelMargin();
}
FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
}
}
if (!(levelNow & SC_FOLDLEVELWHITEFLAG) &&
((levelPrev & SC_FOLDLEVELNUMBERMASK) > (levelNow & SC_FOLDLEVELNUMBERMASK))) {
if (cs.HiddenLines()) {
// See if should still be hidden
int parentLine = pdoc->GetFoldParent(line);
if ((parentLine < 0) || (cs.GetExpanded(parentLine) && cs.GetVisible(parentLine))) {
cs.SetVisible(line, line, true);
SetScrollBars();
Redraw();
}
}
}
}
void Editor::NeedShown(int pos, int len) {
if (foldAutomatic & SC_AUTOMATICFOLD_SHOW) {
int lineStart = pdoc->LineFromPosition(pos);
int lineEnd = pdoc->LineFromPosition(pos+len);
for (int line = lineStart; line <= lineEnd; line++) {
EnsureLineVisible(line, false);
}
} else {
NotifyNeedShown(pos, len);
}
}
int Editor::GetTag(char *tagValue, int tagNumber) { int Editor::GetTag(char *tagValue, int tagNumber) {
const char *text = 0; const char *text = 0;
int length = 0; int length = 0;
@ -7148,18 +7263,17 @@ int Editor::WrapCount(int line) {
void Editor::AddStyledText(char *buffer, int appendLength) { void Editor::AddStyledText(char *buffer, int appendLength) {
// The buffer consists of alternating character bytes and style bytes // The buffer consists of alternating character bytes and style bytes
int textLength = appendLength / 2; int textLength = appendLength / 2;
char *text = new char[textLength]; std::string text(textLength, '\0');
int i; int i;
for (i = 0; i < textLength; i++) { for (i = 0; i < textLength; i++) {
text[i] = buffer[i*2]; text[i] = buffer[i*2];
} }
pdoc->InsertString(CurrentPosition(), text, textLength); pdoc->InsertString(CurrentPosition(), text.c_str(), textLength);
for (i = 0; i < textLength; i++) { for (i = 0; i < textLength; i++) {
text[i] = buffer[i*2+1]; text[i] = buffer[i*2+1];
} }
pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff)); pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
pdoc->SetStyles(textLength, text); pdoc->SetStyles(textLength, text.c_str());
delete []text;
SetEmptySelection(sel.MainCaret() + textLength); SetEmptySelection(sel.MainCaret() + textLength);
} }
@ -7907,10 +8021,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_GETLINEENDTYPESALLOWED: case SCI_GETLINEENDTYPESALLOWED:
return pdoc->GetLineEndTypesAllowed(); return pdoc->GetLineEndTypesAllowed();
case SCI_GETLINEENDTYPESACTIVE: case SCI_GETLINEENDTYPESACTIVE:
return pdoc->GetLineEndTypesActive(); return pdoc->GetLineEndTypesActive();
case SCI_STARTSTYLING: case SCI_STARTSTYLING:
pdoc->StartStyling(wParam, static_cast<char>(lParam)); pdoc->StartStyling(wParam, static_cast<char>(lParam));
break; break;
@ -8123,7 +8237,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break; break;
case SCI_TEXTWIDTH: case SCI_TEXTWIDTH:
PLATFORM_ASSERT(wParam < vs.stylesSize); PLATFORM_ASSERT(wParam < vs.styles.size());
PLATFORM_ASSERT(lParam); PLATFORM_ASSERT(lParam);
return TextWidth(wParam, CharPtrFromSPtr(lParam)); return TextWidth(wParam, CharPtrFromSPtr(lParam));
@ -8292,7 +8406,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_MARKERGET: case SCI_MARKERGET:
return pdoc->GetMark(wParam); return pdoc->GetMark(wParam);
case SCI_MARKERNEXT: case SCI_MARKERNEXT:
return pdoc->MarkerNext(wParam, lParam); return pdoc->MarkerNext(wParam, lParam);
case SCI_MARKERPREVIOUS: { case SCI_MARKERPREVIOUS: {
@ -8533,21 +8647,42 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return cs.HiddenLines() ? 0 : 1; return cs.HiddenLines() ? 0 : 1;
case SCI_SETFOLDEXPANDED: case SCI_SETFOLDEXPANDED:
if (cs.SetExpanded(wParam, lParam != 0)) { SetFoldExpanded(wParam, lParam != 0);
RedrawSelMargin();
}
break; break;
case SCI_GETFOLDEXPANDED: case SCI_GETFOLDEXPANDED:
return cs.GetExpanded(wParam); return cs.GetExpanded(wParam);
case SCI_SETAUTOMATICFOLD:
foldAutomatic = wParam;
break;
case SCI_GETAUTOMATICFOLD:
return foldAutomatic;
case SCI_SETFOLDFLAGS: case SCI_SETFOLDFLAGS:
foldFlags = wParam; foldFlags = wParam;
Redraw(); Redraw();
break; break;
case SCI_TOGGLEFOLD: case SCI_TOGGLEFOLD:
ToggleContraction(wParam); FoldLine(wParam, SC_FOLDACTION_TOGGLE);
break;
case SCI_FOLDLINE:
FoldLine(wParam, lParam);
break;
case SCI_FOLDCHILDREN:
FoldExpand(wParam, lParam, pdoc->GetLevel(wParam));
break;
case SCI_FOLDALL:
FoldAll(wParam);
break;
case SCI_EXPANDCHILDREN:
FoldExpand(wParam, SC_FOLDACTION_EXPAND, lParam);
break; break;
case SCI_CONTRACTEDFOLDNEXT: case SCI_CONTRACTEDFOLDNEXT:
@ -8561,7 +8696,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
EnsureLineVisible(wParam, true); EnsureLineVisible(wParam, true);
break; break;
case SCI_SCROLLRANGE: case SCI_SCROLLRANGE:
ScrollRange(SelectionRange(lParam, wParam)); ScrollRange(SelectionRange(lParam, wParam));
break; break;
@ -8934,9 +9069,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_CREATEDOCUMENT: { case SCI_CREATEDOCUMENT: {
Document *doc = new Document(); Document *doc = new Document();
if (doc) { doc->AddRef();
doc->AddRef();
}
return reinterpret_cast<sptr_t>(doc); return reinterpret_cast<sptr_t>(doc);
} }
@ -8950,11 +9083,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_CREATELOADER: { case SCI_CREATELOADER: {
Document *doc = new Document(); Document *doc = new Document();
if (doc) { doc->AddRef();
doc->AddRef(); doc->Allocate(wParam);
doc->Allocate(wParam); doc->SetUndoCollection(false);
doc->SetUndoCollection(false);
}
return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc)); return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
} }
@ -9499,18 +9630,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_CHANGELEXERSTATE: case SCI_CHANGELEXERSTATE:
pdoc->ChangeLexerState(wParam, lParam); pdoc->ChangeLexerState(wParam, lParam);
break; break;
case SCI_SETIDENTIFIER: case SCI_SETIDENTIFIER:
SetCtrlID(wParam); SetCtrlID(wParam);
break; break;
case SCI_GETIDENTIFIER: case SCI_GETIDENTIFIER:
return GetCtrlID(); return GetCtrlID();
case SCI_SETTECHNOLOGY: case SCI_SETTECHNOLOGY:
// No action by default // No action by default
break; break;
case SCI_GETTECHNOLOGY: case SCI_GETTECHNOLOGY:
return technology; return technology;

View File

@ -91,20 +91,13 @@ public:
Free(); Free();
} }
void Free() { void Free() {
Set(0, 0, 0, 0, false, false);
}
void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s; delete []s;
s = s_; s = 0;
if (s) len = 0;
len = len_; rectangular = false;
else lineCopy = false;
len = 0; codePage = 0;
codePage = codePage_; characterSet = 0;
characterSet = characterSet_;
rectangular = rectangular_;
lineCopy = lineCopy_;
FixSelectionForClipboard();
} }
void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) { void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s; delete []s;
@ -274,6 +267,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
bool recordingMacro; bool recordingMacro;
int foldFlags; int foldFlags;
int foldAutomatic;
ContractionState cs; ContractionState cs;
// Hotspot support // Hotspot support
@ -522,7 +516,6 @@ protected: // ScintillaBase subclass needs access to much of Editor
void GoToLine(int lineNo); void GoToLine(int lineNo);
virtual void CopyToClipboard(const SelectionText &selectedText) = 0; virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
char *CopyRange(int start, int end);
std::string RangeText(int start, int end) const; std::string RangeText(int start, int end) const;
void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false); void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
void CopyRangeToClipboard(int start, int end); void CopyRangeToClipboard(int start, int end);
@ -565,14 +558,20 @@ protected: // ScintillaBase subclass needs access to much of Editor
void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
void SetAnnotationHeights(int start, int end); void SetAnnotationHeights(int start, int end);
void SetDocPointer(Document *document); virtual void SetDocPointer(Document *document);
void SetAnnotationVisible(int visible); void SetAnnotationVisible(int visible);
void Expand(int &line, bool doExpand); int ExpandLine(int line);
void ToggleContraction(int line); void SetFoldExpanded(int lineDoc, bool expanded);
void FoldLine(int line, int action);
void FoldExpand(int line, int action, int level);
int ContractedFoldNext(int lineStart); int ContractedFoldNext(int lineStart);
void EnsureLineVisible(int lineDoc, bool enforcePolicy); void EnsureLineVisible(int lineDoc, bool enforcePolicy);
void FoldChanged(int line, int levelNow, int levelPrev);
void NeedShown(int pos, int len);
void FoldAll(int action);
int GetTag(char *tagValue, int tagNumber); int GetTag(char *tagValue, int tagNumber);
int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);

View File

@ -152,6 +152,9 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
surface->FillRectangle(rcDot, fore); surface->FillRectangle(rcDot, fore);
x += 2; x += 2;
} }
} else if (style == INDIC_COMPOSITIONTHICK) {
PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom);
surface->FillRectangle(rcComposition, fore);
} else { // Either INDIC_PLAIN or unknown } else { // Either INDIC_PLAIN or unknown
surface->MoveTo(rc.left, ymid); surface->MoveTo(rc.left, ymid);
surface->LineTo(rc.right, ymid); surface->LineTo(rc.right, ymid);

View File

@ -5,6 +5,10 @@
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <vector>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
@ -15,7 +19,7 @@
using namespace Scintilla; using namespace Scintilla;
#endif #endif
KeyMap::KeyMap() : kmap(0), len(0), alloc(0) { KeyMap::KeyMap() {
for (int i = 0; MapDefault[i].key; i++) { for (int i = 0; MapDefault[i].key; i++) {
AssignCmdKey(MapDefault[i].key, AssignCmdKey(MapDefault[i].key,
MapDefault[i].modifiers, MapDefault[i].modifiers,
@ -28,37 +32,25 @@ KeyMap::~KeyMap() {
} }
void KeyMap::Clear() { void KeyMap::Clear() {
delete []kmap; kmap.clear();
kmap = 0;
len = 0;
alloc = 0;
} }
void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) { void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) {
if ((len+1) >= alloc) { for (size_t keyIndex = 0; keyIndex < kmap.size(); keyIndex++) {
KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
if (!ktcNew)
return;
for (int k = 0; k < len; k++)
ktcNew[k] = kmap[k];
alloc += 5;
delete []kmap;
kmap = ktcNew;
}
for (int keyIndex = 0; keyIndex < len; keyIndex++) {
if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) { if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
kmap[keyIndex].msg = msg; kmap[keyIndex].msg = msg;
return; return;
} }
} }
kmap[len].key = key; KeyToCommand ktc;
kmap[len].modifiers = modifiers; ktc.key = key;
kmap[len].msg = msg; ktc.modifiers = modifiers;
len++; ktc.msg = msg;
kmap.push_back(ktc);
} }
unsigned int KeyMap::Find(int key, int modifiers) { unsigned int KeyMap::Find(int key, int modifiers) {
for (int i = 0; i < len; i++) { for (size_t i = 0; i < kmap.size(); i++) {
if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) { if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
return kmap[i].msg; return kmap[i].msg;
} }

View File

@ -32,9 +32,7 @@ public:
/** /**
*/ */
class KeyMap { class KeyMap {
KeyToCommand *kmap; std::vector<KeyToCommand> kmap;
int len;
int alloc;
static const KeyToCommand MapDefault[]; static const KeyToCommand MapDefault[];
public: public:

View File

@ -7,6 +7,8 @@
#include <string.h> #include <string.h>
#include <algorithm>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
@ -43,17 +45,6 @@ int MarkerHandleSet::Length() const {
return c; return c;
} }
int MarkerHandleSet::NumberFromHandle(int handle) const {
MarkerHandleNumber *mhn = root;
while (mhn) {
if (mhn->handle == handle) {
return mhn->number;
}
mhn = mhn->next;
}
return - 1;
}
int MarkerHandleSet::MarkValue() const { int MarkerHandleSet::MarkValue() const {
unsigned int m = 0; unsigned int m = 0;
MarkerHandleNumber *mhn = root; MarkerHandleNumber *mhn = root;
@ -77,8 +68,6 @@ bool MarkerHandleSet::Contains(int handle) const {
bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
MarkerHandleNumber *mhn = new MarkerHandleNumber; MarkerHandleNumber *mhn = new MarkerHandleNumber;
if (!mhn)
return false;
mhn->handle = handle; mhn->handle = handle;
mhn->number = markerNum; mhn->number = markerNum;
mhn->next = root; mhn->next = root;
@ -209,8 +198,6 @@ int LineMarkers::AddMark(int line, int markerNum, int lines) {
if (!markers[line]) { if (!markers[line]) {
// Need new structure to hold marker handle // Need new structure to hold marker handle
markers[line] = new MarkerHandleSet(); markers[line] = new MarkerHandleSet();
if (!markers[line])
return -1;
} }
markers[line]->InsertHandle(handleCurrent, markerNum); markers[line]->InsertHandle(handleCurrent, markerNum);
@ -389,10 +376,6 @@ void LineAnnotation::RemoveLine(int line) {
} }
} }
bool LineAnnotation::AnySet() const {
return annotations.Length() > 0;
}
bool LineAnnotation::MultipleStyles(int line) const { bool LineAnnotation::MultipleStyles(int line) const {
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles; return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;

View File

@ -32,7 +32,6 @@ public:
MarkerHandleSet(); MarkerHandleSet();
~MarkerHandleSet(); ~MarkerHandleSet();
int Length() const; int Length() const;
int NumberFromHandle(int handle) const;
int MarkValue() const; ///< Bit set of marker numbers. int MarkValue() const; ///< Bit set of marker numbers.
bool Contains(int handle) const; bool Contains(int handle) const;
bool InsertHandle(int handle, int markerNum); bool InsertHandle(int handle, int markerNum);
@ -101,7 +100,6 @@ public:
virtual void InsertLine(int line); virtual void InsertLine(int line);
virtual void RemoveLine(int line); virtual void RemoveLine(int line);
bool AnySet() const;
bool MultipleStyles(int line) const; bool MultipleStyles(int line) const;
int Style(int line); int Style(int line);
const char *Text(int line) const; const char *Text(int line) const;

View File

@ -207,7 +207,7 @@ int LineLayout::EndLineStyle() const {
} }
LineLayoutCache::LineLayoutCache() : LineLayoutCache::LineLayoutCache() :
level(0), length(0), size(0), cache(0), level(0),
allInvalidated(false), styleClock(-1), useCount(0) { allInvalidated(false), styleClock(-1), useCount(0) {
Allocate(0); Allocate(0);
} }
@ -216,24 +216,15 @@ LineLayoutCache::~LineLayoutCache() {
Deallocate(); Deallocate();
} }
void LineLayoutCache::Allocate(int length_) { void LineLayoutCache::Allocate(size_t length_) {
PLATFORM_ASSERT(cache == NULL); PLATFORM_ASSERT(cache.empty());
allInvalidated = false; allInvalidated = false;
length = length_; cache.resize(length_);
size = length;
if (size > 1) {
size = (size / 16 + 1) * 16;
}
if (size > 0) {
cache = new LineLayout * [size];
}
for (int i = 0; i < size; i++)
cache[i] = 0;
} }
void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) { void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
PLATFORM_ASSERT(useCount == 0); PLATFORM_ASSERT(useCount == 0);
int lengthForLevel = 0; size_t lengthForLevel = 0;
if (level == llcCaret) { if (level == llcCaret) {
lengthForLevel = 1; lengthForLevel = 1;
} else if (level == llcPage) { } else if (level == llcPage) {
@ -241,35 +232,31 @@ void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
} else if (level == llcDocument) { } else if (level == llcDocument) {
lengthForLevel = linesInDoc; lengthForLevel = linesInDoc;
} }
if (lengthForLevel > size) { if (lengthForLevel > cache.size()) {
Deallocate(); Deallocate();
Allocate(lengthForLevel); Allocate(lengthForLevel);
} else { } else {
if (lengthForLevel < length) { if (lengthForLevel < cache.size()) {
for (int i = lengthForLevel; i < length; i++) { for (size_t i = lengthForLevel; i < cache.size(); i++) {
delete cache[i]; delete cache[i];
cache[i] = 0; cache[i] = 0;
} }
} }
length = lengthForLevel; cache.resize(lengthForLevel);
} }
PLATFORM_ASSERT(length == lengthForLevel); PLATFORM_ASSERT(cache.size() == lengthForLevel);
PLATFORM_ASSERT(cache != NULL || length == 0);
} }
void LineLayoutCache::Deallocate() { void LineLayoutCache::Deallocate() {
PLATFORM_ASSERT(useCount == 0); PLATFORM_ASSERT(useCount == 0);
for (int i = 0; i < length; i++) for (size_t i = 0; i < cache.size(); i++)
delete cache[i]; delete cache[i];
delete []cache; cache.clear();
cache = 0;
length = 0;
size = 0;
} }
void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) { void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
if (cache && !allInvalidated) { if (!cache.empty() && !allInvalidated) {
for (int i = 0; i < length; i++) { for (size_t i = 0; i < cache.size(); i++) {
if (cache[i]) { if (cache[i]) {
cache[i]->Invalidate(validity_); cache[i]->Invalidate(validity_);
} }
@ -303,15 +290,15 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
} else if (level == llcPage) { } else if (level == llcPage) {
if (lineNumber == lineCaret) { if (lineNumber == lineCaret) {
pos = 0; pos = 0;
} else if (length > 1) { } else if (cache.size() > 1) {
pos = 1 + (lineNumber % (length - 1)); pos = 1 + (lineNumber % (cache.size() - 1));
} }
} else if (level == llcDocument) { } else if (level == llcDocument) {
pos = lineNumber; pos = lineNumber;
} }
if (pos >= 0) { if (pos >= 0) {
PLATFORM_ASSERT(useCount == 0); PLATFORM_ASSERT(useCount == 0);
if (cache && (pos < length)) { if (!cache.empty() && (pos < static_cast<int>(cache.size()))) {
if (cache[pos]) { if (cache[pos]) {
if ((cache[pos]->lineNumber != lineNumber) || if ((cache[pos]->lineNumber != lineNumber) ||
(cache[pos]->maxLineLength < maxChars)) { (cache[pos]->maxLineLength < maxChars)) {
@ -322,12 +309,10 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
if (!cache[pos]) { if (!cache[pos]) {
cache[pos] = new LineLayout(maxChars); cache[pos] = new LineLayout(maxChars);
} }
if (cache[pos]) { cache[pos]->lineNumber = lineNumber;
cache[pos]->lineNumber = lineNumber; cache[pos]->inCache = true;
cache[pos]->inCache = true; ret = cache[pos];
ret = cache[pos]; useCount++;
useCount++;
}
} }
} }
@ -351,33 +336,18 @@ void LineLayoutCache::Dispose(LineLayout *ll) {
} }
void BreakFinder::Insert(int val) { void BreakFinder::Insert(int val) {
// Expand if needed
if (saeLen >= saeSize) {
saeSize *= 2;
int *selAndEdgeNew = new int[saeSize];
for (unsigned int j = 0; j<saeLen; j++) {
selAndEdgeNew[j] = selAndEdge[j];
}
delete []selAndEdge;
selAndEdge = selAndEdgeNew;
}
if (val >= nextBreak) { if (val >= nextBreak) {
for (unsigned int j = 0; j<saeLen; j++) { for (std::vector<int>::iterator it = selAndEdge.begin(); it != selAndEdge.end(); ++it) {
if (val == selAndEdge[j]) { if (val == *it) {
return; return;
} }
if (val < selAndEdge[j]) { if (val <*it) {
for (unsigned int k = saeLen; k>j; k--) { selAndEdge.insert(it, 1, val);
selAndEdge[k] = selAndEdge[k-1];
}
saeLen++;
selAndEdge[j] = val;
return; return;
} }
} }
// Not less than any so append // Not less than any so append
selAndEdge[saeLen++] = val; selAndEdge.push_back(val);
} }
} }
@ -399,17 +369,10 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL
lineEnd(lineEnd_), lineEnd(lineEnd_),
posLineStart(posLineStart_), posLineStart(posLineStart_),
nextBreak(lineStart_), nextBreak(lineStart_),
saeSize(0),
saeLen(0),
saeCurrentPos(0), saeCurrentPos(0),
saeNext(0), saeNext(0),
subBreak(-1), subBreak(-1),
pdoc(pdoc_) { pdoc(pdoc_) {
saeSize = 8;
selAndEdge = new int[saeSize];
for (unsigned int j=0; j < saeSize; j++) {
selAndEdge[j] = 0;
}
// Search for first visible break // Search for first visible break
// First find the first visible character // First find the first visible character
@ -447,11 +410,10 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL
Insert(pos); Insert(pos);
} }
} }
saeNext = (saeLen > 0) ? selAndEdge[0] : -1; saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1;
} }
BreakFinder::~BreakFinder() { BreakFinder::~BreakFinder() {
delete []selAndEdge;
} }
int BreakFinder::First() const { int BreakFinder::First() const {
@ -467,7 +429,7 @@ int BreakFinder::Next() {
IsControlCharacter(ll->chars[nextBreak]) || IsControlCharacter(ll->chars[nextBreak + 1])) { IsControlCharacter(ll->chars[nextBreak]) || IsControlCharacter(ll->chars[nextBreak + 1])) {
if (nextBreak == saeNext) { if (nextBreak == saeNext) {
saeCurrentPos++; saeCurrentPos++;
saeNext = (saeLen > saeCurrentPos) ? selAndEdge[saeCurrentPos] : -1; saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : -1;
} }
nextBreak++; nextBreak++;
if ((nextBreak - prev) < lengthStartSubdivision) { if ((nextBreak - prev) < lengthStartSubdivision) {
@ -509,7 +471,7 @@ void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
len = len_; len = len_;
clock = clock_; clock = clock_;
if (s_ && positions_) { if (s_ && positions_) {
positions = new XYPOSITION[len + (len + 1) / 2]; positions = new XYPOSITION[len + (len / 4) + 1];
for (unsigned int i=0; i<len; i++) { for (unsigned int i=0; i<len; i++) {
positions[i] = static_cast<XYPOSITION>(positions_[i]); positions[i] = static_cast<XYPOSITION>(positions_[i]);
} }
@ -566,20 +528,18 @@ void PositionCacheEntry::ResetClock() {
} }
PositionCache::PositionCache() { PositionCache::PositionCache() {
size = 0x400;
clock = 1; clock = 1;
pces = new PositionCacheEntry[size]; pces.resize(0x400);
allClear = true; allClear = true;
} }
PositionCache::~PositionCache() { PositionCache::~PositionCache() {
Clear(); Clear();
delete []pces;
} }
void PositionCache::Clear() { void PositionCache::Clear() {
if (!allClear) { if (!allClear) {
for (size_t i=0; i<size; i++) { for (size_t i=0; i<pces.size(); i++) {
pces[i].Clear(); pces[i].Clear();
} }
} }
@ -589,9 +549,7 @@ void PositionCache::Clear() {
void PositionCache::SetSize(size_t size_) { void PositionCache::SetSize(size_t size_) {
Clear(); Clear();
delete []pces; pces.resize(size_);
size = size_;
pces = new PositionCacheEntry[size];
} }
void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
@ -599,17 +557,17 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned
allClear = false; allClear = false;
int probe = -1; int probe = -1;
if ((size > 0) && (len < 30)) { if ((!pces.empty()) && (len < 30)) {
// Only store short strings in the cache so it doesn't churn with // Only store short strings in the cache so it doesn't churn with
// long comments with only a single comment. // long comments with only a single comment.
// Two way associative: try two probe positions. // Two way associative: try two probe positions.
int hashValue = PositionCacheEntry::Hash(styleNumber, s, len); int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
probe = static_cast<int>(hashValue % size); probe = static_cast<int>(hashValue % pces.size());
if (pces[probe].Retrieve(styleNumber, s, len, positions)) { if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
return; return;
} }
int probe2 = static_cast<int>((hashValue * 37) % size); int probe2 = static_cast<int>((hashValue * 37) % pces.size());
if (pces[probe2].Retrieve(styleNumber, s, len, positions)) { if (pces[probe2].Retrieve(styleNumber, s, len, positions)) {
return; return;
} }
@ -639,7 +597,7 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned
if (clock > 60000) { if (clock > 60000) {
// Since there are only 16 bits for the clock, wrap it round and // Since there are only 16 bits for the clock, wrap it round and
// reset all cache entries so none get stuck with a high clock. // reset all cache entries so none get stuck with a high clock.
for (size_t i=0; i<size; i++) { for (size_t i=0; i<pces.size(); i++) {
pces[i].ResetClock(); pces[i].ResetClock();
} }
clock = 2; clock = 2;

View File

@ -73,13 +73,11 @@ public:
*/ */
class LineLayoutCache { class LineLayoutCache {
int level; int level;
int length; std::vector<LineLayout *>cache;
int size;
LineLayout **cache;
bool allInvalidated; bool allInvalidated;
int styleClock; int styleClock;
int useCount; int useCount;
void Allocate(int length_); void Allocate(size_t length_);
void AllocateForLevel(int linesOnScreen, int linesInDoc); void AllocateForLevel(int linesOnScreen, int linesInDoc);
public: public:
LineLayoutCache(); LineLayoutCache();
@ -122,9 +120,7 @@ class BreakFinder {
int lineEnd; int lineEnd;
int posLineStart; int posLineStart;
int nextBreak; int nextBreak;
int *selAndEdge; std::vector<int> selAndEdge;
unsigned int saeSize;
unsigned int saeLen;
unsigned int saeCurrentPos; unsigned int saeCurrentPos;
int saeNext; int saeNext;
int subBreak; int subBreak;
@ -146,8 +142,7 @@ public:
}; };
class PositionCache { class PositionCache {
PositionCacheEntry *pces; std::vector<PositionCacheEntry> pces;
size_t size;
unsigned int clock; unsigned int clock;
bool allClear; bool allClear;
// Private so PositionCache objects can not be copied // Private so PositionCache objects can not be copied
@ -157,7 +152,7 @@ public:
~PositionCache(); ~PositionCache();
void Clear(); void Clear();
void SetSize(size_t size_); void SetSize(size_t size_);
size_t GetSize() const { return size; } size_t GetSize() const { return pces.size(); }
void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc);
}; };

View File

@ -43,10 +43,6 @@
* *
* int RESearch::Execute(characterIndexer &ci, int lp, int endp) * int RESearch::Execute(characterIndexer &ci, int lp, int endp)
* *
* RESearch::Substitute: substitute the matched portions in a new string.
*
* int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst)
*
* re_fail: failure routine for RESearch::Execute. (no longer used) * re_fail: failure routine for RESearch::Execute. (no longer used)
* *
* void re_fail(char *msg, char op) * void re_fail(char *msg, char op)
@ -206,6 +202,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string>
#include "CharClassify.h" #include "CharClassify.h"
#include "RESearch.h" #include "RESearch.h"
@ -269,36 +267,29 @@ void RESearch::Init() {
sta = NOP; /* status of lastpat */ sta = NOP; /* status of lastpat */
bol = 0; bol = 0;
for (int i = 0; i < MAXTAG; i++) for (int i = 0; i < MAXTAG; i++)
pat[i] = 0; pat[i].clear();
for (int j = 0; j < BITBLK; j++) for (int j = 0; j < BITBLK; j++)
bittab[j] = 0; bittab[j] = 0;
} }
void RESearch::Clear() { void RESearch::Clear() {
for (int i = 0; i < MAXTAG; i++) { for (int i = 0; i < MAXTAG; i++) {
delete []pat[i]; pat[i].clear();
pat[i] = 0;
bopat[i] = NOTFOUND; bopat[i] = NOTFOUND;
eopat[i] = NOTFOUND; eopat[i] = NOTFOUND;
} }
} }
bool RESearch::GrabMatches(CharacterIndexer &ci) { void RESearch::GrabMatches(CharacterIndexer &ci) {
bool success = true;
for (unsigned int i = 0; i < MAXTAG; i++) { for (unsigned int i = 0; i < MAXTAG; i++) {
if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) { if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
unsigned int len = eopat[i] - bopat[i]; unsigned int len = eopat[i] - bopat[i];
pat[i] = new char[len + 1]; pat[i] = std::string(len+1, '\0');
if (pat[i]) { for (unsigned int j = 0; j < len; j++)
for (unsigned int j = 0; j < len; j++) pat[i][j] = ci.CharAt(bopat[i] + j);
pat[i][j] = ci.CharAt(bopat[i] + j); pat[i][len] = '\0';
pat[i][len] = '\0';
} else {
success = false;
}
} }
} }
return success;
} }
void RESearch::ChSet(unsigned char c) { void RESearch::ChSet(unsigned char c) {
@ -967,52 +958,4 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) {
return lp; return lp;
} }
/*
* RESearch::Substitute:
* substitute the matched portions of the src in dst.
*
* & substitute the entire matched pattern.
*
* \digit substitute a subpattern, with the given tag number.
* Tags are numbered from 1 to 9. If the particular
* tagged subpattern does not exist, null is substituted.
*/
int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst) {
unsigned char c;
int pin;
int bp;
int ep;
if (!*src || !bopat[0])
return 0;
while ((c = *src++) != 0) {
switch (c) {
case '&':
pin = 0;
break;
case '\\':
c = *src++;
if (c >= '0' && c <= '9') {
pin = c - '0';
break;
}
default:
*dst++ = c;
continue;
}
if ((bp = bopat[pin]) != 0 && (ep = eopat[pin]) != 0) {
while (ci.CharAt(bp) && bp < ep)
*dst++ = ci.CharAt(bp++);
if (bp < ep)
return 0;
}
}
*dst = '\0';
return 1;
}

View File

@ -33,10 +33,9 @@ class RESearch {
public: public:
RESearch(CharClassify *charClassTable); RESearch(CharClassify *charClassTable);
~RESearch(); ~RESearch();
bool GrabMatches(CharacterIndexer &ci); void GrabMatches(CharacterIndexer &ci);
const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix); const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
int Execute(CharacterIndexer &ci, int lp, int endp); int Execute(CharacterIndexer &ci, int lp, int endp);
int Substitute(CharacterIndexer &ci, char *src, char *dst);
enum { MAXTAG=10 }; enum { MAXTAG=10 };
enum { MAXNFA=2048 }; enum { MAXNFA=2048 };
@ -44,7 +43,7 @@ public:
int bopat[MAXTAG]; int bopat[MAXTAG];
int eopat[MAXTAG]; int eopat[MAXTAG];
char *pat[MAXTAG]; std::string pat[MAXTAG];
private: private:
void Init(); void Init();

View File

@ -9,6 +9,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdexcept>
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
@ -113,7 +115,13 @@ int RunStyles::EndRun(int position) {
} }
bool RunStyles::FillRange(int &position, int value, int &fillLength) { bool RunStyles::FillRange(int &position, int value, int &fillLength) {
if (fillLength <= 0) {
return false;
}
int end = position + fillLength; int end = position + fillLength;
if (end > Length()) {
return false;
}
int runEnd = RunFromPosition(end); int runEnd = RunFromPosition(end);
if (styles->ValueAt(runEnd) == value) { if (styles->ValueAt(runEnd) == value) {
// End already has value so trim range. // End already has value so trim range.
@ -249,3 +257,31 @@ int RunStyles::Find(int value, int start) const {
} }
return -1; return -1;
} }
void RunStyles::Check() {
if (Length() < 0) {
throw std::runtime_error("RunStyles: Length can not be negative.");
}
if (starts->Partitions() < 1) {
throw std::runtime_error("RunStyles: Must always have 1 or more partitions.");
}
if (starts->Partitions() != styles->Length()-1) {
throw std::runtime_error("RunStyles: Partitions and styles different lengths.");
}
int start=0;
while (start < Length()) {
int end = EndRun(start);
if (start >= end) {
throw std::runtime_error("RunStyles: Partition is 0 length.");
}
start = end;
}
if (styles->ValueAt(styles->Length()-1) != 0) {
throw std::runtime_error("RunStyles: Unused style at end changed.");
}
for (int j=1; j<styles->Length()-1; j++) {
if (styles->ValueAt(j) == styles->ValueAt(j-1)) {
throw std::runtime_error("RunStyles: Style of a partition same as previous.");
}
}
}

View File

@ -43,6 +43,8 @@ public:
bool AllSame() const; bool AllSame() const;
bool AllSameAs(int value) const; bool AllSameAs(int value) const;
int Find(int value, int start) const; int Find(int value, int start) const;
void Check();
}; };
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE

View File

@ -20,14 +20,18 @@ using namespace Scintilla;
#endif #endif
void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) { void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
if (position == startChange) {
virtualSpace = 0;
}
if (insertion) { if (insertion) {
if (position > startChange) { if (position == startChange) {
int virtualLengthRemove = std::min(length, virtualSpace);
virtualSpace -= virtualLengthRemove;
position += virtualLengthRemove;
} else if (position > startChange) {
position += length; position += length;
} }
} else { } else {
if (position == startChange) {
virtualSpace = 0;
}
if (position > startChange) { if (position > startChange) {
int endDeletion = startChange + length; int endDeletion = startChange + length;
if (position > endDeletion) { if (position > endDeletion) {

View File

@ -174,8 +174,7 @@ public:
} }
RoomFor(insertLength); RoomFor(insertLength);
GapTo(position); GapTo(position);
for (int i = 0; i < insertLength; i++) std::fill(&body[part1Length], &body[part1Length + insertLength], v);
body[part1Length + i] = v;
lengthBody += insertLength; lengthBody += insertLength;
part1Length += insertLength; part1Length += insertLength;
gapLength -= insertLength; gapLength -= insertLength;

View File

@ -21,7 +21,7 @@ FontAlias::FontAlias() {
FontAlias::~FontAlias() { FontAlias::~FontAlias() {
SetID(0); SetID(0);
// ~Font will not release the actual font resource sine it is now 0 // ~Font will not release the actual font resource since it is now 0
} }
void FontAlias::MakeAlias(Font &fontOrigin) { void FontAlias::MakeAlias(Font &fontOrigin) {
@ -32,12 +32,29 @@ void FontAlias::ClearFont() {
SetID(0); SetID(0);
} }
bool FontSpecification::EqualTo(const FontSpecification &other) const { bool FontSpecification::operator==(const FontSpecification &other) const {
return weight == other.weight && return fontName == other.fontName &&
weight == other.weight &&
italic == other.italic && italic == other.italic &&
size == other.size && size == other.size &&
characterSet == other.characterSet && characterSet == other.characterSet &&
fontName == other.fontName; extraFontFlag == other.extraFontFlag;
}
bool FontSpecification::operator<(const FontSpecification &other) const {
if (fontName != other.fontName)
return fontName < other.fontName;
if (weight != other.weight)
return weight < other.weight;
if (italic != other.italic)
return italic == false;
if (size != other.size)
return size < other.size;
if (characterSet != other.characterSet)
return characterSet < other.characterSet;
if (extraFontFlag != other.extraFontFlag)
return extraFontFlag < other.extraFontFlag;
return false;
} }
FontMeasurements::FontMeasurements() { FontMeasurements::FontMeasurements() {
@ -68,6 +85,7 @@ Style::Style(const Style &source) : FontSpecification(), FontMeasurements() {
weight = source.weight; weight = source.weight;
italic = source.italic; italic = source.italic;
size = source.size; size = source.size;
fontName = source.fontName;
eolFilled = source.eolFilled; eolFilled = source.eolFilled;
underline = source.underline; underline = source.underline;
caseForce = source.caseForce; caseForce = source.caseForce;
@ -91,6 +109,7 @@ Style &Style::operator=(const Style &source) {
weight = source.weight; weight = source.weight;
italic = source.italic; italic = source.italic;
size = source.size; size = source.size;
fontName = source.fontName;
eolFilled = source.eolFilled; eolFilled = source.eolFilled;
underline = source.underline; underline = source.underline;
caseForce = source.caseForce; caseForce = source.caseForce;

View File

@ -27,7 +27,8 @@ struct FontSpecification {
characterSet(0), characterSet(0),
extraFontFlag(0) { extraFontFlag(0) {
} }
bool EqualTo(const FontSpecification &other) const; bool operator==(const FontSpecification &other) const;
bool operator<(const FontSpecification &other) const;
}; };
// Just like Font but only has a copy of the FontID so should not delete it // Just like Font but only has a copy of the FontID so should not delete it
@ -77,7 +78,7 @@ public:
const char *fontName_, int characterSet_, const char *fontName_, int characterSet_,
int weight_, bool italic_, bool eolFilled_, int weight_, bool italic_, bool eolFilled_,
bool underline_, ecaseForced caseForce_, bool underline_, ecaseForced caseForce_,
bool visible_, bool changeable_, bool hotspot_); bool visible_, bool changeable_, bool hotspot_);
void ClearTo(const Style &source); void ClearTo(const Style &source);
void Copy(Font &font_, const FontMeasurements &fm_); void Copy(Font &font_, const FontMeasurements &fm_);
bool IsProtected() const { return !(changeable && visible);} bool IsProtected() const { return !(changeable && visible);}

View File

@ -33,100 +33,52 @@ MarginStyle::MarginStyle() :
// A list of the fontnames - avoids wasting space in each style // A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() { FontNames::FontNames() {
size = 8;
names = new char *[size];
max = 0;
} }
FontNames::~FontNames() { FontNames::~FontNames() {
Clear(); Clear();
delete []names;
names = 0;
} }
void FontNames::Clear() { void FontNames::Clear() {
for (int i=0; i<max; i++) { names.clear();
delete []names[i];
}
max = 0;
} }
const char *FontNames::Save(const char *name) { const char *FontNames::Save(const char *name) {
if (!name) if (!name)
return 0; return 0;
for (int i=0; i<max; i++) {
if (strcmp(names[i], name) == 0) { for (std::vector<char *>::const_iterator it=names.begin(); it != names.end(); ++it) {
return names[i]; if (strcmp(*it, name) == 0) {
return *it;
} }
} }
if (max >= size) { char *nameSave = new char[strlen(name) + 1];
// Grow array strcpy(nameSave, name);
int sizeNew = size * 2; names.push_back(nameSave);
char **namesNew = new char *[sizeNew]; return nameSave;
for (int j=0; j<max; j++) {
namesNew[j] = names[j];
}
delete []names;
names = namesNew;
size = sizeNew;
}
names[max] = new char[strlen(name) + 1];
strcpy(names[max], name);
max++;
return names[max-1];
} }
FontRealised::FontRealised(const FontSpecification &fs) { FontRealised::FontRealised() {
frNext = NULL;
(FontSpecification &)(*this) = fs;
} }
FontRealised::~FontRealised() { FontRealised::~FontRealised() {
font.Release(); font.Release();
delete frNext;
frNext = 0;
} }
void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) { void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) {
PLATFORM_ASSERT(fontName); PLATFORM_ASSERT(fs.fontName);
sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER; sizeZoomed = fs.size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
float deviceHeight = surface.DeviceHeightFont(sizeZoomed); float deviceHeight = surface.DeviceHeightFont(sizeZoomed);
FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet); FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet);
font.Create(fp); font.Create(fp);
ascent = surface.Ascent(font); ascent = surface.Ascent(font);
descent = surface.Descent(font); descent = surface.Descent(font);
aveCharWidth = surface.AverageCharWidth(font); aveCharWidth = surface.AverageCharWidth(font);
spaceWidth = surface.WidthChar(font, ' '); spaceWidth = surface.WidthChar(font, ' ');
if (frNext) {
frNext->Realise(surface, zoomLevel, technology);
}
}
FontRealised *FontRealised::Find(const FontSpecification &fs) {
if (!fs.fontName)
return this;
FontRealised *fr = this;
while (fr) {
if (fr->EqualTo(fs))
return fr;
fr = fr->frNext;
}
return 0;
}
void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) {
FontRealised *fr = this;
while (fr) {
if (maxAscent < fr->ascent)
maxAscent = fr->ascent;
if (maxDescent < fr->descent)
maxDescent = fr->descent;
fr = fr->frNext;
}
} }
ViewStyle::ViewStyle() { ViewStyle::ViewStyle() {
@ -134,9 +86,8 @@ ViewStyle::ViewStyle() {
} }
ViewStyle::ViewStyle(const ViewStyle &source) { ViewStyle::ViewStyle(const ViewStyle &source) {
frFirst = NULL; Init(source.styles.size());
Init(source.stylesSize); for (unsigned int sty=0; sty<source.styles.size(); sty++) {
for (unsigned int sty=0; sty<source.stylesSize; sty++) {
styles[sty] = source.styles[sty]; styles[sty] = source.styles[sty];
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle // Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName); styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
@ -218,16 +169,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
} }
ViewStyle::~ViewStyle() { ViewStyle::~ViewStyle() {
delete []styles; styles.clear();
styles = NULL; for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
delete frFirst; delete it->second;
frFirst = NULL; }
fonts.clear();
} }
void ViewStyle::Init(size_t stylesSize_) { void ViewStyle::Init(size_t stylesSize_) {
frFirst = NULL;
stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_); AllocStyles(stylesSize_);
nextExtendedStyle = 256; nextExtendedStyle = 256;
fontNames.Clear(); fontNames.Clear();
@ -334,52 +283,42 @@ void ViewStyle::Init(size_t stylesSize_) {
braceBadLightIndicator = 0; braceBadLightIndicator = 0;
} }
void ViewStyle::CreateFont(const FontSpecification &fs) {
if (fs.fontName) {
for (FontRealised *cur=frFirst; cur; cur=cur->frNext) {
if (cur->EqualTo(fs))
return;
if (!cur->frNext) {
cur->frNext = new FontRealised(fs);
return;
}
}
frFirst = new FontRealised(fs);
}
}
void ViewStyle::Refresh(Surface &surface) { void ViewStyle::Refresh(Surface &surface) {
delete frFirst; for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
frFirst = NULL; delete it->second;
}
fonts.clear();
selbar = Platform::Chrome(); selbar = Platform::Chrome();
selbarlight = Platform::ChromeHighlight(); selbarlight = Platform::ChromeHighlight();
for (unsigned int i=0; i<stylesSize; i++) { for (unsigned int i=0; i<styles.size(); i++) {
styles[i].extraFontFlag = extraFontFlag; styles[i].extraFontFlag = extraFontFlag;
} }
CreateFont(styles[STYLE_DEFAULT]); CreateFont(styles[STYLE_DEFAULT]);
for (unsigned int j=0; j<stylesSize; j++) { for (unsigned int j=0; j<styles.size(); j++) {
CreateFont(styles[j]); CreateFont(styles[j]);
} }
assert(frFirst); for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
frFirst->Realise(surface, zoomLevel, technology); it->second->Realise(surface, zoomLevel, technology, it->first);
}
for (unsigned int k=0; k<stylesSize; k++) { for (unsigned int k=0; k<styles.size(); k++) {
FontRealised *fr = frFirst->Find(styles[k]); FontRealised *fr = Find(styles[k]);
styles[k].Copy(fr->font, *fr); styles[k].Copy(fr->font, *fr);
} }
maxAscent = 1; maxAscent = 1;
maxDescent = 1; maxDescent = 1;
frFirst->FindMaxAscentDescent(maxAscent, maxDescent); FindMaxAscentDescent(maxAscent, maxDescent);
maxAscent += extraAscent; maxAscent += extraAscent;
maxDescent += extraDescent; maxDescent += extraDescent;
lineHeight = maxAscent + maxDescent; lineHeight = maxAscent + maxDescent;
someStylesProtected = false; someStylesProtected = false;
someStylesForceCase = false; someStylesForceCase = false;
for (unsigned int l=0; l<stylesSize; l++) { for (unsigned int l=0; l<styles.size(); l++) {
if (styles[l].IsProtected()) { if (styles[l].IsProtected()) {
someStylesProtected = true; someStylesProtected = true;
} }
@ -401,25 +340,6 @@ void ViewStyle::Refresh(Surface &surface) {
textStart = marginInside ? fixedColumnWidth : leftMarginWidth; textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
} }
void ViewStyle::AllocStyles(size_t sizeNew) {
Style *stylesNew = new Style[sizeNew];
size_t i=0;
for (; i<stylesSize; i++) {
stylesNew[i] = styles[i];
stylesNew[i].fontName = styles[i].fontName;
}
if (stylesSize > STYLE_DEFAULT) {
for (; i<sizeNew; i++) {
if (i != STYLE_DEFAULT) {
stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
}
}
}
delete []styles;
styles = stylesNew;
stylesSize = sizeNew;
}
void ViewStyle::ReleaseAllExtendedStyles() { void ViewStyle::ReleaseAllExtendedStyles() {
nextExtendedStyle = 256; nextExtendedStyle = 256;
} }
@ -431,11 +351,8 @@ int ViewStyle::AllocateExtendedStyles(int numberStyles) {
} }
void ViewStyle::EnsureStyle(size_t index) { void ViewStyle::EnsureStyle(size_t index) {
if (index >= stylesSize) { if (index >= styles.size()) {
size_t sizeNew = stylesSize * 2; AllocStyles(index+1);
while (sizeNew <= index)
sizeNew *= 2;
AllocStyles(sizeNew);
} }
} }
@ -449,7 +366,7 @@ void ViewStyle::ResetDefaultStyle() {
void ViewStyle::ClearStyles() { void ViewStyle::ClearStyles() {
// Reset all styles to be like the default style // Reset all styles to be like the default style
for (unsigned int i=0; i<stylesSize; i++) { for (unsigned int i=0; i<styles.size(); i++) {
if (i != STYLE_DEFAULT) { if (i != STYLE_DEFAULT) {
styles[i].ClearTo(styles[STYLE_DEFAULT]); styles[i].ClearTo(styles[STYLE_DEFAULT]);
} }
@ -470,7 +387,7 @@ bool ViewStyle::ProtectionActive() const {
} }
bool ViewStyle::ValidStyle(size_t styleIndex) const { bool ViewStyle::ValidStyle(size_t styleIndex) const {
return styleIndex < stylesSize; return styleIndex < styles.size();
} }
void ViewStyle::CalcLargestMarkerHeight() { void ViewStyle::CalcLargestMarkerHeight() {
@ -488,3 +405,44 @@ void ViewStyle::CalcLargestMarkerHeight() {
} }
} }
} }
void ViewStyle::AllocStyles(size_t sizeNew) {
size_t i=styles.size();
styles.resize(sizeNew);
if (styles.size() > STYLE_DEFAULT) {
for (; i<sizeNew; i++) {
if (i != STYLE_DEFAULT) {
styles[i].ClearTo(styles[STYLE_DEFAULT]);
}
}
}
}
void ViewStyle::CreateFont(const FontSpecification &fs) {
if (fs.fontName) {
FontMap::iterator it = fonts.find(fs);
if (it == fonts.end()) {
fonts[fs] = new FontRealised();
}
}
}
FontRealised *ViewStyle::Find(const FontSpecification &fs) {
if (!fs.fontName) // Invalid specification so return arbitrary object
return fonts.begin()->second;
FontMap::iterator it = fonts.find(fs);
if (it != fonts.end()) {
// Should always reach here since map was just set for all styles
return it->second;
}
return 0;
}
void ViewStyle::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) {
for (FontMap::const_iterator it = fonts.begin(); it != fonts.end(); ++it) {
if (maxAscent < it->second->ascent)
maxAscent = it->second->ascent;
if (maxDescent < it->second->descent)
maxDescent = it->second->descent;
}
}

View File

@ -28,9 +28,7 @@ public:
*/ */
class FontNames { class FontNames {
private: private:
char **names; std::vector<char *> names;
int size;
int max;
// Private so FontNames objects can not be copied // Private so FontNames objects can not be copied
FontNames(const FontNames &); FontNames(const FontNames &);
@ -41,32 +39,30 @@ public:
const char *Save(const char *name); const char *Save(const char *name);
}; };
class FontRealised : public FontSpecification, public FontMeasurements { class FontRealised : public FontMeasurements {
// Private so FontRealised objects can not be copied // Private so FontRealised objects can not be copied
FontRealised(const FontRealised &); FontRealised(const FontRealised &);
FontRealised &operator=(const FontRealised &); FontRealised &operator=(const FontRealised &);
public: public:
Font font; Font font;
FontRealised *frNext; FontRealised();
FontRealised(const FontSpecification &fs);
virtual ~FontRealised(); virtual ~FontRealised();
void Realise(Surface &surface, int zoomLevel, int technology); void Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs);
FontRealised *Find(const FontSpecification &fs);
void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
}; };
enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth}; enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2}; enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
typedef std::map<FontSpecification, FontRealised *> FontMap;
/** /**
*/ */
class ViewStyle { class ViewStyle {
public:
FontNames fontNames; FontNames fontNames;
FontRealised *frFirst; FontMap fonts;
size_t stylesSize; public:
Style *styles; std::vector<Style> styles;
size_t nextExtendedStyle; size_t nextExtendedStyle;
LineMarker markers[MARKER_MAX + 1]; LineMarker markers[MARKER_MAX + 1];
int largestMarkerHeight; int largestMarkerHeight;
@ -143,9 +139,7 @@ public:
ViewStyle(const ViewStyle &source); ViewStyle(const ViewStyle &source);
~ViewStyle(); ~ViewStyle();
void Init(size_t stylesSize_=64); void Init(size_t stylesSize_=64);
void CreateFont(const FontSpecification &fs);
void Refresh(Surface &surface); void Refresh(Surface &surface);
void AllocStyles(size_t sizeNew);
void ReleaseAllExtendedStyles(); void ReleaseAllExtendedStyles();
int AllocateExtendedStyles(int numberStyles); int AllocateExtendedStyles(int numberStyles);
void EnsureStyle(size_t index); void EnsureStyle(size_t index);
@ -155,6 +149,13 @@ public:
bool ProtectionActive() const; bool ProtectionActive() const;
bool ValidStyle(size_t styleIndex) const; bool ValidStyle(size_t styleIndex) const;
void CalcLargestMarkerHeight(); void CalcLargestMarkerHeight();
private:
void AllocStyles(size_t sizeNew);
void CreateFont(const FontSpecification &fs);
FontRealised *Find(const FontSpecification &fs);
void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
// Private so can only be copied through copy constructor which ensures font names initialised correctly
ViewStyle &operator=(const ViewStyle &);
}; };
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE

View File

@ -41,12 +41,8 @@ static size_t MeasureLength(const char *s) {
return i; return i;
} }
ColourDesired XPM::ColourDesiredFromCode(int ch) const {
return *colourCodeTable[ch];
}
ColourDesired XPM::ColourFromCode(int ch) const { ColourDesired XPM::ColourFromCode(int ch) const {
return *colourCodeTable[ch]; return colourCodeTable[ch];
} }
void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) { void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) {
@ -56,13 +52,11 @@ void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) {
} }
} }
XPM::XPM(const char *textForm) : XPM::XPM(const char *textForm) {
data(0), codes(0), colours(0), lines(0) {
Init(textForm); Init(textForm);
} }
XPM::XPM(const char *const *linesForm) : XPM::XPM(const char *const *linesForm) {
data(0), codes(0), colours(0), lines(0) {
Init(linesForm); Init(linesForm);
} }
@ -76,10 +70,9 @@ void XPM::Init(const char *textForm) {
// if memcmp implemented strangely. Must be 4 bytes at least at destination. // if memcmp implemented strangely. Must be 4 bytes at least at destination.
if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) { if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
// Build the lines form out of the text form // Build the lines form out of the text form
const char **linesForm = LinesFormFromTextForm(textForm); std::vector<const char *> linesForm = LinesFormFromTextForm(textForm);
if (linesForm != 0) { if (!linesForm.empty()) {
Init(linesForm); Init(&linesForm[0]);
delete []linesForm;
} }
} else { } else {
// It is really in line form // It is really in line form
@ -92,18 +85,17 @@ void XPM::Init(const char *const *linesForm) {
height = 1; height = 1;
width = 1; width = 1;
nColours = 1; nColours = 1;
data = NULL; pixels.clear();
codeTransparent = ' '; codeTransparent = ' ';
codes = NULL;
colours = NULL;
lines = NULL;
if (!linesForm) if (!linesForm)
return; return;
std::fill(colourCodeTable, colourCodeTable+256, 0);
const char *line0 = linesForm[0]; const char *line0 = linesForm[0];
width = atoi(line0); width = atoi(line0);
line0 = NextField(line0); line0 = NextField(line0);
height = atoi(line0); height = atoi(line0);
pixels.resize(width*height);
line0 = NextField(line0); line0 = NextField(line0);
nColours = atoi(line0); nColours = atoi(line0);
line0 = NextField(line0); line0 = NextField(line0);
@ -111,56 +103,33 @@ void XPM::Init(const char *const *linesForm) {
// Only one char per pixel is supported // Only one char per pixel is supported
return; return;
} }
codes = new char[nColours];
colours = new ColourDesired[nColours];
int strings = 1+height+nColours;
lines = new char *[strings];
size_t allocation = 0;
for (int i=0; i<strings; i++) {
allocation += MeasureLength(linesForm[i]) + 1;
}
data = new char[allocation];
char *nextBit = data;
for (int j=0; j<strings; j++) {
lines[j] = nextBit;
size_t len = MeasureLength(linesForm[j]);
memcpy(nextBit, linesForm[j], len);
nextBit += len;
*nextBit++ = '\0';
}
for (int code=0; code<256; code++) {
colourCodeTable[code] = 0;
}
for (int c=0; c<nColours; c++) { for (int c=0; c<nColours; c++) {
const char *colourDef = linesForm[c+1]; const char *colourDef = linesForm[c+1];
codes[c] = colourDef[0]; int code = static_cast<unsigned char>(colourDef[0]);
colourDef += 4; colourDef += 4;
ColourDesired colour(0xff, 0xff, 0xff);
if (*colourDef == '#') { if (*colourDef == '#') {
colours[c].Set(colourDef); colour.Set(colourDef);
} else { } else {
colours[c] = ColourDesired(0xff, 0xff, 0xff); codeTransparent = code;
codeTransparent = codes[c];
} }
colourCodeTable[static_cast<unsigned char>(codes[c])] = &(colours[c]); colourCodeTable[code] = colour;
}
for (int y=0; y<height; y++) {
const char *lform = linesForm[y+nColours+1];
size_t len = MeasureLength(lform);
for (size_t x = 0; x<len; x++)
pixels[y * width + x] = static_cast<unsigned char>(lform[x]);
} }
} }
void XPM::Clear() { void XPM::Clear() {
delete []data;
data = 0;
delete []codes;
codes = 0;
delete []colours;
colours = 0;
delete []lines;
lines = 0;
} }
void XPM::Draw(Surface *surface, PRectangle &rc) { void XPM::Draw(Surface *surface, PRectangle &rc) {
if (!data || !codes || !colours || !lines) { if (pixels.empty()) {
return; return;
} }
// Centre the pixmap // Centre the pixmap
@ -170,7 +139,7 @@ void XPM::Draw(Surface *surface, PRectangle &rc) {
int prevCode = 0; int prevCode = 0;
int xStartRun = 0; int xStartRun = 0;
for (int x=0; x<width; x++) { for (int x=0; x<width; x++) {
int code = lines[y+nColours+1][x]; int code = pixels[y * width + x];
if (code != prevCode) { if (code != prevCode) {
FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x); FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x);
xStartRun = x; xStartRun = x;
@ -182,23 +151,23 @@ void XPM::Draw(Surface *surface, PRectangle &rc) {
} }
void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const { void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const {
if (!data || !codes || !colours || !lines || (x<0) || (x >= width) || (y<0) || (y >= height)) { if (pixels.empty() || (x<0) || (x >= width) || (y<0) || (y >= height)) {
colour = 0; colour = 0;
transparent = true; transparent = true;
return; return;
} }
int code = lines[y+nColours+1][x]; int code = pixels[y * width + x];
transparent = code == codeTransparent; transparent = code == codeTransparent;
if (transparent) { if (transparent) {
colour = 0; colour = 0;
} else { } else {
colour = ColourDesiredFromCode(code).AsLong(); colour = ColourFromCode(code).AsLong();
} }
} }
const char **XPM::LinesFormFromTextForm(const char *textForm) { std::vector<const char *> XPM::LinesFormFromTextForm(const char *textForm) {
// Build the lines form out of the text form // Build the lines form out of the text form
const char **linesForm = 0; std::vector<const char *> linesForm;
int countQuotes = 0; int countQuotes = 0;
int strings=1; int strings=1;
int j=0; int j=0;
@ -214,111 +183,23 @@ const char **XPM::LinesFormFromTextForm(const char *textForm) {
line0 = NextField(line0); line0 = NextField(line0);
// Add 1 line for each colour // Add 1 line for each colour
strings += atoi(line0); strings += atoi(line0);
linesForm = new const char *[strings];
if (linesForm == 0) {
break; // Memory error!
}
} }
if (countQuotes / 2 >= strings) { if (countQuotes / 2 >= strings) {
break; // Bad height or number of colors! break; // Bad height or number of colors!
} }
if ((countQuotes & 1) == 0) { if ((countQuotes & 1) == 0) {
linesForm[countQuotes / 2] = textForm + j + 1; linesForm.push_back(textForm + j + 1);
} }
countQuotes++; countQuotes++;
} }
} }
if (textForm[j] == '\0' || countQuotes / 2 > strings) { if (textForm[j] == '\0' || countQuotes / 2 > strings) {
// Malformed XPM! Height + number of colors too high or too low // Malformed XPM! Height + number of colors too high or too low
delete []linesForm; linesForm.clear();
linesForm = 0;
} }
return linesForm; return linesForm;
} }
// In future, may want to minimize search time by sorting and using a binary search.
XPMSet::XPMSet() : set(0), len(0), maximum(0), height(-1), width(-1) {
}
XPMSet::~XPMSet() {
Clear();
}
void XPMSet::Clear() {
for (int i = 0; i < len; i++) {
delete set[i];
}
delete []set;
set = 0;
len = 0;
maximum = 0;
height = -1;
width = -1;
}
void XPMSet::Add(int ident, const char *textForm) {
// Invalidate cached dimensions
height = -1;
width = -1;
// Replace if this id already present
for (int i = 0; i < len; i++) {
if (set[i]->GetId() == ident) {
set[i]->Init(textForm);
return;
}
}
// Not present, so add to end
XPM *pxpm = new XPM(textForm);
if (pxpm) {
pxpm->SetId(ident);
if (len == maximum) {
maximum += 64;
XPM **setNew = new XPM *[maximum];
for (int i = 0; i < len; i++) {
setNew[i] = set[i];
}
delete []set;
set = setNew;
}
set[len] = pxpm;
len++;
}
}
XPM *XPMSet::Get(int ident) {
for (int i = 0; i < len; i++) {
if (set[i]->GetId() == ident) {
return set[i];
}
}
return 0;
}
int XPMSet::GetHeight() {
if (height < 0) {
for (int i = 0; i < len; i++) {
if (height < set[i]->GetHeight()) {
height = set[i]->GetHeight();
}
}
}
return (height > 0) ? height : 0;
}
int XPMSet::GetWidth() {
if (width < 0) {
for (int i = 0; i < len; i++) {
if (width < set[i]->GetWidth()) {
width = set[i]->GetWidth();
}
}
}
return (width > 0) ? width : 0;
}
RGBAImage::RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_) : RGBAImage::RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_) :
height(height_), width(width_), scale(scale_) { height(height_), width(width_), scale(scale_) {
if (pixels_) { if (pixels_) {

View File

@ -1,6 +1,6 @@
// Scintilla source code edit control // Scintilla source code edit control
/** @file XPM.h /** @file XPM.h
** Define a class that holds data in the X Pixmap (XPM) format. ** Define a classes to hold image data in the X Pixmap (XPM) and RGBA formats.
**/ **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
@ -16,19 +16,14 @@ namespace Scintilla {
* Hold a pixmap in XPM format. * Hold a pixmap in XPM format.
*/ */
class XPM { class XPM {
int pid; // Assigned by container
int height; int height;
int width; int width;
int nColours; int nColours;
char *data; std::vector<unsigned char> pixels;
ColourDesired colourCodeTable[256];
char codeTransparent; char codeTransparent;
char *codes;
ColourDesired *colours;
ColourDesired ColourDesiredFromCode(int ch) const;
ColourDesired ColourFromCode(int ch) const; ColourDesired ColourFromCode(int ch) const;
void FillRun(Surface *surface, int code, int startX, int y, int x); void FillRun(Surface *surface, int code, int startX, int y, int x);
char **lines;
ColourDesired *colourCodeTable[256];
public: public:
XPM(const char *textForm); XPM(const char *textForm);
XPM(const char *const *linesForm); XPM(const char *const *linesForm);
@ -38,41 +33,15 @@ public:
void Clear(); void Clear();
/// Decompose image into runs and use FillRectangle for each run /// Decompose image into runs and use FillRectangle for each run
void Draw(Surface *surface, PRectangle &rc); void Draw(Surface *surface, PRectangle &rc);
char **InLinesForm() { return lines; }
void SetId(int pid_) { pid = pid_; }
int GetId() const { return pid; }
int GetHeight() const { return height; } int GetHeight() const { return height; }
int GetWidth() const { return width; } int GetWidth() const { return width; }
void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const; void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const;
static const char **LinesFormFromTextForm(const char *textForm); private:
static std::vector<const char *>LinesFormFromTextForm(const char *textForm);
}; };
/** /**
* A collection of pixmaps indexed by integer id. * A translucent image stored as a sequence of RGBA bytes.
*/
class XPMSet {
XPM **set; ///< The stored XPMs.
int len; ///< Current number of XPMs.
int maximum; ///< Current maximum number of XPMs, increased by steps if reached.
int height; ///< Memorize largest height of the set.
int width; ///< Memorize largest width of the set.
public:
XPMSet();
~XPMSet();
/// Remove all XPMs.
void Clear();
/// Add a XPM.
void Add(int ident, const char *textForm);
/// Get XPM by id.
XPM *Get(int ident);
/// Give the largest height of the set.
int GetHeight();
/// Give the largest width of the set.
int GetWidth();
};
/**
* An translucent image stoed as a sequence of RGBA bytes.
*/ */
class RGBAImage { class RGBAImage {
// Private so RGBAImage objects can not be copied // Private so RGBAImage objects can not be copied

View File

@ -1 +1 @@
331 332