%!
%%Title:PStab 2.0
%%Creator:Baz
%%CreationDate:14 March 1994
%PStab 2.0 (first full release)
%
%
% Copyright (C) 1994 Brian Ewins. All rights reserved.
%
%PStab is distributed in the hope that it will be useful, but
%WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
%to anyone for the consequences of using it or for whether it serves any
%particular purpose or works at all, unless he says so in writing. Refer
%to the PStab General Public License for full details.
%
%Everyone is granted permission to copy, modify and redistribute
%PStab, but only under the conditions described in the PStab
%General Public License. A copy of this license is supposed to have been
%given to you along with PStab so you can know your rights and
%responsibilities. It should be in a file named COPYING. Among other
%things, the copyright notice and this notice must be preserved on all
%copies.
%
%-------------------------------------------------------------------------------
%Revision History: started Friday, 2 March 1994.
%-------------------------------------------------------------------------------
% 0.1 :Friday: crap program for lining numbers up in columns
% 0.2 :Sunday: complete rewrite. chord table program only
% 0.3 :Tuesday: reorganized into core & styles.
% Centred,Columns,ChordTable supplied.
% ifcase added to core.
% 0.4 :Wednesday: rethink on text styles.easier method of entry.
% Verses replaced Columns
% ChordPro style provides compatability.
% ChordTable renamed Chords, now has
% huge table of chords you can use.
% Handles VM restore properly !!!
% added revision history.
% 0.5 :Thursday: Back to doing tablature (again)
% Chords now size-independent
% Verbatim made default style.
% Verbatim-equivalent defs removed.(shortens prog}
% Tablature works! hooray!!!
% Many marks allowed in music.
% 0.6 :Friday: added default case to ifcase
% finished Parser. program is still buggy.
% 0.7 :: Due to a hitch, there was no alpha 7.
% 0.8 :Sunday: Commented.
% fbox made internal size.
% Manual doubles as torture test.
% manual nearly complete, program debugged
% completely except for Tablature.
% 1.0 :Monday: It all works!!! I'll type last man page & post.
% 1.1 :Tuesday: the '2nd last page' bug fixed.
% fingermark bug fixed. top , bottom, rows set
% once only in Tablature.
% Parsers now separate part of the program.
% Font sizes reduced:I was viewing on A3!!!
% Errors in manual fixed.
% Only things left to do now are ASCII tab reader,
% and more complete manual.
% 1.2: :Tuesday: ASCII parser started. buggy. remembered to fix bug
% for looooong bars.incidentally, redundant defs were
% placed back in at 1.0. ASCII parser works. WOW!
% manual to do. ASCII parser now does an excellent
% job of it. only two pathogenic cases I can think of.
% 2.0: :Wednesday: ASCII parser fixed so it split up 'bars'. this
% is truly monumental: ASCII'd tab now looks
% _nice_ (!)... almost worth using...
% manual finished.
%-------------------------------------------------------------------------------
%-CORE--------------------------------------------------------------------------
%Contains idioms, and other stuff essential for
%the program to break lines, pages, etc.
%-------------------------------------------------------------------------------
%-------Idioms
%-------------------------------------------------------------------------------
/debug {dup 20 string cvs show ( ) show} def
/edef {exch def} def
/max { 2 copy gt {pop} {exch pop} ifelse } def
/min { 2 copy lt {pop} {exch pop} ifelse } def
/inch {72 mul} def
/plus
{ % x y plus is equivalent to x+=y; in C
1 index cvx exec add def
} def
/minus
{ % x y minus is equivalent to x-=y; in C
1 index cvx exec exch sub def
} def
/ifcase
{ % syntax: pattern { {match1 {proc1}} {match2 {proc2}} ...} ifcase
% if match is /default, it will be executed immediately
% pattern is on the stack at the start of any proc.
% proc should really remove it.
exch /pattern edef
{
aload pop exch dup
/default eq {pop pattern exch exec exit} if
pattern eq {pattern exch exec exit} {pop} ifelse
} forall
} def
/ToString {3 string cvs} def
/ChooseFont
{ % selects font and sets fbox
/fbox edef
findfont fbox scalefont setfont
} def
%-------------------------------------------------------------------------------
%-------Sizes: internal unit is font size.
%------------- also here is code to use real page size.
%-------------------------------------------------------------------------------
/ptof {fbox div exch fbox div exch} def
/ftop {fbox mul exch fbox mul exch} def
/moverel {ftop rmoveto} def
/linerel {ftop rlineto} def
/StringWidth {stringwidth pop fbox div} def
/GetPageMargins
{
clippath pathbbox %get page size
/TopMargin edef
/RightMargin edef %put it where I can use it.
/BottomMargin edef
/LeftMargin edef
newpath %stops me strokeing the clipping path
} def
/PageWidth {RightMargin LeftMargin ptof sub} def
/smaller
{
exch
{ {/LeftMargin {exch plus}}
{/RightMargin {exch minus}}
{/TopMargin {exch minus}}
{/BottomMargin {exch plus}}
} ifcase
} def
%-------------------------------------------------------------------------------
%-------Line,Page breaking code.
%-------------------------------------------------------------------------------
/Atom
{
GetAtom
currentpoint pop
hbox fbox mul add
RightMargin gt
{NewLine} if
currentpoint
vbox fbox mul sub
BottomMargin lt
{NewPage} if pop
} def
/NewDoc
{ % begin a document
% assumes margins have been set
LeftMargin TopMargin moveto
Verbatim %default style
/Home save def
/StyleDict 128 dict def
StyleDict begin
} def
/NewStyle
{ % clean up and start again
Flush end
currentpoint
Home restore
/Home save def
moveto
/StyleDict 128 dict def
StyleDict begin
} def
/EndDoc
{
Flush end
showpage %show what's left.
Home
restore
} def
/PageBreak
{ % when the user wants to insert a page break.
EndDoc NewDoc
} def
%-------------------------------------------------------------------------------
%-------Chord data: a table taken from ChordPro, and put in
%------------------ the simpler format used here. Some mistakes corrected.
%------------------ Chordpro is (c) Mario Dorion & Martin Leclerc
%-------------------------------------------------------------------------------
/Chordata % this is spinal tap!
[
[(Ab)[ 4 6 6 5 4 4 ]] [(Abm)[ 4 6 6 4 4 4 ]]
[(Ab7)[ -1 -1 1 1 1 2 ]] [(Abm7)[ -1 -1 4 4 4 4 ]]
[(Absus)[ -1 -1 1 1 2 4 ]] [(Ab+)[ -1 -1 2 1 1 0 ]]
[(Abdim)[ -1 -1 0 1 0 1 ]] [(Abmaj7)[ -1 -1 1 1 1 3 ]]
[(A)[ -1 0 2 2 2 0 ]] [(Am)[ -1 0 2 2 1 0 ]]
[(A7)[ -1 0 2 0 2 0 ]] [(Am7)[ -1 0 2 2 1 3 ]]
[(Asus)[ -1 -1 2 2 3 0 ]] [(A+)[ -1 0 3 2 2 1 ]]
[(Adim)[ -1 -1 1 2 1 2 ]] [(Amaj7)[ -1 0 2 1 2 0 ]]
[(A#)[ -1 1 3 3 3 1 ]] [(A#m)[ -1 1 3 3 2 1 ]]
[(A#7)[ -1 -1 3 3 3 4 ]] [(A#m7)[ -1 1 3 1 2 1 ]]
[(A#sus)[ -1 -1 3 3 4 1 ]] [(A#+)[ -1 -1 0 3 3 2 ]]
[(A#dim)[ -1 -1 2 3 2 3 ]] [(A#maj7)[ -1 1 3 2 3 -1 ]]
[(Bb)[ -1 1 3 3 3 1 ]] [(Bbm)[ -1 1 3 3 2 1 ]]
[(Bb7)[ -1 -1 3 3 3 4 ]] [(Bbm7)[ -1 1 3 1 2 1 ]]
[(Bbsus)[ -1 -1 3 3 4 1 ]] [(Bb+)[ -1 -1 0 3 3 2 ]]
[(Bbdim)[ -1 -1 2 3 2 3 ]] [(Bbmaj7)[ -1 1 3 2 3 -1 ]]
[(B)[ -1 2 4 4 4 2 ]] [(Bm)[ -1 2 4 4 3 2 ]]
[(B7)[ 0 2 1 2 0 2 ]] [(Bm7)[ -1 2 4 2 3 2 ]]
[(Bsus)[ -1 -1 4 4 5 2 ]] [(B+)[ -1 -1 1 0 0 4 ]]
[(Bdim)[ -1 -1 0 1 0 1 ]] [(Bmaj7)[ -1 2 4 3 4 -1 ]]
[(C)[ 0 3 2 0 1 0 ]] [(Cm)[ -1 1 5 5 4 3 ]]
[(C7)[ 0 3 2 3 1 0 ]] [(Cm7)[ -1 1 5 3 4 3 ]]
[(Csus)[ -1 -1 3 0 1 3 ]] [(C+)[ -1 -1 2 1 1 0 ]]
[(Cdim)[ -1 -1 1 2 1 2 ]] [(Cmaj7)[ -1 3 2 0 0 0 ]]
[(C#)[ -1 -1 3 1 2 1 ]] [(C#m)[ -1 -1 2 1 2 0 ]]
[(C#7)[ -1 -1 3 4 2 4 ]] [(C#m7)[ -1 -1 2 4 2 4 ]]
[(C#sus)[ -1 -1 6 6 7 4 ]] [(C#+)[ -1 -1 3 2 2 1 ]]
[(C#dim)[ -1 -1 2 3 2 3 ]] [(C#maj7)[ -1 4 3 1 1 1 ]]
[(Db)[ -1 -1 3 1 2 1 ]] [(Dbm)[ -1 -1 2 1 2 0 ]]
[(Db7)[ -1 -1 3 4 2 4 ]] [(Dbm7)[ -1 -1 2 4 2 4 ]]
[(Dbsus)[ -1 -1 6 6 7 4 ]] [(Db+)[ -1 -1 3 2 2 1 ]]
[(Dbdim)[ -1 -1 2 3 2 3 ]] [(Dbmaj7)[ -1 4 3 1 1 1 ]]
[(D)[ -1 -1 0 2 3 2 ]] [(Dm)[ -1 -1 0 2 3 1 ]]
[(D7)[ -1 -1 0 2 1 2 ]] [(Dm7)[ -1 -1 0 2 1 1 ]]
[(Dsus)[ -1 -1 0 2 3 3 ]] [(D+)[ -1 -1 0 3 3 2 ]]
[(Ddim)[ -1 -1 0 1 0 1 ]] [(Dmaj7)[ -1 -1 0 1 1 1 ]]
[(D#)[ -1 -1 5 3 4 3 ]] [(D#m)[ -1 -1 4 3 4 2 ]]
[(D#7)[ -1 -1 1 3 2 3 ]] [(D#m7)[ -1 -1 1 3 2 2 ]]
[(D#sus)[ -1 -1 1 3 4 4 ]] [(D#+)[ -1 -1 1 0 0 4 ]]
[(D#dim)[ -1 -1 1 2 1 2 ]] [(D#maj7)[ -1 -1 1 3 3 3 ]]
[(Eb)[ -1 -1 6 4 5 4 ]] [(Ebm)[ -1 -1 4 3 4 2 ]]
[(Eb7)[ -1 -1 1 3 2 3 ]] [(Ebm7)[ -1 -1 1 3 2 2 ]]
[(Ebsus)[ -1 -1 1 3 4 4 ]] [(Eb+)[ -1 -1 1 0 0 4 ]]
[(Ebdim)[ -1 -1 1 2 1 2 ]] [(Ebmaj7)[ -1 -1 1 3 3 3 ]]
[(E)[ 0 2 2 1 0 0 ]] [(Em)[ 0 2 2 0 0 0 ]]
[(E7)[ 0 2 2 1 3 0 ]] [(Em7)[ 0 2 2 0 3 0 ]]
[(Esus)[ 0 2 2 2 0 0 ]] [(E+)[ -1 -1 2 1 1 0 ]]
[(Edim)[ -1 -1 2 3 2 3 ]] [(Emaj7)[ 0 2 1 1 0 -1 ]]
[(F)[ 1 3 3 2 1 1 ]] [(Fm)[ 1 3 3 1 1 1 ]]
[(F7)[ 1 3 1 2 1 1 ]] [(Fm7)[ 1 3 1 1 1 1 ]]
[(Fsus)[ -1 -1 3 3 1 1 ]] [(F+)[ -1 -1 3 2 2 1 ]]
[(Fdim)[ -1 -1 0 1 0 1 ]] [(Fmaj7)[ -1 3 3 2 1 0 ]]
[(F#)[ 2 4 4 3 2 2 ]] [(F#m)[ 2 4 4 2 2 2 ]]
[(F#7)[ -1 -1 4 3 2 0 ]] [(F#m7)[ -1 -1 2 2 2 2 ]]
[(F#sus)[ -1 -1 4 4 2 2 ]] [(F#+)[ -1 -1 4 3 3 2 ]]
[(F#dim)[ -1 -1 1 2 1 2 ]] [(F#maj7)[ -1 -1 4 3 2 1 ]]
[(Gb)[ 2 4 4 3 2 2 ]] [(Gbm)[ 2 4 4 2 2 2 ]]
[(Gb7)[ -1 -1 4 3 2 0 ]] [(Gbm7)[ -1 -1 2 2 2 2 ]]
[(Gbsus)[ -1 -1 4 4 2 2 ]] [(Gb+)[ -1 -1 4 3 3 2 ]]
[(Gbdim)[ -1 -1 1 2 1 2 ]] [(Gbmaj7)[ -1 -1 4 3 2 1 ]]
[(G)[ 3 2 0 0 0 3 ]] [(Gm)[ 3 5 5 3 3 3]]
[(G7)[ 3 2 0 0 0 1 ]] [(Gm7)[ 3 5 3 3 3 3 ]]
[(Gsus)[ -1 -1 0 0 1 3 ]] [(G+)[ -1 -1 1 0 0 4 ]]
[(Gdim)[ -1 -1 2 3 2 3 ]] [(Gmaj7)[ -1 -1 5 4 3 2 ]]
[(G#)[ 4 6 6 5 4 4 ]] [(G#m)[ 4 6 6 4 4 4 ]]
[(G#7)[ -1 -1 1 1 1 2 ]] [(G#m7)[ -1 -1 4 4 4 4]]
[(G#sus)[ -1 -1 1 1 2 4 ]] [(G#+)[ -1 -1 2 1 1 0 ]]
[(G#dim)[ -1 -1 0 1 0 1 ]] [(G#maj7)[ -1 -1 1 1 1 3 ]]
] def
%-------------------------------------------------------------------------------
%-PARSERS-----------------------------------------------------------------------
% This new section is to allow different methods of entry in different styles.
% There is a plan to allow the program to parse ASCII tab, and also for
% a possible interface with TabEdit, or other programs.
%-------------------------------------------------------------------------------
/StdParser
{ %the usual parser, for tablature.
/Parse
{
/lastwasname false def
/barcols 0 def
{ % open ({) loop
({) search exch
{ % open (,) loop
(,) search exch
{ %loop again
(\n) search exch
{ %loop again
( ) search exch
dup length 0 ne
{TabHandler}
{pop} ifelse
{pop}{exit} ifelse
} loop
{pop}{exit} ifelse
} loop
{pop WriteColumn}{exit} ifelse
} loop
{pop}{exit} ifelse
(}) search % assumed true
pop exch pop
(:) search
{exch pop TextHandler}
{MarkHandler} ifelse
} loop
WriteColumn
0 1 barcols 1 sub
{
BarArray exch get
} for % get everything back
barcols array astore
Atom % linebreaks do printing.
/cols barcols plus %more columns...
/bars 1 plus %and another bar.
} def
/WriteColumn
{ %push column to stack; make a fresh column
lastwasname
{
DefaultColumn DefaultString get
dup length array copy
CurrentColumn DefaultString
3 -1 roll put
} if
/lastwasname false def
BarArray barcols [0 CurrentColumn] put
/barcols barcols 1 add def
/CurrentColumn BlankColumn rows array
copy def %Do this every time.
} def
/IsTextRow
{ % put text into column.
CurrentColumn exch 3 -1 roll put
} def
/IsRow
{ %if last was row too, fill it in.
lastwasname
{
DefaultColumn DefaultString get
dup length array copy
CurrentColumn DefaultString
3 -1 roll put
} if
/DefaultString edef
/lastwasname true def
} def
/IsFret
{
/lastwasname false def
1 array dup 0 3 index put
CurrentColumn DefaultString
2 index put
DefaultColumn DefaultString
2 index put
pop pop
} def
/MarkHandler
{% what to do with special marks.
CurrentColumn DefaultString get
0 get % for sensible use, we must set this
dup length 0 eq % if it's not already set.
{ pop DefaultColumn DefaultString get
0 get /lastwasname false def} if
exch
{
{ (tie) {pop 1 2} } { (up) {pop 2 2} }
{ (down) {pop 3 2} } { (h) {pop 4 2} }
{ (p) {pop 5 2} } { (harm){pop 6 2} }
{ (vib) {pop 8 2} } { (0) {pop 7 (0) 3} }
{ (1) {pop 7 (1) 3} } { (2) {pop 7 (2) 3} }
{ (3) {pop 7 (3) 3} } { (4) {pop 7 (4) 3} }
} ifcase
array astore CurrentColumn DefaultString 3 -1 roll put
} def
} def
%-------------------------------------------------------------------------------
%-------ASCIIparser: puts any marks that aren't - into the tab. ignores first
%------------------- and last thing to avoid spurious barlines.
%-------------------------------------------------------------------------------
/ASCIIparser
{
/WholeBar rows array def
/WholeLine rows array def
BlankColumn WholeLine copy /WholeLine def
BlankColumn WholeBar copy /WholeBar def
/Parse
{ %parse ascii tab.
0 1 rows 2 sub
{
exch
(\n) search pop %must be true
WholeLine exch 5 -1 roll exch put
pop
} for
%tab now split into rows. now generate columns.
WholeLine rows 1 sub 3 -1 roll put
{
/barcols 0 def /alldone true def
/row 0 def
{
WholeLine row get (|) search
{ /alldone false def
WholeBar row 3 -1 roll put
pop WholeLine row 3 -1 roll put
}
{ WholeBar row 3 -1 roll put
WholeLine row () put
} ifelse
/row 1 plus
row rows eq {exit} if
} loop
WholeBar
{
(-) search
{ 3 1 roll pop pop
dup length 1 sub 0 1 3 -1 roll
{1 index exch (-) 0 get put} for pop
}{pop} ifelse
} forall
{
/finished true def
/makecolumn false def
/row 0 def
WholeBar
{
(-) search
{
/finished false def
pop 0 ( ) 0 get put
(-) search dup
{4 1 roll exch pop exch pop}
{exch} ifelse
dup dup 4 1 roll length dup 0 ne
{3 -1 roll makecolumn or /makecolumn edef}
{3 -1 roll pop} ifelse
% stick it in the column.
string copy 1 array dup 0 4 -1
roll put
CurrentColumn row
3 -1 roll put
%left with a copy of the string
%fill it with minus signs.
dup length 1 sub 0 1 3 -1 roll
{1 index exch (-) 0 get put} for pop
}
{
pop
} ifelse
/row 1 plus
} forall
makecolumn
{ % write a column !
/row 0 def
%needs to blank out later columns.
BarArray barcols [0 CurrentColumn] put
/barcols barcols 1 add def
/CurrentColumn BlankColumn rows array
copy def %Do this every time.
} if
finished {exit} if
} loop
barcols 0 ne
{
0 1 barcols 1 sub
{
BarArray exch get
} for % get everything back
barcols array astore
Atom % linebreaks do printing.
/cols barcols plus %more columns...
/bars 1 plus %and another bar.
} if
alldone {exit} if
} loop
} def
} def
%-------------------------------------------------------------------------------
%-STYLES------------------------------------------------------------------------
% In this section I define some styles in which
% the program will print. You can add more, but
% don't change these.
%-------------------------------------------------------------------------------
%-------Tablature: this is an engine for printing tablature
%----------------- in a very general way. It needs some externally
%----------------- supplied information to work.
%-------------------------------------------------------------------------------
/Tablature
{
/BlankColumn edef
/rows BlankColumn length def
/DefaultColumn BlankColumn rows array copy def %One-shot initalise
/DefaultString 1 def% first string.
/CurrentColumn BlankColumn rows array copy def %Do this every time.
/BarArray 128 array def %very generous too!
% Initialise variables.
/hbox 0 def /cols 0 def /bars 0 def
BlankColumn
0 1 rows 1 sub
{ dup 2 index exch get type cvlit
/arraytype eq
{neg 0.25 add /top edef exit}
{pop} ifelse
} for
rows 1 sub -1 0
{ dup 2 index exch get type cvlit
/arraytype eq
{neg 0.25 add /bottom edef exit}
{pop} ifelse
} for
/bottom top minus
pop
/vbox {rows 1 add} def
/, {Parse} def
/NewPage {showpage LeftMargin TopMargin moveto} def
/NewLine
{
bars 0 eq
{ %very long bar. attempts to recover,
%but an extra bar line gets drawn.
/bars 1 def /cols barcols def
/Justify PageWidth hbox sub cols div def
Display
/bars -1 def /cols barcols neg def /hbox 0 def
}
{ %/Justify 0 def
/hbox barbox minus
/Justify PageWidth hbox sub cols div def
bars 1 add 1 roll % stick this one on the bottom
Display
/bars 0 def /cols 0 def /hbox barbox def
} ifelse
LeftMargin currentpoint vbox fbox mul sub
exch pop moveto %usual newline
} def
/Flush
{
Parse
/Justify 0 def % Don't justify
Display %don't bother cleaning up-we're outta here
LeftMargin currentpoint vbox fbox mul sub
exch pop moveto %usual newline
} def
/Display
{ %Draw bar line, tab all columns, draw bar line..
gsave
0 top moverel
0 bottom linerel
stroke grestore
bars 1 sub -1 0
{ index % ...not reverse order
[2 BlankColumn] TabColumn
{ %tab a single column.
TabColumn
} forall gsave
0 top moverel
0 bottom linerel
stroke grestore
} for
bars {pop} repeat
} def
/TabColumn
{ /finger (x) def
dup 0 get /cbox edef 1 get gsave
{ %forall loop
gsave dup type cvlit
/arraytype eq
{
/tie 0 def dup length
{{1 {pop}}
{2 {pop dup 1 get /tie edef}}
{3 {pop dup dup 1 get /tie
edef 2 get /finger edef}}
} ifcase
0 get dup StringWidth
cbox exch sub Justify add /rbox edef
show gsave 0 0.25 moverel
rbox 0 linerel stroke grestore
SpecialMarks
}{show} ifelse
grestore 0 -1 moverel
} forall
grestore cbox Justify add 0 moverel
} def
/GetAtom
{ % needs to set: top,bottom,barcols,barbox,vbox
dup %leave a copy on the stack.
dup length 1 add /barcols edef
/barbox 0 def %1 down!
/previous [0] def
/oldsbox 0 def /oldcbox 0 def
{ %forall
/cbox 0 def
/sbox 0 def
0 1 rows 1 sub
{ % for loop...
1 index 1 get% copy of array
exch get % get this row
dup type cvlit
/arraytype eq
{
0 get %get the string
StringWidth cbox max /cbox edef
}
{
StringWidth sbox max /sbox edef
} ifelse
} for
sbox 0 gt
{%there is a string
oldsbox oldcbox max 2 add
dup barbox add /barbox edef
previous 0 3 -1 roll put
/oldsbox sbox def
/oldcbox cbox def
}
{%there is no string!
previous 0 oldcbox 2 add put
oldcbox 2 add barbox add /barbox edef
/oldsbox oldsbox oldcbox sub 2 sub def
/oldcbox cbox def
} ifelse
/previous edef
} forall
previous 0 oldsbox oldcbox max 2 add put
oldsbox oldcbox max 2 add barbox add /barbox edef
/hbox barbox plus
} def
/SpecialMarks
{ % produce all the extra bits of notation.
gsave tie
{ {1{pop % code to do ties
0.25 0 moverel
rbox 0.5 sub 3 div -0.25 ftop
rbox 0.5 sub 3 div 2 mul -0.25 ftop
rbox 0.5 sub 0 ftop rcurveto stroke}}
{2{pop % code to do slides up
0.25 0 moverel
rbox 0.5 sub 0.5 linerel stroke}}
{3{pop % code to do slides down
0.25 0.5 moverel
rbox 0.5 sub -0.5 linerel stroke}}
{4{pop % code to do hammer on
0.5 0.5 moverel 0.25 -0.5 linerel
0.25 0.5 linerel stroke}}
{5{pop % code to do pull off
0.5 0 moverel
0.25 0.5 linerel
0.25 -0.5 linerel stroke}}
{6{pop % code to do harmonic
0.5 0.25 moverel 0.25 0.25 linerel
0.25 -0.25 linerel -0.25 -0.25 linerel
closepath stroke}}
{7{pop % code to do finger mark (specify fingering)
gsave 1 0.25 moverel
currentpoint newpath
fbox 2 div 0 360 arc
gsave 1 setgray fill grestore
stroke grestore
13 16 div 0 moverel
finger ToString show}}
{8{pop % code to do vibrato
0.25 0.5 moverel
3 {0.125 -0.125 linerel 0.125 0.125 linerel}
repeat stroke}}
} ifcase grestore
} def
} def
%-------------------------------------------------------------------------------
%-------Verbatim: this is the default style. It's intended for reproducing
%---------------- blocks of text directly, such as an ASCII tab file.
%-------------------------------------------------------------------------------
/Verbatim
{
/, {Parse} def
/vbox 1 def
/Courier 8 ChooseFont
/Parse
{ % breaks into words.
{
(\n) search exch
{
( ) search exch
Atom Display
{Atom Display}{exit} ifelse
} loop
{pop} {exit} ifelse
NewLine
} loop
NewLine
} def
/GetAtom {dup StringWidth /hbox edef} def
/Display {gsave 0 -1 moverel show grestore hbox 0 moverel} def
/NewLine
{ LeftMargin currentpoint vbox fbox mul sub
exch pop moveto
} def
/NewPage {showpage LeftMargin TopMargin moveto} def
/Flush {Parse NewLine} def
} def
%-------------------------------------------------------------------------------
%-------Centred: This style produces centred text. It's intended for
%--------------- making titles.
%-------------------------------------------------------------------------------
/Centred
{
/, {Parse} def
/vbox 1 def
/Helvetica 12 ChooseFont
/Parse
{ % breaks into words.
{
(\n) search exch
{
dup
( ) search
{
3 1 roll
0 (\267) putinterval
pop
Atom pop dup
(\267) search pop
exch pop
( ) search
{
pop pop pop
exch pop
}
{
pop pop
} ifelse
}
{
pop Atom exit
} ifelse
} loop
NewLine pop
{pop} {exit} ifelse
} loop
} def
/GetAtom {dup StringWidth /hbox edef} def
/Display
{
dup dup
{
(\267) search
{pop 0 ( ) putinterval}
{pop exit} ifelse
} loop
gsave PageWidth hbox sub 2 div -1 moverel
show grestore
}def
/NewLine
{
Display
LeftMargin currentpoint vbox fbox mul sub
exch pop moveto
} def
/NewPage {showpage LeftMargin TopMargin moveto} def
/Flush {Parse} def
} def
%-------------------------------------------------------------------------------
%-------Verses: Each block of text is assumed to be a verse, and this
%-------------- style tries to place as many verses horizontally as it can.
%-------------------------------------------------------------------------------
/Verses
{
/rows 0 def
/vbox 0 def
/Times-Roman 8 ChooseFont
/, {Parse} def
/Parse
{ /hbox 0 def
{
(\n) search exch Atom exch
{exch pop exch} {exit} ifelse
} loop
Display
} def
/GetAtom
{ dup StringWidth
hbox max /hbox edef
/rows 1 plus
rows vbox max /vbox edef
} def
/NewLine
{
LeftMargin currentpoint vbox 1 add fbox mul sub
exch pop moveto %usual def ...
/vbox rows def % and reset vbox
} def
/NewPage
{
showpage
LeftMargin TopMargin moveto %usual def..
/vbox rows def % and reset vbox
} def
/Display
{ % show whole verse
rows -1 1
{
gsave
neg 0 exch moverel
show grestore %start popping strings
} for
/rows 0 def % reset rows
hbox 1 add 0 moverel
/hbox 0 def % reset hbox too.
} def
/Flush {Parse NewLine} def
} def
%-------------------------------------------------------------------------------
%-------Chords: This style prints chord diagrams. It 'knows' over
%-------------- 130 chords, but you can use your own.
%-------------------------------------------------------------------------------
/Chords
{
/, {Parse} def
/vbox 9 def
/Times-Roman 8 ChooseFont
/Parse {Atom Display} def
/Flush {Parse NewLine} def
/CentreShow
{ % centre a string horizontally and vertically
gsave
dup StringWidth
2 div neg -0.3 moverel% horizontal
show grestore %back to centre
} def
/GetAtom
{ % first pass, find range, also diagram width.
dup type cvlit
/stringtype eq
{ %find it in Chordata
Chordata
{
dup 0 get 2 index eq
{ %found it
1 get
exit % stop search
}
{pop} ifelse
} forall
dup type cvlit /stringtype eq
{ %there was no match
[-1 -1 -1 -1 -1 -1] % rescue program
} if
} if % no action otherwise
dup dup length /cols edef % width of diagram.
/top -2 def
/bottom 99 def
{
dup type cvlit
/arraytype eq
{ 0 get } if
%pop % don't want string this time round.
dup
top max /top edef %highest fret
dup
0 gt %ignore 0 fret, unplayed strings
{ bottom min /bottom edef }
{ pop } ifelse
} forall
top 5 le
{ /top 5 def /bottom 0 def }
{ /top bottom 5 add def
bottom 1 sub /bottom edef
} ifelse
/hbox cols 2 add def
} def
/Display
{ %style object.
gsave
0.5 -1 moverel
gsave
-1 -1 -6
{
1 exch moverel
cols 1 sub 0 linerel stroke
grestore gsave
} for
bottom 0 eq
{ % gotta draw extra line.
1 -0.875 moverel cols 1 sub 0 linerel stroke % ok that's it.
} if %label first fret elsewhere...
grestore gsave 1 -0.5 moverel
{
dup type cvlit
/arraytype eq
{ aload pop ToString }
{ () } ifelse
exch dup gsave % draw string
0 -0.5 moverel 0 -5 linerel stroke
grestore gsave 0 le
{ % something is printed here
-1 eq
{ (x) CentreShow }
{ (o) CentreShow }
ifelse pop % if we did that,that's this string done.
}
{ % figure out where to put this string
bottom sub neg 0 exch moverel
gsave currentpoint newpath
0.5 fbox mul 0 360 arc
gsave 1 setgray fill grestore
stroke grestore CentreShow
} ifelse
grestore
1 0 moverel
} forall
bottom 0 ne
{ % label first fret.
0 -0.5 moverel
bottom ToString CentreShow
} if
grestore
cols 1 add 2 div -7 moverel
CentreShow %write name centred.
grestore
cols 2 add 0 moverel
} def
/NewLine
{ LeftMargin currentpoint vbox fbox mul sub
exch pop moveto
} def
/NewPage {showpage LeftMargin TopMargin moveto} def
} def
%-------------------------------------------------------------------------------
%-------ChordPro: This style prints chords above lyrics, a la ChordPro
%-------------------------------------------------------------------------------
/ChordPro
{
/vbox 3 def
/Times-Roman 8 ChooseFont
/, {Parse} def
/Flush {Parse NewLine} def
/Parse
{ %split into atoms
{
(\n) search exch
{
([) search
{
dup length 0 ne
{ Atom Display }
{ pop } ifelse
pop
}
{ Atom Display exit } ifelse
} loop
{pop NewLine} {exit} ifelse
} loop
} def
/GetAtom
{ % get width attributes of atom
/hbox 0 def
dup
(]) search % contains a chord ?
{ StringWidth 1 add /hbox edef pop
StringWidth hbox max /hbox edef }
{ StringWidth /hbox edef } ifelse
}def
/Display
{
(]) search % contains a chord ?
{ gsave 0 -1 moverel
show grestore pop } if
gsave 0 -2 moverel
show grestore hbox 0 moverel
} def
/NewLine
{
LeftMargin currentpoint vbox fbox mul sub
exch pop moveto
} def
/NewPage {showpage LeftMargin TopMargin moveto} def
} def
%-------------------------------------------------------------------------------
%-------Guitar: an example of a style that uses Tablature. It defines the
%-------------- things that Tablature needs to know, for printing guitar
%-------------- tab with a row of text above & below.
%-------------------------------------------------------------------------------
/Guitar
{ % a tab style. this must come BEFORE 'Tablature'
/Times-Roman 8 ChooseFont
StdParser % usual method of entry.
/TextHandler
{% what to do with text.depends how many text objects you have.
{
{ (chord) {pop 0 IsTextRow} }
{ (lyric) {pop 7 IsTextRow} }
} ifcase
} def
[() [()][()][()][()][()][()] ()]
} def
/ASCIItab
{ % a tab style. this must come BEFORE 'Tablature'
/Times-Roman 8 ChooseFont
[[()][()][()][()][()][()]]
Tablature
ASCIIparser
} def
%-------------------------------------------------------------------------------
%-DOCUMENT SETUP----------------------------------------------------------------
%This section defines the margins of the page, and
%the line thickness used in the program. you may want
%to change some of this.
%-------------------------------------------------------------------------------
GetPageMargins
/LeftMargin 1 inch smaller
/RightMargin 1 inch smaller
/TopMargin 1 inch smaller
/BottomMargin 1 inch smaller
0.1 setlinewidth
/Text
{
/Times-Roman 8 ChooseFont
} def
%-------------------------------------------------------------------------------
%-DOCUMENT----------------------------------------------------------------------
% Your PStab files are added beyond this point.
%-------------------------------------------------------------------------------