diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/EditView.cxx | 60 | ||||
-rw-r--r-- | src/EditView.h | 9 | ||||
-rw-r--r-- | src/Editor.cxx | 27 | ||||
-rw-r--r-- | src/PerLine.cxx | 70 | ||||
-rw-r--r-- | src/PerLine.h | 17 |
5 files changed, 181 insertions, 2 deletions
diff --git a/src/EditView.cxx b/src/EditView.cxx index b033c7cf6..c46a0fbcf 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -29,6 +29,7 @@ #include "RunStyles.h" #include "ContractionState.h" #include "CellBuffer.h" +#include "PerLine.h" #include "KeyMap.h" #include "Indicator.h" #include "XPM.h" @@ -170,6 +171,7 @@ void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRec const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues EditView::EditView() { + ldTabstops = NULL; hideSelection = false; drawOverstrikeCaret = true; bufferedDraw = true; @@ -185,6 +187,11 @@ EditView::EditView() { posCache.SetSize(0x400); } +EditView::~EditView() { + delete ldTabstops; + ldTabstops = NULL; +} + bool EditView::SetTwoPhaseDraw(bool twoPhaseDraw) { const PhasesDraw phasesDrawNew = twoPhaseDraw ? phasesTwo : phasesOne; const bool redraw = phasesDraw != phasesDrawNew; @@ -203,6 +210,54 @@ bool EditView::LinesOverlap() const { return phasesDraw == phasesMultiple; } +void EditView::ClearAllTabstops() { + delete ldTabstops; + ldTabstops = 0; +} + +int EditView::NextTabstopPos(int line, int x, int tabWidth) const { + int next = GetNextTabstop(line, x); + if (next > 0) + return next; + return ((((x + 2) / tabWidth) + 1) * tabWidth); +} + +bool EditView::ClearTabstops(int line) { + LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops); + return lt && lt->ClearTabstops(line); +} + +bool EditView::AddTabstop(int line, int x) { + if (!ldTabstops) { + ldTabstops = new LineTabstops(); + } + LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops); + return lt && lt->AddTabstop(line, x); +} + +int EditView::GetNextTabstop(int line, int x) const { + LineTabstops *lt = static_cast<LineTabstops *>(ldTabstops); + if (lt) { + return lt->GetNextTabstop(line, x); + } else { + return 0; + } +} + +void EditView::LinesAddedOrRemoved(int lineOfPos, int linesAdded) { + if (ldTabstops) { + if (linesAdded > 0) { + for (int line = lineOfPos; line < lineOfPos + linesAdded; line++) { + ldTabstops->InsertLine(line); + } + } else { + for (int line = (lineOfPos + -linesAdded) - 1; line >= lineOfPos; line--) { + ldTabstops->RemoveLine(line); + } + } + } +} + void EditView::DropGraphics(bool freeObjects) { if (freeObjects) { delete pixmapLine; @@ -397,8 +452,9 @@ void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, co XYPOSITION representationWidth = vstyle.controlCharWidth; if (ll->chars[ts.start] == '\t') { // Tab is a special case of representation, taking a variable amount of space - representationWidth = - ((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start]; + const int x = static_cast<int>(ll->positions[ts.start]); + const int tabWidth = static_cast<int>(vstyle.tabWidth); + representationWidth = static_cast<XYPOSITION>(NextTabstopPos(line, x, tabWidth) - ll->positions[ts.start]); } else { if (representationWidth <= 0.0) { XYPOSITION positionsRepr[256]; // Should expand when needed diff --git a/src/EditView.h b/src/EditView.h index 7d64aff90..18451104f 100644 --- a/src/EditView.h +++ b/src/EditView.h @@ -48,6 +48,7 @@ void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRec class EditView { public: PrintParameters printParameters; + PerLine *ldTabstops; bool hideSelection; bool drawOverstrikeCaret; @@ -78,11 +79,19 @@ public: PositionCache posCache; EditView(); + virtual ~EditView(); bool SetTwoPhaseDraw(bool twoPhaseDraw); bool SetPhasesDraw(int phases); bool LinesOverlap() const; + void ClearAllTabstops(); + int NextTabstopPos(int line, int x, int tabWidth) const; + bool ClearTabstops(int line); + bool AddTabstop(int line, int x); + int GetNextTabstop(int line, int x) const; + void LinesAddedOrRemoved(int lineOfPos, int linesAdded); + void DropGraphics(bool freeObjects); void AllocateGraphics(const ViewStyle &vsDraw); void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); diff --git a/src/Editor.cxx b/src/Editor.cxx index 7fb849114..1c1e38d65 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -29,6 +29,7 @@ #include "RunStyles.h" #include "ContractionState.h" #include "CellBuffer.h" +#include "PerLine.h" #include "KeyMap.h" #include "Indicator.h" #include "XPM.h" @@ -1987,6 +1988,9 @@ void Editor::ClearAll() { pdoc->MarginClearAll(); } } + + view.ClearAllTabstops(); + sel.Clear(); SetTopLine(0); SetVerticalScrollPos(); @@ -2457,6 +2461,9 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { Redraw(); } } + if (mh.modificationType & SC_MOD_CHANGETABSTOPS) { + Redraw(); + } if (mh.modificationType & SC_MOD_LEXERSTATE) { if (paintState == painting) { CheckForChangeOutsidePaint( @@ -2520,6 +2527,7 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { } else { cs.DeleteLines(lineOfPos, -mh.linesAdded); } + view.LinesAddedOrRemoved(lineOfPos, mh.linesAdded); } if (mh.modificationType & SC_MOD_CHANGEANNOTATION) { int lineDoc = pdoc->LineFromPosition(mh.position); @@ -4813,6 +4821,8 @@ void Editor::SetDocPointer(Document *document) { view.llc.Deallocate(); NeedWrapping(); + view.ClearAllTabstops(); + pdoc->AddWatcher(this, 0); SetScrollBars(); Redraw(); @@ -5983,6 +5993,23 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETTABWIDTH: return pdoc->tabInChars; + case SCI_CLEARTABSTOPS: + if (view.ClearTabstops(static_cast<int>(wParam))) { + DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast<int>(wParam)); + NotifyModified(pdoc, mh, NULL); + } + break; + + case SCI_ADDTABSTOP: + if (view.AddTabstop(static_cast<int>(wParam), static_cast<int>(lParam))) { + DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast<int>(wParam)); + NotifyModified(pdoc, mh, NULL); + } + break; + + case SCI_GETNEXTTABSTOP: + return view.GetNextTabstop(static_cast<int>(wParam), static_cast<int>(lParam)); + case SCI_SETINDENT: pdoc->indentInChars = static_cast<int>(wParam); if (pdoc->indentInChars != 0) diff --git a/src/PerLine.cxx b/src/PerLine.cxx index 8b0dbc44b..8fd96cbed 100644 --- a/src/PerLine.cxx +++ b/src/PerLine.cxx @@ -7,6 +7,7 @@ #include <string.h> +#include <vector> #include <algorithm> #include "Platform.h" @@ -484,3 +485,72 @@ int LineAnnotation::Lines(int line) const { else return 0; } + +LineTabstops::~LineTabstops() { + Init(); +} + +void LineTabstops::Init() { + for (int line = 0; line < tabstops.Length(); line++) { + delete tabstops[line]; + } + tabstops.DeleteAll(); +} + +void LineTabstops::InsertLine(int line) { + if (tabstops.Length()) { + tabstops.EnsureLength(line); + tabstops.Insert(line, 0); + } +} + +void LineTabstops::RemoveLine(int line) { + if (tabstops.Length() > line) { + delete tabstops[line]; + tabstops.Delete(line); + } +} + +bool LineTabstops::ClearTabstops(int line) { + if (line < tabstops.Length()) { + TabstopList *tl = tabstops[line]; + if (tl) { + tl->clear(); + return true; + } + } + return false; +} + +bool LineTabstops::AddTabstop(int line, int x) { + tabstops.EnsureLength(line + 1); + if (!tabstops[line]) { + tabstops[line] = new TabstopList(); + } + + TabstopList *tl = tabstops[line]; + if (tl) { + // tabstop positions are kept in order - insert in the right place + std::vector<int>::iterator it = std::lower_bound(tl->begin(), tl->end(), x); + // don't insert duplicates + if (it == tl->end() || *it != x) { + tl->insert(it, x); + return true; + } + } + return false; +} + +int LineTabstops::GetNextTabstop(int line, int x) const { + if (line < tabstops.Length()) { + TabstopList *tl = tabstops[line]; + if (tl) { + for (size_t i = 0; i < tl->size(); i++) { + if ((*tl)[i] > x) { + return (*tl)[i]; + } + } + } + } + return 0; +} diff --git a/src/PerLine.h b/src/PerLine.h index 70d0023e4..4bf1c88fd 100644 --- a/src/PerLine.h +++ b/src/PerLine.h @@ -112,6 +112,23 @@ public: int Lines(int line) const; }; +typedef std::vector<int> TabstopList; + +class LineTabstops : public PerLine { + SplitVector<TabstopList *> tabstops; +public: + LineTabstops() { + } + virtual ~LineTabstops(); + virtual void Init(); + virtual void InsertLine(int line); + virtual void RemoveLine(int line); + + bool ClearTabstops(int line); + bool AddTabstop(int line, int x); + int GetNextTabstop(int line, int x) const; +}; + #ifdef SCI_NAMESPACE } #endif |