Overview
========

  To make a graphical boot screen you need a PCX image and a config file. 
  Optionally you might want a font file, but that is not really necessary as
  you can simply use standard BIOS fonts.

  The config file is actually a program written in a Postscript-like
  language that is run right after the boot manager entered graphics mode. 
  You must program everything related to graphics output in it. That does
  even include drawing the background picture and setting the palette.

  The PCX image must be a 8-bit color image. Put a line like this into your
  config file:
  
  %% image mybootimage.pcx

  Or, if you want a screen resolution that does not match the resolution of
  your picture, specify the screen resolution you want explicitly:

  %% image mybootimage.pcx 640 480

  If you want to use a loadable font, put a line like this into the config file:

  %% font font_id font_file

  font_id is a name you can use to reference the font in your config file. 
  font_file is the actual name of the font file.

  Font files have a special format. Create them using 'getx11font':
  
  getx11font x11_font_spec font_file

  The font must not exceed a size of 16x32.

  BIOS fonts have font ids 0-5. Bit 0 specifies whether you want to uses
  them as fixed width fonts (0) or variable with fonts (1). (See config file
  examples.)

  If you have written a suitable config file, create a syslinux/lilo message file
  using mkbootmsg:

  mkbootmsg -c my_boot_configfile gfx_bootmessage

  Debugging this config file is rather tedious. In doing so, 'mkbootmsg -v'
  might give you some information. Or try the 'dtrace' command (see language
  reference below).

