/*****************************************************************************
*
* PSAncestry.rexx
*
* $VER: PSAncestry 1.02 (4 Dec 1998)
*
* Produces a Postscript¹ Ancestry Chart showing a total of 4 generations
* of ancestors of the "base" person. The resulting chart can be sent
* directly to a POSTSCRIPT printer connected to the parallel port or to a file.
*
* NOTES: (1) Requires 'rexxreqtools.library'
*
*        (2) This chart WILL correctly handle accented characters (such
*            as è, ð, ý, etc.).
*
* Credits: The postscript code generated by this program borrows heavily
*          from the LifeLines report program 'famtree1' by James P. Jones
*          and the orginal postscript code written by Phil Lloyd
*          (lloyd@prl.philips.co.uk).  
*
* Author: Robbie Akins
*
* ¹Postscript is a registered trademark of Adobe Systems Inc.
*
*****************************************************************************/
/* Tell ARexx we'll be expecting results */
Options Results

/*****************************************************************************
*
* User defined "constants". These may be edited for your own requirements
*
*****************************************************************************/

/* Noe defined! */

/*****************************************************************************
*
* End of user defined "constants". There's nothing you should change below!
*
*****************************************************************************/
versionstr = "1.02"	/* Program version */
maxgen = 4		/* Default number of generations */
NL = '0A'x		/* new-line */
MAX_NAME_LENGTH = 30	/* Maximum length of name strings */
MAX_PLACE_LENGTH = 35	/* Maximum length of place strings */

/* Enable error handling routins for syntax errors and Rexx errors */
Signal On Error
Signal On Syntax
Signal On Halt
Signal On IOErr

/* Also requires 'rexxreqtools.library' */
if ~show('l','rexxreqtools.library') then do
	if exists('libs:rexxreqtools.library') then do
		call addlib('rexxreqtools.library',0,-30,0)
	end
	else do
		Say "Unable to open rexxreqtools.library - quitting."
		exit
	end
end

/* Setup address of Scion */
MyPort = "SCIONGEN"

if(~Show('P',myport)) then do
	retval = Message("Please start Scion before"||NL||"running this program.")
	exit
end

Address value MyPort

/*****************************************************************************
*
* Postscript trailer code
*
*****************************************************************************/
trailer.1  = "% Draw lines tying the generations together"
trailer.2  = "% Tie 1st generation"
trailer.3  = "20 393 136 0 tie 20 393 136 0 tie"
trailer.4  = "% Tie 2nd generation"
trailer.5  = "210 461  68 1 tie  210 189  68 1 tie"
trailer.6  = "% Tie 3rd generation"
trailer.7  = "400 495  34 1 tie  400 359  34 1 tie"
trailer.8  = "400 223  34 1 tie  400  87  34 1 tie"
trailer.9  = "% Tie 4th generation"
trailer.10 = "590 512  17 1 tie  590 444  17 1 tie"
trailer.11 = "590 376  17 1 tie  590 308  17 1 tie"
trailer.12 = "590 240  17 1 tie  590 172  17 1 tie"
trailer.13 = "590 104  17 1 tie  590  36  17 1 tie"
trailer.14 = "showpage"
trailer.15 = ""			/* Empty string marks end of trailer */

