scintilla: Accessible: use the built-in character position cache
It's quite a lot faster even after trying and optimizing the custom version, and it makes the code simpler. Also improve ByteOffsetFromCharacterOffset() to make use of the cache, making it drastically faster. X-Scintilla-Bug-URL: https://sourceforge.net/p/scintilla/bugs/2094/ X-Scintilla-Commit-ID: 01aab5f24e50ed14551c8c9c8ecce7ece0594c09 X-Scintilla-Commit-ID: 2c8b52af4ae5de2abe7c00fd18e78be60340cbf9 Fixes #2092.
This commit is contained in:
parent
b6a132bc12
commit
a587385de0
@ -859,7 +859,7 @@ sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
|
|||||||
if (accessible) {
|
if (accessible) {
|
||||||
ScintillaGTKAccessible *sciAccessible = ScintillaGTKAccessible::FromAccessible(accessible);
|
ScintillaGTKAccessible *sciAccessible = ScintillaGTKAccessible::FromAccessible(accessible);
|
||||||
if (sciAccessible) {
|
if (sciAccessible) {
|
||||||
sciAccessible->SetAccessibility();
|
sciAccessible->SetAccessibility(accessibilityEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -158,6 +158,7 @@ ScintillaGTKAccessible::ScintillaGTKAccessible(GtkAccessible *accessible_, GtkWi
|
|||||||
sci(ScintillaGTK::FromWidget(widget_)),
|
sci(ScintillaGTK::FromWidget(widget_)),
|
||||||
deletionLengthChar(0),
|
deletionLengthChar(0),
|
||||||
old_pos(-1) {
|
old_pos(-1) {
|
||||||
|
SetAccessibility(true);
|
||||||
g_signal_connect(widget_, "sci-notify", G_CALLBACK(SciNotify), this);
|
g_signal_connect(widget_, "sci-notify", G_CALLBACK(SciNotify), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,10 +862,12 @@ void ScintillaGTKAccessible::NotifyReadOnly() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaGTKAccessible::SetAccessibility() {
|
void ScintillaGTKAccessible::SetAccessibility(bool enabled) {
|
||||||
// Called by ScintillaGTK when application has enabled or disabled accessibility
|
// Called by ScintillaGTK when application has enabled or disabled accessibility
|
||||||
character_offsets.resize(0);
|
if (enabled)
|
||||||
character_offsets.push_back(0);
|
sci->pdoc->AllocateLineCharacterIndex(SC_LINECHARACTERINDEX_UTF32);
|
||||||
|
else
|
||||||
|
sci->pdoc->ReleaseLineCharacterIndex(SC_LINECHARACTERINDEX_UTF32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
|
void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
|
||||||
@ -872,13 +875,6 @@ void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
|
|||||||
return;
|
return;
|
||||||
switch (nt->nmhdr.code) {
|
switch (nt->nmhdr.code) {
|
||||||
case SCN_MODIFIED: {
|
case SCN_MODIFIED: {
|
||||||
if (nt->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
|
|
||||||
// invalidate character offset cache if applicable
|
|
||||||
const Sci::Line line = sci->pdoc->LineFromPosition(nt->position);
|
|
||||||
if (character_offsets.size() > static_cast<size_t>(line + 1)) {
|
|
||||||
character_offsets.resize(line + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nt->modificationType & SC_MOD_INSERTTEXT) {
|
if (nt->modificationType & SC_MOD_INSERTTEXT) {
|
||||||
int startChar = CharacterOffsetFromByteOffset(nt->position);
|
int startChar = CharacterOffsetFromByteOffset(nt->position);
|
||||||
int lengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length);
|
int lengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length);
|
||||||
|
@ -18,9 +18,6 @@ private:
|
|||||||
GtkAccessible *accessible;
|
GtkAccessible *accessible;
|
||||||
ScintillaGTK *sci;
|
ScintillaGTK *sci;
|
||||||
|
|
||||||
// cache holding character offset for each line start, see CharacterOffsetFromByteOffset()
|
|
||||||
std::vector<Sci::Position> character_offsets;
|
|
||||||
|
|
||||||
// cached length of the deletion, in characters (see Notify())
|
// cached length of the deletion, in characters (see Notify())
|
||||||
int deletionLengthChar;
|
int deletionLengthChar;
|
||||||
// local state for comparing
|
// local state for comparing
|
||||||
@ -37,6 +34,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sci::Position ByteOffsetFromCharacterOffset(Sci::Position startByte, int characterOffset) {
|
Sci::Position ByteOffsetFromCharacterOffset(Sci::Position startByte, int characterOffset) {
|
||||||
|
if (!(sci->pdoc->LineCharacterIndex() & SC_LINECHARACTERINDEX_UTF32)) {
|
||||||
|
return startByte + characterOffset;
|
||||||
|
}
|
||||||
|
if (characterOffset > 0) {
|
||||||
|
// Try and reduce the range by reverse-looking into the character offset cache
|
||||||
|
Sci::Line lineStart = sci->pdoc->LineFromPosition(startByte);
|
||||||
|
Sci::Position posStart = sci->pdoc->IndexLineStart(lineStart, SC_LINECHARACTERINDEX_UTF32);
|
||||||
|
Sci::Line line = sci->pdoc->LineFromPositionIndex(posStart + characterOffset, SC_LINECHARACTERINDEX_UTF32);
|
||||||
|
if (line != lineStart) {
|
||||||
|
startByte += sci->pdoc->LineStart(line) - sci->pdoc->LineStart(lineStart);
|
||||||
|
characterOffset -= sci->pdoc->IndexLineStart(line, SC_LINECHARACTERINDEX_UTF32) - posStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
Sci::Position pos = sci->pdoc->GetRelativePosition(startByte, characterOffset);
|
Sci::Position pos = sci->pdoc->GetRelativePosition(startByte, characterOffset);
|
||||||
if (pos == INVALID_POSITION) {
|
if (pos == INVALID_POSITION) {
|
||||||
// clamp invalid positions inside the document
|
// clamp invalid positions inside the document
|
||||||
@ -54,18 +64,12 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Sci::Position CharacterOffsetFromByteOffset(Sci::Position byteOffset) {
|
Sci::Position CharacterOffsetFromByteOffset(Sci::Position byteOffset) {
|
||||||
const Sci::Line line = sci->pdoc->LineFromPosition(byteOffset);
|
if (!(sci->pdoc->LineCharacterIndex() & SC_LINECHARACTERINDEX_UTF32)) {
|
||||||
if (character_offsets.size() <= static_cast<size_t>(line)) {
|
return byteOffset;
|
||||||
if (character_offsets.empty())
|
|
||||||
character_offsets.push_back(0);
|
|
||||||
for (Sci::Position i = character_offsets.size(); i <= line; i++) {
|
|
||||||
const Sci::Position start = sci->pdoc->LineStart(i - 1);
|
|
||||||
const Sci::Position end = sci->pdoc->LineStart(i);
|
|
||||||
character_offsets.push_back(character_offsets[i - 1] + sci->pdoc->CountCharacters(start, end));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const Sci::Line line = sci->pdoc->LineFromPosition(byteOffset);
|
||||||
const Sci::Position lineStart = sci->pdoc->LineStart(line);
|
const Sci::Position lineStart = sci->pdoc->LineStart(line);
|
||||||
return character_offsets[line] + sci->pdoc->CountCharacters(lineStart, byteOffset);
|
return sci->pdoc->IndexLineStart(line, SC_LINECHARACTERINDEX_UTF32) + sci->pdoc->CountCharacters(lineStart, byteOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterRangeFromByteRange(Sci::Position startByte, Sci::Position endByte, int *startChar, int *endChar) {
|
void CharacterRangeFromByteRange(Sci::Position startByte, Sci::Position endByte, int *startChar, int *endChar) {
|
||||||
@ -135,7 +139,7 @@ public:
|
|||||||
// So ScintillaGTK can notify us
|
// So ScintillaGTK can notify us
|
||||||
void ChangeDocument(Document *oldDoc, Document *newDoc);
|
void ChangeDocument(Document *oldDoc, Document *newDoc);
|
||||||
void NotifyReadOnly();
|
void NotifyReadOnly();
|
||||||
void SetAccessibility();
|
void SetAccessibility(bool enabled);
|
||||||
|
|
||||||
// Helper GtkWidget methods
|
// Helper GtkWidget methods
|
||||||
static AtkObject *WidgetGetAccessibleImpl(GtkWidget *widget, AtkObject **cache, gpointer widget_parent_class);
|
static AtkObject *WidgetGetAccessibleImpl(GtkWidget *widget, AtkObject **cache, gpointer widget_parent_class);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user