分享
 
 
 

XWINDOWS系统使用指南(转载自清华BBS)

王朝other·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

xedit.vpaned.row1.Help.background:navy

是一个完整的规格但是将只影响到命名当中的物件名称的属性。(本例中,

尽管事实上是大写的,"Help"是一个成员名称,它的类别是"Command" 。)

除非你有一些非常特别的需求,最好不要用句点当分隔号,尽量以星号代

替,如此可减少错误发生的可能,而且在重写应用程式时,比较不会受到阶层

结构改变的影响。

上述的对应结构解释了为什麽你可以输入奇怪的规格,或者resource

和属性尚未定义:意即一个规格只有当应用程式查询资料库才会附著,甚至范

围的意义也是不足道的 -- 规格对应或不对应到查询。

15.3.4 当多种Resorce规格对应的居先(precedence) 规则

我们现在有一个非常弹性的方法来指定应用程式的resource,但正因它太

笼统,以致当一个应用程式查询resources 资料库时常常有数种规格与之对应,

如何解决呢?

简单地说,如果同时有超过一个规格对应,则最具体的(specific)一个会

被使用,Resource Manager有一组的居先规则用来决定是否一个规格较另一个

具体。

.使用句号为分隔号较使用星号为具体,例如:*Command.Foreground 较

*Command*Foreground 为具体。

.成员名称较类别名称具体,例如:*foreground 较*Foreground 具体。

.指定一个元素较省略它具体,例如:xmh*command*foreground较

xmh*foreground具体。

.元素靠近规格左边的星号较靠近右边的具体,例如:xmh*foreground较

*command*foreground具体。

这些规则相当直接,它们大部份可用另一种方法来说明:”如果一个规格

对应到另一个规格而为其子集合者,则前者较後者具体。”

15.3.5 在Toolkit 程式中应用程式Resource

通常一个应用程式使用Resource Manager来定义程式阶层中widget的属性

预设值,但有时需要有和widget不直接相关的设定预设值(或传值)的能力。

为了达到这点,Toolkit 提供了一个叫做Application Resource的设施,

它和非Toolkit 预设的外表原则相同 -- 应用程式定义了它本身选择的属性。

类别名称也相同,所以事实上这些属性和一般常见的阶层没有什麽不同。

xman使用到一点这个设施,它让你能在求助视窗(help window) 指定不同

的本文档案,是否在主选择视窗中指定一个你要的视窗,或当程式启动时直接

进入一个指南页等。(查看指南页,在X Default那一节,它会明确地列出它

的”应用程式特定的resources ”)。

15.3.6 Resource和non-toolkit 应用程式

并非所有的程式均使用Toolkit ,但Toolkit 几乎掌握了所有对一个应用

程式的resource管理,特别是应用程式的widget结构定义了物件和子物件的阶

层,并能适当地查询Resource Manager。但是non-Toolkit 应用程式要如何使

用Resource Manager?

答案是应用程式只需明确地查询每一个它有兴趣的属性。稍早我们曾说过

Resource Manager对resource无限制,因此应用程式能使用任何它想要的属性

名称,只要程式的文件告诉使用者它们在何处,它们就如同其它的应用程式一

样。

xcalc 应用程式是一个不使用Toolkit 的程式范例,它也利用上述方式掌

握resource规格。

有几点需要注意:

.此种型态的预设值没有类别。

.程式以类似类别名称(也就是说,第一个字母大写)来定义属性,例如

xcalc 使用Background, Foreground, BorderWidth 等等。

.如果大小写错误,你的规格不会工作,例如:规格

xcalc.foreground:green

会被xcalc 忽略。

.即使这个程式定义的属性并非阶层的一部份,你仍能使用星号当分隔号,

例如:

xcalc*Foregroundrange

15.4 Resources 的型态----如何指定值

直到现在我们仍然只看resource规格的”左半边”,而忽略了值(value)

的部份,或只是用色彩名称。现在,我们来看一看”右半边”(值的部份)。

简单地说,值只是一个传递到应用程式的本文字串,和Resource Manager

完全相关,之後,应用程式以此值做它所要做的事。当然,在实际的操作上,

应用程式必须明确地做某些事,而Toolkit 的确也掌握了大多数这一部份的工

作,所以你可获得一致地介面。

所以当我们以一个Resource值传递我们所需时,实际上我们使用少数的型

态,你已看过它们的大部份,你在任何地方均可以resource规格来使用它们:

Colours (色彩):我们已广泛的使用过它们----毋需多做解释。

Fonts (字型):在一般的方法我们已描述过,在resource规格,你也

可使用通用字元或全名。例如:

*Font: *-courier-medium-r-*-140-*

xterm*Font: 8*13

xterm*boldFont: 8*13

demo*font: *-courier-medium-r-*-240-*

demo*boldFont: *-courier-bold-r-*-240-*

设定一个整体性的预设字型,但使用一个正常的xterm 指定一个明确的一对字

型,和一对被demo应用程式使用的较大的字型。(可用xterm -name demo)

Numeric quantities:在不同的情形,例如:

xclock*update:30

xclock*update:60

BorderWidth:10

xlogo*Width:120

xterm*saveLines:200

Boolean values:指定"yes" 或"no",你可以使用"yes" 、"on"、"true"

和"no"、"off" 、"false" ,例如:

xterm*scrollBar:false

xman*bothShown:true

Cursor names:指定在/usr/include/X11/bitmaps中包含你所要的游标的

档案名称,例如:

xterm*pointer Shape:cntr_ptr

注意:如果被指定的游标不包含 "热点" (hot spot),你可能得到错误讯

息。

Geometry spec :全部或部份。

xcalc*Geometry: 180*240-0-0

xcolock*Geometry: -0+0

设定一个计算器的预设尺寸及其启始位置在右下角,时钟的启始位置在右上角。

键盘转换(keyboard translations) :安排特定的字串给一个键,或安排

特殊(非印出)动作给键或按钮,这相当的复杂,第17章会全面专门讨论它。

Pixmaps :Pixmaps 是像位元映像纹理(texture) 一般的图样,像位元映

像或游标一样的指定它们。当你在单色萤幕上工作时非常方便,一旦为不同类

别的widget设定背景,你便能看到应用程式在何处使用到它们。例如:以下的

resource规格:

*Pixmap: mensetmanu;

List*backgroundPixmap: scales

Box*backgroundPixmap: cntr_ptr

Command*backgroundPixmap: sipb

导致你的应用程式看起来很讨厌----你得到杂乱的视窗,每一个空间以某

种图样填满----但它们的确在作用,有时这样做可能会有用,backgroundPixmap

是类别Pixmap的属性。

15.5 结论

在这复杂的一章中,你看到了什麽是”resource”,和你如何使用它们指

定预设值或其它的值给应用程式,我们勾绘出Toolkit 大致轮廓,和widget的

阶层观念,并说明如何利用widget结构或应用程式的其它物件来设定较大范围

的预设值。从这里我们介绍类别的概念,它可以让你指定物件而无需知道它们

个别的名称,接著谈到Resource Manager和它在资料库中对应resource规格的

规则以便程式查询预设值,最後,我们大致说明如何指定它们的值。

本章专注於resources 结构运作的规则,现在是告诉你如何在系统下实际

使用的时候了。在下一章,我们告诉你如何及在何处储存预设规格,也就是说

,如何管理我们前述的”resource资料库”。在这章之後,我们解释如何使用

resource来定制你的键盘。

=====

第16章 实际的使用Resource

前一章解释X resources的规则----为什麽需要它们,结构如何工作和

resource规格的格式。本章中继续讨论resources ,但较强调实用性:我们告

诉你如何及何处设定resources 预设值,来影响你的系统的一部份或全部。在

本章结束前,我们将完成一些范例,点出你可能常见的错误,并告诉你如何克

服它们。

在这些范例中,我们假设你自己的工作站叫做venus ,并且大部份时间你

是使用它。从venus 的显示器,你可在远方的机器saturn和mars上执行client

