|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
%
|
|
|
|
% List dialog handling.
|
|
|
|
%
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Some global vars.
|
|
|
|
%
|
|
|
|
/xmenu.vspace.default { xmenu .xm_list get length 15 ge { 2 } { 4 } ifelse } def
|
|
|
|
/xmenu.hspace 12 def
|
|
|
|
/xmenu.light white def
|
|
|
|
/xmenu.dark black def
|
|
|
|
/xmenu.font font.normal def
|
|
|
|
/xmenu.normal.bg lightgray def
|
|
|
|
/xmenu.normal.fg black def
|
|
|
|
/xmenu.selected.fg white def
|
|
|
|
/xmenu.selected.bg 0x6c6c6c newcolor
|
|
|
|
|
|
|
|
small_layout {
|
|
|
|
/xmenu.maxlines 22 def
|
|
|
|
} {
|
|
|
|
/xmenu.maxlines 28 def
|
|
|
|
} ifelse
|
|
|
|
|
|
|
|
% xmenu layout
|
|
|
|
%
|
|
|
|
% [ selected_entry string_list x y panel_x ]
|
|
|
|
%
|
|
|
|
/.xm_current 0 def % selected entry
|
|
|
|
/.xm_list 1 def % string list
|
|
|
|
/.xm_x 2 def % menu x pos
|
|
|
|
/.xm_y 3 def % menu y pos
|
|
|
|
/.xm_width 4 def % menu width
|
|
|
|
/.xm_height 5 def % menu height
|
|
|
|
/.xm_panel_x 6 def % panel entry x pos
|
|
|
|
/.xm_panel_width 7 def % panel entry width
|
|
|
|
/.xm_panel_height 8 def % panel entry height
|
|
|
|
/.xm_vspace 9 def % vspace per menu
|
|
|
|
/.xm_title 10 def % xmenu title
|
|
|
|
/.xm_columns 11 def % menu columns
|
|
|
|
/.xm_size 12 def % xmenu size
|
|
|
|
|
|
|
|
|
|
|
|
% short hands
|
|
|
|
/xmenu.x { xmenu .xm_x get } def
|
|
|
|
/xmenu.y { xmenu .xm_y get } def
|
|
|
|
/xmenu.width { xmenu .xm_width get } def
|
|
|
|
/xmenu.height { xmenu .xm_height get } def
|
|
|
|
/xmenu.columns { xmenu .xm_columns get } def
|
|
|
|
|
|
|
|
/xmenu.vspace { xmenu .xm_vspace get dup .undef ne { } { pop xmenu.vspace.default } ifelse } def
|
|
|
|
|
|
|
|
/xmenu.saved { xmenu.saved.areas xmenu.column get 2 get } def
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Create new xmenu.
|
|
|
|
%
|
|
|
|
% ( ) ==> ( window )
|
|
|
|
%
|
|
|
|
/window.xmenu {
|
|
|
|
widget.size array
|
|
|
|
dup .type t_xmenu put
|
|
|
|
dup .xmenu.select .undef put
|
|
|
|
dup .xmenu.input .undef put
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Handle keyboard input.
|
|
|
|
%
|
|
|
|
% ( key_in ) ==> ( key_out )
|
|
|
|
%
|
|
|
|
/xmenu.input {
|
|
|
|
dup 0 eq { return } if
|
|
|
|
|
|
|
|
dup keyEsc eq {
|
|
|
|
xmenu 0 xmenu.oldentry put
|
|
|
|
window.done
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyEnter eq {
|
|
|
|
window.current .xmenu.update get
|
|
|
|
window.done
|
|
|
|
exec
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyDown eq {
|
|
|
|
xmenu .xm_current get 1 add xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyUp eq {
|
|
|
|
xmenu .xm_current get 1 sub xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyPgDown eq {
|
|
|
|
xmenu .xm_current get 5 add
|
|
|
|
xmenu .xm_list get length 1 sub min xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyPgUp eq {
|
|
|
|
xmenu .xm_current get 5 sub
|
|
|
|
0 max xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyHome eq {
|
|
|
|
0 xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyEnd eq {
|
|
|
|
xmenu .xm_list get length 1 sub xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyRight eq {
|
|
|
|
xmenu .xm_current get
|
|
|
|
dup xmenu.maxlines div 1 add xmenu.columns mod xmenu.maxlines mul
|
|
|
|
exch xmenu.maxlines mod add
|
|
|
|
xmenu .xm_list get length 1 sub min xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyLeft eq {
|
|
|
|
xmenu .xm_current get
|
|
|
|
dup xmenu.maxlines div xmenu.columns add 1 sub xmenu.columns mod xmenu.maxlines mul
|
|
|
|
exch xmenu.maxlines mod add
|
|
|
|
xmenu .xm_list get length 1 sub min xmenu.select
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup keyF1 eq {
|
|
|
|
show_help
|
|
|
|
pop 0
|
|
|
|
} if
|
|
|
|
|
|
|
|
window.current .xmenu.input get dup .undef ne { exec } { pop } ifelse
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Calculate menu sizes.
|
|
|
|
%
|
|
|
|
% ( ) ==> ( )
|
|
|
|
%
|
|
|
|
/xmenu.sizes {
|
|
|
|
/xmenu.lheight xmenu.font setfont fontheight xmenu.vspace dup add add def
|
|
|
|
|
|
|
|
xmenu .xm_columns
|
|
|
|
xmenu .xm_list get length xmenu.maxlines add 1 sub xmenu.maxlines div
|
|
|
|
put
|
|
|
|
|
|
|
|
/xmenu.lastheight
|
|
|
|
xmenu .xm_list get length xmenu.maxlines xmenu.columns 1 sub mul sub xmenu.lheight mul
|
|
|
|
def
|
|
|
|
|
|
|
|
xmenu .xm_height
|
|
|
|
xmenu .xm_list get length xmenu.maxlines min xmenu.lheight mul
|
|
|
|
put
|
|
|
|
|
|
|
|
xmenu .xm_width
|
|
|
|
0 xmenu .xm_list get { exec strsize pop max } forall xmenu.hspace 2 mul add
|
|
|
|
put
|
|
|
|
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Init and show menu.
|
|
|
|
%
|
|
|
|
% ( window ) ==> ( )
|
|
|
|
%
|
|
|
|
% xmenu: [ selected_entry [ text0 text1 ... ] x y ]
|
|
|
|
%
|
|
|
|
/xmenu.init {
|
|
|
|
/xmenu over .xmenu get def
|
|
|
|
|
|
|
|
xmenu.sizes
|
|
|
|
|
|
|
|
dup .saved.areas xmenu.columns array /xmenu.saved.areas over def put
|
|
|
|
|
|
|
|
0 1 xmenu.columns 1 sub {
|
|
|
|
/xmenu.column exch def
|
|
|
|
|
|
|
|
dup .saved.areas get xmenu.column
|
|
|
|
|
|
|
|
[
|
|
|
|
xmenu.column xmenu.width 2 add mul xmenu.x add 1 sub xmenu.y 1 sub moveto
|
|
|
|
currentpoint
|
|
|
|
|
|
|
|
xmenu.light xmenu.dark
|
|
|
|
xmenu.width 2 add
|
|
|
|
xmenu.column 1 add xmenu.columns eq { xmenu.lastheight } { xmenu.height } ifelse 2 add
|
|
|
|
over over savescreen 5 1 roll
|
|
|
|
drawborder
|
|
|
|
|
|
|
|
] put
|
|
|
|
|
|
|
|
} for
|
|
|
|
|
|
|
|
0 1 xmenu .xm_list get length 1 sub { xmenu.viewentry } for
|
|
|
|
|
|
|
|
/xmenu.oldentry xmenu .xm_current get def
|
|
|
|
|
|
|
|
dup .x xmenu.x put
|
|
|
|
.y xmenu.y put
|
|
|
|
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Close menu.
|
|
|
|
%
|
|
|
|
% ( ) ==> ( )
|
|
|
|
%
|
|
|
|
/xmenu.done {
|
|
|
|
/xmenu.tmpbuf xmenu.tmpbuf free .undef def
|
|
|
|
/xmenu.saved.normal xmenu.saved.normal free .undef def
|
|
|
|
/xmenu.saved.selected xmenu.saved.selected free .undef def
|
|
|
|
/xmenu.saved.areas .undef def
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Draw xmenu.
|
|
|
|
%
|
|
|
|
% ( window ) ==> ( )
|
|
|
|
%
|
|
|
|
/xmenu.show {
|
|
|
|
window.push
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Draw single entry.
|
|
|
|
%
|
|
|
|
% ( entry ) ==> ( )
|
|
|
|
%
|
|
|
|
/xmenu.viewentry {
|
|
|
|
xmenu.font setfont
|
|
|
|
|
|
|
|
dup xmenu.maxlines mod xmenu.lheight mul xmenu.y add /xmenu.pos.y exch def
|
|
|
|
|
|
|
|
dup xmenu.maxlines div /xmenu.column over def
|
|
|
|
xmenu.width 2 add mul xmenu.x add /xmenu.pos.x exch def
|
|
|
|
|
|
|
|
xmenu.pos.x xmenu.pos.y moveto
|
|
|
|
|
|
|
|
dup xmenu .xm_current get eq { xmenu.saved.selected } { xmenu.saved.normal } ifelse
|
|
|
|
|
|
|
|
dup {
|
|
|
|
transp { pop } { restorescreen } ifelse
|
|
|
|
} {
|
|
|
|
pop
|
|
|
|
|
|
|
|
dup xmenu .xm_current get eq { xmenu.selected.bg } { xmenu.normal.bg } ifelse
|
|
|
|
setcolor xmenu.width xmenu.lheight fillrect
|
|
|
|
|
|
|
|
dup xmenu .xm_current get eq {
|
|
|
|
xmenu.pos.x xmenu.pos.y moveto
|
|
|
|
xmenu.dark xmenu.light xmenu.width xmenu.lheight drawborder
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup xmenu .xm_current get eq { /xmenu.saved.selected } { /xmenu.saved.normal } ifelse
|
|
|
|
xmenu.pos.x xmenu.pos.y moveto
|
|
|
|
xmenu.width xmenu.lheight
|
|
|
|
savescreen
|
|
|
|
def
|
|
|
|
} ifelse
|
|
|
|
|
|
|
|
|
|
|
|
transp {
|
|
|
|
% copy entry to avoid reading the screen again
|
|
|
|
dup xmenu .xm_current get eq { xmenu.saved.selected } { xmenu.saved.normal } ifelse
|
|
|
|
xmenu.tmpbuf .undef eq {
|
|
|
|
dup length malloc /xmenu.tmpbuf exch def
|
|
|
|
} if
|
|
|
|
xmenu.tmpbuf exch dup length memcpy
|
|
|
|
|
|
|
|
0 xmenu.pos.y xmenu.y sub moveto 1 1 rmoveto
|
|
|
|
xmenu.saved transp xmenu.tmpbuf blend
|
|
|
|
|
|
|
|
xmenu.pos.x xmenu.pos.y moveto xmenu.tmpbuf restorescreen
|
|
|
|
} if
|
|
|
|
|
|
|
|
dup xmenu .xm_current get eq { xmenu.selected.fg } { xmenu.normal.fg } ifelse setcolor
|
|
|
|
xmenu.pos.x xmenu.hspace add xmenu.pos.y xmenu.vspace add moveto
|
|
|
|
xmenu .xm_list get over get exec show
|
|
|
|
|
|
|
|
pop
|
|
|
|
|
|
|
|
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Select menu entry.
|
|
|
|
%
|
|
|
|
% ( new_entry ) ==> ( )
|
|
|
|
%
|
|
|
|
/xmenu.select {
|
|
|
|
dup 0 lt { xmenu .xm_list get length add } if
|
|
|
|
dup xmenu .xm_list get length ge { xmenu .xm_list get length sub } if
|
|
|
|
|
|
|
|
xmenu .xm_current get over xmenu .xm_current rot put
|
|
|
|
xmenu.viewentry
|
|
|
|
xmenu.viewentry
|
|
|
|
window.current .xmenu.select get dup .undef ne { exec } { pop } ifelse
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Panel/xmenu helper function.
|
|
|
|
%
|
|
|
|
% ( ) => ( )
|
|
|
|
%
|
|
|
|
/pmenu.panel.update {
|
|
|
|
panel.text.moveto
|
|
|
|
|
|
|
|
xmenu .xm_panel_x currentpoint pop xmenu.hspace sub put
|
|
|
|
% try to ensure that the menu doesn't overflow the screen
|
|
|
|
xmenu .xm_x
|
|
|
|
xmenu .xm_panel_x get
|
|
|
|
screen.size pop xmenu.width 2 add xmenu.columns mul 10 add sub
|
|
|
|
min put
|
|
|
|
|
|
|
|
pmenu.update
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Panel/xmenu helper function.
|
|
|
|
%
|
|
|
|
% ( ) => ( width )
|
|
|
|
%
|
|
|
|
/pmenu.width {
|
|
|
|
% Use this instead of the line below and remove the actRedrawPanel
|
|
|
|
% things if you want fixed size panel entries.
|
|
|
|
|
|
|
|
% xmenu .xm_panel_width get xmenu.hspace 2 mul sub
|
|
|
|
|
|
|
|
xmenu .xm_title get dup .undef eq {
|
|
|
|
pop xmenu .xm_list get xmenu .xm_current get get
|
|
|
|
} if
|
|
|
|
exec strsize pop
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Panel/xmenu helper function.
|
|
|
|
%
|
|
|
|
% ( ) => ( )
|
|
|
|
%
|
|
|
|
/pmenu.update {
|
|
|
|
xmenu .xm_panel_x get xmenu.hspace add panel.text.y moveto
|
|
|
|
|
|
|
|
% currently not needed - we're redrawing the whole panel anyway
|
|
|
|
% xmenu .xm_panel_width get xmenu.hspace sub xmenu .xm_panel_height get
|
|
|
|
% panel.bg setcolor fillrect
|
|
|
|
|
|
|
|
panel.normal setcolor
|
|
|
|
panel.font setfont
|
|
|
|
xmenu .xm_panel_x get xmenu.hspace add
|
|
|
|
panel.text.y
|
|
|
|
moveto
|
|
|
|
xmenu .xm_title get dup .undef eq {
|
|
|
|
pop xmenu .xm_list get xmenu .xm_current get get
|
|
|
|
} if
|
|
|
|
exec show
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
% Panel/xmenu helper function.
|
|
|
|
%
|
|
|
|
% ( ) => ( )
|
|
|
|
%
|
|
|
|
/pmenu.init {
|
|
|
|
xmenu.sizes
|
|
|
|
|
|
|
|
xmenu .xm_y panel.text.y 1 sub xmenu.height sub put
|
|
|
|
xmenu .xm_panel_width xmenu.width put
|
|
|
|
xmenu .xm_panel_height fontheight put
|
|
|
|
} def
|
|
|
|
|
|
|
|
|