Keyboard and fonts
6 September 2005

This file describes various troubles I had on sokrates getting Norwegian fonts to display properly in the Linux console, with a keyboard that works like the one in x-windows.  In brief,

  • just reconfigure locales (to NO-nb-8859-1)
  • install-keymap /usr/share/keymaps/i386/qwerty/no-x1.kmap.gz (defines custom keymap as default)
  • consolechars -f lat9u-16 (gets you euro symbol € too)

Remaining issues

  • KDE konsole needs font encoding 8859-15 to display the euro, and it won't save this setting as default
  • the no-standard keyboard should be bugreported to console tools
  • assign volume to the volume keys in console -- you can use amixer set Master 2+ -q

Installation history

Defining a default keyboard

Discovered that console-tools has the install-keymap utility, which takes a keymap file name as argument:

The file is passed to loadkeys for loading, so that valid values for this argument are the same as that of arguments to loadkeys. install-keymap expands include-like statements in that file, and puts the result in /etc/console/boottime.kmap.gz, which will be loaded into the kernel at boot-time.

This is clearly the way to do it -- just issue,

install-keymap /usr/share/keymaps/i386/qwerty/no-x1.kmap.gz

and you have your default boottime keyboard. Very nice. Now, my first method was simply to copy the custom Norwegian keyboard, calling it /etc/console/boottime.kmap.gz, and this worked great. You might want to check that doing it properly like this also has the desired effect, as the include commands will have changed the keyboard.

Also installed kbd-compat, which I assume translates commands from the kbd package into those of the console-tools package.

Reprogramming the volume keys

The sound volume keys, Fn-PgUp and Fn-PgDn, don't work correctly in console. A "showkey -t 5 -k shows PageUp has the 'make' code 0x68 (which is hex code, or decimal 6x16+8=104) and the 'break' code 0xe8; while PageDn has make code 0x6d (or decimal 6x16+13=109) and break code 0xed.

In the US keyboard we're using, keycode 104 plain has been assigned "Prior", which is to say PageUp, and shift has been assigned "Scroll_Backward". Since Ctrl and AltGr don't have their own definitions, they also produce "Prior". Similarly, keycode 109 plain has "Next" and shift has "Scroll_Forward".

Further, in console, "showkey -k" shows that Fn-PageUp triggers "0x73 0xf3", or 115, and Fn-PageDn "0x72 0xf2", or 114. In the US keyboard we're using, 115 (Fn-PageUp) has been assigned the keysym "Help" (it has no function in nano) and 114 (Fn-PageDn) the keysym F14. The F14 string is in turn assigned the string value "\033[26~", which has the effect of Ctrl-w or search in nano. Simply removing these functions did not will restore the sound volume control function, but I added "amixer set Master 2+ -q\n" to Fn-PageUp and 2- to Fn-PageDn. Now, how do you get this defined as a keysyms-type function, so that pressing the key performs the action rather than typing it out at the command prompt?

To edit the keyboard file, issue

gunzip /usr/share/keymaps/i386/qwerty/no-x1.kmap.gz

edit with "/usr/share/keymaps/i386/qwerty/no-x1.kmap" and and then gzip it afterwards. Load it with /usr/local/bin/no.

There are other mistakes in this keyboard definition file, now called us-x1. For instance, on the x1, Scroll lock is on 0x46 or keycode 71, while us-x1 puts scroll lock on 70. This is surprising -- you would have thought such assignments would have to be standard.

In the no-x1 keyboard definition file I defined scroll lock on 70; there was nothing there. The scroll lock light lights up when you press Fn-F5, but of course this doesn't mean the linux console knows it should be on -- though it's likely xorg does. In fact different programs may handle scroll lock in different ways in console.

In brief, I could add volume control to the keys, but only as a string, as I don't know how to define this in terms of keysyms.

Reprogramming the hibernate key

The Fn+F1 "Hibernate" key generates a scancode that isn't recognized by Linux, but dmesg tells you how to define it -- give it a keycode, such as 155:

setkeycodes e00a 155

This in turn allows you to assign a script to the key in the keyboard definition file, which in our case is no-x1.kmap.gz. You first assign the script to a spare variable, in this case I used F20, and then you assign the F20 variable to keycode 155. Pressing the key will now trigger the dvale script, as sudo, which will prompt non-root users for a password (unless the sudoers file lets them skip it). I wrote a new dvale script as the /etc/acpi/hibernate.sh script is so slow. It works beautifully -- but only in the linux console, not in x-windows.