应用程式且和venus 共享档案系统;neptune 则不可,我们曾在第4章描述过。

当你在本章中时,记得resource结构是:传递资讯给应用程式,通常这些

资讯是用来传递一些比较感兴趣的预设值(例如色彩和字型),但只要应用程

式取得协调你就能使用这种设施传递任何资讯。所以我们一般状况下倾向於把

”resource规格””预设值”(defaults)”resource”这三个名词视为同一含

意。

16.1 在何处储存resource的预设值

在上一章我们只告诉你输入resource规格到”一个资料库”,但未告诉你

如何做。事实上有几个不同的地方可以储存预设值:这些”地方”通常是一个

你可以用任何编辑器修改的简单的文字档案,但有一个特殊的位置需要特殊的

工具来设定它,我们先很快的给你一个概念,再讨论细节部份。

首先它的架构非常的复杂:包含命令列选项总共有八种设定resource方法,

但有两个重点需要注意:

1 .你最好只使用其中的一或二种设置,只要你做完启始设定,你将只

须改变预设的设定。

2 .系统是被设计来掌握许多不同模式的工作,和满足那些在许多显示器

上工作或在一台显示器上工作而存取远方机器的使用者的。

总结来说,这些设置是提供来让系统尽可能富於弹性,但任何时刻你将只

须存取其中的子集合而已。

16.1.1 设定Resource的八种方法

总共有八种方法设定resource,但它们可分为下面几类:

.应用程式专属的(Application-specific)resource:resource的表列,

限定档案只能被特定的应用程式读取。

.Server专属的resource:应用设定,不管应用程式在那一种主机上执行。

.主机专属的设定(Host-specific-setting) :对应用程式在主机上执行

有关的设定,和显示器无关。

.命令列选项:在执行时期做一次关闭(one-off) 设定。

应用程式专属的resource -- 方法1 和方法2

Toolkit 程式初始时在和应用程式直接相关的两个档案中寻找resource,

这些档案只能被特定的应用程式读取:

1 .应用程式--类别(Application-class) resource档案:这个档案包含

了机器一般性(site-wide) 对应用程式的类别之预设值,通常为系统

管理者所设定。它的名称就是应用程式类别的名称,在标准安装的系

统中它是储存在目录/usr/lib/X11/app-defaults 中,例如xterm 的

相关档案为:

/usr/lib/X11/app-defaults/XTerm

在core版中,有一个相关於Xmh 的此种档案,观察此档案可以看所使

用之设定的型态。

2 .你自己拥有的应用程式专属的resource档案:这个档案的名称和上述

相同,但它存放在不同的地方----由shell 变数$XAPPLRESDIR所指定

的目录,如果未定义,则放在home目录。例如对Xmh 类别的程式,它

的档案放在下列二者之一:

$XAPPLRESDIR/Xmh

$HOME/Xmh

你可以使用此种档案,处理方法1 中你不喜欢的 site-wide档案使其无

效。

Server专属的Resource -- 方法3 和方法4

这是对你目前工作的Server(显示器)做有关的设定。键盘的设定通常是

server专属的(因为不同的显示器有不同的键盘)。另一个server专属的特徵

为显示器是彩色或单色。

Resource和这些有关的项目会被所有与这个终端机相关的应用程式应用到,

并且不论应用程式在何主机上执行。(例如,如果你使用的显示器为单色,则

不管你的应用程式在何处执行,你还是不会要它使用彩色。)

储存server专属设定的方法是:

3 .server的RESOURCE_MANAGER性质(property):(你可在12章中xprop

的输出看到),使用下述的xrdb程式,你可以在server的根视窗的

RESOURCE_MANAGER性质中储存resource设定。它的优点如下:

(a) 你不需编辑任何档案即可设定预设值。(当你为了了解系统而实

验系统时特别有用)

(b) resource被server掌握,所以不论应用程式在那一部主机上执行,

均能被所有的应用程式应用。在我们的范例中,在neptune 的

情况下特别有用,甚至在不和我们的显示机器venus 共享档案系

统时,它仍然自动地选出为了使用此显示器所必需的resource设定。

4 .你的$HOME/.Xdefaults档案:(只有在根视窗没有RESOURCE_MANAGER

性质定义的情况下使用)。如果你对xrdb尚不熟悉,你便可以此档取

代,但你必须在每一部你执行client应用程式的机器上均设定一个。

主机专属设定 -- 方法5 和方法6

主机专属预设值和server专属相反,不管应用程式所使用机器的终端机为

何,只要应用程式在此主机上执行,均使用主机专属预设值,你可以用它们来:

.让应用程式在不同的机器上对不同的档案系统作计算,例如:被一个应

用程式读取的资料档案可能在不同的主机上保持不同的位置。

.区分显示在同一个萤幕上不同的主机的视窗(这些视窗可能由同一个应

用程式执行),例如:你可以要所有在mars机器上执行的xterm 的视窗

为红色的边框,而在saturn上执行的视窗为黄边。

.调高一个相同的应用程式在不同的client机器上版本的差异,例如:

xterm 在venus 是标准的MIT 版,但在neptune 机器上是由第三集团修

改过以适应机器结构的产品,这两版的xterm 可能并不完全相容。

主机专属Resource储存在:

5 .由$XENVIRONMENT 来的档案名称:如果shell 变数$ENVIRONMENT有被

定义,它会被解释为一个含有resource设定的档案之完整的路径名称。

6 .你的$HOME/.Xdefaults-thishost 档案:(当$XENVIRONMENT 未被定

义时使用)。注意它和我们先前的档案有所不同,它必须附加上主机

名称,例如,如果你在neptune 执行应用程式而在venus 显示(假设

RESOURCE MANAGER性质未定义),则server专属 resource 读取自:

.Xdefaults

而主机专属resource则是:

.Xdefaults-neptune

两者均在neptune 的家目录(home directory)中。

注意:在不同的小节中,我们曾说过类似”server专属resource读取自...”

这可能造成误导:”如果你实际需要,你可以放置任何型态的resource设定到

任何的档案或资料库。”我们真正的意思是你应该放置机器特性或不论甚麽的

resource到任何地方,如果你这样做,你将获得你需要的动作。

命令列选项 -- 方法7 和方法8

最後,你可以藉著命令列选项设定应用程式的值。通常当你设定预设值时

,为的是你不需要使用选项为你的程式作X相关的设定。但你实际上可以用它

们来:

.一次关闭(one-off) ,例如:你暂时性地在萤幕上需要一个极小的xedit。

.为了区别在相同应用程式中各自的成员,你已看过一个这样的例子,当

我们使用命令

xterm -name demo

来设定应用程式的成员名称给demo,将造成以应用程式名称为demo的

resource取代xterm 的resource。

命令列选项分为下列两种:

7 .应用程式专属选项:例如xclock的-chime的xpr 或-scale。

8 .Toolkit 标准选项:所有用到Toolkit 的应用程式均接受一些标准的

命令列选项,我们看过其中的大部份,包括-fg, -bg, -display,

-geometry 等等,标准选项的清单在”X Toolkit Intrinsics ”手

册的2.3 节中。

在其中有一个选项-xrm,重要的足以用一个小节来描述。

Toolkit 标准选项-xrm

大多数一般的resource均能被命令列选项明确地设定,例如你可以用

-bg colour设定视窗背景颜色。但无论如何,有一些resource并没有符合的选

项。为了克服这点,Toolkit 提供一个 "捕捉遗漏" (catch all) 的选项-xrm

(X Resource Manager 缩写)。

-xrm以一个引数当做resource规格,就如同你在预设值档案中输入的相同,

例如:你可以输入:

xclock -xrm "*update:30"

xclock -update 30

是相等的。

在同一命令列你可以使用数次-xrm,但每一次只能包含一个resource规格,

例如:

xclock -xrm "*update:30" -xrm "*chimen"

-xrm的好处在於你可以用它来设定任何resource供应用程式使用,尤其是

