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.
|