summaryrefslogtreecommitdiff
path: root/support/pstab/PStab
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/pstab/PStab
Initial commit
Diffstat (limited to 'support/pstab/PStab')
-rw-r--r--support/pstab/PStab1027
1 files changed, 1027 insertions, 0 deletions
diff --git a/support/pstab/PStab b/support/pstab/PStab
new file mode 100644
index 0000000000..74bf88c619
--- /dev/null
+++ b/support/pstab/PStab
@@ -0,0 +1,1027 @@
+%!
+%%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
+
+ /TabHandler
+ {% what you call the rows that contain strings.
+ {
+ { (e) {pop 1 IsRow} }
+ { (B) {pop 2 IsRow} }
+ { (G) {pop 3 IsRow} }
+ { (D) {pop 4 IsRow} }
+ { (A) {pop 5 IsRow} }
+ { (E) {pop 6 IsRow} }
+ { /default {IsFret}}
+ } ifcase
+ } def
+ %template
+
+ [() [()][()][()][()][()][()] ()]
+} 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.
+%-------------------------------------------------------------------------------