コード例 #1
0
        /// <summary>
        /// 返回指定字符的宽度,字符串遍历的顺序是从后至前的。
        /// </summary>
        /// <param name="ch">要获取宽度的字符。</param>
        /// <returns><paramref name="ch"/> 的宽度。</returns>
        private int GetWidthReversed(char ch)
        {
            if (!char.IsSurrogate(ch))
            {
                return(ch.Width());
            }
            if (char.IsLowSurrogate(ch))
            {
                surrogate = ch;
                return(0);
            }
            // ch 是高代理项
            if (surrogate == NoSurrogate)
            {
                // 缺失相应低代理项,忽略无效数据。
                return(0);
            }
            var chValue = char.ConvertToUtf32(ch, surrogate);

            surrogate = NoSurrogate;
            return(CharExt.Width(chValue));
        }
コード例 #2
0
        /// <summary>
        /// 返回指定字符的宽度。
        /// </summary>
        /// <param name="ch">要获取宽度的字符。</param>
        /// <returns><paramref name="ch"/> 的宽度。</returns>
        private int GetWidth(char ch)
        {
            if (!char.IsSurrogate(ch))
            {
                return(ch.Width());
            }
            if (char.IsHighSurrogate(ch))
            {
                surrogate = ch;
                return(0);
            }
            // ch 是低代理项
            if (surrogate == NoSurrogate)
            {
                // 缺失相应高代理项,忽略无效数据。
                return(0);
            }
            var chValue = char.ConvertToUtf32(surrogate, ch);

            surrogate = NoSurrogate;
            return(CharExt.Width(chValue));
        }
コード例 #3
0
        /// <summary>
        /// 令位置前进指定字符指针所指的部分。
        /// </summary>
        /// <param name="start">要前进的起始字符指针(包含)。</param>
        /// <param name="end">要前进的结束字符指针(包含)。</param>
        /// <remarks>不会修改 <c>curIndex</c> 属性。</remarks>
        private unsafe void ForwardInternal(char *start, char *end)
        {
            Contract.Requires(end > start);
            Contract.Requires(widths.Count == 0);
            var oldHighSurrogate = surrogate;

            surrogate = NoSurrogate;
            // 最后一个字符需要特殊考虑,否则无法得到当前位置。
            var lastWidth = 0;
            var lastChar  = *end--;

            if (!char.IsHighSurrogate(lastChar))
            {
                if (lastChar == '\n')
                {
                    lastWidth = -1;
                }
                else if (lastChar == '\t')
                {
                    lastWidth = -2;
                }
                else if (char.IsLowSurrogate(lastChar))
                {
                    if (char.IsHighSurrogate(*end))
                    {
                        // 匹配的代理项对。
                        lastWidth = CharExt.Width(char.ConvertToUtf32(*end, lastChar));
                        end--;
                    }
                }
                else
                {
                    lastWidth = lastChar.Width();
                }
                lastChar = NoSurrogate;
            }
            curCol  = nextCol;
            curLine = nextLine;
            var width = 0;

            for (; end >= start; end--)
            {
                if (*end == '\n')
                {
                    widths.Add(width);
                    oldHighSurrogate = NoSurrogate;
                    // 统计之前的行数。
                    curCol = 1;
                    curLine++;
                    for (; end >= start; end--)
                    {
                        if (*end == '\n')
                        {
                            curLine++;
                        }
                    }
                    break;
                }
                if (*end == '\t')
                {
                    widths.Add(width);
                    width = 0;
                }
                else
                {
                    width += GetWidthReversed(*end);
                }
            }
            if (oldHighSurrogate != NoSurrogate)
            {
                width += GetWidthReversed(oldHighSurrogate);
            }
            if (width > 0)
            {
                widths.Add(width);
            }
            // 统计列数。
            for (var j = widths.Count - 1; j > 0; j--)
            {
                curCol += widths[j];
                curCol  = ForwardTab(curCol);
            }
            surrogate = lastChar;
            curCol   += widths[0];
            widths.Clear();
            nextLine = curLine;
            if (lastWidth >= 0)
            {
                nextCol = curCol + lastWidth;
            }
            else if (lastWidth == -1)
            {
                nextCol = 1;
                nextLine++;
            }
            else
            {
                nextCol = ForwardTab(curCol);
            }
        }
