This is my agenda,

and that's me, in the background.

In this page:


Keyboard improvements:

I've been trying to do some improvements in the keyboard application for the agenda. The keyboard layout is easily modified, by editing /etc/alpha.keyboard, /etc/numeric.keyboard and /etc/writepad.keyboard.
I found it very useful to modify the writepad screen, replacing the upper case region by some extra keys:

Normal

Shifted

The extra keys are: [ {, ] }, \ " (all of them without a defined "stroke"), modifier keys: Shift, Cap, Ctrl and Alt. (Specially useful is the Ctrl key, allowing to enter cut and paste commands and Shift that allows entering upper case letters). The "CK" key is the "compose key", by tapping the compose key, then "a", then "'", you get "á". Compose key, then "/", then "O", and you get "Ø". This compose method can fully replace the international keyboard. This seems to be a feature of X (I use the same trick in my desktop, redefining the right control key as the compose key).
This layout is obtained by replacing the /etc/writepad.keyboard with this file.

Attention: in order for this to work, you will need a modified keyboard binary:
- When the keyboard application receives a handwritten stroke, normally doesn't test the state of the shift
key, and don't toggle the state of a modifier key, if it's down. (The original writepad layout is not supposed to contain modifier keys). This can be corrected by this patch:

$ diff -Naur keyboard.cxx.original keyboard.cxx
--- keyboard.cxx.original       Mon May 21 01:01:40 2001
+++ keyboard.cxx        Fri Jul 20 18:17:17 2001
@@ -167,7 +167,29 @@

 void writepad_cb(Fl_Widget* widget, void* data) {
        Fl_Scribble* s = reinterpret_cast<Fl_Scribble*>(widget);
-       fake_keyboard->press(s->key());
+       // Patch to make shift, caps lock, meta & ctrol work with writepads
+       KeySym kk=s->key();
+       if ((shifted || caps_lock) && (kk >= XK_a && kk <= XK_z))
+         fake_keyboard->press(kk + XK_A - XK_a);
+       else
+         fake_keyboard->press(kk);
+
+       if(shifted) 
+               shifted = 0;
+               update();
+       }
+       if(meta == true) {
+               meta = false;
+               if(meta_key_) {
+                       ((Fl_Button*)meta_key_)->value(0);
+               }
+       }
+       if(ctrl == true) {
+               ctrl = false;
+               if(ctrl_key_) {
+                       ((Fl_Button*)ctrl_key_)->value(0);
+               }
+       }
 }

 int curx = 0;
@@ -236,10 +258,16 @@
        widget->callback(function_cb, (void*)keysym);
 }

