MilliKeys Graffiti Replacement
for Palm handhelds

Readme File

Installation 1-2-3:

If you just want to use the built-in layout, it should be easy to set up:

  1. Install the program components: X-Master (X-Master enables other programs, like MilliKeys, to modify system functions), MilliKeys.prc and MKeyHack.prc.
  2. Somehow, get a stamp on your screen. It looks like there is now enough demand for stamps that I could have them manufactured; however, I don't have a supplier as of yet.
  3. Run MilliKeys. In the "Manage" screen, check the box labelled "Enable hack (i.e. keyboard)", and click "Calibrate" to tell MilliKeys the exact size and position of your stamp.

If you want to use a layout you downloaded from somewhere, it's more work.  Typically the layout is provided in plain text format (as a memo which starts with the words "MilliKeys Layout:"), in which case, you need to:

  1. As per the instructions above, install MilliKeys and get a stamp.
  2. Start Palm Desktop on your PC and click the "Memo" button to reach the memo editor.
  3. Click "New" to make a new memo.  Copy and paste the text of the layout into the new memo.
  4. HotSync to get the memo onto your Palm device.
  5. Start MilliKeys, open the menu, and choose "Import from Memo".  If you copied the layout correctly, you should be asked whether you want to import the layout.  Choose "Yes, yes, a thousand times yes!"
  6. In the "Master Controls" screen, select your new layout from the list.  Check the box labelled "Enable hack (i.e. keyboard)", and click "Calibrate".

Release Notes

Beta: Version 1.0.2 

Request for help

Known Issues & Bugs

Beta: Version 1.0.0

Important note for upgrading users: You must disable the hack before HotSyncing. Be sure to install both PRC files.  Finally, before using the hack, run the application once from the application launcher in order to upgrade the setup database.

 Beta: Version 0.9.9[b]

 Beta: Version 0.9.7[a]

Important note for upgrading users: You must disable the hack before HotSyncing. Also, be sure to install both PRC files.

Beta: Version 0.9.6

At long last I've finished the new version. I quit working on MilliKeys four months ago due to excessive work load and imperfect health. Both of these will probably return as the new semester progresses, but here's a new version before things get heavy. I know there's a couple of bugs left, but I've decided to upgrade the program to 'beta' status.

Alpha: Version 0.9.4

Alpha: Version 0.9.3

Alpha: Version 0.9.2

Alpha: Version 0.9.1

Alpha: Version 0.9.0

Important note for upgrading users: The database format has changed, and the new version cannot read the database from the old version; furthermore, there is a bug which causes it to crash on exit if an old database is present. Therefore, before installing the vew version you MUST delete the old version, which causes the database to be deleted. If you have created a layout you want to keep, export it to a memo before deleting MilliKeys.

Luckily, there are only about three users (yeah, including me) so far, so this problem is not what I would call a big deal.

Also, when upgrading, remember to disable the hack before HotSyncing, and be sure to install both PRC files.


Alpha: Version 0.8.6

Important unimlemented features


GCCFilter & NoStdErr - Visual C++ users only

These programs help Visual C++ interpret the output of GCC in its "Output" window. GCCFilter translates error messages to a format VC++ understands (so you can press F4 to step through the errors), while NoStdErr is needed for Win9X users to redirect stderr to stdout. Without NoStdErr, GCCFilter does not receive the output of stderr. But of course, stderr is precicely what GCCFilter is supposed to process (i.e. error messages), hence the need for NoStdErr. On the command line, run GCCFilter -? and NoStdErr (no arguments) for more information. To use them with VC++, put both of these programs in your path for executable files (Tools | Options | Directories | (for) Executable Files). I personally put them in my Cygwin/bin directory.

Alpha: Version 0.8

I had a heck of a time trying to make MilliKeys into a hack.

To make a long story shorter ( skip the story):

To begin with, I don't know how to put the application part of MilliKeys--the part you run from the launcher--into the same PRC file as the hack part of MilliKeys.

I have been trying instead to get the hack to coexist with the application in a different database, MKeyHack.prc. I couldn't get them both on the emulator with the same creator ID (loading one would cause deletion of the other, or so it seemed), so I tried giving them different IDs. While that turned out to be difficult in itself (because they share the same makefile and source code), once I had done it (hack ID=MKHk), it still didn't work. I was puzzled, but then figured out that the program title had to be different too. Anyway, with both the creator ID and the titles different, the hack wouldn't activate in X-Master... I determined that it was missing its TRAP resource for some reason, even though it was specified in the resource file AND the source file.

