summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llkeywords.cpp52
-rw-r--r--indra/llui/llkeywords.h8
-rw-r--r--indra/newview/llscripteditor.cpp132
-rw-r--r--indra/newview/llscripteditor.h28
4 files changed, 204 insertions, 16 deletions
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index 0ada54df06..8c34e4ab9c 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -828,29 +828,41 @@ void LLKeywords::collectSegmentOps(segment_ops_t& ops, const LLWString& wtext, b
}
}
-void LLKeywords::applySegmentOps(std::vector<LLTextSegmentPtr> *seg_list,
- const LLWString& wtext,
- const segment_ops_t& ops,
- LLTextEditor& editor,
- LLStyleConstSP style)
+bool LLKeywords::applySegmentOpsRange(std::vector<LLTextSegmentPtr> *seg_list,
+ const LLWString& wtext,
+ const segment_ops_t& ops,
+ size_t& op_index,
+ size_t max_ops,
+ LLTextEditor& editor,
+ LLStyleConstSP style)
{
if (wtext.empty())
{
- return;
+ return true;
}
- // Clear the segment list
- seg_list->clear();
- // Reserve capacity for segments based on an estimated average of 8 characters per segment.
- constexpr size_t AVERAGE_SEGMENT_LENGTH = 8;
- seg_list->reserve(wtext.size() / AVERAGE_SEGMENT_LENGTH);
+ if (op_index == 0)
+ {
+ // Clear the segment list
+ seg_list->clear();
+ // Reserve capacity for segments based on an estimated average of 8 characters per segment.
+ constexpr size_t AVERAGE_SEGMENT_LENGTH = 8;
+ seg_list->reserve(wtext.size() / AVERAGE_SEGMENT_LENGTH);
- S32 text_len = static_cast<S32>(wtext.size()) + 1;
+ S32 text_len = static_cast<S32>(wtext.size()) + 1;
+ seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) );
+ }
- seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) );
+ S32 text_len = static_cast<S32>(wtext.size()) + 1;
+ size_t end_index = op_index + max_ops;
+ if (end_index > ops.size())
+ {
+ end_index = ops.size();
+ }
- for (const auto& op : ops)
+ for (; op_index < end_index; ++op_index)
{
+ const auto& op = ops[op_index];
if (op.type == SegmentOp::OP_LINE_BREAK)
{
LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, op.start);
@@ -862,6 +874,18 @@ void LLKeywords::applySegmentOps(std::vector<LLTextSegmentPtr> *seg_list,
insertSegments(wtext, *seg_list, op.token, text_len, op.start, op.end, style, editor);
}
}
+
+ return op_index >= ops.size();
+}
+
+void LLKeywords::applySegmentOps(std::vector<LLTextSegmentPtr> *seg_list,
+ const LLWString& wtext,
+ const segment_ops_t& ops,
+ LLTextEditor& editor,
+ LLStyleConstSP style)
+{
+ size_t op_index = 0;
+ applySegmentOpsRange(seg_list, wtext, ops, op_index, ops.size(), editor, style);
}
// Walk through a string, applying the rules specified by the keyword token list and
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index b8689a0e88..70fc2c20d5 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -37,6 +37,7 @@
#include <list>
#include <deque>
#include <vector>
+#include <cstddef>
#include "llpointer.h"
class LLTextSegment;
@@ -144,6 +145,13 @@ public:
const segment_ops_t& ops,
class LLTextEditor& editor,
LLStyleConstSP style);
+ bool applySegmentOpsRange(std::vector<LLTextSegmentPtr> *seg_list,
+ const LLWString& text,
+ const segment_ops_t& ops,
+ size_t& op_index,
+ size_t max_ops,
+ class LLTextEditor& editor,
+ LLStyleConstSP style);
void initialize(LLSD SyntaxXML, bool luau_language = false);
void processTokens();
diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp
index 871210ea6d..93244107ca 100644
--- a/indra/newview/llscripteditor.cpp
+++ b/indra/newview/llscripteditor.cpp
@@ -32,6 +32,7 @@
#include "lllocalcliprect.h"
#include "llviewercontrol.h"
#include "llworkerthread.h"
+#include <algorithm>
#include <utility>
static LLWorkerThread& getSyntaxWorkerThread()
@@ -186,7 +187,12 @@ private:
return;
}
- mEditor->applySyntaxSegments(result.text, result.ops);
+ mEditor->queueSyntaxApply(std::move(result.text),
+ std::move(result.ops),
+ result.text_generation,
+ result.keywords_generation,
+ result.disable_highlight,
+ result.keywords);
}
LLScriptEditor* mEditor;
@@ -219,7 +225,14 @@ LLScriptEditor::LLScriptEditor(const Params& p)
mLastQueuedKeywordsGeneration(0),
mLastQueuedDisableHighlight(false),
mLastQueuedKeywords(nullptr),
- mSyntaxWorker(nullptr)
+ mSyntaxWorker(nullptr),
+ mSyntaxApplyState(SyntaxApplyState::Idle),
+ mPendingApplyOpIndex(0),
+ mPendingApplySegmentIndex(0),
+ mPendingApplyTextGeneration(-1),
+ mPendingApplyKeywordsGeneration(0),
+ mPendingApplyDisableHighlight(false),
+ mPendingApplyKeywords(nullptr)
{
if (mShowLineNumbers)
{
@@ -339,6 +352,7 @@ void LLScriptEditor::loadKeywords()
LL_PROFILE_ZONE_SCOPED;
ensureSyntaxWorker();
mSyntaxWorker->waitForIdle(true);
+ resetPendingSyntaxApply();
getKeywords().processTokens();
++mKeywordsGeneration;
@@ -367,6 +381,7 @@ void LLScriptEditor::updateSegments()
{
queueSyntaxParse();
}
+ processPendingSyntaxApply();
}
LLTextBase::updateSegments();
@@ -410,6 +425,119 @@ void LLScriptEditor::queueSyntaxParse()
mSyntaxWorker->queueRequest(request);
}
+void LLScriptEditor::queueSyntaxApply(LLWString text,
+ LLKeywords::segment_ops_t ops,
+ S32 text_generation,
+ U32 keywords_generation,
+ bool disable_highlight,
+ LLKeywords* keywords)
+{
+ if (text_generation != getTextGeneration()
+ || keywords_generation != mKeywordsGeneration
+ || keywords != &getKeywords())
+ {
+ return;
+ }
+
+ resetPendingSyntaxApply();
+
+ constexpr size_t kImmediateOpsThreshold = 500;
+ if (ops.size() <= kImmediateOpsThreshold)
+ {
+ applySyntaxSegments(text, ops);
+ return;
+ }
+
+ mPendingApplyText = std::move(text);
+ mPendingApplyOps = std::move(ops);
+ mPendingApplyTextGeneration = text_generation;
+ mPendingApplyKeywordsGeneration = keywords_generation;
+ mPendingApplyDisableHighlight = disable_highlight;
+ mPendingApplyKeywords = keywords;
+ mPendingApplyOpIndex = 0;
+ mPendingApplySegmentIndex = 0;
+ mPendingApplySegments.clear();
+ mPendingApplySegmentSet.clear();
+ mPendingApplyStyle = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
+ mSyntaxApplyState = SyntaxApplyState::Building;
+}
+
+void LLScriptEditor::processPendingSyntaxApply()
+{
+ if (mSyntaxApplyState == SyntaxApplyState::Idle)
+ {
+ return;
+ }
+
+ static LLCachedControl<bool> sDisableSyntaxHighlighting(gSavedSettings, "ScriptEditorDisableSyntaxHighlight", false);
+ if (mPendingApplyTextGeneration != getTextGeneration()
+ || mPendingApplyKeywordsGeneration != mKeywordsGeneration
+ || mPendingApplyKeywords != &getKeywords()
+ || mPendingApplyDisableHighlight != sDisableSyntaxHighlighting)
+ {
+ resetPendingSyntaxApply();
+ return;
+ }
+
+ constexpr size_t kOpsPerSlice = 250;
+ constexpr size_t kSegmentsPerSlice = 250;
+
+ if (mSyntaxApplyState == SyntaxApplyState::Building)
+ {
+ if (mPendingApplyStyle.isNull())
+ {
+ mPendingApplyStyle = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
+ }
+ bool done = getKeywords().applySegmentOpsRange(&mPendingApplySegments,
+ mPendingApplyText,
+ mPendingApplyOps,
+ mPendingApplyOpIndex,
+ kOpsPerSlice,
+ *this,
+ mPendingApplyStyle);
+ if (done)
+ {
+ mSyntaxApplyState = SyntaxApplyState::Inserting;
+ }
+ return;
+ }
+
+ size_t end_index = std::min(mPendingApplySegmentIndex + kSegmentsPerSlice, mPendingApplySegments.size());
+ for (; mPendingApplySegmentIndex < end_index; ++mPendingApplySegmentIndex)
+ {
+ LLTextSegmentPtr segment = mPendingApplySegments[mPendingApplySegmentIndex];
+ segment->linkToDocument(this);
+ mPendingApplySegmentSet.insert(segment);
+ }
+
+ if (mPendingApplySegmentIndex >= mPendingApplySegments.size())
+ {
+ S32 saved_scroll_index = mScrollIndex;
+ segment_set_t old_segments;
+ old_segments.swap(mSegments);
+ mSegments.swap(mPendingApplySegmentSet);
+ mScrollIndex = saved_scroll_index;
+ needsReflow(0);
+ resetPendingSyntaxApply();
+ }
+}
+
+void LLScriptEditor::resetPendingSyntaxApply()
+{
+ mSyntaxApplyState = SyntaxApplyState::Idle;
+ mPendingApplyText.clear();
+ mPendingApplyOps.clear();
+ mPendingApplySegments.clear();
+ mPendingApplySegmentSet.clear();
+ mPendingApplyOpIndex = 0;
+ mPendingApplySegmentIndex = 0;
+ mPendingApplyStyle = LLStyleConstSP();
+ mPendingApplyTextGeneration = -1;
+ mPendingApplyKeywordsGeneration = 0;
+ mPendingApplyDisableHighlight = false;
+ mPendingApplyKeywords = nullptr;
+}
+
void LLScriptEditor::applySyntaxSegments(const LLWString& text, const LLKeywords::segment_ops_t& ops)
{
LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
diff --git a/indra/newview/llscripteditor.h b/indra/newview/llscripteditor.h
index 1ca26fbcc9..dcbfdf3085 100644
--- a/indra/newview/llscripteditor.h
+++ b/indra/newview/llscripteditor.h
@@ -29,6 +29,7 @@
#define LL_SCRIPTEDITOR_H
#include "lltexteditor.h"
+#include <cstddef>
class LLScriptEditor : public LLTextEditor
{
@@ -64,14 +65,29 @@ public:
protected:
friend class LLUICtrlFactory;
+ friend class LLScriptEditorSyntaxWorker;
LLScriptEditor(const Params& p);
private:
+ enum class SyntaxApplyState
+ {
+ Idle,
+ Building,
+ Inserting
+ };
void drawLineNumbers();
void updateSegments() override;
void drawSelectionBackground() override;
void ensureSyntaxWorker();
void queueSyntaxParse();
+ void queueSyntaxApply(LLWString text,
+ LLKeywords::segment_ops_t ops,
+ S32 text_generation,
+ U32 keywords_generation,
+ bool disable_highlight,
+ LLKeywords* keywords);
+ void processPendingSyntaxApply();
+ void resetPendingSyntaxApply();
LLKeywords mKeywordsLua;
LLKeywords mKeywordsLSL;
@@ -85,6 +101,18 @@ private:
bool mLastQueuedDisableHighlight;
LLKeywords* mLastQueuedKeywords;
class LLScriptEditorSyntaxWorker* mSyntaxWorker;
+ SyntaxApplyState mSyntaxApplyState;
+ LLWString mPendingApplyText;
+ LLKeywords::segment_ops_t mPendingApplyOps;
+ segment_vec_t mPendingApplySegments;
+ segment_set_t mPendingApplySegmentSet;
+ size_t mPendingApplyOpIndex;
+ size_t mPendingApplySegmentIndex;
+ LLStyleConstSP mPendingApplyStyle;
+ S32 mPendingApplyTextGeneration;
+ U32 mPendingApplyKeywordsGeneration;
+ bool mPendingApplyDisableHighlight;
+ LLKeywords* mPendingApplyKeywords;
};
#endif // LL_SCRIPTEDITOR_H