那些和命令列选项不符合的resource。其中一些非常有用的像:

iconX, iconY:视窗表徵图左上角x,y 座标的位置。

iconPixmap:被用来当作视窗表徵图的位元映像的名称,你可以用它

来指定任何的位元映像当作应用程式表徵图。(位元映像

为已有或利用bitmap程式建立。)例如:命令

xedit -iconic -xrm "*IconPixmap:cntr_ptr"-xrm "*iconX:500"-xrm "*iconY:400"

的意义为将xedit 设定以表徵图开始启始,表徵图的左上角

座标为(500,400) (在大多数的显示器会在萤幕中央),使

用名为cntr_ptr的位元映像来当作表徵图。

backgroundPixmap:设定用一个位元映像当作背景。

borderPixmap:设定以一个位元映像当作视窗的边,例如:

xclock -bw 20 -xrm "*backgroundPixmap: scales"-xrm "*borderPixmap: cntr_ptr"

执行xclock,用一个宽达20个像素的边框,视窗的背景为鱼鳞

(fish-scales) 图案,边框则用cntr_ptr的位元映像。

所有的这些resource当然也可用类别指定。(如IconX ,BorderPixmap等等。)

注意:请记住,-xrm只有在程式有用到Toolkit 才可应用。

16.1.2 设定Resource不同方法的摘要

现在我们将如何对一个指定应用程式resource设定的八种方法作一摘要:

应用程式专属resource:它们被两个档案掌握,且仅能被Toolkit 使用,

其中一个档案通常由系统管理者设定,另一个由你自己设定。

server专属的resource:不是存在根视窗的RESOURCE_MANAGER性质中,便

是在你的$HOME/.Xdefaults档案中。

主机专属resource:如果shell 变数$XENVIRONMENT 有定义的话,存在其

所定义的档案中,否则在你的$HOME/.Xdefaults-host 档案。

一次关闭设定:用应用程式的本身命令列选项来设定,和用Toolkit 标准

命令列选项,包含”捕捉遗漏”-xrm.

它们以下列顺序处理:

if (程式使用Toolkit )

读取 /usr/lib/X11/app-defaults/class档案 (1)

读取你的 $HOME/class档案 (2)

if (RESOURCE_MANAGER性质被定义)

处理内含的指定 (3)

else

读取你的$HOME/.Xdefaults档案 (4)

if (shell 变数XENVIRONMENT被定义)

读取所定义名称的档案 (5)

else

读取你的$HOME/.Xdefaults-host 档案 (6)

if (程式使用Toolkit )

处理标准的resource选项,包含-xrm (7)

处理应用程式本身的选项 (8)

现在我们将更详细的看一个较不熟悉的方法 -- 用来储存server本身

resource的方法。

16.2 在Server上储存预设值 -- xrdb

大部份预设值的结构均和档案有关,当应用程式启始时,不同的档案被读

取且其内容被处理,这种方式的缺点为你希望所有的client在一个特定的

server上使用同一组的预设值,但client所执行的机器上如果没有一个共同的

档案系统,你该怎麽办?

答案是在server本身储存预设值。X的性质设施是一个具有一般性目的的

结构。(记住,一个”性质(property)”是一小段已知格式资料的名称,被储

存在server),指定由server根视窗的RESOURCE_MANAGER性质载入,且当应用

程式启始时系统会注意此事。当视窗系统启始时,RESOURCE_MANAGER性质未定

义:如果你要使用这个设施,你必须明确地设定它。

并没有一个一般性的工具来操作一个性质,所以X提供了一个特殊的程式

来处理resource性质,它就是xrdb(the X Resource DataBase 公用程式)。

16.2.1 xrdb能为你做什麽

为了方便起见,本章剩馀的部份,我们只把RESOURCE_MANAGER性质和它的

内容当成”资料库”。

xrdb的功能非常简单,它让你能:

.设定一个新的资料库。

.看目前有那些resource在资料库中。

.在现存的资料库加入一个新的resource。

.完全去除资料库。

这些是基本操作,且很容易完成。当然也有一些更进一步的功能可以很精

确地让你控制resource,但我们先来讨论基本操作。

16.2.2 使用xrdb的基本功能

xrdb的操作类似大多数Unix的程式:它从一个档案或标准输入读取输入资

料,并且你可以用命令列选项来控制它的操作模式,它所读取的输入是我们曾经看

过的一系列resource设定,不过比较特别的是它把这些设定载入资料库,让我们看

一看它主要的功能:

设定一个新的资料库:输入下面命令两者之一:

xrdb filename

xrdb < filename

用以将一个档案中的设定载入到一个资料库中,如果只键入xrdb,表示你将由

标准输入(通常为键盘)直接输入设定,稍後我们将说明xrdb所接受的档案格

式,但现在先把输入resource设定当作和.Xdefaults档案或-xrm引数相同的方

法,例如,你可以用下列的方式定义xclock设定:

venus% xrdb

xclocks*Background: pink

xclock*update: 30

xclock*backgroundPixmap: cntr_ptr

<end-of-file>

通常你用一个档案当作xrdb的输入,也就是说,xrdb从一个档案载入预设

值作为你的视窗系统初始化的一部份。如果你很有经验,直接输入它的设定也

许容易些。

查看现存资料库中的内容,输入命令:

xrdb -query

则xrdb将以明白本文格式(plain text format) 印出资料库的内容(-query可

以缩写为 -q )。

(你可能记得也可以在根视窗用xprop 来看资料库的内容,但xprop 的输

出格式不太灵巧,它给你其它一大堆你不需要的资讯。)

如果需要,你可以抓取xrdb的输出到一个档案,编辑它,更改设定後可再

用它当作xrdb的输入。(下一项功能告诉你一个更好的方法)

注意:查看资料库,你必须使用选项-query。如果你忽略这个选项而只输

入xrdb,将造成会清除资料库,且xrdb在等待你自标准输入键入你

新的设定。

在现存资料库加入新的设定:加入新的设定到资料库且不要破坏原有的设

定,使用命令:

xrdb -merge filename

(-merge可缩写为-m,如果你省略档案名称,xrdb会自标准输入读取。)

xrdb自指定的档案中读取resource设定,并加入现存的资料库中;对於资料库

中已存在的resource,如果有新的设定,旧值会为新值取代,否则则不会变动。

完全移去资料库:如同先前所述,当系统结束时资料库会自动消失,但如

果你在系统仍在执行时移去资料库,使用命令:

xrdb -remove

本节介绍xrdb基本的功能,下一节我们介绍当你熟悉系统时,你可能需要

的更进一步的功能。

16.2.3 xrdb的档案格式

你已知道大多数的格式细节 -- 你可以用标准的resource规格的形式

characteristic: value

上述的格式你已看过多次,但xrdb有两个额外的规则:

1 .注解(comments):每一行的开头如果是惊叹号(!)会被忽略,所以

你可以此当作注解。

2 .xrdb预设将它的输入列传到C 前处理器。

让我们进一步看一看前处理器的过程。

xrdb前处理它的输入列

让我们看一看一个你可能碰到的典型问题。假设在一般的场景,你使用下

列显示器:

venus 彩色萤幕,正常解析度

saturn 单色萤幕,正常解析度

mars 彩色萤幕,高解析度

以上三者共享一个共同网路档案系统,当你在一个显示器上启动X,你需

要定义预设值来反应显示器的特徵。例如:在高解析度萤幕你可能需要较大的

预设字型,或是你不需要在单色系统上定义彩色预设值。

如何做呢?让我们看一看,如果你能使用.Xdefaults-host 档案:在

.Xdefaults-venus我们包含了彩色指定,而在.Xdefaults-saturn 我们只放入

单色型态的参数。行得通吗?当然,但是是有限度的:它只能掌握应用程式在

和server相同的机器上执行,如果应用程式在其它的机器上执行会得到它们主

机上的预设档案。所以如果你使用venus 且在saturn启始远方的client,将会