Now at that point I was compiling the resources for both the app and the hack in the source code folder. This was wasteful because the hack inherited the resources (*.bin) left over from the app's compilation, but I didn't mind an increased PRC size when I was merely trying to get it to work. Well, it seems that somehow, resources of other types from the app were preventing the TRAP resource from getting in the PRC. I found that if I deleted tAIB03e8.bin (app icon resource, ID 1000), just before calling build-prc, then the trap resource (also ID 1000) was then put in the prc, and the hack could be activated in X-Master. I didn't think resources of different types could conflict, but since it appears they can, I wonder what possessed the guy who wrote HackMaster to require a trap ID of 1000, when 1000 was already taken by the app icon resource? I mean, I know hacks weren't intended to show up in the launcher when HackMaster first came out, but it isn't too hard to see that someone, someday, might want to.

Anyway, then it occurred to me that maybe the titles conflicting was the only real problem, but having the same creator ID was actually okay. So I changed the creator ID of the hack back to that of the app (MKey) and the apps still coexisted! This is good news for two reasons:
1. I don't need to juggle two IDs... for example the hack doesn't have to keep track of the app's ID in order to access its database.
2. In the 'Delete' dialog on the palm, both the hack and the app are grouped together into one entry so you can delete them together. Interestingly, the delete box chooses to label them collectively "MilliKeys" and not "MilliKeys Hack", indicating it prefers to use the name of the app over the hack. This makes sense, though, since the OS recognizes the app as an app, and doesn't understand what a "HACK" is.

It makes me wonder why Palm bothers to have a creator ID registry, when they lack a database name registry. As far as I can tell, if two databases have the same name, they can't coexist on the same machine. Meanwhile, at least if two databases have the same creator ID, they can still coexist if their types are different. Seems much more likely to me that any two given developers might be uneducated enough to put their settings in a database called "Setup", than that they would choose the same creator ID....

The bottom line

MilliKeys comes in two parts:

  1. MilliKeys.prc - the setup application which is run from the launcher
  2. MKeyHack.prc - the hack, which actually takes over the graffiti area

