1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Minor optimisations. New method OwnedArray::insertArray(). Changed some CodeDocument inner class constructors to use references rather than pointers.

This commit is contained in:
jules 2012-07-23 07:54:23 +01:00
parent 98e37b8e7a
commit d4ae8f3d55
8 changed files with 236 additions and 235 deletions

1
.gitignore vendored
View file

@ -15,6 +15,7 @@
*.manifest.res *.manifest.res
*.o *.o
*.d *.d
*.sdf
xcuserdata xcuserdata
contents.xcworkspacedata contents.xcworkspacedata
.DS_Store .DS_Store

View file

@ -142,7 +142,7 @@ void SourceCodeEditor::highlightLine (int lineNum, int characterIndex)
editor->getDocument().getNumLines() - editor->getNumLinesOnScreen()))); editor->getDocument().getNumLines() - editor->getNumLinesOnScreen())));
} }
editor->moveCaretTo (CodeDocument::Position (&editor->getDocument(), lineNum - 1, characterIndex), false); editor->moveCaretTo (CodeDocument::Position (editor->getDocument(), lineNum - 1, characterIndex), false);
} }
void SourceCodeEditor::resized() void SourceCodeEditor::resized()

View file

@ -135,10 +135,10 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
for (int m = info.numSamples; --m >= 0;) for (int m = info.numSamples; --m >= 0;)
{ {
const float alpha = (float) subSampleOffset; const float alpha = (float) subSampleOffset;
const float invAlpha = 1.0f - alpha;
for (int channel = 0; channel < channelsToProcess; ++channel) for (int channel = 0; channel < channelsToProcess; ++channel)
*destBuffers[channel]++ = srcBuffers[channel][bufferPos] * invAlpha + srcBuffers[channel][nextPos] * alpha; *destBuffers[channel]++ = srcBuffers[channel][bufferPos]
+ alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);
subSampleOffset += localRatio; subSampleOffset += localRatio;

View file

@ -460,17 +460,17 @@ public:
{ {
const ScopedLockType lock (getLock()); const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + numberOfElements); data.ensureAllocatedSize (numUsed + numberOfElements);
ElementType* insertPos; ElementType* insertPos = data.elements;
if (isPositiveAndBelow (indexToInsertAt, numUsed)) if (isPositiveAndBelow (indexToInsertAt, numUsed))
{ {
insertPos = data.elements + indexToInsertAt; insertPos += indexToInsertAt;
const int numberToMove = numUsed - indexToInsertAt; const int numberToMove = numUsed - indexToInsertAt;
memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ElementType)); memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ElementType));
} }
else else
{ {
insertPos = data.elements + numUsed; insertPos += numUsed;
} }
numUsed += numberOfElements; numUsed += numberOfElements;

View file

