20070607

[合集]Emacs22和Emacs23的内部编码原理(转寄)

发信人: brep (哪个虫儿敢做声), 信区: Emacs
标 题: [合集]Emacs22和Emacs23的内部编码原理
发信站: 水木社区 (Tue Oct 31 11:40:57 2006), 站内

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Sun Oct 29 15:36:25 2006) 提到:

Emacs 的编码系统这个话题太大了,得写一篇很长的文章才能说清楚。而且
对于用户来说,可能并不感兴趣,也不关心这个。

Emacs22 的编码原理是让多个国家的编码系统共存。buffer里的每一个字符
都用 1-4 个字节表示,比如 gb2312 的汉字就是用3个字节表示,这三个
字节中的第一个字节叫 leading byte, 说明了这个字符所属的字符集,后
面两个字节是这个字符的gb2312编码。chinese-gb2312 的 leading byte
是 0x91, big5 因为比较大,所以分成了两个 charset: chinese-big5-1
和 chinese-big5-2, leading byte 分别是 0x98 和 0x99。

所以对于 Emacs22 来说,只要查看一个字符的 leading byte,就可以知道
它属于哪个字符集,一看是 0x91 就知道它是 gb2312 字符,一看是 0x98
就知道它是 big5 字符。所以一个汉字可能会有好几种内部编码,比如"好"
字,gb2312, big5, 朝鲜文, 日文中都有这个字,那么它就有四种内部编码。

当 Emacs22 打开一个文件的时候,就需要判断出这个文件的编码系统,然
后给文件中的每个字符加上 leading byte,放到内存中,Emacs22把这个过
程叫做 decode。当emacs22保存文件时就需要根据每个字符的 leading
byte 把它转换成相应字符集的编码,再写到文件中,emacs22把这个过程叫
做 encode。

为了演示 Emacs decode/encode 的过程,我们可以做个小实验:

- 新建一个文件 ~/test.txt
- 输入"中文"两个字
- C-x <return> f gb2312
- C-x C-s 保存文件
- 在 *scrach* buffer 里输入
(insert-file-contents-literally "~/test.txt")
C-j 一下可以看到 \326\320\316\304 ,这是八进制的"中文"两个字的编码。
- 现在打开 ~/test.txt,然后执行
M-x toggle-enable-multibyte-characters
我们可以看到 \221\326\320\221\316\304,Emacs在每个汉字的编码前都加
上了一个 \221,正是十六进制的 0x91――gb2312的 leading byte。

然而,leading byte 的数量是有限的,而世界上的字符集却越来越多,因
此当 gbk 和 gb18030 出现以后,就没有合适的 leading byte 分配给它们,
所以 Emacs22 不支持 gbk 和 gb18030。

苏勇和詹剑写的 mule-gbk,实际上是把全部的gbk字符分成了三部分,分别
占用了 chinese-cns-5, chinese-cns-6, chinese-cns-7 的 3 个
leading byte。mule-gbk 的主要代码就是把 gbk 中的字符加上这三个
leading byte 之一,放入内存,也就是 decode;或者反过来把内存中带有
这三个 leading byte 之一的字符转换成 gbk 编码,也就是 encode。
Emacs为了方便进行各种编码的转换,专门内嵌了一种称为 ccl 的语言,编
码转换部分的代码就是用 ccl 写成的。

Emacs23的编码原理是把所有的字符集都转换成 utf-8,内部字符都是
utf-8 编码。这样对于每个字符集都需要两张表,一个是 charset -->
utf-8,另一个是 utf-8 --> charset。Emacs23源码的 etc/charsets/ 目录
下有很多 *.map 文件,就是这种转换表。

当Emacs23打开一个文件时,先判断文件的编码,然后加载相应的表格,再
按照表格把文件中的字符一个一个转换成 utf-8 放入内存;保存文件时,
也是按照表格把内部的 utf-8 编码转换成相应的字符集编码。

unicode 的全部编码可以分成很多 block,在 www.unicode.org 可以查到。
由于中国参与 unicode 的制定比较晚,因此造成了gb2312/gbk/gb18030中
的字符被分配到了很多不同的 block 中,汉字还相对比较连续,标点符号
就特别分散,这个block中有几个,那个block中有几个。

