home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / rexx / ScionRexx.lha / PrintDescendant.rexx < prev    next >
OS/2 REXX Batch file  |  1995-10-31  |  22KB  |  766 lines

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