aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Document.cxx164
-rw-r--r--src/Document.h47
-rw-r--r--src/Editor.cxx375
-rw-r--r--src/Editor.h5
-rw-r--r--src/PerLine.cxx464
-rw-r--r--src/PerLine.h104
-rw-r--r--src/ViewStyle.cxx11
-rw-r--r--src/ViewStyle.h4
8 files changed, 1156 insertions, 18 deletions
diff --git a/src/Document.cxx b/src/Document.cxx
index e5913ad98..2c9ac34a9 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -17,6 +17,7 @@
#include "Partitioning.h"
#include "RunStyles.h"
#include "CellBuffer.h"
+#include "PerLine.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
@@ -74,6 +75,14 @@ Document::Document() {
matchesValid = false;
regex = 0;
+
+ perLineData[ldMarkers] = new LineMarkers();
+ perLineData[ldLevels] = new LineLevels();
+ perLineData[ldState] = new LineState();
+ perLineData[ldMargin] = new LineAnnotation();
+ perLineData[ldAnnotation] = new LineAnnotation();
+
+ cb.SetPerLine(this);
}
Document::~Document() {
@@ -81,12 +90,30 @@ Document::~Document() {
watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
}
delete []watchers;
+ for (int j=0; j<ldSize; j++) {
+ delete perLineData[j];
+ perLineData[j] = 0;
+ }
watchers = 0;
lenWatchers = 0;
delete regex;
regex = 0;
}
+void Document::InsertLine(int line) {
+ for (int j=0; j<ldSize; j++) {
+ if (perLineData[j])
+ perLineData[j]->InsertLine(line);
+ }
+}
+
+void Document::RemoveLine(int line) {
+ for (int j=0; j<ldSize; j++) {
+ if (perLineData[j])
+ perLineData[j]->RemoveLine(line);
+ }
+}
+
// Increase reference count and return its previous value.
int Document::AddRef() {
return refCount++;
@@ -106,8 +133,13 @@ void Document::SetSavePoint() {
NotifySavePoint(true);
}
+int Document::GetMark(int line) {
+ return static_cast<LineMarkers*>(perLineData[ldMarkers])->MarkValue(line);
+}
+
int Document::AddMark(int line, int markerNum) {
- int prev = cb.AddMark(line, markerNum);
+ int prev = static_cast<LineMarkers*>(perLineData[ldMarkers])->
+ AddMark(line, markerNum, LinesTotal());
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
NotifyModified(mh);
return prev;
@@ -117,31 +149,38 @@ void Document::AddMarkSet(int line, int valueSet) {
unsigned int m = valueSet;
for (int i = 0; m; i++, m >>= 1)
if (m & 1)
- cb.AddMark(line, i);
+ static_cast<LineMarkers*>(perLineData[ldMarkers])->
+ AddMark(line, i, LinesTotal());
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
NotifyModified(mh);
}
void Document::DeleteMark(int line, int markerNum) {
- cb.DeleteMark(line, markerNum);
+ static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
NotifyModified(mh);
}
void Document::DeleteMarkFromHandle(int markerHandle) {
- cb.DeleteMarkFromHandle(markerHandle);
+ static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle);
DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
mh.line = -1;
NotifyModified(mh);
}
void Document::DeleteAllMarks(int markerNum) {
- cb.DeleteAllMarks(markerNum);
+ for (int line = 0; line < LinesTotal(); line++) {
+ static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true);
+ }
DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
mh.line = -1;
NotifyModified(mh);
}
+int Document::LineFromHandle(int markerHandle) {
+ return static_cast<LineMarkers*>(perLineData[ldMarkers])->LineFromHandle(markerHandle);
+}
+
int Document::LineStart(int line) const {
return cb.LineStart(line);
}
@@ -181,7 +220,7 @@ int Document::VCHomePosition(int position) {
}
int Document::SetLevel(int line, int level) {
- int prev = cb.SetLevel(line, level);
+ int prev = static_cast<LineLevels*>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());
if (prev != level) {
DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
LineStart(line), 0, 0, 0, line);
@@ -192,6 +231,14 @@ int Document::SetLevel(int line, int level) {
return prev;
}
+int Document::GetLevel(int line) {
+ return static_cast<LineLevels*>(perLineData[ldLevels])->GetLevel(line);
+}
+
+void Document::ClearLevels() {
+ static_cast<LineLevels*>(perLineData[ldLevels])->ClearLevels();
+}
+
static bool IsSubordinate(int levelStart, int levelTry) {
if (levelTry & SC_FOLDLEVELWHITEFLAG)
return true;
@@ -1206,7 +1253,7 @@ void Document::EnsureStyledTo(int pos) {
}
int Document::SetLineState(int line, int state) {
- int statePrevious = cb.SetLineState(line, state);
+ int statePrevious = static_cast<LineState*>(perLineData[ldState])->SetLineState(line, state);
if (state != statePrevious) {
DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
NotifyModified(mh);
@@ -1214,6 +1261,109 @@ int Document::SetLineState(int line, int state) {
return statePrevious;
}
+int Document::GetLineState(int line) {
+ return static_cast<LineState*>(perLineData[ldState])->GetLineState(line);
+}
+
+int Document::GetMaxLineState() {
+ return static_cast<LineState*>(perLineData[ldState])->GetMaxLineState();
+}
+
+bool Document::MarginMultipleStyles(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldMargin])->MultipleStyles(line);
+}
+
+const char *Document::MarginText(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldMargin])->Text(line);
+}
+
+int Document::MarginStyle(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldMargin])->Style(line);
+}
+
+const char *Document::MarginStyles(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldMargin])->Styles(line);
+}
+
+void Document::MarginSetText(int line, const char *text) {
+ static_cast<LineAnnotation*>(perLineData[ldMargin])->SetText(line, text);
+ DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line);
+ NotifyModified(mh);
+}
+
+void Document::MarginSetStyle(int line, int style) {
+ static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyle(line, style);
+}
+
+void Document::MarginSetStyles(int line, const char *styles) {
+ static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyles(line, styles);
+}
+
+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++)
+ MarginSetText(l, 0);
+ // Free remaining data
+ static_cast<LineAnnotation*>(perLineData[ldMargin])->ClearAll();
+}
+
+bool Document::AnnotationAny() const {
+ return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->AnySet();
+}
+
+bool Document::AnnotationMultipleStyles(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->MultipleStyles(line);
+}
+
+const char *Document::AnnotationText(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Text(line);
+}
+
+int Document::AnnotationStyle(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Style(line);
+}
+
+const char *Document::AnnotationStyles(int line) {
+ return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Styles(line);
+}
+
+void Document::AnnotationSetText(int line, const char *text) {
+ const int linesBefore = AnnotationLines(line);
+ static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetText(line, text);
+ const int linesAfter = AnnotationLines(line);
+ DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line);
+ mh.annotationLinesAdded = linesAfter - linesBefore;
+ NotifyModified(mh);
+}
+
+void Document::AnnotationSetStyle(int line, int style) {
+ static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyle(line, style);
+}
+
+void Document::AnnotationSetStyles(int line, const char *styles) {
+ static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyles(line, 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);
+}
+
+void Document::AnnotationClearAll() {
+ int maxEditorLine = LinesTotal();
+ for (int l=0;l<maxEditorLine;l++)
+ AnnotationSetText(l, 0);
+ // Free remaining data
+ static_cast<LineAnnotation*>(perLineData[ldAnnotation])->ClearAll();
+}
+
void Document::IncrementStyleClock() {
styleClock = (styleClock + 1) % 0x100000;
}
diff --git a/src/Document.h b/src/Document.h
index 2e8c43eeb..6c0d9d51c 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -95,7 +95,7 @@ extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable);
/**
*/
-class Document {
+class Document : PerLine {
public:
/** Used to pair watcher pointer with user data. */
@@ -110,7 +110,6 @@ public:
};
enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation };
-
private:
int refCount;
CellBuffer cb;
@@ -125,6 +124,10 @@ private:
WatcherWithUserData *watchers;
int lenWatchers;
+ // ldSize is not real data - it is for dimensions and loops
+ enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
+ PerLine *perLineData[ldSize];
+
bool matchesValid;
RegexSearchBase* regex;
@@ -150,6 +153,9 @@ public:
int AddRef();
int Release();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
int LineFromPosition(int pos);
int ClampPositionIntoDocument(int pos);
bool IsCrLf(int pos);
@@ -200,21 +206,21 @@ public:
cb.GetCharRange(buffer, position, lengthRetrieve);
}
char StyleAt(int position) { return cb.StyleAt(position); }
- int GetMark(int line) { return cb.GetMark(line); }
+ int GetMark(int line);
int AddMark(int line, int markerNum);
void AddMarkSet(int line, int valueSet);
void DeleteMark(int line, int markerNum);
void DeleteMarkFromHandle(int markerHandle);
void DeleteAllMarks(int markerNum);
- int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
+ int LineFromHandle(int markerHandle);
int LineStart(int line) const;
int LineEnd(int line) const;
int LineEndPosition(int position);
int VCHomePosition(int position);
int SetLevel(int line, int level);
- int GetLevel(int line) { return cb.GetLevel(line); }
- void ClearLevels() { cb.ClearLevels(); }
+ int GetLevel(int line);
+ void ClearLevels();
int GetLastChild(int lineParent, int level=-1);
int GetFoldParent(int line);
@@ -245,8 +251,30 @@ public:
void DecorationFillRange(int position, int value, int fillLength);
int SetLineState(int line, int state);
- int GetLineState(int line) { return cb.GetLineState(line); }
- int GetMaxLineState() { return cb.GetMaxLineState(); }
+ int GetLineState(int line);
+ int GetMaxLineState();
+
+ bool MarginMultipleStyles(int line);
+ const char *MarginText(int line);
+ int MarginStyle(int line);
+ const char *MarginStyles(int line);
+ void MarginSetStyle(int line, int style);
+ void MarginSetStyles(int line, const char *styles);
+ void MarginSetText(int line, const char *text);
+ int MarginLength(int line) const;
+ void MarginClearAll();
+
+ bool AnnotationAny() const;
+ bool AnnotationMultipleStyles(int line);
+ const char *AnnotationText(int line);
+ const char *AnnotationStyles(int line);
+ int AnnotationStyle(int line);
+ void AnnotationSetText(int line, const char *text);
+ void AnnotationSetStyle(int line, int style);
+ void AnnotationSetStyles(int line, const 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);
@@ -289,6 +317,7 @@ public:
int line;
int foldLevelNow;
int foldLevelPrev;
+ int annotationLinesAdded;
int token;
DocModification(int modificationType_, int position_=0, int length_=0,
@@ -301,6 +330,7 @@ public:
line(line_),
foldLevelNow(0),
foldLevelPrev(0),
+ annotationLinesAdded(0),
token(0) {}
DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
@@ -312,6 +342,7 @@ public:
line(0),
foldLevelNow(0),
foldLevelPrev(0),
+ annotationLinesAdded(0),
token(0) {}
};
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 5d709fe06..77fbb4cec 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -1277,7 +1277,8 @@ bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
linesWrapped = ll->lines;
}
- return cs.SetHeight(lineToWrap, linesWrapped);
+ return cs.SetHeight(lineToWrap, linesWrapped +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
}
// Check if wrapping needed and perform any needed wrapping.
@@ -1315,7 +1316,8 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
if (wrapWidth != LineLayout::wrapWidthInfinite) {
wrapWidth = LineLayout::wrapWidthInfinite;
for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
- cs.SetHeight(lineDoc, 1);
+ cs.SetHeight(lineDoc, 1 +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
}
wrapOccurred = true;
}
@@ -1457,6 +1459,30 @@ static int istrlen(const char *s) {
return static_cast<int>(strlen(s));
}
+void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,
+ const char *text, const char *styles, int length) {
+
+ int x = rcText.left;
+ int i = 0;
+ while (i < length) {
+ int end = i;
+ int style = styles[i];
+ while (end < length-1 && styles[end+1] == style)
+ end++;
+ style += styleOffset;
+ int width = surface->WidthText(vs.styles[style].font, text + i, end - i + 1);
+ PRectangle rcSegment = rcText;
+ rcSegment.left = x;
+ rcSegment.right = x + width + 1;
+ surface->DrawTextNoClip(rcSegment, vs.styles[style].font,
+ ascent, text + i, end - i + 1,
+ vs.styles[style].fore.allocated,
+ vs.styles[style].back.allocated);
+ x += width;
+ i = end + 1;
+ }
+}
+
void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
if (vs.fixedColumnWidth == 0)
return;
@@ -1638,6 +1664,38 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
rcNumber.top + vs.maxAscent, number, istrlen(number),
vs.styles[STYLE_LINENUMBER].fore.allocated,
vs.styles[STYLE_LINENUMBER].back.allocated);
+ } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ if (firstSubLine) {
+ const char *marginText = pdoc->MarginText(lineDoc);
+ int lengthMargin = pdoc->MarginLength(lineDoc);
+ if (marginText) {
+ if (pdoc->MarginMultipleStyles(lineDoc)) {
+ const char *marginStyles = pdoc->MarginStyles(lineDoc);
+ for (size_t iStyle=0;iStyle<static_cast<size_t>(lengthMargin); iStyle++) {
+ if (!vs.ValidStyle(static_cast<size_t>(
+ vs.marginStyleOffset + marginStyles[iStyle])))
+ return;
+ }
+ surface->FillRectangle(rcMarker,
+ vs.styles[marginStyles[0]+vs.marginStyleOffset].back.allocated);
+ DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,
+ marginText, marginStyles, lengthMargin);
+ } else {
+ int style = pdoc->MarginStyle(lineDoc) + vs.marginStyleOffset;
+ if (!vs.ValidStyle(static_cast<size_t>(style)))
+ return;
+ surface->FillRectangle(rcMarker, vs.styles[style].back.allocated);
+ if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ int width = surface->WidthText(vs.styles[style].font, marginText, istrlen(marginText));
+ rcMarker.left = rcMarker.right - width - 3;
+ }
+ surface->DrawTextNoClip(rcMarker, vs.styles[style].font,
+ rcMarker.top + vs.maxAscent, marginText, lengthMargin,
+ vs.styles[style].fore.allocated,
+ vs.styles[style].back.allocated);
+ }
+ }
+ }
}
if (marks) {
@@ -2221,6 +2279,161 @@ void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
textBack, textFore);
}
+struct LineSegment {
+ const char *s;
+ int len;
+};
+
+class LineEnumerator {
+public:
+ const char *s;
+ int len;
+ LineEnumerator(const char *s_, size_t len_) : s(s_), len(len_) {
+ }
+ LineSegment Next() {
+ LineSegment ret;
+ ret.s = s;
+ int cur = 0;
+ while ((cur < len) && (s[cur] != '\n'))
+ cur++;
+ ret.len = cur;
+ s += cur + 1;
+ len -= cur + 1;
+ return ret;
+ }
+ bool Finished() const {
+ return len <= 0;
+ }
+};
+
+static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset,
+ const char *text, const char *styles, size_t len) {
+ int width = 0;
+ size_t start = 0;
+ while (start < len) {
+ int style = styles[start];
+ size_t endSegment = start;
+ while ((endSegment < len-1) && (styles[endSegment+1] == style))
+ endSegment++;
+ width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, endSegment - start + 1);
+ start = endSegment + 1;
+ }
+ return width;
+}
+
+static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset,
+ const char *text, const char *styles, size_t len) {
+ LineEnumerator le(text, len);
+ int widthComment = 0;
+ while (!le.Finished()) {
+ LineSegment ls = le.Next();
+ int widthSubLine = WidthStyledText(surface, vs, styleOffset, ls.s, styles, ls.len);
+ if (widthSubLine > widthComment)
+ widthComment = widthSubLine;
+ styles += ls.len;
+ }
+ return widthComment;
+}
+
+static int WidestLineWidth(Surface *surface, const char *text, size_t len, Font &font) {
+ LineEnumerator le(text, len);
+ int widthComment = 0;
+ while (!le.Finished()) {
+ LineSegment ls = le.Next();
+ int widthSubLine = surface->WidthText(font, ls.s, ls.len);
+ if (widthSubLine > widthComment)
+ widthComment = widthSubLine;
+ }
+ return widthComment;
+}
+
+void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+ int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth;
+ PRectangle rcSegment = rcLine;
+ int annotationLine = subLine - ll->lines;
+ int annotationStyle = pdoc->AnnotationStyle(line) + vsDraw.annotationStyleOffset;
+ const char *annotationText = pdoc->AnnotationText(line);
+ const char *annotationStyles = pdoc->AnnotationStyles(line);
+ int lengthAnnotation = pdoc->AnnotationLength(line);
+ const bool multipleStyles = pdoc->AnnotationMultipleStyles(line);
+ if (multipleStyles) {
+ for (size_t iStyle=0;iStyle<static_cast<size_t>(lengthAnnotation); iStyle++) {
+ if (!vsDraw.ValidStyle(static_cast<size_t>(
+ vsDraw.annotationStyleOffset + annotationStyles[iStyle])))
+ return;
+ }
+ } else {
+ if (!vsDraw.ValidStyle(static_cast<size_t>(annotationStyle)))
+ return;
+ }
+ if (annotationText) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[0].back.allocated);
+
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ // Only care about calculating width if need to draw box
+ int widthAnnotation;
+ if (multipleStyles) {
+ widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset,
+ annotationText, annotationStyles, lengthAnnotation);
+ } else {
+ widthAnnotation = WidestLineWidth(surface, annotationText, lengthAnnotation, vsDraw.styles[annotationStyle].font);
+ }
+ widthAnnotation += 16; // Margin
+ rcSegment.left = xStart + indent;
+ rcSegment.right = rcSegment.left + widthAnnotation;
+ surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated);
+ } else {
+ rcSegment.left = xStart;
+ }
+ const int annotationLines = pdoc->AnnotationLines(line);
+ LineEnumerator le(annotationText, lengthAnnotation);
+ LineSegment ls = le.Next();
+ annotationText = ls.s;
+ lengthAnnotation = ls.len;
+ int lineInAnnotation = 0;
+ while ((lineInAnnotation < annotationLine) && !le.Finished()) {
+ annotationStyles += ls.len;
+ ls = le.Next();
+ annotationText = ls.s;
+ lengthAnnotation = ls.len;
+ lineInAnnotation++;
+ }
+ PRectangle rcText = rcSegment;
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ if (multipleStyles) {
+ surface->FillRectangle(rcText, vsDraw.styles[annotationStyles[0] + vsDraw.annotationStyleOffset].back.allocated);
+ } else {
+ surface->FillRectangle(rcText, vsDraw.styles[annotationStyle].back.allocated);
+ }
+ rcText.left += 8;
+ }
+ if (multipleStyles) {
+ DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,
+ annotationText, annotationStyles, lengthAnnotation);
+ } else {
+ surface->DrawTextNoClip(rcText, vsDraw.styles[annotationStyle].font,
+ rcLine.top + vsDraw.maxAscent, annotationText, lengthAnnotation,
+ vsDraw.styles[annotationStyle].fore.allocated,
+ vsDraw.styles[annotationStyle].back.allocated);
+ }
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.left, rcSegment.bottom);
+ surface->MoveTo(rcSegment.right, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.bottom);
+ if (subLine == ll->lines){
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.top);
+ }
+ if (subLine == ll->lines+annotationLines-1) {
+ surface->MoveTo(rcSegment.left, rcSegment.bottom - 1);
+ surface->LineTo(rcSegment.right, rcSegment.bottom - 1);
+ }
+ }
+ }
+}
+
void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
PRectangle rcLine, LineLayout *ll, int subLine) {
@@ -2280,6 +2493,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
int startseg = ll->LineStart(subLine);
int subLineStart = ll->positions[startseg];
+ if (subLine >= ll->lines) {
+ DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine);
+ return; // No further drawing
+ }
int lineStart = 0;
int lineEnd = 0;
if (subLine < ll->lines) {
@@ -3810,6 +4027,10 @@ void Editor::CheckModificationForWrap(DocModification mh) {
int lines = Platform::Maximum(0, mh.linesAdded);
NeedWrapping(lineDoc, lineDoc + lines + 1);
}
+ // Fix up annotation heights
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ int lines = Platform::Maximum(0, mh.linesAdded);
+ SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
}
}
@@ -3897,6 +4118,12 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
cs.DeleteLines(lineOfPos, -mh.linesAdded);
}
}
+ if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ if (vs.annotationVisible) {
+ cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded);
+ }
+ }
CheckModificationForWrap(mh);
if (mh.linesAdded != 0) {
// Avoid scrolling of display if change before current display
@@ -3927,7 +4154,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
SetScrollBars();
}
- if (mh.modificationType & SC_MOD_CHANGEMARKER) {
+ if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
if ((paintState == notPainting) || !PaintContainsMargin()) {
if (mh.modificationType & SC_MOD_CHANGEFOLD) {
// Fold changes can affect the drawing of following lines so redraw whole margin
@@ -3962,6 +4189,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
scn.foldLevelNow = mh.foldLevelNow;
scn.foldLevelPrev = mh.foldLevelPrev;
scn.token = mh.token;
+ scn.annotationLinesAdded = mh.annotationLinesAdded;
NotifyParent(scn);
}
}
@@ -4231,8 +4459,16 @@ void Editor::NewLine() {
void Editor::CursorUpOrDown(int direction, selTypes sel) {
Point pt = LocationFromPosition(currentPos);
+ int lineDoc = pdoc->LineFromPosition(currentPos);
+ Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
+ int subLine = (pt.y - ptStartLine.y) / vs.lineHeight;
+ int commentLines = vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0;
int posNew = PositionFromLocation(
Point(lastXChosen, pt.y + direction * vs.lineHeight));
+ if ((direction > 0) && (subLine >= (cs.GetHeight(lineDoc) - 1 - commentLines))) {
+ posNew = PositionFromLocation(
+ Point(lastXChosen, pt.y + (commentLines + 1) * vs.lineHeight));
+ }
if (direction < 0) {
// Line wrapping may lead to a location on the same line, so
// seek back if that is the case.
@@ -5668,6 +5904,14 @@ void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
}
}
+void Editor::SetAnnotationHeights(int start, int end) {
+ if (vs.annotationVisible) {
+ for (int line=start; line<end; line++) {
+ cs.SetHeight(line, pdoc->AnnotationLines(line) + 1);
+ }
+ }
+}
+
void Editor::SetDocPointer(Document *document) {
//Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
pdoc->RemoveWatcher(this, 0);
@@ -5692,6 +5936,7 @@ void Editor::SetDocPointer(Document *document) {
// Reset the contraction state to fully shown.
cs.Clear();
cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
llc.Deallocate();
NeedWrapping();
@@ -5700,6 +5945,22 @@ void Editor::SetDocPointer(Document *document) {
Redraw();
}
+void Editor::SetAnnotationVisible(int visible) {
+ if (vs.annotationVisible != visible) {
+ bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
+ vs.annotationVisible = visible;
+ if (changedFromOrToHidden) {
+ int dir = vs.annotationVisible ? 1 : -1;
+ for (int line=0; line<pdoc->LinesTotal(); line++) {
+ int annotationLines = pdoc->AnnotationLines(line);
+ if (annotationLines > 0) {
+ cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir);
+ }
+ }
+ }
+ }
+}
+
/**
* Recursively expand a fold, making lines visible except where they have an unexpanded parent.
*/
@@ -7636,6 +7897,114 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_GETEXTRADESCENT:
return vs.extraDescent;
+ case SCI_MARGINSETSTYLEOFFSET:
+ vs.marginStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_MARGINGETSTYLEOFFSET:
+ return vs.marginStyleOffset;
+
+ case SCI_MARGINSETTEXT:
+ pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_MARGINGETTEXT: {
+ const char *text = pdoc->MarginText(wParam);
+ if (lParam) {
+ if (text)
+ memcpy(CharPtrFromSPtr(lParam), text, pdoc->MarginLength(wParam));
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return text ? pdoc->MarginLength(wParam) : 0;
+ }
+
+ case SCI_MARGINSETSTYLE:
+ pdoc->MarginSetStyle(wParam, lParam);
+ break;
+
+ case SCI_MARGINGETSTYLE:
+ return pdoc->MarginStyle(wParam);
+
+ case SCI_MARGINSETSTYLES:
+ pdoc->MarginSetStyles(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_MARGINGETSTYLES: {
+ const char *styles = pdoc->MarginStyles(wParam);
+ if (lParam) {
+ if (styles)
+ memcpy(CharPtrFromSPtr(lParam), styles, pdoc->MarginLength(wParam));
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return styles ? pdoc->MarginLength(wParam) : 0;
+ }
+
+ case SCI_MARGINTEXTCLEARALL:
+ pdoc->MarginClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETTEXT:
+ pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETTEXT: {
+ const char *text = pdoc->AnnotationText(wParam);
+ if (lParam) {
+ if (text)
+ memcpy(CharPtrFromSPtr(lParam), text, pdoc->AnnotationLength(wParam));
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return text ? pdoc->AnnotationLength(wParam) : 0;
+ }
+
+ case SCI_ANNOTATIONGETSTYLE:
+ return pdoc->AnnotationStyle(wParam);
+
+ case SCI_ANNOTATIONSETSTYLE:
+ pdoc->AnnotationSetStyle(wParam, lParam);
+ break;
+
+ case SCI_ANNOTATIONSETSTYLES:
+ pdoc->AnnotationSetStyles(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETSTYLES: {
+ const char *styles = pdoc->AnnotationStyles(wParam);
+ if (lParam) {
+ if (styles)
+ memcpy(CharPtrFromSPtr(lParam), styles, pdoc->AnnotationLength(wParam));
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return styles ? pdoc->AnnotationLength(wParam) : 0;
+ }
+
+ case SCI_ANNOTATIONGETLINES:
+ return pdoc->AnnotationLines(wParam);
+
+ case SCI_ANNOTATIONCLEARALL:
+ pdoc->AnnotationClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETVISIBLE:
+ SetAnnotationVisible(wParam);
+ break;
+
+ case SCI_ANNOTATIONGETVISIBLE:
+ return vs.annotationVisible;
+
+ case SCI_ANNOTATIONSETSTYLEOFFSET:
+ vs.annotationStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_ANNOTATIONGETSTYLEOFFSET:
+ return vs.annotationStyleOffset;
+
case SCI_ADDUNDOACTION:
pdoc->AddUndoAction(wParam);
break;
diff --git a/src/Editor.h b/src/Editor.h
index 0d0b8ac9c..35564ca8c 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -322,6 +322,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
bool drawWrapMark, ColourAllocated wrapColour);
void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under);
+ void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine);
void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
PRectangle rcLine, LineLayout *ll, int subLine=0);
void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret);
@@ -443,7 +445,10 @@ protected: // ScintillaBase subclass needs access to much of Editor
void CheckForChangeOutsidePaint(Range r);
void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
+ void SetAnnotationHeights(int start, int end);
void SetDocPointer(Document *document);
+
+ void SetAnnotationVisible(int visible);
void Expand(int &line, bool doExpand);
void ToggleContraction(int line);
diff --git a/src/PerLine.cxx b/src/PerLine.cxx
new file mode 100644
index 000000000..b90416abb
--- /dev/null
+++ b/src/PerLine.cxx
@@ -0,0 +1,464 @@
+// Scintilla source code edit control
+/** @file PerLine.cxx
+ ** Manages data associated with each line of the document
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "CellBuffer.h"
+#include "PerLine.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+MarkerHandleSet::MarkerHandleSet() {
+ root = 0;
+}
+
+MarkerHandleSet::~MarkerHandleSet() {
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ MarkerHandleNumber *mhnToFree = mhn;
+ mhn = mhn->next;
+ delete mhnToFree;
+ }
+ root = 0;
+}
+
+int MarkerHandleSet::Length() const {
+ int c = 0;
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ c++;
+ mhn = mhn->next;
+ }
+ 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;
+ while (mhn) {
+ m |= (1 << mhn->number);
+ mhn = mhn->next;
+ }
+ return m;
+}
+
+bool MarkerHandleSet::Contains(int handle) const {
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ if (mhn->handle == handle) {
+ return true;
+ }
+ mhn = mhn->next;
+ }
+ return false;
+}
+
+bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
+ MarkerHandleNumber *mhn = new MarkerHandleNumber;
+ if (!mhn)
+ return false;
+ mhn->handle = handle;
+ mhn->number = markerNum;
+ mhn->next = root;
+ root = mhn;
+ return true;
+}
+
+void MarkerHandleSet::RemoveHandle(int handle) {
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ MarkerHandleNumber *mhn = *pmhn;
+ if (mhn->handle == handle) {
+ *pmhn = mhn->next;
+ delete mhn;
+ return;
+ }
+ pmhn = &((*pmhn)->next);
+ }
+}
+
+bool MarkerHandleSet::RemoveNumber(int markerNum) {
+ bool performedDeletion = false;
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ MarkerHandleNumber *mhn = *pmhn;
+ if (mhn->number == markerNum) {
+ *pmhn = mhn->next;
+ delete mhn;
+ performedDeletion = true;
+ } else {
+ pmhn = &((*pmhn)->next);
+ }
+ }
+ return performedDeletion;
+}
+
+void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ pmhn = &((*pmhn)->next);
+ }
+ *pmhn = other->root;
+ other->root = 0;
+}
+
+LineMarkers::~LineMarkers() {
+ for (int line = 0; line < markers.Length(); line++) {
+ delete markers[line];
+ markers[line] = 0;
+ }
+ markers.DeleteAll();
+}
+
+void LineMarkers::InsertLine(int line) {
+ if (markers.Length()) {
+ markers.Insert(line, 0);
+ }
+}
+
+void LineMarkers::RemoveLine(int line) {
+ // Retain the markers from the deleted line by oring them into the previous line
+ if (markers.Length()) {
+ if (line > 0) {
+ MergeMarkers(line - 1);
+ }
+ markers.Delete(line);
+ }
+}
+
+int LineMarkers::LineFromHandle(int markerHandle) {
+ if (markers.Length()) {
+ for (int line = 0; line < markers.Length(); line++) {
+ if (markers[line]) {
+ if (markers[line]->Contains(markerHandle)) {
+ return line;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+void LineMarkers::MergeMarkers(int pos) {
+ if (markers[pos + 1] != NULL) {
+ if (markers[pos] == NULL)
+ markers[pos] = new MarkerHandleSet;
+ markers[pos]->CombineWith(markers[pos + 1]);
+ delete markers[pos + 1];
+ markers[pos + 1] = NULL;
+ }
+}
+
+int LineMarkers::MarkValue(int line) {
+ if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
+ return markers[line]->MarkValue();
+ else
+ return 0;
+}
+
+int LineMarkers::AddMark(int line, int markerNum, int lines) {
+ handleCurrent++;
+ if (!markers.Length()) {
+ // No existing markers so allocate one element per line
+ markers.InsertValue(0, lines, 0);
+ }
+ if (!markers[line]) {
+ // Need new structure to hold marker handle
+ markers[line] = new MarkerHandleSet();
+ if (!markers[line])
+ return - 1;
+ }
+ markers[line]->InsertHandle(handleCurrent, markerNum);
+
+ return handleCurrent;
+}
+
+void LineMarkers::DeleteMark(int line, int markerNum, bool all) {
+ if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
+ if (markerNum == -1) {
+ delete markers[line];
+ markers[line] = NULL;
+ } else {
+ bool performedDeletion = markers[line]->RemoveNumber(markerNum);
+ while (all && performedDeletion) {
+ performedDeletion = markers[line]->RemoveNumber(markerNum);
+ }
+ if (markers[line]->Length() == 0) {
+ delete markers[line];
+ markers[line] = NULL;
+ }
+ }
+ }
+}
+
+void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
+ int line = LineFromHandle(markerHandle);
+ if (line >= 0) {
+ markers[line]->RemoveHandle(markerHandle);
+ if (markers[line]->Length() == 0) {
+ delete markers[line];
+ markers[line] = NULL;
+ }
+ }
+}
+
+LineLevels::~LineLevels() {
+}
+
+void LineLevels::InsertLine(int line) {
+ if (levels.Length()) {
+ int level = SC_FOLDLEVELBASE;
+ if ((line > 0) && (line < levels.Length())) {
+ level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
+ }
+ levels.InsertValue(line, 1, level);
+ }
+}
+
+void LineLevels::RemoveLine(int line) {
+ if (levels.Length()) {
+ // Move up following lines but merge header flag from this line
+ // to line before to avoid a temporary disappearence causing expansion.
+ int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
+ levels.Delete(line);
+ if (line > 0)
+ levels[line-1] |= firstHeader;
+ }
+}
+
+void LineLevels::ExpandLevels(int sizeNew) {
+ levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
+}
+
+void LineLevels::ClearLevels() {
+ levels.DeleteAll();
+}
+
+int LineLevels::SetLevel(int line, int level, int lines) {
+ int prev = 0;
+ if ((line >= 0) && (line < lines)) {
+ if (!levels.Length()) {
+ ExpandLevels(lines + 1);
+ }
+ prev = levels[line];
+ if (prev != level) {
+ levels[line] = level;
+ }
+ }
+ return prev;
+}
+
+int LineLevels::GetLevel(int line) {
+ if (levels.Length() && (line >= 0) && (line < levels.Length())) {
+ return levels[line];
+ } else {
+ return SC_FOLDLEVELBASE;
+ }
+}
+
+LineState::~LineState() {
+}
+
+void LineState::InsertLine(int line) {
+ if (lineStates.Length()) {
+ lineStates.EnsureLength(line);
+ lineStates.Insert(line, 0);
+ }
+}
+
+void LineState::RemoveLine(int line) {
+ if (lineStates.Length() > line) {
+ lineStates.Delete(line);
+ }
+}
+
+int LineState::SetLineState(int line, int state) {
+ lineStates.EnsureLength(line + 1);
+ int stateOld = lineStates[line];
+ lineStates[line] = state;
+ return stateOld;
+}
+
+int LineState::GetLineState(int line) {
+ lineStates.EnsureLength(line + 1);
+ return lineStates[line];
+}
+
+int LineState::GetMaxLineState() {
+ return lineStates.Length();
+}
+
+static int NumberLines(const char *text) {
+ if (text) {
+ int newLines = 0;
+ while (*text) {
+ if (*text == '\n')
+ newLines++;
+ text++;
+ }
+ return newLines+1;
+ } else {
+ return 0;
+ }
+}
+
+// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
+// and then has text and optional styles.
+
+static const int IndividualStyles = 0x100;
+
+struct AnnotationHeader {
+ short style; // Style IndividualStyles implies array of styles
+ short lines;
+ int length;
+};
+
+LineAnnotation::~LineAnnotation() {
+ ClearAll();
+}
+
+void LineAnnotation::InsertLine(int line) {
+ if (annotations.Length()) {
+ annotations.Insert(line, 0);
+ }
+}
+
+void LineAnnotation::RemoveLine(int line) {
+ if (annotations.Length() && (line < annotations.Length())) {
+ delete []annotations[line];
+ annotations.Delete(line);
+ }
+}
+
+bool LineAnnotation::AnySet() const {
+ return annotations.Length() > 0;
+}
+
+bool LineAnnotation::MultipleStyles(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
+ else
+ return 0;
+}
+
+int LineAnnotation::Style(int line) {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
+ else
+ return 0;
+}
+
+const char *LineAnnotation::Text(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return annotations[line]+sizeof(AnnotationHeader);
+ else
+ return 0;
+}
+
+const char *LineAnnotation::Styles(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
+ return annotations[line] + sizeof(AnnotationHeader) + Length(line);
+ else
+ return 0;
+}
+
+static char *AllocateAnnotation(int length, int style) {
+ size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
+ char *ret = new char[len];
+ memset(ret, 0, len);
+ return ret;
+}
+
+void LineAnnotation::SetText(int line, const char *text) {
+ if (text) {
+ annotations.EnsureLength(line+1);
+ int style = Style(line);
+ if (annotations[line]) {
+ delete []annotations[line];
+ }
+ annotations[line] = AllocateAnnotation(strlen(text), style);
+ AnnotationHeader *pah = reinterpret_cast<AnnotationHeader*>(annotations[line]);
+ pah->style = static_cast<short>(style);
+ pah->length = strlen(text);
+ pah->lines = static_cast<short>(NumberLines(text));
+ memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
+ } else {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
+ delete []annotations[line];
+ annotations[line] = 0;
+ }
+ }
+}
+
+void LineAnnotation::ClearAll() {
+ for (int line = 0; line < annotations.Length(); line++) {
+ delete []annotations[line];
+ annotations[line] = 0;
+ }
+ annotations.DeleteAll();
+}
+
+void LineAnnotation::SetStyle(int line, int style) {
+ annotations.EnsureLength(line+1);
+ if (!annotations[line]) {
+ annotations[line] = AllocateAnnotation(0, style);
+ }
+ reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
+}
+
+void LineAnnotation::SetStyles(int line, const char *styles) {
+ annotations.EnsureLength(line+1);
+ if (!annotations[line]) {
+ annotations[line] = AllocateAnnotation(0, IndividualStyles);
+ } else {
+ AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
+ if (pahSource->style != IndividualStyles) {
+ char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
+ AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
+ pahAlloc->length = pahSource->length;
+ pahAlloc->lines = pahSource->lines;
+ memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
+ delete []annotations[line];
+ annotations[line] = allocation;
+ }
+ }
+ AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
+ pah->style = IndividualStyles;
+ memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
+}
+
+int LineAnnotation::Length(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
+ else
+ return 0;
+}
+
+int LineAnnotation::Lines(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
+ else
+ return 0;
+}
diff --git a/src/PerLine.h b/src/PerLine.h
new file mode 100644
index 000000000..471219131
--- /dev/null
+++ b/src/PerLine.h
@@ -0,0 +1,104 @@
+// Scintilla source code edit control
+/** @file PerLine.h
+ ** Manages data associated with each line of the document
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/**
+ * This holds the marker identifier and the marker type to display.
+ * MarkerHandleNumbers are members of lists.
+ */
+struct MarkerHandleNumber {
+ int handle;
+ int number;
+ MarkerHandleNumber *next;
+};
+
+/**
+ * A marker handle set contains any number of MarkerHandleNumbers.
+ */
+class MarkerHandleSet {
+ MarkerHandleNumber *root;
+
+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);
+ void RemoveHandle(int handle);
+ bool RemoveNumber(int markerNum);
+ void CombineWith(MarkerHandleSet *other);
+};
+
+class LineMarkers : public PerLine {
+ SplitVector<MarkerHandleSet *> markers;
+ /// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
+ int handleCurrent;
+public:
+ LineMarkers() : handleCurrent(0) {
+ }
+ virtual ~LineMarkers();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ int MarkValue(int line);
+ int AddMark(int line, int marker, int lines);
+ void MergeMarkers(int pos);
+ void DeleteMark(int line, int markerNum, bool all);
+ void DeleteMarkFromHandle(int markerHandle);
+ int LineFromHandle(int markerHandle);
+};
+
+class LineLevels : public PerLine {
+ SplitVector<int> levels;
+public:
+ virtual ~LineLevels();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ void ExpandLevels(int sizeNew=-1);
+ void ClearLevels();
+ int SetLevel(int line, int level, int lines);
+ int GetLevel(int line);
+};
+
+class LineState : public PerLine {
+ SplitVector<int> lineStates;
+public:
+ LineState() {
+ }
+ virtual ~LineState();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ int SetLineState(int line, int state);
+ int GetLineState(int line);
+ int GetMaxLineState();
+};
+
+class LineAnnotation : public PerLine {
+ SplitVector<char *> annotations;
+public:
+ LineAnnotation() {
+ }
+ virtual ~LineAnnotation();
+ 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;
+ const char *Styles(int line) const;
+ void SetText(int line, const char *text);
+ void ClearAll();
+ void SetStyle(int line, int style);
+ void SetStyles(int line, const char *styles);
+ int Length(int line) const;
+ int Lines(int line) const;
+};
+
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 686862a2d..0955928b0 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -141,6 +141,9 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
extraFontFlag = source.extraFontFlag;
extraAscent = source.extraAscent;
extraDescent = source.extraDescent;
+ marginStyleOffset = source.marginStyleOffset;
+ annotationVisible = source.annotationVisible;
+ annotationStyleOffset = source.annotationStyleOffset;
}
ViewStyle::~ViewStyle() {
@@ -237,6 +240,9 @@ void ViewStyle::Init(size_t stylesSize_) {
extraFontFlag = false;
extraAscent = 0;
extraDescent = 0;
+ marginStyleOffset = 0;
+ annotationVisible = ANNOTATION_HIDDEN;
+ annotationStyleOffset = 0;
}
void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
@@ -363,3 +369,8 @@ void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
bool ViewStyle::ProtectionActive() const {
return someStylesProtected;
}
+
+bool ViewStyle::ValidStyle(size_t styleIndex) const {
+ return styleIndex < stylesSize;
+}
+
diff --git a/src/ViewStyle.h b/src/ViewStyle.h
index 3f8b856b9..5390848e5 100644
--- a/src/ViewStyle.h
+++ b/src/ViewStyle.h
@@ -104,6 +104,9 @@ public:
bool extraFontFlag;
int extraAscent;
int extraDescent;
+ int marginStyleOffset;
+ int annotationVisible;
+ int annotationStyleOffset;
ViewStyle();
ViewStyle(const ViewStyle &source);
@@ -117,6 +120,7 @@ public:
void ClearStyles();
void SetStyleFontName(int styleIndex, const char *name);
bool ProtectionActive() const;
+ bool ValidStyle(size_t styleIndex) const;
};
#ifdef SCI_NAMESPACE