/src/mozilla-central/accessible/atk/DOMtoATK.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "DOMtoATK.h" |
8 | | #include "nsUTF8Utils.h" |
9 | | |
10 | | namespace mozilla { |
11 | | namespace a11y { |
12 | | |
13 | | namespace DOMtoATK { |
14 | | |
15 | | void |
16 | | AddBOMs(nsACString& aDest, const nsACString& aSource) |
17 | 0 | { |
18 | 0 | uint32_t destlength = 0; |
19 | 0 |
|
20 | 0 | // First compute how much room we will need. |
21 | 0 | for (uint32_t srci = 0; srci < aSource.Length(); ) { |
22 | 0 | int bytes = UTF8traits::bytes(aSource[srci]); |
23 | 0 | if (bytes >= 4) { |
24 | 0 | // Non-BMP character, will add a BOM after it. |
25 | 0 | destlength += 3; |
26 | 0 | } |
27 | 0 | // Skip whole character encoding. |
28 | 0 | srci += bytes; |
29 | 0 | destlength += bytes; |
30 | 0 | } |
31 | 0 |
|
32 | 0 | uint32_t desti = 0; // Index within aDest. |
33 | 0 |
|
34 | 0 | // Add BOMs after non-BMP characters. |
35 | 0 | aDest.SetLength(destlength); |
36 | 0 | for (uint32_t srci = 0; srci < aSource.Length(); ) { |
37 | 0 | uint32_t bytes = UTF8traits::bytes(aSource[srci]); |
38 | 0 |
|
39 | 0 | MOZ_ASSERT(bytes <= aSource.Length() - srci, "We should have the whole sequence"); |
40 | 0 |
|
41 | 0 | // Copy whole sequence. |
42 | 0 | aDest.Replace(desti, bytes, Substring(aSource, srci, bytes)); |
43 | 0 | desti += bytes; |
44 | 0 | srci += bytes; |
45 | 0 |
|
46 | 0 | if (bytes >= 4) { |
47 | 0 | // More than 4 bytes in UTF-8 encoding exactly means more than 16 encoded |
48 | 0 | // bits. This is thus a non-BMP character which needed a surrogate |
49 | 0 | // pair to get encoded in UTF-16, add a BOM after it. |
50 | 0 |
|
51 | 0 | // And add a BOM after it. |
52 | 0 | aDest.Replace(desti, 3, "\xEF\xBB\xBF"); |
53 | 0 | desti += 3; |
54 | 0 | } |
55 | 0 | } |
56 | 0 | MOZ_ASSERT(desti == destlength, "Incoherency between computed length" |
57 | 0 | "and actually translated length"); |
58 | 0 | } |
59 | | |
60 | | void |
61 | | ATKStringConverterHelper::AdjustOffsets(gint* aStartOffset, gint* aEndOffset, |
62 | | gint count) |
63 | 0 | { |
64 | 0 | MOZ_ASSERT(!mAdjusted, "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be called only once"); |
65 | 0 |
|
66 | 0 | if (*aStartOffset > 0) { |
67 | 0 | (*aStartOffset)--; |
68 | 0 | mStartShifted = true; |
69 | 0 | } |
70 | 0 |
|
71 | 0 | if (*aEndOffset != -1 && *aEndOffset < count) { |
72 | 0 | (*aEndOffset)++; |
73 | 0 | mEndShifted = true; |
74 | 0 | } |
75 | 0 |
|
76 | | #ifdef DEBUG |
77 | | mAdjusted = true; |
78 | | #endif |
79 | | } |
80 | | |
81 | | gchar* |
82 | | ATKStringConverterHelper::FinishUTF16toUTF8(nsCString& aStr) |
83 | 0 | { |
84 | 0 | int skip = 0; |
85 | 0 |
|
86 | 0 | if (mStartShifted) { |
87 | 0 | // AdjustOffsets added a leading character. |
88 | 0 |
|
89 | 0 | MOZ_ASSERT(aStr.Length() > 0, "There should be a leading character"); |
90 | 0 | MOZ_ASSERT(static_cast<int>(aStr.Length()) >= UTF8traits::bytes(aStr.CharAt(0)), |
91 | 0 | "The leading character should be complete"); |
92 | 0 |
|
93 | 0 | // drop first character |
94 | 0 | skip = UTF8traits::bytes(aStr.CharAt(0)); |
95 | 0 | } |
96 | 0 |
|
97 | 0 | if (mEndShifted) { |
98 | 0 | // AdjustOffsets added a trailing character. |
99 | 0 |
|
100 | 0 | MOZ_ASSERT(aStr.Length() > 0, "There should be a trailing character"); |
101 | 0 |
|
102 | 0 | int trail = -1; |
103 | 0 | // Find beginning of last character. |
104 | 0 | for (trail = aStr.Length() - 1; trail >= 0; trail--) { |
105 | 0 | if (!UTF8traits::isInSeq(aStr.CharAt(trail))) { |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | MOZ_ASSERT(trail >= 0, |
110 | 0 | "There should be at least a whole trailing character"); |
111 | 0 | MOZ_ASSERT(trail + UTF8traits::bytes(aStr.CharAt(trail)) == static_cast<int>(aStr.Length()), |
112 | 0 | "The trailing character should be complete"); |
113 | 0 |
|
114 | 0 | // Drop the last character. |
115 | 0 | aStr.Truncate(trail); |
116 | 0 | } |
117 | 0 |
|
118 | 0 | // copy and return, libspi will free it |
119 | 0 | return g_strdup(aStr.get() + skip); |
120 | 0 | } |
121 | | |
122 | | gchar* |
123 | | ATKStringConverterHelper::ConvertAdjusted(const nsAString& aStr) |
124 | 0 | { |
125 | 0 | MOZ_ASSERT(mAdjusted, "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be called before ATKStringConverterHelper::ConvertAdjusted"); |
126 | 0 |
|
127 | 0 | NS_ConvertUTF16toUTF8 cautoStr(aStr); |
128 | 0 | if (!cautoStr.get()) { |
129 | 0 | return nullptr; |
130 | 0 | } |
131 | 0 | |
132 | 0 | nsAutoCString cautoStrBOMs; |
133 | 0 | AddBOMs(cautoStrBOMs, cautoStr); |
134 | 0 | return FinishUTF16toUTF8(cautoStrBOMs); |
135 | 0 | } |
136 | | |
137 | | gchar* |
138 | | Convert(const nsAString& aStr) |
139 | 0 | { |
140 | 0 | NS_ConvertUTF16toUTF8 cautoStr(aStr); |
141 | 0 | if (!cautoStr.get()) { |
142 | 0 | return nullptr; |
143 | 0 | } |
144 | 0 | |
145 | 0 | nsAutoCString cautoStrBOMs; |
146 | 0 | AddBOMs(cautoStrBOMs, cautoStr); |
147 | 0 | return g_strdup(cautoStrBOMs.get()); |
148 | 0 | } |
149 | | |
150 | | void |
151 | | ConvertTexttoAsterisks(nsAString& aString) |
152 | 0 | { |
153 | 0 | for (uint32_t i = 0; i < aString.Length(); i++) { |
154 | 0 | aString.ReplaceLiteral(i, 1, u"*"); |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | | } |
159 | | |
160 | | } // namespace a11y |
161 | | } // namespace mozilla |