/*****************************************************************************
*
* Postscript prologue code
*
* Contrary to appearances, the 'prolog' string below is actually pure ASCII!
* It is the postscript code to send to the output before any of the
* genealogy information is output in postscript form. In order to preserve
* the new-lines at the end of each line of postscript code, it has been
* necessary to "embed" the postscript code in hexadecimal form.
*
* To generate the hex code -
*	(1) convert the postscript ASCII prolog code to hex using the
*	    command "type >ram:pshex postscript_ascii_file opt h"
*	(2) using a text editor that supports rectangular block marking
*	    (such as TurboText) delete all the "surplus" output, retaining
*	    ONLY the hex code
*	(3) Enclose the hex code with " at the start and "X at the end. This
*	    marks the hex code as a hex string as far as ARexx is concerned.
*	(4) Copy the resulting "hex string" file into the section below
*	    such that 'prolog = "hex string generated"X'
*
* NOTE: To re-generate the ASCII postscript code for re-editing, simply
*       send the output of this ARexx programme to a file. This file will
*       contain the postscript code in ASCII. It will be obvious where the
*       'prolog' section of the code ends - it's labelled with a comment!
*
*****************************************************************************/
prolog = "2521200A25200A252050726F6475636573206120506F7374736372697074B920416E6365737472792043686172742073
686F77696E67206120746F74616C206F6620342067656E65726174696F6E730A25206F6620616E636573746F7273206F
66207468652022626173652220706572736F6E2E0A250A2520437265646974733A2054686520706F7374736372697074
20636F6465207573656420696E20746869732070726F6772616D20626F72726F77732068656176696C790A2520202020
20202020202066726F6D20746865204C6966654C696E6573207265706F72742070726F6772616D202766616D74726565
3127206279204A616D657320502E204A6F6E65730A2520202020202020202020616E6420746865206F7267696E616C20
706F737473637269707420636F6465207772697474656E206279205068696C204C6C6F79640A25202020202020202020
20286C6C6F79644070726C2E7068696C6970732E636F2E756B292E20200A250A2520417574686F723A20526F62626965
20416B696E730A250A2520B9506F7374736372697074206973206120726567697374657265642074726164656D61726B
206F662041646F62652053797374656D7320496E632E0A250A2520524A413A205265706C616365642027726573696465
6E636527206669656C642077697468202762757269616C27206669656C64200A2520524A413A20436F736D6574696320
6C61796F7574206368616E6765730A2520524A413A2041646465642049534F4C6174696E31456E636F64696E670A0A25
2049534F4C6174696E31456E636F64696E670A2F7265656E636F646549534F207B0A647570206475702066696E64666F
6E7420647570206C656E677468206469637420626567696E0A7B203120696E646578202F464944206E65207B20646566
207D7B20706F7020706F70207D206966656C7365207D20666F72616C6C0A2F456E636F64696E672049534F4C6174696E
31456E636F64696E67206465660A63757272656E746469637420656E6420646566696E65666F6E740A7D206465660A2F
49534F4C6174696E31456E636F64696E67205B0A2F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F
746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465660A2F2E6E6F746465662F2E6E
6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E
6F746465660A2F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E
6E6F746465662F2E6E6F746465662F2E6E6F746465660A2F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F
2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465660A2F73706163652F65
78636C616D2F71756F746564626C2F6E756D6265727369676E2F646F6C6C61722F70657263656E742F616D7065727361
6E642F71756F746572696768740A2F706172656E6C6566742F706172656E72696768742F617374657269736B2F706C75
732F636F6D6D612F6D696E75732F706572696F642F736C6173680A2F7A65726F2F6F6E652F74776F2F74687265652F66
6F75722F666976652F7369782F736576656E2F65696768742F6E696E652F636F6C6F6E2F73656D69636F6C6F6E0A2F6C
6573732F657175616C2F677265617465722F7175657374696F6E2F61742F412F422F432F442F452F462F472F482F492F
4A2F4B2F4C2F4D2F4E0A2F4F2F502F512F522F532F542F552F562F572F582F592F5A2F627261636B65746C6566742F62
61636B736C6173682F627261636B657472696768740A2F617363696963697263756D2F756E64657273636F72652F7175
6F74656C6566742F612F622F632F642F652F662F672F682F692F6A2F6B2F6C2F6D0A2F6E2F6F2F702F712F722F732F74
2F752F762F772F782F792F7A2F62726163656C6566742F6261722F627261636572696768742F617363696974696C6465
0A2F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465
662F2E6E6F746465662F2E6E6F746465660A2F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F7464
65662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465662F2E6E6F746465660A2F2E6E6F746465662F646F746C
657373692F67726176652F61637574652F63697263756D666C65782F74696C64652F6D6163726F6E2F62726576650A2F
646F74616363656E742F64696572657369732F2E6E6F746465662F72696E672F636564696C6C612F2E6E6F746465662F
68756E676172756D6C6175740A2F6F676F6E656B2F6361726F6E2F73706163652F6578636C616D646F776E2F63656E74
2F737465726C696E672F63757272656E63792F79656E2F62726F6B656E6261720A2F73656374696F6E2F646965726573
69732F636F707972696768742F6F726466656D696E696E652F6775696C6C656D6F746C6566742F6C6F676963616C6E6F
740A2F68797068656E2F726567697374657265642F6D6163726F6E2F6465677265652F706C75736D696E75732F74776F
7375706572696F722F74687265657375706572696F720A2F61637574652F6D752F7061726167726170682F706572696F
6463656E74657265642F636564696C6C612F6F6E657375706572696F722F6F72646D617363756C696E650A2F6775696C
6C656D6F7472696768742F6F6E65717561727465722F6F6E6568616C662F746872656571756172746572732F71756573
74696F6E646F776E0A2F4167726176652F4161637574652F4163697263756D666C65782F4174696C64652F4164696572
657369732F4172696E672F41452F43636564696C6C610A2F4567726176652F4561637574652F4563697263756D666C65
782F4564696572657369732F4967726176652F4961637574652F4963697263756D666C65780A2F496469657265736973
2F4574682F4E74696C64652F4F67726176652F4F61637574652F4F63697263756D666C65782F4F74696C64652F4F6469
6572657369730A2F6D756C7469706C792F4F736C6173682F5567726176652F5561637574652F5563697263756D666C65
782F5564696572657369732F5961637574650A2F54686F726E2F6765726D616E64626C732F6167726176652F61616375
74652F6163697263756D666C65782F6174696C64652F6164696572657369730A2F6172696E672F61652F63636564696C
6C612F6567726176652F6561637574652F6563697263756D666C65782F6564696572657369732F6967726176650A2F69
61637574652F6963697263756D666C65782F6964696572657369732F6574682F6E74696C64652F6F67726176652F6F61
637574652F6F63697263756D666C65780A2F6F74696C64652F6F64696572657369732F6469766964652F6F736C617368
2F7567726176652F7561637574652F7563697263756D666C65782F7564696572657369730A2F7961637574652F74686F
726E2F7964696572657369730A5D206465660A5B2F48656C766574696361202F48656C7665746963612D426F6C64202F
48656C7665746963612D4F626C697175655D207B7265656E636F646549534F206465667D20666F72616C6C0A0A252063
72656174652061207374616E64617264203120706F696E742048656C76657469636120666F6E74200A2F726F6D616E20
2F48656C7665746963612066696E64666F6E7420646566200A200A25206372656174652061207374616E646172642031
20706F696E742048656C7665746963612D426F6C6420666F6E74200A2F626F6C64202F48656C7665746963612D426F6C
642066696E64666F6E7420646566200A200A25206372656174652061207374616E64617264203120706F696E74204865
6C7665746963612D4F626C6971756520666F6E74200A2F6974616C202F48656C7665746963612D4F626C697175652066
696E64666F6E7420646566200A0A2520626F782070726F636564757265200A25203520617267756D656E74733A207820
616E642079206F66206D6964646C65206F66206C6566742D68616E642073696465200A25206E3A20656E747279206E75
6D62657220282031202D2033312029200A25207374796C653A20666F6E742028626F6C64206F72206974616C29200A25
20706F696E743A20706F696E742073697A652028766572746963616C29200A2520636F6E643A2060706F696E74207369
7A65272028686F72697A6F6E74616C29200A2520703A20706572736F6E2773206E616D65200A2F6D747278206D617472
697820646566200A2F626F78200A207B202F70206578636820646566200A202F636F6E64206578636820646566202F70
6F696E74206578636820646566202F7374796C65206578636820646566200A202F6E206578636820646566202F792065
78636820646566202F78206578636820646566200A200A202F736176656D6174726978206D7472782063757272656E74
6D617472697820646566200A200A20302E31207365746C696E657769647468200A200A202F6420313620646566202F73
7472203220737472696E6720646566200A202F772031373020646566202F6820313420646566202F6868206820322064
697620646566202F62726164203320646566200A20782079207472616E736C617465200A200A206E2030206E65207B20
0A202520626C61636B20626F7820666F72206E756D626572200A206E657770617468200A20302E3020302E30206D6F76
65746F200A20302E302068682064206868206272616420617263746F2034207B706F707D20726570656174200A206420
68682064206868206E6567206272616420617263746F2034207B706F707D20726570656174200A2064206868206E6567
20302E30206868206E6567206272616420617263746F2034207B706F707D20726570656174200A20302E30206868206E
656720302E3020302E30206272616420617263746F2034207B706F707D20726570656174200A20302E3020302E30206C
696E65746F200A2066696C6C200A200A2025207768697465206E756D626572200A202F48656C7665746963612066696E
64666F6E74203130207363616C65666F6E7420736574666F6E74200A20302E30206868206E6567206D6F7665746F200A
206E2073747220637673200A2064757020737472696E67776964746820706F70200A206E656720642061646420322064
6976202D332E35206D6F7665746F200A20312E3020736574677261792073686F7720302E302073657467726179200A20
7D206966200A200A202520626F7820666F72206E616D65200A206E657770617468200A206420302E30206D6F7665746F
200A20642068682077206868206272616420617263746F2034207B706F707D20726570656174200A2077206868207720
6868206E6567206272616420617263746F2034207B706F707D20726570656174200A2077206868206E65672064206868
206E6567206272616420617263746F2034207B706F707D20726570656174200A2064206868206E6567206420302E3020
6272616420617263746F2034207B706F707D20726570656174200A206420302E30206C696E65746F200A207374726F6B
65200A200A2025206E616D6520696E2063686F73656E20666F6E74200A2064203520616464206868206E656720332061
6464206D6F7665746F200A207374796C65205B636F6E642030203020706F696E74203020305D206D616B65666F6E7420
736574666F6E74200A20702073686F77200A202F48656C7665746963612066696E64666F6E74203130207363616C6566
6F6E7420736574666F6E74200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A200A
25207469652070726F636564757265200A25203420617267756D656E74733A207820616E642079206F6620746F702072
696768742D68616E6420656E64206F6620746965200A252076683A2068616C6620766572746963616C207370616E206F
662074686520746965200A2520626D756C3A206D756C7469706C69657220746F2072656469726563742063656E747261
6C207461696C200A2520313A207461696C206661636573206C656674200A2520303A207461696C206661636573207269
676874200A2F6D747278206D617472697820646566200A2F746965200A207B202F626D756C206578636820646566202F
7668206578636820646566202F79206578636820646566202F78206578636820646566200A200A202F736176656D6174
726978206D7472782063757272656E746D617472697820646566200A200A20302E31207365746C696E65776964746820
0A200A202F6820313020646566202F683220682032206D756C20646566202F762076682032206D756C20646566202F74
726164203420646566200A20782079207472616E736C617465200A200A206E657770617468200A20302E3020302E3020
6D6F7665746F200A2068206E656720302E302068206E6567207668206E6567207472616420617263746F2034207B706F
707D20726570656174200A2068206E6567207668206E6567206832206E656720626D756C206D756C207668206E656720
7472616420617263746F2034207B706F707D20726570656174200A206832206E656720626D756C206D756C207668206E
6567206C696E65746F200A20302E302076206E6567206D6F7665746F200A2068206E65672076206E65672068206E6567
207668206E6567207472616420617263746F2034207B706F707D20726570656174200A2068206E6567207668206E6567
206832206E656720626D756C206D756C207668206E6567207472616420617263746F2034207B706F707D207265706561
74200A207374726F6B65200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A200A25
206461746573312070726F636564757265200A2520333420617267756D656E74733A207820616E642079207374617274
206F66206669727374206C696E65206F662074657874200A25207362312C207062312C206362313A20666F6E7420666F
722074686520666F6C6C6F77696E672074657874200A252062313A206669727374206C696E65206F6620746578742066
6F722022626F726E22200A25207362322C207062322C206362323A20666F6E7420666F7220666F6C6C6F77696E672074
6578743A200A252062323A207365636F6E64206C696E65206F66207465787420666F722022626F726E22200A2520736D
312C20706D312C20636D313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A25206D313A20666972
7374206C696E65206F66207465787420666F7220226D61727269656422200A2520736D322C20706D322C20636D323A20
666F6E7420666F7220666F6C6C6F77696E6720746578743A200A25206D323A207365636F6E64206C696E65206F662074
65787420666F7220226D61727269656422200A25207372312C207072312C206372313A20666F6E7420666F7220666F6C
6C6F77696E6720746578743A200A252072313A206669727374206C696E65206F66207465787420666F72202264696564
22200A25207372322C207072322C206372323A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A2520
72323A207365636F6E64206C696E65206F66207465787420666F7220226469656422200A25207364312C207064312C20
6364313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252064313A206669727374206C696E6520
6F66207465787420666F72202262757269656422200A25207364322C207064322C206364323A20666F6E7420666F7220
666F6C6C6F77696E6720746578743A200A252064323A207365636F6E64206C696E65206F66207465787420666F722022
62757269656422200A2F6D747278206D617472697820646566200A2F646174657331200A207B202F6432206578636820
646566202F636432206578636820646566202F706432206578636820646566202F736432206578636820646566200A20
2F6431206578636820646566202F636431206578636820646566202F706431206578636820646566202F736431206578
636820646566200A202F7232206578636820646566202F637232206578636820646566202F7072322065786368206465
66202F737232206578636820646566200A202F7231206578636820646566202F637231206578636820646566202F7072
31206578636820646566202F737231206578636820646566200A202F6D32206578636820646566202F636D3220657863
6820646566202F706D32206578636820646566202F736D32206578636820646566200A202F6D31206578636820646566
202F636D31206578636820646566202F706D31206578636820646566202F736D31206578636820646566200A202F6232
206578636820646566202F636232206578636820646566202F706232206578636820646566202F736232206578636820
646566200A202F6231206578636820646566202F636231206578636820646566202F706231206578636820646566202F
736231206578636820646566200A202F79206578636820646566202F78206578636820646566200A200A202F73617665
6D6174726978206D7472782063757272656E746D617472697820646566200A202F766F6666203230206E656720646566
202F7620313920646566202F7676203920646566202F686F666620313520646566200A20782079207472616E736C6174
65200A200A206E657770617468200A20302E3020766F6666206D6F7665746F2028622E292073686F7720090925205761
732027426F726E270A20302E3020766F6666207620737562206D6F7665746F20286D2E292073686F7720092009252057
617320274D617272696564270A20302E3020766F666620762032206D756C20737562206D6F7665746F2028642E292073
686F77092520576173202744696564270A20302E3020766F666620762033206D756C20737562206D6F7665746F202866
2E292073686F77200925205761732027427572696564270A20736231205B6362312030203020706231203020305D206D
616B65666F6E7420736574666F6E74200A20686F666620766F6666206D6F7665746F2062312073686F77200A20736232
205B6362322030203020706232203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F666620
767620737562206D6F7665746F2062322073686F77200A20736D31205B636D312030203020706D31203020305D206D61
6B65666F6E7420736574666F6E74200A20686F666620766F6666207620737562206D6F7665746F206D312073686F7720
0A20736D32205B636D322030203020706D32203020305D206D616B65666F6E7420736574666F6E74200A20686F666620
766F666620762073756220767620737562206D6F7665746F206D322073686F77200A20737231205B6372312030203020
707231203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F666620762032206D756C207375
62206D6F7665746F2072312073686F77200A20737232205B6372322030203020707232203020305D206D616B65666F6E
7420736574666F6E74200A20686F666620766F666620762032206D756C2073756220767620737562206D6F7665746F20
72322073686F77200A20736431205B6364312030203020706431203020305D206D616B65666F6E7420736574666F6E74
200A20686F666620766F666620762033206D756C20737562206D6F7665746F2064312073686F77200A20736432205B63
64322030203020706432203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F666620762033
206D756C2073756220767620737562206D6F7665746F2064322073686F77200A200A20736176656D6174726978207365
746D6174726978200A207D20646566200A200A25206461746573322070726F636564757265200A252031302061726775
6D656E74733A207820616E642079207374617274206F66206669727374206C696E65206F662074657874200A25207362
312C207062312C206362313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252062313A20666972
7374206C696E65206F66207465787420666F722022626F726E22200A25207362322C207062322C206362323A20666F6E
7420666F7220666F6C6C6F77696E6720746578743A200A252062323A207365636F6E64206C696E65206F662074657874
20666F722022626F726E22200A25207364312C207064312C206364313A20666F6E7420666F7220666F6C6C6F77696E67
20746578743A200A252064313A206669727374206C696E65206F66207465787420666F7220226469656422200A252073
64322C207064322C206364323A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252064323A207365
636F6E64206C696E65206F66207465787420666F7220226469656422200A2F6D747278206D617472697820646566200A
2F646174657332200A207B202F6432206578636820646566202F636432206578636820646566202F7064322065786368
20646566202F736432206578636820646566200A202F6431206578636820646566202F63643120657863682064656620
2F706431206578636820646566202F736431206578636820646566200A202F6232206578636820646566202F63623220
6578636820646566202F706232206578636820646566202F736232206578636820646566200A202F6231206578636820
646566202F636231206578636820646566202F706231206578636820646566202F736231206578636820646566200A20
2F79206578636820646566202F78206578636820646566200A200A202F736176656D6174726978206D74727820637572
72656E746D617472697820646566200A202F766F6666203230206E656720646566202F7620313920646566202F767620
3920646566202F686F666620313520646566200A20782079207472616E736C617465200A200A206E657770617468200A
20302E3020766F6666206D6F7665746F2028622E292073686F772009090925205761732027426F726E270A20302E3020
766F6666207620737562206D6F7665746F2028642E292073686F772009092520576173202744696564270A2073623120
5B6362312030203020706231203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F6666206D
6F7665746F2062312073686F77200A20736232205B6362322030203020706232203020305D206D616B65666F6E742073
6574666F6E74200A20686F666620766F666620767620737562206D6F7665746F2062322073686F77200A20736431205B
6364312030203020706431203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F6666207620
737562206D6F7665746F2064312073686F77200A20736432205B6364322030203020706432203020305D206D616B6566
6F6E7420736574666F6E74200A20686F666620766F666620762073756220767620737562206D6F7665746F2064322073
686F77200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A200A2520646174657333
2070726F636564757265200A2520313020617267756D656E74733A207820616E642079207374617274206F6620666972
7374206C696E65206F662074657874200A25207362312C207062312C206362313A20666F6E7420666F7220666F6C6C6F
77696E6720746578743A200A252062313A206C696E65206F66207465787420666F722022626F726E22200A2520736D31
2C20706D312C20636D313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A25206D313A206C696E65
206F66207465787420666F7220226D61727269656422200A25207372312C207072312C206372313A20666F6E7420666F
7220666F6C6C6F77696E6720746578743A200A252072313A206C696E65206F66207465787420666F7220226469656422
200A25207364312C207064312C206364313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252064
313A206C696E65206F66207465787420666F72202262757269656422200A2F6D747278206D617472697820646566200A
2F646174657333200A207B202F6431206578636820646566202F636431206578636820646566202F7064312065786368
20646566202F736431206578636820646566200A202F7231206578636820646566202F63723120657863682064656620
2F707231206578636820646566202F737231206578636820646566200A202F6D31206578636820646566202F636D3120
6578636820646566202F706D31206578636820646566202F736D31206578636820646566200A202F6231206578636820
646566202F636231206578636820646566202F706231206578636820646566202F736231206578636820646566200A20
2F79206578636820646566202F78206578636820646566200A200A202F736176656D6174726978206D74727820637572
72656E746D617472697820646566200A202F766F6666203137206E656720646566202F7620313120646566202F686F66
6620313520646566200A20782079207472616E736C617465200A200A206E657770617468200A20302E3020766F666620
6D6F7665746F2028622E292073686F770920090925205761732027426F726E270A20302E3020766F6666207620737562
206D6F7665746F20286D2E292073686F77092009252057617320274D617272696564270A20302E3020766F6666207620
32206D756C20737562206D6F7665746F2028642E292073686F7720092520576173202744696564270A20302E3020766F
666620762033206D756C20737562206D6F7665746F2028662E292073686F77200925205761732027427572696564270A
20736231205B6362312030203020706231203020305D206D616B65666F6E7420736574666F6E74200A20686F66662076
6F6666206D6F7665746F2062312073686F77200A20736D31205B636D312030203020706D31203020305D206D616B6566
6F6E7420736574666F6E74200A20686F666620766F6666207620737562206D6F7665746F206D312073686F77200A2073
7231205B6372312030203020707231203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F66
6620762032206D756C20737562206D6F7665746F2072312073686F77200A20736431205B636431203020302070643120
3020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F666620762033206D756C20737562206D6F
7665746F2064312073686F77200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A20
0A25206461746573342070726F636564757265200A25203620617267756D656E74733A207820616E6420792073746172
74206F66206669727374206C696E65206F662074657874200A25207362312C207062312C206362313A20666F6E742066
6F7220666F6C6C6F77696E6720746578743A200A252062313A206C696E65206F66207465787420666F722022626F726E
22200A25207364312C207064312C206364313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A2520
64313A206C696E65206F66207465787420666F7220226469656422200A2F6D747278206D617472697820646566200A2F
646174657334200A207B202F6431206578636820646566202F636431206578636820646566202F706431206578636820
646566202F736431206578636820646566200A202F6231206578636820646566202F636231206578636820646566202F
706231206578636820646566202F736231206578636820646566200A202F79206578636820646566202F782065786368
20646566200A200A202F736176656D6174726978206D7472782063757272656E746D617472697820646566200A202F76
6F6666203137206E656720646566202F7620313120646566202F686F6666203135206465660A20782079207472616E73
6C617465200A200A206E657770617468200A20302E3020766F6666206D6F7665746F2028622E292073686F7709200909
25205761732027426F726E270A20302E3020766F6666207620737562206D6F7665746F2028642E292073686F77200909
2520576173202744696564270A20736231205B6362312030203020706231203020305D206D616B65666F6E7420736574
666F6E74200A20686F666620766F6666206D6F7665746F2062312073686F77200A20736431205B636431203020302070
6431203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F6666207620737562206D6F766574
6F2064312073686F77200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A200A2520
6461746573352070726F636564757265200A2520524A413A2057697468206368616E6765206F6620277265736964656E
742720746F202762757269616C272C20643120262072312068617665206265656E20696E7465726368616E676564210A
2520313020617267756D656E74733A207820616E642079207374617274206F66206669727374206C696E65206F662074
657874200A25207362312C207062312C206362313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A
252062313A207465787420666F722022626F726E22200A2520736D312C20706D312C20636D313A20666F6E7420666F72
20666F6C6C6F77696E6720746578743A200A25206D313A207465787420666F7220226D61727269656422200A25207372
312C207072312C206372313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252072313A20746578
7420666F7220226469656422200A25207364312C207064312C206364313A20666F6E7420666F7220666F6C6C6F77696E
6720746578743A200A252064313A207465787420666F72202262757269656422200A2F6D747278206D61747269782064
6566200A2F646174657335200A207B202F6431206578636820646566202F636431206578636820646566202F70643120
6578636820646566202F736431206578636820646566200A202F7231206578636820646566202F637231206578636820
646566202F707231206578636820646566202F737231206578636820646566200A202F6D31206578636820646566202F
636D31206578636820646566202F706D31206578636820646566202F736D31206578636820646566200A202F62312065
78636820646566202F636231206578636820646566202F706231206578636820646566202F7362312065786368206465
66200A202F79206578636820646566202F78206578636820646566200A200A202F736176656D6174726978206D747278
2063757272656E746D617472697820646566200A202F766F6666203135206E656720646566202F762031302064656620
2F776820383520646566202F686F666620313520646566200A20782079207472616E736C617465200A200A206E657770
617468200A20302E3020766F6666206D6F7665746F2028622E292073686F770920090925205761732027426F726E270A
20302E3020766F6666207620737562206D6F7665746F20286D2E292073686F77200909252057617320274D617272270A
20776820766F6666207620737562206D6F7665746F2028662E292073686F772009092520576173202742757279270A20
776820766F6666206D6F7665746F2028642E292073686F77092009092520576173202744696564270A20736231205B63
62312030203020706231203020305D206D616B65666F6E7420736574666F6E74200A20686F666620766F6666206D6F76
65746F2062312073686F77200A20736D31205B636D312030203020706D31203020305D206D616B65666F6E7420736574
666F6E74200A20686F666620766F6666207620737562206D6F7665746F206D312073686F77200A20737231205B637231
2030203020707231203020305D206D616B65666F6E7420736574666F6E74200A20776820686F66662061646420766F66
66207620737562206D6F7665746F2064312073686F77200A20736431205B6364312030203020706431203020305D206D
616B65666F6E7420736574666F6E74200A20776820686F66662061646420766F6666206D6F7665746F2072312073686F
77200A200A20736176656D6174726978207365746D6174726978200A207D20646566200A200A25206461746573362070
726F636564757265200A25203620617267756D656E74733A207820616E642079207374617274206F662074657874200A
25207362312C207062312C206362313A20666F6E7420666F7220666F6C6C6F77696E6720746578743A200A252062313A
207465787420666F722022626F726E22200A25207364312C207064312C206364313A20666F6E7420666F7220666F6C6C
6F77696E6720746578743A200A252064313A207465787420666F7220226469656422200A2F6D747278206D6174726978
20646566200A2F646174657336200A207B202F6431206578636820646566202F636431206578636820646566202F7064
31206578636820646566202F736431206578636820646566200A202F6231206578636820646566202F63623120657863
6820646566202F706231206578636820646566202F736231206578636820646566200A202F7920657863682064656620
2F78206578636820646566200A200A202F736176656D6174726978206D7472782063757272656E746D61747269782064
6566200A202F766F6666203135206E656720646566202F7620313020646566202F776820383520646566202F686F6666
20313520646566200A20782079207472616E736C617465200A200A206E657770617468200A20302E3020766F6666206D
6F7665746F2028622E292073686F7709090925205761732027426F726E27200A20776820766F6666206D6F7665746F20
28642E292073686F77092009092520576173202744696564270A20736231205B6362312030203020706231203020305D
206D616B65666F6E7420736574666F6E74200A20686F666620766F6666206D6F7665746F2062312073686F77200A2073
6431205B6364312030203020706431203020305D206D616B65666F6E7420736574666F6E74200A20776820686F666620
61646420766F6666206D6F7665746F2064312073686F77200A200A20736176656D6174726978207365746D6174726978
200A207D20646566200A200A2520636F6F7264696E617465207472616E73666F726D20746F206C616E64736361706520
666F726D6174200A393020726F74617465203230202D353633207472616E736C617465200A200A25207363616C696E67
207573656420666F7220706F636B65742076657273696F6E200A2520302E3620302E36207363616C65200A253D3D3D3D
20456E64206F6620706F7374736372697074207072656C6F67756520636F6465203D3D3D3D3D3D0A"X

