home *** CD-ROM | disk | FTP | other *** search
/ The AGA Experience 2 / agavol2.iso / rexx / printdescendant.rexx < prev    next >
OS/2 REXX Batch file  |  1995-09-21  |  19KB  |  692 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * $VER: PrintDescendant 2.00 (2 Feb 1995)
  4.  *                                                                          *
  5.  *                      Written by Freddy Ariës                             *
  6.  *                                                                          *
  7.  * Output options:                                                          *
  8.  *  1. Descendant Chart - all descendants [Dutch: parenteel]                *
  9.  *  2. Descendant Chart - male descendants (mention daughters, no children) *
  10.  *     [Dutch: genealogie - nageslacht van zonen, maar vermelding dochters] *
  11.  *  3. Descendant Chart - male descendants (leave out daughters)            *
  12.  *     [Dutch: stamboom - nageslacht van zonen, geen vermelding dochters]   *
  13.  *                                                                          *
  14.  * This script uses (by default) the rexxreqtools.library (which requires   *
  15.  * a version of reqtools larger than 2.0 and rexxsyslib.library)            *
  16.  * If you do not have these, you need to supply the NOREQ argument (for     *
  17.  * Shell output), or the QUIET argument (for no output at all).             *
  18.  *                                                                          *
  19.  * As of v2 of this script, and Scion V4, the current person on Scion's     *
  20.  * Personal Window will be used to determine where the search starts.       *
  21.  * Scion 3.13 can still be used, though, in which case the user will be     *
  22.  * asked at which IRN he wants to start.                                    *
  23.  *                                                                          *
  24.  * TO DO (mostly low priority, unless someone really wants this):           *
  25.  *  - find a good way to handle the people with sex '?'                     *
  26.  *  - count the number of lines output and give a linefeed after a certain  *
  27.  *    number (ie. skip page breaks)                                         *
  28.  *  - add a menu option for the maximum number of generations to print      *
  29.  *  - allow user to specify if he wants burial data printed, occupation,    *
  30.  *    comments, references fields, ....                                     *
  31.  *  - If the person has multiple marriages, output a list to the            *
  32.  *    screen and let the user select one (1..x), or all (0).                *
  33.  *  - Suggestions, comments, bugreports, donations, etc. are appreciated.   *
  34.  *                                                                          *
  35.  ****************************************************************************/
  36.  
  37. options results
  38. arg prtin outname noirn mgen outval
  39.  
  40. versionstr = "2.00"
  41. usereq = 1; /* change this to 0 if you don't want to use reqtools */
  42. outp = 1; useirn = 1; prtdev = stdout; prtopt = 0
  43. plwidth = 78;  /* linewidth of the printer */
  44. NL = '0A'x
  45. PSCR = 'SCIONGEN'; /* public screen to open the requesters on */
  46.  
  47. signal on IOERR
  48.  
  49. do while prtin = '?'
  50.   Tell("NUMOPT/A/N,OUTFILE/A,NOIRN/S,MAXGEN/N,NOREQ/S,QUIET/S: ")
  51.   pull prtin outname noirn mgen outval
  52. end
  53.  
  54. ParseArguments()
  55.  
  56. if usereq & ~show('l','rexxreqtools.library') then do
  57.   if exists('libs:rexxreqtools.library') then
  58.     call addlib('rexxreqtools.library',0,-30,0)
  59.   else do
  60.     usereq = 0; outp = 1
  61.     Tell("Unable to open rexxreqtools.library - using text output")
  62.   end
  63. end
  64.  
  65. /* These few lines were stolen from Peter Billings - thanks Peter ;-) */
  66. if ~show('P','SCIONGEN') then do
  67.   TermError('I am sorry to say that the SCION Genealogist' || NL ||,
  68.     'database is not available. Please start the' || NL ||,
  69.     'SCION program BEFORE using this script!')
  70. end
  71.  
  72. myport = "SCIONGEN"
  73. address value myport
  74. GETDBNAME
  75. dbname = upper(RESULT)
  76. fill = 7;        /* number of spaces at the beginning of lines */
  77. malesex = 'M';   /* as of V4, sexes are always 'M', 'F' or '?' */
  78. femalesex = 'F'
  79. GETPROGVERSION
  80. progvers = RESULT
  81.  
  82. if progvers >= 4 then do
  83.   GETCURRENTIRN
  84.   irn = RESULT
  85. end
  86.  
  87. if outp & ~usereq then do
  88.   Tell("*** PrintDescendant version "||versionstr||" ***")
  89.   Tell("***        by Freddy Ariës       ***")
  90.   Tell("Current database: "||dbname||NL)
  91. end
  92. if prtopt = 0 then do
  93.   if usereq then do
  94.     prtopt = rtezrequest('Current Scion database: '||dbname||NL||,
  95.       NL||'Please make your choice: '||,
  96.       NL||' 1. Descendant Chart - all descendants'||,
  97.       NL||' 2. Descendant Chart - male descendants'||,
  98.       NL||'    (mention daughters, without children)'||,
  99.       NL||' 3. Descendant Chart - male descendants'||,
  100.       NL||'    (leave out daughters)'||,
  101.       '',' _1 | _2 | _3 |E_xit','PrintDescendant v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  102.     if prtopt = 0 then
  103.       EXIT
  104.  
  105.     if progvers < 4 then do
  106.       irn = rtgetlong(,'Enter the IRN of the person whose'||,
  107.             NL||'descendants you want to print: '||,
  108.             NL,'Input Request:','_Continue','rt_pubscrname = '||PSCR)
  109.       if irn = '' then
  110.         EXIT
  111.       irn = abs(irn)
  112.     end
  113.  
  114.     useirn = rtezrequest('Do you want to output the IRNs'||,
  115.               NL||'(the record numbers) as well?'||,
  116.               '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  117.   end
  118.   else do
  119.     /* No use in asking for input if we're not allowed to output anything */
  120.     Tell("1. Descendant Chart - all descendants")
  121.     Tell("2. Descendant Chart - male descendants (mention daughters, without children)")
  122.     Tell("3. Descendant Chart - male descendants (leave out daughters)")
  123.     TellNN("Your choice: ")
  124.     pull prtopt
  125.     prtopt = CheckAnswer(prtopt)
  126.  
  127.     if progvers < 4 then do
  128.       TellNN("Enter the IRN of the person whose descendants you want to print: ")
  129.       pull irn
  130.     end
  131.  
  132.     TellNN("Do you want to output the IRNs (numbers) as well (y/n)? ")
  133.     pull instr
  134.     Tell("")
  135.     if left(instr, 1) = "Y" then useirn = 1
  136.     else useirn = 0
  137.   end
  138. end
  139.  
  140. if progvers < 4 then do
  141.   irn = CheckIRN(irn)
  142. end
  143.  
  144. EXISTPERSON irn
  145. if RESULT ~= 'YES' then
  146. do
  147.   if progvers >= 4 then
  148.     TermError("Unable to locate current person in the current database.")
  149.   else
  150.     TermError("No person with IRN "||irn||" in the current database.")
  151. end
  152.  
  153. if prtopt > 1 then do
  154.   GETSEX irn
  155.   parsex = RESULT
  156.   if prtopt = 3 & parsex = femalesex then
  157.     TermError("Person isn't male - nothing to print.")
  158. end
  159.  
  160. if outp then do
  161.   /* No use trying to get input if we're not allowed to ask anything */
  162.   pname = GetNameStr(irn, 0)
  163.   if prtopt = 1 | parsex = malesex then do
  164.     if usereq then do
  165.       valcont = rtezrequest('The selected person is: '||NL||pname||'.'||,
  166.         NL||'Continue?','_Continue| _Abort','PrintDescendant Request:','rt_pubscrname = '||PSCR)
  167.       if valcont = 0 then
  168.         EXIT
  169.     end
  170.     else do
  171.       TellNN("Current person is "||pname||". Continue? (y/n) ")
  172.       pull valcont
  173.       if left(valcont, 1) ~= 'Y' then
  174.         TermError("Ok.")
  175.     end
  176.   end
  177.   else do
  178.     /* with prtopt = 2, we would only print the (generation I) female and
  179.      * her husbands, but no children!
  180.      */
  181.     if usereq then do
  182.       valcont = rtezrequest("WARNING!!! Person "||NL||pname||,
  183.         NL||"is not male! Continue anyway?",'_Continue| _Abort','PrintDescendant Request:','rt_pubscrname = '||PSCR)
  184.       if valcont = 0 then
  185.         EXIT
  186.     end
  187.     else do
  188.       Tell("WARNING! Person "||pname||" isn't male!")
  189.       TellNN("Continue anyway? (y/n) ")
  190.       pull valcont
  191.       if left(valcont, 1) ~= 'Y' then
  192.         TermError("Ok.")
  193.     end
  194.   end
  195. end
  196.  
  197. /* TO DO: (at this location:)
  198.  * If the person has multiple marriages, output the spouse name, IRN
  199.  * and FGRN to screen, and let the user select one (1..x), or all (0)
  200.  */
  201.  
  202. if outp & outname = "" then do
  203.   if usereq then do
  204.     odev = rtezrequest('Current Scion database: '||dbname||,
  205.       NL||'Where should the output be sent to?'||,
  206.       NL,' _File |_Printer|_Screen|_Nowhere','PrintDescendant v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  207.     select
  208.       when odev = 1 then do
  209.         /* We need a file requester for further data */
  210.         dblen = length(dbname)
  211.         if dblen>6 & right(dbname, 6)=".SCION" then
  212.           dbname=left(dbname, dblen - 6)
  213.         outname = rtfilerequest(,dbname||'.DSC','Output filename',,'rtfi_buffer = true   rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
  214.         if outname = '' then
  215.           outname = dbname||'.DSC'
  216.       end
  217.       when odev = 2 then
  218.         outname = 'PRT:'
  219.       when odev = 3 then
  220.         outname = 'STDOUT'
  221.       otherwise
  222.         EXIT
  223.         /* You selected 'Nowhere' */
  224.     end
  225.   end
  226.   else do
  227.     Tell("Enter output file (filename with complete path, or PRT: for printer,")
  228.     TellNN("or STDOUT for screen): ")
  229.     pull outname
  230.     if outname = "" then
  231.       outname = "STDOUT"
  232.   end
  233. end
  234.  
  235. /* Anyone know a better way to translate numbers into Roman? */
  236. GenerationS.1 = "I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX"
  237. GenerationS.2 = "XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII IXL XL"
  238. MaxChild = 26
  239.  
  240. /* Printer Codes, some of which are currently unused: */
  241. ESC = '1B'x
  242. prtinit = ESC||"#1";     /* ESC#1 initialize      */
  243. prtundon = ESC||"[4m";   /* ESC[4m underline on   */
  244. prtundoff = ESC||"[24m"; /* ESC[24m underline off */
  245. prtdson = ESC||"[1m";    /* ESC[1m boldface on    */
  246. prtdsoff = ESC||"[22m";  /* ESC[22m boldface off  */
  247. prtnlqon = ESC||"[2"||'22'x||"z"; /* ESC[2"z NLQ on */
  248. prtnlqoff = ESC||"[1"||'22'x||"z"; /* ESC[1"z NLQ off */
  249.  
  250. if ~usereq then
  251.   Tell("Printing...")
  252.  
  253. OpenPrinter()
  254.  
  255. childnums = irn; childgens = "1"
  256. alcount = 0; chcount = 0
  257.  
  258. do while childnums ~= ""
  259.   irn = word(childnums, 1)
  260.   cgen = word(childgens, 1)
  261.   if cgen ~= currgen then do
  262.     alcount = 0
  263.     /* New generation: reset alfabet counter */
  264.     currgen = cgen
  265.     genchild = 0
  266.   end
  267.   childnums = delstr(childnums, 1, length(irn)+1)
  268.   childgens = delstr(childgens, 1, length(currgen)+1)
  269.  
  270.   ccnt = 1
  271.   /* Sex to use with options 2 and 3 */
  272.   GETSEX irn
  273.   parsex = RESULT
  274.  
  275.   g1 = GetPersonStr(irn)
  276.   mnum = 0
  277.   GETMARRIAGE irn mnum
  278.   fgrn = RESULT
  279.   EXISTFAMILY fgrn
  280.   ftrue = RESULT
  281.  
  282.   do while ftrue = 'YES'
  283.     m1 = GetMarriageStr(fgrn)
  284.     ptn = GetPartnerIRN(fgrn, irn)
  285.     if ptn ~= 0 then do
  286.       if m1 ~= "" then m1 = m1||' '
  287.       m1 = m1||GetPersonStr(ptn)
  288.     end
  289.     if m1 ~= "" then m1 = ", m: "||m1
  290.     if ccnt = 1 then do
  291.       ggs = GetGenStr(currgen, 0)
  292.       if currgen > 1 then do
  293.         alcount = alcount + 1
  294.     /* TO DO: only if this person has any siblings who have children,
  295.      *      or if there are other persons (with children) on this
  296.      *      generation
  297.      */
  298.         ggs = ggs||D2C(alcount+96)
  299.       end
  300.       ggs = left(ggs||".       ", fill)
  301.       m1 = ggs||g1||m1||'.'
  302.       ccnt = 0
  303.     end
  304.     else
  305.       m1 = copies(' ',fill)||g1||m1||'.'
  306.     PrintLines(m1, fill)
  307.     if prtopt ~= 3 | parsex = malesex then
  308.       chcount = chcount + PrintChildren(fgrn, parsex)
  309.     PrintLF()
  310.     mnum = mnum + 1
  311.     GETMARRIAGE irn mnum
  312.     fgrn = RESULT
  313.     EXISTFAMILY fgrn
  314.     ftrue = RESULT
  315.   end
  316.   if mnum = 0 then do
  317.     m1 = GetGenStr(currgen,fill)||g1
  318.     PrintLines(m1, fill)
  319.     if currgen = 1 then
  320.       PrintLines("No marriages are recorded for this person.", 0)
  321.     PrintLF()
  322.   end
  323. end
  324. if currgen = 1 & chcount = 0 then do
  325.   if prtopt = 1 then
  326.     PrintLines("No descendants are recorded for person.")
  327.   else 
  328.     PrintLines("No male descendants are recorded for person.")
  329. end
  330.  
  331. writeln(prtdev, prtnlqoff);
  332. close(prtdev)
  333. if usereq then
  334.   rtezrequest('Output ready.','E_xit','PrintDescendant Message:','rt_pubscrname = '||PSCR)
  335. else
  336.   Tell("Done.")
  337. EXIT
  338.  
  339. ParseArguments:
  340. if noirn = "NOIRN" then useirn = 0
  341. else if noirn = "QUIET" || noirn = "NOREQ" then do
  342.   outval = noirn
  343.   noirn = ""
  344. end
  345. else do
  346.   outval = mgen
  347.   mgen = noirn
  348.   noirn = ""
  349. end
  350. if mgen = "QUIET" || mgen = "NOREQ" then do
  351.   outval = mgen
  352.   mgen = ""
  353. end
  354.  
  355. MaxGens = 40; /* due to the Roman numbers, we can't handle more */
  356. if mgen ~= "" then do
  357.   if DATATYPE(mgen, 'w') & mgen > 0 & mgen < MaxGens then
  358.     MaxGens = mgen
  359. end
  360.  
  361. if outval = "QUIET" then do
  362.   usereq = 0
  363.   outp = 0
  364. end
  365. else if outval = "NOREQ" then
  366.   usereq = 0
  367.  
  368. if prtin = "" then do
  369.   prtopt = 0
  370.   if ~outp then TermError("Requires argument is missing.")
  371.     /* actually, with outp = 0, all it does is EXIT */
  372. end
  373. else do
  374.   prtopt = CheckAnswer(prtin)
  375.   /* Note that it was important to establish outp before calling these */
  376. end  
  377. return 0
  378.  
  379. OpenPrinter:
  380. /* Open the printer device and print out a nice header */
  381. if outname = "STDOUT" then
  382.   prtdev = stdout
  383. else do
  384.   prtdev = 'PRINTER'
  385.   if ~open(prtdev, outname, 'w') then
  386.     TermError("ERROR: Failed to open output file!")
  387. end
  388. writeln(prtdev, prtinit||prtnlqon)
  389. if prtopt = 1 then
  390.   prtstr = "DESCENDANT CHART - ALL DESCENDANTS"
  391. else if prtopt = 2 then
  392.   prtstr = "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE I)"
  393. else
  394.   prtstr = "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE II)"
  395. prtstr = prtundon||prtdson||prtstr||prtdsoff||prtundoff
  396. writeln(prtdev, prtstr)
  397. prtstr = prtdson||"Report printed on: "||date()||prtdsoff
  398. writeln(prtdev, prtstr)
  399. prtstr = copies('=', plwidth)
  400. writeln(prtdev, prtstr)
  401. return 0
  402.  
  403. PrintLines: PROCEDURE EXPOSE prtdev plwidth prtopt
  404. parse arg ostr, fill
  405. /* TO DO:
  406.  * if there are control strings within ostr (like prtdson or prtdsoff)
  407.  * don't include them in the length count
  408.  */
  409. do while ostr ~= ""
  410.   nnl = plwidth+1
  411.   if length(ostr) > plwidth then do
  412.     do until pc = ' ' | nnl = 1
  413.       pc = substr(ostr, nnl, 1)
  414.       nnl = nnl - 1
  415.     end
  416.     if nnl = 1 then do
  417.       prtstr = left(ostr, plwidth)
  418.       ostr = delstr(ostr, 1, nnl)
  419.     end
  420.     else do
  421.       prtstr = left(ostr, nnl)
  422.       ostr = delstr(ostr, 1, nnl+1)
  423.     end
  424.   end
  425.   else do
  426.     prtstr = ostr
  427.     ostr = ""
  428.   end
  429.   writeln(prtdev, prtstr)
  430.   if ostr ~= "" then
  431.     ostr = copies(' ',fill)||ostr
  432. end
  433. return 0
  434.  
  435. PrintLF:
  436. writeln(prtdev, "")
  437. return 1
  438.  
  439. PrintChildren:
  440. parse arg ffnum, parsx
  441. /* If we turn this into a PROCEDURE, we'll have to EXPOSE a lot!
  442.  * The disadvantage now is that we have to be extremely careful
  443.  * not to overwrite any global variables by accident!
  444.  */
  445. cidx = 0; cham = 0
  446. GETCHILD ffnum cidx
  447. chld = RESULT
  448. EXISTPERSON chld
  449. ctrue = RESULT
  450. nextgen = currgen + 1
  451. if nextgen > MaxGens then return cham
  452.   /* Maximum number of generations reached! */
  453. do while ctrue = 'YES'
  454.   cidx = cidx + 1
  455.   if prtopt > 1 then do
  456.     GETSEX chld
  457.     csx = RESULT
  458.   end
  459.   if prtopt ~= 3 | csx = malesex then do
  460.     cham = cham + 1
  461.     m1 = copies(' ',8)||cham||". "||GetChildStr(chld)
  462.     if (prtopt = 1 | csx = malesex) & HasChild(chld) then do
  463.       childnums = childnums||chld||' '
  464.       childgens = childgens||nextgen||' '
  465.       genchild = genchild + 1
  466.       if genchild > MaxChild then return 1
  467.       /* Maximum number of children reached! */
  468.       /* TO DO: if genchild = 1 and the current person has no siblings,
  469.        *    or none of his siblings have any children of their own,
  470.        *    and if there are no other persons with children on this
  471.        *    generation, then leave off the D2C part
  472.        */
  473.       m1 = m1||", see "||GetGenStr(nextgen, 0)||D2C(genchild+96)
  474.     end
  475.     else
  476.       m1 = m1||GetDeathStr(chld)||GetMarriages(chld)
  477.     PrintLines(m1||'.', 11)
  478.   end
  479.   GETCHILD ffnum cidx
  480.   chld = RESULT
  481.   EXISTPERSON chld
  482.   ctrue = RESULT
  483. end
  484. return cham
  485.  
  486. GetGenStr: PROCEDURE EXPOSE GenerationS.
  487. parse arg gnum, fill
  488. if gnum <= 20 then
  489.   gstr = word(GenerationS.1, gnum)
  490. else if gnum <= 40 then
  491.   gstr = word(GenerationS.2, gnum)
  492. else
  493.   return ""
  494. if fill > 0 then
  495.   gstr = left(gstr||".       ",fill)
  496. return gstr
  497.  
  498. GetPersonStr: PROCEDURE EXPOSE useirn
  499. parse arg irn
  500. if irn ~= 0 then do
  501.   nstr = GetNameStr(irn)
  502.   nstr = nstr||GetBirthStr(irn)
  503.   nstr = nstr||GetDeathStr(irn)
  504. end
  505. else
  506.   nstr = "UNKNOWN"
  507. return nstr
  508.  
  509. GetChildStr: PROCEDURE EXPOSE useirn
  510. parse arg irn
  511. if irn ~= 0 then do
  512.   nstr = GetNameStr(irn)
  513.   nstr = nstr||GetBirthStr(irn)
  514. end
  515. else
  516.   nstr = "UNKNOWN"
  517. return nstr
  518.  
  519. HasChild: PROCEDURE EXPOSE prtopt malesex
  520. parse arg irn
  521. mnum = 0
  522. GETMARRIAGE irn mnum
  523. marr = RESULT
  524. EXISTFAMILY marr
  525. mtrue = RESULT
  526. do while mtrue = 'YES'
  527.   chnxt = 0
  528.   GETCHILD marr chnxt
  529.   ch = RESULT
  530.   EXISTPERSON ch
  531.   ct = RESULT
  532.   if prtopt < 3 then do
  533.     if ct = 'YES' then return 1
  534.   end
  535.   else do
  536.     /* For option 3: search for male children */
  537.     do while ct = 'YES'
  538.       GETSEX ch
  539.       csx = RESULT
  540.       if csx = malesex then return 1
  541.       chnxt = chnxt + 1
  542.       GETCHILD marr chnxt
  543.       ch = RESULT
  544.       EXISTPERSON ch
  545.       ct = RESULT
  546.     end
  547.   end
  548.   mnum = mnum + 1
  549.   GETMARRIAGE irn mnum
  550.   marr = RESULT
  551.   EXISTFAMILY marr
  552.   mtrue = RESULT
  553. end
  554. return 0
  555.  
  556. GetNameStr: PROCEDURE EXPOSE useirn
  557. parse arg gnum
  558. GETFIRSTNAME gnum
  559. name = RESULT
  560. if name ~= "" then name = name||" "
  561. GETLASTNAME gnum
  562. lname = RESULT
  563. if lname = "" then lname = "UNKNOWN"
  564. name = name||lname
  565. if useirn then name = name||" ["gnum"]"
  566. return name
  567.  
  568. GetBirthStr: PROCEDURE
  569. parse arg gnum
  570. GETBIRTHPLACE gnum
  571. bstr = RESULT
  572. GETBIRTHDATE gnum
  573. bdat = RESULT
  574. if bdat ~= "" & bstr ~= "" then bstr = bstr||" "
  575. bstr = bstr||bdat
  576. if bstr ~= "" then bstr = ", b: "||bstr
  577. return bstr
  578.  
  579. GetDeathStr: PROCEDURE
  580. parse arg gnum
  581. GETDEATHPLACE gnum
  582. dstr = RESULT
  583. GETDEATHDATE gnum
  584. ddat = RESULT
  585. if ddat ~= "" & dstr ~= "" then dstr = dstr||" "
  586. dstr = dstr||ddat
  587. if dstr ~= "" then dstr = ", d: "||dstr
  588. return dstr
  589.  
  590. GetMarriages: PROCEDURE EXPOSE useirn
  591. parse arg irn
  592. mstr = ""
  593. GETMARRIAGE irn 0
  594. mf = RESULT
  595. EXISTFAMILY mf
  596. if RESULT = 'YES' then do
  597.   mtrue = 1
  598.   GETMARRIAGE irn 1
  599.   m2 = RESULT
  600.   EXISTFAMILY m2
  601.   if RESULT = 'YES' then mset = 1
  602.   else mset = 0
  603. end
  604. else
  605.   mtrue = 0  
  606. mnum = 0
  607. do while mtrue
  608.   m1 = GetMarriageStr(mf)
  609.   if m1 ~= "" then m1  = m1||' '
  610.   ptn = GetPartnerIRN(mf, irn)
  611.   m1 = m1||GetPersonStr(ptn)
  612.  
  613.   if mset then mstr = ", m("||mnum||"): "||m1
  614.   else mstr = ", m: "||m1
  615.  
  616.   mnum = mnum + 1    
  617.   GETMARRIAGE irn mnum
  618.   mf = RESULT
  619.   EXISTFAMILY mf
  620.   if RESULT ~= 'YES' then mtrue = 0
  621. end
  622. return mstr
  623.  
  624. GetMarriageStr: PROCEDURE
  625. parse arg mf
  626. GETMARRYPLACE mf
  627. mstr = RESULT
  628. GETMARRYDATE mf
  629. mdat = RESULT
  630. if mdat ~= "" & mstr ~= "" then mstr = mstr||" "
  631. mstr = mstr||mdat
  632. return mstr
  633.  
  634. GetPartnerIRN: PROCEDURE
  635. parse arg fnum, inum
  636. GETPRINCIPAL fnum
  637. prn = RESULT
  638. GETSPOUSE fnum
  639. sps = RESULT
  640. if inum = prn then pnum = sps
  641. else if inum = sps then pnum = prn
  642. else pnum = 0
  643. EXISTPERSON pnum
  644. if RESULT ~= 'YES' then pnum = 0
  645. return pnum
  646.  
  647. CheckAnswer: PROCEDURE EXPOSE outp prtdev
  648. parse arg str
  649. str = left(str, 1)
  650. if ~DATATYPE(str, 'w') then
  651.   TermError("Arg(1): not a valid option number.")
  652. if str < 1 | str > 3 then
  653.   TermError("Arg(1): not a valid option number.")
  654. return str
  655.  
  656. CheckIRN: PROCEDURE EXPOSE outp prtdev
  657. parse arg str
  658. if ~DATATYPE(str, 'w') then
  659.   TermError("Arg(2): not a valid IRN.")
  660. return str
  661.  
  662. Tell: PROCEDURE EXPOSE outp
  663. parse arg str
  664. if outp then
  665.   writeln(stdout, str)
  666. return 0
  667.  
  668. TellNN: PROCEDURE EXPOSE outp
  669. parse arg str
  670. if outp then
  671.   writech(stdout, str)
  672. return 0
  673.  
  674. TermError: PROCEDURE EXPOSE outp prtdev usereq PSCR
  675. parse arg str
  676. /* If you turned off stdout, no error messages will be shown! */
  677. if usereq then
  678.   rtezrequest(str,'E_xit','PrintDescendant Message:','rt_pubscrname = '||PSCR)
  679. else do
  680.   Tell(str || '0A'x)
  681. end
  682. close(prtdev)
  683. EXIT
  684.  
  685. /* Let's make sure you get a nice message when you turn off the printer :-) */
  686.  
  687. IOERR:
  688. bline = SIGL
  689. say "I/O error #"||RC||" detected in line "||bline||":"
  690. say sourceline(bline)
  691. EXIT
  692.