summaryrefslogtreecommitdiffstats
path: root/accessible/atk/DOMtoATK.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/atk/DOMtoATK.cpp')
-rw-r--r--accessible/atk/DOMtoATK.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/accessible/atk/DOMtoATK.cpp b/accessible/atk/DOMtoATK.cpp
new file mode 100644
index 0000000000..2c23731bba
--- /dev/null
+++ b/accessible/atk/DOMtoATK.cpp
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DOMtoATK.h"
+#include "nsUTF8Utils.h"
+
+namespace mozilla {
+namespace a11y {
+
+namespace DOMtoATK {
+
+void AddBOMs(nsACString& aDest, const nsACString& aSource) {
+ uint32_t destlength = 0;
+
+ // First compute how much room we will need.
+ for (uint32_t srci = 0; srci < aSource.Length();) {
+ int bytes = UTF8traits::bytes(aSource[srci]);
+ if (bytes >= 4) {
+ // Non-BMP character, will add a BOM after it.
+ destlength += 3;
+ }
+ // Skip whole character encoding.
+ srci += bytes;
+ destlength += bytes;
+ }
+
+ uint32_t desti = 0; // Index within aDest.
+
+ // Add BOMs after non-BMP characters.
+ aDest.SetLength(destlength);
+ for (uint32_t srci = 0; srci < aSource.Length();) {
+ uint32_t bytes = UTF8traits::bytes(aSource[srci]);
+
+ MOZ_ASSERT(bytes <= aSource.Length() - srci,
+ "We should have the whole sequence");
+
+ // Copy whole sequence.
+ aDest.Replace(desti, bytes, Substring(aSource, srci, bytes));
+ desti += bytes;
+ srci += bytes;
+
+ if (bytes >= 4) {
+ // More than 4 bytes in UTF-8 encoding exactly means more than 16 encoded
+ // bits. This is thus a non-BMP character which needed a surrogate
+ // pair to get encoded in UTF-16, add a BOM after it.
+
+ // And add a BOM after it.
+ aDest.Replace(desti, 3, "\xEF\xBB\xBF");
+ desti += 3;
+ }
+ }
+ MOZ_ASSERT(desti == destlength,
+ "Incoherency between computed length"
+ "and actually translated length");
+}
+
+void ATKStringConverterHelper::AdjustOffsets(gint* aStartOffset,
+ gint* aEndOffset, gint count) {
+ MOZ_ASSERT(!mAdjusted,
+ "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
+ "called only once");
+
+ if (*aStartOffset > 0) {
+ (*aStartOffset)--;
+ mStartShifted = true;
+ }
+
+ if (*aEndOffset >= 0 && *aEndOffset < count) {
+ (*aEndOffset)++;
+ mEndShifted = true;
+ }
+
+#ifdef DEBUG
+ mAdjusted = true;
+#endif
+}
+
+gchar* ATKStringConverterHelper::FinishUTF16toUTF8(nsCString& aStr) {
+ int skip = 0;
+
+ if (mStartShifted) {
+ // AdjustOffsets added a leading character.
+
+ MOZ_ASSERT(aStr.Length() > 0, "There should be a leading character");
+ MOZ_ASSERT(
+ static_cast<int>(aStr.Length()) >= UTF8traits::bytes(aStr.CharAt(0)),
+ "The leading character should be complete");
+
+ // drop first character
+ skip = UTF8traits::bytes(aStr.CharAt(0));
+ }
+
+ if (mEndShifted) {
+ // AdjustOffsets added a trailing character.
+
+ MOZ_ASSERT(aStr.Length() > 0, "There should be a trailing character");
+
+ int trail = -1;
+ // Find beginning of last character.
+ for (trail = aStr.Length() - 1; trail >= 0; trail--) {
+ if (!UTF8traits::isInSeq(aStr.CharAt(trail))) {
+ break;
+ }
+ }
+ MOZ_ASSERT(trail >= 0,
+ "There should be at least a whole trailing character");
+ MOZ_ASSERT(trail + UTF8traits::bytes(aStr.CharAt(trail)) ==
+ static_cast<int>(aStr.Length()),
+ "The trailing character should be complete");
+
+ // Drop the last character.
+ aStr.Truncate(trail);
+ }
+
+ // copy and return, libspi will free it
+ return g_strdup(aStr.get() + skip);
+}
+
+gchar* ATKStringConverterHelper::ConvertAdjusted(const nsAString& aStr) {
+ MOZ_ASSERT(mAdjusted,
+ "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be "
+ "called before ATKStringConverterHelper::ConvertAdjusted");
+
+ NS_ConvertUTF16toUTF8 cautoStr(aStr);
+ if (!cautoStr.get()) {
+ return nullptr;
+ }
+
+ nsAutoCString cautoStrBOMs;
+ AddBOMs(cautoStrBOMs, cautoStr);
+ return FinishUTF16toUTF8(cautoStrBOMs);
+}
+
+gchar* Convert(const nsAString& aStr) {
+ NS_ConvertUTF16toUTF8 cautoStr(aStr);
+ if (!cautoStr.get()) {
+ return nullptr;
+ }
+
+ nsAutoCString cautoStrBOMs;
+ AddBOMs(cautoStrBOMs, cautoStr);
+ return g_strdup(cautoStrBOMs.get());
+}
+
+} // namespace DOMtoATK
+
+} // namespace a11y
+} // namespace mozilla