Driver: Linux
Author: Salvador E. Tropea, Robert Hoehne
Status: Complete
Revision: $Revision: 1.6 $

  This is the driver for the Linux console. It can't be used for X or
other UNIX terminals. This driver is used when the terminal can be
identified as "console" or "linux*".

1. INTRODUCTION
2. THE KEYBOARD
3. ENCODINGS AND FONTS
4. SECONDARY FONT AND SYSTEMS WITH 512 CHARACTERS
5. CONFIGURATION VARIABLES
6. MOUSE

1. INTRODUCTION

  This driver is quite complex and you could need to configure your system
and/or Turbo Vision to get all the features or to even get it working. This
is a bad thing, but that's how Linux is implemented.
  Two important things affects the behavior of this driver:

1) If the user have rights to write to the /dev/vcsa* devices. Usually users
don't have access to these devices. This is because somebody logged in your
system could write to your screen to make you do something wrong or expose
important information. Lamentably these devices doesn't check if the owner is
who opened the device, a simple rights test is done. When the user can write
to this device the performance of the library is much better. I recommend
using it unless your system is used by a lot of untrusted persons.
2) If you are running the application in a real console or not. Note that
sometimes you can be using the real console but through a program that starts
their child processes in a way that they aren't really attached to the
console. A common case is the "midnight commander" program, it runs the
commands you type in something like /dev/pts/N. You can find it using the tty
command. Currently Turbo Vision can bypass applications like midnight
commander, but some stuff (like the keyboard) lose functionality.

  To solve the first point I recommend creating a group for the /dev/vcsa*
devices, something like:

  $ addgroup vcs

  Then add the user/s you want to give access to the device:

  $ addgroup user vcs

  Finally change the /dev/vcs* right and owner like this:

  $ chown root.vcs /dev/vcs*
  $ chmod 0660 /dev/vcs*

  In this way you can control which users can read or write the screen using
these devices.
  The second point is simple: run the application without using programs like
midnight commander.
  When the application runs in the real console you can:

1) Change the fonts.
2) Find information about the screen and input encoding.
3) Get good information about keyboard modifiers (shift, control, alt, etc.).


2. THE KEYBOARD

  The library uses the keyboard in "cook mode", this is much more safe than
using "raw mode" and in this way all the keyboard configuration is honored.
But this have a drawback: the information from the keyboard is incomplete and
some keys are used by the kernel.
  To solve the first issue this driver uses a Linux IOCTL that return the
current state of keyboard modifiers (like shift). The IOCTLs only work if the
process owns the real console. It won't work if you run the application using
a remote connection (i.e. ssh) or something like midnight commander.
  The second problem is more complex. Some common keys, like Shift+PgUp or
Alt+Function_key, are used for special purposes. IMHO this is a bad idea, but
is a fact. In order to solve this problem this driver modifies the kernel
tables a little bit. When you switch to another console or normally exit the
application this reverted. If it fails the solution is to reload the keyboard
map. Use the loadkeys command for it.
  For this reason you can't switch to another console using Alt+Fx, use
Ctrl+Alt+Fx, as you do when running X.
  Note that this driver *doesn't* uses ncurses nor parses the terminal
description. It means this: if you force Delete to report a strange escape
sequence and put this information in the terminfo database it won't work. It
will work for other applications, but not for this driver.
  Why not ncurses? ncurses is bulky and unpredictable, we had too much
problems using ncurses. Currently ncurses is only used by the generic UNIX
driver.
  Why not reading terminfo/termcap information? this information usually have
errors and needs a lot of code.


3. ENCODINGS AND FONTS

  Linux have a complex and flexible mechanism to support the different text
encondings (code pages). But this is wrongly used by the console-tools
(formerly kbd) tools and Linux distributions. This generates a lot of
problems. Another issue is that Linux kernel is wrongly designed, you have
services to setup things but you don't have the mechanism to know (and save)
the current state. It gets even worst when you use escape sequences and you
don't have access to the IOCTLs.
  The first thing you must understand is that code pages concept doesn't