Language Reference
==================

 Comments start with '%' and extend to the end of line.

 Numbers are always 32 bit signed integer. Numerical and string constants
 are given in a C-like way (_not_ as in Postscript). Examples:

   123
   0x4567
   "Hi there\n"
   '\033'

 But: chars have values in the range 0 ... 255.

 Logical operations return values of type 'bool'. They are _not_ identical
 with integers. There are no pre-defines constants 'true' and 'false'. But
 you can define them yourself if you need them, e.g.: '/true 0 0 eq def'.

 Variable/constants/function names can consist of everything except
 whitespace.

 - Callback functions
   Communication with lilo/syslinux is done via callback functions. You are
   responsible to assign useful actions to these.
   See config file examples for more documentation.

   o KeyEvent
     Called if a key is pressed.

   o MenuInit
     Should draw the boot menu.

   o InfoBoxInit
     Show a message box (e.g. error messages).

   o InfoBoxDone
     Hide the message box.

   o ProgressInit
     Initialize the progress bar (not yet available in lilo).

   o ProgressDone
     Hide the progress bar.

   o ProgressUpdate
     Advance the progress bar.

   o PasswordInit
     Show password dialog.

   o PasswordDone
     Hide password dialog.

   o Timeout
     Timeout counter; called every 18.3th second until the timeout occurs.

   o Timer
     Called every 18.3th second regardless of timeout.

 - {
   Start code definition.

   stack: ( ) --> ( proc_1 )

   Example:
     /f { 10 mul } def

 - }
   Finish code definition. 

   stack: ( ) --> ( )

   Example:
     /f { 10 mul } def

 - [
   Start of an array.

   stack: ( ) --> ( array_start )

   Example:
     [ 1 2 3 ]

 - ]
   End of an array (completes an array definition).

   stack: ( array_start obj_1 obj_2 ... ) --> ( array_1 )
   % array_1[0] is obj_1, array_1[1] is obj_2, etc.

   Example:
     [ 1 2 3 ]

 - abs
   Absolute value.

   stack: ( int_1 ) --> ( int_2 )		% int_2 = abs(int_1)

 - add

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 + int_2

 - and

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 & int_2
   stack: ( bool_1 bool_2 ) --> ( bool_3 )	% bool_3 = bool_1 && bool_2

 - array
   Create an empty array.

   stack: ( int_1 ) --> ( array_1 )
   % array_1 is an array with int_1 elements

 - bootloader

   stack: ( ) --> ( int_1 )
   % int_1: 0 = lilo, 1 = syslinux

 - currentcolor
   Returns current drawing color.

   stack: ( ) --> ( int_1 )

 - currentfont
   Returns current font.

   stack: ( ) --> ( int_1 )

 - currentpoint
   Return current cursor position.

   stack: ( ) --> ( int_1 int_2 )
   % int_1: x pos, int_2: y pos

 - def
   Defines a word.

   stack: ( key value ) --> ( )
   % key is defined as value

   Examples:
     % constants
     /x 55 def
     % functions
     /f { 10 mul } def

 - div

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 / int_2

 - dtrace
   Turn on trace mode (cf. 'trace') and show debug info in the upper left
   screen corner (might not be visible on some graphics cards).

   stack: ( ) --> ( )

 - dup
   Duplicate tos.

   stack: ( obj_1 ) --> ( obj_1 obj_1 )

 - edit.done
   Restore input field background.

   stack: ( array_1 ) --> ( )
   % for array_1, see edit.init

 - edit.hidecursor
   Hide cursor in input field.

   stack: ( array_1 ) --> ( )
   % for array_1, see edit.init

 - edit.init
   Setup and show an editable input field.

   stack: ( array_1 string_1 ) --> ( )
   % the input field is initialized with string_1.
   % array_1 must be a 8-dimensional array:
   %   [ x_pos, y_pos, screen_area, text_buf, text_buf_size, 0, 0, 0 ]
   %   screen_area holds the background pixmap for the input field and
   %   indirectly determines the size of the field. See 'savescreen' on
   %   how to create such a pixmap.
   %   text_buf is a string and should be large enough to hold
   %   text_buf_size chars.
   %   The last 3 elements are needed internally.

 - edit.input
   Do some input action.

   stack: ( array_1 int_1 ) --> ( )
   % for array_1, see edit.init
   % int_1, bits 15-8: scancode; int_1, bits 7-0: ascii

 - edit.showcursor
   Show cursor in input field.

   stack: ( array_1 ) --> ( )
   % for array_1, see edit.init

 - eq
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )	% bool_1 = int_1 == int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )	% bool_1 = string_1 eq string_2

 - exch
   Swap the top two stack elements.

   stack: ( obj_1 obj_2 ) --> ( obj_2 obj_1 )

 - exit
   Leave loop/repeat/for loops.

   stack: ( ) --> ( )
   Example:
     % leave if counter == 56
     0 1 100 { 56 eq { exit } if } for

 - fillmode
   Set fillmode used by 'fillrect'.

   stack: ( int_1 int_2 int_3 ) --> ( )
   % int_3 == 0: copy
   % int_3 == 1: add
   % int_1, int_2 color values

 - fillrect
   Fill a rectangle; drawing mode is set by 'fillmode'.

   stack: ( int_1 int_2 ) --> ( )
   % int_1: width, int_2: height.

 - fontsize
   Returns current fontsize.

   stack: ( ) --> ( int_1 int_2 )
   % int_1: font width, int_2: font height

 - for
   Typical 'for' loop.

   stack: ( int_1 int_2 int_3 proc_1 )
   % int_1: start value, int_2: step size, int_3: end value (inclusive)
   % every time proc_1 is executed, the current counter is put
   % on the stack

   Example:
   0 1 4 { } for
   % leaves ( 0 1 2 3 4 ) on the stack

 - free
   Free malloc'ed memory.
   Note: memory management is not implemented. You must do it currently all
   by yourself using 'malloc' and 'free'. Arrays defined via 'array' should
   also be free'ed. It does not harm, however, to free objects that were not
   malloc'ed ('free' does nothing, then).

   stack: ( string_1 ) --> ( )
   stack: ( array_1 ) --> ( )

 - ge
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )	% bool_1 = int_1 >= int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )	% bool_1 = string_1 ge string_2

 - get
   Return a array/string element.

   stack: ( array_1 int_1 ) --> ( obj_1 )	% obj_1 = array_1[int_1]
   stack: ( string_1 int_1 ) --> ( int_2 )	% int2 = string_1[int_1]

 - getpalette
   Return palette values for a color.

   stack: ( int_1 ) --> ( int_2 )
   % int_1: color
   % int_2: rgb value for color
   % (bits 23-16 red, bits 15-8 green, bits 7-0 blue)

 - getpixel
   Read pixel from current drawing position.

   stack: ( ) --> ( int_1 )

 - getsysconfig

   stack: ( ) --> ( int_1 int_2 )

 - gt
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )        % bool_1 = int_1 > int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )  % bool_1 = string_1 gt string_2

 - if
   Typical 'if'.

   stack: ( bool_1 proc_1 ) --> ( )
   % execute proc_1 if bool_1 is true

   Example:
     10 4 gt { "Greater!" show } if

 - ifelse
   Typical 'if'/'else'

   stack: ( bool_1 proc_1 proc_2 )
   % execute proc_1 if bool_1 is true otherwise proc_2

   Example:
     10 4 gt { "Greater!" } { "Smaller!" } show ifelse

 - image
   Draw part of the image (image was given via '%% image ...').

   stack: ( int_1 int_2 int_3 int_4 ) --> ( )
   % int_1, int_2: position in image
   % int_3, int_4: width, height

   Example:
     % redraw the whole screen
     0 0 moveto
     0 0 screen.size image

 - image.colors
   Return number of image colors.

   stack: ( ) --> ( int_1 )

 - le
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )        % bool_1 = int_1 <= int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )  % bool_1 = string_1 le string_2

 - length
   Return array/string size.
   Note: returns the actual length of the (0 terminated) string, _not_
   the size of the memory area allocated for it.

   stack: ( array_1 ) --> ( int_1 )
   stack: ( string_1 ) --> ( int_1 )

 - lineto
   Draw a line.

   stack: ( int_1 int_2 )
   % int_1, int_2: x, y line end

   Example:
     0 0 moveto
     200 100 lineto

 - loadpalette
   Activate the image palette.

   stack: ( ) --> ( )

 - loop
   Typical 'loop'.

   stack: ( proc_1 )
   % proc_1 is executed forever (use 'exit' to break leave it)

   Example:
     % loop until x == 56
     /x 0 def { /x x 1 add def x 56 eq { exit } if } loop

 - lt
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )        % bool_1 = int_1 < int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )  % bool_1 = string_1 lt string_2

 - malloc
   Malloc some memory (cf. 'free').

   stack: ( int_1 ) --> ( string_1 )
   % Note: string_1 is initialized with 0

 - max

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = max(int_1, int_2)

 - min

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = min(int_1, int_2)

 - mod

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 mod int_2

 - moveto
   Set current drawing position.

   stack ( int_1 int_2 )  --> ( )
   % int_1, int_2: x, y

   Example:
     200 100 moveto
     "Hello" show

 - mul

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 * int_2

 - ne
   Compare.

   stack: ( int_1 int_2 ) --> ( bool_1 )        % bool_1 = int_1 != int_2
   stack: ( string_1 string_2 ) --> ( bool_1 )  % bool_1 = string_1 ne string_2

 - neg

   stack: ( int_1 ) --> ( int_2 )		% int_2 = -int_1

 - not

   stack: ( bool_1 ) --> ( bool_2 )		% bool_2 = !bool_1

 - or

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 | int_2
   stack: ( bool_1 bool_2 ) --> ( bool_3 )	% bool_3 = bool_1 || bool_2

 - over

   stack: ( obj_1 obj_2 ) --> ( obj_1 obj_2 obj_1 )

 - pop
   Remove tos.

   stack: ( obj_1 ) --> ( )

 - put
   Set a array/string element.
   Note: string size is not checked!

   stack: ( array_1 int_1 obj_1 ) --> ( )	% array_1[int_1] = obj_1
   stack: ( string_1 int_1 int_2 ) --> ( )	% string_1[int_1] = int_2

 - putpixel
   Set a pixel.

   stack: ( ) --> ()

 - repeat
   Typical 'repeat'.

   stack: ( int_1 proc_1 )
   % run proc_1 int_1 times

   Example:
     % print "XXXXX"
     5 { "X" show } repeat
     
 - restorescreen
   Restore screen area.

   stack: ( string_1 ) --> ( )
   % string_1 should be created by 'savescreen'

 - return
   Leave the current function.

   stack: ( ) --> ( )

 - rmoveto
   Set current drawing position relative to current position.

   stack ( int_1 int_2 )  --> ( )
   % int_1, int_2: x, y

   Example:
     200 100 rmoveto
     "Hello" show

 - roll
   Rotate stack elements.

   stack: ( obj_1 ... obj_n int_1 int_2 ) --> ( obj_1' ... obj_n' )
   % int_1: number of elements to rotate (== n)
   % int_2: amount
   % 1' = (1 + int_2) mod int_1
   % n' = (n + int_2) mod int_1

 - rot
   Rotate upper tree stack elements.
   Equivalent to "3 -1 roll".

 - savescreen
   Save a screen area.

   stack: ( int_1 int_2 ) --> ( string_1 )
   % int_1, int_2: width, height
   % string_1 is automatically malloc'ed but must manually be free'ed

 - screen.size
   Return screen size.

   stack: ( ) --> ( int_1 int_2 )
   % int_1, int_2: width, height

 - setcolor
   Set drawing color.

   stack: ( int_1 ) --> ( )
   % int_1: color

 - setfont
   Set text font.

   stack: ( int_1 ) --> ( )
   % int_1: font

 - setpalette
   Set palette.

   stack: ( int_1 int_2 ) --> ( )
   % int_1: color
   % int_2: rgb value, (bits 23-16 red, bits 15-8 green, bits 7-0 blue)

 - setsysconfig

   stack: ( int_1 int_2 ) --> ( )

 - settintcolor

   stack: ( int_1 int_2 ) --> ( )
   % int_1: rgb value

 - settransparentcolor
   Set transparent color for 'image' operator.

   stack: ( int_1 ) --> ( )
   % int_1: color

 - shl

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 << int_2

 - show
   Print text.

   stack: ( string_1 ) --> ( );
   % print string_1

 - shr

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 >> int_2

 - snprintf
   C-style snprintf.
   Note the reversed argument order!

   stack: ( obj_1 ... obj_n string_1 int_1 string_2 ) --> ( )

   Example:
     /buf 100 malloc def
     10 5 "Hi, %d > %d\n" 100 buf snprintf
     % sets buf to "Hi, 10 > 5\n"

 - strsize
   Returns the size of the string in pixel (using the current font).

   stack: ( string_1 ) --> ( int_1 int_2 )
   % int_1, int_2: width, height

 - sub

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 - int_2

 - tint

   stack: ( int_1 int_2 int_3 ) --> ( )

 - trace
   Enter single step mode. Waits for a keypress after every instruction.
   Leave this mode by pressing Esc.

   stack: ( ) --> ( )

 - xor

   stack: ( int_1 int_2 ) --> ( int_3 )		% int_3 = int_1 ^ int_2
   stack: ( bool_1 bool_2 ) --> ( bool_3 )	% bool_3 = bool_1 ^^ bool_2

