【问题标题】:Lazarus. Equivalent to Chr() for Unicode symbols拉撒路。等效于 Unicode 符号的 Chr()
【发布时间】:2011-08-05 20:28:38
【问题描述】:

freepascal 中是否有任何函数可以通过代码显示 Unicode 符号(例如 U+1D15E)?不幸的是,Chr() 仅适用于 ANSI 符号(代码小于 127)。
我想使用自定义符号字体中的符号,直接将它们放入源代码非常不方便(它们在 Lazarus 中显示为 ? 或其他内容,因为它们在系统字体中不存在)。

【问题讨论】:

  • U+1D15E 是一个有点病态的例子,因为1D15E 不是一个词(一个十六进制数字太多)。
  • @Andreas:Unicode 的符号代码为 U+1D15E。它在音乐符号组中:unicode.org/charts/PDF/U1D100.pdf
  • 我知道。我只是说这有点病态,从某种意义上说,使用适合单词的代码点更容易,而许多应用程序只能使用这些代码点。
  • @Andreas 如果这是您想要的代码点,那么这就是您想要的代码点。
  • @Andreas:U+1D15E 是一个有效的代码点。这种代码点的指定不限于某种编码,如 UTF-16(您似乎指的是)甚至 UTF-8。如何将其编码为代理对是 UTF-16 的一部分。如果 FP 使用 UTF-8(这不会让我感到惊讶),它会被编码为多个字节。

标签: delphi unicode freepascal lazarus


【解决方案1】:

看看this page。我假设 Freepascal 要么使用 UTF-16,其中它成为两个 WideChars 的代理对(见表),要么使用 UTF-8,其中它成为一个字节值序列(再次见表)。

UTF-8:

const
  HalfNoteString = UTF8String(#$F0#$9D#$85#$9E);

UTF-16:

const
  HalfNoteString = UnicodeString(#$D834#$DD5E);

字符串类型的名称可能不同,因为我不太了解 FreePascal。也许是 AnsiString 和 WideString。

【讨论】:

  • @Rudy Velthuis:谢谢!第一个变体在 Lazarus 中完美运行!
  • FPC 2.4.x+ 有 unicodestring。它没有带有代码页的 ansistring,并且 unicodestring 在库中使用得不多,但它就在那里。 (因为基本上它是旧的 Kylix 宽弦,在唱片中进行了轻微的重新排列和增强)
【解决方案2】:

我从未使用过 Free Pascal,但如果我是你,我会尝试

var
  s: char;
begin
  s := char($222b);                   // Just cast a word

或者,如果编译器真的很顽固,

var
  s: char;
begin
  PWord(@s)^ := $222b;                // Forcibly write a word

【讨论】:

  • 谢谢!两种变体都可以正常工作。不过,你知道有什么方法可以使用不适合单词的代码点吗(我的字体有几个符号)?
  • @VIK:恐怕我什至不知道 Delphi 是如何处理这些的……也许 David 知道?
  • @VIK:在 Delphi 的 UnicodeString 中,它们被编码为 pair 的单词,称为代理对。 U+1D15E 如何以 UTF-16 编码(假设这实际上是 Free Pascal 使用的——我可以想象他们也可以在任何地方使用 UTF-8,它最多可以编码为 5 个字节,IIRC),我不知道。
  • UTF-16 确实是一对 WideChars。这就是你在 Windows 上想要的方式。至于 Free Pascal,我不知道自然 Unicode 编码是什么。
  • 代码点被编码为最多一对宽字符。请注意,代码点与字符不同,例如OS X 上的 UTF16 通常是非规范化的(重音字符有更多代码点)
【解决方案3】:

据我所知,FPC 的当前 unicode 状态

  1. 文字的代码页可以用 $codepage http://www.freepascal.org/docs-html/prog/progsu81.html 设置
  2. FPC 2.4.x+ 确实有 unicodestring(因为它是 +/- Kylix 宽字符串),但只有基本的例程支持。 (pos 和 copy,不是 format 之类的例程),但“记录”错过了代码页字段。
  3. Lazarus 小部件在普通 ansistrings 中需要 UTF8(D7..D2007 ansistrings 没有代码页数据),如果需要,程序员必须手动插入转换。因此,在 Windows 上,小部件主要使用 unicode (-W) 调用,但采用带有 UTF8 的 ansistrings。
  4. FPC 不遵循 ansistring 方案中的 utf8,因此对于 sysutils 中的某些字符串接受例程,Lazarus 中有一些特殊例程假定 UTF8 调用 -W 变体)
  5. FPC ansistring 是系统默认的 1 字节编码。 Windows 上的 ansi,大多数其他平台上的 utf8。
  6. Trunk 2.7.1 支持新的 D2009+ ansistring(带有代码页)。
  7. 目前还没有讨论如何处理默认的字符串类型(例如,“字符串”在 *nix 上是 utf8string,在 Windows 上是 unicodestring,还是到处都是 unicodestring 或 utf8string?)
  8. 未实现其他与 unicodestring 相关的增强功能(如 tstringlist.savetofile 的编码参数)。对于伪对象也是如此(例如 TCharacter,它们大多是静态的)

更新:2.7.1 有一个变量编码 ansistring 类型,并且 lazarus 已被修复以继续工作。不过,没有什么能真正从中受益,例如大多数 RTL 仍然使用 -A 调用,sysutils 的原型和接受字符串的系统过程尚未更改为 rawbytestring。

【讨论】:

    【解决方案4】:

    我认为问题是从 UCS4 编码(实际上是一个 Unicode 代码点编号)转换为 UTF16。

    在Delphi中,可以使用UCS4StringToUnicodeString函数。

    警告:注意UCS4String 类型。它实际上是一个以零结尾的动态数组,而不是字符串(这意味着它是从零开始的)。

    var
      S1: UCS4String;
      S: string;
    
    begin
      SetLength(S1, 2);
      S1[0]:= UCS4Char($1D15E);
      S1[1]:= UCS4Char(0);
      S:= UCS4StringToUnicodeString(S1);
      ShowMessage(Format('%d, %x, %x', [Length(S), Ord(S[1]), Ord(S[2])]));
    end;
    

    【讨论】:

    • 这应该是公认的答案。其他答案只会让你走到一半。这确实有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 2018-10-06
    相关资源
    最近更新 更多