exist for the Linux kernel. This is quite different to DOS, Windows, MacOS,
etc. where you have fixed encodings with known names. What Linux understands
are just translation tables. Usually people uses some tables that are quite
common, but sometimes these tables changes or are just adjusted by a vendor.
A complete explanation about this topic is outside the scope of this
document, If you want to know more about this topic read the html
documentation included with console-tools. What I'll describe here is just a
simplification.

3.1 TABLES TO TRANSLATE WHAT?

  Most applications, Turbo Vision applications included, uses 8 bits
characters. It gives 256 possible combinations, but: what exactly means each
one? it depends on the system. To avoid problems some standars exists. DOS
uses some IBM/ANSI encodings like code page 437, 850, 866, etc., Windows uses
another set of code pages created by Microsoft (code pages 1250, 1251, etc.)
and most UNIX systems uses enconding described in the ISO 8859 standard.
  In this way a document is:

1) Compact, each character/letter needs one byte.
2) Exchangeable, you can use documents from other system just knowing which
encoding is used.

  But this scheme isn't enough to represent all possible characters of
languages like chinese, japanese, etc. To represent these things you need an
extended system. Unicode is a really complex mechanism to achieve it. Unicode
implies a lot of complex things, but the most widely used thing is the
ability to reprsent the most common languages used in the world using a
standarized mechanism.
  The Linux kernel currently uses Unicode (16 bits variant) for internal
purposes. You can also enter text using the UTF-8 mechanism, that's a special
way to encode Unicode using variable length characters.
  What Linux does is: when a character is received by the kernel it is
converted into Unicode (first table), it is processed and when the kernel
needs to print it the value is converted to 1 byte (second table, this isn't
in fact a table).
  The first conversion is from the application encoding to Unicode and the
second is from Unicode to the screen encoding.
  Here you can see the first complexity: the application can be encoded in a
way and the screen in another. For stupid reasons is quite common to use it
in Linux systems. The reasons are all stupid and the result is a waste of
performance and added complexity.
  You can skip this paragraph if you don't want to know about some of the
stupid things common to almost all Linux systems. One of the problems people
faced in the past was that VGA video controller uses 8 pixels width fonts,
but they are represented as 9 pixels in the screen. What's in the 9th column?
It depends on the value to represent, usually it is filled with a blank
column, it helps to keep the characters visually separated. But a particular
range of values uses the same information found in the 8th column. This range
corresponds to the graphics used for frames in the code page 437, that's
because the boards have a 437 encoding by default. This range is used by ISO
8859 standard and the result is that linux encodings have the frames in the
range where the 9th column is blanked. This generates ugly frames. The real
solution for that is to just modifiy the VGA registers to create a video mode
where characters have 8 pixels. It also have a plus: you gain a couple of
columns that could be used by the kernel and/or the user. But lamentably
people uses a wrong approach. Instead of it a tweaked encoding is used. This
is the difference between lat1 and lat1u fonts. Another lamentably fact is
that newer packages (Debian Potato and Woody for example) have files called
lat1* that are in fact the tweacked lat1u* files. Another stupid thing is the
fact that most Linux distros doesn't load a font, all of them should load ISO
8859-1 because that's what the applications uses by default. Usually distros
just let the 437 default BIOS encoding, it only generates confusion and
avoids the use of a bypass for the translations. The bypass is possible
because ISO 8859-1 is a subset of Unicode (the first 256 values).
  Ok, again in the topic: the first table is what is called ACM (Application
Charset Map) and the second is called SFM (Screen Font Map).
  The first is a real table, it maps one to one. A value from the application
(8 bits) is translated into an Unicode value (16 bits in this case). The
second isn't a real table because more than one Unicode value can be
represented by the same drawing (similar or identical, remmember Unicode is
much more than an encoding). Things are even more complex because a table
with 65536 entries isn't a good idea. For this reason this map is more
complex and the kernel doesn't use a table.

3.2 WHY IS THAT A PROBLEM IF ALL LINUX APPLICATIONS WORKS OK?

  The main problem appears when you want to access to the screen using the
/dev/vcs* devices. In this case you are bypassing the kernel translation.
  Another problem appears if you have to know more about the text you are