用到.Xdefault-saturn而错失所有的彩色指定。

你能够只使用.Xdefault 档案来区分机器吗?不能,因为三台主机共享相

同的档案系统,所以$HOME/.Xdefaults会被venus 获得也会被其它的机器获得。

答案是在resource处理程序的某些地方,有一个结构可以分辨出所使用

server的某些特徵。xrdb可以用相当简单的办法做到这点,它先定义一些说明

server特徵的C 前处理器符号,而後将它所有的输入传递到前处理器,最後将

处理过的资料载入资料库。指南页列出所有的xrdb定义的前处理器的符号,但

在此处我们需要用到的是:

X_RESOLUTION=n:n是每公尺长萤幕有多少像素。(根据我们的server,我

们正常解析度的萤幕为每□90个像素,相当於每公尺3454个像素。)

COLOR :只有萤幕支援彩色才被定义。

WIDTH,HEIGHT:萤幕的宽度和高度,单位为像素。

图16-1显示我们如何在xrdb的输入档案使用这些。(我们命名为

$HOME/.Xresources ,稍後我们仍将再度用到。)它可以正确地做到我们所想

要的 -- 它正确掌握了所有我们的显示器,不论是彩色或高解析度或两者都有。

一些要点值得注意:

┌—————————————————————┐

│ P197 FIG 16.1 │

│ │

│ 图16-1 利用前处理器命令的Resource档案 │

└—————————————————————┘

.你可以使用所有前处理器的功能。例如,我们使用它的表示掌握

(expression-handling) 能力:

#if X_RESOLUTION > 3600

.你可以在档案中任何地方使用前处理器符号,并不只是前面有# 号的列,

例如,当

xload*Width: WIDTH

在venus 上xrdb执行到时,它将会读取成:

xload:Width: 1152

所以由预设值可知,xload 视窗宽度将和萤幕宽度相同,高为80个像素,

且在萤幕的正上方。

注意:大多数Unix前处理器定义了一些和它们机器结构与作业系统相关的

符号,这些可能会干扰到你,特别是Unix通常定义的符号,现在

xrdb定义HOST为显示器名称中主机名称的部份,所以你可能认为你

可以像这样使用一个resource规格:

demo*title: X demo using display HOST

比方在venus 上,预期它相当於:

demo*title: X demo using display venus

事实上,在我们的机器上会得到

demo*title: X demo using display 1

原因为显示器名称是unix:0.0,所以主机名称部份为unix,但前处

理器已定义了unix,所以整个解释的顺序为:

HOST -> unix -> 1

你可以用xrdb的-u选项来解除符号的定义,用以克服这点,也就是

xrdb -Unix < filename

但即使如此,主机名称仍为unix,除非你明确地指定显示器:

xrdb -display venus:0 < filename

另一个会产生干扰的范例,如何你输入规格

xedit*Font: *-sun-screen-*

使用xrdb,现在用一个xrdb -query ,你可以看到在资料库中实际

地设定:

xedit*Font: *-1-screen-*

在我们sun 的机器上,前处理器定义成另一个符号。如果你使用和你的机

器相关的名称,你可能也会得到相同的效应。(如果你决定不需要前处理器的

功能,你可以用xrdb的-nocpp选项停止它的功能。)

16.2.4 如何将资料库设定和你的xrdb输入档连接在一起

藉著像前述在一个含有大量前处理器命令的档案执行xrdb,你初始化了资

料库,在稍後的期间,交谈式的使用xrdb,你将对资料库做大量的更动,现在

你需要记录这些设定,且将之与原来的输入档连接,以备将来之用。

如果你只使用xrdb -query ,你只能获得目前的设定:所有在输入档中的

条件指令列若和现在的server不符则不会被包含。例如在saturn上执行前述的

