Lazarus. 对于Unicode符号相当于Chr()函数

3

在freepascal中有没有显示Unicode符号的函数(例如U+1D15E)?不幸的是,Chr()只能用于ANSI字符(其代码小于127)。
我想使用来自自定义符号字体的符号,将它们直接放入源代码非常不方便(因为它们在系统字体中不存在,所以它们在Lazarus中显示为?或其他一些东西)。


U+1D15E 是一个稍微有点病态的例子,因为 1D15E 不是一个单词(多了一个十六进制数字)。 - Andreas Rejbrand
3
@Andreas: Unicode有一个编码为U+1D15E的符号,它属于音乐符号组:http://www.unicode.org/charts/PDF/U1D100.pdf - VIK
我知道。我只是说这有点病态,因为使用适合于一个单词的代码点更容易处理,并且许多应用程序只能使用这些代码点。 - Andreas Rejbrand
3
如果那是你想要的代码点,那就是你想要的代码点。 - David Heffernan
2
@Andreas:U+1D15E 是一个有效的代码点。这种代码点的指定不仅限于某种编码,比如你所提到的 UTF-16,甚至包括 UTF-8。如何将其编码为代理对是 UTF-16 的一部分。如果 FP 使用 UTF-8(这并不让我感到惊讶),它将被编码为多个字节。 - Rudy Velthuis
4个回答

8
请看这个页面。我认为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中完美运行! - VIK
FPC 2.4.x+具有unicodestring。它没有带有代码页的ansistring,并且unicodestring在库中使用不多,但是它确实存在。(因为基本上它是旧的Kylix widestring,记录中进行了轻微的重新排列和增强) - Marco van de Voort

5

我从未使用过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
@VIK:我恐怕甚至不知道Delphi如何处理这些问题...也许David知道? - Andreas Rejbrand
3
在Delphi的UnicodeString中,它们被编码为一个称为代理对的两个字,即一对surrogate pair。关于U+1D15E在UTF-16中的编码方式(假设Free Pascal实际使用的是UTF-16——我可以想象他们可能会在所有地方都使用UTF-8,在那里它可以用多达5个字节进行编码),我不清楚。 - Rudy Velthuis
UTF-16确实是一对WideChars。这是在Windows上所需要的。至于Free Pascal,我不知道自然的Unicode编码是什么。 - David Heffernan
代码点被编码为最多一对宽字符。请注意,代码点不同于字符,并且例如,在OS X上,UTF16通常是非规范化的(带有更多带重音字符的代码点)。 - Marco van de Voort

4

据我所知,FPC的当前Unicode状态如下:

  1. 可以使用$codepage设置文字的代码页。 http://www.freepascal.org/docs-html/prog/progsu81.html
  2. FPC 2.4.x+有unicodestring(因为它是+/- Kylix widestring),但仅具有基本例程支持(pos和copy,而不是像format这样的例程),但“record”缺少codepage字段。
  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. 尚未讨论如何处理默认的stringtype(例如,“string”在*nix上是否为utf8string,在Windows上为unicodestring或utf8string?)
  8. 其他与unicodestring相关的增强功能(例如向tstringlist.savetofile传递编码参数)未实现。同样,伪对象(如TCharacter)也是如此。

更新:2.7.1具有可变编码ansistring类型,并且已经修复了Lazarus以保持工作状态。但是,目前还没有真正利用它的地方,例如大多数RTL仍使用-A调用,并且接受字符串的sysutils和系统过程的原型尚未更改为rawbytestring。


3
我猜问题是将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;

这应该是被接受的答案。其他答案只能帮你解决部分问题。这个确实可行。 - user4815162342

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接