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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@
#include <string>
#include <vector>
#include <algorithm>
#include "Platform.h"
@ -102,8 +103,6 @@ Document::Document() {
useTabs = true;
tabIndents = true;
backspaceUnindents = false;
watchers = 0;
lenWatchers = 0;
matchesValid = false;
regex = 0;
@ -122,16 +121,13 @@ Document::Document() {
}
Document::~Document() {
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
it->watcher->NotifyDeleted(this, it->userData);
}
delete []watchers;
for (int j=0; j<ldSize; j++) {
delete perLineData[j];
perLineData[j] = 0;
}
watchers = 0;
lenWatchers = 0;
delete regex;
regex = 0;
delete pli;
@ -309,9 +305,9 @@ int SCI_METHOD Document::LineEnd(int line) const {
}
void SCI_METHOD Document::SetErrorStatus(int status) {
// Tell the watchers the lexer has changed.
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status);
// Tell the watchers an error has occurred.
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
it->watcher->NotifyErrorOccurred(this, it->userData, status);
}
}
@ -892,7 +888,7 @@ void * SCI_METHOD Document::ConvertToDocument() {
int Document::Undo() {
int newPos = -1;
CheckReadOnly();
if (enteredModification == 0) {
if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++;
if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint();
@ -977,7 +973,7 @@ int Document::Undo() {
int Document::Redo() {
int newPos = -1;
CheckReadOnly();
if (enteredModification == 0) {
if ((enteredModification == 0) && (cb.IsCollectingUndo())) {
enteredModification++;
if (!cb.IsReadOnly()) {
bool startSavePoint = cb.IsSavePoint();
@ -1050,11 +1046,6 @@ bool Document::InsertCString(int position, const char *s) {
return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0));
}
void Document::ChangeChar(int pos, char ch) {
DeleteChars(pos, 1);
InsertChar(pos, ch);
}
void Document::DelChar(int pos) {
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.
// Stop at len or when a NUL is found.
// Caller must delete the returned pointer.
char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted) {
char *dest = new char[2 * len + 1];
const char *sptr = s;
char *dptr = dest;
for (size_t i = 0; (i < len) && (*sptr != '\0'); i++) {
if (*sptr == '\n' || *sptr == '\r') {
std::string Document::TransformLineEnds(const char *s, size_t len, int eolModeWanted) {
std::string dest;
for (size_t i = 0; (i < len) && (s[i]); i++) {
if (s[i] == '\n' || s[i] == '\r') {
if (eolModeWanted == SC_EOL_CR) {
*dptr++ = '\r';
dest.push_back('\r');
} else if (eolModeWanted == SC_EOL_LF) {
*dptr++ = '\n';
dest.push_back('\n');
} else { // eolModeWanted == SC_EOL_CRLF
*dptr++ = '\r';
*dptr++ = '\n';
dest.push_back('\r');
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++;
sptr++;
}
sptr++;
} else {
*dptr++ = *sptr++;
dest.push_back(s[i]);
}
}
*dptr++ = '\0';
*pLenOut = (dptr - dest) - 1;
return dest;
}
@ -1667,25 +1651,6 @@ int Document::LinesTotal() const {
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) {
charClass.SetDefaultCharClasses(includeWordClass);
}
@ -1763,8 +1728,9 @@ void Document::EnsureStyledTo(int pos) {
pli->Colourise(endStyledTo, pos);
} else {
// Ask the watchers to style, and stop as soon as one responds.
for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) {
watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin();
(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() {
// Tell the watchers the lexer has changed.
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyLexerChanged(this, watchers[i].userData);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
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));
}
int Document::MarginLength(int line) const {
return static_cast<LineAnnotation *>(perLineData[ldMargin])->Length(line);
}
void Document::MarginClearAll() {
int maxEditorLine = LinesTotal();
for (int l=0; l<maxEditorLine; l++)
@ -1833,10 +1795,6 @@ void Document::MarginClearAll() {
static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll();
}
bool Document::AnnotationAny() const {
return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->AnySet();
}
StyledText Document::AnnotationStyledText(int line) {
LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]);
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 {
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) {
for (int i = 0; i < lenWatchers; i++) {
if ((watchers[i].watcher == watcher) &&
(watchers[i].userData == userData))
WatcherWithUserData wwud(watcher, userData);
std::vector<WatcherWithUserData>::iterator it =
std::find(watchers.begin(), watchers.end(), wwud);
if (it != watchers.end())
return false;
}
WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers + 1];
for (int j = 0; j < lenWatchers; j++)
pwNew[j] = watchers[j];
pwNew[lenWatchers].watcher = watcher;
pwNew[lenWatchers].userData = userData;
delete []watchers;
watchers = pwNew;
lenWatchers++;
watchers.push_back(wwud);
return true;
}
bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) {
for (int i = 0; i < lenWatchers; i++) {
if ((watchers[i].watcher == watcher) &&
(watchers[i].userData == userData)) {
if (lenWatchers == 1) {
delete []watchers;
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--;
}
std::vector<WatcherWithUserData>::iterator it =
std::find(watchers.begin(), watchers.end(), WatcherWithUserData(watcher, userData));
if (it != watchers.end()) {
watchers.erase(it);
return true;
}
}
return false;
}
void Document::NotifyModifyAttempt() {
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyModifyAttempt(this, watchers[i].userData);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
it->watcher->NotifyModifyAttempt(this, it->userData);
}
}
void Document::NotifySavePoint(bool atSavePoint) {
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifySavePoint(this, watchers[i].userData, atSavePoint);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
it->watcher->NotifySavePoint(this, it->userData, atSavePoint);
}
}
@ -1952,8 +1886,8 @@ void Document::NotifyModified(DocModification mh) {
} else if (mh.modificationType & SC_MOD_DELETETEXT) {
decorations.DeleteRange(mh.position, mh.length);
}
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
for (std::vector<WatcherWithUserData>::iterator it = watchers.begin(); it != watchers.end(); ++it) {
it->watcher->NotifyModified(this, mh, it->userData);
}
}
@ -2127,10 +2061,9 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) {
*/
class BuiltinRegex : public RegexSearchBase {
public:
BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {}
BuiltinRegex(CharClassify *charClassTable) : search(charClassTable) {}
virtual ~BuiltinRegex() {
delete substituted;
}
virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
@ -2141,7 +2074,7 @@ public:
private:
RESearch search;
char *substituted;
std::string substituted;
};
// 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);
if (success) {
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];
// There can be only one start of a line, so no need to look for last match in line
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) {
delete []substituted;
substituted = 0;
substituted.clear();
DocumentIndexer di(doc, doc->Length());
if (!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;
search.GrabMatches(di);
for (int j = 0; j < *length; j++) {
if (text[j] == '\\') {
if (text[j + 1] >= '0' && text[j + 1] <= '9') {
unsigned int patNum = text[j + 1] - '0';
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
memcpy(o, search.pat[patNum], len);
o += len;
if (!search.pat[patNum].empty()) // Will be null if try for a match that did not occur
substituted.append(search.pat[patNum].c_str(), len);
j++;
} else {
j++;
switch (text[j]) {
case 'a':
*o++ = '\a';
substituted.push_back('\a');
break;
case 'b':
*o++ = '\b';
substituted.push_back('\b');
break;
case 'f':
*o++ = '\f';
substituted.push_back('\f');
break;
case 'n':
*o++ = '\n';
substituted.push_back('\n');
break;
case 'r':
*o++ = '\r';
substituted.push_back('\r');
break;
case 't':
*o++ = '\t';
substituted.push_back('\t');
break;
case 'v':
*o++ = '\v';
substituted.push_back('\v');
break;
case '\\':
*o++ = '\\';
substituted.push_back('\\');
break;
default:
*o++ = '\\';
substituted.push_back('\\');
j--;
}
}
} else {
*o++ = text[j];
substituted.push_back(text[j]);
}
}
*o = '\0';
*length = lenResult;
return substituted;
*length = static_cast<int>(substituted.length());
return substituted.c_str();
}
#ifndef SCI_OWNREGEX

View File

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

View File

@ -208,6 +208,7 @@ Editor::Editor() {
recordingMacro = false;
foldFlags = 0;
foldAutomatic = 0;
wrapState = eWrapNone;
wrapWidth = LineLayout::wrapWidthInfinite;
@ -1246,6 +1247,9 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange rang
const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
XYScrollPosition newXY(xOffset, topLine);
if (rcClient.Empty()) {
return newXY;
}
// Vertical positioning
if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
@ -3850,7 +3854,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
vsPrint.braceBadLightIndicatorSet = false;
// 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) {
vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
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) {
NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
static_cast<unsigned char>(s[1]));
} else {
} else if (len > 0) {
int byte = static_cast<unsigned char>(s[0]);
if ((byte < 0xC0) || (1 == len)) {
// Handles UTF-8 characters between 0x01 and 0x7F and single byte
@ -4563,11 +4567,32 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
x += vs.ms[margin].width;
}
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};
scn.nmhdr.code = SCN_MARGINCLICK;
scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
(alt ? SCI_ALT : 0);
scn.position = pdoc->LineStart(LineFromLocation(pt));
scn.position = position;
scn.margin = marginClicked;
NotifyParent(scn);
return true;
@ -4706,11 +4731,11 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {
insertingNewLine = true;
}
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
NotifyNeedShown(mh.position, 0);
NeedShown(mh.position, 0);
} else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
NotifyNeedShown(mh.position, mh.length);
NeedShown(mh.position, mh.length);
}
}
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
if (IsLastStep(mh)) {
@ -4989,10 +5017,9 @@ void Editor::ChangeCaseOfSelection(int caseMapping) {
SelectionRange current = sel.Range(r);
SelectionRange currentNoVS = current;
currentNoVS.ClearVirtualSpace();
char *text = CopyRange(currentNoVS.Start().Position(), currentNoVS.End().Position());
size_t rangeBytes = currentNoVS.Length();
if (rangeBytes > 0) {
std::string sText(text, rangeBytes);
std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position());
std::string sMapped = CaseMapString(sText, caseMapping);
@ -5015,7 +5042,6 @@ void Editor::ChangeCaseOfSelection(int caseMapping) {
sel.Range(r) = current;
}
}
delete []text;
}
}
@ -5027,17 +5053,15 @@ void Editor::LineTranspose() {
int endPrev = pdoc->LineEnd(line - 1);
int start = pdoc->LineStart(line);
int end = pdoc->LineEnd(line);
char *line1 = CopyRange(startPrev, endPrev);
std::string line1 = RangeText(startPrev, endPrev);
int len1 = endPrev - startPrev;
char *line2 = CopyRange(start, end);
std::string line2 = RangeText(start, end);
int len2 = end - start;
pdoc->DeleteChars(start, len2);
pdoc->DeleteChars(startPrev, len1);
pdoc->InsertString(startPrev, line2, len2);
pdoc->InsertString(start - len1 + len2, line1, len1);
pdoc->InsertString(startPrev, line2.c_str(), len2);
pdoc->InsertString(start - len1 + len2, line1.c_str(), len1);
MovePositionTo(SelectionPosition(start - len1 + len2));
delete []line1;
delete []line2;
}
}
@ -5060,11 +5084,10 @@ void Editor::Duplicate(bool forLine) {
start = SelectionPosition(pdoc->LineStart(line));
end = SelectionPosition(pdoc->LineEnd(line));
}
char *text = CopyRange(start.Position(), end.Position());
std::string text = RangeText(start.Position(), end.Position());
if (forLine)
pdoc->InsertString(end.Position(), eol, eolLen);
pdoc->InsertString(end.Position() + eolLen, text, SelectionRange(end, start).Length());
delete []text;
pdoc->InsertString(end.Position() + eolLen, text.c_str(), SelectionRange(end, start).Length());
}
if (sel.Count() && sel.IsRectangular()) {
SelectionPosition last = sel.Last();
@ -5975,19 +5998,6 @@ static bool Close(Point pt1, Point pt2) {
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 {
if (start < end) {
int len = end - start;
@ -6007,21 +6017,13 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
int start = pdoc->LineStart(currentLine);
int end = pdoc->LineEnd(currentLine);
char *text = CopyRange(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);
std::string text = RangeText(start, end);
if (pdoc->eolMode != SC_EOL_LF)
strcat(textWithEndl, "\r");
text.append("\r");
if (pdoc->eolMode != SC_EOL_CR)
strcat(textWithEndl, "\n");
ss->Set(textWithEndl, static_cast<int>(strlen(textWithEndl) + 1),
text.append("\n");
ss->Copy(text.c_str(), static_cast<int>(text.length() + 1),
pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true);
delete []text;
}
} else {
int delimiterLength = 0;
@ -6033,7 +6035,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
}
}
size_t size = sel.Length() + delimiterLength * sel.Count();
char *text = new char[size + 1];
std::string text(size+1, '\0');
int j = 0;
std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
if (sel.selType == Selection::selRectangle)
@ -6055,7 +6057,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
}
}
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);
}
}
@ -6064,7 +6066,8 @@ void Editor::CopyRangeToClipboard(int start, int end) {
start = pdoc->ClampPositionIntoDocument(start);
end = pdoc->ClampPositionIntoDocument(end);
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);
CopyToClipboard(selectedText);
}
@ -6962,34 +6965,42 @@ void Editor::SetAnnotationVisible(int visible) {
/**
* 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);
line++;
while (line <= lineMaxSubord) {
if (doExpand)
cs.SetVisible(line, line, true);
int level = pdoc->GetLevel(line);
if (level & SC_FOLDLEVELHEADERFLAG) {
if (doExpand && cs.GetExpanded(line)) {
Expand(line, true);
if (cs.GetExpanded(line)) {
line = ExpandLine(line);
} else {
Expand(line, false);
line = pdoc->GetLastChild(line);
}
}
} else {
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 (action == SC_FOLDACTION_TOGGLE) {
if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
line = pdoc->GetFoldParent(line);
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);
if (lineMaxSubord > line) {
cs.SetExpanded(line, 0);
@ -7000,9 +7011,6 @@ void Editor::ToggleContraction(int line) {
// This does not re-expand the fold
EnsureCaretVisible();
}
SetScrollBars();
Redraw();
}
} else {
@ -7011,11 +7019,35 @@ void Editor::ToggleContraction(int line) {
GoToLine(line);
}
cs.SetExpanded(line, 1);
Expand(line, true);
ExpandLine(line);
}
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) {
@ -7057,7 +7089,7 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
EnsureLineVisible(lineParent, enforcePolicy);
if (!cs.GetExpanded(lineParent)) {
cs.SetExpanded(lineParent, 1);
Expand(lineParent, true);
ExpandLine(lineParent);
}
}
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) {
const char *text = 0;
int length = 0;
@ -7148,18 +7263,17 @@ int Editor::WrapCount(int line) {
void Editor::AddStyledText(char *buffer, int appendLength) {
// The buffer consists of alternating character bytes and style bytes
int textLength = appendLength / 2;
char *text = new char[textLength];
std::string text(textLength, '\0');
int i;
for (i = 0; i < textLength; i++) {
text[i] = buffer[i*2];
}
pdoc->InsertString(CurrentPosition(), text, textLength);
pdoc->InsertString(CurrentPosition(), text.c_str(), textLength);
for (i = 0; i < textLength; i++) {
text[i] = buffer[i*2+1];
}
pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
pdoc->SetStyles(textLength, text);
delete []text;
pdoc->SetStyles(textLength, text.c_str());
SetEmptySelection(sel.MainCaret() + textLength);
}
@ -8123,7 +8237,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break;
case SCI_TEXTWIDTH:
PLATFORM_ASSERT(wParam < vs.stylesSize);
PLATFORM_ASSERT(wParam < vs.styles.size());
PLATFORM_ASSERT(lParam);
return TextWidth(wParam, CharPtrFromSPtr(lParam));
@ -8533,21 +8647,42 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return cs.HiddenLines() ? 0 : 1;
case SCI_SETFOLDEXPANDED:
if (cs.SetExpanded(wParam, lParam != 0)) {
RedrawSelMargin();
}
SetFoldExpanded(wParam, lParam != 0);
break;
case SCI_GETFOLDEXPANDED:
return cs.GetExpanded(wParam);
case SCI_SETAUTOMATICFOLD:
foldAutomatic = wParam;
break;
case SCI_GETAUTOMATICFOLD:
return foldAutomatic;
case SCI_SETFOLDFLAGS:
foldFlags = wParam;
Redraw();
break;
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;
case SCI_CONTRACTEDFOLDNEXT:
@ -8934,9 +9069,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_CREATEDOCUMENT: {
Document *doc = new Document();
if (doc) {
doc->AddRef();
}
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: {
Document *doc = new Document();
if (doc) {
doc->AddRef();
doc->Allocate(wParam);
doc->SetUndoCollection(false);
}
return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
}

View File

@ -91,20 +91,13 @@ public:
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;
s = s_;
if (s)
len = len_;
else
s = 0;
len = 0;
codePage = codePage_;
characterSet = characterSet_;
rectangular = rectangular_;
lineCopy = lineCopy_;
FixSelectionForClipboard();
rectangular = false;
lineCopy = false;
codePage = 0;
characterSet = 0;
}
void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s;
@ -274,6 +267,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
bool recordingMacro;
int foldFlags;
int foldAutomatic;
ContractionState cs;
// Hotspot support
@ -522,7 +516,6 @@ protected: // ScintillaBase subclass needs access to much of Editor
void GoToLine(int lineNo);
virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
char *CopyRange(int start, int end);
std::string RangeText(int start, int end) const;
void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
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 SetAnnotationHeights(int start, int end);
void SetDocPointer(Document *document);
virtual void SetDocPointer(Document *document);
void SetAnnotationVisible(int visible);
void Expand(int &line, bool doExpand);
void ToggleContraction(int line);
int ExpandLine(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);
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 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);
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
surface->MoveTo(rc.left, ymid);
surface->LineTo(rc.right, ymid);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -73,13 +73,11 @@ public:
*/
class LineLayoutCache {
int level;
int length;
int size;
LineLayout **cache;
std::vector<LineLayout *>cache;
bool allInvalidated;
int styleClock;
int useCount;
void Allocate(int length_);
void Allocate(size_t length_);
void AllocateForLevel(int linesOnScreen, int linesInDoc);
public:
LineLayoutCache();
@ -122,9 +120,7 @@ class BreakFinder {
int lineEnd;
int posLineStart;
int nextBreak;
int *selAndEdge;
unsigned int saeSize;
unsigned int saeLen;
std::vector<int> selAndEdge;
unsigned int saeCurrentPos;
int saeNext;
int subBreak;
@ -146,8 +142,7 @@ public:
};
class PositionCache {
PositionCacheEntry *pces;
size_t size;
std::vector<PositionCacheEntry> pces;
unsigned int clock;
bool allClear;
// Private so PositionCache objects can not be copied
@ -157,7 +152,7 @@ public:
~PositionCache();
void Clear();
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,
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)
*
* 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)
*
* void re_fail(char *msg, char op)
@ -206,6 +202,8 @@
#include <stdlib.h>
#include <string>
#include "CharClassify.h"
#include "RESearch.h"
@ -269,37 +267,30 @@ void RESearch::Init() {
sta = NOP; /* status of lastpat */
bol = 0;
for (int i = 0; i < MAXTAG; i++)
pat[i] = 0;
pat[i].clear();
for (int j = 0; j < BITBLK; j++)
bittab[j] = 0;
}
void RESearch::Clear() {
for (int i = 0; i < MAXTAG; i++) {
delete []pat[i];
pat[i] = 0;
pat[i].clear();
bopat[i] = NOTFOUND;
eopat[i] = NOTFOUND;
}
}
bool RESearch::GrabMatches(CharacterIndexer &ci) {
bool success = true;
void RESearch::GrabMatches(CharacterIndexer &ci) {
for (unsigned int i = 0; i < MAXTAG; i++) {
if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
unsigned int len = eopat[i] - bopat[i];
pat[i] = new char[len + 1];
if (pat[i]) {
pat[i] = std::string(len+1, '\0');
for (unsigned int j = 0; j < len; j++)
pat[i][j] = ci.CharAt(bopat[i] + j);
pat[i][len] = '\0';
} else {
success = false;
}
}
}
return success;
}
void RESearch::ChSet(unsigned char c) {
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
@ -967,52 +958,4 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) {
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:
RESearch(CharClassify *charClassTable);
~RESearch();
bool GrabMatches(CharacterIndexer &ci);
void GrabMatches(CharacterIndexer &ci);
const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
int Execute(CharacterIndexer &ci, int lp, int endp);
int Substitute(CharacterIndexer &ci, char *src, char *dst);
enum { MAXTAG=10 };
enum { MAXNFA=2048 };
@ -44,7 +43,7 @@ public:
int bopat[MAXTAG];
int eopat[MAXTAG];
char *pat[MAXTAG];
std::string pat[MAXTAG];
private:
void Init();

View File

@ -9,6 +9,8 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdexcept>
#include "Platform.h"
#include "Scintilla.h"
@ -113,7 +115,13 @@ int RunStyles::EndRun(int position) {
}
bool RunStyles::FillRange(int &position, int value, int &fillLength) {
if (fillLength <= 0) {
return false;
}
int end = position + fillLength;
if (end > Length()) {
return false;
}
int runEnd = RunFromPosition(end);
if (styles->ValueAt(runEnd) == value) {
// End already has value so trim range.
@ -249,3 +257,31 @@ int RunStyles::Find(int value, int start) const {
}
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 AllSameAs(int value) const;
int Find(int value, int start) const;
void Check();
};
#ifdef SCI_NAMESPACE

View File

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

View File

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

View File

@ -21,7 +21,7 @@ FontAlias::FontAlias() {
FontAlias::~FontAlias() {
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) {
@ -32,12 +32,29 @@ void FontAlias::ClearFont() {
SetID(0);
}
bool FontSpecification::EqualTo(const FontSpecification &other) const {
return weight == other.weight &&
bool FontSpecification::operator==(const FontSpecification &other) const {
return fontName == other.fontName &&
weight == other.weight &&
italic == other.italic &&
size == other.size &&
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() {
@ -68,6 +85,7 @@ Style::Style(const Style &source) : FontSpecification(), FontMeasurements() {
weight = source.weight;
italic = source.italic;
size = source.size;
fontName = source.fontName;
eolFilled = source.eolFilled;
underline = source.underline;
caseForce = source.caseForce;
@ -91,6 +109,7 @@ Style &Style::operator=(const Style &source) {
weight = source.weight;
italic = source.italic;
size = source.size;
fontName = source.fontName;
eolFilled = source.eolFilled;
underline = source.underline;
caseForce = source.caseForce;

View File

@ -27,7 +27,8 @@ struct FontSpecification {
characterSet(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

View File

@ -33,100 +33,52 @@ MarginStyle::MarginStyle() :
// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
size = 8;
names = new char *[size];
max = 0;
}
FontNames::~FontNames() {
Clear();
delete []names;
names = 0;
}
void FontNames::Clear() {
for (int i=0; i<max; i++) {
delete []names[i];
}
max = 0;
names.clear();
}
const char *FontNames::Save(const char *name) {
if (!name)
return 0;
for (int i=0; i<max; i++) {
if (strcmp(names[i], name) == 0) {
return names[i];
for (std::vector<char *>::const_iterator it=names.begin(); it != names.end(); ++it) {
if (strcmp(*it, name) == 0) {
return *it;
}
}
if (max >= size) {
// Grow array
int sizeNew = size * 2;
char **namesNew = new char *[sizeNew];
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];
char *nameSave = new char[strlen(name) + 1];
strcpy(nameSave, name);
names.push_back(nameSave);
return nameSave;
}
FontRealised::FontRealised(const FontSpecification &fs) {
frNext = NULL;
(FontSpecification &)(*this) = fs;
FontRealised::FontRealised() {
}
FontRealised::~FontRealised() {
font.Release();
delete frNext;
frNext = 0;
}
void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) {
PLATFORM_ASSERT(fontName);
sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) {
PLATFORM_ASSERT(fs.fontName);
sizeZoomed = fs.size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
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);
ascent = surface.Ascent(font);
descent = surface.Descent(font);
aveCharWidth = surface.AverageCharWidth(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() {
@ -134,9 +86,8 @@ ViewStyle::ViewStyle() {
}
ViewStyle::ViewStyle(const ViewStyle &source) {
frFirst = NULL;
Init(source.stylesSize);
for (unsigned int sty=0; sty<source.stylesSize; sty++) {
Init(source.styles.size());
for (unsigned int sty=0; sty<source.styles.size(); sty++) {
styles[sty] = source.styles[sty];
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
@ -218,16 +169,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
}
ViewStyle::~ViewStyle() {
delete []styles;
styles = NULL;
delete frFirst;
frFirst = NULL;
styles.clear();
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
delete it->second;
}
fonts.clear();
}
void ViewStyle::Init(size_t stylesSize_) {
frFirst = NULL;
stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_);
nextExtendedStyle = 256;
fontNames.Clear();
@ -334,52 +283,42 @@ void ViewStyle::Init(size_t stylesSize_) {
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) {
delete frFirst;
frFirst = NULL;
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
delete it->second;
}
fonts.clear();
selbar = Platform::Chrome();
selbarlight = Platform::ChromeHighlight();
for (unsigned int i=0; i<stylesSize; i++) {
for (unsigned int i=0; i<styles.size(); i++) {
styles[i].extraFontFlag = extraFontFlag;
}
CreateFont(styles[STYLE_DEFAULT]);
for (unsigned int j=0; j<stylesSize; j++) {
for (unsigned int j=0; j<styles.size(); j++) {
CreateFont(styles[j]);
}
assert(frFirst);
frFirst->Realise(surface, zoomLevel, technology);
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
it->second->Realise(surface, zoomLevel, technology, it->first);
}
for (unsigned int k=0; k<stylesSize; k++) {
FontRealised *fr = frFirst->Find(styles[k]);
for (unsigned int k=0; k<styles.size(); k++) {
FontRealised *fr = Find(styles[k]);
styles[k].Copy(fr->font, *fr);
}
maxAscent = 1;
maxDescent = 1;
frFirst->FindMaxAscentDescent(maxAscent, maxDescent);
FindMaxAscentDescent(maxAscent, maxDescent);
maxAscent += extraAscent;
maxDescent += extraDescent;
lineHeight = maxAscent + maxDescent;
someStylesProtected = false;
someStylesForceCase = false;
for (unsigned int l=0; l<stylesSize; l++) {
for (unsigned int l=0; l<styles.size(); l++) {
if (styles[l].IsProtected()) {
someStylesProtected = true;
}
@ -401,25 +340,6 @@ void ViewStyle::Refresh(Surface &surface) {
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() {
nextExtendedStyle = 256;
}
@ -431,11 +351,8 @@ int ViewStyle::AllocateExtendedStyles(int numberStyles) {
}
void ViewStyle::EnsureStyle(size_t index) {
if (index >= stylesSize) {
size_t sizeNew = stylesSize * 2;
while (sizeNew <= index)
sizeNew *= 2;
AllocStyles(sizeNew);
if (index >= styles.size()) {
AllocStyles(index+1);
}
}
@ -449,7 +366,7 @@ void ViewStyle::ResetDefaultStyle() {
void ViewStyle::ClearStyles() {
// 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) {
styles[i].ClearTo(styles[STYLE_DEFAULT]);
}
@ -470,7 +387,7 @@ bool ViewStyle::ProtectionActive() const {
}
bool ViewStyle::ValidStyle(size_t styleIndex) const {
return styleIndex < stylesSize;
return styleIndex < styles.size();
}
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 {
private:
char **names;
int size;
int max;
std::vector<char *> names;
// Private so FontNames objects can not be copied
FontNames(const FontNames &);
@ -41,32 +39,30 @@ public:
const char *Save(const char *name);
};
class FontRealised : public FontSpecification, public FontMeasurements {
class FontRealised : public FontMeasurements {
// Private so FontRealised objects can not be copied
FontRealised(const FontRealised &);
FontRealised &operator=(const FontRealised &);
public:
Font font;
FontRealised *frNext;
FontRealised(const FontSpecification &fs);
FontRealised();
virtual ~FontRealised();
void Realise(Surface &surface, int zoomLevel, int technology);
FontRealised *Find(const FontSpecification &fs);
void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
void Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs);
};
enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
typedef std::map<FontSpecification, FontRealised *> FontMap;
/**
*/
class ViewStyle {
public:
FontNames fontNames;
FontRealised *frFirst;
size_t stylesSize;
Style *styles;
FontMap fonts;
public:
std::vector<Style> styles;
size_t nextExtendedStyle;
LineMarker markers[MARKER_MAX + 1];
int largestMarkerHeight;
@ -143,9 +139,7 @@ public:
ViewStyle(const ViewStyle &source);
~ViewStyle();
void Init(size_t stylesSize_=64);
void CreateFont(const FontSpecification &fs);
void Refresh(Surface &surface);
void AllocStyles(size_t sizeNew);
void ReleaseAllExtendedStyles();
int AllocateExtendedStyles(int numberStyles);
void EnsureStyle(size_t index);
@ -155,6 +149,13 @@ public:
bool ProtectionActive() const;
bool ValidStyle(size_t styleIndex) const;
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

View File

@ -41,12 +41,8 @@ static size_t MeasureLength(const char *s) {
return i;
}
ColourDesired XPM::ColourDesiredFromCode(int ch) const {
return *colourCodeTable[ch];
}
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) {
@ -56,13 +52,11 @@ void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) {
}
}
XPM::XPM(const char *textForm) :
data(0), codes(0), colours(0), lines(0) {
XPM::XPM(const char *textForm) {
Init(textForm);
}
XPM::XPM(const char *const *linesForm) :
data(0), codes(0), colours(0), lines(0) {
XPM::XPM(const char *const *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 ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
// Build the lines form out of the text form
const char **linesForm = LinesFormFromTextForm(textForm);
if (linesForm != 0) {
Init(linesForm);
delete []linesForm;
std::vector<const char *> linesForm = LinesFormFromTextForm(textForm);
if (!linesForm.empty()) {
Init(&linesForm[0]);
}
} else {
// It is really in line form
@ -92,18 +85,17 @@ void XPM::Init(const char *const *linesForm) {
height = 1;
width = 1;
nColours = 1;
data = NULL;
pixels.clear();
codeTransparent = ' ';
codes = NULL;
colours = NULL;
lines = NULL;
if (!linesForm)
return;
std::fill(colourCodeTable, colourCodeTable+256, 0);
const char *line0 = linesForm[0];
width = atoi(line0);
line0 = NextField(line0);
height = atoi(line0);
pixels.resize(width*height);
line0 = NextField(line0);
nColours = atoi(line0);
line0 = NextField(line0);
@ -111,56 +103,33 @@ void XPM::Init(const char *const *linesForm) {
// Only one char per pixel is supported
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++) {
const char *colourDef = linesForm[c+1];
codes[c] = colourDef[0];
int code = static_cast<unsigned char>(colourDef[0]);
colourDef += 4;
ColourDesired colour(0xff, 0xff, 0xff);
if (*colourDef == '#') {
colours[c].Set(colourDef);
colour.Set(colourDef);
} else {
colours[c] = ColourDesired(0xff, 0xff, 0xff);
codeTransparent = codes[c];
codeTransparent = code;
}
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() {
delete []data;
data = 0;
delete []codes;
codes = 0;
delete []colours;
colours = 0;
delete []lines;
lines = 0;
}
void XPM::Draw(Surface *surface, PRectangle &rc) {
if (!data || !codes || !colours || !lines) {
if (pixels.empty()) {
return;
}
// Centre the pixmap
@ -170,7 +139,7 @@ void XPM::Draw(Surface *surface, PRectangle &rc) {
int prevCode = 0;
int xStartRun = 0;
for (int x=0; x<width; x++) {
int code = lines[y+nColours+1][x];
int code = pixels[y * width + x];
if (code != prevCode) {
FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + 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 {
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;
transparent = true;
return;
}
int code = lines[y+nColours+1][x];
int code = pixels[y * width + x];
transparent = code == codeTransparent;
if (transparent) {
colour = 0;
} 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
const char **linesForm = 0;
std::vector<const char *> linesForm;
int countQuotes = 0;
int strings=1;
int j=0;
@ -214,111 +183,23 @@ const char **XPM::LinesFormFromTextForm(const char *textForm) {
line0 = NextField(line0);
// Add 1 line for each colour
strings += atoi(line0);
linesForm = new const char *[strings];
if (linesForm == 0) {
break; // Memory error!
}
}
if (countQuotes / 2 >= strings) {
break; // Bad height or number of colors!
}
if ((countQuotes & 1) == 0) {
linesForm[countQuotes / 2] = textForm + j + 1;
linesForm.push_back(textForm + j + 1);
}
countQuotes++;
}
}
if (textForm[j] == '\0' || countQuotes / 2 > strings) {
// Malformed XPM! Height + number of colors too high or too low
delete []linesForm;
linesForm = 0;
linesForm.clear();
}
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_) :
height(height_), width(width_), scale(scale_) {
if (pixels_) {

View File

@ -1,6 +1,6 @@
// Scintilla source code edit control
/** @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>
// 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.
*/
class XPM {
int pid; // Assigned by container
int height;
int width;
int nColours;
char *data;
std::vector<unsigned char> pixels;
ColourDesired colourCodeTable[256];
char codeTransparent;
char *codes;
ColourDesired *colours;
ColourDesired ColourDesiredFromCode(int ch) const;
ColourDesired ColourFromCode(int ch) const;
void FillRun(Surface *surface, int code, int startX, int y, int x);
char **lines;
ColourDesired *colourCodeTable[256];
public:
XPM(const char *textForm);
XPM(const char *const *linesForm);
@ -38,41 +33,15 @@ public:
void Clear();
/// Decompose image into runs and use FillRectangle for each run
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 GetWidth() const { return width; }
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.
*/
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.
* A translucent image stored as a sequence of RGBA bytes.
*/
class RGBAImage {
// Private so RGBAImage objects can not be copied

View File

@ -1 +1 @@
331
332