档案,则所有色彩和高解析度的设定,均被忽略(当然以 #开头的也不例外),

为了克服这点,xrdb提供-edit 选项,例如命令:

xrdb -edit myresf

连接目前在资料库中的值到档案myresf内存在的内容,它藉著比对resource指

定特徵值的部份做到这点:如果在档案中某一行和资料库中某一项特徵相同,

则档案中值的部份会被在资料库中的值取代,用此方法,所有的以 #开头的列

和条件设定均会保留在档案中。

注意:前处理器完全不可以使用-edit 选项,那会导致问题,我们看一

下当我们使用venus ,且以前述档案初始化资料库时,会发生什麽

情况,假设我们做了更动:

venus% xrdb -merge

XTerm*font: *-courier-medium-r-*-140-*

<end-of-file>

然後用命令:

xrdb -edit myresf

将设定更改的部份放回档案,我们看到两件事:

1 .前处理器符号在规格中值的部份会被字面(literal)值取代,

例如:

xload*Width: 1152 会被

xload*Width: WIDTH 取代

2 .在规格中只要特性符合,值均会被取代,甚至那些在条件段中

目前尚未应用到的也不例外。例如,在前述档案,设定

XTerm*font的那两行(一行在高解析度那段,一行在正常显示

器那段)都会被更改,即使我们只需要改变正常显示器也不例

外。

16.3 一些常见的错误和如何修正它们

特别是当你对系统是新手的时候,resource看起来相当的复杂。当有些状

况不能正常执行,而系统无法帮助你查觉是什麽错误,或你在何处犯了错误,

这里列出一些常见错误的明细,并提出如何修正它们。

.如果你未设定一个应用程式的名称和类别,确定在你的resource规格之

前加一个星号,(如果你省略这个星号,将没有任何东西会对应这个规

格)这个错误在你使用-xrm时特别常见,例如:

xclock -xrm "update:3" (错误)

xclock -xrm "*update:3" (正确)

.并非所有的应用程式均使用Toolkit ,非Toolkit 的程式不使用类别,

且它们的属性名称也可能不同。例如,规格

*geometry: 300*400+500+600

对xclock,xlogo 有效,但对xcalc 无效,因它不使用Toolkit ,xcalc

使用属性名称Geometry(开头为大写的G ),因为在这种情况,Toolkit

类别名称和xcalc 的属性名称相同,所以单独一个规格

*Geometry: 300*400+500+600

可以对所有这类的应用程式有效。

.你可能在规格中用了错误的属性或Widget的名称,特别是容易把类别名

称和成员名称搞混,例如:以下两者均错:

xclock*Update: 10

xclock*interval: 10

其它常见的错误如:

xterm*Text*background:blue

它不能执行的原因为xterm 并未使用Text widget ,xterm 正常的视窗

和Tektronix 的视窗分别使用widget类别 VT100和Tek 。最後,当你

知道一个widget是什麽类别,你可能对成员名称假设错误,不是widget

本身便是其中之一的属性。试著更换类别名称来修正这个问题。

.即使你已设定实际的widget和属性名称或类别,应用程式可能以不是你

预期的方式使用它们。例如:你可能设定如下:

xterm*Width: 40

xterm*Height: 10

意图用比平常较小的视窗启动xterm ,但它不能执行,xterm 只能在

Tektronix window应用这些值,无法在正常的视窗。

.你可能所有的设定完全正确,但仍然什麽也没发生,例如:

xmh -xrm "*inc.Label: Include"

是一个正确的方式,执行xmh 并指定label 为inc 盒的必须被"Include"。

但在标准系统的发行版,是没有任何动作发生的,原因是xmh 有一个应

用程式设定预设值档案/usr/lib/X11/app-defaults/Xmh ,其中有一行:

xmh*inc.label:Incorporate New Mail

这个规格较我们的设定有较高优先。

.将规格

*Width: 200

单独包含在资料库将导致大多数的Toolkit 程式启始失败,且有一个

讯息说它的"shell widget has zero height or width" 。如果你设定

height和width 二者之一,你必须也设定另外一个。

.如果你用编辑器建立一个resource档案,你可能省略了最後一个new line

这将导致当你试图用xrdb载入它时整个档案均被忽略。为了避免如此,

当载入resource时,用一个命令列像:

xrdb resfile; xrdb -query

如果xrdb无法列印出resfile 中的内容,就是有问题了。

.你可能忘了用-xrm选项的引数来获得resource规格,有时有人会把

resource规格放入一个档案,而以档案名称为-xrm的引数,预期它自此

档案中读取resources。

.最後,一个非常人性的错误,当你发生问题,你通常会循环动作:编辑

resource档案... 储存它... 载入resource到资料库... 执行应用程式

和看一看发生什麽状况。”其中载入resource到资料库”常常会被忽略

以致你更为困惑。

16.4 结论

本章中,你已看过了所有你能设定resource的地方,为何有这麽多种的方

法,如何决定设定放置在何处。你看到如何使用xrdb程式在server实际地储存

预设值,它们在何处被server所有的client存取,甚至它们可以在远方的机器

上执行。最後,有一些关於常见错误的实际提示,告诉你什麽需要注意。

你现在处於实际使用resources ,和剪裁你的系统适合你的口味,resource

结构功能非常强大且有无限的弹性,所以它可让你定制任何你需要的事。刚开

始不妨试一些像字型或色彩之类简单的设定,当你熟於基本的结构时,再转到

更高水准的例子。

下一章将告诉你如何使用特别形式的resource规格 -- Translations(转

译),来剪裁你的键盘以适於特别的应用程式。

=====

第17章 定制你的键盘和滑鼠 -- 转译

电脑的键盘通常含有一些 "特殊功能" (special function)键,在此有一

些方法来 "制定"(program)这些特殊功能键,使它们能完成特定的功能以适合

你工作的方式。例如,你可以定义一些键来输入那些你常用的命令,或只需按

一个键便能够输入一些程式的片段。

在X中,你能制定的不只是功能键而已,其它一般的键和滑鼠的按钮也都

可制定。对每一个应用程式,你均可指定特别的功能给键盘和滑鼠按钮,或两

者之组合。 (例如在 xedit中你可以结合SHIFT 键和滑鼠的右按钮来让你向前

移动一个单字)。 所有使用X Toolkit的程式均允许使用者利用一个被称之为

键盘转译 (translations) 的设施来执行此种定义,且此种定义藉著正规的

resources 结构传递给应用程式。 (那些不使用X Toolkit的应用程式,同样

地也可以用相同的设施来制定, 但它们需个别的定义所以不能广泛地应用,从

现在起,我们假设每当讨论有关转译的种种,均为对那些使用X Toolkit的应

用程式而言。)

就如同所有的 resources一样,转译是当应用程式执行时才被处置。例如

你可以拥有数个具备不同转译设定的 xedit,在同时一起执行。( 你可以让一

个xedit 适合编辑本文,另一个适合编辑程式码,而另一个适合编辑文书)。

本章讨论转译 -- 包刮它们的定义格式,如何将它们设定到应用程式,和

它们所涵盖功能的范围。我们首先以实例来介绍,逐渐地导引你看到不同的角

度。而後比较正式和详细地讨论转译。最後,我们列出当你使用转译时常会碰

到的错误,并给你一些如何克服这些问题的提示。

17.1 实际使用转译

Toolkit 转译结构最简单的用途便是让你制定你键盘的键。例如,当你使

用xterm 为一个执行一般shell 命令的视窗时,你可能希望定义一些特殊功能

键来输入你常用的命令,且希望指定的关系如下:

当我按下这个键时... 我希望这个字串被输入

F1 rm core *.tmp <newline>

利用Toolkit 达到此目的方法为:指定一个值给使用转译的widget中的resources

。此值设定应用程式中所必需的定制 (customisation),且被Toolkit 的 Trans-

lation Manager (转译管理器) 所处理。此 resources属於类别Translation,

且其成员名称几乎一定是translations。

在下一节我们将看到设定到resources 中的值的格式。

17.1.1 如何对一个应用程式指定转译

对前述xterm 的例子,我们定义 (在即将被应用程式读入的resource资料

库中或一些resource档案中) 一个规格类似:

xterm*VT100*Translations: (contd.)

<key>F1: string("rm core *.tmp") 注意:不完整!!

其意为在任何类别 VT100的 xterm widget 中,当键 F1 被按下时,插入

字串 "rm core *.tmp")。

不幸的是,并没有这麽简单,转译管理器会把上面的规格解释为 "去掉所

有现存的转译,且加入... " ,所以所有正常的像 " A键是插入一个 A" 这种

系结 (binding)都会消失。为了克服这点,你必需使用一些被称为 directive

(指引)的语法插入在 resource 值之前:

xterm*VT100*Translations: #override(contd.)

<key>F1: string("rm core *.tmp")

通常你会希望保持大部份现存的系结,而只是把你明确指定的值覆盖上去

,所以你一般都是在你的转译表中,指定 #override。

