|
2 | 2 | using System.Buffers; |
3 | 3 | using System.Collections.Generic; |
4 | 4 | using System.Diagnostics; |
| 5 | +using System.Globalization; |
5 | 6 | using System.Text; |
6 | 7 |
|
7 | 8 | using LightTextEditorPlus.Core.Document; |
| 9 | +using LightTextEditorPlus.Core.Primitive; |
8 | 10 | using LightTextEditorPlus.Core.Primitive.Collections; |
9 | 11 | using LightTextEditorPlus.Core.Utils.TextArrayPools; |
10 | 12 |
|
@@ -177,30 +179,91 @@ public static TextReadOnlyListSpan<CharData> GetFirstCharSpanContinuous(this Tex |
177 | 179 | } |
178 | 180 |
|
179 | 181 | var count = 1; |
180 | | - var current = charList[0]; |
181 | | - for (int i = 1; i < charList.Count; i++) |
| 182 | + |
| 183 | + if (checker is null) |
182 | 184 | { |
183 | | - var next = charList[i]; |
184 | | - if (checker is null) |
| 185 | + var current = charList[0]; |
| 186 | + var currentStrongDirection = GetStrongFlowDirection(charList[0]); |
| 187 | + for (int i = 1; i < charList.Count; i++) |
185 | 188 | { |
| 189 | + var next = charList[i]; |
186 | 190 | if (!current.RunProperty.Equals(next.RunProperty)) |
187 | 191 | { |
188 | 192 | break; |
189 | 193 | } |
| 194 | + |
| 195 | + var nextStrongDirection = GetStrongFlowDirection(next); |
| 196 | + if (nextStrongDirection.HasValue) |
| 197 | + { |
| 198 | + if (currentStrongDirection.HasValue && currentStrongDirection.Value != nextStrongDirection.Value) |
| 199 | + { |
| 200 | + break; |
| 201 | + } |
| 202 | + |
| 203 | + currentStrongDirection = nextStrongDirection; |
| 204 | + } |
| 205 | + |
| 206 | + count++; |
| 207 | + current = next; |
190 | 208 | } |
191 | | - else |
| 209 | + } |
| 210 | + else |
| 211 | + { |
| 212 | + var current = charList[0]; |
| 213 | + for (int i = 1; i < charList.Count; i++) |
192 | 214 | { |
| 215 | + var next = charList[i]; |
193 | 216 | if (!checker(current, next)) |
194 | 217 | { |
195 | 218 | break; |
196 | 219 | } |
| 220 | + |
| 221 | + count++; |
| 222 | + current = next; |
197 | 223 | } |
198 | | - count++; |
199 | | - current = next; // 这步有些多余,但是为了代码的可读性,还是加上了。为什么多余?因此此时 current 必定和 next 相等 |
200 | 224 | } |
201 | 225 |
|
202 | 226 | return charList.Slice(0, count); |
203 | 227 | } |
| 228 | + |
| 229 | + /// <summary> |
| 230 | + /// 获取当前的文本方向 |
| 231 | + /// </summary> |
| 232 | + /// <param name="charData"></param> |
| 233 | + /// <returns></returns> |
| 234 | + private static FlowDirection? GetStrongFlowDirection(CharData charData) |
| 235 | + { |
| 236 | + var rune = charData.CharObject.CodePoint.Rune; |
| 237 | + UnicodeCategory category = Rune.GetUnicodeCategory(rune); |
| 238 | + |
| 239 | + if (category is not (UnicodeCategory.UppercaseLetter |
| 240 | + or UnicodeCategory.LowercaseLetter |
| 241 | + or UnicodeCategory.TitlecaseLetter |
| 242 | + or UnicodeCategory.ModifierLetter |
| 243 | + or UnicodeCategory.OtherLetter)) |
| 244 | + { |
| 245 | + return null; |
| 246 | + } |
| 247 | + |
| 248 | + return IsRightToLeftScript(charData.CharObject.CodePoint.Value) |
| 249 | + ? FlowDirection.RightToLeft |
| 250 | + : FlowDirection.LeftToRight; |
| 251 | + } |
| 252 | + |
| 253 | + /// <summary> |
| 254 | + /// 是否在从右到左范围内 |
| 255 | + /// </summary> |
| 256 | + /// <param name="codePoint"></param> |
| 257 | + /// <returns></returns> |
| 258 | + private static bool IsRightToLeftScript(int codePoint) |
| 259 | + { |
| 260 | + return codePoint is |
| 261 | + >= 0x0590 and <= 0x08FF // Hebrew, Arabic, Syriac, Thaana 等 |
| 262 | + or >= 0xFB1D and <= 0xFDFF // Hebrew/Arabic Presentation Forms-A |
| 263 | + or >= 0xFE70 and <= 0xFEFF // Arabic Presentation Forms-B |
| 264 | + or >= 0x1E900 and <= 0x1E95F // Adlam |
| 265 | + or >= 0x1EE00 and <= 0x1EEFF; // Arabic Mathematical Alphabetic Symbols |
| 266 | + } |
204 | 267 | } |
205 | 268 |
|
206 | 269 | /// <summary> |
|
0 commit comments