The keycode must be set on each boot, so I added the setkeycodes line above to the /etc/init.d/bootmisc.sh script.

More good news: it turns out that /etc/console/boottime.kmap.gz really is the keyboard that is used by the kernel on boot. I ran "install /usr/share/keymaps/i386/qwerty/no-x1.kmap.gz" to create your custom version; it now loads on boot. This means full support for Norwegian letters, the euro sign, and programmed keys are available by default. The are also accepted and correctly shown on the command line and can be used in script names.

To switch between US and Norwegian keyboards in console, type us or no on the command line. The US keyboard also has the programmed hibernation key, and the euro symbol in the AltGr-4 position (the dollar sign is on shift-4, as usual), but obviously not the Norwegian letters.

If you ever figure out how to get the script to be called without needing a command-line prompt, you can create a single script that switches between the keyboards and put it on Alt-Tab.

Note that all of this is still dependent on the two other steps taken, as outlined in this file: locale must be nb-NO-8859-1 not UTF-8, and the console screen font, which must still be loaded on boot (and after suspend) with "consolechars -f lat9u-16", must be iso 8859-15, which is to say latin9, which is to say a Western European keyboard with a euro sign (the -16 is a size indicator). The setting is done in /etc/console-tools/config (which is read on boot) and repeated in /etc/acpi/resume.sh and /usr/local/bin/dvale.

Finally, note that you can set locale in ~./bashrc, with

export LC_ALL=C
export LANG=en_US
export LANGUAGE=""

to determine the language of your error messages, nano, etc. Norwegian is default.

In addition, programs look at the environmental variable LANGUAGE to
determine which language to run in; this can also be set in .bashrc. The
current default setting is nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en_GB:en,
which tells applications to prefer bokmål, then nynorsk, norsk, dansk,
svensk, britisk engelsk, and finally any engelsk. This means you get
some programs in Danish and Swedish if you're using the default
settings; this is controlled through the LANGUAGE environment variable.

Backspace for Delete

The Delete key in the Norwegian keyboard backspaces -- solved
by loading one of the other Norwegian keyboards (standard, not latin1).

Unicode woes

Summary

There was a problem with the console font -- Norwegian letters
displayed incorrectly in nano and in Linux console error messages, even
on a fresh boot. Issuing "just reconfigure console-tools -p low"
improved matters, but it seemed to be unstable. Switching locales from
UTF-8 to 8859-1 appears to be the stable solution -- these problems are
essentially unicode problems.

Details

Norske bokstaver i linux consoll feilmeldinger og nano:

liten ae      blir A-tilde brokenbar        (æ blir æ)
liten acircle blir A-tilde yen (å blir Ã¥)
liten oslash blir A-tilde comma (ø blir Ã,)
stor acircle blir A-tilde tilde E (Å blir Ã~E)

After a resume from suspend to disk, the same values now use
the a box-drawing sign instead of A-tilde, and an upside down U rather
than a brokenbar. Clearly the character set is different -- this is the
default kernel console screen font.

This means you're operating with three different console fonts
-- the kernel console font, compiled in; the default console-tools
console font; and the preferred console-tools font, specified in the
configuration file.

The letters that used to show fine in nano now don't --
notably, small oslash has become a large omega, and large acircle has
become large acircumflex. In a way this is hopeful since it shows it's
perfectly possible to change character set. Running just reconfigure
console-tools reset the glyphs to their former appearances.

Here are the keys typed in using the default bootmap:
æøå ÆØÅ So is that the problem?
The default bootmap is wrong for oslash?

If I load the alternative norwegian keyboard, this doesn't seem
to change -- æøå ÆØÅ -- the
letters still display the same way.

Now, /usr/share/consolefonts has a set of fonts from the
console-tools package. At the bottom of /etc/console-tools/config is the
name of the screen font:

SCREEN_FONT=lat0-sun16

This appears to refer to
/usr/share/consolefonts/lat0-sun16.psf.gz

OK, I got the command:

% consolechars --default-font # load PC font, just to be sure

% echo -e '\033%8'              # set Unicode output mode
% ls -N # show filenames (raw)
% echo -e '\033%@' # set Latin1 output mode again.