コード例 #4
0
ファイル: UnitTestCharExt.cs プロジェクト: zyj0021/Cyjb
 public void TestWidth()
 {
     // 宽字符范围:
     // 0x1100 ~ 0x115F:Hangul Jamo init. consonants
     Assert.AreEqual(1, '\u10FF'.Width());
     Assert.AreEqual(2, '\u1100'.Width());
     Assert.AreEqual(2, '\u1101'.Width());
     Assert.AreEqual(2, '\u115E'.Width());
     Assert.AreEqual(2, '\u115F'.Width());
     Assert.AreEqual(1, '\u1160'.Width());
     // 0x2329, 0x232A:左右尖括号〈〉
     Assert.AreEqual(1, '\u2328'.Width());
     Assert.AreEqual(2, '\u2329'.Width());
     Assert.AreEqual(2, '\u232A'.Width());
     Assert.AreEqual(1, '\u232B'.Width());
     // 0x2E80 ~ 0xA4CF 除了 0x303F:CJK ... YI
     Assert.AreEqual(1, '\u2E7F'.Width());
     Assert.AreEqual(2, '\u2E80'.Width());
     Assert.AreEqual(2, '\u2E81'.Width());
     Assert.AreEqual(2, '\u303E'.Width());
     Assert.AreEqual(1, '\u303F'.Width());
     Assert.AreEqual(2, '\u3040'.Width());
     Assert.AreEqual(2, '\uA4CE'.Width());
     Assert.AreEqual(2, '\uA4CF'.Width());
     Assert.AreEqual(1, '\uA4D0'.Width());
     // 0xAC00 ~ 0xD7A3:Hangul Syllables
     Assert.AreEqual(1, '\uABFF'.Width());
     Assert.AreEqual(2, '\uAC00'.Width());
     Assert.AreEqual(2, '\uD7A3'.Width());
     Assert.AreEqual(1, '\uD7A4'.Width());
     // 0xF900 ~ 0xFAFF:CJK Compatibility Ideographs
     Assert.AreEqual(1, '\uF8FF'.Width());
     Assert.AreEqual(2, '\uF900'.Width());
     Assert.AreEqual(2, '\uFAFF'.Width());
     Assert.AreEqual(1, '\uFB00'.Width());
     // 0xFE10 ~ 0xFE19:Vertical forms
     Assert.AreEqual(0, '\uFE0F'.Width());             // '\uFE0F' 是 NonSpacingMark
     Assert.AreEqual(2, '\uFE10'.Width());
     Assert.AreEqual(2, '\uFE19'.Width());
     Assert.AreEqual(1, '\uFE1A'.Width());
     // 0xFE30 ~ 0xFE6F:CJK Compatibility Forms
     Assert.AreEqual(1, '\uFE2F'.Width());
     Assert.AreEqual(2, '\uFE30'.Width());
     Assert.AreEqual(2, '\uFE6F'.Width());
     Assert.AreEqual(1, '\uFE70'.Width());
     // 0xFF00 ~ 0xFF60:Fullwidth Forms
     Assert.AreEqual(0, '\uFEFF'.Width());             // '\uFEFF' 是 Format
     Assert.AreEqual(2, '\uFF00'.Width());
     Assert.AreEqual(2, '\uFF60'.Width());
     Assert.AreEqual(1, '\uFF61'.Width());
     // 0xFFE0 ~ 0xFFE6
     Assert.AreEqual(1, '\uFFDF'.Width());
     Assert.AreEqual(2, '\uFFE0'.Width());
     Assert.AreEqual(2, '\uFFE6'.Width());
     Assert.AreEqual(1, '\uFFE7'.Width());
     // 0x20000 ~ 0x2FFFD
     Assert.AreEqual(1, CharExt.Width(char.ConvertFromUtf32(0x1FFFF), 0));
     Assert.AreEqual(2, CharExt.Width(char.ConvertFromUtf32(0x20000), 0));
     Assert.AreEqual(2, CharExt.Width(char.ConvertFromUtf32(0x2FFFD), 0));
     Assert.AreEqual(1, CharExt.Width(char.ConvertFromUtf32(0x2FFFE), 0));
     // 0x30000 ~ 0x3FFFD
     Assert.AreEqual(1, CharExt.Width(char.ConvertFromUtf32(0x2FFFF), 0));
     Assert.AreEqual(2, CharExt.Width(char.ConvertFromUtf32(0x30000), 0));
     Assert.AreEqual(2, CharExt.Width(char.ConvertFromUtf32(0x3FFFD), 0));
     Assert.AreEqual(1, CharExt.Width(char.ConvertFromUtf32(0x3FFFE), 0));
 }