现在这个规格可以开始工作了,藉著启始一个 xterm且把此规格 (在两个

单引号 (')中间的部份) 当成选项 -xrm 的引数来测试它:

xterm -xrm 'xterm*VT100*Translations: ... 等等'

按下特殊功能键 F1,你将看到指定的字串成功的插入,但并未包含新列字元

(newline) ,你可以用一点语法的技巧来克服它,像:

xterm*VT100*Translations: #override(contd.)

<key>F1: string("rm core *.tmp")string(0xd)

这解释了以下两点:

1. string()的作用和它的引数相关。你可以直接输入本文 (例如 string(lpq))

,但如果本文包含空白或非字母字元,则必需在本文前後加上双引号。

如果引数是以 "0X" 开头,则将其後解释为十六进位,并插入相对的

ASCII 字元。(例如,0xd是RETURN)

2. 在你指定此功能时可结合一个以上的作用,在上例,我们用到 string()

作用两次,如果我们知道其它的作用,我们也一样可以系结起来。

定义许多的转译在一起

你可以根据需求在一个表中定义许多的转译。假设,我们在前面的转译中增加

系结:

当我按下这个键时... 我希望这个字串被输入

F2 lpq-Plpa3 <newline>

对此的转译为:

<Key>F2: string("lpq-Plpa3")string(0xd)

所以可以将本列加入前面的表中。但是转译管理器的格式规则告诉我们必需将

两个转译以 "\n" 分开且独立成为一列:

xterm*VT100*Translations: #override(contd.)

<key>F1: string("rm core *.tmp")sting(0xd) \n(cond.)

<Key>F2: string("lpq-Plpa3")string(0xd)

以上的形式将造成管理上的困难,你可以藉著包含 "隐藏的新列字元" 来使它

具可读性一些: (新列字元以倒斜线 ""处理)

xterm*VT100*Translations: #override\n<key>F1: string("rm core *.tmp")sting(0xd)\n<Key>F2: string("lpq-Plpa3")string(0xd)

你可以放置任意多个你所需的 "隐藏的新列字元" , 且几乎在任何地方均可,

它们只是被忽略而已。 (只要和转译管理器相关,甚至你每隔一个单字便使用

一个也没关系。但千万不要在一个规格的 resource 特徵部份使用它们,它们

无法被resource manager解释,也没有相同的效果。) 如果你感觉有些混淆,

不用担心。简单地说,resource结构需要的是要在一列中的一个resource规格

的 "值" 的部份,而转译管理器以分开的列来分开 (也就是以\n终结),而使用

者刚好以每一个实际分开的列代表一个意义以增加可读性,所以规则很简单:

在除了最後一列的每一个转译列均加上一个 "\n"。

17.1.2 转译可系结许多型式的作用

上述的 xterm范例,展示了如何能够当你按下一个键时,插入任意的字串。但

转译结构的功能比这更多 -- 它可以系结任何widget所提供的作用到按键,让

我们详细一点地看一下这些作用。

前述的例子,我们在 xterm的 VT100 widget完成了键F1和F2在 string()

上的对应。我们将仍以 xterm为例,说明更多的作用。

查阅xterm 的指南页,在标题KEY TRANSLATIONS 和 KEY/BUTTON BINDINGS

你将发现列有数个作用。我们将定义一个转译对应键F3到insert-selection()

作用之上,所以我们可以用键盘来取代滑鼠,将先前 "剪"下的本文 "贴"出。

指南页告诉我们此作用需要一个引数,从列出的预设系结,我们可以看出预设

的 "剪贴" 结构为使用 CUT_BUFFER0, 所以我们将CUT_BUFFER0当作引数。我们

的resource规格是:

xterm*VT100*Translations: #override\n<key>F3: insert-selection(CUT_BUFFER0)

到目前为止,这只是一点小小的便利。然而,假定说你花了许多时间在本文文

件上工作,你用 tbl格式化,你用 nroff在萤幕上预视 (preview)它们,用

troff 排版,且将输出送到你的一个用过滤器 (filter) 为tr2printer的印表

机上。设定转译为:

xterm*VT100*Translations: #override\n<key>F3: string("ed") insert-selection(CUT_BUFFER0)string(0xd)\n<key>F4: string("tbl") insert-selection(CUT_BUFFER0)string("| nroff -man") string(0xd)\n<key>F5: string("tbl") insert-selection(CUT_BUFFER0)string("| troff -man -t | tr2printer") string(0dx)

xterm 会确定这些转译是以xrdb自资料库载入或是在一个resource档案中,并

加以处理。现在当你启始xterm,用滑鼠 "剪"取你所需的工作的档案名称。接

下来,便可按F3键编辑它,按F4键预视它,和按F5键在硬拷贝上排版它。

更多的widget作用范例 -- xbiff

查阅xbiff 的指南页:在ACTIONS 的标题下,你将看到Mailbox widget所支援

作用的名单。它惟一预设的转译为当你按下任何按钮时降下信件 (mail)的旗帜

(flag)(作用unset())。我们将设定转译让你以键盘来运用这些作用,将这些作

用对应到 "?" 和 "UP" "DOWN"两个方向键如下:

? check() 有新的信件吗?

UP set() 升起信件的旗帜

DOWN unset() 降下信件的旗帜

以下是相关的转译表:

xbiff*Mailbox*Translations: #override\n<Key>?: check()\n<Key>Down: unset()\n<Key>Up: set()

以此测试之:用xrdb从你的resource资料库载入这些设定,然後启动xbiff ,

将指标移到视窗内。重复地按下Up和Down游标控制键以升起和降下信件旗

帜。

找出有哪些作用被提供

你对widget作用将和widget名称遭遇相同的问题:如何找出某个widget到底提

供哪些作用以及它们能做些什麽?同样地,没有一个完美的解答,但有一个合

理的方法来处理:

1. 查看应用程式的指南页。大多数的应用程式有它们自己专门的作用文件

。例如:xbiff 有一节叫做ACTION,而xterm 有两节关於转译和作用的

文件 -- KEY TRANSLATIONS 和 KEY/BUTTON BINDING。

2. 最初的指南页可能给你提示,或甚至直接告诉你它用到何种widget的类

别,所以你可以查看它的widget set文件中的特定的widget。(在 core

版中惟一的widget set为Athena,所以你在此不易出错)。即使指南页未

告诉你widget的类别,当你对系统熟悉之後,你将对一个widget是否为

标准型态较具有概念,如果还是不行 ...

3. 查看程式的原始码,看看用到什麽widget的类别,以及widget提供了哪

些作用。

17.1.3 转译系结作用到一序列事件,不只是单一键

我们已经看到转译让你设定插入,转译结构也能让你系结这些作用:它可以是

单一的键,或是一序列的键,或者是事实上一序列任何的X事件。

让我们继续以xbiff 为例,看看如何转译一序列的键盘字元。例如我们定

义字元字串的转译如下:

look check()

raise set()

lower unset()

以下为相关的转译表:

xbiff*Mailbox*Translation: #override\n<Key>l,<Key>o,<Key>o,<Key>k: check()\n<Key>r,<Key>a,<Key>i,<Key>s,<Key>e: set()

<Key>l,<Key>o,<Key>w,<Key>e,<Key>r: unset()

以此测试之 -- 载入设定和启动xbiff ,将指标移到视窗内。现在你可藉

著输入完整的字串来升起和降下旗帜。例如键入五个字元 r, a, i, s, e以升

起旗帜。对xbiff 的两个表有几点值得说明:

. 键的名称可以用不同的方式指定。正常的印出字元直接指定 (如"<Key>w")

, 其它的字元则拼出全名(如"<Key>Down").附录A "文件指引" 告诉你

在何处可查到键的名称,但在本节下面有更简单的方法。

. 对字元字串,你必需一一指定,并以逗点分开

(如"<Key>l,<Key>o,<Key>o,<Key>k").

. 转译可允许相同开头的键,例如 "look" 和 "lower" 均拥有相同的开头

"lo",对转译管理器不会形成问题。

找出键的名称

找出转译所需的键的名称,最简单的方法为执行xev ,将指标移到视窗内,按

下你所需的键,则键的名称会出现在括弧内字串keysym和一个十六进位数之後

。例如在xev 的视窗内按下游标控制键DOWN,它的输出如图17 - 1,在其中你

会看到

(keysym 0xff54, Down)

也就是说,键的名称为Down。

┌————————————————┐

│ P209. fig 17 - 1 │

│ │

│ │

│ │

│ 图 17 - 1 xev 显示键名称的输出 │

└————————————————┘

你可以在转译中使用任何型态的事件

到目前为止,我们所写的转译都是系结作用到一个按下的键盘字元。但我们曾

说过,转译结构可系结作用到任何事件,而不只於按下键盘而已。可能的事件

型态非常的多,在此我们只提及一小部份:

型态 意义

<Key> 按下一个键

<KeyDown> 按下一个键 (只是另一个名称)

<KeyUp> 放松一个键

<BtnDown> 按下一个滑鼠按钮

<BtnUp> 放松一个滑鼠按钮

<Enter> 指标进入视窗内

<Leave> 指标移出视窗外

我们已经使用过按下一个键的事件,让我们系结xbiff 作用到滑鼠按钮以取代之:

xbiff*Mailbox*Translations: #override\n<BtnDown>Button1: unset()\n<BtnDown>Button2: check()\n<BtnDown>Button3: set()

你可以看到语法和前面相似:你先给定一般性的事件型态 (例如 <Key> 或

<BtnDown> ),其後跟著你所需事件的事件细节部份 (例如s 和Button3) (

Button 1, 2, 3分别对应到左、中、右按钮)

对一序列的事件的转译

就如同我们定义了一序列按下键事件的转译(set,unset和check),我们当然

也可以定义一序列的滑鼠事件。事实上你转译的一序列的事件可以任意组合在

一起,你可以在一个转译的左边随意混合事件的型态。所以你可以定义如下的

转译表:

xbiff*Mailbox*Translations: #override\n<BtnDown>Button1, <Key>?, <BtnDown>Button3: check()\n<BtnDown>Button1: <Key>u, <BtnDown>Button3: unset()\n<BtnDown>Button1: <Key>s, <BtnDown>Button3: set()

也就是说,用到check(),你必需依序先按下按钮1 (左按钮),然後按下"?"

键 ,最後按下按钮3 (右按钮)。 这个范例并不是很好,但对於一些危险或不

可取消 (irreversible) 的作用 (例如删除一个档案,或是覆写一个缓冲区的

内容) ,你可以依照这种方式来使用转译。你需要使用一个非常谨慎的命令序

列,才能用到此作用,这样使得使用者不可能因意外而输入此命令。

使用非键盘和非滑鼠事件的转译

通常你是对按下或放松滑鼠按钮或键盘的键定义转译。但我们曾经说过,你可

以对任何事件设定转译,例如指标移入或移出一个widget的视窗。让我们以

xman的主选项视窗 (图10 - 3) 为范例来解释它。这是一个相当人为的范例,

因为它没有任何用途。但无论如何,它很容易被看出在做些什麽操作。

查看xman的指南页,在X DEFAULTS标题下,你将看到概括的xman所用到的widget

的名称和类别:主选择项视窗widget的名称叫topBox,类别名为Command。这

是一个好的猜测,因为在选单操作盒的方法。我们可用第15章所提过的技巧

来确认它,使用以下的命令:

xman -xrm "*Command*backgroundPixmap: scales"

且所有的Command widget将会有鱼鳞状的背景)。

这和我们先前的范例有一个重要的不同:我们所用到的作用不是由特定的应用

程式指定,而是由标准的widget提供 (本例中为Command widget,在 "X

Toolkit Athena Widget"使用手册中有描述)。

在我们定义任何东西之前,先来看一看此widget预设的功用,以便我们能

够了解有些什麽事发生和有哪些widget的作用会做。启动xman,移动指标进入

Help 盒,你会看到盒的外框变成高亮度 -- 这是highlight() 在作用。将指

标移出,盒的外框恢复正常 -- 这是unhighlight() 作用。将指标再度移入

Help 盒,按下一个滑鼠按钮,保持按住不放。则盒内的色彩反转 (盒内的文

字变成预设的背景色,而原来视窗的背景变成视窗的前景色)。-- 这是set()

在作用。继续保持按住滑鼠按钮,将指标移出视窗外,盒内色彩恢复正常 --

这是reset() 在作用。一个正常 "碰触一下" (clicking on) Help盒的次序为:

1. 移动指标进入盒中:highlight()将外框变为高亮度。

2. 按下按钮:set() 反转盒中的色彩。

3. 松开按钮:notify()开始作用,造成程式建立求助视窗(help window)

。在进行中时,盒的色彩保持反相。当视窗建立完成之後,reset()反

转盒内的色彩为正常,但外框仍保持高亮度。

4. 将指标移出视窗:unhighlight()将外框恢复正常。

现在你了解了有哪些作用,我们将定义一些转译来改变原先进出视窗的作

用:

*Command*translations: #override\n<EnterWindow>: reset()\n<LeaveWindow>: set()

用这个奇怪的转译表,当你一开始移动指标进入盒中,什麽事也不会发生,但

当你移出指标时,色彩会反转。如果你再度移动指标进入盒中,色彩会变回正

常。其它的作用和前述相同。

使用修饰键来修饰事件规格

有时你指定的转译希望能同时按下一或多个修饰键 (modifiers) ,例如你要系

结一个作用到和META键同时按下的一个键,或是当CTRL和SHIFT 同时按下的滑

鼠按钮。到目前为止我们还没有任何办法可指定如此。我们不能用事件序列达

成这点,因为它是依序定义的,而我们需要的是指定同时,例如 "按下X 键且

CTRL键同时被按下"。

欲在转译中指定修饰键,你只需在事件名称之前加上你所需的修饰键名。

例如在xterm 中,定义meta-i为 "贴" 上一次 "剪" 的本文,使用:

*VT100*Translations: #overrideMeta <Key>i: insert-selection(PRIMARY, CUT_BUFFER0)

因为这种修饰键/事件型态的组合十分常见,转译管理器允许使用一种缩写的

形式。相等於上面第二列的写法为:

<Meta>i: insert-selection(PRIMARY, CUT_BUFFER0)

我们可以对滑鼠事件做同样的处理。让我们对xedit 定义转译,使得使用

滑鼠可以在本文上方便地移动,我们首先的尝试如下:

*Text*Translation: #overrideShift <Btn1Down>: forward-character()\nShift <Btn2Down>: forward-word()\nShift <Btn3Down>: next-line()\nCtrl <Btn1Down>: backward-character()\nCtrl <Btn2Down>: backward-word()\nCtrl <Btn3Down>: previous-line()

如果你测试它,奇怪的现象会发生 -- 游标好像会自行其是,而且本文的片段

会一下子被选择,一下子又取消选择。发生这种现象的原因是Text widget 的

预设系结仍然会作用,它包含的转译像:

<Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0)

你可能认为这不会影响你,因为当你松开按钮时你总是按著SHIFT 键或CTRL键

。但事实上会作用:转译管理器对於你未定义的修饰键解释为你不在乎它们的

影响,所以松开Button1 时会对应到上述的规格。为了克服这点,我们对那些

可能不小心便会发生的按钮松开事件定义转译,并系结到一个空 (null) 作用

。这些转译当被对应到时会盖掉预设的转译。对使用Text widget 我们需再增

加两列,才是一个完整的转译表:

*Text*Translation: #overrideShift <Btn1Down>: forward-character()\nShift <Btn2Down>: forward-word()\nShift <Btn3Down>: next-line()\nCtrl <Btn1Down>: backward-character()\nCtrl <Btn2Down>: backward-word()\nCtrl <Btn3Down>: previous-line()\nShift <BtnUp>: do-nothing()\nCtrl <BtnUp>: do-nothing()

这解释了下列几点:

.我们对滑鼠事件使用了缩写的语法,也就是先前的语法像<BtnDown>Button1

以<Btn1Down>取代。转译管理器容许一些缩写的语法存在。 (我们在前

面看到的 <Meta> 也是一例)。

.我们用 do-nothing() 当作一个哑 (dummy)作用,就好像它是列在Text

widget的文件中一般。事实上这个作用是不存在的,因此会导致错误的

讯息出现,但因为我们本来就是要用它来什麽事也不做的,所以无需介

意。

.对於我们方才指定的哑作用,我们用了一个事件 <BtnUp>便代表了三个

按钮。相同地,转译管理器把从缺的修饰规格的解释为 "对任何",在一

个事件中缺少细节部份 (例如在规格"<BtnUp>Button1"中"Button1"的部

份) 解释为 "对任何所有的细节部份"。

这点在转译中有一个非常常用的形式为:

<Key>: ...

因为缺少细节部份,所以可被用於所有按下键 (key-press)事件,也就

是对所有的键。事实上在Text widget 上有一个预设的转译为:

<Key>: insert-char()

insert-char()作用的功能为当一个键被按下时,插入相对应的ASCII字

元。

17.1.4 复合的转译表及范例

到目前为止,我们把所有的转译均应用於整体的widget类别。但你能对个别的

widget指定转译,就如同resource一般。在此我们将对xman定义更多的转译。

我们将对Help盒widget (对应作用到助忆(mnemonic)字元)只用到键盘事件,对

Quit盒只用到视窗事件。为了达到此点,我们将对转译应用到的widget 给予明

确的名称。我们的转译表如下:

*Help*translations: <Key>h: highlight()\n<Key>u: unhighlight()\n<Key>n: notify()\n<Key>s: set()\n<Key>r: reset()\n<Key>LineFeed: set() notify()

Quit*translations: #override\n<EnterWindow>: reset()\n<LeaveWindaw>: set()

有几点特别的语法需要注意:

.在此我们对相同类别中不同的widget指定不同的转译,所以我们需要知

道成员 (instance) 名称。不幸的是,这些成员名称 (Help,Quit,

Manual Page)并不明显。如果它们在文件中找不到 (本例即找不到),那

你只能用猜的或是去查看原始程式了。

.对於Help,我们省略了常用的#override,因为我们对此widget不需要考

虑任何预设的系结。特别的是,当指标进入视窗时,我们不要此widget

呈现高亮度,如此我们才能看出这个转译的效用。

.由於省略 #override,我们将这个转译规格移至第一列。(如果不这麽作

,而且对第一列仍以\n\ 作结束,我们将得到错误:

X Toolkit Warning: translation table syntax er-

ror: Missing ':' after event sequence.

X Toolkit Warning: ... found while parsing ''

因为\n是用来区隔转译规格或类似像 #override 指令的)。而将此列和

第一个规格以隐藏的新列字元区隔,就如同:

*Help*translations: <Key>h: highlight()\n...

.对LineFeed那一列的转译,包含了复合的作用,和前面xterm 中复合的

string()作用类似。

我们已大致涵盖了你所常用的转译。基本的概念很简单,生成它们的结构

也不复杂,但它们非常的令人迷惑。原因是它是一个发展中的糸统,随著发行

版本所附的文件并不是很多。下一节重复本节所述的,本节均以例子来介绍观

念,下一节我们将对转译的规则,作比较正式的描述。

17.2 转译 -- 格式和规则

转译是一个由Toolkit 提供的一般性结构,它让使用者指定当某些特定的事件

由widget接收到时,一个widget应完成何种作用。Toolkit 中处理转译的部份

被称之为转译管理器。

转译由widget指定,它的确是一个widget的每一个成员。一个转译的集合

称之为一个转译表,而这个表藉著标准的resource结构传递给应用程式。widget

(对转译而言意味深长) 会有一个Translation 类别的resource属性,通常的

成员名称为translation。这个转译resource期待的一个值即为一个转译表。就

像所有其它的resource一般,你可以在同一个应用程式对不同的widget指定不同

的resource,而且你能以类别名称或成员名称或二者混合来指定它们。

每一个widget定义了它所提供的作用,不论是在数量或型态上,它们都是

极富变化的。

转译可被各种不同型态的事件指定,不仅只於键盘和滑鼠事件而已。任何

序列的事件均能被处理,就如同单一事件一般。

转译和转译表在 " X Toolkit Intrinsics " 使用手册附录B一节中,有

简洁地描述。它不是初学者查看转译的好地方,但它含有完整的事件型态、修

饰名称等等的表列,在此不再赘述。

17.2.1 转译表的格式

一个转译表大体上的格式如下:

[optional-directive\n] list-of-translations

每一个 list-of-translations 由一或多个转译组成,格式如下:

event-sequence : list-of-actions

当event-sequence发生时,规格中的list-of-actions 会由widget所完成。如

果在一个表中,有多於一个的转译,每一个需以 "\n" 区隔开。

我们首先来看一下选项的指令,然後看一下list-of-translations的细节

部份。

17.2.2 转译指引 -- #override 等等

选项指引 (directive) 告诉转译管理器,它应对任何已设定之相关widget在此

转译集合中应如何处理。

#replace : 清除所有现存的对应,只采用在转译表中所含有的。(只使用新

的)。