Loading --default-font changes oslash to a degree sign,
æøå ÆØÅ, the cap
oslash to a double cross. Clearly I'm on the right track. Adding echo
-e
'\033%@' as instructed lets me see the file name in
/usr/share/doc/console-tools/examples as two musical notes. Norwegian
letters look the same.

Finally the file /usr/share/doc/console-tools/README.Debian
has some
decent information at my level, and recommends using

dpkg-reconfigure console-tools

Running this command created havoc -- I was tossed out of the
linux
console and into KDE, where the keyboard had stopped functioning.
Closing everything with the mouse and selecting console login I was
brought back to the console. vt2, where I write this, was a blank blue
screen with a pulsing cursor, but ctrl-l restored it. vt3, where I gave
the command, was blank but also recovered with ctrl-l. Wow.

I try a second time with -plow and get a measured "Setting up
general
console font... ", but no options to change it.

showcfont gives me a great matrix of the console glyphs.

/etc/init.d/console-screen.sh runs at boot, reading the
configuration from /etc/console-tools/config, so this is where you need
to change stuff. Incidentally, I uncommented "DO_VCSTIME=yes" so that
consoles now have the time in the upper right corner.

OK, so here's more theory. You have three things:

  • the console font, set by /usr/bin/consolechars
  • the character set, set by /usr/bin/charset (eg latin1)
  • the keyboard map, set by /usr/bin/loadkeys (eg no-standard)

I went to /usr/share/consolefonts and played around:

  • consolechars -f t850b.psf.gz (it works, very cool)
  • consolechars -d (reset)

All the ones I tried give worse results with Norwegian letters
than the default. When I load lat0-sun16.psf.gz, which I thought was my
default, it does indeed show the keys in the way I describe above, but
now this happens also when I type, not just in error messages. So
there's a layer in between that does some remapping, and it's messing
up. Running "just reconfigure console-tools" restores the old behavior
-- I can now type æøå in
console.

Let's see if the problem is in charset.

I issue unicode_start and get "unicode_start: Already in UTF8
mode".

Når man skriver norske bokstaver på kommandolinja
(men
ikke i nano), oppfører de seg som om de var dødtaster --
bokstaven vises bare etter at den neste tasten er trykket.

Discovering just reconfigure
console-tools -p low

Note that this doesn't happen after running "just reconfigure
console-tools -plow" -- the keys behave like regular keys also on the
command line. And wow: suddenly the letters display correctly also in
nano! Help text and all is correct. I guess what's happening is that
swsuspend messes the stuff up and you need to run "just reconfigure
console-tools -plow" in the resume portion of the hibernate script.

In brief, the behavior is erratic and unstable. Sometimes it
works,
sometimes it don't-- and when it doesn't, the errors are all over the
place. Anyway, you can try adding "just reconfigure console-tools
-plow"
in the resume portion of the hibernate script -- that's the only thing
that has had a salutary effect so far.

In fact I discovered this solves the problem on boot too --
I'll try
adding it to /etc/init.d/bootmisc.sh.

The good news is that the problem is in principle fixed --
that is to
say, there's nothing additional I need to do. The bad news is that the
working solution is unstable.

Installing kbd

After the mess with console-tools, I gave kbd a try.
Installing it
uninstalled base-config console-tools ubuntu-base -- I downloaded the
packages and put copies in /platon/programvare/debs to be on the safe
side.

First impression: you have the wrong character set loaded --
capital
oslash is Omega, the others look OK. I added this line to
/etc/kbd/config:

CONSOLE_FONT=lat0-sun16

and ran just reconfigure kbd -p low. That looks promising --
and the
letters now look OK.

å være eller ikke
være, det
er spørsmålet

However, the keyboard doesn't type the capital letters -- they
end up as
disembodied chapeaux. They also don't display correctly. You should
just
ask advice on this -- itÃ's clearly a complicated issue.

Since kbd didn't cleanly resolve the issue, I reverted to
console-tools
and reinstalled the two base packages.

å være eller ikke
være, det er spørsmålet

Caps still don't get typed, nor do they display correctly --
you're no
better off, but in ubuntu the kbd package is regarded as legacy.

Now the bad news is that the capital Norwegian letters no
longer display
correctly in nano even in x-windows (in Mozilla Composer they work
fine). This really is messed up.

