summaryrefslogtreecommitdiffstats
path: root/src/system.inc
diff options
context:
space:
mode:
Diffstat (limited to 'src/system.inc')
-rw-r--r--src/system.inc1406
1 files changed, 1406 insertions, 0 deletions
diff --git a/src/system.inc b/src/system.inc
new file mode 100644
index 0000000..a08945b
--- /dev/null
+++ b/src/system.inc
@@ -0,0 +1,1406 @@
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Some basic definitions.
+%
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+% some key codes
+/keyEsc 0x0000001b def
+/keyEnter 0x0000000d def
+/keyTab 0x00000009 def
+/keyShiftTab 0x0f000000 def
+/keyF1 0x3b000000 def
+/keyF2 0x3c000000 def
+/keyF3 0x3d000000 def
+/keyF4 0x3e000000 def
+/keyF5 0x3f000000 def
+/keyF6 0x40000000 def
+/keyF7 0x41000000 def
+/keyF8 0x42000000 def
+/keyF9 0x43000000 def
+/keyF10 0x44000000 def
+/keyF11 0x85000000 def
+/keyF12 0x86000000 def
+/keyHome 0x47000000 def
+/keyUp 0x48000000 def
+/keyPgUp 0x49000000 def
+/keyLeft 0x4b000000 def
+/keyRight 0x4d000000 def
+/keyEnd 0x4f000000 def
+/keyDown 0x50000000 def
+/keyPgDown 0x51000000 def
+/keyIns 0x52000000 def
+/keyDel 0x53000000 def
+/keyShiftF1 0x54000000 def
+/keyShiftF2 0x55000000 def
+/keyShiftF3 0x56000000 def
+/keyShiftF4 0x57000000 def
+/keyShiftF5 0x58000000 def
+/keyShiftF6 0x59000000 def
+/keyShiftF7 0x5a000000 def
+/keyShiftF8 0x5b000000 def
+/keyShiftF9 0x5c000000 def
+/keyShiftF10 0x5d000000 def
+/keyShiftF11 0x87000000 def
+/keyShiftF12 0x88000000 def
+/keyCtrlF1 0x5e000000 def
+/keyCtrlF2 0x5f000000 def
+/keyCtrlF3 0x60000000 def
+/keyCtrlF4 0x61000000 def
+/keyCtrlF5 0x62000000 def
+/keyCtrlF6 0x63000000 def
+/keyCtrlF7 0x64000000 def
+/keyCtrlF8 0x65000000 def
+/keyCtrlF9 0x66000000 def
+/keyCtrlF10 0x67000000 def
+/keyAltF1 0x68000000 def
+/keyAltF2 0x69000000 def
+/keyAltF3 0x6a000000 def
+/keyAltF4 0x6b000000 def
+/keyAltF5 0x6c000000 def
+/keyAltF6 0x6d000000 def
+/keyAltF7 0x6e000000 def
+/keyAltF8 0x6f000000 def
+/keyAltF9 0x70000000 def
+/keyAltF10 0x71000000 def
+/keyCtrlLeft 0x73000000 def
+/keyCtrlRight 0x74000000 def
+/keyCtrlEnd 0x75000000 def
+/keyCtrlDown 0x76000000 def
+/keyCtrlHome 0x76000000 def
+/keyCtrlUp 0x84000000 def
+/keyStatus 0xff000000 def
+
+/statusAlt 0x0208 def
+/statusAltL 0x0200 def
+/statusAltR 0x0008 def
+/statusCtrl 0x0104 def
+/statusShift 0x0003 def
+
+/CapsLock { 0x417 cvp getbyte 0x40 and 0 ne } def
+
+/black 0 def
+/white 0xffffff def
+
+% input object fields
+/.inp_x 0 def % x pos
+/.inp_y 1 def % y pos
+/.inp_back 2 def % background pixmap
+/.inp_buf 3 def % input buffer
+/.inp_buf_len 4 def % input buffer length
+/.inp_int 5 def % internal state array, see below
+% optional fields
+/.inp_hidden 6 def % hidden buffer
+/.inp_label 7 def % input field label
+/.inp_visible 8 def % field is visible
+/.inp_show 9 def % field should be visible
+
+/.inp_int_cur 0 def % current edit char offset
+/.inp_int_cursor 1 def % cursor pos (pixel)
+/.inp_int_shift 2 def % input line shifted (pixel)
+/.inp_int_flags 3 def % bit 0: cursor visible
+/.inp_int_saved_cursor 4 def % saved cursor background
+
+% boot loader
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% bootloader - boot loader type
+%
+% group: system
+%
+% ( -- int1 )
+%
+% int1: boot loader type (0: lilo, 1:syslinux/isolinux, 2: grub)
+%
+/bootloader sysconfig getbyte def
+
+/lilo bootloader 0 eq def
+/syslinux bootloader 1 eq def
+/grub bootloader 2 eq def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% boot_failsafe - failsafe options the user selected (bitmask)
+%
+% group: system
+%
+% ( -- int1 )
+%
+% int1: option bitmask
+% bit 0: SHIFT pressed
+% bit 1: no graphics
+% bit 2: no monitor detection
+%
+/boot_failsafe sysconfig 3 add getbyte def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% bootdrive - drive the BIOS booted from
+%
+% group: system
+%
+% ( -- int1 )
+%
+% int1: BIOS drive id
+%
+/bootdrive sysconfig 5 add getbyte def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% mediatype - type of media we booted from
+%
+% group: system
+%
+% ( -- int1 )
+%
+% int1: media type (0 disk, 1 floppy, 2 cdrom)
+%
+/mediatype sysconfig 2 add getbyte def
+
+/m_disk 0 def
+/m_floppy 1 def
+/m_cdrom 2 def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% biosmem - BIOS reported memory size
+%
+% group: mem
+%
+% ( -- int1 )
+%
+% int1: total memory size according to BIOS
+%
+/biosmem sysconfig 20 add getdword def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% sectorsize - sector size
+%
+% group: mem system
+%
+% ( -- int1 )
+%
+% int1: sector size in bytes
+%
+/sectorsize
+ 1
+ sysconfig 1 add getbyte
+ 20 min % max. 1 MB
+ dup 0 eq { pop 9 } if
+ shl
+def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% getinfo - type of info box
+%
+% group: system
+%
+% ( int1 -- int2 )
+%
+% int1: type of info box we have to show
+% int2: some data
+%
+% Note: really weird, should be replaced by something more obvious.
+%
+/getinfo {
+ 2 shl
+ sysconfig 12 add exch add getdword
+} def
+
+
+% bool values
+/true 0 0 eq def
+/false 0 0 ne def
+
+% type values
+/t_none 0 def
+/t_int 1 def
+/t_unsigned 2 def
+/t_bool 3 def
+/t_string 4 def
+/t_code 5 def
+/t_ret 6 def
+/t_prim 7 def
+/t_sec 8 def
+/t_dict_idx 9 def
+/t_array 10 def
+/t_end 11 def
+/t_ptr 12 def
+
+/.value { t_int settype } def
+/.undef 0 t_none settype def
+/.end 0 t_end settype def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print string (for debugging).
+%
+% ( string ) ==> ( )
+%
+/string.print {
+ dup
+ currentpoint currentpoint 5 -1 roll strsize image moveto
+ show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print number (for debugging).
+%
+% ( number ) ==> ( )
+%
+/number.print {
+ 32 string
+ exch over
+ "%08x" exch sprintf
+ dup string.print
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print obj (for debugging).
+%
+% ( obj ) ==> ( )
+%
+/obj.print {
+ 64 string
+ exch dup
+ .value exch gettype
+ "%x:%08x" 3 index sprintf
+ dup string.print
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Print (for debugging).
+%
+% ( obj ) ==> ( )
+%
+/print {
+ dup gettype t_int eq { number.print return } if
+ dup gettype t_string eq { string.print return } if
+ obj.print
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Convert object to pointer.
+%
+% ( obj ) ==> ( ptr )
+%
+/cvp { t_ptr settype } def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Convert object to string.
+%
+% ( obj ) ==> ( string )
+%
+/cvs { t_string settype } def
+
+
+% base num char
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Convert object to number.
+%
+% ( obj ) ==> ( int )
+%
+/cvn {
+ dup gettype t_string eq {
+ 1 % sign
+ exch dup 0 get '-' eq {
+ exch pop 1 add -1 exch
+ } if
+ 10 % initial base
+ 0 % value
+ rot
+ {
+ dup 'a' ge { 0x20 sub } if
+ dup 'X' eq { pop pop pop 16 0 '0' } if
+ '0' sub
+ dup 9 gt { 7 sub } if
+ dup 0 lt over 4 index ge or { pop exit } if
+ exch 2 index mul add
+ } forall
+ exch pop mul
+ } {
+ t_int settype
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Arguments like snprintf.
+%
+% ( obj_1 ... obj_n string_1 string_2 ) ==> ( )
+%
+/sprintf {
+ dup cvp length exch snprintf
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Allocate new string.
+%
+% ( size ) ==> ( string )
+/string {
+ 1 add malloc cvs
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Increment variable.
+%
+% ( dict_ref ) ==> ( )
+%
+/inc {
+ dup exec 1 add def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Decrement variable.
+%
+% ( dict_ref ) ==> ( )
+%
+/dec {
+ dup exec 1 sub def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Copy src to dst.
+%
+% Watch overlapping src & dst!
+%
+% ( dst src ) ==> ( dst )
+%
+/strcpy {
+ "%s" 2 index sprintf
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Duplicate string.
+%
+% ( string ) ==> ( string )
+%
+/strdup {
+ dup length string exch strcpy
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Concatenate strings.
+%
+% ( string1 string2 ) ==> ( string1 )
+%
+/strcat {
+ over dup length add exch strcpy pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Test for AltGr.
+%
+% ( ) ==> ( bool )
+%
+/is_altGr {
+ keystat statusAltR and 0 ne keystat statusAltL and 0 eq and
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Keyboard mapping.
+%
+% ( key ) ==> ( key )
+%
+/mapkey {
+ dup 24 shr 0xff and /key.code exch def
+ is_altGr {
+ % bios is too smart...
+ key.code 0x78 ge key.code 0x83 le and { /key.code key.code 0x76 sub def } if
+ } if
+ 0 1 config.keymap length 1 sub {
+ config.keymap exch get
+ dup 0 get key.code eq {
+ 1
+ keystat statusShift and { pop 2 } if
+ is_altGr { pop 3 } if
+ get
+ exch pop
+ } {
+ pop
+ } ifelse
+ } for
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Set password mode font property.
+%
+% ( font ) ==> ( font )
+%
+/pwmode {
+ dup gettype t_ptr eq {
+ .value 0x80000000 or t_ptr settype
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Test for password mode.
+%
+% ( font -- true|false )
+%
+/is.pwmode {
+ dup gettype t_ptr eq {
+ .value 0x80000000 and 0 ne
+ } {
+ false
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show one-line string right aligned.
+%
+% ( string ) ==> ( )
+%
+/showright1 {
+ dup strsize pop neg 0 rmoveto currentpoint rot show currentpoint exch pop exch pop moveto
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show string right aligned.
+%
+% ( string ) ==> ( )
+%
+/showright {
+ '\n' split
+ currentpoint pop
+ false 2 index
+
+ % array x not_first? array
+ {
+ % array x not_first? elem
+
+ over {
+ "\n" show
+ 2 index currentpoint exch pop moveto
+ } if
+
+ dup showright1 free
+
+ pop true
+ } forall
+ pop pop
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show string right/left aligned.
+%
+% ( string ) ==> ( )
+%
+/show.rtl {
+ config.rtl { showright } { show } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Show string centered.
+%
+% ( string ) ==> ( )
+%
+/showcenter {
+ dup strsize pop 2 div neg 0 rmoveto show
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Generate pseudo random number.
+% Good enough for boot loader splash screen.
+%
+% ( ) ==> ( int )
+%
+/rand {
+ rand.start 59 mul 97 add 0x7fffffff and
+ /rand.start over def
+} def
+
+% start value
+/rand.start time def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% ( date ) ==> ( weekday )
+%
+% (Monday: 0)
+%
+% d + [26*(m+1)/10] + j + [j/4] + [c/4] - 2 c - 2
+%
+/weekday {
+ dup day exch
+ dup year exch
+ month dup 2 le { 12 add exch 1 sub exch } if
+ 1 add 26 mul 10 div
+ exch dup
+ 100 mod dup 4 div add
+ exch 100 div dup 4 div exch 2 mul sub
+ add add add
+ 7 mod 12 add
+ 7 mod
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% ( date ) ==> ( day )
+%
+/day {
+ 0xff and
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% ( date ) ==> ( month )
+%
+/month {
+ 8 shr 0xff and
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% ( date ) ==> ( year )
+%
+/year {
+ 16 shr
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Read CMOS RAM.
+%
+% ( index ) ==> ( value )
+%
+/nvram {
+ 0x70 exch outbyte
+ 0x71 inbyte
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% readsector - read sector
+%
+% group: system
+%
+% ( int1 -- ptr1 )
+%
+% int1: sector number
+% ptr1: buffer with sector data or .undef. Use @free to free the buffer.
+%
+% Note: does not return on error. Returns .undef if function is not implemented.
+%
+/readsector {
+ _readsector
+ dup .undef eq { return } if
+
+ sectorsize malloc dup rot over length memcpy
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.data - return array with gfxboot config entries
+%
+% Reads and parses "gfxboot.cfg" when called first time.
+%
+% group: system
+%
+% ( -- array1 )
+%
+% array1: config values
+%
+% array1 may be empty but is never .undef.
+% Elements of array1 (if any) are arrays of three strings: [ section key value ].
+%
+/gfxconfig.data {
+
+ % read file and copy to temp string (we need the final 0)
+ "gfxboot.cfg" findfile dup .undef ne {
+ dup dup length dup string dup cvp 4 2 roll memcpy exch free
+ } {
+ pop ""
+ } ifelse
+
+ % free temp string and create temp array
+ /gfxconfig.data over '\n' split def free
+
+ % modifies gfxconfig.data
+ /gfxconfig.data [
+
+ "base" % default section
+
+ gfxconfig.data {
+
+ skipspaces
+
+ dup 0 get dup 0 eq over ';' eq or exch '#' eq or {
+ % empty or comment
+ pop
+ } {
+ dup 0 get '[' eq {
+ % [section]
+ 1 add
+ dup "]" strstr dup {
+ % put new section on stack
+ 1 sub over exch 0 put
+ exch free
+ } {
+ % wrong [section] entry
+ pop pop
+ } ifelse
+ } {
+ % key=value?
+ dup "=" strstr dup {
+ over over 1 sub over exch 0 put add
+ [ 3 index 4 2 roll ] exch
+ } {
+ % no "="
+ pop pop
+ } ifelse
+ } ifelse
+ } ifelse
+ } forall
+
+ free
+ ]
+
+ % free temp array
+ gfxconfig.data free
+
+ def
+
+ gfxconfig.data
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.layout - return array with config file sections
+%
+% group: system
+%
+% ( -- array1 )
+%
+% array1: section names
+%
+% array1 may be empty but is never .undef.
+%
+/gfxconfig.layout {
+
+ /gfxconfig.layout [ "base" ] def
+
+ "layout" gfxconfig.array_str
+ dup .undef ne {
+ gfxconfig.layout free
+ [ exch { } forall "base" ] /gfxconfig.layout exch def
+ } {
+ pop
+ } ifelse
+
+ gfxconfig.layout
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.getentry_s - return gfxboot config file entry
+%
+% group: system
+%
+% ( str1 str2 -- str3 )
+%
+% str1: section
+% str2: config entry key
+% str3: config value (or .undef)
+%
+/gfxconfig.getentry_s {
+ .undef
+ gfxconfig.data {
+ 3 index over 0 get eq 3 index 2 index 1 get eq and {
+ 2 get exch pop exit
+ } {
+ pop
+ } ifelse
+ } forall
+
+ exch pop exch pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.getentry - return raw gfxboot config file entry
+%
+% group: system
+%
+% ( str1 -- str2 )
+%
+% str1: config entry key
+% str2: config value (or .undef)
+%
+/gfxconfig.getentry {
+ .undef
+
+ gfxconfig.layout {
+ 2 index gfxconfig.getentry_s
+ dup .undef eq {
+ pop
+ } {
+ exch pop
+ exit
+ } ifelse
+ } forall
+
+ exch pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.str - return gfxboot config file entry: string
+%
+% group: system
+%
+% ( str1 -- str2 )
+%
+% str1: config entry key
+% str2: config value (or .undef)
+%
+/gfxconfig.str {
+ gfxconfig.getentry dup .undef ne { strdup dup dropspaces } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.int - return gfxboot config file entry: integer
+%
+% group: system
+%
+% ( str1 -- int1 )
+%
+% str1: config entry key
+% int1: config value (or .undef)
+%
+/gfxconfig.int {
+ gfxconfig.getentry dup .undef ne { cvn } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.int2 - return gfxboot config file entry: two integers
+%
+% group: system
+%
+% ( str1 -- int1 int2 )
+%
+% str1: config entry key
+% int1: first config value (or .undef)
+% int2: second config value (or .undef)
+%
+/gfxconfig.int2 {
+ gfxconfig.array_int dup .undef eq { pop [ ] } if
+ dup 0 aget over 1 aget rot free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.array_str - return gfxboot config file entry: array of strings
+%
+% group: system
+%
+% ( str1 -- array1 )
+%
+% str1: config entry key
+% array1: config value (or .undef)
+%
+/gfxconfig.array_str {
+ gfxconfig.getentry dup .undef ne { ',' split } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.array_int - return gfxboot config file entry: array of integers
+%
+% group: system
+%
+% ( str1 -- array1 )
+%
+% str1: config entry key
+% array1: config value (or .undef)
+%
+/gfxconfig.array_int {
+ gfxconfig.array_str dup .undef ne {
+ [ exch
+ { dup .undef ne { cvn } if } forall
+ ]
+ } if
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.str - initialize variable with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 str1 str2 -- )
+%
+% dict1: variable to modify
+% str1: config entry key
+% str2: default value
+%
+/gfxconfig.set.str {
+ exch gfxconfig.str
+ dup .undef ne { exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.int - initialize variable with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 str1 int1 -- )
+%
+% dict1: variable to modify
+% str1: config entry key
+% int1: default value
+%
+/gfxconfig.set.int {
+ exch gfxconfig.int
+ dup .undef ne { exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.int2 - initialize two variables with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 dict2 str1 int1 int2 -- )
+%
+% dict1: first variable to modify
+% dict2: second variable to modify
+% str1: config entry key
+% int1: first default value
+% int2: second default value
+%
+/gfxconfig.set.int2 {
+ rot gfxconfig.int2
+ % dict1 dict2 def1 def2 val1 val2
+ exch 4 -1 roll exch
+ % dict1 dict2 def2 val2 def1 val1
+ dup .undef ne { exch } if pop
+ 5 -1 roll exch def
+ % dict2 def2 val2
+ dup .undef ne { exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.bool - initialize variable with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 str1 bool1 -- )
+%
+% dict1: variable to modify
+% str1: config entry key
+% bool1: default value
+%
+/gfxconfig.set.bool {
+ exch gfxconfig.int
+ dup .undef ne { 0 ne exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.array_str - initialize variable with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 str1 array1 -- )
+%
+% dict1: variable to modify
+% str1: config entry key
+% array1: default value
+%
+/gfxconfig.set.array_str {
+ exch gfxconfig.array_str
+ dup .undef ne { exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% gfxconfig.set.array_int - initialize variable with gfxboot config file entry
+%
+% group: system
+%
+% ( dict1 str1 array1 -- )
+%
+% dict1: variable to modify
+% str1: config entry key
+% array1: default value
+%
+/gfxconfig.set.array_int {
+ exch gfxconfig.array_int
+ dup .undef ne { exch } if pop def
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% split - split string
+%
+% group:
+%
+% ( str1 int1 -- array1 )
+%
+% str1: string
+% int1: char
+% array1: array of strings
+%
+/split {
+
+ % split does not work if str1 is in a special memory region (where
+ % 'cvp length' does not work). So we dup it first.
+
+ exch strdup dup rot
+
+ currenteotchar exch seteotchar exch
+
+ [ exch
+
+ {
+ dup strdup exch
+ dup length add
+
+ dup cvp length 1 le { pop exit } if
+
+ 1 add
+
+ } loop
+
+ ]
+
+ exch seteotchar
+
+ exch free
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% join - join array of strings
+%
+% group:
+%
+% ( array1 str1 -- str2 )
+%
+% array1: array of strings
+% str1: separator
+% str2: complete string
+%
+/join {
+ over length 0 eq { pop pop 0 string return } if
+
+ over length 1 sub over length mul
+ 2 index { length add } forall
+ string
+
+ % note: last element is not followed by separator because it exceeds
+ % the destination string size
+ rot {
+ strcat over strcat
+ } forall
+
+ exch pop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Skip leading non-spaces.
+%
+% ( string ) ==> ( string )
+%
+/skipnonspaces {
+ { dup 0 get dup 0 ne exch ' ' ne and { 1 add } { exit } ifelse } loop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Skip leading spaces.
+%
+% ( string ) ==> ( string )
+%
+/skipspaces {
+ { dup 0 get ' ' eq { 1 add } { exit } ifelse } loop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Drop spaces at string end.
+% Modifies string!
+%
+% ( string ) ==> ( )
+%
+/dropspaces {
+ dup length
+ dup 0 eq {
+ pop pop
+ } {
+ 1 sub
+ -1 0 {
+ over over get ' ' eq { over exch 0 put } { pop exit } ifelse
+ } for
+ pop
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Test if string[ofs-1]/string[ofs] is a word boundary.
+%
+% ( string ofs ) ==> ( true|false )
+%
+% boundary is either space/non-space or non-space/(space|'=')
+%
+/iswordboundary {
+ dup 0 eq { pop pop true return } if
+
+ add dup 1 sub 0 get exch 0 get
+
+ over ' ' eq over ' ' gt and { pop pop true return } if
+ over ' ' gt over dup ' ' eq exch dup '=' eq exch 0 eq or or and { pop pop true return } if
+
+ pop pop false
+} def
+
+
+%% findmode - find video mode number
+%
+% group: gfx.screen
+%
+% ( int1 int2 int3 -- int4 )
+%
+% int1, int2: width, height
+% int3: color bits
+% int4: mode number (or .undef)
+%
+% example
+% 1024 768 16 findmode setmode % 1024x768, 16-bit color mode
+%
+/findmode {
+ 0 1 videomodes {
+ videomodeinfo dup .undef eq {
+ pop pop pop pop
+ } {
+ % compare width, height, colors
+ 6 index 4 index eq 6 index 4 index eq and 5 index 3 index eq and {
+ 7 1 roll 6 { pop } repeat 0xbfff and return
+ } {
+ pop pop pop pop
+ } ifelse
+ } ifelse
+ } for
+
+ pop pop pop .undef
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%
+% Replace substring. Returns newly allocated string.
+%
+% ( str key value ) ==> ( new_str )
+%
+% Replaces first occurence of 'key' in str with 'value'.
+%
+/strreplace {
+ 2 index 2 index strstr dup 0 ne {
+ 1 sub
+ over length 3 index length sub 4 index length add string
+ dup cvp 5 index cvp 3 index memcpy
+ dup 6 1 roll over add exch 5 -1 roll exch add
+ 4 -1 roll length add 3 1 roll "%s%s" exch sprintf
+ } {
+ pop pop pop strdup
+ } ifelse
+
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Search for option in cmdline.
+% Returns .undef if not found.
+%
+% ( cmdline option_name ) ==> ( option_start )
+%
+/bootopt.find {
+ /_bo.opt exch def
+ /_bo.cmdline exch def
+ /_bo.= _bo.opt dup length 1 sub get '=' eq def
+
+ {
+ _bo.cmdline _bo.opt strstr
+ dup {
+ dup 1 eq {
+ true
+ } {
+ dup 2 sub _bo.cmdline exch get ' ' eq
+ } ifelse
+
+ {
+ _bo.cmdline over _bo.opt length add 1 sub get
+ dup '=' eq
+ over ' ' eq or
+ exch 0 eq or
+ _bo.= or
+ } {
+ false
+ } ifelse
+
+ _bo.cmdline rot add exch
+
+ {
+ 1 sub exit
+ } {
+ /_bo.cmdline exch def
+ } ifelse
+ } {
+ pop
+ .undef exit
+ } ifelse
+ } loop
+
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Search for second occurence of option in cmdline.
+% Returns .undef if not found.
+%
+% ( cmdline option_name ) ==> ( option_start )
+%
+/bootopt.find2 {
+ over over bootopt.find dup .undef eq {
+ pop pop pop .undef
+ } {
+ 1 add rot pop exch bootopt.find
+ } ifelse
+} def
+
+
+% Remove option from cmdline. Returns removed option or .undef.
+%
+% cmdline is modified, option_entry is allocated dynamicyll and must be
+% freed later.
+%
+% ( cmdline option_name -- option_entry )
+%
+/bootopt.remove {
+ bootopt.find dup .undef ne {
+ dup
+ skipnonspaces dup skipspaces 2 index sub rot rot over sub string over strcpy
+ rot rot
+ {
+ over over exch get
+ over over 0 exch put {
+ 1 add
+ } {
+ exit
+ } ifelse
+ } loop
+ pop pop
+ } if
+} def
+
+
+% Video memory in kb.
+%
+% ( -- int )
+%
+/video.memory {
+ /video.memory 0 sysinfo def
+ video.memory
+} def
+
+
+% Graphics card OEM info.
+%
+% ( -- string )
+%
+/video.oem {
+ /video.oem 1 sysinfo strdup def
+ video.oem
+} def
+
+
+% Graphics card vendor name.
+%
+% ( -- string )
+%
+/video.vendor {
+ /video.vendor 2 sysinfo strdup def
+ video.vendor
+} def
+
+
+% Graphics card product name.
+%
+% ( -- string )
+%
+/video.product {
+ /video.product 3 sysinfo strdup def
+ video.product
+} def
+
+
+% Graphics card revision.
+%
+% ( -- string )
+%
+/video.revision {
+ /video.revision 4 sysinfo strdup def
+ video.revision
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Free memory.
+%
+% Like free, but accepts dict entries, too.
+%
+% ( obj -- )
+%
+/xfree {
+ dup gettype
+ t_dict_idx eq {
+ dup exec exch .undef def
+ } if
+ free
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Free array and all its elements.
+%
+% If array is a dict entries, undefines it, too.
+%
+% ( array -- )
+%
+/afree {
+ dup .undef ne {
+ dup gettype t_dict_idx eq { dup exec exch .undef def } if
+ dup { free } forall
+ free
+ } {
+ pop
+ } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Get array element.
+%
+% Like get, but returns .undef if index is outside array bounds.
+%
+% ( array index -- obj )
+%
+/aget {
+ over length over gt { get } { pop pop .undef } ifelse
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Search for array element.
+%
+% ( array key -- bool )
+%
+/iselement {
+ false rot {
+ 2 index eq { pop true exit } if
+ } forall
+ exch pop
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% pc speaker beep.
+%
+% ( freq duration -- )
+%
+% freq in Hz, duration in microseconds.
+%
+/beep {
+ exch
+ 0x61 inbyte
+ dup 3 or 0x61 exch outbyte
+ 0x43 0xb6 outbyte
+ exch 2386360 exch div
+
+ dup 0x42 exch outbyte
+ 8 shr 0x42 exch outbyte
+
+ exch usleep
+
+ 0x61 exch outbyte
+} def
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Play movie.
+%
+% ( str1 -- )
+%
+% Image filename template.
+%
+/play_movie {
+ 64 string
+
+ 0
+
+ {
+ 1 add
+ dup 3 index 3 index sprintf
+
+ over findfile dup .undef eq {
+ pop exit
+ } {
+ 10000 usleep
+ currentimage
+ over setimage 0 0 image.size image
+ setimage
+ free
+ } ifelse
+
+
+ } loop
+
+ pop free pop
+
+} def
+
+