#override : 强制留下现有的对应,加入转译表中。如果在表中有任何项

目设定,旧有的即被覆写。也就是说,旧有的被新有的取代。 (结合

旧有的和新的,但新的比较重要)。

#augment : 强制留下现有的对应,加入转译表中。如果在表中有任何项

目设定在现有的设定存在,使用旧的而忽略新的。 (结合旧有的和新的

,但旧的比较重要)。

如果未设定指引,预设为 #replace 。

17.2.3 个别的转译规格格式

每一个转译的格式为:

event-sequence : list-of-actions

让我们来看一看此规格的两个部份。

事件和事件序列(event-sequence)的格式

一个事件序列包含一或多个事件规格(event-specs), 其格式为:

[modifiers] <event-type> [repeat-count] [detail]

除了事件型态(event type)外,均为可选择。(<>中为必需)。

modifiers : 这是基本设计中比较精巧的部份,我们在下一段说明。

event-type : 指定我们有兴趣的事件的型态,例如按键(<KeyDown> )、

松开按钮(<BtnUp> )或指标离开视窗(<Leave> )等等。

detail : 指定我们有兴趣的特定型态。如果你省略细节栏(detail field

),事件规格将对应到任何detail,如此,<Key>将对应到所有的按键

事件。此格式指定到每一个事件型态。对指定事件型态的细节栏为:

.对<Key>、<KeyUp>和<KeyDown>事件,细节如果不是键的名称(例如

"<Key>s"),便是 keysym (keysym是按键以开头为"0x"的十六进位

数表示,将於下一章详细解释)。

.对於按钮事件,细节就是按钮的名称,也就是 Button1 ... Button5

中的一个。例如我们先前使用过的"<BtnDown>Button1"。

型态/细节的缩写:常用於转译管理器的一些事件型态和细节的组合,允许

你对它们使用缩写:

缩写 相等的全名

<Btn1Down> <BtnDown>Button1

...

<Btn5Down> <BtnDown>Button5

<Btn1Up> <BtnUp>Button1

...

<Btn5Up> <BtnUp>Button5

repeat-count : 这指定了事件需要的次数。如果被指定,它们被包含在

括弧之中。例如:

<Btn1Down>(2)

指定需对一号按钮(button-1)碰触两次。如果你在後面再加上加号(+)

,其意为碰触的数目需大於或等於指定。例如:

<Btn1Down>(3+)

意为需碰触三或更多次。预设的重复次数为一次。

一个事件序列以一或多个事件规格组成,以逗点分开。当这个事件的序列

在其widget发生时,相关的作用便会运作。

当序列发生时,转译管理器会根据一些规则决定它自己是否被满足。我们

用一个例子以便仔细地观察,假设你对两个字元序列set 和unset定义了转译:

.概略地说,如果个别的事件依序发生,转译管理器会被满足,其它的事

件 (那些你未指定的事件) 如果在指定的序列中间发生,不会妨碍序列

被满足。例如,set 可被sweat 和serpent 对应。

.如果介於其间的未指定事件,启动了转译表中的另一个事件序列,转译

管理器会放弃原先的序列,而尝试著去满足新的序列。例如,set 不会

被sauerkraut对应,因为u 会使得转译管理器对应到unset。

.如果在一个事件的集合中有超过一个的事件序列发生,转译管理器只会

应用到一个转译:

- 如果一个序列对应到结束 (右端),较短的那个序列只有在不包含於

较长的序列才会发生。所以如果unset 被对应到,对set 转译将不会

作用。

- 如果一个序列是在另一个序列的中间发生,例如,如果你定义序列

at和rate,则较长的那个永远不会被对应到。

事件修饰键

修饰键 (modifiers)是一些键或按钮,系指当主要事件发生时,那些必需被按

下才会让转译管理器满足的键或按钮。你可以对键、按钮、移动、进出视窗等

事件指定修饰键。常见的修饰键为:

Button1 ... Button5

Ctrl Shift Meta

Lock

如果你未指定任何的修饰键,转译管理器会解释为: "当事件发生时,不

论修饰键是否被按下,均会被接受"。例如,<BtnDown>会被满足,不论当时

SHIFT 或META键是否有被按下。

如果你真的需要指定 "只有在没有修饰键被按下时才接受此事件"。则需使

用虚拟修饰键 (pseudo-modifier) None。例如,None <BtnDown> 会使得当按

钮按下时若META键也被按下则不会满足。

对一个事件指定一些修饰键意为 "只要符合转译中指定的修饰键,其它的

修饰键不需介意"。它并没有 "一定要完全恰好符合才可以"的意思。例如,

Ctrl <Key>a 在你按下 meta-ctl-shift-a 时仍会被满足。

如果你真的要指定 "只有刚好符合修饰键的才要",在修饰键之前加一个惊

叹号 (!)。例如,!Ctrl <Key>a 在你按下 meta-ctl-shift-a 时不会被满足。

对一个修饰键的集合 (可能是空集合) 作限制,意为 "除了这些修饰键不

不接受",需要在不接受的修饰键之前加一个(~)号。例如,Shift~Meta <Key>t

会被ctl-shift-t满足,不会被meta-shift-t满足。

键事件通常忽略大小写,如果你要区分,需在之前加一个冒号(。例如,

不论 H或 h均可符合<Key>H,但只有H 才符合 :<Key>H。

就如同对常用的事件型态/细节配对有缩写一般,转译管理器对常用的修

饰键/事件型态配对同样地提供缩写:

缩写 相等的全名

<Ctrl> Ctrl <KeyDown>

<Shift> Shift <KeyDown>

<Meta> Meta <KeyDown>

<Btn1Motion> Button1 <Motion>

BBS水木清华站∶精华区

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有