home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / geneal / part03 / family.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  9KB  |  334 lines

  1. /* family.c - produce a family information page
  2.  * Written by Jim McBeath (jimmc) at SCI
  3.  *
  4.  * Revision history:
  5.  * 24-Jan-85    Jim McBeath    Remove redundant declaration of gendp
  6.  * 27-Jan-85    Jim McBeath    Use fgbslist; change fgclist to bclist
  7.  * 29-Jan-85    Jim McBeath    convert to 7-char-distinct names
  8.  * 14-Feb-85    (Ian Darwin)    remove mnumstr (unused variable)
  9.  * 24.Aug.87  jimmc  Add Label stuff, add BUR info
  10.  * 14.Sep.87  jimmc  Add addr stuff
  11.  * 27.Oct.87  jimmc  General cleanup; call fggen to get GEN info
  12.  *  4.Jan.88  jimmc  Make printindented not static
  13.  *  8.Jan.88  jimmc  Allow lists of families to be printed
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include "geneal.h"
  19. #include "pagemap.h"
  20.  
  21. #define PAGEWID 80
  22. #define LEFTMARGIN 4
  23. #define RIGHTMARGIN 4
  24. #define CENTERMARGIN 2
  25. #define LEFTCOL ((PAGEWID-LEFTMARGIN-RIGHTMARGIN-CENTERMARGIN)/2)
  26. #define RIGHTCOL (PAGEWID-LEFTMARGIN-RIGHTMARGIN-CENTERMARGIN-LEFTCOL)
  27. #define ADDRCOL (LEFTMARGIN+20)
  28. #define SPOUSEOFFSET 10
  29.  
  30. #define TBLOCKSIZE 1000
  31. #define NOTEMAX 500
  32.  
  33. struct tblock {        /* a text block */
  34.     int width;        /* length of longest line */
  35.     int lines;        /* number of lines */
  36.     char *text[TBLOCKSIZE];    /* the text pointers */
  37. };
  38.  
  39. extern int dataStatus;
  40. extern char *dataErrStrs[];
  41. extern char *Label;
  42.  
  43. int notenum;
  44. int notecount;        /* for storing the footnotes */
  45. char *notes[NOTEMAX];
  46.  
  47. printindented(indent,str)
  48. int indent;
  49. char *str;
  50. {
  51.     if (!str || !str[0]) return;
  52.     fprintf(outfp,"%*s", indent, "");
  53.     for (; *str; str++) {
  54.         if (*str == '\n') {
  55.             fprintf(outfp,"\n%*s", indent, "");
  56.         }
  57.         else putc(*str,outfp);
  58.     }
  59.     putc('\n',outfp);
  60. }
  61.  
  62. /*..........*/
  63.  
  64. int            /* 0 if all OK */
  65. family(ac,av)
  66. int ac;            /* number of families */
  67. int *av;        /* list of family id numbers */
  68. {
  69.     int i,t;
  70.  
  71.     t = 0;
  72.     for (i=0; i<ac; i++) {
  73.         if (i>0) fprintf(outfp,sepstr);
  74.         t += family1(av[i]);
  75.     }
  76.     return t;
  77. }
  78.  
  79. /*..........*/
  80.  
  81. int            /* 0 if OK */
  82. family1(famnum)
  83. int famnum;            /* the family to give info about */
  84. {
  85.     int rtype;
  86.     char *famname, *husname, *wifename;
  87.     char *huslname, *wifelname;
  88.     int husnum, wifenum;
  89.     char *headerline;
  90.     int i, cnum, clist[1000];
  91.     char *ss;
  92.     int addrnum;
  93.     char *addr;
  94.     char *phone;
  95.  
  96.     notecount=notenum=0;
  97.     rtype = fgtype(famnum);
  98.     if (rtype<=0) {
  99.         warning("no such record number %d", famnum);
  100.         return 1;
  101.     }
  102.     if (rtype!='F') {
  103.         warning("record %d is not a family", famnum);
  104.         return 1;
  105.     }
  106.     famname = fgstr(famnum,"N");        /* get the family name */
  107.     husnum = fgnum(famnum,"H");    /* get husband and wife index nums */
  108.     wifenum = fgnum(famnum,"W");
  109.     husname = fgbname(husnum);
  110.     wifename = fgbname(wifenum);
  111.     huslname = fgstr(husnum,"LN");
  112.     wifelname = fgstr(wifenum,"LNM");
  113.  
  114.     if (wifelname==0 || wifelname[0]==0) wifelname = fgstr(wifenum,"LN");
  115.  
  116.     if (huslname && huslname[0]==0) huslname=0;
  117.     if (wifelname && wifelname[0]==0) wifelname=0;
  118.     if (famname && famname[0]==0) famname=0;
  119.     if (husname==0 || husname[0]==0) husname = "???";
  120.     if (wifename==0 || wifename[0]==0) wifename = "???";
  121.     if (famname && (huslname==0 || strcmp(famname,huslname)!=0))
  122.         headerline =
  123.             tprintf("%s - %s & %s", famname, husname, wifename);
  124.     else
  125.         headerline = tprintf("%s & %s", husname, wifename);
  126.     strup(headerline);
  127.     if (Gflag['N'] && Gflag['n']) {
  128.         ss = tprintf("[%d]: %s",famnum,headerline);
  129.         free(headerline);
  130.         headerline = ss;
  131.     }
  132.     printindented(LEFTMARGIN,Label);
  133.     printindented(LEFTMARGIN,headerline);
  134.     fprintf(outfp,"\n");
  135.     printpair(0,famnum,husnum, wifenum);    /* print data about parents */
  136.  
  137.     addrnum = fgnum(famnum,"ADDR");
  138.     if (Gflag['a'] && addrnum>0) {    /* print address if known */
  139.         addr = fgstr(addrnum,"ADDR");
  140.         printindented(ADDRCOL,addr);
  141.         phone = fgstr(addrnum,"PHONE");
  142.         printindented(ADDRCOL,phone);
  143.         fprintf(outfp,"\n");
  144.     }
  145.  
  146.     cnum = fgbclist(famnum,clist);
  147.     if (cnum==0) {
  148. #if 0        /* be silent about no children... */
  149.         printindented(LEFTMARGIN,"NO CHILDREN");
  150. #endif
  151.     }
  152.     else {
  153.         fprintf(outfp,"%*s%*s%*s%s\n\n",
  154.             LEFTMARGIN, "", -LEFTCOL, "CHILDREN",
  155.             CENTERMARGIN, "", "SPOUSES OF CHILDREN");
  156.         for (i=0; i<cnum; i++) {
  157.             int childnum, mgnum, spousenum, chusnum, cwifenum;
  158.             int scount,slist[1000],mnum;
  159.  
  160.             childnum = clist[i];
  161.             scount = fgbslist(childnum,slist);
  162.             for (mnum=0; mnum<scount; mnum++) {
  163.                 /* until we run out of marriages */
  164.                 mgnum = slist[mnum];
  165.                 chusnum = fgnum(mgnum, "H");
  166.                 cwifenum = fgnum(mgnum, "W");
  167.                 if (childnum==chusnum) spousenum=cwifenum;
  168.                 else if (childnum==cwifenum) spousenum=chusnum;
  169.                 else {
  170. warning("person %d claims marriage %d, but not vice-versa!",
  171.                         childnum, mgnum);
  172.                     spousenum= -1;
  173.                 }
  174.                 printpair(mnum,mgnum,childnum,spousenum);
  175.             }
  176.             if (scount==0) printpair(0,-1,childnum,-1);
  177.                 /* print the individual if no marriage */
  178.         }
  179.     }
  180.     if (notecount>0) {        /* if we accumulated any notes */
  181.         printindented(LEFTMARGIN, "-----------------------");
  182.         for (i=0; i<notecount; i++)
  183.             printindented(LEFTMARGIN, notes[i]);
  184.     }
  185.     return 0;
  186. }
  187.  
  188. /*..........*/
  189.  
  190. printpair(n,mn,cn,sn)    /* print info about a couple */
  191. int n;            /* which marriage in the list this is; -1=only one */
  192. int mn;            /* marriage number */
  193. int cn;            /* primary person number */
  194. int sn;            /* spouse number */
  195. {
  196.     struct tblock cntb, sntb;    /* where to store data */
  197.     int i, max;
  198.  
  199.     fampdat(n,mn,cn,&cntb);        /* get the data */
  200.     fampdat(-1,mn,sn,&sntb);
  201.     /* decide if they should both be on the same lines or not */
  202.     if (cntb.width>LEFTCOL || sntb.width>RIGHTCOL) { /* separate */
  203.         printtb(&cntb,LEFTMARGIN);    /* output the first one */
  204.         printtb(&sntb,LEFTMARGIN+SPOUSEOFFSET);    /* output spouse */
  205.     }
  206.     else {    /* both on the same line */
  207.         if (cntb.lines > sntb.lines) max = cntb.lines;
  208.         else max = sntb.lines;
  209.         for (i=0; i<max; i++) {
  210.             if (i>=cntb.lines)
  211.                 printindented(
  212.                     -(LEFTMARGIN+CENTERMARGIN+LEFTCOL),
  213.                     sntb.text[i]);
  214.             else if (i>=sntb.lines)
  215.                 printindented(LEFTMARGIN, cntb.text[i]);
  216.             else
  217. /*** Problems here if field in database was > 1 line */
  218.                 fprintf(outfp,"%*s%*s%*s%s\n", LEFTMARGIN, "",
  219.                     -LEFTCOL, cntb.text[i], CENTERMARGIN,
  220.                     "", sntb.text[i]);
  221.         }
  222.         fprintf(outfp,"\n");
  223.     }
  224. }
  225.  
  226. /*..........*/
  227.  
  228. printtb(b,offset)        /* print a text block */
  229. struct tblock *b;
  230. int offset;            /* left margin offset */
  231. {
  232.     int i;
  233.  
  234.     for (i=0; i<b->lines; i++)
  235.         printindented(offset, b->text[i]);
  236.     if (b->lines!=0) fprintf(outfp,"\n");
  237. }
  238.  
  239. /*..........*/
  240.  
  241. fampdat(i,m,n,b)        /* get a tblock about a person */
  242. int i;            /* iteration number to determine how to format */
  243. int m;            /* marriage number */
  244. int n;            /* the person to get info about */
  245. struct tblock *b;    /* where to put the data */
  246. {
  247.     char *name, *birth, *death, *buried, *marriage;
  248.  
  249.     b->lines = b->width = 0;    /* clear it out first */
  250.     if (n<=0) return;
  251.     name = fgbname(n);
  252.     birth = fgbirth(n);
  253.     death = fgdeath(n);
  254.     buried = fgburied(n);
  255.     marriage = fgnmarriage(m);
  256.     if (i<=0) {
  257.         addtline(name,b);
  258.         if (birth && *birth) addtline(birth,b);
  259.         if (death && *death) addtline(death,b);
  260.         if (buried && *buried) addtline(buried,b);
  261.         if (i==0) {
  262.             if (marriage && *marriage) addtline(marriage,b);
  263.             addnots(n,m,b);        /* add general comment notes */
  264.         }
  265.         else    /* i== -1 */
  266.             addnots(n,-1,b);    /* don't add marriage notes */
  267.     }
  268.     else {
  269.         if (marriage && *marriage)
  270.             marriage = tprintf("re-%s", marriage);
  271.         else marriage = "remarried:";
  272.         addtline(marriage,b);
  273.         addnots(-1,m,b);
  274.     }
  275. }
  276.  
  277. /*..........*/
  278.  
  279. addnots(n,m,b)        /* add general comment notes to a block */
  280. int n;            /* index of person */
  281. int m;            /* index of marriage */
  282. struct tblock *b;    /* text block to add to */
  283. {
  284.     addnote(n,b,"");
  285.     addnote(m,b," (m)");
  286. }
  287.  
  288. /*..........*/
  289.  
  290. addnote(n,b,ss)        /* add general comment notes to a block */
  291. int n;            /* index of person */
  292. struct tblock *b;    /* text block to add to */
  293. char *ss;        /* note indicator string */
  294. {
  295.     char *gencom;
  296.     int lcount;
  297.     int hlen;
  298.     int t;
  299.  
  300.     lcount = 0;
  301.     hlen = strlen(ss)+sizeof("Note")+2;
  302.     gencom = fggen(n);
  303.     lcount += countlines(gencom);
  304.     if (lcount==1 && ((t=strlen(gencom)+hlen)<=b->width||t<LEFTCOL)) {
  305.         /* if we have one relatively short string, do it in-line */
  306.         addtline(tprintf("[Note%s: %s]", ss, gencom),b);
  307.     }
  308.     else if (lcount>0) {
  309.         addtline(tprintf("[Note %d%s]", 1+notenum, ss),b);
  310.         notes[notecount++] = tprintf("Note %d%s:", 1+notenum++, ss);
  311.         notes[notecount++] = gencom;    /* add string to notes */
  312.         notes[notecount++] = "";
  313.     }
  314. }
  315.  
  316. /*..........*/
  317.  
  318. addtline(ss,b)            /* add a line to a tblock */
  319. char *ss;            /* the string to add */
  320. struct tblock *b;        /* the block to add to */
  321. {
  322.     int l;
  323.  
  324.     if (b->lines >= TBLOCKSIZE) {
  325.         warning("tblock overflow!");
  326.         return;            /* ignore the addition */
  327.     }
  328.     b->text[b->lines++] = ss;    /* add in the string */
  329.     l = strlen(ss);
  330.     if (l> b->width) b->width=l;    /* keep track of width */
  331. }
  332.  
  333. /* end */
  334.