1/*
2 * @progname    BW_descendants.ll
3 * @version     1.00
4 * @author      Birger Wathne
5 * @category
6 * @output      Text
7 * @description
8 *              List successors with notes
9
10BW_descendants - a LifeLines report by Birger Wathne (Birger.Wathne@sdata.no)
11
12Version 1.00
13This program partially based on code by Brad Frecker and Dick Knowles.
14Suggestions and comments welcome.
15
16
17Output sample at bottom of this source file.
18
19This report generates a list of successors of the given person. For each
20successor and its spouse(s), all level 1 notes are listed.
21
22The report asks for some parameters:
23- Number of generations to include (0 gives all)
24- Amount of output for spouse's other families
25        0 - Only list the main person's marriages. Don't even mention
26            the fact that the spouse(s) have had other relationships.
27        1 - Print a one-line summary for each of the spouse's other
28            relationships (number of children, spouses name, etc)
29        2 - Print the one-liner from option 1, plus a full listing of
30            all stepchildren (not recursive)
31- Output type
32        0 - Text. Plain ascii output (like the sample)
33        1 - roff. Not finished, as I don't have an 8-bit clean roff.
34            If someone wants this, please finish it, and send me the code.
35        2 - HTML. This output uses <TABLE> tags, so you need HTML 3.0 support.
36            Uses bold fonts, etc. Nice....
37- Language for generated text. The header, and all those small words
38  used in the output can be generated in the language you have your
39  data. Makes it look more natural. If you add new languages, please tell me.
40*/
41
42global(strings)
43global(outputtype)
44global(true)
45global(false)
46
47func init_strings(language) {
48        if ( eq( language, 0)) {
49                insert(strings, "Header", "Successors of")
50                insert(strings, "Headerdate", "Date")
51                insert(strings, "Born", "Born")
52                insert(strings, "Dead", "Dead")
53                insert(strings, "Married", "Married")
54                insert(strings, "Relationship", "Relationship")
55                insert(strings, "with", "with")
56                insert(strings, "unknownspouse", "unknown spouse")
57                insert(strings, "descendants", "descendants")
58                insert(strings, "generations", "generations")
59                insert(strings, "children", "children")
60                insert(strings, "had", "had")
61                insert(strings, "all", "all")
62                insert(strings, "Notesfor", "Notes for")
63
64                return(0)
65        }
66
67        if ( eq( language, 1)) {
68                insert(strings, "Header", "Etterkommere etter")
69                insert(strings, "Headerdate", "Dato")
70                insert(strings, "Born", "F�dt")
71                insert(strings, "Dead", "D�d")
72                insert(strings, "Married", "Gift")
73                insert(strings, "Relationship", "Forhold")
74                insert(strings, "with", "med")
75                insert(strings, "unknownspouse", "ukjent ektefelle")
76                insert(strings, "descendants", "etterkommere")
77                insert(strings, "generations", "generasjoner")
78                insert(strings, "children", "barn")
79                insert(strings, "had", "hadde")
80                insert(strings, "all", "alle")
81                insert(strings, "Notesfor", "Notater for")
82
83                return(0)
84        }
85
86        return(1)
87}
88
89
90proc main () {
91        table(strings)
92
93        set(true, 1)
94        set(false, 0)
95
96        dayformat(0)
97        monthformat(4)
98        dateformat(0)
99
100        getindi(indi)
101
102        getintmsg (generation_count, "How many generations (0 for all)?")
103        if ( lt( generation_count, 0)) {
104                print("Illegal number of generations")
105                return()
106        }
107
108        getintmsg (
109                spousefamilies,
110                "How much output for spouse's other families (0=none, 1=summary, 2=list children)?"
111        )
112        if ( or( lt( spousefamilies, 0), gt( spousefamilies, 2))) {
113                print("Illegal answer")
114                return()
115        }
116
117        getintmsg(outputtype, "Output type (0=TEXT, 1=ROFF, 2=HTML)?")
118        if ( or( lt( outputtype, 0), gt( outputtype, 2))) {
119                print("Illegal output type")
120                return()
121        }
122
123
124        getintmsg(
125                language,
126                "Language for generated text (0=English, 1=Norwegian)?"
127        )
128        if ( ne( init_strings(language), 0)) {
129                print("Couldn't initialize string table to selected language")
130                return()
131        }
132
133        output_init()
134        /* Headers */
135        if ( eq( generation_count, 0)) {
136                output_header1 (
137                        concat(
138                                lookup( strings, "Header")," ",
139                                name(indi), " ",
140                                lookup( strings, "with"), " ",
141                                lookup( strings, "all"), " ",
142                                lookup( strings, "descendants")
143                        )
144                )
145        } else {
146                if ( eq( generation_count, 1)) {
147                        output_header1 (
148                                concat(
149                                        lookup( strings, "Header"), " ",
150                                        name(indi), " "
151                                )
152                        )
153                } else {
154                        output_header1 (
155                                concat(
156                                        lookup( strings, "Header"), " ",
157                                        name(indi), " ",
158                                        lookup( strings, "with"), " ",
159                                        d(sub(generation_count,1)), " ",
160                                        lookup( strings, "generations"), " ",
161                                        lookup( strings, "descendants")
162                                )
163                        )
164                }
165        }
166        nl() nl()
167
168        output_header2(
169                concat(
170                        lookup( strings, "Headerdate"), ": ",
171                        stddate(gettoday())
172                )
173        )
174        nl() nl()
175
176        call descendants(indi, "1", generation_count, spousefamilies)
177        output_terminate()
178}
179
180
181
182proc descendants (indi, number, generation_count, spousefamilies) {
183        output_startpara()
184        number output_linebreak()
185        call print_person(indi, 1)
186
187        call write_notes(indi)
188
189        set(childnumber, 0)
190
191        families(indi, family, spouse, i) {
192                if(e, marriage(family)) {
193                        lookup( strings, "Married") " " stddate(e)
194                } else {
195                        lookup( strings, "Relationship")
196                }
197
198                if ( ne( spouse, null)) {
199                        " " lookup( strings, "with") " "
200                        call print_person(spouse, 1)
201                } else {
202                        " " lookup( strings, "with") " "
203                        lookup( strings, "unknownspouse")
204                }
205
206                if ( ne(spousefamilies, 0)) {
207                        families(spouse, spfamily, spspouse, j) {
208                                if (ne(family, spfamily)) {
209                                        name(spouse) " "
210                                        lookup( strings, "had") " "
211                                        d(nchildren(spfamily)) " "
212                                        lookup( strings, "children")
213                                        if ( ne( spspouse, null)) {
214                                                " " lookup( strings, "with") " "
215                                                call print_person(spspouse, 0)
216                                        } else {
217                                                " " lookup( strings, "with") " "
218                                                lookup( strings, "unknownspouse")
219                                        }
220                                        if( eq(spousefamilies, 2)) {
221                                                output_leftin()
222                                                children(spfamily, child, k) {
223                                                        "\t"
224                                                        call print_person(child, 0)
225                                                }
226                                                output_leftout()
227                                        }
228                                }
229                        }
230                }
231
232                call write_notes(spouse)
233
234                output_leftin()
235                children(family, child, j) {
236                        "\t" number "." d(add(j, childnumber)) nl() "\t"
237                        call print_person(child, 1)
238                }
239                output_leftout()
240                set(childnumber, add(childnumber, j))
241        }
242
243        output_endpara()
244
245        set(childnumber, 0)
246
247        families(indi, family, spouse, i) {
248                if (ne(1, generation_count)) {
249                        if ( gt(generation_count, 1)) {
250                                decr(generation_count)
251                        }
252                        children(family, child, j) {
253                                call descendants (
254                                        child,
255                                        strconcat(
256                                                number, ".",
257                                                d(add(j, childnumber))
258                                        ),
259                                        generation_count, spousefamilies)
260                        }
261                        set(childnumber, add(childnumber, j))
262                }
263        }
264
265}
266
267
268
269proc write_notes(indi) {
270        set(done_header, 0)
271        fornodes(inode(indi), node) {
272                if (eq(0,strcmp("FILE", tag(node)))) {
273                        if ( eq(done_header, 0) ) {
274                                lookup( strings, "Notesfor") " "
275                                name(indi) ":" output_linebreak()
276                                incr(done_header)
277                        }
278                        copyfile(value(node))
279                } elsif (eq(0,strcmp("NOTE", tag(node)))) {
280                        if ( eq(done_header, 0) ) {
281                                lookup( strings, "Notesfor") " "
282                                name(indi) ":" output_linebreak()
283                                incr(done_header)
284                        }
285                        value(node)
286                        fornodes(node, subnode) {
287                                if (eq(0,strcmp("CONT", tag(subnode)))) {
288                                        nl() value(subnode)
289                                }
290                        }
291                        output_linebreak()
292                }
293        }
294}
295
296
297proc print_person (indi, bold) {
298        if(bold) {
299                output_bold( name(indi))
300        } else {
301                name(indi)
302        }
303        if (e, stddate(birth(indi))) {
304                ", " lookup( strings, "Born") " " e
305        }
306        if(e, stddate(death(indi))) {
307                ", " lookup( strings, "Dead") " " e
308        }
309        "." output_linebreak()
310}
311
312
313func output_header1 (string) {
314        if ( eq( outputtype, 1)) {
315                return(concat( ".(b C", nl(), ".ps 16", nl(), "\\fB",
316                        split(string), "\\fP", nl(),
317                        ".ps 8", nl(), ".)b", nl()))
318        }
319        if ( eq( outputtype, 2)) {
320                return(concat( "<H1>", string, "</H1>"))
321        }
322        return(string)
323}
324
325func output_header2 (string) {
326        if ( eq( outputtype, 1)) {
327                return(concat( ".(b C", nl(), ".ps 12", nl(), "\\fB",
328                        string, "\\fP", nl(),
329                        ".ps 8", nl(), ".)b", nl()))
330        }
331        if ( eq( outputtype, 2)) {
332                return(concat( "<H2>", string, "</H2>"))
333        }
334        return(string)
335}
336
337
338func output_init () {
339        if ( eq( outputtype, 1)) {
340                return(concat( ".po 0.8i", nl(), ".ll 6.8i", nl(),
341                        ".pl +1.5i", nl(), ".nf", nl(), ".ps 8", nl()))
342        }
343        if ( eq( outputtype, 2)) {
344                return(concat("<HTML><HEAD><TITLE>Descendant chart</TITLE></HEAD><BODY>", nl() ))
345        }
346}
347
348
349func output_terminate () {
350        if ( eq( outputtype, 2)) {
351                return("</BODY></HTML>")
352        }
353}
354
355
356func output_linebreak () {
357        if ( eq( outputtype, 1)) {
358                return(nl())
359        }
360        if ( eq( outputtype, 2)) {
361                return("<BR>")
362        }
363        return(nl())
364}
365
366
367func output_startpara () {
368        if ( eq( outputtype, 2)) {
369                return("<P>")
370        }
371}
372
373
374func output_endpara () {
375        if ( eq( outputtype, 2)) {
376                return("</P>")
377        }
378        return(concat( output_linebreak(), output_linebreak()))
379}
380
381func output_bold (string) {
382        if ( eq( outputtype, 1)) {
383                return(concat( "\\fB", string, "\\fP"))
384        }
385        if ( eq( outputtype, 2)) {
386                return(concat( "<B>", string, "</B>"))
387        }
388        return(string)
389}
390
391
392func output_leftin () {
393        if ( eq( outputtype, 2)) {
394                return(concat( "<TABLE WIDTH=100%><TR><TD WIDTH=5%></TD><TD>"))
395        }
396}
397
398
399func output_leftout () {
400        if ( eq( outputtype, 2)) {
401                return(concat( "</TD></TR></TABLE>"))
402        }
403}
404
405
406func split(string) {
407        set(i, 1)
408        set(tmpstr, "")
409        while( ne( i, strlen(string))) {
410                if ( nestr( substring( string, i, i), " ")) {
411                        set(tmpstr, concat(tmpstr, substring( string, i, i)))
412                } else {
413                        set(tmpstr, concat(tmpstr, "\\0"))
414                }
415                incr(i)
416        }
417        return (tmpstr)
418}
419
420
421/* Sample output:
422
423
424Successors of N.N. Helgesdtr. �SE with 2 generations descendants
425
426Date: 14 Jun 1995
427
4281
429N.N. Helgesdtr. �SE.
430Relationship with Tjeran Hallvardson (Halldors.) VASSHUS, Born        1610.
431Notes for Tjeran Hallvardson (Halldors.) VASSHUS:
432Er nevnt som leilending i 1635 sammen med Helge �se som sannsynligvis var
433hans svigerfar.
434Tjeran og broren Rasmus stevnet stefaren Laurits Asserson for odelsgods i
435Kluge, Gjesdal som deres mor eide.
436        1.1
437        Lars Tjeranson �SE, Born        1643, Dead  9 Jun 1702.
438        1.2
439        Marite Tjerandsdtr. �SE, Dead        1691.
440        1.3
441        Hallvard TJERANSON, Born        1651.
442        1.4
443        Helge TJERANSON, Born        1654.
444
445
4461.1
447Lars Tjeranson �SE, Born        1643, Dead  9 Jun 1702.
448Notes for Lars Tjeranson �SE:
449Gift I med Kirsti Olsdtr. Malmeim (f.1665 d.12.04.1695).
450II med Johanna Gunnarsdtr. Sveinsvoll (d.1741).
451Lars hadde v�rt soldat i 10 �r. 2 barn kjent.
452
453
4541.2
455Marite Tjerandsdtr. �SE, Dead        1691.
456Relationship with Ola Olson KJOSAVIK, Born        1623, Dead  9     1702.
457Ola Olson KJOSAVIK had 7 children with KariI Pedersdtr., Born 16     , Dead        1674.
458Ola Olson KJOSAVIK had 1 children with KariII Torkellsdtr. ALSNES, Born        1661, Dead 30 Mar 1705.
459Notes for Ola Olson KJOSAVIK:
4607 barn av f�rste ekteskap, 3 av andre og 1 av tredje ekteskap.
461        1.2.1
462        Berit Olsdtr. KJOSAVIK, Born        1674, Dead        1746.
463        1.2.2
464        Kristoffer Olson KJOSAVIK, Born        1677.
465        1.2.3
466        Ola O. KJOSAVIK, Born        1681, Dead 23     1695.
467
468.
469.
470.
471
472*/
473