handling. The C locales mechanism is useless because it only covers really
standard code pages.
  Most Linux applications:
1) Uses a slow screen output, after all most of them have a crappy look.
2) Doesn't really know much about encodings, just know how to draw the
frames.

3.3 WHAT'S THE PROBLEM?

  At first sight it just looks complex, but not impossible. After all doesn't
really matters if these tables follows an standard or not if you can analyze
them.
  But things are more complex. This information is only available using
IOCTLs so you can't do it when using a remote console. Currently the library
just does a guess using the contents of the LANG environment variable. If
this guess is wrongly done just use the the configuration file (tvrc).
  Another problem is that some maps wrongly done. The KOI8-R is a good
example. Here the ACM doesn't translate the input into Unicode, instead the
text passes without change (or a very small change in some systems, to make
things even worst). It works because the SFM is also wrong and in fact is a
KOI-8R->Screen conversion and not Unicode->Screen. You get a table that is
supposed to be encoded in Unicode but it isn't.
  The driver anlyze the code page and tries to figure out what encodings are
used but it can fail. If it doesn't work for your system please contact me
and we will try to find some solution.

3.4 HOW TO FORCE THE ENCODINGS

  If you know how your system is encoded look for the closest code page
supported by Turbo Vision, they are defined in codepage.cc, and create a
configuration file indicating the encoding.
  The configuration variables used for it are: AppCP and ScrCP. The first is
the equivalent to the ACM and the second is like the SFM.
  To force KOI8-R you can use:

[TV]
{
 [Linux]
 {
  AppCP=100000
  ScrCP=100000
 }
}


4. SECONDARY FONT AND SYSTEMS WITH 512 CHARACTERS

  Linux supports loading an extended font with 512 characters instead of 256.
This isn't currently supported by this driver because things are all 8 bits.
I don't really know the result. If you use such a system please contact me.
  Turbo Vision now supports loading fonts and you can use it if you are
running in the Linux console. TV also supports loading a secondary font. This
can be used for very special cases. To achieve it the driver uses a 512
characters font, the first 256 for the primary font and the other 256 for the
secondary. By default this is disabled because the kernel reduces the colors
to 8 when you load a 512 characters font. This is quite logical when the 512
symbols belongs to one big encoding but really annoying when they are two
different fonts. To enable it use the UseSecondaryFont configuration
variable.
  Note: The PC VGA controller uses eight bits for color attributes. Four are
used for the foreground color and the other four for the background color. It
gives sixteen colors. But the most significant bit of each color have a
second meaning that can be optionally enabled. The fourth bit of the
background is used for blinking and the fourth bit of the foreground is used
to select a second set of characters. This is why Linux reduces the colors to
eight, but the bit still working, you can still using sixteen colors. The
last is what TV uses. What Linux does is to redefine the colors to be the
same and disables any attempt to reprogram the palette entries to these
colors.


5. CONFIGURATION VARIABLES

  This driver supports the following variables:

* AppCP, ScrCP and InpCP. The point 3 explains the first two. The InpCP is to
force the encoding of the keyboard and isn't usually needed.
* UseSecondaryFont explained in 4.
* LoadSecondaryFont: Request a secondary font to the application (must
provide a call back).
* UseVCS. This is one by default and can be used to disable the use of
/dev/vcsa* devices.
* UseMDA. This is one by default and can be used to disable the use of the
monochrome display.
* PatchKeys. This is one by default and can be used to disable the keyboard
patching explained in 2.
* BrokenCursorShape. This is one by default and can be used to indicate we
are using a broken console where the cursor shape can't be changed. This
happends with some frame buffer consoles that fails to implement it.

  An example of configuration file is shown in 3.4.
  Read the ConfigFile.txt for more information about configuration files.


6. MOUSE

  The driver have full support for gpm 1.x, pressing Alt+mouse releases the
mouse to gpm. It alows copying from a Turbo Vision application to other
application, but not the reverse, why? because gpm will simply type the keys
and as you are holding Alt all will be received as Alt+key. But there are a
solution ;-) if you configure the library to use the left alt key for the
menues (see TGKey::SetAltSettings(value)) you can use the right alt for the
mouse paste.