ØÆÅ

Here's the kicker: it turns out that nano keeps track of its
own
character sets. If you set it to Tegnkoding (Character set)
Vesteuropeisk iso-8859-1, everything in x-windows looks fine. Maybe
it's
the UTF-8 system that's just not working.

å være eller ikke være, det er
spørsmålet
Å VÆRE ELLER IKKE
VÆRE, DET ER
SPØRSMÅLET

These two lines type cleanly and display perfectly in
x-windows nano set
to 8859-1. It looks like UTF-8 is the culprit.

The menus in nano now display incorrect Norwegian letters,
again because
the system as a whole is running UTF-8. I'll try changing it to 8859
and
turn off UTF.

Changing locales fixes the worst problems

Now, after changing locales to 8859-1 it looks like things
display fine, though nano's help screens are still doing unicode. You
can tell because the characters are composite, made up of two characters
-- this is what unicode has had to do, take the basic characters and
combine them in order to find room for all the world's characters! So
that's a new level of combinatorics.

I try issuing unicode_stop and get "Already in byte-mode", so
this looks good. I may have to restart to get everything in this mode.

In brief, switching locales from UTF-8 to 8859-1 solved the
problem. This may well have been something I did myself (defining UTF-8
locales) and not part of the original configuration.

Wow -- that was a pain, but it does appear to have resolved
cleanly.


Note in addition that different users can maintain different
locales -- or you could switch locales along with keyboards! All it
takes -- assuming you have no_NB and en_US locales set up with "just
reconfigure locales" -- is setting two environmental variables:

# set en_US environment export LC_ALL=C export LANG=en_US

For some reason I don't understand, you need the "export LC_ALL=C"
rather than "export LC_ALL=en_US" to get an English nano.

Alternatively, for Norwegian, use:

# set nb_NO environment export LC_ALL=nb_NO export LANG=nb_NO

I tried to put this into the keyboard scripts to give you wholesale
local environments, but the variables could not be set by the script for
some reason (that might be worth discovering eventuall). Maybe it's
tidier to maintain a consistent locale for each user; I put US local in
/home/steen/.bashrc.

Unicode curiosity

Some Ubuntu/Debian packages use unicode characters in the
names of
maintainers; for instance, prelink has "Andrés Roldán".
After switching
locale away from UTF-8 unicode to 8859-1 "bytemap", these characters
display as composite, non-rendered unicode characters of the type I
describe below -- an A-tilde plus another random sign, which is what is
used to compose the unicode characters. But here's the news: if you now
issue "unicode_start", the character is rendered correctly!

Mind you, this does not work properly in nano, where the
unicode
characters now simply vanish, so it's not a good permanent setting, but
it does let you have a brief (and rather convenient) glimpse of the
truth without having to commit to it in the least.

What is perhaps at least as interesting is that if you then
issue
"unicode_stop", in which case the "just show prelink" command shows you
the gunk of unrendered unicode, nano displays the name perfectly:
Andrés
Roldán, with an aigu over the e and a. So nano handles unicode
characters appropriately, while the linux console only does so after
being told to use unicode.

Discovering consolechars

Since the "just reconfigure console-tools -p low" command is
such a
gut wrencher and takes so long, I tried to figure out if there's a more
painless solution. Here's just loading the screen font I want:

  • consolechars /usr/share/consolefonts/lat0-sun16.psf.gz

Here's seeing what happens when you load the default screen
font:

# consolechars -d -v

     Loading 256-chars 8x16 font from file 

`/usr/share/consolefonts/default8x16.psf.gz'.

Setting kernel SFM.

The only other font of the same file size as this font is
lat2u-16.psf.gz, but that has a different character set.

Here's what happens when I use the -v switch for the correct
font:

  # consolechars -v -f /usr/share/consolefonts/lat0-sun16.psf.gz
Loading 256-chars 8x16 font from file
`/usr/share/consolefonts/lat0-sun16.psf.gz'.
Setting kernel SFM.

Type consolechars -h for the options.
Type showcfonts to see the glyphs.

The lat1-16.psf.gz font also works fine, but lacks a euro
sign.
The /usr/share/consolefonts/lat*16* fonts all look the same.

All this makes me wonder if I couldn't just rename the screen
font I
want to this one, so that it becomes the default. Would that confuse
something else? Give it a try:

