2007年12月28日星期五

对字符集和编码的一些错误认识

字符集和编码一直很头疼的一块,最近为了搞培训,研究了一下,发现以前确实有很多不明白甚至是错误的认识:
  • ISO-8859-1 .. ISO-8859-16 这些都是西欧各国用的字符集,主要的差别在与128-255之间各自代表的字符不同;
  • 仍然不明白为啥GB2312, Big5这些就算MBCS,而同样采用多字节编码的Unicode却不算
  • GBK应该是GB2312的超集,向下兼容GB2312的,记得以前谁跟我说不是,我迷惑了好一阵;
  • 很 多编辑器说可以支持"Unicode编码",并且一些软件说"Unicode"就是两字节编码,这都是基于Unicode 4.0之前的认识。在那之前,Unicode跟GB2312这样的名称一样,即是字符集(charset)名称又是编码(encoding)名称, Unicode字符均是两个字节。但从Unicode 4.0开始,它已经不只65536个字符了,Unicode只是一个字符集名称,而UCS-2, UCS-4,UTF-8, UTF-16, UTF-32这些才是编码名称(当然,历史包袱总是存在的);
  • UCS-2与UTF-16是不一样的,UCS-2固定采用两个字节,它不能表达Unicode 4.0之后增补的字符(当然,那些字符很生僻),而UTF-16里面每个字符可能是2或4个字符组成;
  • UTF-8
    • 从新的理论上而言,UTF-8应该是1-6个字符不等,但目前应该是1-3个字符就可以表达已有的字符了;
    • UTF-8的优点
      • 如果原有数据大都采用ASCII表达,那么这些数据不用转换
      • 如果系统采用ASCII可以表达大多数数据,那么相对UCS-2,UTF-16这些节省空间;
      • 编码中字符边界很容易找到:以0开头的字节肯定是ASCII字符,最高位以11开头的字节肯定是字符的开头字节,以10开头的字节肯定是字符的后续字节;
      • 容错性强一些,偶尔一两个错误不会影响后面,原因同上(想咱们都碰到过GB2312/Big5的半个汉字问题带来的乱码问题吧)
      • 按字节流读取,不用考虑大端(big endian)/小端(little endian)问题
      • 字符串中不会出现0x00这样的字节(而UCS-2这些会),这样char *这样的方式表达缓冲区时不太容易导致错误
    • UTF-8的缺点
      • 对于非ASCII字符,相对以前存储空间增加了,比如非英语的西欧字符集现在都需要两个字节了,而中文等很多都需要三个字节了;
      • 计算字符串长度比较麻烦,只能逐个统计;
    • 综上,现在很多系统内部处理采用UCS-2,只在存储和数据交换中采用UTF-8
  • Java以前内部全部采用Unicode(其实是UCS-2)来处理字符串,但Unicode 4.0以上的那些字符它不能处理。在Java 5.0中加入了一些奇怪的机制来解决这个问题
  • Python也不能同时支持UCS-2和UCS-4,只是可以在编译时挑选(--enable-unicode=ucs2和--enable-unicode=ucs4),看sys.maxunicode是否大于65535就知道是否是UCS-4了。我看Windows上的预编译版本是UCS-2(python2.5)的,而Linux上是UCS-4(Debian testing, python 2.4)。注意这两种版本在二进制上是不兼容的。
参考文档

2007年12月27日星期四

Firefox 3上使用旧扩展

目前还有很多插件不支持Firefox 3,如果你实在想用,可以修改下面两个设置:
user_pref("extensions.checkCompatibility", false);
user_pref("extensions.checkUpdateSecurity", false);
这样Firefox升级或者安装新扩展时就不会检查兼容性和签名了(检查扩展的签名是Fx3新增的功能)。不过扩展不一定能正常工作,比如Google工具栏就不成。

可以将这两行加在profile下prefs.js(请先关闭Firefox),也可以在about:config中手工增加这两项。

2007年12月25日星期二

Firefox 3上如何添加 del.icio.us 书签

以前我为了几台机器、几个操作系统上书签的同步烦心不已,即使安装了Foxmarks同步器还得留神用哪个覆盖哪个,而Google工具栏提供的书签功能也不太好用。后来开始使用del.icio.us的书签服务,加上del.icio.us Bookmarks扩展,终于很满意了。

Firefox 3出来了beta 1之后,我就基本上开始用新版本了,毕竟很多功能很不错,内存占用比原来少了(也许是目前安装的扩展还比较少),再说反正以后要切的。不过目前还是两个版本都用。

但目前很多扩展都还不支持Firefox 3(而且Firefox 3开始要求对扩展进行签名了,不能象以前那样简单地下载xpi包后自己来改改版本匹配申明就说不定可以使用),有些扩展倒也罢了,但现在del.icio.us 似乎变成必须了 :-)

查看/搜索书签的功能倒简单,只要访问 http://del.icio.us/home 就可以了,网页上也有输入tag进行搜索的功能。

主要的问题是没法方便地添加书签了,以前只要在网上逛,看到不错的地方,按一下Ctrl+D或者点击工具栏的TAG按钮,就有一个对话框出来,当前网页的标题、其他人的tag都显示出来了,并且当前网页选中的文字还可以自动放入书签的说明栏。
del.icio.us

