#include #include #include #include #include #define MAXNRC 55 // Used in printper for positioning output #define MAXKEY 21 // Max length of keyword #define MAXVAL 401 // Max length of an info field #define MAXBUF 1201 // Max amt of info entered in one set #define MAXNAM 31 // Max length of std name #define MAXHUM 2000 // Max number of people mentioned #define MAXREL 900 // Max people in an individual's family tree static struct pmenu query = { NULL, FALSE, 0, 1, 7, { 1,16, "FAMILY TREE OPTIONS" ,0, 3, 4, "1 Long Output for Everyone in Database" ,1, 4, 4, "2 Long Output for All Kinfolk of a Person" ,4, 5, 4, "3 Long Output for Ancestors of a Person" ,2, 6, 4, "4 Long Output for Offspring of a Person" ,3, 7, 4, "5 Make List of Ancestors of a Person" ,5, 8, 4, "6 Make List of Offspring of a Person" ,6, 9, 4, "7 View Output" ,7, 11, 4, "Press ESC to Quit, or Select with Cursor Keys",0, 12, 4, "Then Press Enter." ,0, 99,99,"",99} }; WINDOWPTR w1,w2,wsav1; FILE *inn, *out, *msg; typedef struct person *human; typedef struct name *tag; typedef struct marriage *bliss; typedef struct child *issue; void putvalue(human you, char *keywd, char *value); human palloc(void); bliss mmalloc(void); issue challoc(void); tag nalloc(void); char *parse(char *str, char *token); human addtree(human p, char *w); void printper(human you, int flag); void treeprint(human p); void addchild(human you, human baby); void addparent(human parent, human baby, char sex); void gatherAll(human p); void heapsort(int n, human *ra); char *getname(human p); char *dayt(char *date); char *aged(human who); int validate(char *date); char *demise(human you); void printdat(human you); void anctree(human p, int level); void getAncs(human p); human getptr(char *name); void desctree(human you, int level); void getDesc(human p); void leave(void); void getRel(human p); void getAncDesc(human you); struct person {tag std; human left; human right; human father; human mother; char *dtborn; char *dtdied; char *plborn; char *pldied; char *plbury; bliss spouse; char *persnote; char sex; int number; }; struct name{char *name; tag next; }; struct marriage{human husband; human wife; char *dtmarr; char *plmarr; char *marrnote; issue kid; bliss newHusband; bliss newWife; }; struct child{human name; issue next; }; human root, kin, you, list[MAXHUM], reltiv[MAXREL]; int count, nancs, ndesc, nrel; void main(int argc, char *argv[]) { char inname[13], outname[13], keywd[MAXKEY], value[MAXVAL], Name[MAXNAM], line[81],*ptr,*saveptr,*chr; int ii,flag,ntimes=0,nx,neof=0,wat,bat,option,wat2,bat2; wn_init(); bat = (BLUE << 4) | WHITE; // border attrib wat = (WHITE <<4) | BLUE ; // window attrib v_cls(NORMAL); // clear the screen w1 = wn_open(0,0,0,35,10,wat,bat); wn_wrap(w1,1); wn_title(w1," G W P  F A M I L Y  T R E E "); if(argc>1)strcpy(inname,argv[1]); // Open input file else strcpy(inname,"gwp.dat"); if((inn=fopen(inname,"r"))==NULL) { wn_printf(w1,"Couldn't open input file %s\n",inname); leave(); } else wn_printf(w1,"Opened %s\n",inname); if(argc>2)strcpy(outname,argv[2]); // Open output file else strcpy(outname,"fam.out"); if((out=fopen(outname,"w"))==NULL) { wn_printf(w1,"Couldn't open output file %s\n",outname); leave(); } else wn_printf(w1,"Opened %s\n",outname); if((msg=fopen("c:\\fam.log","w"))==NULL) { wn_printf(w1,"Couldn't open file fam.log\n"); leave(); } else wn_printf(w1,"Opened fam.log\n"); wn_printf(w1,"Reading Database...\n"); root = NULL; saveptr=malloc(MAXBUF); while(1) // Loop over all sets of data { ptr=saveptr; // Initialize ptr strcpy(ptr," "); while(1) // Read all lines of a set and concatenate { fgets(line,81,inn); strcat(ptr,line); if(strcmp(outname,"fam.out") != 0) { fprintf(msg,"%s",line); fprintf(msg,"file2 %s %s\n",inname,outname); } if(feof(inn)) { // End of file was read. strcat(ptr," Z9Z "); neof=1; break; } if(strspn(line," \n")==strlen(line)) { // End of record was reached. strcat(ptr," Z9Z "); break; } if(strlen(ptr)>MAXBUF) { wn_printf(w1,"Error. Record too big %d\n",strlen(ptr)); goto john; } } ptr = parse(ptr,keywd); if(strcmp(outname,"fam.out") != 0) fprintf(msg,"file1: %s %s keywd %s\n",inname,outname,keywd); if((nx=strlen(keywd)+1) > MAXKEY) { wn_printf(w1,"Error. Keyword=%s length of %d exceeds %d\n", keywd,nx,MAXKEY); break; } if(strcmpi(keywd,"end")==0) { fprintf(msg,"End file marker was read.\n"); break; } if(strcmpi(keywd,"name")!=0 ) { wn_printf(w1,"Error. Keywd=%s but should have been 'name'.\n",keywd); break; } ptr = parse(ptr,Name); // Find out who this record is for; wn_printf(w1,"%s\n",Name); if(strcmp(outname,"fam.out") != 0) fprintf(msg,"file3: %s %s Name %s\n",inname,outname,Name); // Now parse the info into keywords and values if((nx=strlen(Name)+1) > MAXNAM) { wn_printf(w1,"Error. Name=%s length of %d exceeds %d\n",Name,nx,MAXNAM); break; } root=addtree(root,Name); you=kin; // you is person this data block is for // kin is the person being described as being related // addtree sets kin to point to the last struct person accessed while(1) // Loop over all keywords for this Name { ptr = parse(ptr,keywd); if(strcmp(outname,"fam.out") != 0) fprintf(msg,"file4: %s %s keywd %s\n",inname,outname,keywd); if(strcmp(keywd,"Z9Z")==0) { // Record parsed. break; } ptr = parse(ptr,value); if(strcmp(outname,"fam.out") != 0) fprintf(msg,"file5: %s %s value %s %d\n", inname,outname,value,strlen(value)); if((nx=strlen(value)+1) > MAXVAL) { wn_printf(w1,"Error. Value=%s length of %d exceeds %d\n", value,nx,MAXVAL); goto john; } putvalue(you,keywd,value); if(strcmp(outname,"fam.out") != 0) fprintf(msg,"file7: %s %s %s %s %d\n", inname,outname,keywd,value,strlen(value)); } if(neof==1)break; } john: fclose(inn); count=0; gatherAll(root); wn_printf(w1,"There are %d individuals\nmentioned in the data.\n",count-1); if(strcmp(outname,"fam.out"))wn_printf(w1,"file6 %s %s\n",inname,outname); if(count>=MAXHUM) { wn_printf(w1,"Error. Raise MAXHUM from %d\nto at least %d.\n", MAXHUM,count); treeprint(root); leave(); } heapsort(count,list); // Sort in chronological order of birthdays for(nx=0; nxnumber = nx+1; // Assign cross reference number } while(1) // Loop here until all output requests are satisfied { wat2 = (BLUE<<4) | WHITE; bat2 = (RED<<4 ) | WHITE; option = wn_popup(0, 9, 25, 52, 13, wat2, bat2, &query, TRUE); if(option==99)leave(); else if(option==1) // Formatted listing of entire database { if(ntimes > 0) { wn_printf(w1,"Formatted Listing Of Database\nAlready Made.\n"); continue; } else wn_printf(w1,"Writing..."); fprintf(out,"\n<<<ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"\ "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\n"); fprintf(out,"\n Listing of Entire Database\n"); for(nx=0; nx MAXREL) { wn_printf(w1,"Error. Raise MAXREL from %d\nto at least %d.\n", MAXREL,nancs); nancs=MAXREL; } wn_printf(w1,"%d Ancestors were found.\n",nancs); heapsort(nancs,reltiv); //Sort by birthday for(nx=0; nx MAXREL) { wn_printf(w1,"Error. Raise MAXREL from %d\nto at least %d.\n", MAXREL,ndesc); ndesc=MAXREL; } wn_printf(w1,"%d Offspring were found.\n",ndesc); heapsort(ndesc,reltiv); //Sort by birthday for(nx=0; nx MAXREL) { wn_printf(w1,"Error. Raise MAXREL from %d\nto at least %d.\n", MAXREL,nrel); nrel=MAXREL; } wn_printf(w1,"%d Relatives were found.\n",nrel); heapsort(nrel,reltiv); //Sort by birthday for(nx=0; nxsex == 'F' && you->spouse!=NULL) // married female { kin=you->spouse->husband; for(ii=0; iistd = NULL; p->left = p->right = NULL; p->father = p->mother = NULL; p->dtborn = p->dtdied = NULL; p->plborn = p->pldied = p->plbury = NULL; p->spouse = NULL; p->persnote = NULL; p->sex = '\0'; p->number = 0; return p; } bliss mmalloc(void) { bliss p; p = (bliss) malloc(sizeof(struct marriage)); p->husband = NULL; p->wife = NULL; p->dtmarr = NULL; p->plmarr = NULL; p->marrnote = NULL; p->kid = NULL; p->newHusband = NULL; p->newWife = NULL; return p; } issue challoc(void) { issue p; p = (issue) malloc(sizeof(struct child)); p->name=NULL; p->next=NULL; return p; } tag nalloc(void) { tag p; p = (tag) malloc(sizeof(struct name)); p->name = NULL; p->next = NULL; return p; } char *parse(char *str, char *token) { char c; while(isspace(*str))str++; // Skip over space chars if(ispunct(*str)) // First character is a punctuation character { c=*str++; // Save the punct char and advance pointer while(*str != c)*token++ = *str++; str++; } else { while(!isspace(*str))*token++ = *str++; } *token = '\0'; return str; } void putvalue(human you, char *keywd, char *value) { bliss m1,m2,m3,m4; tag n1,n2; issue k1,k2; if(strcmpi(keywd,"name")==0) { n2 = you->std; do { n1 = n2; n2 = n1->next; }while(n2 != NULL); n2 = nalloc(); n1->next = n2; n2->name = strdup(value); n2->next = NULL; } else if(strcmpi(keywd,"mother")==0) { // Get pointer to mother's person struct root = addtree(root,value); addparent(kin,you,'F'); you->mother = kin; } else if(strcmpi(keywd,"father")==0) { root = addtree(root,value); addparent(kin,you,'M'); you->father = kin; } else if(strcmpi(keywd,"dtborn")==0) you->dtborn = strdup(value); else if(strcmpi(keywd,"dtdied")==0) you->dtdied = strdup(value); else if(strcmpi(keywd,"plborn")==0) you->plborn = strdup(value); else if(strcmpi(keywd,"pldied")==0) you->pldied = strdup(value); else if(strcmpi(keywd,"plbury")==0) you->plbury = strdup(value); else if(strcmpi(keywd,"persnote")==0) you->persnote = strdup(value); else if(strcmpi(keywd,"sex")==0) you->sex = (char) toupper(value[0]); // Use M or F else if(strcmpi(keywd,"husband")==0) { you->sex = 'F'; m2 = you->spouse; if(m2 == NULL) you->spouse = m2 = mmalloc(); else { while(m2 != NULL) { m1 = m2; if(strcmp(m1->husband->std->name,value)==0)return; m2 = m2->newHusband; } m1->newHusband = m2 = mmalloc(); } root = addtree(root,value); // Now search thru new mate's list of spouses m4 = kin->spouse; if(m4 == NULL) kin->spouse = m2; else { while(m4 != NULL) { m3 = m4; if(strcmp(m3->wife->std->name,you->std->name)==0)return; m4 = m4->newWife; } m3->newWife = m2; } m2->wife = you; m2->husband = kin; kin->sex = 'M'; m2->newWife = NULL; m2->newHusband = NULL; } else if(strcmpi(keywd,"wife")==0) { you->sex = 'M'; m2 = you->spouse; if(m2 == NULL) you->spouse = m2 = mmalloc(); else { while(m2 != NULL) { m1 = m2; if(strcmp(m1->wife->std->name,value)==0)return; m2 = m2->newWife; } m1->newWife = m2 = mmalloc(); } root = addtree(root,value); // Now search thru new mate's list of spouses m4 = kin->spouse; if(m4 == NULL) kin->spouse = m2; else { while(m4 != NULL) { m3 = m4; if(strcmp(m3->husband->std->name,you->std->name)==0)return; m4 = m4->newHusband; } m3->newHusband = m2; } m2->wife = kin; m2->husband = you; kin->sex = 'F'; m2->newWife = NULL; m2->newHusband = NULL; } else if(strcmpi(keywd,"dtmarr")==0) // Trap error of no spouse { m2 = you->spouse; do { m1 = m2; m2 = (you->sex=='M') ? m1->newWife : m1->newHusband; }while(m2 != NULL); m1->dtmarr = strdup(value); } else if(strcmpi(keywd,"plmarr")==0) // Trap error of no spouse { m2 = you->spouse; do { m1 = m2; m2 = (you->sex=='M') ? m1->newWife : m1->newHusband; }while(m2 != NULL); m1->plmarr = strdup(value); } else if(strcmpi(keywd,"marrnote")==0) // Trap error of no spouse { m2 = you->spouse; do { m1 = m2; m2 = (you->sex=='M') ? m1->newWife : m1->newHusband; }while(m2 != NULL); m1->marrnote = strdup(value); } else if(strcmpi(keywd,"child")==0) { root = addtree(root,value); addchild(you,kin); } else { wn_printf(w1,"Error. Keywd=%s value=%s not recognized for %s \n", keywd,value,you->std->name); v_getch(); } } human addtree(human p, char *w) { tag n; int cond; if(p==NULL) { kin = p = palloc(); p->std = nalloc(); p->std->name = strdup(w); } else if((cond=strcmpi(w,p->std->name))==0) kin = p; else if(cond<0) // left branch p->left = addtree(p->left,w); else // right branch p->right = addtree(p->right,w); return p; } void printper(human you,int flag) { issue k1; // kid tag n1; // name bliss m1; // marriage human p1; // person int nrc; if(strcmpi(you->std->name,"UNKNOWN")==0)return; fprintf(out,"\n>>>ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"\ "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\n"); // Print data for married females with that of their husband(s) if(flag==0 && you->sex=='F' && (m1=you->spouse)!=NULL) { fprintf(out,"[%d] %s ",you->number,getname(you)); nrc=0; while(m1!=NULL) { p1 = m1->husband; if((nrc = 1-nrc) == 0)fprintf(out,"\n"); fprintf(out," Husband: %s [%d] ",getname(p1),p1->number); m1 = m1->newHusband; } return; } printdat(you); m1 = you->spouse; while(m1!=NULL) { p1 = (you->sex == 'M') ? m1->wife : m1->husband; if(flag==0)fprintf(out,"\n\nWife: "); else fprintf(out,"\n\nSpouse: "); printdat(p1); nrc = 0; if(m1->dtmarr!=NULL) nrc = fprintf(out,"\n\nDate Married: %s ",dayt(m1->dtmarr)); if(m1->plmarr!=NULL) { if(nrc > MAXNRC)fprintf(out,"\n"); fprintf(out,"Place Married: %s ",m1->plmarr); } if(m1->marrnote!=NULL)fprintf(out,"\n%s",m1->marrnote); k1 = m1->kid; while(k1!=NULL) { p1 = k1->name; if(p1->std->name==NULL)break; nrc = fprintf(out,"\n\nChild: %s [%d] ",getname(p1),p1->number); if(p1->dtborn!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Dt Born %s ",p1->dtborn); } if(p1->sex!='\0') { if(nrc > MAXNRC+10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Sex %c " ,p1->sex); } if(p1->plborn!=NULL) { if(nrc > MAXNRC)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Born %s ",p1->plborn); } if(p1->dtdied!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Died %s ",p1->dtdied); } if(p1->pldied!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Died %s ",p1->pldied); } if(p1->plbury!=NULL) { if(nrc > MAXNRC-10)fprintf(out,"\n"); fprintf(out,"Buried %s ",p1->plbury); } k1 = k1->next; } m1 = (you->sex=='M') ? m1->newWife: m1->newHusband; } } void treeprint(human p) { if(p!=NULL) { treeprint(p->left); printper(p,0); treeprint(p->right); } } void addchild(human parent, human baby) { issue k1,k2; human p1; bliss m1,m2; m2 = parent->spouse; // Find ptr to other parent if(m2==NULL) { wn_printf(w1,"Error in addchild. Must be married to have a child.\n"); wn_printf(w1,"Parent %s, child %s\n",parent->std->name,baby->std->name); return; } while(m2!=NULL) { m1 = m2; m2 = (parent->sex=='M') ? m1->newWife : m1->newHusband; } p1 = (parent->sex=='M') ? m1->wife : m1->husband; //other parent k2 = m1->kid; // Find slot for child to be added if(k2==NULL) { k2 = m1->kid = challoc(); } else { while(k2!=NULL) { k1 = k2; if(strcmp(k1->name->std->name,baby->std->name)==0)goto x03; k2 = k1->next; } k2 = k1->next = challoc(); } k2->next = NULL; k2->name = baby; x03:if(parent->sex=='M') // Tell baby who its parents are { baby->father = parent; baby->mother = p1; } else { baby->father = p1; baby->mother = parent; } } void addparent(human parent, human baby, char sex) // Infer the other parent only if // (1) both parents are defined and neither is married, or // (2) this parent has exactly one spouse // { bliss m1; human p1; issue k1,k2; if(sex == 'M') { baby->father = parent; parent->sex = 'M'; m1=parent->spouse; // if parent not married and mother defined and mother not married if(m1==NULL && (p1=baby->mother)!=NULL && p1->spouse == NULL) { m1 = mmalloc(); // Assume they are married m1->husband = parent; m1->wife = baby->mother; parent->spouse = m1; baby->mother->spouse = m1; baby->mother->sex = 'F'; k2 = m1->kid = challoc(); k2->next = NULL; // must be first child k2->name = baby; } // if parent married and has only one wife else if(m1!=NULL && m1->newWife==NULL) { baby->mother = m1->wife; k2 = m1->kid; // there may be other children if(k2==NULL) { k2 = m1->kid = challoc(); } else { while(k2!=NULL) { k1 = k2; k2 = k1->next; // Avoid duplicate entries if(strcmp(k1->name->std->name,baby->std->name)==0)return; } k2 = k1->next = challoc(); } k2->next = NULL; k2->name = baby; } } else // sex=='F' { baby->mother = parent; parent->sex='F'; m1=parent->spouse; // if parent not married and father defined and father not married if(m1==NULL && (p1=baby->father)!=NULL && p1->spouse == NULL) { m1 = mmalloc(); // Assume they are married m1->husband = baby->father; m1->wife = parent; baby->father->spouse = m1; baby->father->sex = 'M'; parent->spouse = m1; k2 = m1->kid = challoc(); k2->next = NULL; // must be first child k2->name = baby; } else if(m1!=NULL && m1->newHusband==NULL) // Just one husband { baby->father = m1->husband; k2 = m1->kid; if(k2==NULL) { k2 = m1->kid = challoc(); } else { while(k2!=NULL) { k1 = k2; k2 = k1->next; if(strcmp(k1->name->std->name,baby->std->name)==0)return; } k2 = k1->next = challoc(); } k2->next = NULL; k2->name = baby; } } } void gatherAll(human p) { if(p!=NULL) { gatherAll(p->left); if(count < MAXHUM)list[count] = p; count++; gatherAll(p->right); } } char *getname(human p) { tag n1; n1= p->std; if(n1->next == NULL) return n1->name; else return n1->next->name; } /* Given a date in the form "yyyy-mm-dd", dayt calculates the date in the * form, e.g. Saturday, September 29, 1990 * It returns a pointer to this string. * In the event of a date not in the form "yyyy-mm-dd" the date itself * is returned. */ char *dayt(char *date) { static char result[31]; char *ptr, *month[]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, *day_of_week[]={"Saturday", "Sunday", "Monday","Tuesday", "Wednesday","Thursday","Friday"}; int nd,ii,j,zmon,mon,day,yr,year,cent,leap; int days_in_mon[]={31,28,31,30,31,30,31,31,30,31,30,31}; if(date == NULL)return " "; // Verify that three items are read, in format yyyy-mm-dd if(sscanf(date,"%4d-%2d-%2d",&year,&mon,&day)!=3)return date; cent=year/100; yr=year%100; if(year%4==0) leap=1-(year==1700 || year==1800 || year==1900); // these not leap yrs else leap=0; nd=days_in_mon[mon-1]; // check for invalid day of the month if(mon==2)nd+=leap; if(day<1 || day>nd || mon<1 || mon>12)return date; // j = yr + yr/4 + day + addmon[mon-1] + addcent[cent-18] - leap; // Algorithm is known as Zeller's Congruence zmon=mon; if(zmon<3) { zmon+=12; if (yr>0) yr--; else { yr=99; cent--; } } ii = day + (zmon+1)*26/10 + yr + yr/4 + cent/4 - cent - cent ; while(ii<0)ii+=7; // this makes mod of neg number work correctly ii=ii%7; ptr=day_of_week[ii]; sprintf(result, "%s, %s %d, %d",day_of_week[ii], month[mon-1],day,year); ptr=result; return ptr; } char *aged(human who) { int yr2, yr1, mon2, mon1, day2, day1, delyr, delmon, delday, jday1, jday2; int days_so_far[] = {0,31,59,90,120,151,181,212,243,273,304,334}; int val1, val2; char result[31]=" "; if((val1 = validate(who->dtborn))==0) return result; if((val2 = validate(who->dtdied))==0) return result; if (val1==3 && val2==3) { sscanf(who->dtdied,"%4d-%2d-%2d",&yr2,&mon2,&day2); jday2 = days_so_far[mon2-1] + day2; sscanf(who->dtborn,"%4d-%2d-%2d",&yr1,&mon1,&day1); jday1 = days_so_far[mon1-1] + day1; if(jday1 > jday2) { jday2 += 365; // ignore leap year yr2--; } delday = jday2 - jday1; delyr = yr2 - yr1; sprintf(result, " Age %d yrs %d days",delyr,delday); } else if (val1>=2 && val2>=2) { sscanf(who->dtdied,"%4d-%2d",&yr2,&mon2); sscanf(who->dtborn,"%4d-%2d",&yr1,&mon1); if(mon1 > mon2) { mon2 += 12; // ignore leap year yr2--; } delmon = mon2 - mon1; delyr = yr2 - yr1; sprintf(result, " Age %d yrs %d mon",delyr,delmon); } else if(val1>=1 && val2>=1) { sscanf(who->dtdied,"%4d",&yr2); sscanf(who->dtborn,"%4d",&yr1); delyr = yr2 -yr1; sprintf(result," Age approx %d years",delyr); } else strcpy(result,"Invalid dates."); return result; } int validate(char *date) // Check validity of date { int len,yy,mm,dd; int dpm[]={31,29,31,30,31,30,31,31,30,31,30,31}; if((len=strlen(date))<4)return 0; sscanf(date,"%4d",&yy); if(yy<1500 || yy>2020)return 0; // 0 => invalid dates if(len<7)return 1; if(sscanf(&date[4],"-%2d",&mm)!=1)return 1; if(mm<1 || mm>12)return 1; // 1 => year is valid if(len<9)return 2; if(sscanf(&date[7],"-%2d",&dd)!=1)return 2; if(dd<1 || dd>dpm[mm-1]) return 2; // 2 => year/mon are valid return 3; // 3 => year/mon/day are valid } char *demise(human you) { static char buff[51]; strcpy(buff,dayt(you->dtdied)); strcat(buff,aged(you)); return buff; } void printdat(human you) { tag n1; human p1; int nrc; if(strcmpi(you->std->name,"UNKNOWN")==0) { fprintf(out,"UNKNOWN"); return; } n1 = you->std; nrc = fprintf(out,"[%d] %s ",you->number,n1->name); n1 = n1->next; while(n1!=NULL) { if(nrc > MAXNRC)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Name: %s ",n1->name); n1 = n1->next; } nrc = fprintf(out,"\n"); p1 = you->father; if(p1!=NULL)nrc = fprintf(out,"Father: %s [%d] ", getname(p1), p1->number); p1 = you->mother; if(p1!=NULL) { if(nrc > MAXNRC)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Mother: %s [%d] ", getname(p1), p1->number); } if(you->dtborn!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Born: %s ",dayt(you->dtborn)); } if(you->plborn!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Place born: %s ",you->plborn); } if(you->sex!='\0' && you->spouse == NULL) { if(nrc > MAXNRC+10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Sex: %c ",you->sex); } if(you->dtdied!=NULL) { if(nrc > 30)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Died: %s ",demise(you)); } if(you->pldied!=NULL) { if(nrc > MAXNRC-10)nrc = fprintf(out,"\n"); nrc += fprintf(out,"Place died: %s ",you->pldied); } if(you->plbury!=NULL) { if(nrc > MAXNRC-10)fprintf(out,"\n"); fprintf(out,"Place buried: %s",you->plbury); } if(you->persnote!=NULL)fprintf(out,"\n%s",you->persnote); } void anctree(human p, int level) { int i,newlevel; if(p!=NULL) { fprintf(out,"\n"); for(i=0;inumber); if(p->dtborn!=NULL)fprintf(out," b %s",p->dtborn); newlevel = level + 1; anctree(p->father,newlevel); anctree(p->mother,newlevel); } } // Adapted from Numerical Recipes by Press et al, page 231 by GWP 10/90 void heapsort(int n, human *ra) // Sorts by birthday { int i,l,ir,j; // Modified by subtracting 1 from every subscript human rra; l = n/2+1; ir=n; while(1) { if(l > 1) { l--; rra=ra[l-1]; } else { rra=ra[ir-1]; ra[ir-1]=ra[1-1]; if(--ir == 1) { ra[1-1]=rra; return; } } i=l; j=l+l; while(j <= ir) { if(j < ir && strcmp(ra[j-1]->dtborn,ra[j]->dtborn) < 0)j++; if(strcmp(rra->dtborn,ra[j-1]->dtborn) < 0) { ra[i-1]=ra[j-1]; i=j; j+=j; } else { j=ir+1; } } ra[i-1]=rra; } } void getAncs(human p) // Make list of a person's ancestors { if(p!=NULL) { getAncs(p->father); if(nancs < MAXREL)reltiv[nancs] = p; nancs++; getAncs(p->mother); } } human getptr(char *name) // Search list of names for a specified name { int i; human ptr; for(i=0;istd->name,name)==0)return list[i]; } wn_printf(w1,"getptr failed to find %s\nin the list of names.\n",name); v_getch(); return NULL; } void desctree(human you, int level) { int i,newlevel; bliss m1; issue k1; if(you!=NULL) { fprintf(out,"\n"); for(i=0;inumber); if(you->dtborn!=NULL)fprintf(out," b %s",you->dtborn); newlevel = level + 1; m1 = you->spouse; while(m1!=NULL) // Loop over marriages { k1 = m1->kid; while(k1!=NULL) // Loop over children of each marriage { desctree(k1->name,newlevel); k1 = k1->next; } m1 = (you->sex=='M') ? m1->newWife: m1->newHusband; } } } void getDesc(human you) { bliss m1; issue k1; if(you!=NULL) { m1 = you->spouse; while(m1!=NULL) // Loop over marriages { k1 = m1->kid; while(k1!=NULL) // Loop over children of each marriage { if(ndesc < MAXREL)reltiv[ndesc] = k1->name; ndesc++; getDesc(k1->name); k1 = k1->next; } m1 = (you->sex=='M') ? m1->newWife: m1->newHusband; } } } void leave(void) { v_getch(); wn_close(w1); fclose(msg); fclose(out); wn_exit(); exit(0); } void getRel(human p) // Make list of a person's relatives { int i, nn; if(p!=NULL) { if(strcmpi(p->std->name,"UNKNOWN")==0)return; getRel(p->father); getRel(p->mother); nn = nrel < MAXREL ? nrel : MAXREL ; for(i=0; istd->name); nrel++; getAncDesc(p); // Get descendants of this ancestor } } void getAncDesc(human you) // Get each ancestor's descendants { bliss m1; issue k1; // may need to chg to loop over Ancs then Desc int i,nn; if(you!=NULL) { m1 = you->spouse; while(m1!=NULL) // Loop over marriages { k1 = m1->kid; while(k1!=NULL) // Loop over children of each marriage { // fprintf(msg," des %d %s\n",nrel,k1->name->std->name); nn = nrel < MAXREL ? nrel : MAXREL ; for(i=0;i < nn; i++) { if(k1->name==reltiv[i])goto x01; } if(nrel < MAXREL) reltiv[nrel] = k1->name; nrel++; x01: getAncDesc(k1->name); k1 = k1->next; } m1 = (you->sex=='M') ? m1->newWife: m1->newHusband; } } }