# cd /usr/share/consolefonts
# mv default8x16.psf.gz default8x16.psf.gz.orig
# cp lat0-sun16.psf.gz default8x16.psf.gz

Looks good so far -- but if this is all it takes, why isn't
this the default setup? Why keep the wrong console screen font as
default if you chose a different locale? The point is that the default
is a safe screen font that you can fall back on -- but in this case the
lat9u-16 is perfectly fine as a default.

In the meantime, try leaving "just reconfigure console-tools
-p low" out of /etc/acpi/hibernate.sh.

Result: you still get a different console screen font on resume
-- it's clearly not the /usr/share/consolefonts default screen font that
loads by default, but a console screen font compiled into the kernel. So
making the change i just did -- making the font I want default -- is
harmless but ineffective; what you need to do is to tell the kernel to
use this font.

Now in the kernel configuration, there is a way of telling the
kernel which console font to use, and it's also possible that you could
move the font you want into the kernel, so that it compiles in.

In the meantime, it seems to work to just issue

# consolechars -d

since the default font is now the right one, and this is
obviously a lot better than reconfiguring console-tools every time. If
it works that is. So far it seems to.

Euro support

I discovered euro support is built into iso 8859-15 or latin9.
lat9u-16.psf.gz has all the Norwegian letters, and the euro between the
pound and the yen. Norwegian letters øæåØÆÅ
display correctly when typed from the keyboard. And
the euro sign simply shows up as Shift+4! While
this is a good solution, it's not the standard Norwegian keyboard, so
in the no-x1.kmap keyboard I also mapped the euro to AltGr-e, which is
where it is on sokrates, and also where x-windows puts it.

Conclusion: copy lat9u-16 to default screen font:

 # cd /usr/share/consolefonts

# cp lat9u-16.psf.gz default8x16.psf.gz

Note that the idea of a default screen font, which you're now
subverting, is designed to ensure that you have a workable screen font
if you're experimenting and something goes wrong. However, this lat9u-16
is as good a default as any. In addition, just to be explicit, I defined
"lat9u-16" as the preferred screen font in /etc/console-tools/config and
ran "just reconfigure console-tools -p low" -- this is where the screen
font is loaded on boot, when the console-tool init script runs. Of
course you could have left it blank, since you've now usurped the system
default already. However, if the console-tool package gets upgraded, the
default screen font would likely get overwritten, and it's safer to use
"consolechars -f lat9u-16" in scripts -- it's also more explicit and really
has no downside. When the default screen font is upgraded on a package
update, you shouldn't notice a difference.

Both dvale and hibernate use consolechars -f lat9u-16. Type
showcfont to see the glyphs.

The altgr keys are largely as shown on sokrates' keyboard,
but with lots of additional keys. Note there's also a pile
of Shift-AltGr keys.

However, on loading the no-standard keyboard, I get three
lines of
"null" messages indicating three failed bindings. These are in fact
mysterious codes in the no-standard.kmap.gz file and produce missing
functionality:

§!"#¤%&/()=?` (grave deadkey)
|1234567890+\
¦¡@£$½¾{[]}± (mistake -- should be acute deadkey)

qwertyuiopå] (mistake -- should be diaeresis deadkey)
QWERTYUIOPÅ^ (chapeau deadkey works)
{}é®þÿüïò¶}~ (deadkey works)

asdfghjkløæ'
ASDFGHJKLØÆ*
áßðªghjkl|{^

<zxcvbnm,.-
>ZXCVBNM;:_
«z×çvbñµ·­ (comma is missing altgr)

I modified some of these and created no-x1.kmap.gz:

|1234567890+\
§!"#¤%&/()=?è (grave deadkey works)
¦¡@£$½¾{[]}±é (acute deadkey now works)

qwertyuiopåë (diaeresis deadkey now works)

AltGr comma doesn't show an AltGr function, so I tried to add
+dotlessi
for the Scandinavian Society in Istanbul, but the letter isn't present
in the console font.

Changed /usr/local/bin/no to load this keyboard -- not sure
how to set
it as default. I tried copying it to /etc/console/boottime.kmap.gz and
surprisingly it works! That solves the main font issues -- most of it
due to my defining UTF-8 in locales. However, you should bugreport the
Norwegian no-standard keyboard, which also needs the new euro location.



 

top