在del.icio.us的帮助中找了一下,发现可以用如下办法: 在书签栏上添加一个书签,其URL是:
javascript:location.href='http://del.icio.us/post?v=4;url='+encodeURIComponent(location.href)+';title='+encodeURIComponent(document.title)
(可以拖这个链接到书签栏,然后自己改名字)

详细的说明在这里: bookmarklet buttons for any browser

但“当前网页选中的文字还可以自动放入书签的说明栏”这一点还不能做到,不太爽。我试验了一下,发现多传一个notes参数就可以了: 在上述URL后面再添加一节:
+';notes='+encodeURIComponent(window.getSelection().toString())

结论: 拖下面这个链接到书签栏就可以了:
post to del.icio.us

2007年12月20日星期四

找不到python24_d.lib怎么办(VC上编译wxPython)

编译一个wxWidgets内嵌wxPython的示例工程时,编译器说需要python24_d.lib,因为懒得自己重新编译一遍python,在网上找到一个办法: 修改Python\include里面的python.h,把静态库都改成同一个(即将python24_d.lib改成python24.lib),其它.h文件也搜索Py_DEBUG,将两种模式下的处理搞成一致(比如不采用不同的引用计数函数),然后就OK了。

---------------------------------------
(下面是详细说明——我现在是越来越罗嗦了)
这几日在琢磨能不能直接采用wxPython搭建我们的下一版本的界面,各方面看都是我们要找的东西,除了一条: 如何将旧系统兼容进去(旧系统采用MFC+COM+Active Scripting技术搭建)。

于是我想先看看用MFC写的程序能不能集成wxPython,但google了半天没有任何信息,只好退而求其次查找wxWidgets上嵌入wxPython,倒是找到一个例子:
http://svn.wxwidgets.org/viewvc/wx/wxPython/trunk/samples/embedded/

它本来的Makefile是编译debug版的,这就需要python, wxWidgets和wxPython的debug版本动态库,好像网上对于Windows上都没有提供(不象Linux上还有python2.4-dbg, libwxgtk2.6-dbg可供安装),这就意味着必须完全自己来编译,编译时还有unicode,universal一大堆的选项,编译完了还有安装/配置的问题。

我烦了,就编译release版本吧,自己修改Makefile.vc,去掉了调试选项,编译出来了。但将embeded.exe放到wxPython的目录运行,它跟我报怨说版本不匹配,wxPython的是"debug,unicode,Visual C++....",而embeded.exe是"no debug,unicode,Visual C++..."。奇怪,怎么预编译的wxPython居然还是debug版本?

没办法,又回头来编译debug版本,但折腾了半天,最后碰到一个python24_d.lib过不去。看来非得自己编译python不可了。我不死心,又在网上搜了一阵,找到一个办法: 修改Python\include里面的python.h,把静态库都改成同一个,其它.h文件也搜索Py_DEBUG,将两种模式下的处理搞成一致(比如不采用不同的引用计数函数),然后就OK了。

2007年12月11日星期二

PDF文件的分割与合并

装个pdftk就行了。

分割可以采用分段抽取来搞定:
pdftk wxPIA.pdf cat 114-146 output chapter04.pdf

合并:
pdftk chapter0*.pdf cat output part1.pdf

还可以将A文档的某些页和B文档的某些页拼起来:
pdftk A=one.pdf B=two.pdf cat A1-7 B1-5 A8 output combined.pdf

添加附件:
pdftk chapter01.pdf attach_files ../chapter-01/* output chapter01a.pdf

拆离附件:
pdftk chapter01a.pdf unpack_files output ./chapter-01/

更复杂的应用还是看项目主页上的文章吧。

另外, 这东西用到libgcj,估计部分是用java写的,反正运行起来有点慢。

修正Launchy在Thunberbird中独立邮件窗口里菜单不能显示的问题

在Thunderbird中碰到一些链接,需要调用外部程序(firefox或者d4x等)打开,于是安装了Launchy。但Launchy菜单可以在主窗口的邮件视图中出现,而在独立的邮件视图(双击列表栏一个邮件时打开的),这个菜单就没有出现了。

估计Launchy没有在独立邮件窗口注册overlay,但要去查邮件窗口的chrome url,也挺麻烦的。
我看ThunderBrowse的菜单工作得挺好,于是看了一下它的chrome.manifest,里面就三行overlay:
overlay chrome://global/content/customizeToolbar.xul chrome://tbrowse/content/accessbrowser.xul
overlay chrome://messenger/content/messenger.xul chrome://tbrowse/content/accessbrowser.xul
overlay chrome://messenger/content/messageWindow.xul chrome://tbrowse/content/accessbrowser.xul
而Launchy是这样
overlay chrome://browser/content/browser.xul chrome://launchy/content/main.xul
overlay chrome://messenger/content/messenger.xul chrome://launchy/content/main.xul

看名字就知道独立的邮件视图是messageWindow.xul,于是在launchy的chrome.manifest添加如下一行就可以了
overlay chrome://messenger/content/messageWindow.xul chrome://launchy/content/main.xul