TextEdit/UCD R5 与 Cocoa Text System

更新: TextEdit/UCD 的代码现在可以在 [http://gitorious.org/projects/textedit-ucd/](http://gitorious.org/projects/textedit-ucd/) 找到。

TextEdit/UCD 的第 5 个版本[发布](http://jjgod.org/program/TextEdit-UCD-r5.dmg)了,TextEdit/UCD 开发的目标是尽可能解决所有 TextEdit 固有的中文处理问题,但并不改变 TextEdit 原有的轻量小巧。

在开发这个版本中,我发现了一个 Cocoa Text System 的固有问题:还没有下载的朋友可以先打开自己机器上的 TextEdit,输入一个汉字,一个英文字母,如“中a”,这时汉字会以默认的中文字体显示,英文字母会以 Preferences 中设定的 Plain Text 字体 (如 Monaco) 显示,此时按下 cmd-‘+’ 增大一号字体,然后再输入一个英文字母,就会发现这个新的英文字母居然改用中文字体显示了?

为什么呢?在 TextEdit 中花了一段时间重载各个类,加上 gdb 分析,结果发现,其实在 Make Text Bigger/Make Text Smaller 时,调用 `[NSFontManager modifyFont:]`,这个 `modifyFont:` 方法会将 `-changeFont:` 这个 action 发送到 responder chain 中,而此时的 NSTextView 收到这个 action 以后,居然会将 `[NSFontManager sharedInstance]` 的 `selectedFont` 修改为这个 TextView 的 TextStorage 中第一个字符使用的字体。于是就导致了已选字体的变化。这其实不是我们期望的结果。

然而,由于事实上 NSTextView 的 changeFont 实现可能很复杂,它要逐个分析所有的 run,逐个将这个 run 的字体送到 NSFontManager 中 convertFont 获得新的字体。既然我们无法直接修改这个 changeFont 的代码,就只能用重载的方法,写一个新的 NSTextView 的子类,重载这个函数,在调用基类的 changeFont 之前,先给整个文档的开头加上一个用纯文本字体的新字符,然后在调用完基类 changeFont 之后再把它删除。

这是一个看起来有些 dirty 的方法,不过很有用,也算是“曲线救国”,用欺骗的方式使之有正确的效果。

Author: Jiang Jiang

A software engineer from China, working on some OS for a fruit company. Interested in typography and science fiction.

10 thoughts on “TextEdit/UCD R5 与 Cocoa Text System”

  1. 第一个链接的href没有设,另外代码里要用到的charset detector库也没有放上去,导致不能直接拿到代码就编译。

Leave a Reply

Your email address will not be published. Required fields are marked *