Emacs 23 在进行 fill 时不整齐的原因,主要是那些标点符号的宽度属性
设置错误,本来应该是2,却设成了1,因此 fill 时计算行宽不准确,标点
符号越多,误差越大。我的那个patch主要是更改了这些标点符号的宽度属
性。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 好像你对编码系统特别有研究,总结一下,让我们学习一下吧。
: 比如,你今天的那几个区域分别对应什么?还有 mule-gbk 是什么原理?
: ...................

☆─────────────────────────────────────☆
ann77 (ann) 于 (Mon Oct 30 12:18:51 2006) 提到:

我还以为 Emacs 23 会使用 UCS 32 作为内码,如果用 UTF-8 的话,
计算一个字符串有多少个字符就很麻烦了。
定位一个字符的下标也很低效。

【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: Emacs 的编码系统这个话题太大了,得写一篇很长的文章才能说清楚。而且
: 对于用户来说,可能并不感兴趣,也不关心这个。
: Emacs22 的编码原理是让多个国家的编码系统共存。buffer里的每一个字符
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 12:25:49 2006) 提到:

emacs 是以处理英文为主的,utf-32 每个字母要占 4 个字节,内存占用太
多了。utf-8 与 ascii 是兼容的,带来很多好处。utf-8 是变长编码,统
计字符串长度肯定比 utf-32 慢,不过 utf-8 编码很有特点,第一个字节
中"1"的个数,说明了这个字符的编码一共有几个字节。

其实权衡一下的话,utf-16 是个不错的选择,大部分的字符都是两个字节。

【 在 ann77 (ann) 的大作中提到: 】
: 我还以为 Emacs 23 会使用 UCS 32 作为内码,如果用 UTF-8 的话,
: 计算一个字符串有多少个字符就很麻烦了。
: 定位一个字符的下标也很低效。
: ...................

☆─────────────────────────────────────☆
shgsun (shgsun) 于 (Mon Oct 30 12:35:27 2006) 提到:

23 fill的patch是哪一个?
就是那个纠正标点字符数的


【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: Emacs 的编码系统这个话题太大了,得写一篇很长的文章才能说清楚。而且
: 对于用户来说,可能并不感兴趣,也不关心这个。
: Emacs22 的编码原理是让多个国家的编码系统共存。buffer里的每一个字符
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 13:10:44 2006) 提到:

用这个吧:

(let ((l '(chinese-gb2312
gb18030-2-byte
gb18030-4-byte-bmp
gb18030-4-byte-ext-1
gb18030-4-byte-ext-2
gb18030-4-byte-smp)))
(dolist (elt l)
(map-charset-chars #'modify-category-entry elt ?|)
(map-charset-chars
(lambda (range ignore)
(set-char-table-range char-width-table range 2))
elt)))

【 在 shgsun (shgsun) 的大作中提到: 】
: 23 fill的patch是哪一个?
: 就是那个纠正标点字符数的


☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 13:22:22 2006) 提到:

你知道怎样自己定义一个编码系统吗?
或者怎样设置 translation-table-for-decode。比如我想在 emacs 里看 nfo
文件,现在知道它的转换规则是:
(defvar nfo-translation-table
(make-translation-table
'(
(0 . #x263A)
(1 . #x263B)
(2 . #x2665)
(3 . #x2666)
(4 . #x2663)
(5 . #x2660)
(6 . #x25CF)
(7 . #x25D8)
(8 . #x2642)
(9 . #x2640)
(11 . #x263C)
(12 . #x25BA)
(14 . #x2195)
(15 . #x203C)
(16 . #xB6)
(17 . #xA7)
(18 . #xF5)
(19 . #x21A8)
(20 . #x2191)
(21 . #x2193)
(22 . #x2192)
(23 . #x2190)
(24 . #x221F)
(25 . #x2194)
(26 . #x25B2)
(27 . #x25BC)
(176 . #x2591)
(177 . #x2592)
(178 . #x2593)
(179 . #x2502)
(180 . #x2524)
(181 . #x2561)
(182 . #x2562)
(183 . #x2556)
(184 . #x2555)
(185 . #x2563)
(186 . #x2551)
(187 . #x2557)
(188 . #x255D)
(189 . #x255C)
(190 . #x255B)
(191 . #x2510)
(192 . #x2514)
(193 . #x2534)
(194 . #x252C)
(195 . #x251C)
(196 . #x2500)
(197 . #x253C)
(198 . #x255E)
(199 . #x255F)
(200 . #x255A)
(201 . #x2554)
(202 . #x2569)
(203 . #x2566)
(204 . #x2560)
(205 . #x2550)
(206 . #x256C)
(207 . #x2567)
(208 . #x2568)
(209 . #x2564)
(210 . #x2565)
(211 . #x2559)
(212 . #x2558)
(213 . #x2552)
(214 . #x2553)
(215 . #x256A)
(216 . #x256A)
(217 . #x2518)
(218 . #x250C)
(219 . #x2588)
(220 . #x2584)
(221 . #x258C)
(222 . #x2590)
(223 . #x2580)
(224 . #x3B1)
(225 . #x3B2)
(248 . #x25CB)
(249 . #x2014)
(250 . #x2013)
(254 . #x25A0)
)))
然后应该怎样写呢?
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: Emacs 的编码系统这个话题太大了,得写一篇很长的文章才能说清楚。而且
: 对于用户来说,可能并不感兴趣,也不关心这个。
: Emacs22 的编码原理是让多个国家的编码系统共存。buffer里的每一个字符
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 13:43:01 2006) 提到:

是那些电影avi文件中带的 nfo文件吗?还是windows下的系统信息文件?
后面的编码是 gb2312 ? 还是 unicode ?
【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 你知道怎样自己定义一个编码系统吗?
: 或者怎样设置 translation-table-for-decode。比如我想在 emacs 里看 nfo
: 文件,现在知道它的转换规则是:
: ...................

☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 13:55:08 2006) 提到:

就是电影和软件的 nfo 文件,后面的编码应该就是 utf8 的字符。
emacs23 可以用 insert-char 插入。
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 是那些电影avi文件中带的 nfo文件吗?还是windows下的系统信息文件?
: 后面的编码是 gb2312 ? 还是 unicode ?


☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 14:25:51 2006) 提到:

把附件中的 NFO.map拷贝到
/usr/local/share/emacs/23.0.0/etc/charsets/NFO.map
然后:

(define-charset 'nfo
"movie nfo."
:short-name "NFO"
:code-space [0 255]
:map "NFO")

(define-coding-system 'nfo
"movie nfo."
:coding-type 'charset
:mnemonic ?n
:charset-list '(nfo))

试试看怎么样。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 就是电影和软件的 nfo 文件,后面的编码应该就是 utf8 的字符。
: emacs23 可以用 insert-char 插入。


☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 14:40:29 2006) 提到:

你的转码规则从哪里找来的?好像缺几个字符
【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 就是电影和软件的 nfo 文件,后面的编码应该就是 utf8 的字符。
: emacs23 可以用 insert-char 插入。


☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 15:07:01 2006) 提到:

网上找的,一个叫 nfo2txt.php,我按这个转换的:
<?php
$conv_table = array(
/* 0*/ 0x263a, 0x263b, 0x2665, 0x2666, 0x2663,
/* 5*/ 0x2660, 0x25cf, 0x25d8, 0x2642, 0x2640,
/* 10*/ 0x0000, 0x263c, 0x25ba, 0x0000, 0x2195,
/* 15*/ 0x203c, 0x00b6, 0x00a7, 0x00f5, 0x21a8,
/* 20*/ 0x2191, 0x2193, 0x2192, 0x2190, 0x221f,
/* 25*/ 0x2194, 0x25b2, 0x25bc, 0x0000, 0x0000,
/* 30*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 35*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 40*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 45*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 50*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 55*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 60*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 65*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 70*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 75*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 80*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 85*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 90*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 95*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*100*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*105*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*110*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*115*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*120*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*125*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*130*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*135*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*140*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*145*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*150*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*155*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*160*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*165*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*170*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*175*/ 0x0000, 0x2591, 0x2592, 0x2593, 0x2502,
/*180*/ 0x2524, 0x2561, 0x2562, 0x2556, 0x2555,
/*185*/ 0x2563, 0x2551, 0x2557, 0x255d, 0x255c,
/*190*/ 0x255b, 0x2510, 0x2514, 0x2534, 0x252c,
/*195*/ 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
/*200*/ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560,
/*205*/ 0x2550, 0x256c, 0x2567, 0x2568, 0x2564,
/*210*/ 0x2565, 0x2559, 0x2558, 0x2552, 0x2553,
/*215*/ 0x256a, 0x256a, 0x2518, 0x250c, 0x2588,
/*220*/ 0x2584, 0x258c, 0x2590, 0x2580, 0x03b1,
/*225*/ 0x03b2, 0x0000, 0x0000, 0x0000, 0x0000,
/*230*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*235*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*240*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/*245*/ 0x0000, 0x0000, 0x0000, 0x25cb, 0x2014,
/*250*/ 0x2013, 0x0000, 0x0000, 0x0000, 0x25a0,
/*255*/ 0x0000,
);

function conv_nfo($str)
{
global $conv_table;

for($i = 0; $i < strlen($str); $i ++)
{
if($conv_table[ord($str[$i])] == 0)
{
$output .= code2utf(ord($str[$i]));
}
else
{
$output .= code2utf($conv_table[ord($str[$i])]);
}
}

return $output;
}

//code 2 unicode
function code2utf($num)
{
if($num<128)
return chr($num);

if($num<1024)
return chr(($num>>6)+192).chr(($num&63)+128);

if($num<32768)
return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);

if($num<2097152)
return chr($num>>18+240).chr((($num>>12)&63)+128).chr(($num>>6)&63+128). chr($num&63+128);

return '';
}
?>
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 你的转码规则从哪里找来的?好像缺几个字符


☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 15:20:39 2006) 提到:

小于 128 的那些 0x0000 对应的应该是 ascii
大于 128 的那些 0x0000 对应的是什么? iso-8859-1 ?
估计加入这部分就不会缺码了。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 网上找的,一个叫 nfo2txt.php,我按这个转换的:
: <?php
: $conv_table = array(
: ...................

☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 15:31:43 2006) 提到:

不是,你看这个代码的意思是,只对 0-255 之间的字符有一个转换表,
code2utf 函数只是把 unicode 转换成 utf8 编码而已。
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 小于 128 的那些 0x0000 对应的应该是 ascii
: 大于 128 的那些 0x0000 对应的是什么? iso-8859-1 ?
: 估计加入这部分就不会缺码了。
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 15:45:27 2006) 提到:

果然那些 0x0000 对应的是不需要转码的。
我们不需要自己去转 utf-8, Emacs自己会转的,
map里面直接用unicode码位值就行。
用这个新的 NFO.map,再

(define-charset 'nfo
"movie nfo."
:short-name "NFO"
:code-space [0 255]
:map "NFO")

(define-coding-system 'nfo
"movie nfo."
:coding-type 'charset
:mnemonic ?n
:charset-list '(nfo))

(modify-coding-system-alist 'file "\\.nfo\\'" 'nfo)

这样看nfo文件就没问题了。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 不是,你看这个代码的意思是,只对 0-255 之间的字符有一个转换表,
: code2utf 函数只是把 unicode 转换成 utf8 编码而已。


☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 15:52:03 2006) 提到:

强。
还有一个很搞不清楚的问题,怎样控制字符的宽度,比如在转换表里的这些字符如果都要
是一个英文字符的宽度应该怎么办?不知道按你前面那个 patch 里的方法设置字符宽度
不知道有没有效果?
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 把附件中的 NFO.map拷贝到
: /usr/local/share/emacs/23.0.0/etc/charsets/NFO.map
: 然后:
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 16:04:33 2006) 提到:

设置字符的宽度包括两个方面,
一个是在 char-width-table 里设为 1,
另一方面要找到合适的字体,
simsun之类的中文字体,
往往把那些格式化字符显示为 double width,
所以最好设个合适的英文字体:

(map-charset-chars
(lambda (range ignore)
(set-char-table-range char-width-table range 1))
'nfo)

(set-fontset-font "fontset-default" 'nfo en-font)

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 强。
: 还有一个很搞不清楚的问题,怎样控制字符的宽度,比如在转换表里的这些字符如果都要
: 是一个英文字符的宽度应该怎么办?不知道按你前面那个 patch 里的方法设置字符宽度
: ...................

☆─────────────────────────────────────☆
shgsun (shgsun) 于 (Mon Oct 30 16:19:44 2006) 提到:

那个en-font是从哪里来得?


【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 设置字符的宽度包括两个方面,
: 一个是在 char-width-table 里设为 1,
: 另一方面要找到合适的字体,
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 16:20:03 2006) 提到:

其实,我们可以利用这个功能自己做文件加密,
把 GBK.map shuffle 一下,
自己定义一个新的编码系统,
然后用这个编码系统书写文档。
这样至少可以达到国共内战时期的加密强度,
除非人家搞到你的 map 文件,
否则需要大量密文做统计分析,
才有可能破译。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 强。
: 还有一个很搞不清楚的问题,怎样控制字符的宽度,比如在转换表里的这些字符如果都要
: 是一个英文字符的宽度应该怎么办?不知道按你前面那个 patch 里的方法设置字符宽度
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 16:21:29 2006) 提到:

自己随便定义的:
(setq en-font
"-*-Bitstream Vera Sans Mono-normal-r-normal-normal-14-*-*-*-c-*-iso8859-1")

【 在 shgsun (shgsun) 的大作中提到: 】
: 那个en-font是从哪里来得?


☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 20:37:15 2006) 提到:

赞一个,虽然我看不懂perl :-(
不过最好把
0x00-0x7F 0x0000
加在里面,否则ascii部分还是明码。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 按这个想法,我写了一个程序生成 map,有兴趣的可以试试:
: #!/usr/bin/perl -w
: use List::Util qw(shuffle);
: ...................

☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 20:45:27 2006) 提到:

不是,我是把所有的字符都加进去了,因为 map 文件可以允许空缺,这样在 shuffle
会有很大问题,因为不能把整个表去 shuffle ,当然也可以用 并行数组。
我是把 GBK 填上后把其它的空位都用本身的下标填上了,这样起码所有的 gbk 加
ascii 都包括了。
可能直接用 0-0xffff 的下标数组进行随机分组,然后再 shuffle 可能会更好一些。
这样是一一对应的关系,而且不用读文件。

【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 赞一个,虽然我看不懂perl :-(
: 不过最好把
: 0x00-0x7F 0x0000
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 20:51:37 2006) 提到:

其实我们不必考虑GBK,
我们只要把 0-0x10FFFF 之间所有的数字 shuffle 一下,
再给它们按顺序编上 0-0x10FFFF 的号码就行了。
不过这样码表可能太大了,用 0-0xFFFF 就足够了。

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 不是,我是把所有的字符都加进去了,因为 map 文件可以允许空缺,这样在 shuffle
: 会有很大问题,因为不能把整个表去 shuffle ,当然也可以用 并行数组。
: 我是把 GBK 填上后把其它的空位都用本身的下标填上了,这样起码所有的 gbk 加
: ...................

☆─────────────────────────────────────☆
happierbee (吾生也有涯,而知也无涯) 于 (Mon Oct 30 22:49:38 2006) 提到:

用这个 elisp 的版本吧,也可以顺便检查一下有没有错误:
用法很简单,M-x ywb-generate-map 后把输出保存到 charsets 某文件里。
然后在 .emacs 里创建 coding,:map 中应该要和刚才保存的文件同名。编
码名字自己改就好了。

绝对保密。但是一旦丢了自己的 map 那就谁也不能读出来了。

;; 在 .emacs 里的配置:
(define-charset 'ywb
"ywb encode."
:short-name "YWB"
:code-space [0 #xFF 0 #xFF]
:map "ywb")
(define-coding-system 'ywb
"ywb encode."
:coding-type 'charset
:mnemonic ?y
:charset-list '(ywb))

;; 先运行下面的命令
(defvar ywb-map-group-size 255)
(defvar ywb-map-max-char #xffff)
(defun ywb-generate-map ()
(interactive)
(let ((i 0)
step
groups
pair
newgroups
start end)
;; put ascii random
(while (< i 256)
(setq groups (cons (cons i i) groups)
i (1+ i)))
;; random group other chars
(while (<= i ywb-map-max-char)
(setq step (random ywb-map-group-size)
groups (cons (cons i (min (+ i step) ywb-map-max-char))
groups)
i (+ i step 1)))
;; shuffle groups
(setq groups (append (shuffle-vector (apply 'vector groups)) nil))
;; merge groups
(setq pair (car groups)
groups (cdr groups))
(while groups
(if (= (1+ (cdr pair)) (caar groups))
(progn
(setcdr pair (cdar groups))
(setq groups (cdr groups)))
(setq newgroups (cons pair newgroups)
pair (car groups)
groups (cdr groups))))
(setq start 0)
(setq newgroups (cons pair newgroups))
;; print groups
(with-current-buffer (get-buffer-create "*map*")
(erase-buffer)
(dolist (pair newgroups)
(if (= (car pair) (cdr pair))
(progn
(insert (format "0x%X 0x%04X\n" start (car pair)))
(setq start (1+ start)))
(setq end (+ start (- (cdr pair) (car pair))))
(insert (format "0x%X-0x%X 0x%04X\n" start end (car pair)))
(setq start (1+ end))))
(display-buffer (current-buffer)))))

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 不是,我是把所有的字符都加进去了,因为 map 文件可以允许空缺,这样在 shuffle
: 会有很大问题,因为不能把整个表去 shuffle ,当然也可以用 并行数组。
: 我是把 GBK 填上后把其它的空位都用本身的下标填上了,这样起码所有的 gbk 加
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 23:38:14 2006) 提到:

哈哈,我也写了一个,从 emms 里偷了一个 shuffle 函数:

(defun encrypt-shuffle-vector (vector)
"Shuffle VECTOR."
(let ((i (- (length vector) 1)))
(while (>= i 0)
(let* ((r (random (1+ i)))
(old (aref vector r)))
(aset vector r (aref vector i))
(aset vector i old))
(setq i (- i 1))))
vector)

(defun encrypt-make-new-map ()
(interactive)
(let ((filename (read-file-name "New map file: " nil "MYKEY.map"))
(table (make-vector #x10000 0))
(idx 0))
(while (<= idx #xFFFF)
(aset table idx idx)
(setq idx (1+ idx)))
(encrypt-shuffle-vector table)
(get-buffer-create filename)
(with-current-buffer filename
(setq idx 0)
(while (<= idx #xFFFF)
(setq elt (aref table idx))
(insert (concat (format "0x%04X" elt) " " (format "0x%04X" idx) "\n"))
(setq idx (1+ idx)))
(write-file filename)
(display-buffer (current-buffer)))))

(define-charset 'encrypt-charset
"An encrypt charset in the range (U+0000..U+FFFF)"
:short-name "Encrypt charset"
:code-space [0 255 0 255]
:map "MYKEY")

(define-coding-system 'encrypt-coding
"Encrypt coding system."
:coding-type 'charset
:mnemonic ?e
:charset-list '(encrypt-charset))

【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 用这个 elisp 的版本吧,也可以顺便检查一下有没有错误:
: 用法很简单,M-x ywb-generate-map 后把输出保存到 charsets 某文件里。
: 然后在 .emacs 里创建 coding,:map 中应该要和刚才保存的文件同名。编
: ...................

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Mon Oct 30 23:44:21 2006) 提到:

原来有 shuffle-vector 这个函数啊,没想到,
我还从 emms 里翻了一个出来。
【 在 happierbee (吾生也有涯,而知也无涯) 的大作中提到: 】
: 用这个 elisp 的版本吧,也可以顺便检查一下有没有错误:
: 用法很简单,M-x ywb-generate-map 后把输出保存到 charsets 某文件里。
: 然后在 .emacs 里创建 coding,:map 中应该要和刚才保存的文件同名。编
: ...................

☆─────────────────────────────────────☆
jasonal (ronie) 于 (Tue Oct 31 00:24:08 2006) 提到:

VIM 的 :X 加密也是这个原理吗?
【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: 原来有 shuffle-vector 这个函数啊,没想到,
: 我还从 emms 里翻了一个出来。

☆─────────────────────────────────────☆
brep (哪个虫儿敢做声) 于 (Tue Oct 31 00:37:39 2006) 提到:

不懂VIM,一般的加密都是给个口令,然后用这个口令做密钥进行加密。
【 在 jasonal (ronie) 的大作中提到: 】
: VIM 的 :X 加密也是这个原理吗?


☆─────────────────────────────────────☆
runsnake (狂奔之蛇) 于 (Tue Oct 31 09:50:59 2006) 提到:

vim是Pkzip加密方法

【 在 jasonal (ronie) 的大作中提到: 】
: 标 题: Re: Emacs22 和 Emacs23 的内部编码原理
: 发信站: 水木社区 (Tue Oct 31 00:24:08 2006), 站内
:
: VIM 的 :X 加密也是这个原理吗?
: 【 在 brep (哪个虫儿敢做声) 的大作中提到: 】
: : 原来有 shuffle-vector 这个函数啊,没想到,
: : 我还从 emms 里翻了一个出来。
:
:
:
: --
: http://jasonal.spaces.live.com/
: http://jasonal.blogspot.com/
: alias (for those who can't access blogspot):
: http://pkblogs.com/jasonal
:
:
※ 修改:・brep 于 Oct 31 11:41:36 修改本文・[FROM: 59.66.78.*]
: ※ 来源:・水木社区 http://newsmth.net・[FROM: 212.14.75.*]