Normally you install both of them on the handheld. If you don't install MKeyHack.prc, you won't be able to use the hack functionality (so you're limited to using it in the Test screen). If you don't install MilliKeys.prc, you can't configure the hack. That's okay, though, if you have a .pdb file with the configuration you want stored in it. Just install that pdb and you'll be able to use MKeyHack.prc without MilliKeys.prc, but of course you won't be able to change the setup.

If you do not install a MilliKeys pdb file explicitly, then you must run the MilliKeys setup program at least once before you can use the hack.

If you disable the keyboard with the "\Z" key, you should have \Z assigned to a big stroke so that you can re-enable the keyboard. If you disable the keyboard without a big stroke to re-enable it, you can still get it back by switching applications: the hack responds to appStopEvent by re-enabling the keyboard and clearing all shift states.

Known Issues & Bugs

- Problem with lists on Pre-OS 3.5 machines: My code seems unable to set the usable state of lists and gadgets programmatically; the usable bit in the resource file applies for the duration of the program. The only reason I can show/hide popup lists is because I'm using LstPopupList which does its own thing... However, the keyboard gadget does not display at the wrong time because I put in some special code prohibiting the displaying of the gadget except on page [4].
- Hack and database are not beamed with the config app. As a workaround for the hack, at least for X-Master users, you can beam it using X-Master's beam function (other hack managers probably have a beam function too).


Pre-Alpha: Version 0.7

This is the initial public release. Here's the description I gave with my SourceForge application:

This project will implement a virtual keyboard on the silkscreen area of a PalmOS device. This requires that the program be a 'Hack', in order to intercept system calls, but as I'm having difficulty figuring out how to make it a hack, at the moment it is merely a standalone application, pre-alpha stage.

Anyway, its basic function works. You can input a layout in the Edit screen, then render it and use it on the Test screen. You can have multiple layouts; layouts can be duplicated, erased, and switched between. It has a "macro" feature; each macro can either input a series of keys or run a program, although the latter is not yet implemented.

A layout consists of up to five rows of keys; each row can have a different setting for height, key width, and alignment (width of the leftmost key).

Mind you, there's already a little program for getting keys on your silkscreen area, and it's called DotHack. [it's based on a previous GPL program, but for some reason source is not available...oh well] So why make another program? As well as being able to use the entire silkscreen area, not just the graffiti area--thus allowing an entire Qwerty keyboard to fit--MilliKeys supports "short strokes". A short stroke (as opposed to "big strokes", which I'll get to later) is a stroke where you press the pen down on a key, then move it in one of eight directions (up, right, up-right, etc.) and let go. This feature alone allows up to nine characters or actions to be represented by a single key. Additionally, when the program is finished it will support a shift and a caps lock, providing access to a predefined set of capital letter mappings, and a user-defined "extra" layout, which is kind of a user-defined shift/caps lock.

In the built-in layout the user can tap for lowercase keys; stroke up for uppercase; stroke down on the top row for numbers; stroke horizontally on the top row for punctuation (!@#$ instead of 1234); stroke down, left, or right on the second row for much more punctuation including extended characters; and stroke left anywhere on the bottom two rows for backspace. Finally, the "extra" layout contains accented characters. I have created a bitmap depicting this layout, which users can print out and tape on their PalmPilots.

It supports "big strokes"--strokes from the lower left or lower right to some other corner of the screen. The capability of a big stroke is the same as a macro.

Eventually I plan to implement a smart Graffiti passthrough feature where the program will detect irregular strokes and let Graffiti handle it.

Source Code Notes

Compiling MilliKeys

To compile MilliKeys under Windows, you need:

Instructions for installing and setting up the above software can be found here.  After setting it all up according to the instructions on the aforementioned page, you should be able to compile MilliKeys by

  1. Putting the MilliKeys sources in /PalmDev/MilliKeys
  2. Opening the cygwin bash shell
  3. Inputting the following commands:
    1. cd /PalmDev/MilliKeys
    2. make

Source Code Overview

This code is somewhat of a mess, using too many globals (variables and functions) placed too randomly.  But here's an overview.

Project Files
   Keyboard.dsw Visual C++ 6 Workspace File (needed only for VC++ 6 users)
  Keyboard.dsp Visual C++ 6 Project File (needed only for VC++ 6 users)
  MilliKeys.sln Visual Studio.NET Solution file (needed only for VC++.NET users)
  MilliKeys.vcproj Visual C++.NET Project file (needed only for VC++.NET users)
Resource files (used to declare forms, alerts, strings, icons, and other resources)
Resource file for MilliKeys application; Resource.h contains #define directives for the identifiers used by Resource.rcp (PilRC has absolutely no capacity to understand C except for integer #define directives)
  Hack.rcp Resource file for MilliKeys hack
C++ Source/header files

Note: MilliKeys.prc is compiled from all of these source files, but MKeyHack is compiled only from Utils.cpp and Hack.cpp (and the header files included thereby.)

  Keyboard.cpp/h Various globals; memo import/export; shift map reset; CallXMaster; startup/shutdown code; PilotMain; main event loop.
  StringConvert.cpp/h  Code to convert between the key strings you see on-screen and in memos, and the binary key/layout format MilliKeys uses internally.
  Hack.cpp/h Code for the hack part of MilliKeys.  Most of the code in the hack is in Hack.cpp. The app contains an on-screen test keyboard that behaves like the standalone hack; Hack.cpp is compiled into the app for this purpose.  Declarations needed by both the app and hack are placed in Hack.h.
  Utils.cpp/h Utility code not specific to MilliKeys:
  • Assertion and debug tracing support
  • Enum value mapper
  • Database functions and classes
  • StringTable & StringList
  • Miscellaneous functions
  BaseUI.cpp/h UI code made for MilliKeys, but independent from it (re-usable).  See the large block comment in BaseUI.h for more information.
  UI.cpp/h UI code for the main (non-modal) part of the MilliKeys app; built on top of BaseUI.cpp.
  Calibrate.cpp/h UI code for the calibration dialog; code for calculating the 6 calibration parameters based on the 2 or 3 user input points.
  ConstTables.cpp Various global arrays of structures: the built-in Qwerty layout (gBuiltinQwerty, gBuiltinQwertySizes), the special key table (gVKeyTable), and the UI tables (gRadioTable, gPropPages, gPopupTable, and most importantly, gStateVarMap.)
  Layout.h Key layout structure and substructures; Calibration structure; enums used in key layouts.
  Standalone.h I can no longer remember what this is for!  It has something to do with the hack...
Other files
  Makefile Make file for gnu 'make': rules for building MilliKeys; see the block comment at the top of the file for more information.
  Sections.def Segment definition file compiled by m68k-palmos-multigen.  Without 'segments', 68k-based PalmOS programs have a limit of between 32K-64K of code.  PRC-Tools requires that the programmer manually break up larger programs into named 'segments' by declaring each function with __attribute__ ((section ("name"))).  This file is required to tell PRC-Tools what segments are in the program; should you fail to compile and link this file, PRC-Tools stupidly omits your multi-segment code from the final executable, resulting in a PRC which doesn't work.
  Hack.def The hack is only one section, and I forgot why I made this file.  But I keep it lest its removal should break something.

[ Home Page @ SourceForge / Geocities | SourceForge Summary | Qwertie's Page | Code Notes | Manual ]