diff options
author | nyamatongwe <unknown> | 2009-04-12 09:32:53 +0000 |
---|---|---|
committer | nyamatongwe <unknown> | 2009-04-12 09:32:53 +0000 |
commit | 01355323d119b4c7b74d11f5012099813afa3031 (patch) | |
tree | 20390b4aacfaa851b870a4236d2d33bf40f9c65c /src | |
parent | 001550a0de196eca314eea792bfada74a19773b1 (diff) | |
download | scintilla-mirror-01355323d119b4c7b74d11f5012099813afa3031.tar.gz |
Annotations and text margins added.
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.cxx | 164 | ||||
-rw-r--r-- | src/Document.h | 47 | ||||
-rw-r--r-- | src/Editor.cxx | 375 | ||||
-rw-r--r-- | src/Editor.h | 5 | ||||
-rw-r--r-- | src/PerLine.cxx | 464 | ||||
-rw-r--r-- | src/PerLine.h | 104 | ||||
-rw-r--r-- | src/ViewStyle.cxx | 11 | ||||
-rw-r--r-- | src/ViewStyle.h | 4 |
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 |