BBS水木清华站∶精华区
发信人: BloodDreamer (血梦), 信区: Linux
标 题: kfm
发信站: BBS 水木清华站 (Tue Jul 20 15:25:24 1999)
发信人: PeterPan (血梦◇信仰天长地久的爱情), 信区: Unix
标 题: 改进kfm
发信站: 一网深情 (Tue Jul 20 15:05:05 1999), 转信
1 解决的问题
KDE 1.1中所带的kfm是一个文件管理器兼浏览器, 有速度快占用资源少并且支持 frame
的优点。遗憾的是, kfm并不适合浏览中文网站, 原因如下:一、kfm只在出现空格处断
行, 而对连续的汉字串不做断行处理;二、 kfm中指定不用代理服务器的站点, 只能通
过完整IP或域名, 或其右部子串。对于国内大量无域名的网站只能通过完整IP加以逐个
指定 (这是由于IP地址是从前往后分配的, 如202.115.*.*是教育网中的IP, 而对域名
而言 *.edu.cn是教育中的域名);三、kfm直接以字符方式显示中文, 导致在一些 X-Win
下无法正确显示繁体网站, 若保留字符方式, 则须对码制做相应的转换。
2 问题的分析与解决思路
2.1 关于汉字断行。
断行的问题有两处, 一处是 kfm作为文件管理器, 对于汉子文件名, 在需要断行时如何
正确断行的问题。这一部分在文件kfmman.cpp(kdebase包中)中的函数:
void KFMManager::writeWrapped( char *_str, int _maxlen );
中, 对其加一改进加如对汉字的判断可在扫描字符串时设置一个状态字, 在"英文",
"汉字第一字节", "汉字第二字节"三种状态中转换, 并在适当时断行。
第二处是kfm作为浏览器, 在这部分, KDE中定义了基类HTMLObject, 各种HTML对象都作
为HTMLObject的派生类, 以下是与文本有关的HTML对象:
HTMLHSpace:水平空格
HTMLVSpace:垂直空格(如换行)
HTMLText:其间不可断行的文本对象
HTMLTextMaster:其间可以断行的文本对象
HTMLLinkText:其间不可断行的超连接文本对象
HTMLLinkTextMaster:其间可以断行的超连接文本对象
其中HTMLLinkText是HTMLText的派生类, HTMLLinkTextMaster是HTMLTextMaster的派生
类。HTMLTextMaster是为自动断行而设计的, 它将为每一行分配一个 HTMLTextSlave对
象。为了内存的有效利用, 所有的文本本身是存放在HTMLTextMaster中而非HTMLTextSlave
中的。
文本断行的主要工作在htmlobj.cpp(kdelib包中)的函数:
HTMLFitType HTMLTextSlave::fitLine( bool startOfLine, bool firstRun,
int widthLeft )
中完成。此函数通过调用库函数index与rindex完成断行点的寻找:
char *index(const char *s, int c);
char *rindex(const char *s, int c);
index返回字符c在字符串s中出现的第一个位置, rindex返回字符c在字符串 s中出现
的最后一个位置, 若字符c没找到则index与rindex都返回NULL。
fitLine检查当前的HTMLTextSlave对象是否能在给定的宽度 widthLeft中完整显示,
若能完整显示则返回 HTMLCompleteFit, 否则尝试能否通过断行使其在给定宽度中显
示, 若能则返回HTMLPartialFit, 并设定断行信息, 若断行也不能达到目的( 根本无
处断行或给定宽度不足以显示最短的词) 则返回HTMLNoFit。
由于 fitLine是通过查找空格来确定断行点的, 在当前文本中全是汉字就不会有空格,
则fitLine将因为根本无处断行而返回HTMLNoFit。为了解决这个问题, 可以将对 index
与rindex的调用替换成两个新的函数, 故添加函数 splitword与rsplitword作为 index
与rindex的替换。
splitword返回给定字符串的第一个可断行点, rsplitword返回给定字符串的最后一个可
断行点.
若按上述思想完成相应的改动, 会发现大多数汉字显示得到了改进, 但仍有一些汉字串
得不到正确的断行, 原因在于这些串被 kfm当成了不可断行的字符串处理,
也就是说在为这些串生成相应的HTML对象时是生成的HTMLText而不是HTMLTextMaster。
这段代码在html.cpp(kdelib包中)中的函数:
void KHTMLWidget::insertText(char *str, const HTMLFont * fp);
中。该函数中设有一个标识当前串是否为可断行串的标志字textType, 有unknown,
fixed, variable三中取值, 通过分析发现只需将textType的初值及其后的一次赋值从
unkown改为variable就能阻止错误的HTMLText类型的生成。
2.2 关于不使用代理服务器的网站
只要找到判断是否需用代理服务器的代码, 就能改变判断的方法, 使之更加合理。
在源代码中查找"proxy"对查找结果一一分析, 最后发现相关代码在http.cpp(kdebase
包中)中的:
int revmatch(const char *host, const char *nplist);
函数中。http.cpp并不是kfm的一部分, 它属于 kioslave。关于它的响应改动请参见所
附源代码。
因为制定IP范围比指定域名范围更全面更方便, 我在http.cpp(kdebase包中)中的:
int KProtocolHTTP::OpenHTTP( KURL *_url, int mode,bool _reload );
函数中加如了一些代码, 在用户用域名指定时若所准定域名不在不用代理服务器的网站
范围之内, 则将其转化为IP地址再检测一次, 这就使用户可以只指定不用代理服务器的
IP范围而不必为IP和域名分别指定了。
2.3 关于大五码到国标码的转换
GCE的hztty中有码制转换功能, 可以将其原代码加以改造得如下三个文件:
b2g.c,b2g_tables.c,hzconvert.c(hzconvert.c从io.c中截得).
为了为每个kfm窗口指定转换与否, 在kfmgui.cpp中为kfm窗口加入一个菜单项"Force
Big5 to GB"并设置相应变量, 为kfmview.h中的类KfmView加入从其父类 KHTMLView中继
承的虚函数:
virtual void write( const char *_text );(写HTML串)
由于KfmView中保存有对应KfmGui类的指针, 故可检测菜单项" Force Big5 to GB"是否被
选中, 若选中则在调用KHTMLView::write之前对_text进行码制转换。
3 问题的解决
对kde源代码加以改进, 并填加必要的新代码:
改动的源文件 所属程序 所属包
html.cpp libkhtmlw.la kdelib
htmlobj.cpp libkhtmlw.la kdelib
kfmgui.cpp kfm kdebase
kfmman.cpp kfm kdebase
kfmview.cpp kfm kdebase
kfmgui.h kfm kdebase
kfmview.h kfm kdebase
http.cpp kioslave kdebase
添加的源文件 所属程序
b2gconfig.h kfm
b2g.c kfm
b2g_tables.c kfm
hzconvert.c kfm
源程序已上到202.115.16.8/pub/Linux/WM/KDE/kde1.1.1src/modified_for_chinese/
(凡是改动的文件, "//blood >"与"//blood <" 之间所夹内容为添加之内容, "//blood
remove it"后的封注行为被移去的行。)
时间仓促, 难免又不周全之处, 有什么问题自己动动手或者和我联系吧, 不过因为放假
回家不能及时收信的说.
我在自己编译kde1.1.1时遇到些麻烦, 建议先安装可执行包, 再将改动的部分编译而覆
盖之, 这样就保险多乐:))))))))
祝好运.
蜀南血梦
blood_dreamer@126.com
BloodDreamer@263.net
--
的 规 就 吧 狱 下 我
饿 则 如 爱 你 来 是
死 撑 同 情 也 吧 天
胆 死 商 的 跳 我 堂
小 胆 场 规 下 是 你
的 大 的 则 来 地 跳
※ 修改:.PeterPan 于 Jul 20 15:06:15 修改本文.[FROM: 202.115.16.23]
※ 来源:.一网深情 bbs.uestc.edu.cn.[FROM: 202.115.16.23]
--
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 202.115.16.23]
BBS水木清华站∶精华区