aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/EditView.cxx60
-rw-r--r--src/EditView.h9
-rw-r--r--src/Editor.cxx27
-rw-r--r--src/PerLine.cxx70
-rw-r--r--src/PerLine.h17
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