@ -292,6 +292,46 @@ public:
} }
} }
/** Inserts an array of values into this array at a given position.
If the index is less than 0 or greater than the size of the array, the
new elements will be added to the end of the array.
Otherwise, they will be inserted into the array, moving all the later elements
along to make room.
@param indexToInsertAt the index at which the first new element should be inserted
@param newObjects the new values to add to the array
@param numberOfElements how many items are in the array
@see insert, add, addSorted, set
*/
void insertArray (int indexToInsertAt,
ObjectClass* const* newObjects,
int numberOfElements)
{
if (numberOfElements > 0)
{
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + numberOfElements);
ObjectClass** insertPos = data.elements;
if (isPositiveAndBelow (indexToInsertAt, numUsed))
{
insertPos += indexToInsertAt;
const int numberToMove = numUsed - indexToInsertAt;
memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ObjectClass*));
}
else
{
insertPos += numUsed;
}
numUsed += numberOfElements;
while (--numberOfElements >= 0)
*insertPos++ = *newObjects++;
}
}
/** Appends a new object at the end of the array as long as the array doesn't /** Appends a new object at the end of the array as long as the array doesn't
already contain it. already contain it.

View file

@ -123,15 +123,15 @@ public:
}; };
//============================================================================== //==============================================================================
CodeDocument::Iterator::Iterator (CodeDocument* const document_) CodeDocument::Iterator::Iterator (const CodeDocument& document_) noexcept
: document (document_), : document (&document_),
charPointer (nullptr), charPointer (nullptr),
line (0), line (0),
position (0) position (0)
{ {
} }
CodeDocument::Iterator::Iterator (const CodeDocument::Iterator& other) CodeDocument::Iterator::Iterator (const CodeDocument::Iterator& other) noexcept
: document (other.document), : document (other.document),
charPointer (other.charPointer), charPointer (other.charPointer),
line (other.line), line (other.line),
@ -153,13 +153,13 @@ CodeDocument::Iterator::~Iterator() noexcept
{ {
} }
juce_wchar CodeDocument::Iterator::nextChar() juce_wchar CodeDocument::Iterator::nextChar() noexcept
{ {
for (;;) for (;;)
{ {
if (charPointer.getAddress() == nullptr) if (charPointer.getAddress() == nullptr)
{ {
CodeDocumentLine* const l = document->lines[line]; const CodeDocumentLine* const l = document->lines[line];
if (l == nullptr) if (l == nullptr)
return 0; return 0;
@ -182,16 +182,16 @@ juce_wchar CodeDocument::Iterator::nextChar()
} }
} }
void CodeDocument::Iterator::skip() void CodeDocument::Iterator::skip() noexcept
{ {
nextChar(); nextChar();
} }
void CodeDocument::Iterator::skipToEndOfLine() void CodeDocument::Iterator::skipToEndOfLine() noexcept
{ {
if (charPointer.getAddress() == nullptr) if (charPointer.getAddress() == nullptr)
{ {
CodeDocumentLine* const l = document->lines[line]; const CodeDocumentLine* const l = document->lines[line];
if (l == nullptr) if (l == nullptr)
return; return;
@ -204,11 +204,11 @@ void CodeDocument::Iterator::skipToEndOfLine()
charPointer = nullptr; charPointer = nullptr;
} }
juce_wchar CodeDocument::Iterator::peekNextChar() const juce_wchar CodeDocument::Iterator::peekNextChar() const noexcept
{ {
if (charPointer.getAddress() == nullptr) if (charPointer.getAddress() == nullptr)
{ {
CodeDocumentLine* const l = document->lines[line]; const CodeDocumentLine* const l = document->lines[line];
if (l == nullptr) if (l == nullptr)
return 0; return 0;
@ -221,11 +221,11 @@ juce_wchar CodeDocument::Iterator::peekNextChar() const
if (c != 0) if (c != 0)
return c; return c;
CodeDocumentLine* const l = document->lines [line + 1]; const CodeDocumentLine* const l = document->lines [line + 1];
return l == nullptr ? 0 : l->line[0]; return l == nullptr ? 0 : l->line[0];
} }
void CodeDocument::Iterator::skipWhitespace() void CodeDocument::Iterator::skipWhitespace() noexcept
{ {
while (CharacterFunctions::isWhitespace (peekNextChar())) while (CharacterFunctions::isWhitespace (peekNextChar()))
skip(); skip();
@ -238,23 +238,22 @@ bool CodeDocument::Iterator::isEOF() const noexcept
//============================================================================== //==============================================================================
CodeDocument::Position::Position() noexcept CodeDocument::Position::Position() noexcept
: owner (0), characterPos (0), line (0), : owner (nullptr), characterPos (0), line (0),
indexInLine (0), positionMaintained (false) indexInLine (0), positionMaintained (false)
{ {
} }
CodeDocument::Position::Position (const CodeDocument* const ownerDocument, CodeDocument::Position::Position (const CodeDocument& ownerDocument,
const int line_, const int indexInLine_) noexcept const int line_, const int indexInLine_) noexcept
: owner (const_cast <CodeDocument*> (ownerDocument)), : owner (const_cast <CodeDocument*> (&ownerDocument)),
characterPos (0), line (line_), characterPos (0), line (line_),
indexInLine (indexInLine_), positionMaintained (false) indexInLine (indexInLine_), positionMaintained (false)
{ {
setLineAndIndex (line_, indexInLine_); setLineAndIndex (line_, indexInLine_);
} }
CodeDocument::Position::Position (const CodeDocument* const ownerDocument, CodeDocument::Position::Position (const CodeDocument& ownerDocument, const int characterPos_) noexcept
const int characterPos_) noexcept : owner (const_cast <CodeDocument*> (&ownerDocument)),
: owner (const_cast <CodeDocument*> (ownerDocument)),
positionMaintained (false) positionMaintained (false)
{ {
setPosition (characterPos_); setPosition (characterPos_);
@ -324,25 +323,22 @@ void CodeDocument::Position::setLineAndIndex (const int newLineNum, const int ne
{ {
line = owner->lines.size() - 1; line = owner->lines.size() - 1;
CodeDocumentLine* const l = owner->lines.getUnchecked (line); const CodeDocumentLine& l = *owner->lines.getUnchecked (line);
jassert (l != nullptr); indexInLine = l.lineLengthWithoutNewLines;
characterPos = l.lineStartInFile + indexInLine;
indexInLine = l->lineLengthWithoutNewLines;
characterPos = l->lineStartInFile + indexInLine;
} }
else else
{ {
line = jmax (0, newLineNum); line = jmax (0, newLineNum);
CodeDocumentLine* const l = owner->lines.getUnchecked (line); const CodeDocumentLine& l = *owner->lines.getUnchecked (line);
jassert (l != nullptr);
if (l->lineLengthWithoutNewLines > 0) if (l.lineLengthWithoutNewLines > 0)
indexInLine = jlimit (0, l->lineLengthWithoutNewLines, newIndexInLine); indexInLine = jlimit (0, l.lineLengthWithoutNewLines, newIndexInLine);
else else
indexInLine = 0; indexInLine = 0;
characterPos = l->lineStartInFile + indexInLine; characterPos = l.lineStartInFile + indexInLine;
} }
} }
} }
@ -366,15 +362,14 @@ void CodeDocument::Position::setPosition (const int newPosition)
{ {
for (int i = lineStart; i < lineEnd; ++i) for (int i = lineStart; i < lineEnd; ++i)
{ {
CodeDocumentLine* const l = owner->lines.getUnchecked (i); const CodeDocumentLine& l = *owner->lines.getUnchecked (i);
const int index = newPosition - l.lineStartInFile;
int index = newPosition - l->lineStartInFile; if (index >= 0 && (index < l.lineLength || i == lineEnd - 1))
if (index >= 0 && (index < l->lineLength || i == lineEnd - 1))
{ {
line = i; line = i;
indexInLine = jmin (l->lineLengthWithoutNewLines, index); indexInLine = jmin (l.lineLengthWithoutNewLines, index);
characterPos = l->lineStartInFile + indexInLine; characterPos = l.lineStartInFile + indexInLine;
} }
} }
@ -383,9 +378,8 @@ void CodeDocument::Position::setPosition (const int newPosition)
else else
{ {
const int midIndex = (lineStart + lineEnd + 1) / 2; const int midIndex = (lineStart + lineEnd + 1) / 2;
CodeDocumentLine* const mid = owner->lines.getUnchecked (midIndex);
if (newPosition >= mid->lineStartInFile) if (newPosition >= owner->lines.getUnchecked (midIndex)->lineStartInFile)
lineStart = midIndex; lineStart = midIndex;
else else
lineEnd = midIndex; lineEnd = midIndex;
@ -405,9 +399,10 @@ void CodeDocument::Position::moveBy (int characterDelta)
// If moving right, make sure we don't get stuck between the \r and \n characters.. // If moving right, make sure we don't get stuck between the \r and \n characters..
if (line < owner->lines.size()) if (line < owner->lines.size())
{ {
CodeDocumentLine* const l = owner->lines.getUnchecked (line); const CodeDocumentLine& l = *owner->lines.getUnchecked (line);
if (indexInLine + characterDelta < l->lineLength
&& indexInLine + characterDelta >= l->lineLengthWithoutNewLines + 1) if (indexInLine + characterDelta < l.lineLength
&& indexInLine + characterDelta >= l.lineLengthWithoutNewLines + 1)
++characterDelta; ++characterDelta;
} }
} }
@ -415,21 +410,21 @@ void CodeDocument::Position::moveBy (int characterDelta)
setPosition (characterPos + characterDelta); setPosition (characterPos + characterDelta);
} }
const CodeDocument::Position CodeDocument::Position::movedBy (const int characterDelta) const CodeDocument::Position CodeDocument::Position::movedBy (const int characterDelta) const
{ {
CodeDocument::Position p (*this); CodeDocument::Position p (*this);
p.moveBy (characterDelta); p.moveBy (characterDelta);
return p; return p;
} }
const CodeDocument::Position CodeDocument::Position::movedByLines (const int deltaLines) const CodeDocument::Position CodeDocument::Position::movedByLines (const int deltaLines) const
{ {
CodeDocument::Position p (*this); CodeDocument::Position p (*this);
p.setLineAndIndex (getLineNumber() + deltaLines, getIndexInLine()); p.setLineAndIndex (getLineNumber() + deltaLines, getIndexInLine());
return p; return p;
} }
const juce_wchar CodeDocument::Position::getCharacter() const juce_wchar CodeDocument::Position::getCharacter() const
{ {
const CodeDocumentLine* const l = owner->lines [line]; const CodeDocumentLine* const l = owner->lines [line];
return l == nullptr ? 0 : l->line [getIndexInLine()]; return l == nullptr ? 0 : l->line [getIndexInLine()];
@ -480,8 +475,8 @@ CodeDocument::~CodeDocument()
String CodeDocument::getAllContent() const String CodeDocument::getAllContent() const
{ {
return getTextBetween (Position (this, 0), return getTextBetween (Position (*this, 0),
Position (this, lines.size(), 0)); Position (*this, lines.size(), 0));
} }
String CodeDocument::getTextBetween (const Position& start, const Position& end) const String CodeDocument::getTextBetween (const Position& start, const Position& end) const
@ -505,22 +500,22 @@ String CodeDocument::getTextBetween (const Position& start, const Position& end)
for (int i = jmax (0, startLine); i <= maxLine; ++i) for (int i = jmax (0, startLine); i <= maxLine; ++i)
{ {
const CodeDocumentLine* line = lines.getUnchecked(i); const CodeDocumentLine& line = *lines.getUnchecked(i);
int len = line->lineLength; int len = line.lineLength;
if (i == startLine) if (i == startLine)
{ {
const int index = start.getIndexInLine(); const int index = start.getIndexInLine();
mo << line->line.substring (index, len); mo << line.line.substring (index, len);
} }
else if (i == endLine) else if (i == endLine)
{ {
len = end.getIndexInLine(); len = end.getIndexInLine();
mo << line->line.substring (0, len); mo << line.line.substring (0, len);
} }
else else
{ {
mo << line->line; mo << line.line;
} }
} }
@ -736,20 +731,13 @@ void CodeDocument::checkLastLineStatus()
} }
//============================================================================== //==============================================================================
void CodeDocument::addListener (CodeDocument::Listener* const listener) noexcept void CodeDocument::addListener (CodeDocument::Listener* const l) noexcept { listeners.add (l); }
{ void CodeDocument::removeListener (CodeDocument::Listener* const l) noexcept { listeners.remove (l); }
listeners.add (listener);
}
void CodeDocument::removeListener (CodeDocument::Listener* const listener) noexcept
{
listeners.remove (listener);
}
void CodeDocument::sendListenerChangeMessage (const int startLine, const int endLine) void CodeDocument::sendListenerChangeMessage (const int startLine, const int endLine)
{ {
Position startPos (this, startLine, 0); Position startPos (*this, startLine, 0);
Position endPos (this, endLine, 0); Position endPos (*this, endLine, 0);
listeners.call (&CodeDocument::Listener::codeDocumentChanged, startPos, endPos); listeners.call (&CodeDocument::Listener::codeDocumentChanged, startPos, endPos);
} }
@ -758,10 +746,8 @@ void CodeDocument::sendListenerChangeMessage (const int startLine, const int end
class CodeDocumentInsertAction : public UndoableAction class CodeDocumentInsertAction : public UndoableAction
{ {
public: public:
CodeDocumentInsertAction (CodeDocument& owner_, const String& text_, const int insertPos_) noexcept CodeDocumentInsertAction (CodeDocument& doc, const String& t, const int pos) noexcept
: owner (owner_), : owner (doc), text (t), insertPos (pos)
text (text_),
insertPos (insertPos_)
{ {
} }
@ -784,77 +770,72 @@ public:
private: private:
CodeDocument& owner; CodeDocument& owner;
const String text; const String text;
int insertPos; const int insertPos;
JUCE_DECLARE_NON_COPYABLE (CodeDocumentInsertAction); JUCE_DECLARE_NON_COPYABLE (CodeDocumentInsertAction);
}; };
void CodeDocument::insert (const String& text, const int insertPos, const bool undoable) void CodeDocument::insert (const String& text, const int insertPos, const bool undoable)
{ {
if (text.isEmpty()) if (text.isNotEmpty())
return;
if (undoable)
{ {
undoManager.perform (new CodeDocumentInsertAction (*this, text, insertPos)); if (undoable)
}
else
{
Position pos (this, insertPos);
const int firstAffectedLine = pos.getLineNumber();
int lastAffectedLine = firstAffectedLine + 1;
CodeDocumentLine* const firstLine = lines [firstAffectedLine];
String textInsideOriginalLine (text);
if (firstLine != nullptr)
{ {
const int index = pos.getIndexInLine(); undoManager.perform (new CodeDocumentInsertAction (*this, text, insertPos));
textInsideOriginalLine = firstLine->line.substring (0, index)
+ textInsideOriginalLine
+ firstLine->line.substring (index);
} }
else
maximumLineLength = -1;
Array <CodeDocumentLine*> newLines;
CodeDocumentLine::createLines (newLines, textInsideOriginalLine);
jassert (newLines.size() > 0);
CodeDocumentLine* const newFirstLine = newLines.getUnchecked (0);
newFirstLine->lineStartInFile = firstLine != nullptr ? firstLine->lineStartInFile : 0;
lines.set (firstAffectedLine, newFirstLine);
if (newLines.size() > 1)
{ {
for (int i = 1; i < newLines.size(); ++i) Position pos (*this, insertPos);
const int firstAffectedLine = pos.getLineNumber();
int lastAffectedLine = firstAffectedLine + 1;
CodeDocumentLine* const firstLine = lines [firstAffectedLine];
String textInsideOriginalLine (text);
if (firstLine != nullptr)
{ {
CodeDocumentLine* const l = newLines.getUnchecked (i); const int index = pos.getIndexInLine();
lines.insert (firstAffectedLine + i, l); textInsideOriginalLine = firstLine->line.substring (0, index)
+ textInsideOriginalLine
+ firstLine->line.substring (index);
} }
lastAffectedLine = lines.size(); maximumLineLength = -1;
Array <CodeDocumentLine*> newLines;
CodeDocumentLine::createLines (newLines, textInsideOriginalLine);
jassert (newLines.size() > 0);
CodeDocumentLine* const newFirstLine = newLines.getUnchecked (0);
newFirstLine->lineStartInFile = firstLine != nullptr ? firstLine->lineStartInFile : 0;
lines.set (firstAffectedLine, newFirstLine);
if (newLines.size() > 1)
{
lines.insertArray (firstAffectedLine + 1, newLines.getRawDataPointer() + 1, newLines.size() - 1);
lastAffectedLine = lines.size();
}
int lineStart = newFirstLine->lineStartInFile;
for (int i = firstAffectedLine; i < lines.size(); ++i)
{
CodeDocumentLine& l = *lines.getUnchecked (i);
l.lineStartInFile = lineStart;
lineStart += l.lineLength;
}
checkLastLineStatus();
const int newTextLength = text.length();
for (int i = 0; i < positionsToMaintain.size(); ++i)
{
CodeDocument::Position& p = *positionsToMaintain.getUnchecked(i);
if (p.getPosition() >= insertPos)
p.setPosition (p.getPosition() + newTextLength);
}
sendListenerChangeMessage (firstAffectedLine, lastAffectedLine);
} }
int i, lineStart = newFirstLine->lineStartInFile;
for (i = firstAffectedLine; i < lines.size(); ++i)
{
CodeDocumentLine* const l = lines.getUnchecked (i);
l->lineStartInFile = lineStart;
lineStart += l->lineLength;
}
checkLastLineStatus();
const int newTextLength = text.length();
for (i = 0; i < positionsToMaintain.size(); ++i)
{
CodeDocument::Position* const p = positionsToMaintain.getUnchecked(i);
if (p->getPosition() >= insertPos)
p->setPosition (p->getPosition() + newTextLength);
}
sendListenerChangeMessage (firstAffectedLine, lastAffectedLine);
} }
} }
@ -862,13 +843,11 @@ void CodeDocument::insert (const String& text, const int insertPos, const bool u
class CodeDocumentDeleteAction : public UndoableAction class CodeDocumentDeleteAction : public UndoableAction
{ {
public: public:
CodeDocumentDeleteAction (CodeDocument& owner_, const int startPos_, const int endPos_) noexcept CodeDocumentDeleteAction (CodeDocument& doc, const int start, const int end) noexcept
: owner (owner_), : owner (doc), startPos (start), endPos (end),
startPos (startPos_), removedText (doc.getTextBetween (CodeDocument::Position (doc, start),
endPos (endPos_) CodeDocument::Position (doc, end)))
{ {
removedText = owner.getTextBetween (CodeDocument::Position (&owner, startPos),
CodeDocument::Position (&owner, endPos));
} }
bool perform() bool perform()
@ -885,12 +864,12 @@ public:
return true; return true;
} }
int getSizeInUnits() { return removedText.length() + 32; } int getSizeInUnits() { return (endPos - startPos) + 32; }
private: private:
CodeDocument& owner; CodeDocument& owner;
int startPos, endPos; const int startPos, endPos;
String removedText; const String removedText;
JUCE_DECLARE_NON_COPYABLE (CodeDocumentDeleteAction); JUCE_DECLARE_NON_COPYABLE (CodeDocumentDeleteAction);
}; };
@ -906,57 +885,55 @@ void CodeDocument::remove (const int startPos, const int endPos, const bool undo
} }
else else
{ {
Position startPosition (this, startPos); Position startPosition (*this, startPos);
Position endPosition (this, endPos); Position endPosition (*this, endPos);
maximumLineLength = -1; maximumLineLength = -1;
const int firstAffectedLine = startPosition.getLineNumber(); const int firstAffectedLine = startPosition.getLineNumber();
const int endLine = endPosition.getLineNumber(); const int endLine = endPosition.getLineNumber();
int lastAffectedLine = firstAffectedLine + 1; int lastAffectedLine = firstAffectedLine + 1;
CodeDocumentLine* const firstLine = lines.getUnchecked (firstAffectedLine); CodeDocumentLine& firstLine = *lines.getUnchecked (firstAffectedLine);
if (firstAffectedLine == endLine) if (firstAffectedLine == endLine)
{ {
firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) firstLine.line = firstLine.line.substring (0, startPosition.getIndexInLine())
+ firstLine->line.substring (endPosition.getIndexInLine()); + firstLine.line.substring (endPosition.getIndexInLine());
firstLine->updateLength(); firstLine.updateLength();
} }
else else
{ {
lastAffectedLine = lines.size(); lastAffectedLine = lines.size();
CodeDocumentLine* const lastLine = lines.getUnchecked (endLine); CodeDocumentLine& lastLine = *lines.getUnchecked (endLine);
jassert (lastLine != nullptr);
firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) firstLine.line = firstLine.line.substring (0, startPosition.getIndexInLine())
+ lastLine->line.substring (endPosition.getIndexInLine()); + lastLine.line.substring (endPosition.getIndexInLine());
firstLine->updateLength(); firstLine.updateLength();
int numLinesToRemove = endLine - firstAffectedLine; int numLinesToRemove = endLine - firstAffectedLine;
lines.removeRange (firstAffectedLine + 1, numLinesToRemove); lines.removeRange (firstAffectedLine + 1, numLinesToRemove);
} }
int i; for (int i = firstAffectedLine + 1; i < lines.size(); ++i)
for (i = firstAffectedLine + 1; i < lines.size(); ++i)
{ {
CodeDocumentLine* const l = lines.getUnchecked (i); CodeDocumentLine& l = *lines.getUnchecked (i);
const CodeDocumentLine* const previousLine = lines.getUnchecked (i - 1); const CodeDocumentLine& previousLine = *lines.getUnchecked (i - 1);
l->lineStartInFile = previousLine->lineStartInFile + previousLine->lineLength; l.lineStartInFile = previousLine.lineStartInFile + previousLine.lineLength;
} }
checkLastLineStatus(); checkLastLineStatus();
const int totalChars = getNumCharacters(); const int totalChars = getNumCharacters();
for (i = 0; i < positionsToMaintain.size(); ++i) for (int i = 0; i < positionsToMaintain.size(); ++i)
{ {
CodeDocument::Position* p = positionsToMaintain.getUnchecked(i); CodeDocument::Position& p = *positionsToMaintain.getUnchecked(i);
if (p->getPosition() > startPosition.getPosition()) if (p.getPosition() > startPosition.getPosition())
p->setPosition (jmax (startPos, p->getPosition() + startPos - endPos)); p.setPosition (jmax (startPos, p.getPosition() + startPos - endPos));
if (p->getPosition() > totalChars) if (p.getPosition() > totalChars)
p->setPosition (totalChars); p.setPosition (totalChars);
} }
sendListenerChangeMessage (firstAffectedLine, lastAffectedLine); sendListenerChangeMessage (firstAffectedLine, lastAffectedLine);

View file

@ -77,7 +77,7 @@ public:
Lines are numbered from zero, and if the line or index are beyond the bounds of the document, Lines are numbered from zero, and if the line or index are beyond the bounds of the document,
they will be adjusted to keep them within its limits. they will be adjusted to keep them within its limits.
*/ */
Position (const CodeDocument* ownerDocument, Position (const CodeDocument& ownerDocument,
int line, int indexInLine) noexcept; int line, int indexInLine) noexcept;
/** Creates a position based on a character index in a document. /** Creates a position based on a character index in a document.
@ -87,7 +87,7 @@ public:
If the position is beyond the range of the document, it'll be adjusted to keep it If the position is beyond the range of the document, it'll be adjusted to keep it
inside. inside.
*/ */
Position (const CodeDocument* ownerDocument, Position (const CodeDocument& ownerDocument,
int charactersFromStartOfDocument) noexcept; int charactersFromStartOfDocument) noexcept;
/** Creates a copy of another position. /** Creates a copy of another position.
@ -101,6 +101,7 @@ public:
~Position(); ~Position();
Position& operator= (const Position& other); Position& operator= (const Position& other);
bool operator== (const Position& other) const noexcept; bool operator== (const Position& other) const noexcept;
bool operator!= (const Position& other) const noexcept; bool operator!= (const Position& other) const noexcept;
@ -159,18 +160,18 @@ public:
characters. characters.
@see moveBy @see moveBy
*/ */
const Position movedBy (int characterDelta) const; Position movedBy (int characterDelta) const;
/** Returns a position which is the same as this one, moved up or down by the specified /** Returns a position which is the same as this one, moved up or down by the specified
number of lines. number of lines.
@see movedBy @see movedBy
*/ */
const Position movedByLines (int deltaLines) const; Position movedByLines (int deltaLines) const;
/** Returns the character in the document at this position. /** Returns the character in the document at this position.
@see getLineText @see getLineText
*/ */
const juce_wchar getCharacter() const; juce_wchar getCharacter() const;
/** Returns the line from the document that this position is within. /** Returns the line from the document that this position is within.
@see getCharacter, getLineNumber @see getCharacter, getLineNumber
@ -334,32 +335,30 @@ public:
class JUCE_API Iterator class JUCE_API Iterator
{ {
public: public:
Iterator (CodeDocument* document); Iterator (const CodeDocument& document) noexcept;
Iterator (const Iterator& other); Iterator (const Iterator& other) noexcept;
Iterator& operator= (const Iterator& other) noexcept; Iterator& operator= (const Iterator& other) noexcept;
~Iterator() noexcept; ~Iterator() noexcept;
/** Reads the next character and returns it. /** Reads the next character and returns it.
@see peekNextChar @see peekNextChar
*/ */
juce_wchar nextChar(); juce_wchar nextChar() noexcept;
/** Reads the next character without advancing the current position. */ /** Reads the next character without advancing the current position. */
juce_wchar peekNextChar() const; juce_wchar peekNextChar() const noexcept;
/** Advances the position by one character. */ /** Advances the position by one character. */
void skip(); void skip() noexcept;
/** Returns the position of the next character as its position within the /** Returns the position as the number of characters from the start of the document. */
whole document.
*/
int getPosition() const noexcept { return position; } int getPosition() const noexcept { return position; }
/** Skips over any whitespace characters until the next character is non-whitespace. */ /** Skips over any whitespace characters until the next character is non-whitespace. */
void skipWhitespace(); void skipWhitespace() noexcept;
/** Skips forward until the next character will be the first character on the next line */ /** Skips forward until the next character will be the first character on the next line */
void skipToEndOfLine(); void skipToEndOfLine() noexcept;
/** Returns the line number of the next character. */ /** Returns the line number of the next character. */
int getLine() const noexcept { return line; } int getLine() const noexcept { return line; }
@ -368,7 +367,7 @@ public:
bool isEOF() const noexcept; bool isEOF() const noexcept;
private: private:
CodeDocument* document; const CodeDocument* document;
mutable String::CharPointerType charPointer; mutable String::CharPointerType charPointer;
int line, position; int line, position;
}; };