/*****************************************************************************
*
* Start of program proper
*
*****************************************************************************/

GETPROGVERSION
version = RESULT
if(version < 5.00) then do
	retval = Message("This program requires Scion"||NL||"Version 5.00 or later.")
	Exit
end

GETTOTALIRN
p = RESULT
GETTOTALFGRN
f = RESULT
if (p = 0) | (f = 0) then do
	retval = Message("Insufficient data in database"||NL||"to produce a chart.")
	Exit
end

/* Use Scion public screen */
PSCR = "SCIONGEN"

/* Startup message */
thanks = rtezrequest('This program produces a Postscript'||NL||,
	'Ancestry Chart from a Scion database.'||NL||NL||,
	'Select the person whose ancestors you'||NL|| 'want printed from the next requester.','Okay','PSAncestry v'||versionstr' by R J Akins','rt_pubscrname = '||PSCR)

/* Select "base" person of chart */
REQUESTPERSON
BasePerson = RESULT
if BasePerson = 0 then exit	/* User cancelled */

/* Build selected name to display in requesters */
GETLASTNAME BasePerson
lastname = RESULT
GETFIRSTNAME BasePerson
firstname = RESULT
reqname = lastname||', '||firstname
reqname = TrimString(reqname, MAX_NAME_LENGTH)

