Previous Next Contents

4. The X Window System

Like the console mode, the X environment also requires some setup. This involves setting up the input mode and the X fonts. Both are being discussed below.

4.1 The X fonts.

First of all, you have to obtain the fonts having the Cyrillic glyphs at the appropriate positions.

If you are using the most recent X (or XFree86) distribution, chances are, that you already have such fonts. In the late 1995, the X Window System incorporated a set of Cyrillic fonts, created by Cronyx. Ask your system administrator, or, if you are the one, check your system, namely:

  1. Run 'xlsfonts | grep koi8'. If there are fonts listed, your X server is already aware about the fonts.
  2. Otherwise, run
    find -name crox\*.pcf\*
    
    to find the location of the Cyrillic fonts in the system. You'll have to enable those fonts to the X server, as I explain below.

If you haven't found such fonts installed, you'll have to do it yourself.

There is some ambiguity with the fonts. XFree86 docs claim that the russian fonts collection included in the distribution is developed by Cronyx. Nevertheless, you may find another set of Cronyx Cyrillic fonts on the net (eg. on ftp.kiae.su), known as the xrus package (don't confuse it with the xrus program, which is used to setup a Cyrillic keyboard layout. Hopefully, tha letter one was renamed to xruskb recently). Xrus has fewer fonts than the collection in Xfree86 (38 vs 68), but the latter one didn't go along with my Netscape setup - it gave me some really huge font in the menubar. The xrus package doesn't have this problem.

I would suggest you to download and try both of them. Pick up the one which you'll like more. Also, I'm going to creat RPM packages soon for both collections and download them both to ftp.redhat.com and to my FTP site.

There are also older stuff, for example the vakufonts package, created by Serge Vakulenko, which was the base for the one in the X distribution. There are also a number of others. The important point is that the fonts' names in the old collection were not strictly conforming to the standard. The latter is fine in general, but sometimes it may cause various weird errors. For example, I had a bad experience with Maple V for Linux, which crashed mysteriously with the vakufonts package, but ran smoothly with the "standard" ones.

So, let's start with the fonts:

  1. Download the appropriate fonts collection. The package for XFree86 may be found at any FTP site, containing the X distribution, for example, directly from the XFree86 FTP site. The xrus package may be found on ftp.kiae.su
  2. Now when you have the fonts, you create some directory for them. It is generally a bad idea to put new fonts to the already existing font directory. So, place them, to, say, /usr/lib/X11/fonts/cyrillic for a system-wide setup, or just create a private directory for personal use.
  3. If the new fonts are in BDF format (*.bdf files), you have to compile them. For each font do:
    bdftopcf -o <font>.pcf <font>.bdf
    
    If your server supports compressed fonts, do it, using the compress program:
    compress *.pcf
    
    Also, if you do want to put the new fonts to an already existing font directory. you have to concatenate the old and the new files named fonts.alias in the case both of them exist.
  4. Each font directory in the X must contain a list of fonts in it. This list is stored in the file fonts.dir. You don't have to create this list manually. Instead, do:
    cd <new font directory>
    mkfontdir .
    
  5. Now you have to make this font directory known to the X server. Here, you have a number of options:
    xset +fp <new font directory>
    xset fp rehash
    
  6. Now restart your X. If you have done everything right, the tests in the beginning of the section will be successful. Also, play with xfontsel(1x) to make sure you are able to select the cyrillic fonts.

In order to make the X clients use the Cyrillic fonts, you have to set up the appropriate X resources. For example, I make the russian font the default one in my ~/.Xdefaults:

*font:         6x13

Since my cyrillic fonts are first in the font path (see output of 'xset q'), the font above is taken from the "cyrillic" directory.

This just a simple case. If you want to set the appropriate part of the X client to a cyrillic font, you have to figure out the name of the resource (eg. using editres(1x)) and to specify it either in the resource database, or in the command line. Here go some examples:

$ xterm -font '-cronyx-*-bold-*-*-*-19-*-*-*-*-*-*-*'

...will run xterm with some ugly font; and

$ xfontsel -xrm '*quitButton.font: -*-times-*-*-*-*-13-*-*-*-*-*-koi8-*'

...will set a Cyrillic Times font for the Quit button in xfontsel.

4.2 The input translation

The switching between the different input translations is set up by the xmodmap program. This program allows customization of codes emitted by various characters and their combinations. It sets the things up based on the file containing the translation table.

If you don't want to deal with all these tricks and you prefer having a solution right away, either download an appropriate xmodmap table, available at many sites dealing with the Cyrillic, for example, ftp.kiae.su or ftp.funet.fi. Also, I made the table, described below, available at my FTP site.

More convenient alternative is to install the xruskb package, which allows you to configure most of the input translation parameters without having to know about xmodmap.

The following is a simplified description of input customization. If you want to do more sophisticated tricks, refer to the xmodmap(1) or, even better, wait for the next major X release, which will hopefully address the current input problems.

In our case, the translation table should define two things:

The table of characters

This is basically a sequence of directives which assign the certain keysyms to a specified keycodes. The general syntax is the following:

keycode code = sym1 sym2 sym3 sym4

where code is the numerical code of the given key on the keyboard (refer to the standard table for your system. In my case it is stored in the file /usr/lib/X11/etc/xmodmap.std). The syms define the keysyms emitted by that key in different conditions. Sym1 is the keysym emitted by the key in a regular state, sym2 corresponds the key in shifted state (usually when Shift is held down). Sym3 and sym4 define the keysyms emitted when the Mode_switch is active for the normal and shifted states respectively (group 2, according to the X Protocol Specification). In our case, the active Mode_switch corresponds to the Cyrillic input mode.

These should be either hexadecimal codes or the symbolic constants from /usr/include/X11/keysymdef.h (without leading "XK_").

Thus, if we wanted the key corresponding to the Latin 'a' generate the Russian 'a' in the alternative mode, we would write the following:

keycode 38  =  a  A  0xC1 0xE1

The reader might be curious why I don't use the Cyrillic_a and Cyrillic_A constants respectively. The answer is that it didn't work for me. I am not very familiar with the guts of the X Window System specification, but I've got the following explanation. The symbolic constants above have the values 0x6C1 and 0x6E1 respectively. This means that in really multi-lingual environment they could be successfully used without overlapping with any other character set. However the KOI-8 standard is not well suited for such environment. Thus, since we want to retain compatible with the past, we will violate the rules of multi-lingual support in the X Window System.

The following is a table for the most popular russian JCUKEN keyboard layout (these tables are derived from the ones in the vakufonts package):

keysym  4             = 4               dollar          4       quotedbl
keysym  5             = 5               percent         5       colon
keysym  6             = 6               asciicircum     6       comma
keysym  7             = 7               ampersand       7       period
keysym  q             = q               Q               0xCA    0xEA
keysym  w             = w               W               0xC3    0xE3
keysym  e             = e               E               0xD5    0xF5
keysym  r             = r               R               0xCB    0xEB
keysym  t             = t               T               0xC5    0xE5
keysym  y             = y               Y               0xCE    0xEE
keysym  u             = u               U               0xC7    0xE7
keysym  i             = i               I               0xDB    0xFB
keysym  o             = o               O               0xDD    0xFD
keysym  p             = p               P               0xDA    0xFA
keysym  bracketleft   = bracketleft     braceleft       0xC8    0xE8
keysym  bracketright  = bracketright    braceright      0xDF    0xFF
keysym  a             = a               A               0xC6    0xE6
keysym  s             = s               S               0xD9    0xF9
keysym  d             = d               D               0xD7    0xF7
keysym  f             = f               F               0xC1    0xE1
keysym  g             = g               G               0xD0    0xF0
keysym  h             = h               H               0xD2    0xF2
keysym  j             = j               J               0xCF    0xEF
keysym  k             = k               K               0xCC    0xEC
keysym  l             = l               L               0xC4    0xE4
keysym  semicolon     = semicolon       colon           0xD6    0xF6
keysym  apostrophe    = apostrophe      quotedbl        0xDC    0xFC
keysym  grave         = grave           asciitilde      0xA3    0xB3
keysym  z             = z               Z               0xD1    0xF1
keysym  x             = x               X               0xDE    0xFE
keysym  c             = c               C               0xD3    0xF3
keysym  v             = v               V               0xCD    0xED
keysym  b             = b               B               0xC9    0xE9
keysym  n             = n               N               0xD4    0xF4
keysym  m             = m               M               0xD8    0xF8
keysym  comma         = comma           less            0xC2    0xE2
keysym  period        = period          greater         0xC0    0xE0

Also, for those using the russian YAWERTY layout, I include the following table:

keysym  q             = q               Q               0xD1    0xF1
keysym  w             = w               W               0xD7    0xF7
keysym  e             = e               E               0xC5    0xE5
keysym  r             = r               R               0xD2    0xF2
keysym  t             = t               T               0xD4    0xF4
keysym  y             = y               Y               0xD9    0xF9
keysym  u             = u               U               0xD5    0xF5
keysym  i             = i               I               0xC9    0xE9
keysym  o             = o               O               0xCF    0xEF
keysym  p             = p               P               0xD0    0xF0
keysym  bracketleft   = bracketleft     braceleft       0xDB    0xFB
keysym  bracketright  = bracketright    braceright      0xDD    0xFD
keysym  a             = a               A               0xC1    0xE1
keysym  s             = s               S               0xD3    0xF3
keysym  d             = d               D               0xC4    0xE4
keysym  f             = f               F               0xC6    0xE6
keysym  g             = g               G               0xC7    0xE7
keysym  h             = h               H               0xC8    0xE8
keysym  j             = j               J               0xCA    0xEA
keysym  k             = k               K               0xCB    0xEB
keysym  l             = l               L               0xCC    0xEC
keysym  z             = z               Z               0xDA    0xFA
keysym  x             = x               X               0xD8    0xF8
keysym  c             = c               C               0xC3    0xE3
keysym  v             = v               V               0xD6    0xF6
keysym  b             = b               B               0xC2    0xE2
keysym  n             = n               N               0xCE    0xEE
keysym  m             = m               M               0xCD    0xED
keysym  backslash     = backslash       bar             0xDC    0xFC
keysym  grave         = grave           asciitilde      0xC0    0xE0
keysym  equal         = equal           plus            0xDE    0xFE
keysym  3             = 3               numbersign      3       0xDF
keysym  4             = 4               dollar          4       0xFF

The mode switching rules

This is the trickiest part of the X Cyrillic setup. You should define the conditions in which the current mode is switched between the regular and the Cyrillic one.

There are two ways to achieve that in Linux. One is XFree86-specific, while the other is more general (well, not too much, as I'll show below).

The XFree86-specific way is the following. There are two virtual actions which can be assigned to the keys in the XF86Config file: ModeShift which changes to the mode alternative to the regular one without locking, and ModeLock which does the same but with locking. In the first case the keys will emit the alternative keysyms only when the key generating the ModeShift is held down, whereas in the latter case the user needs to press the key generating the ModeLock keysym only once and the keyboard will be generating the alternative keysyms until that key is pressed for a second time. You should assign the ModeShift and ModeLock keysyms to the keys you want to work the mode switches.

Thus, if one wants to assign the ModeShift action to the right Alt key, she should place the following directive in her XF86Config:

RightAlt        ModeShift

Similarly, if the action required was ModeLock, the directive would be:

RightAlt        ModeLock

See the XF86Config(4/5) for more details.

The other way is, again, to use the xmodmap utility. This is also tricky. Generally, what you should do is:

Now the key to which the ModeShift is assigned will act as a mode switch. This means that while it is held down, the keyboard is in alternative mode.

Moreover, if you add a lockable key to that modifier's map, this key will lock the alternative mode.

Note: There are some problems however. Serge Vakulenko (vak@cronyx.com) pointed out that the different X Server implementations may have different rules of assignments the mode switches (like, for example, some servers restrict the set of the keys which may work in toggle mode to, say, CapsLock, NumLock, and ScrollLock). Hopefully, this is a subject to change in the next release of the X Window System. For more details, see the X Protocol specification.

Unfortunately, I didn't manage to make the CapsLock key have the same functionality in the alternative mode, namely, to lock the upper case. It seems to me, it is impossible to do it, because of the idiotic X input translation design. If I am wrong, please correct me.

Let's see an example. Suppose, one wants to use the right Alt as a mode switch and the ScrollLock as as a mode lock. First of all, one should check the default modifiers' map. This is accomplished by running the xmodmap without arguments:

$ xmodmap

xmodmap:  up to 2 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25)
mod1        Alt_L (0x40),  Alt_R (0x71)
mod2        Num_Lock (0x4d)
mod3      
mod4      
mod5

According to the above, the plan of attack is the following:

  1. remove the Alt_R key from the mod1 map
  2. assign the Mode_switch keysym to the Alt_R key
  3. assign the Scroll_Lock keysym to the keycode 78 (the code of the actual ScrollLock)
  4. add the Mode_switch to the spare (mod3) map, and
  5. add the Scroll_Lock keysym to the mod3 map

Thus, here is the solution:

remove mod1 = Alt_R
keysym Alt_R = Mode_switch
keycode 78 = Scroll_Lock
add mod3 = Mode_switch
add mod3 = Scroll_Lock

If you use the latter solution, you may combine both the table and the mode directives in your ~/.Xmodmap file.

Such files are generally supplied with the various X Cyrillic stuff packages. The good example is the tables in the old package by Serge Vakulenko described above.

Once you have such file containing the table, you should run the command:

xmodmap filename

...every time you start X. Modify your X startup file to do it. The system-wide file is /usr/lib/X11/xinit/xinitrc; the personal one is either ~/.xinitrc, or ~/.Xclients, or ~/.xsession, depending on what you have.

NOTE: If xmodmap complains on your table, try to load the default table first. The default one is usually located in /usr/lib/X11/etc/xmodmap.std.


Previous Next Contents