-void backspace_key(int w, int h) {
-       Fl_Widget* widget = key("@#<-", w, h);
+//void backspace_key(int w, int h) {
+//     Fl_Widget* widget = key("@#<-", w, h);
+//     widget->labeltype(FL_SYMBOL_LABEL);
+//     widget->callback(function_cb, (void*)XK_BackSpace);
+//}
+
+void keysym_symbol_label_key(const char* l, unsigned int keysym, int w, int h) {
+       Fl_Widget* widget = key(l, w, h);
        widget->labeltype(FL_SYMBOL_LABEL);
-       widget->callback(function_cb, (void*)XK_BackSpace);
+       widget->callback(function_cb, (void*)keysym);
 }

 void cap_key(int w, int h) {

Basically, I put the code for a key press in the place where the strokes are interpreted. When the shift or caps_lock are active and the stroke is a letter, it is capitalized, otherwise, it does the same as the old version. Also the states of shift, ctrl and alt keys are tested, in order to toggle their state up. Also the function backspace_key is replaced by keysym_symbol_label_key (it will be also used by the arrow keys, see below).

- There is no support for the compose key in the original keyboard app, but it is easy to add, as it is easy to add support for the keys: home, end, delete, page up, page down and the arrows, with this patch:

$ diff -Naur loader.cxx.original loader.cxx
--- loader.cxx.original Thu Apr 26 18:25:19 2001
+++ loader.cxx Fri Jul 20 18:55:19 2001
@@ -132,13 +132,44 @@
                }
                if(strcasecmp(v0, "backspace") == 0) {
 //                     keysym_key("BS", XK_BackSpace, w * uw / 100, h * uh / 100);

-                       backspace_key(w * uw / 100, h * uh / 100);
+//                     backspace_key(w * uw / 100, h * uh / 100);
+                       keysym_symbol_label_key("@#<-", XK_BackSpace, w * uw / 100, h * uh / 100);
                }
                else if(strcasecmp(v0, "tab") == 0) {
                        keysym_key("Tab", XK_Tab, w * uw / 100, h * uh / 100);
                }
                else if(strcasecmp(v0, "esc") == 0) {
                        keysym_key("Esc", XK_Escape, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "compose") == 0) {
+                       keysym_key("CK", XK_Multi_key, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "delete") == 0) {
+                       keysym_key("Del", XK_Delete, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "left") == 0) {
+                       keysym_symbol_label_key("@#4>", XK_Left, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "up") == 0) {
+                       keysym_symbol_label_key("@#8>", XK_Up, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "right") == 0) {
+                       keysym_symbol_label_key("@#>", XK_Right, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "down") == 0) {
+                       keysym_symbol_label_key("@#2>", XK_Down, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "pageup") == 0) {
+                       keysym_key("PUp", XK_Page_Up, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "pagedown") == 0) {
+                       keysym_key("PDn", XK_Page_Down, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "home") == 0) {
+                       keysym_key("Home", XK_Home, w * uw / 100, h * uh / 100);
+               }
+               else if(strcasecmp(v0, "end") == 0) {
+                       keysym_key("End", XK_End, w * uw / 100, h * uh / 100);
                }
                else if(strcasecmp(v0, "f1") == 0) {
                         keysym_key("F1", XK_F1, w * uw / 100, h * uh / 100);

With these new keys, you can use a modified numeric keyboard such as:

Normal

Shifted

(Immediate access to alpha or hwr mode, lots of keys added: home, end, page up, page down, arrows, insert, delete, f1-f5 and compose key, AKA XK_Multi_key. Symbols now "over" numbers, obtained using shift). This layout is obtained by replacing the /etc/mumeric.keyboard with this file.



- In order to use international characters with the multi-key method, you will need to modify the X11 keymap, adding the keycode for the multi-key. You will need the xmodmap binary and the xmodmap commands.

You can find the first in the Wiki site: http://agendawiki.com/wiki.pl?InternationalHWR, with a much more detailed explanation. Here there's a copy of xmodmap binary: http://agendawiki.com/uploads/indie-hwr-beta-binaries-08062001.tgz. (for a non-snowed rootdisk). And here the commands:

keycode any=Multi_key
keycode any=Delete
keycode any=Insert

If you put this lines in a file called .Xmodmap, the X11 init procedure will take care of running xmodmap (if it is in the PATH).

You can find here the new keyboard binary (for non-snowed rootdisk) . If you don't want to make a new rootdisk, you can put it in /usr/local/bin and modify accordingly the link: /flash/home/default/.wmx/.keyboard and the file /flash/home/default/.wmx/.startup.

And just for completeness, here is the layout I use for the alpha keyboard:

Normal

Shifted

(Immediate access to hwr mode, compose key added, some symbol keys changed). This layout is obtained by replacing the /etc/alpha.keyboard with this file.


Snow binaries (using james-snow-compiler-1.1.0).
xmodmap.snow, keyboard.snow.
Sources:
xmodmap: Look for xutils-4.0.3 here.
Original keyboard: here.


Keyboard supporting Merlin recognition engine:

(This is the keyboard version that has been included in rootdisk 1.2.6 distributed by Agenda Computing Germany).

The main feature of this version is the ability to support xmerlin-type writepads. This writepads can be of any size, but a reasonable size would be half of the keyboard. The remaining space can be used for standard keys or even scribble-type writepads, if you want to test the two recognition engines side-to-side. For example, the keyboard could look like:

Normal

Shifted

In this example, only the "ctrl" and "alt" key are needed to achieve full functionality.

The main advantage of the merlin HWR engine is the ability to configure it easily. The strokes are stored in binary format in /etc/alternatives/merlin-samples, they use only 12 KBytes. You can also put in that directory new strokes in plain text files (x-y pairs), or convert strokes from/to xfig format (tools and plain text strokes included in sources for xmerlin). The conversion is done in two stages: the stroke is recognized as a character (0-255), and then the character is converted into an X11 KeySym. In order to add a new stroke, let's say, for the key F11, you first edit the ctoks.map file, select an unused character, and change the "0" by "XK_F11". Then draw the stroke with xfig, and convert to plain text x-y pairs, put in the header the character used. Put this file in the merlin-samples directory with a name such as natural_something.dat if you will write the stroke on the left side or numeral_something.dat if you will write it on the right side. Then, restart the keyboard.

The predefined strokes already include the alphabetic and numeric keys, plus the arrows, home, end, pgUp, pgDown, etc. see the strokes page here.

I've compiled a couple of versions of this modified keyboard, all of them for the snow-1.1.x rootdisks. This one has support for both recognition engines: scribble and merlin. This one only supports merlin type writepads, the difference in sizes is not big, but if you make your own rootdisk, you can save the space used by /lib/libscrib.1.sso (~50KB) and the scribble strokes in /usr/share/HRE (~100KB). There is also this version which supports only scribble (pretty much as the original keyboard, with the modifications mentioned above, AND... a little change in the size of the button's labels. Now it is possible to have a five row keyboard, such as the fitaly or the full qwerty with readable labels, just change the vertical size of the buttons to 11).

Binaries for snow-1.2.x rootdisks:

With support for Merlin.
With support for Scribble.
With support for both engines.

Installation:

And, of course, here are the sources.

Note:

If you want to use the keys Delete, Insert or Multi_key, or their equivalent merlin strokes, you will need to modify the keyboard map with xmodmap, as explained above. Here you can find an xmodmap binary compiled with the snow 1.2.x toolchain. Adding strokes for international characters in the merlin engine will also need xmodmap to enable the new keysyms.

Note 2:

The latest version of this keyboard application is now called keymacs, and can be found here.
Ported applications:

ftpd:

I like to browse remote directories with "mc" (midnight commander), using the FTP virtual file system. So I compiled an ftpd for the agenda. I downloaded sources from Debian archives: linux-ftpd_0.11.orig.tar.gz (I know: it's not the latest, it even has security bugs, ...) and recompiled it with minor modifications: changed a flag in MCONFIG to not use PAM, and changed the last "return 0" into "return 1" in function authenticate (it was a bug, but anyway, Debian uses PAM and this section of code is not used in that case). Compilation went OK, following directions from the Starting to snow wiki page and latest snow compiler (james-snow-compiler-1.1.0). Here is the binary. I copied it to /flash/local/sbin/in.ftpd and modified /etc/inetd.conf to include the line:

ftp stream tcp nowait root /usr/local/sbin/in.ftpd /usr/local/sbin/in.ftpd

and told inetd to re-read the config file:

/etc/rc.d/init.d/inet reload

...and that's all, you can now use ftp to access the files on your agenda. Check the /etc/ftpusers file if you want to restrict access to some users.

gnuplot:

(why not?).
Again: downloaded sources from the debian pages: gnuplot_3.7.1p1.orig.tar.gz, unpacked, run use_snow (see the Starting to snow wiki page), then run configure, then make. Problem 1: the help page is built with a binary file that is a MIPS binary. Solution: manually compile and run the help builder in the desktop machine. Problem 2: libpng is included in the compiler, but not on my rootdisk (1.1.1S), so configure detected it and compiled using the shared library, but when I tried to execute the binary, the library is missing. Solution: comment the define HAVE_LIBPNG 1 in config.h after running configure. Problem 3: big binary (>800KB), solution: edit term.h and define SHORT_TERMLIST, comment out some, add some others; remember to re-create the help file (only available terminal types are included in the help).
Binaries: gnuplot, gnuplot_x11 (should be placed in /usr/local/bin). Help file: gnuplot.gih (should go to /usr/local/share).

xmerlin:

This is a handwritten character recognition program, original from Stefan Hellkvist (http://www.hellkvist.org/software/), with some adaptations by Brian Webb (http://www.desertscenes.net/agenda/) and some work from my own, including the addition of many strokes for special keys. You can find here the binaries for agenda (rootdisks 1.1.xS). Here the source files, and here the strokes definitions. It's very easy to edit the strokes, I've also written a couple of conversion programs to help drawing the strokes with xfig, they are included in the source files.


Visits since 2001-10-19: ...13856.