序幕有些长

为一份 ConTeXt 中文教程整理的序

Posted by LiYanrui Sep 29, 2009 05:11:00 PM


左顾右盼

很是活动颈椎。

Posted by LiYanrui Sep 12, 2009 02:12:52 AM


Emacs 23 的 org-mode 自动折行

当发现 Emacs 23 在 org-mode 中的文本无法自动折行时,试试在 .emacs 中添加:

;; turn on soft wrapping mode for org mode
(add-hook 'org-mode-hook
  (lambda () (setq truncate-lines nil)))

Posted by LiYanrui Sep 10, 2009 05:23:40 AM


Emacs 与 C/C++ 代码自动补全

基于 Emacs 的 company 模式并配合 semantic 文法分析器,实现 Emacs 的 C/C++ 代码自动补全。

Posted by LiYanrui Aug 29, 2009 10:05:19 AM


创建临时文件

经常在 /tmp 目录下看到许多带有奇怪编号的文件名,比如 XXX_2znzjy、XXX__6yQ1id 之类,却从未想过它们是怎么来的。

近来我一直在搞投机取巧的事情,就是用自己写的 C 程序直接调用 qhull 程序去生成三维点集的凸包。要达到这一目的,我首先需要解决我的程序与 qhull 程序之间的数据交换问题。在不触及 qhull 源代码的条件下,采用文件进行数据传递是我能找到的最好的方法(如果你有更好的,告诉我吧)。

选择使用文件进行数据交换之后,我想做的更加稳妥和专业一些,这时 /tmp 目录冲我暧昧地笑了一下。打开 APUE(版本号的默认值是“第 2 版”),在 5.13 节可以找到有关 ISO C 和 SUS 标准中用于生成临时文件的函数的详细阐述。话说,这本 APUE 自打我从图书馆借过来后,翻看了前两章之后,它就一直做充当我的枕头的工作,现在它总算又重新找回我的宠幸。

我比较喜欢 ISO C 定义的 tmpnam ( ) 函数,因为它可以生成一个唯一的文件名,我可以利用这个文件名打开文件进行各种操作。但是 "man -S 3 tmpnam",却看到:

BUGS
       Never use this function.  Use mkstemp(3) or tmpfile(3) instead.

tmpfile ( ) 这个函数也很不错,不过不知道怎么获取它所创建的文件名。于是,我只能将希望寄托给 mkstemp () 了。

mkstemp ( ) 的确不辱使命,它可以创建临时文件,并且还能告诉我文件名。但是,它也不完美,因为它的容貌不讨人喜欢。首先,要使用它,需 #include <stdlib.h>,并且它不算是 c99 标准定义的函数,所以当你采用 c99 标准去调用 gcc 编译那些使用了 mkstemp ( ) 函数的 C 文件时,就会遇到“未找到 mkstemp ( ) 函数声明”的警告:

warning: implicit declaration of function ‘mkstemp‘

要消除这个警告,需要在 C 文件的头部添加:

#define _XOPEN_SOURCE 500

如果是比较新的 glibc 版本,那么讲 _XOPEN_SOURCE 的值定义成 600 或 700 都可以。这些事情,都是 APUE 和 man 告诉我的。如果不想把代码搞的太难看,也可以在 gcc 的编译命令中添加 "-D_XOPEN_SOURCE" 宏选项来实现。

mkstemp () 函数接受一个字符串变量,返回文件描述符,如果返回值为 -1 表明创建文件失败。调用它的简单示例代码如下:

        char fn[128] = "/tmp/testXXXXXX";
        int fd;

        if ((fd = mkstemp (fn)) == -1)
                exit (-1);

注意,mkstemp ( ) 函数所接受的参数是字符串变量,而非字符串常量,并且该字符串变量的最后 6 位必须是 “XXXXXX”,也就是说这个字符串变量实际上是一个字符串模板,mkstemp ( ) 函数内部会将这个字符串的 "XXXXXX" 部分进行替换,并将替换后字符串作为临时文件名。

还要注意,mkstemp ( ) 函数返回的不是文件指针,而是文件描述符(参考 APUE 3.2 节)。如果想将文件描述符转换为我们熟悉的 C 语言文件指针类型,可以使用 fdopen ( ) 函数,例如:

        FILE *fp;
        char fn[128] = "/tmp/testXXXXXX";
        int fd;

        if ((fd = mkstemp (fn)) == -1)
                exit (-1);
        if ((fp = fdopen (fd)) == NULL)
                exit (-1);

在拥有文件指针的情况下,我们就可以“很自由地”(相对于动态语言,一点都不自由)利用 ISO C 定义的文件操作函数进行文件读写操作了。

最后要注意的就是,mkstemp ( ) 不会对创建的临时文件进行删除。如果临时文件位于 /tmp 目录,那么系统重新启动时一般会自动清理。如果想在程序中删除不再使用的临时文件,可以使用 Unix 系统调用 unlink ( ) 函数来实现。unlink ( ) 函数的用法可以查阅 man 的第 2 节,即 "man -S 2 unlink"。

Posted by LiYanrui Aug 22, 2009 04:02:45 PM


败了

忙活了很久,现在才发现只要使用 pre_linebreak_filter 回调函数,那么 fallback 字体机制就会失去作用,看样子是跟 Hans 的代码有所冲突。心灰意冷,不搞了,跟那么一堆很恶心的代码搏斗,实在没有意思。还是把心思放回 Conote 上来。

Posted by LiYanrui Aug 10, 2009 04:39:08 AM


用 qhull 计算三维点集的凸包

在计算几何领域,qhull 是个很强大的程序,它可以计算 2 维、3 维,以及4 维以上维度点集的凸包、Delaunay 网格、Voronoi 图,并且 Matlab 和 Octave 都基于它来提供计算几何功能,Mathematica 使用它实现 Delaunay 网格构造。不过,也正是因为它过于强大,所以我在它的源代码中逡巡了好久,也没有看懂。现在我能做到的,就是找个梯子先爬上这个黑箱子。

Posted by LiYanrui Jul 18, 2009 09:34:05 PM


罚点

在 TeX 中,罚点(penalty)可以用于控制在某个字符后是否必然会发生断行,我们可以利用它来实现标点禁则。在 LuaTeX 中,函数 nodes.penalty () 可以制作一个罚点,只需要使用 node.insert_before () 或 node.insert_after () 函数将罚点插入不希望断行的字符结点之前或之后即可。

Posted by LiYanrui Jul 03, 2009 03:52:30 PM