/* Get database name to display in requesters */
GETDBNAME
dbname = upper(RESULT)

/* Let user select output destination */
dest = rtezrequest('Current Scion database: '||dbname||NL||'Root: '||reqname||NL||NL||,
'Where should the postscript'||NL||'output be sent to?'||,
	'','_File|_PAR:|_Cancel','PSAncestry v'||versionstr||' by R J Akins','rt_pubscrname = '||PSCR)

select
	when dest = 1 then do
		/* We need a file requester for further data */
		outname = rtfilerequest(,dbname||'.ps','Output filename',,'rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
		if outname = '' then
			outname = dbname||'.ps'
		end
	when dest = 2 then
		outname = 'PAR:'
	otherwise exit	/* Aborted */
end

/* Open output destination */
if ~open(output, outname, "w") then do
	retval = Message("ERROR: Unable to open output file"||NL||"or device. Aborting.")
	exit
end

/* Get information for chart label */
GETFULLNAME BasePerson
bp_full = RESULT
bp_full = TRANSLATE(bp_full, "{}/", "()\")	/* Replace '(', ')' and '\' with '{', '}' and '/' */

/****************************
*                           *
* Output postscript prolog  *
*                           *
****************************/
PSOutput(dest, prolog)

/****************************
*                           *
* Output title, prep., etc  *
*                           *
****************************/
ps_string = "% Print chart title"
PSOutput(dest, ps_string)
ps_string = "/Helvetica-Bold findfont  14 scalefont  setfont"
PSOutput(dest, ps_string)
ps_string = "30 510 moveto  (Ancestry Chart for "||bp_full||") show	% Name of base person"
PSOutput(dest, ps_string)

ps_string = "% Print chart preparation details"
PSOutput(dest, ps_string)
ps_string = "/Helvetica-Oblique findfont  9 scalefont  setfont"
PSOutput(dest, ps_string)

/* Get preparer's details */
GETPREPARER
prep = RESULT
prep = TRANSLATE(prep, "{}/", "()\")	/* Replace '(', ')' and '\' with '{', '}' and '/' */
/* Parse out name and address */
PARSE VAR prep p_name '$' p_adr1 '$' p_adr2 '$' p_adr3 '$'
prepaddr = p_adr1||", "||p_adr2||", "p_adr3
ps_string = "30 495 moveto (Prepared by "||p_name||") show % Name of preparer"
PSOutput(dest, ps_string)
ps_string = "30 485 moveto ("||prepaddr||") show % Address of preparer"
PSOutput(dest, ps_string)
GETPREPPHONE
prepphone = RESULT
prepphone = TRANSLATE(prepphone, "{}/", "()\")	/* Replace '(', ')' and '\' with '{', '}' and '/' */
ps_string = "30 475 moveto ("||prepphone||") show % Phone number of preparer"
PSOutput(dest, ps_string)

/* NOTE: No special provision for email address at this stage */

/* Date report produced */
today = DATE()
ps_string = "30 455 moveto  (Chart dated: "||today||") show % Date chart produced"
PSOutput(dest, ps_string)

/* A bit more 'pre-amble' */
ps_string = "/Helvetica findfont  14 scalefont  setfont"
PSOutput(dest, ps_string)
ps_string = "20 270 moveto  (Ancestors of:) show"
PSOutput(dest, ps_string)
ps_string = "/Helvetica findfont 10 scalefont setfont"
PSOutput(dest, ps_string)
ps_string = "% Now do remainder of chart proper"
PSOutput(dest, ps_string)

/****************************
*                           *
* Do bases's part of chart  *
*                           *
****************************/
/* Need base person's first spouse */
spouse = 0
GETMARRIAGE BasePerson 0
family = RESULT
EXISTFAMILY family
if RESULT = 'YES' then do
	GETPRINCIPAL family
	if RESULT ~= BasePerson then do
		spouse = RESULT
		end
	else do
		GETSPOUSE family
		if RESULT ~= BasePerson then do
			spouse = RESULT
			end
		end
	end

/* Output base person's postscript code */
OutputDetails(BasePerson, spouse, 1)

/* NOTE: Base person's spouses are handled specially belwo */

/****************************
*                           *
* Do father's part of chart *
*                           *
****************************/
GETFATHER BasePerson
Ancestor.1 = RESULT

/* Handle father */
spouse = 0

GETMOTHER BasePerson
mum = RESULT
EXISTPERSON mum
if RESULT = 'YES' then do
	spouse = mum
	end
/* Output father's postscript code */
OutputDetails(Ancestor.1, spouse, 2)

/* Collect father's ancestors and output postscript code */
section = 1
CollectAncestors(section)

/****************************
*                           *
* Do mother's part of chart *
*                           *
****************************/
GETMOTHER BasePerson
Ancestor.1 = RESULT

/* Output mother's postscript code */
OutputDetails(Ancestor.1, 0, 3)

/* Collect mother's ancestors and output postscript code */
section = 2
CollectAncestors(section)

/****************************
*                           *
* Do base person's spouses  *
*                           *
****************************/
/* First spouse is handled slightly differently */
spouse = 0
GETMARRIAGE BasePerson 0
family = RESULT
EXISTFAMILY family
if RESULT = 'YES' then do
	GETPRINCIPAL family
	if RESULT ~= BasePerson then do
		spouse = RESULT
		end
	else do
		GETSPOUSE family
		if RESULT ~= BasePerson then do
			spouse = RESULT
			end
		end
	end
spousename = ""
EXISTPERSON spouse
if RESULT = 'YES' then do
	GETFULLNAME spouse
	spousename = RESULT
	spousename = TrimString(spousename, MAX_NAME_LENGTH)
	ps_string = "/Helvetica findfont  12 scalefont setfont"
	PSOutput(dest, ps_string)
	ps_string = "36 156 moveto  (Spouse #1) show"
	PSOutput(dest, ps_string)
	ps_string = "20 145 0 bold 9 9 ("||spousename||") box"
	PSOutput(dest, ps_string)
	end

/* Reaining spouses (if any) */
GETMARRIAGE BasePerson 1
family = RESULT
EXISTFAMILY family
if RESULT = 'YES' then do
	/* Label for additional spouses */
	ps_string = "/Helvetica findfont  12 scalefont setfont"
	PSOutput(dest, ps_string)
	ps_string = "36 55 moveto  (Other spouses:) show"
	PSOutput(dest, ps_string)
	end

/* Now actual additional spouse details */
i=1
xoffset = 20
do while (i<5)
	spouse = 0
	yoffset = 44 - ((i-1)*16)

	GETMARRIAGE BasePerson i
	family = RESULT
	EXISTFAMILY family
	if RESULT = 'YES' then do
		GETPRINCIPAL family
		if RESULT ~= BasePerson then do
			spouse = RESULT
			end
		else do
			GETSPOUSE family
			if RESULT ~= BasePerson then do
				spouse = RESULT
				end
			end
		end
	spousename = ""
	EXISTPERSON spouse
	if RESULT = 'YES' then do
		GETFULLNAME spouse
		spousename = RESULT
		spousename = TrimString(spousename, MAX_NAME_LENGTH)
		ps_string = "/Helvetica findfont  12 scalefont setfont"
		PSOutput(dest, ps_string)
		ps_string = xoffset yoffset "0 bold 9 9 ("||spousename||") box"
		PSOutput(dest, ps_string)
		end
	i = i+1
	end

/****************************
*                           *
* Do final section of chart *
*                           *
****************************/
/* Output postscript trailer code */
i = 1
do while trailer.i ~= ''
	PSOutput(dest, trailer.i)
	i = i+1
end

/* Ctrl-D: Not to file - only printer */
if dest = 2 then PSOutput(dest, "04"X)

close(output)

/* Notify user that program has finished */
rtezrequest('PSAncestry finished','Okay','PSAncestry v'||versionstr,'rt_pubscrname = '||PSCR)

exit	/* All done */


/*****************************************************************************
*
* Procedure to collect ancestors and output details
*
*****************************************************************************/
CollectAncestors: PROCEDURE EXPOSE Ancestor. maxgen MAX_NAME_LENGTH MAX_PLACE_LENGTH
parse arg sector

do i = 1 to 2**(maxgen-1)
	j = 2*i
	k = 2*i+1
	GETFATHER Ancestor.i
	Ancestor.j = RESULT
	GETMOTHER Ancestor.i
	Ancestor.k = RESULT

	/* Collect and output postscript code for male ancestors */
	AncestorDetails(j, sector)

	/* Collect and output postscript code for female ancestors */
	AncestorDetails(k, sector)
end

return 0

/*****************************************************************************
*
* Procedure to process ancestor details
*
*****************************************************************************/
AncestorDetails: PROCEDURE EXPOSE Ancestor. dest maxgen MAX_NAME_LENGTH MAX_PLACE_LENGTH
parse arg ahnen, sector

/* Convert ahnen, sector to generation, leaf */
Ahnen2Leaf(ahnen, sector)

/* Now calculate chart number */
chart_number = 2**generation + leaf

/* Also need irn of male's spouse for correct marriage details */
spouse = 0			/* No spouse */
if(ahnen//2) = 0 then do	/* Male ancestor */
	temp = ahnen+1
	EXISTPERSON Ancestor.temp
	if RESULT = 'YES' then do
		spouse = Ancestor.temp
		end
	end
if chart_number < 2**(maxgen+1) then do

	/* Output postscript code for this ancestor */
	OutputDetails(Ancestor.ahnen, spouse, chart_number)
	end
return 0

/*****************************************************************************
*
* Procedure to convert an ahnen/sector reference to a generation/leaf
*
*****************************************************************************/
Ahnen2Leaf: PROCEDURE EXPOSE generation leaf
parse arg ahnen, sector

aa = ahnen
gen = 0
do while aa ~= 0
	aa = aa%2
	gen = gen + 1
end
generation = gen

leaf = ahnen - 2**(gen-1)
if sector = 2 then leaf = 2**(gen-1) + leaf

return 0

/*****************************************************************************
*
* Procedure to output actual ancestor details
*
* NOTE: 'irn' is record number of person of interest (can be ""), 'spouse'
*  is irn of male's spouse (required for marriage details) or 0 for females,
*  and 'chartnum' is the position on the o/p ancestry chart.
*
*****************************************************************************/
OutputDetails: PROCEDURE EXPOSE MAX_NAME_LENGTH MAX_PLACE_LENGTH
parse arg irn, spouse, chartnum

if irn ~= "" then do
	/* Collect information for chart */
	GETFULLNAME irn 2	/* Last-name first format */
	fullname = RESULT
	fullname = TrimString(fullname, MAX_NAME_LENGTH) /* Trim name, if needed */
	GETBIRTHDATE irn
	birthdate = RESULT
	GETBIRTHPLACE irn
	birthplace = RESULT
	birthplace = TrimString(birthplace, MAX_PLACE_LENGTH)
	GETDEATHDATE irn
	deathdate = RESULT
	GETDEATHPLACE irn
	deathplace = RESULT
	deathplace = TrimString(deathplace, MAX_PLACE_LENGTH)
	GETBURIALDATE irn
	burialdate = RESULT
	GETBURIALPLACE irn
	burialplace = RESULT
	burialplace = TrimString(burialplace, MAX_PLACE_LENGTH)

	/* If chartnum is even, then person is male. Find correct marriage */
	if((chartnum//2) = 0) | (chartnum = 1) then do
		family = FindMarriage(irn, spouse)
		EXISTFAMILY family
		if RESULT = 'YES' then do
			GETMARRYDATE family
			marrydate = RESULT
			GETMARRYPLACE family
			marryplace = RESULT
			marryplace = TrimString(marryplace, MAX_PLACE_LENGTH)
			end
		else do
			marrydate = ""
			marryplace = ""
			end
		end
	else do
		/* Marriage isn't recorded with females */
		marrydate = ""
		marryplace = ""
		end
	end
else do
	fullname = ""
	birthdate = ""
	birthplace = ""
	deathdate = ""
	deathplace = ""
	burialdate = ""
	burialplace = ""
	marrydate = ""
	marryplace = ""
	end

/* Have everything we need - now output actual postscript code for each person */
if chartnum = 1 then do
	/* Base individual */
	xoffset = 20
	yoffset = 257

	/* Person's name in box */
	ps_string = xoffset yoffset chartnum "bold" 9 9 "("fullname") box % Person's name" 
	PSOutput(dest, ps_string)

	/* Date/place information */
	ps_string = xoffset yoffset
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||birthdate||") % 'Birth date'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||birthplace||") % 'Birth place'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||marrydate||") % 'Marriage date'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||marryplace||") % 'Marriage place'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||deathdate||") % 'Death date'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||deathplace||") % 'Death place'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||burialdate||") % 'Burial date'"
	PSOutput(dest, ps_string)
	ps_string = "roman 10 9 ("||burialplace||") % 'Burial place'"
	PSOutput(dest, ps_string)
	ps_string = "dates1"
	PSOutput(dest, ps_string)
	end
if (chartnum = 2) | (chartnum = 3) then do
	/* Parents */
	xoffset = 20
	yoffset = 393 - ((chartnum-2)*272)

	/* Person's name in box */
	ps_string = xoffset yoffset chartnum "bold" 9 9 "("fullname") box % Person's name" 
	PSOutput(dest, ps_string)

	/* Date/place information */
	ps_string = xoffset yoffset
	PSOutput(dest, ps_string)
	if(chartnum//2) = 0 then do	/* Male ancestor */
		ps_string = "roman 10 9 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||birthplace||") % 'Birth place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||marrydate||") % 'Marriage date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||marryplace||") % 'Marriage place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathplace||") % 'Death place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||burialdate||") % 'Burial date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||burialplace||") % 'Burial place'"
		PSOutput(dest, ps_string)
		ps_string = "dates1"
		PSOutput(dest, ps_string)
		end
	else do
		ps_string = "roman 10 9 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||birthplace||") % 'Birth place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathplace||") % 'Death place'"
		PSOutput(dest, ps_string)
		ps_string = "dates2"
		PSOutput(dest, ps_string)
		end
	end
if (chartnum >3 ) & (chartnum < 8) then do
	/* Grand-parents */
	xoffset = 210
	yoffset = 461 - ((chartnum-4)*136)

	/* Person's name in box */
	ps_string = xoffset yoffset chartnum "bold" 9 9 "("fullname") box % Person's name" 
	PSOutput(dest, ps_string)

	/* Date/place information */
	ps_string = xoffset yoffset
	PSOutput(dest, ps_string)
	if(chartnum//2) = 0 then do	/* Male ancestor */
		ps_string = "roman 10 9 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||birthplace||") % 'Birth place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||marrydate||") % 'Marriage date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||marryplace||") % 'Marriage place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathplace||") % 'Death place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||burialdate||") % 'Burial date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||burialplace||") % 'Burial place'"
		PSOutput(dest, ps_string)
		ps_string = "dates1"
		PSOutput(dest, ps_string)
		end
	else do
		ps_string = "roman 10 9 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||birthplace||") % 'Birth place'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 9 ("||deathplace||") % 'Death place'"
		PSOutput(dest, ps_string)
		ps_string = "dates2"
		PSOutput(dest, ps_string)
		end
	end