View file

@ -45,7 +45,7 @@ public:
} }
else if (lineNum < document.getNumLines()) else if (lineNum < document.getNumLines())
{ {
const CodeDocument::Position pos (&document, lineNum, 0); const CodeDocument::Position pos (document, lineNum, 0);
createTokens (pos.getPosition(), pos.getLineText(), createTokens (pos.getPosition(), pos.getLineText(),
source, *tokeniser, newTokens); source, *tokeniser, newTokens);
} }
@ -59,7 +59,7 @@ public:
{ {
const String line (document.getLine (lineNum)); const String line (document.getLine (lineNum));
CodeDocument::Position lineStart (&document, lineNum, 0), lineEnd (&document, lineNum + 1, 0); CodeDocument::Position lineStart (document, lineNum, 0), lineEnd (document, lineNum + 1, 0);
newHighlightStart = indexToColumn (jmax (0, selectionStart.getPosition() - lineStart.getPosition()), newHighlightStart = indexToColumn (jmax (0, selectionStart.getPosition() - lineStart.getPosition()),
line, spacesPerTab); line, spacesPerTab);
newHighlightEnd = indexToColumn (jmin (lineEnd.getPosition() - lineStart.getPosition(), selectionEnd.getPosition() - lineStart.getPosition()), newHighlightEnd = indexToColumn (jmin (lineEnd.getPosition() - lineStart.getPosition(), selectionEnd.getPosition() - lineStart.getPosition()),
@ -71,24 +71,9 @@ public:
highlightColumnStart = newHighlightStart; highlightColumnStart = newHighlightStart;
highlightColumnEnd = newHighlightEnd; highlightColumnEnd = newHighlightEnd;
} }
else else if (tokens == newTokens)
{ {
if (tokens.size() == newTokens.size()) return false;
{
bool allTheSame = true;
for (int i = newTokens.size(); --i >= 0;)
{
if (tokens.getReference(i) != newTokens.getReference(i))
{
allTheSame = false;
break;
}
}
if (allTheSame)
return false;
}
} }
tokens.swapWithArray (newTokens); tokens.swapWithArray (newTokens);
@ -144,14 +129,14 @@ public:
private: private:
struct SyntaxToken struct SyntaxToken
{ {
SyntaxToken (const String& text_, const int type) noexcept SyntaxToken (const String& t, const int type) noexcept
: text (text_), tokenType (type), width (-1.0f) : text (t), tokenType (type), width (-1.0f)
{ {
} }
bool operator!= (const SyntaxToken& other) const noexcept bool operator== (const SyntaxToken& other) const noexcept
{ {
return text != other.text || tokenType != other.tokenType; return tokenType == other.tokenType && text == other.text;
} }
String text; String text;
@ -321,13 +306,13 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& document_,
horizontalScrollBar (false), horizontalScrollBar (false),
codeTokeniser (codeTokeniser_) codeTokeniser (codeTokeniser_)
{ {
caretPos = CodeDocument::Position (&document_, 0, 0); caretPos = CodeDocument::Position (document_, 0, 0);
caretPos.setPositionMaintained (true); caretPos.setPositionMaintained (true);
selectionStart = CodeDocument::Position (&document_, 0, 0); selectionStart = CodeDocument::Position (document_, 0, 0);
selectionStart.setPositionMaintained (true); selectionStart.setPositionMaintained (true);
selectionEnd = CodeDocument::Position (&document_, 0, 0); selectionEnd = CodeDocument::Position (document_, 0, 0);
selectionEnd.setPositionMaintained (true); selectionEnd.setPositionMaintained (true);
setOpaque (true); setOpaque (true);
@ -509,8 +494,8 @@ void CodeEditorComponent::rebuildLineTokens()
jassert (numNeeded == lines.size()); jassert (numNeeded == lines.size());
CodeDocument::Iterator source (&document); CodeDocument::Iterator source (document);
getIteratorForPosition (CodeDocument::Position (&document, firstLineOnScreen, 0).getPosition(), source); getIteratorForPosition (CodeDocument::Position (document, firstLineOnScreen, 0).getPosition(), source);
for (int i = 0; i < numNeeded; ++i) for (int i = 0; i < numNeeded; ++i)
{ {
@ -686,7 +671,7 @@ CodeDocument::Position CodeEditorComponent::getPositionAt (int x, int y)
const int column = roundToInt ((x - (getGutterSize() - xOffset * charWidth)) / charWidth); const int column = roundToInt ((x - (getGutterSize() - xOffset * charWidth)) / charWidth);
const int index = columnToIndex (line, column); const int index = columnToIndex (line, column);
return CodeDocument::Position (&document, line, index); return CodeDocument::Position (document, line, index);
} }
//============================================================================== //==============================================================================
@ -727,25 +712,25 @@ void CodeEditorComponent::insertTabAtCaret()
bool CodeEditorComponent::deleteWhitespaceBackwardsToTabStop() bool CodeEditorComponent::deleteWhitespaceBackwardsToTabStop()
{ {
if (! getHighlightedRegion().isEmpty()) if (getHighlightedRegion().isEmpty())
return false;
for (;;)
{ {
const int currentColumn = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine()); for (;;)
{
const int currentColumn = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine());
if (currentColumn <= 0 || (currentColumn % spacesPerTab) == 0) if (currentColumn <= 0 || (currentColumn % spacesPerTab) == 0)
break; break;
moveCaretLeft (false, true); moveCaretLeft (false, true);
} }
const String selected (getTextInRange (getHighlightedRegion())); const String selected (getTextInRange (getHighlightedRegion()));
if (selected.isNotEmpty() && selected.trim().isEmpty()) if (selected.isNotEmpty() && selected.trim().isEmpty())
{ {
cut(); cut();
return true; return true;
}
} }
return false; return false;
@ -776,8 +761,8 @@ void CodeEditorComponent::indentSelectedLines (const int spacesToAdd)
if (nonWhitespaceStart > 0 || lineText.trimStart().isNotEmpty()) if (nonWhitespaceStart > 0 || lineText.trimStart().isNotEmpty())
{ {
const CodeDocument::Position wsStart (&document, line, 0); const CodeDocument::Position wsStart (document, line, 0);
const CodeDocument::Position wsEnd (&document, line, nonWhitespaceStart); const CodeDocument::Position wsEnd (document, line, nonWhitespaceStart);
const int numLeadingSpaces = indexToColumn (line, wsEnd.getIndexInLine()); const int numLeadingSpaces = indexToColumn (line, wsEnd.getIndexInLine());
const int newNumLeadingSpaces = jmax (0, numLeadingSpaces + spacesToAdd); const int newNumLeadingSpaces = jmax (0, numLeadingSpaces + spacesToAdd);
@ -803,7 +788,6 @@ void CodeEditorComponent::cut()
bool CodeEditorComponent::copyToClipboard() bool CodeEditorComponent::copyToClipboard()
{ {
newTransaction(); newTransaction();
const String selection (document.getTextBetween (selectionStart, selectionEnd)); const String selection (document.getTextBetween (selectionStart, selectionEnd));
if (selection.isNotEmpty()) if (selection.isNotEmpty())
@ -876,7 +860,7 @@ bool CodeEditorComponent::moveCaretDown (const bool selecting)
newTransaction(); newTransaction();
if (caretPos.getLineNumber() == document.getNumLines() - 1) if (caretPos.getLineNumber() == document.getNumLines() - 1)
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting);
else else
moveLineDelta (1, selecting); moveLineDelta (1, selecting);
@ -888,7 +872,7 @@ bool CodeEditorComponent::moveCaretUp (const bool selecting)
newTransaction(); newTransaction();
if (caretPos.getLineNumber() == 0) if (caretPos.getLineNumber() == 0)
moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); moveCaretTo (CodeDocument::Position (document, 0, 0), selecting);
else else
moveLineDelta (-1, selecting); moveLineDelta (-1, selecting);
@ -936,7 +920,7 @@ bool CodeEditorComponent::scrollDown()
bool CodeEditorComponent::moveCaretToTop (const bool selecting) bool CodeEditorComponent::moveCaretToTop (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); moveCaretTo (CodeDocument::Position (document, 0, 0), selecting);
return true; return true;
} }
@ -949,21 +933,21 @@ bool CodeEditorComponent::moveCaretToStartOfLine (const bool selecting)
if (index >= caretPos.getIndexInLine() && caretPos.getIndexInLine() > 0) if (index >= caretPos.getIndexInLine() && caretPos.getIndexInLine() > 0)
index = 0; index = 0;
moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), index), selecting); moveCaretTo (CodeDocument::Position (document, caretPos.getLineNumber(), index), selecting);
return true; return true;
} }
bool CodeEditorComponent::moveCaretToEnd (const bool selecting) bool CodeEditorComponent::moveCaretToEnd (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), selecting);
return true; return true;
} }
bool CodeEditorComponent::moveCaretToEndOfLine (const bool selecting) bool CodeEditorComponent::moveCaretToEndOfLine (const bool selecting)
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), std::numeric_limits<int>::max()), selecting); moveCaretTo (CodeDocument::Position (document, caretPos.getLineNumber(), std::numeric_limits<int>::max()), selecting);
return true; return true;
} }
@ -1031,8 +1015,8 @@ bool CodeEditorComponent::deleteForwards (const bool moveInWholeWordSteps)
bool CodeEditorComponent::selectAll() bool CodeEditorComponent::selectAll()
{ {
newTransaction(); newTransaction();
moveCaretTo (CodeDocument::Position (&document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), false); moveCaretTo (CodeDocument::Position (document, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()), false);
moveCaretTo (CodeDocument::Position (&document, 0, 0), true); moveCaretTo (CodeDocument::Position (document, 0, 0), true);
return true; return true;
} }
@ -1070,14 +1054,14 @@ Range<int> CodeEditorComponent::getHighlightedRegion() const
void CodeEditorComponent::setHighlightedRegion (const Range<int>& newRange) void CodeEditorComponent::setHighlightedRegion (const Range<int>& newRange)
{ {
moveCaretTo (CodeDocument::Position (&document, newRange.getStart()), false); moveCaretTo (CodeDocument::Position (document, newRange.getStart()), false);
moveCaretTo (CodeDocument::Position (&document, newRange.getEnd()), true); moveCaretTo (CodeDocument::Position (document, newRange.getEnd()), true);
} }
String CodeEditorComponent::getTextInRange (const Range<int>& range) const String CodeEditorComponent::getTextInRange (const Range<int>& range) const
{ {
return document.getTextBetween (CodeDocument::Position (&document, range.getStart()), return document.getTextBetween (CodeDocument::Position (document, range.getStart()),
CodeDocument::Position (&document, range.getEnd())); CodeDocument::Position (document, range.getEnd()));
} }
//============================================================================== //==============================================================================
@ -1379,7 +1363,7 @@ void CodeEditorComponent::updateCachedIterators (int maxLineNum)
const int linesBetweenCachedSources = jmax (10, document.getNumLines() / maxNumCachedPositions); const int linesBetweenCachedSources = jmax (10, document.getNumLines() / maxNumCachedPositions);
if (cachedIterators.size() == 0) if (cachedIterators.size() == 0)
cachedIterators.add (new CodeDocument::Iterator (&document)); cachedIterators.add (new CodeDocument::Iterator (document));
if (codeTokeniser != nullptr) if (codeTokeniser != nullptr)
{ {
@ -1458,8 +1442,8 @@ CodeEditorComponent::State::State (const State& other) noexcept
void CodeEditorComponent::State::restoreState (CodeEditorComponent& editor) const void CodeEditorComponent::State::restoreState (CodeEditorComponent& editor) const
{ {
editor.moveCaretTo (CodeDocument::Position (&editor.getDocument(), lastSelectionEnd), false); editor.moveCaretTo (CodeDocument::Position (editor.getDocument(), lastSelectionEnd), false);
editor.moveCaretTo (CodeDocument::Position (&editor.getDocument(), lastCaretPos), true); editor.moveCaretTo (CodeDocument::Position (editor.getDocument(), lastCaretPos), true);
if (lastTopLine > 0 && lastTopLine < editor.getDocument().getNumLines()) if (lastTopLine > 0 && lastTopLine < editor.getDocument().getNumLines())
editor.scrollToLine (lastTopLine); editor.scrollToLine (lastTopLine);