/*============================================ * cgn_callback -- callback for name traversal * for checking for ghost names * Created: 2001/01/01, Perry Rapp *==========================================*/ static BOOLEAN cgn_callback (TRAV_NAMES_FUNC_ARGS(key, name, newset, param)) { /* a name record which points at indi=key */ RECORD indi0 = NULL; NODE indi = NULL; param=param; /* unused */ /* bail out immediately if not INDI */ if (key[0] != 'I') { report_error(ERR_NONINDINAME , _("Non-indi name, key=%s, name=%s") , key, name); return 1; /* continue traversal */ } indi0 = qkey_to_irecord(key); indi = nztop(indi0); if (newset) { finish_and_delete_nameset(); soundexseq = create_indiseq_sval(); } append_indiseq_sval(soundexseq, strsave(key), (STRING)name, strsave(name) , TRUE, TRUE); /* sure, alloc */ if (!indi) { report_error(ERR_ORPHANNAME, _("Orphaned name: %s"), name); if (todo.fix_ghosts) enqueue_list(tofix, (VPTR)alloc_namerefn(name, key, ERR_ORPHANNAME)); } else { NODE node; BOOLEAN found=FALSE; NODE nam, refn, sex, body, famc, fams; split_indi_old(indi, &nam, &refn, &sex, &body, &famc, &fams); for (node = nam; node; node = nsibling(node)) { if (!strcmp(nval(node), name)) found=TRUE; } join_indi(indi, nam, refn, sex, body, famc, fams); if (!found) { report_error(ERR_GHOSTNAME, _("Ghost name: %s -> %s"), name, key); if (todo.fix_ghosts) enqueue_list(tofix, (VPTR)alloc_namerefn(name, key, ERR_GHOSTNAME)); } } if (noisy) report_progress("Name: %s", name); return 1; /* continue traversal */ }
/*================================================================ * add_indi_no_cache -- Add new person to database * does not insert into cache * (used by import) * (no user interaction) *==============================================================*/ BOOLEAN add_indi_no_cache (NODE indi) { NODE node, name, refn, sex, body, famc, fams; STRING str, key; split_indi_old(indi, &name, &refn, &sex, &body, &famc, &fams); key = rmvat(nxref(indi)); for (node = name; node; node = nsibling(node)) add_name(nval(node), key); for (node = refn; node; node = nsibling(node)) if (nval(node)) add_refn(nval(node), key); join_indi(indi, name, refn, sex, body, famc, fams); resolve_refn_links(indi); str = node_to_string(indi); store_record(key, str, strlen(str)); stdfree(str); return TRUE; }
/*===================================== * write_indi_to_file - write node tree into GEDCOM * (no user interaction) *===================================*/ void write_indi_to_file (NODE indi, CNSTRING file) { FILE *fp; XLAT ttmo = transl_get_predefined_xlat(MINED); NODE name, refn, sex, body, famc, fams; ASSERT(fp = fopen(file, LLWRITETEXT)); prefix_file(fp, ttmo); split_indi_old(indi, &name, &refn, &sex, &body, &famc, &fams); write_nodes(0, fp, ttmo, indi, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, name, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, refn, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, sex, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, body , TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, famc, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, fams, TRUE, TRUE, TRUE); fclose(fp); join_indi(indi, name, refn, sex, body, famc, fams); }
/*========================================================== * add_new_indi_to_db -- Add newly created person to database * (no user interaction) * creates record & adds to cache *========================================================*/ static void add_new_indi_to_db (RECORD indi0) { NODE name, refn, sex, body, dumb, node; char key[MAXKEYWIDTH]=""; INT keynum=0; NODE indi = nztop(indi0); split_indi_old(indi, &name, &refn, &sex, &body, &dumb, &dumb); keynum = getixrefnum(); sprintf(key, "I%ld", keynum); init_new_record(indi0, key); for (node = name; node; node = nsibling(node)) { add_name(nval(node), key); } for (node = refn; node; node = nsibling(node)) { if (nval(node)) add_refn(nval(node), key); } join_indi(indi, name, refn, sex, body, NULL, NULL); resolve_refn_links(indi); indi_to_dbase(indi); add_new_indi_to_cache(indi0); }
/*===================================== * process_indi -- process indi record * checking in pass 1, fixing in pass 2 *===================================*/ static void process_indi (RECORD rec) { NODE indi0, indi1; NODE name1, refn1, sex1, body1, famc1, fams1; NODE node1; BOOLEAN altered=FALSE; BOOLEAN needfix=FALSE; CNSTRING key = nzkey(rec); indi0 = nztop(rec); if (todo.pass==1) { indi1 = indi0; } else { indi1 = copy_node_subtree(indi0); } split_indi_old(indi1, &name1, &refn1, &sex1, &body1, &famc1, &fams1); if (todo.pass == 1) { /* check names */ for (node1 = name1; node1; node1 = nsibling(node1)) { STRING name=nval(node1); if (!valid_name(name)) { report_error(ERR_BADNAME, _("Bad name for individual %s: %s"), key, name); } else { /* TO DO: verify that name is in db */ } } /* check refns */ for (node1 = refn1; node1; node1 = nsibling(node1)) { /* STRING refn=nval(node1); */ /* TO DO: verify that refn is in db */ } } /* check parents */ for (node1 = famc1; node1; node1 = nsibling(node1)) { STRING famkey=rmvat(nval(node1)); NODE fam2 = qkey_to_fam(famkey); if (!fam2) { if (todo.pass == 1) { report_error(ERR_BADFAMREF, _("Bad family reference (%s) individual %s"), famkey, key); } } else { /* look for indi1 (key) in fam2's children */ if (!find_xref(key, fam2, "CHIL", NULL)) { if (todo.pass == 1) { report_error(ERR_MISSINGCHILD, _("Missing child (%s) in family (%s)"), key, famkey); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_MISSINGCHILD, _("Fixed missing child (%s) in family (%s)"), key, famkey); altered=TRUE; } } } } } /* check spouses */ for (node1 = fams1; node1; node1 = nsibling(node1)) { STRING famkey=rmvat(nval(node1)); NODE fam2 = qkey_to_fam(famkey); if (!fam2) { if (todo.pass == 1) { report_error(ERR_BADFAMREF, _("Bad family reference (%s) individual %s"), famkey, key); } } else { /* look for indi1 (key) in fam2's spouses */ if (!find_xref(key, fam2, "HUSB", "WIFE")) { if (todo.pass == 1) { report_error(ERR_MISSINGSPOUSE, _("Missing spouse (%s) in family (%s)"), key, famkey); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_MISSINGSPOUSE, _("Fixed missing spouse (%s) in family (%s)"), key, famkey); altered=TRUE; } } } } } join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); if (altered) { /* must normalize, as some lineage references may have been altered to non-lineage tags to fix broken pointers */ normalize_indi(indi1); /* write to database */ replace_indi(indi0, indi1); } else if (needfix) { enqueue_list(tofix, strsave(key)); } }
/*=================================== * valid_indi_tree -- Validate person tree * indi1: [IN] person to validate * pmsg: [OUT] error message, if any * orig: [IN] person to match - may be NULL * rtn: FALSE for bad * Should be replaced by valid_indi(RECORD,...) ? *=================================*/ BOOLEAN valid_indi_tree (NODE indi1, STRING *pmsg, NODE orig) { NODE name1, refn1, sex1, body1, famc1, fams1, node; NODE name0, refn0, sex0, body0, famc0, fams0; INT isex, num; STRING *keys, ukey; if (!indi1) { *pmsg = _(qSbademp); return FALSE; } if (nestr("INDI", ntag(indi1))) { *pmsg = _(qSbadin0); return FALSE; } if (nsibling(indi1)) { *pmsg = _(qSbadmul); return FALSE; } split_indi_old(indi1, &name1, &refn1, &sex1, &body1, &famc1, &fams1); if (getlloptint("RequireNames", 0) && !name1) { *pmsg = _("This person record does not have a name line."); goto bad2; } for (node = name1; node; node = nsibling(node)) { if (!valid_name(nval(node))) { *pmsg = _(qSbadenm); goto bad2; } } name0 = refn0 = sex0 = body0 = famc0 = fams0 = NULL; if (orig) split_indi_old(orig, &name0, &refn0, &sex0, &body0, &famc0, &fams0); if (orig && !iso_nodes(indi1, orig, FALSE, FALSE)) { *pmsg = _(qSbadind); goto bad1; } if (!iso_nodes(famc1, famc0, FALSE, TRUE)) { *pmsg = _(qSbadfmc); goto bad1; } if (!iso_nodes(fams1, fams0, FALSE, TRUE)) { *pmsg = _(qSbadfms); goto bad1; } isex = val_to_sex(sex0); if (!fams0) isex = SEX_UNKNOWN; if (isex != SEX_UNKNOWN && isex != val_to_sex(sex1)) { *pmsg = _(qSbadparsex); goto bad1; } ukey = (refn1 ? nval(refn1) : NULL); get_refns(ukey, &num, &keys, 'I'); if (num > 1 || (num == 1 && (!orig || nestr(keys[0], rmvat(nxref(indi1)))))) { *pmsg = _(qSbadirefn); goto bad1; } if (orig) join_indi(orig, name0, refn0, sex0, body0, famc0, fams0); join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); return TRUE; bad1: if (orig) join_indi(orig, name0, refn0, sex0, body0, famc0, fams0); bad2: join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); return FALSE; }