if (chartnum > 7) & (chartnum < 16) then do
	/* Great-grand-parents */
	xoffset = 400
	yoffset = 495 - ((chartnum-8)*68)

	/* Person's name in box */
	ps_string = xoffset yoffset chartnum "bold" 9 9 "("fullname") box % Person's name" 
	PSOutput(dest, ps_string)

	/* Date/place information */
	ps_string = xoffset yoffset
	PSOutput(dest, ps_string)
	if(chartnum//2) = 0 then do	/* Male ancestor */
		ps_string = "roman 10 7.6 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||marrydate||") % 'Marriage date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||burialdate||") % 'Burial date'"
		PSOutput(dest, ps_string)
		ps_string = "dates3"
		PSOutput(dest, ps_string)
		end
	else do
		ps_string = "roman 10 7.6 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "dates4"
		PSOutput(dest, ps_string)
		end
	end
if (chartnum > 15) & (chartnum < 32) then do
	/* Great-great-grand-parents */
	xoffset = 590
	yoffset = 512 - ((chartnum-16)*34)

	/* Person's name in box */
	ps_string = xoffset yoffset chartnum "bold" 9 9 "("fullname") box % Person's name" 
	PSOutput(dest, ps_string)

	/* Date/place information */
	ps_string = xoffset yoffset
	PSOutput(dest, ps_string)
	if(chartnum//2) = 0 then do	/* Male ancestor */
		ps_string = "roman 10 7.6 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||marrydate||") % 'Marriage date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||burialdate||") % 'Burial date'"
		PSOutput(dest, ps_string)
		ps_string = "dates5"
		PSOutput(dest, ps_string)
		end
	else do
		ps_string = "roman 10 7.6 ("||birthdate||") % 'Birth date'"
		PSOutput(dest, ps_string)
		ps_string = "roman 10 7.6 ("||deathdate||") % 'Death date'"
		PSOutput(dest, ps_string)
		ps_string = "dates6"
		PSOutput(dest, ps_string)
		end
	end

