XWINDOWS系统使用指南(转载自清华BBS)六
<Btn5Motion> Button5 <Motion><BtnMotion> 任何按钮的 <Motion>
作用的格式和作用的表列
每一个转译在一或多个作用之上系结一个序列的一或多个事件。在表列中的个
别作用是以空白分开的。 (不可用逗点分开,那将会导致错误)。
个别的作用格式如下:
action-name(parameters)
即使没有参数被指定,在作用名称 (action-name)後的括弧,仍然不可省略。
例如:
start-selection()
如果在作用名称和左括弧中间留有空白,你将会得到一个错误。
作用名称只包含了字母、数字、钱号($)、底线(_)四种字元。每一个widget
提供它自己的作用集合 (如果有的话) ,且自我包含这些作用名称的硬码
(hard-coded)表列。
参数(parameters)是一个零到多个字元字串的表列,中间以逗点分开。参
数的意义为对特定的作用作指定 (事实上大多数的作用并没有任何参数) 。参
数字串可以不加引号,例如:
insert-selection(PRIMARY)
或者前後加上双引号,这种情形通常为参数字串内包含了空白或一个逗点,例
如:
string("plot<x,y>")
没有一个一般性的方法,让你在参数字串中的任何位置包含一个双引号,虽然
像这样 string(ab"cd)'将双引号放在字串中间是可被处理的。也没有一般性的
方法在同一个参数字串中同时包含字串和双引号。因为如此,有些widget在解
释它们自己的参数时,可以自行加入它们自己的语法规则。例如:对xterm 的
VT100 widget的 string()作用,如果一个不带双引号且开头为 "0x"的字串,
此字串被解释为代表一个ASCII 字元的十六进位数。
在此结束我们对转译规格及格式的描述。由此,你应有能力了解在不同X
手册列出的转译,且可写你自己的转译。为了帮助你,下节列出你常见的问题
,以及如何克服它们。
17.3 在转译规格中常见的问题
转译在观念上简单,但实际上很混乱。即使你常常使用,语法仍然复杂而难解。
无论如何,如果你是初学者,最好的方式是你以别人的转译当作自己的转译的
基础。在指南页中有几个对xbiff、xdm(目前尚未介绍过,将於第20章介绍
)、xterm 的转译范例,将对你有所帮助。
如果你发现你的转译有错误的话,有几点值得去检查:
.转译只能应用在使用Toolkit的程式上。如果你试图对非Toolkit应用程
式定义转译,看起来不会有任何问题,只是转译不会作用而已。
让我们来看一下为什麽,以对xcalc (这是一个非Toolkit程式)使用转译
为例。你对一个resource名称像 *xcalc*translations定义一个转译表,
且用xrdb载入至你的资料库。xrdb并不会抱怨,因为它不知道是那一个
应用程式使用到resource,它只会设定资料库,稍後供Resource Manager
查询。现在你执行xcalc ,它对转译是一无所知,所以不会向资料库查
询转译,当然也绝不会编译它们了。
.不要省略 #override,除非你确实知道你要做什麽。如果你因错误省略
它,例如在xedit 中,你将发现没有任何的键可输入任何的东西 (因为
预设的转译 "<Key>:insert-char()"被去掉了)。
.检查你对每一列均有终结。如果你在转译表中的一列忽略了"\n"或"\n"
,在其後所有的转译都会被忽略。如果你在最後一列的末端加上一个倒
斜线(\) ,或是省略了档案中最後一个新列字元(newline),整个转译表
都会被忽略。(不过这是xrdb的问题,而非转译管理器的问题)。
这种错误在你编辑一个现存的转译表时特别容易发生。
.当你定义的转译和预设有冲突时,可能会导致奇怪的行为,特别是对滑
鼠按钮事件,每一次按下或"Down"事件,会相关到一个松开或"Up"事件
,当你对此部份没有明确定义时,可能会有一个预设的系结仍然存在,
(键盘的按下和松开也是成对的事件) .所以:
1.检查预设系结的文件。
2.如果你只对按下/松开配对的一半指定一个转译,确定另一半并非预设
转译的一部份,如果是的话,需对它明确地指定一个转译。
3.如果你仍然不能解决,暂时由表中移去#override,这将去掉所有的预
设转译,让你了解问题是由於和预设转译冲突所造成,还是因为你的
转译表有错误。
.转译管理器对语法不正确的问题,无法很好的告诉你原因何在。例如如
果你有一个转译像:
<Key>F6: string("abc""def")
参数的语法并不正确,F6键将没有作用,但你也看不到错误讯息。
.如果你转译一序列的事件,且需要对每一个均指定修饰键,你必需明确
地对每一个都指定。例如如果你需要一个转译使用ctl-X ctl-K:
Ctrl <Key>X, Ctrl <Key>K: ...
而如果你使用:
Ctrl <Key>X, <Key>K: ...
你的指定为 ctl-X K
.检查你所需的widget是否有你指定的名称和类别。例如对xterm ,你可
以在一个表的开头指定:
xterm*Text*translations:
这将什麽事也没作,xterm 正规视窗widget的类别VT100。通常,不论
xrdb或转译管理器均不会有反应,因为看起来没错。
.转译可能指定正确,也可以工作,但它的作用和你预期的不符。例如对
xterm 的转译:
Meta Ctrl <Key>m: mode-menu()
是正确的,且会工作。但mode-menu()实际上检查滑鼠左或中按钮是否有
招唤它,其它方面不做任何事。
.在一个转译中不指定修饰键,并不意味著当修饰键按下时转译会无效。
它真正的意义为: "我并不在乎有没有修饰键" 。如果需要的话,使用
"None",""或!符号。使用时要小心预设的转译是否会妨碍到你。
.转译是针对widget而指定的,所有在转译中的作用必需由widget提供。
在你指定转译resource名称的地方很容易忘掉这一点。例如:
xman*translations: \
<EnterWindow>: reset()\n\
<LeaveWindow>: set()
将导致许多错误:set()和reset()作用只有被Command widget定义,但
xman有数种其它型态的widget可接受转译,且转译管理器会抱怨这些
widget并未提供set()和reset()。解决之道为更完整些的指定resource
名称,例如在本例为 xman*Command*translations 。
.对任何给定的resource,当resource资料库被询问时,Resource Manager
会传回一个值给widget,这个传回的值的 "特徵值" (characteristic)
(resource名称)大多与widget的和属性的完整类别/成员名称相符。所
以你对所有的Text widget指定一个一般性的转译後,又对xedit指定一
个转译,希望它们并存是不可能的,只有一个转译表会传给widget。例
如:
*Text*Translation: #override\
(对Text一般性的转译)
...
xedit*Text*Translation: #override\
(对xedit 的Text特定的转译)
...
你只能得到在xedit 易做图定的转译,或是在别处得到一般性的转译。
#override 会有所混淆,它的意义为 "把转译加入现存的之中" 。但这
完全由转译管理器处理,当时候到时,转译管理器会决定传递哪个值给
由Resource Manager所造的widget。对Resource Manager而言,#override
只是传递给widget值的部份中的一个文字字串而已。
因为你使用resource来指定转译,所以错误可能在两个领域均会发生。为
了减少错误的范围,当你对转译颇有经验时,在你已载入转译resource之後,
最好能明确地列印出你的resource资料库。例如:如果你对xprog 写入转译,
且转译在档案mytrans 中,以下列命令来执行程式:
xrdb mytrans ; xrdb -q ; xprog ...
17.4 结论
这漫长的一章涵盖了被X Toolkit 所使用的标准转译结构,它让你指定
按下一个键或按钮会有什麽影响。这些转译指定到每一个widget,且你藉著使
用标准resource结构传送转译表给widget。你看到如何对一个键盘的键、滑鼠
按钮和其它像移动一个指标进入视窗的事件作指定转译。然後我们藉著指定不
同状态的修饰键所造成的影响,比较严谨地定义我们需要转译的事件。
本章的第二个部份涵盖相同的领域,但较为正式,且详细解释在转译规格
中,可用到的语法,特别是修饰键。