1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
% example_04.bc
%
% Draws simple menu and lets you select an entry.
%
% Notes:
% - 'MenuInit' is, like 'KeyEvent' a callback function; it must be defined
% if you want the menu data
%
% - also, we process the keycode a bit to get the ASCII value
%
% Test with (from top level dir [/usr/share/gfxboot]) 'gfxtest -t example_04'.
%
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Some constants we probably need.
%
/true 0 0 eq def
/false 0 0 ne def
% some key codes
/keyEsc 0x0000001b def
/keyEnter 0x0000000d def
/keyUp 0x48000000 def
/keyLeft 0x4b000000 def
/keyRight 0x4d000000 def
/keyDown 0x50000000 def
% type values
/t_none 0 def
/t_end 11 def
/t_ptr 12 def
% undefined (nil) value
/.undef 0 t_none settype def
% end token, stops execution
/.end 0 t_end settype def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Convert integer to pointer.
%
% ( int1 -- ptr1 )
%
/cvp { t_ptr settype } def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% findmode - find video mode number
%
% ( 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
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Input event handling.
%
% ( key -- input_buffer menu_entry action )
%
% key
% bit 0-7 ascii
% bit 8-15 scan code
% bit 16-32 status bits (ctrl, shift...)
%
% action
% 0: ok, stay in input loop
% 1: switch to text mode (that is, continue with the non-gfxboot bootloader interface)
% >=2: boot
%
% Notes:
% - key = 0 indicates the bootloader timeout is up.
% - input_buffer is the command line that you would have normally entered in the bootloader.
% note that for syslinux it must start with the menu label string but not for grub
% - menu_entry is the number of the menu entry you want to boot
%
/KeyEvent {
% pre-process keycode a bit
dup 0xff00 and 16 shl exch 0xff and dup 0xe0 eq { pop 0 } if add
dup 0xff and { 0xff and } if
/key exch def
% 'key' now holds the ASCII code for 'normal' keys and the scan code in the
% upper 8 bits if there is no ASCII code (e.g. F-keys, cursor keys)
% process key events...
key keyDown eq {
menu.entry menu.texts length 1 sub lt {
menu.entry menu.deselect
/menu.entry menu.entry 1 add def
menu.entry menu.select
} if
} if
key keyUp eq {
menu.entry 0 gt {
menu.entry menu.deselect
/menu.entry menu.entry 1 sub def
menu.entry menu.select
} if
} if
key keyEnter eq {
menu.texts menu.entry get menu.entry 2 return
} if
"" 0 0
} def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Setup boot menu.
%
% ( menu_entries_array cmdline_args_array defaultentry -- )
%
% This function is called before the first key event and gets passed the
% bootloader config data.
%
/MenuInit {
% this is a string
/menu.default_entry exch def
% both are arrays
/menu.args exch def
/menu.texts exch def
% find index of the default entry
/menu.entry 0 def
0 1 menu.texts length 1 sub {
menu.texts over get
menu.default_entry eq { /menu.entry exch def exit } if
pop
} for
% menu position
/menu.x 300 def
/menu.y 150 def
% 1.5 * font size
/menu.dy fontheight dup 2 div add def
% yellow
0xe0e000 setcolor
% draw menu
menu.x menu.y moveto
menu.texts {
show
currentpoint exch pop menu.dy add menu.x exch moveto
} forall
% mark default entry
menu.entry menu.select
} def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Show selected item.
%
% ( index -- )
%
/menu.select {
menu.dy mul menu.y add
menu.x exch moveto
">" dup strsize pop neg 10 sub 0 rmoveto
0xffffff setcolor
show
} def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% Show deselected item.
%
% ( index -- )
%
/menu.deselect {
menu.dy mul menu.y add
menu.x exch moveto
">" dup strsize pop neg 10 sub 0 rmoveto
currentpoint rot strsize image
} def
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% set 800x600 graphics mode
% try 32 bit first; if no mode can be found, exit and continue without gfxboot
800 600 32 findmode setmode not {
800 600 16 findmode setmode not {
false .end
} if
} if
% load and set font
"font.fnt" findfile setfont
% load and set background image
"clouds.jpg" findfile setimage
0 0 moveto
0 0 image.size image
% say we're fine ('false' tells bootloader not to use gfxboot)
true
|