return 0

/*****************************************************************************
*
* Procedure to find marriage between two people. Returns 'fgrn'
*
*****************************************************************************/
FindMarriage: PROCEDURE
parse arg irn, spouse

fgrn = 0
i=0
do while (i<10)
	GETMARRIAGE irn i
	family = RESULT
	EXISTFAMILY family
	if RESULT = 'YES' then do
		GETPRINCIPAL family
		if RESULT = spouse then do
			fgrn = family
			break
			end
		else do
			GETSPOUSE family
			if RESULT = spouse then do
				fgrn = family
				break
				end
			end
		end
	i = i+1
	end
return fgrn

/*****************************************************************************
*
* Procedure to trim string, also replacing "illegal" postscript characters
*
*****************************************************************************/
TrimString: PROCEDURE
parse arg string, length

/* First, replace '(', ')' and '\' with '{', '}' and '/' */
string = TRANSLATE(string, "{}/", "()\")

/* Now trim length */
len = LENGTH(string)
if (len > length) then do
	/* Too long - trim */
	string = LEFT(string, length-3)
	string = string"..."
end
return string

/*****************************************************************************
*
* Output string procedure
*
*****************************************************************************/
PSOutput: PROCEDURE EXPOSE output
parse arg mode, string

if mode ~= 0 then do
	writeln(output, string)
end
else say string

return 0

/*****************************************************************************
*
* Procedure to display a message using rexxreqtools.library
*
*****************************************************************************/
Message: PROCEDURE EXPOSE NL PSCR versionstr
parse arg string

retval = rtezrequest(string,'Okay','PSAncestry v'||versionstr' by R J Akins','rt_pubscrname = '||PSCR)

return retval

/*****************************************************************************
*
* Error handling
*
*****************************************************************************/
Error:
	Parse Source Type Num Script Prog Port
	say 'ERROR: Function failure. Return level 'RC' on line 'SIGL' **'
	exit

Syntax:
	Parse Source Type Num MacroName Script Prog Port
	say 'SYNTAX: Macro "'MacroName'", Error: #'RC' ("'ErrorText(RC)'") on line 'SIGL' **'
	exit

Halt:
	Parse Source Type Num MacroName Script Prog Port
	say 'HALT: Macro "'MacroName'", Error: #'RC' on line 'SIGL' **'
	exit

IOErr:
	Parse Source Type Num MacroName Script Prog Port
	say 'IOERR: Macro "'MacroName'", Error: #'RC' on line 'SIGL' **'
	exit
