Exemple #1
0
/*=================================
 * node_lineprint -- print a node line
 *  in a node tree
 * This is used in gedcom view & extended
 *  gedcom views
 * returns static buffer
 * Created: 2001/01/27, Perry Rapp
 *===============================*/
static STRING
node_lineprint (INT width, void * param)
{
	static char line[120];
	STRING ptr=line;
	INT mylen=sizeof(line);
	NODE_PRINT_PARAM npp = (NODE_PRINT_PARAM)param;
	NODE node=npp->node;

	if (mylen>width)
		mylen=width;
	if (nxref(node)) {
		llstrcatn(&ptr, nxref(node), &mylen);
		llstrcatn(&ptr, " ", &mylen);
	}
	if (ntag(node)) {
		llstrcatn(&ptr, ntag(node), &mylen);
		llstrcatn(&ptr, " ", &mylen);
	}
	if (nval(node)) {
		llstrcatn(&ptr, nval(node), &mylen);
		llstrcatn(&ptr, " ", &mylen);
	}
	if (npp->gdvw == GDVW_EXPANDED && nval(node)) {
		STRING key = rmvat(nval(node)), str;
		if (key) {
			str = generic_to_list_string(NULL, key, mylen, ",", &disp_long_rfmt, TRUE);
			llstrcatn(&ptr, " : ", &mylen);
			llstrcatn(&ptr, str, &mylen);
		}
	}
	return line;
}
Exemple #2
0
/*=====================================
 * check_node -- check node for bad pointers
 *  and bad levels, and continue traverse
 * 2001/02/18, Perry Rapp
 *===================================*/
static void
check_node (CNSTRING n0key, NODE node, INT level)
{
    BOOLEAN lineage=FALSE;
    /* ignore lineage links - they are checked elsewhere */
    if (level==1) {
        INT i;
        for (i=0; i<ARRSIZE(lineage_tags); i++) {
            if (eqstr(ntag(node), lineage_tags[i])) {
                lineage=TRUE;
                break;
            }
        }
    }
    /*
    TO DO: How do we tell non-pointers that *ought* to
    be pointers, eg "1 SOUR <FamilyHistory>" ?
    */
    if (!lineage) {
        STRING skey = rmvat(nval(node));
        if (skey) {
            NODE xnode = qkey_to_type(skey);
            if (!xnode) {
                report_error(ERR_BADPOINTER
                             , _("Bad pointer (in %s): %s")
                             , n0key, nval(node));
            }
        }
    }
    if (nchild(node))
        check_node(n0key, nchild(node), level+1);
    if (nsibling(node))
        check_node(n0key, nsibling(node), level);
}
Exemple #3
0
/*======================================
 * key_util -- Return person's key value
 *====================================*/
void
key_util (void)
{
	RECORD indi = ask_for_indi(_("Whose key value do you want?"), NOASK1);
	if (!indi) return;
	msg_info("%s - %s", rmvat(nxref(nztop(indi))), indi_to_name(nztop(indi), 70));
}
Exemple #4
0
/*==========================================================
 * ask_for_indi_key -- Have user identify person; return key
 *========================================================*/
STRING
ask_for_indi_key (STRING ttl, ASK1Q ask1)
{
	RECORD indi = ask_for_indi(ttl, ask1);
	if (!indi) return NULL;
	return rmvat(nxref(nztop(indi)));
}
Exemple #5
0
/*======================================
 * llrpt_writeindi -- Write person to database
 * usage: writeindi(INDI) -> BOOLEAN
 *====================================*/
PVALUE
llrpt_writeindi (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi1;
	PNODE arg = iargs(node);
	NODE indi2 = eval_indi(arg, stab, eflg, NULL);
	STRING rawrec=0, msg;
	INT len, cnt;
	BOOLEAN rtn=FALSE;

	if (*eflg || !indi2) {
		prog_var_error(node, stab, arg, 0, nonind1, "writeindi");
		return NULL;
	}

	/* make a copy, so we can delete it */
	indi2 = copy_node_subtree(indi2);

	/* get existing record */
	rawrec = retrieve_raw_record(rmvat(nxref(indi2)), &len);
	if (!rawrec) {
		/*
		TODO: What do we do here ? Are they adding a new indi ?
		or did they get the xref wrong ?
		*/
		goto end_writeindi;
	}
	ASSERT(indi1 = string_to_node(rawrec));
 
	cnt = resolve_refn_links(indi2);
	/* validate for showstopper errors */
	if (!valid_indi_tree(indi2, &msg, indi1)) {
		/* TODO: What to do with msg ? */
		goto end_writeindi;
	}
	if (cnt > 0) {
		/* unresolvable refn links */
		/* TODO: optional argument to make this fatal ? */
	}

	if (equal_tree(indi1, indi2)) {
		/* optimization :) */
		rtn = TRUE;
		goto end_writeindi;
	}
	if (readonly) {
		/* TODO: database is read only error message */
		goto end_writeindi;
	}
	
	replace_indi(indi1, indi2);
	strfree(&rawrec);
	rtn = TRUE;

end_writeindi:
	return create_pvalue_from_bool(rtn);
}
Exemple #6
0
/*==========================================
 * parse_key -- Get key type (first char) and numeric value
 * parse_key("I44") => 'I', 44
 *========================================*/
static BOOLEAN
parse_key (CNSTRING key, char * ktype, INT * kval)
{
	if (!key || !key[0] || !key[1])
		return FALSE;
	/* convert "@I44@" to "I44" */
	if (key[0] == '@' && key[strlen(key)-1] == '@')
		key = rmvat(key);
	*ktype = key[0];
	*kval = atoi(key+1);
	return TRUE;
}
Exemple #7
0
/*=====================================
 * llrpt_writefam -- Write family to database
 * usage: writefam(FAM) -> BOOLEAN
 *===================================*/
PVALUE
llrpt_writefam (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE fam1;
	NODE fam2 = eval_fam(iargs(node), stab, eflg, NULL);
	STRING rawrec=0, msg;
	INT len, cnt;
	BOOLEAN rtn=FALSE;
	if (*eflg) return NULL;

	/* make a copy, so we can delete it */
	fam2 = copy_node_subtree(fam2);

	/* get existing record */
	rawrec = retrieve_raw_record(rmvat(nxref(fam2)), &len);
	if (!rawrec) {
		/*
		TODO: What do we do here ? Are they adding a new fam ?
		or did they get the xref wrong ?
		*/
		goto end_writefam;
	}
	ASSERT(fam1 = string_to_node(rawrec));

	cnt = resolve_refn_links(fam2);
	/* validate for showstopper errors */
	if (!valid_fam_tree(fam2, &msg, fam1)) {
		/* TODO: What to do with msg ? */
		goto end_writefam;
	}
	if (cnt > 0) {
		/* unresolvable refn links */
		/* TODO: optional argument to make this fatal ? */
	}

	if (equal_tree(fam1, fam2)) {
		/* optimization :) */
		rtn = TRUE;
		goto end_writefam;
	}
	if (readonly) {
		/* TODO: database is read only error message */
		goto end_writefam;
	}
	
	replace_fam(fam1, fam2);
	strfree(&rawrec);
	rtn = TRUE;

end_writefam:
	return create_pvalue_from_bool(rtn);
}
Exemple #8
0
/*=================================================================
 * advedit_expand_traverse -- Traverse routine called when expanding record
 *===============================================================*/
static BOOLEAN
advedit_expand_traverse (NODE node, VPTR param)
{
	LIST subs = (LIST)param;
	STRING key = value_to_xref(nval(node));
	if (!key) return TRUE;
	key = strsave(key);
#ifdef DEBUG
	llwprintf("expand_traverse: %s %s\n", ntag(node), nval(node));
#endif /* DEBUG */
	FORLIST(subs, el)
#ifdef DEBUG
	llwprintf("expand_traverse: %s %s\n", key, rmvat(nval((NODE) el)));
#endif /* DEBUG */
		if (eqstr(key, rmvat(nval((NODE) el)))) {
			STOPLIST
			stdfree(key);
			return TRUE;
		}
	ENDLIST
	enqueue_list(subs, node);
	stdfree(key);
	return TRUE;
}
Exemple #9
0
/*===========================================+
 * llrpt_deletefromset -- Remove person from INDISEQ
 * usage: deletefromset(SET, INDI, BOOL) -> VOID
 *==========================================*/
PVALUE
llrpt_deletefromset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi;
	STRING key=0;
	BOOLEAN all, rc;
	INDISEQ seq;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1),
	    arg3 = inext(arg2);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE val3=0;
	if (*eflg) {
		prog_var_error(node, stab, arg1, val1, nonsetx, "deletefromset", "1");
		goto dfs_exit;
	}
	ASSERT(seq = pvalue_to_seq(val1));
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "deletefromset", "2");
		goto dfs_exit;
	}
	if (!indi) goto dfs_exit;
	*eflg = TRUE;
	if (!(key = strsave(rmvat(nxref(indi))))) {
		prog_error(node, "major error in deletefromset.");
		goto dfs_exit;
	}
	*eflg = FALSE;
	val3 = eval_and_coerce(PBOOL, arg3, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonboox, "deletefromset", "3");
		goto dfs_exit;
	}
	all = pvalue_to_bool(val3);
	delete_pvalue(val3);
	do {
		rc = delete_indiseq(seq, key, NULL, 0);
	} while (rc && all);
dfs_exit:
	/* delay delete of val1 to last minute lest it is a temp owning seq,
	    eg, deletefromset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	if (key) strfree(&key);
	return NULL;
}
Exemple #10
0
/*================================================================
 * 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;
}
Exemple #11
0
/*==================================+
 * llrpt_addtoset -- Add person to INDISEQ
 * usage: addtoset(SET, INDI, ANY) -> VOID
 *=================================*/
PVALUE
llrpt_addtoset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi=0;
	STRING key=0;
	INDISEQ seq=0;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1),
	    arg3 = inext(arg2);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE val2=0;
	if (*eflg) {
		prog_var_error(node, stab, arg1, val1, nonsetx, "addtoset", "1");
		return NULL;
	}
	ASSERT(seq = pvalue_to_seq(val1));
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "addtoset","2");
		goto ats_exit;
	}
	if (!indi) goto ats_exit;
	*eflg = TRUE;
	if (!(key = strsave(rmvat(nxref(indi))))) {
		prog_error(node, "major error in addtoset.");
		goto ats_exit;
	}
	*eflg = FALSE;
	val2 = evaluate(arg3, stab, eflg);
	if (*eflg) {
		prog_error(node, "3rd arg to addtoset is in error.");
		goto ats_exit;
	}
	append_indiseq_pval(seq, key, NULL, val2, FALSE);
ats_exit:
	if (key) strfree(&key); /* append made its own copy */
	/* delay to last minute val1 cleanup lest it is a temp owning seq,
	    eg, addtoset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	return NULL;
}
Exemple #12
0
/*===================================
 * find_xref -- Search node for a cross-reference key
 * 2001/01/21, Perry Rapp
 *=================================*/
static BOOLEAN
find_xref (CNSTRING key, NODE node, CNSTRING tag1, CNSTRING tag2)
{
    NODE node2;
    CACHEEL ncel2;
    BOOLEAN found=FALSE;
    ncel2 = node_to_cacheel_old(node);
    lock_cache(ncel2);
    for (node2 = nchild(node); node2; node2 = nsibling(node2)) {
        if (eqstr(tag1, ntag(node2))
                || (tag2 && eqstr(tag2, ntag(node2)))) {
            STRING key2 = rmvat(nval(node2));
            if (key2 && eqstr(key, key2)) {
                found = TRUE;
                goto exit_find;
            }
        }
    }
exit_find:
    unlock_cache(ncel2);
    return found;
}
Exemple #13
0
/*====================================+
 * llrpt_inset -- See if person is in INDISEQ
 * usage: inset(SET, INDI) -> BOOL
 *==========================================*/
PVALUE
llrpt_inset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi;
	STRING key=0;
	INDISEQ seq;
	BOOLEAN rel;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE valr=0;
	if (*eflg ||!val1 || !(seq = pvalue_to_seq(val1))) {
		*eflg = TRUE;
		prog_var_error(node, stab, arg1, val1, nonsetx, "inset", "1");
		goto inset_exit;
	}
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "inset", "2");
		goto inset_exit;
	}
	if (!indi) {
		rel = FALSE;
        } else { 
		if (!(key = strsave(rmvat(nxref(indi))))) {
			*eflg = TRUE;
			prog_error(node, "major error in inset.");
			goto inset_exit;
		}
		rel = in_indiseq(seq, key);
	}
	valr = create_pvalue_from_bool(rel);
inset_exit:
	/* delay delete of val1 to last minute lest it is a temp owning seq,
	    eg, inset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	if (key) strfree(&key);
	return valr;
}
Exemple #14
0
/*=================================================================
 * expand_tree -- Create copy of node tree with additional link info
 *===============================================================*/
static NODE
expand_tree (NODE root0)
{
	NODE copy, node, sub;
	STRING key;
	static NODE root;	/* root of record being edited */
	LIST subs;	/* list of contained records */
	NODE expd;	/* expanded main record - copy - our retval */

	root = root0;
	expd = copy_nodes(root, TRUE, TRUE);
	subs = create_list();
	traverse_nodes(expd, advedit_expand_traverse, subs);

   /* expand the list of records into the copied record */
	FORLIST(subs, el)
		node = (NODE) el;
#ifdef DEBUG
		llwprintf("in list: %s %s\n", ntag(node), nval(node));
#endif
		key = rmvat(nval(node));
		if ((sub = nztop(key_possible_to_record(key, *key)))) {
			copy = copy_node_subtree(sub);
			nxref(node)    = nxref(copy);
			ntag(node)     = ntag(copy);
			nchild(node)   = nchild(copy);
			nparent(node)  = nparent(copy);
/*MEMORY LEAK; MEMORY LEAK; MEMORY LEAK: node not removed (because its
  value and possibly xref [probably not] are still being referred to */
		}
	ENDLIST
	/* Shouldn't we free subs now ? Perry 2001/06/22 */
#ifdef DEBUG
	show_node(expd);
#endif
	return expd;
}
Exemple #15
0
/*===========================================
 * ask_for_fam -- Ask user to identify family by spouses
 *  pttl: [IN]  title for prompt to identify spouse
 *  sttl: [IN]  title for prompt to identify sibling
 *=========================================*/
RECORD
ask_for_fam (STRING pttl, STRING sttl)
{
	RECORD sib=0, prn=0;
	prn = ask_for_indi(pttl, DOASK1);
	if (!prn)  {
		NODE fam=0;
		RECORD frec=0;
		sib = ask_for_indi(sttl, DOASK1);
		if (!sib) return NULL;
		fam = FAMC(nztop(sib));
		if (!fam) {
			message(_(qSntchld));
			return NULL;
		}
		frec = key_to_frecord(rmvat(nval(fam)));
		return frec;
	}
	if (!FAMS(nztop(prn))) {
		message(_(qSntprnt));
		return NULL;
	}
	return choose_family(prn, _(qSparadox), _(qSidfbrs), TRUE);
}
Exemple #16
0
/*=====================================
 * process_fam -- process indi record
 *  checking in pass 1, fixing in pass 2
 *===================================*/
static void
process_fam (RECORD rec)
{
    NODE fam0, fam1;
    NODE fref1, husb1, wife1, chil1, rest1;
    NODE node1;
    INT members = 0;
    BOOLEAN altered=FALSE;
    BOOLEAN needfix=FALSE;
    CNSTRING key = nzkey(rec);

    fam0 = nztop(rec);
    if (todo.pass==1) {
        fam1 = fam0;
    } else {
        fam1 = copy_node_subtree(fam0);
    }
    split_fam(fam1, &fref1, &husb1, &wife1, &chil1, &rest1);

    /* check refns */
    for (node1 = fref1; node1; node1 = nsibling(node1)) {
        /* STRING refn=nval(node1); */
        /* TO DO: verify that refn is in db */
    }
    /* check husbs */
    for (node1 = husb1; node1; node1 = nsibling(node1)) {
        STRING husbkey=rmvat(nval(node1));
        NODE husb = qkey_to_indi(husbkey);
        members++;
        if (!husb) {
            if (todo.pass == 1) {
                report_error(ERR_BADHUSBREF
                             , _("Bad HUSB reference (%s) in family %s")
                             , husbkey, key);
                needfix=TRUE;
            } else {
                if (fix_bad_pointer(key, rec, node1)) {
                    report_fix(ERR_BADHUSBREF
                               , _("Fixed Bad HUSB reference (%s) in family %s")
                               , husbkey, key);
                    altered=TRUE;
                }
            }
        } else {
            /* look for family (key) in husb */
            if (!find_xref(key, husb, "FAMS", NULL)) {
                report_error(ERR_EXTRAHUSB
                             , _("Improper HUSB (%s) in family (%s)")
                             , husbkey, key);
            }
        }
    }
    /* check wives */
    for (node1 = wife1; node1; node1 = nsibling(node1)) {
        STRING wifekey=rmvat(nval(node1));
        NODE wife = qkey_to_indi(wifekey);
        members++;
        if (!wife) {
            if (todo.pass == 1) {
                report_error(ERR_BADWIFEREF
                             , _("Bad wife reference (%s) in family %s")
                             , wifekey, key);
                needfix=TRUE;
            } else {
                if (fix_bad_pointer(key, rec, node1)) {
                    report_fix(ERR_BADWIFEREF
                               , _("Fixed Bad wife reference (%s) in family %s")
                               , printkey(wifekey), key);
                    altered=TRUE;
                }
            }
        } else {
            /* look for family (key) in wife */
            if (!find_xref(key, wife, "FAMS", NULL)) {
                report_error(ERR_EXTRAWIFE
                             , _("Improper wife (%s) in family (%s)")
                             , printkey(wifekey), key);
            }
        }
    }
    /* check children */
    for (node1 = chil1; node1; node1 = nsibling(node1)) {
        STRING chilkey=rmvat(nval(node1));
        NODE child = qkey_to_indi(chilkey);
        members++;
        if (!child) {
            if (todo.pass == 1) {
                report_error(ERR_BADCHILDREF
                             , _("Bad child reference (%s) in family %s")
                             , printkey(chilkey), key);
                needfix=TRUE;
            } else {
                if (fix_bad_pointer(key, rec, node1)) {
                    report_fix(ERR_BADCHILDREF
                               , _("Fixed bad child reference (%s) in family %s")
                               , printkey(chilkey), key);
                    altered=TRUE;
                }
            }
        } else {
            /* look for family (key) in child */
            if (!find_xref(key, child, "FAMC", NULL)) {
                report_error(ERR_EXTRACHILD
                             , _("Improper child: Child (%s) without FAMC reference to family (%s)")
                             , printkey(chilkey), key);
            }
        }
    }
    join_fam(fam1, fref1, husb1, wife1, chil1, rest1);
    /* check for undersized family */
    if (!members) {
        report_error(ERR_EMPTYFAM, _("Empty family (%s)"), key);
    } else if (members == 1) {
        report_error(ERR_SOLOFAM, _("Single person family (%s)"), key);
    }


    if (altered) {
        /* must normalize, as some lineage references may have been
        altered to non-lineage tags to fix broken pointers */
        normalize_fam(fam1);

        /* write to database */
        replace_fam(fam0, fam1);

    } else if (needfix) {
        enqueue_list(tofix, strsave(key));
    }
}
Exemple #17
0
/*=======================================
 * edit_record -- Edit record in database
 *  root1:   [IN]  record to edit (may be NULL)
 *  idedt:   [IN]  user id prompt
 *  letr:    [IN]  record type (E, S, or X)
 *  redt:    [IN]  reedit prompt displayed if hard error after editing
 *  redtopt: [IN]  reedit prompt displayed if soft error (unresolved links)
 *  val:     [IN]  callback to validate routine
 *  cfrm:    [IN]  confirmation msg string
 *  tag:     [IN]  tag (SOUR, EVEN, or NULL)
 *  todbase: [IN]  callback to write record to dbase
 *  gdmsg:   [IN]  success message
 *  rfmt:    [IN]  display reformatter
 *=====================================*/
static BOOLEAN
edit_record (RECORD rec1, STRING idedt, INT letr, STRING redt, STRING redtopt
	, BOOLEAN (*val)(NODE, STRING *, NODE)
	, STRING cfrm, void (*todbase)(NODE), STRING gdmsg
	, RFMT rfmt)
{
	XLAT ttmi = transl_get_predefined_xlat(MEDIN);
	STRING msg, key;
	BOOLEAN emp;
	NODE root0=0, root1=0, root2=0;
	NODE refn1=0, refn2=0, refnn=0, refn1n=0;
	NODE body=0, node=0;

/* Identify record if need be */
	if (!rec1) {
		rec1 = ask_for_record(idedt, letr);
	}
	root1 = nztop(rec1);
	if (!root1) {
		message(_(qSnosuchrec));
		return FALSE;
	}

/* Have user edit record */
	annotate_with_supplemental(root1, rfmt);
	write_node_to_editfile(root1);
	resolve_refn_links(root1);

	do_edit();
	if (readonly) {
		root2 = file_to_node(editfile, ttmi, &msg, &emp);
		if (!equal_tree(root1, root2))
			message(_(qSronlye));
		free_nodes(root2);
		return FALSE;
	}

	while (TRUE) {
		INT cnt;
		root2 = file_to_node(editfile, ttmi, &msg, &emp);
		if (!root2) {
			if (ask_yes_or_no_msg(msg, redt)) {
				do_edit();
				continue;
			}
			break;
		}
		cnt = resolve_refn_links(root2);
		/* check validation & allow user to reedit if invalid */
		/* this is a showstopper, so alternative is to abort */
		if (!(*val)(root2, &msg, root1)) {
			if (ask_yes_or_no_msg(msg, redt)) {
				do_edit();
				continue;
			}
			free_nodes(root2);
			root2 = NULL;
			break;
		}
		/* Allow user to reedit if desired if any refn links unresolved */
		/* this is not a showstopper, so alternative is to continue */
		if (cnt > 0) {
			char msgb[120];
			snprintf(msgb, sizeof(msgb)
				, get_unresolved_ref_error_string(cnt), cnt);
			if (ask_yes_or_no_msg(msgb, redtopt)) {
				write_node_to_editfile(root2);
				do_edit();
				continue;
			}
		}
		break;
	}

/* If error or no change or user backs out return */
	if (!root2) return FALSE;
	if (equal_tree(root1, root2) || !ask_yes_or_no(cfrm)) {
		free_nodes(root2);
		return FALSE;
	}

/* Prepare to change database */

	/* Move root1 data into root0 & save refns */
	split_othr(root1, &refn1, &body);
	root0 = copy_node(root1);
	join_othr(root0, NULL, body);
	/* delete root0 tree & root1 node (root1 is solitary node) */
	free_nodes(root0); root0 = 0;
	free_nodes(root1); root1 = 0;
	/* now copy root2 node into root1, then root2 tree under it */
	root1 = copy_node(root2);
	split_othr(root2, &refn2, &body);
	refnn = copy_nodes(refn2, TRUE, TRUE);
	join_othr(root1, refn2, body);
	/* now root2 is solitary node, delete it */
	free_node(root2); root2 = 0;

/* Change the database */

	(*todbase)(root1);
	key = rmvat(nxref(root1));
	/* remove deleted refns & add new ones */
	classify_nodes(&refn1, &refnn, &refn1n);
	for (node = refn1; node; node = nsibling(node))
		if (nval(node)) remove_refn(nval(node), key);
	for (node = refnn; node; node = nsibling(node))
		if (nval(node)) add_refn(nval(node), key);
	free_nodes(refn1);
	free_nodes(refnn);
	free_nodes(refn1n);
	msg_info(gdmsg);
	return TRUE;
}
Exemple #18
0
/*===================================
 * 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;
}
Exemple #19
0
/*=====================================
 * 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));
    }
}
Exemple #20
0
/*================================================
 * edit_add_record -- Add record to database by editing
 *  recstr:  [IN] default record
 *  redt:    [IN] re-edit message
 *  ntype,   [IN] S, E, or X
 *  cfrm:    [IN] confirm message
 *==============================================*/
static RECORD
edit_add_record (STRING recstr, STRING redt, STRING redtopt, char ntype, STRING cfrm)
{
	FILE *fp;
	NODE node=0, refn;
	STRING msg, key;
	BOOLEAN emp;
	XLAT ttmi = transl_get_predefined_xlat(MEDIN);
	STRING (*getreffnc)(void) = NULL; /* get next internal key */
	void (*todbasefnc)(NODE) = NULL;  /* write record to dbase */
	void (*tocachefnc)(NODE) = NULL;  /* write record to cache */
	
	/* set up functions according to type */
	if (ntype == 'S') {
		getreffnc = getsxref;
		todbasefnc = sour_to_dbase;
		tocachefnc = sour_to_cache;
	} else if (ntype == 'E') {
		getreffnc = getexref;
		todbasefnc = even_to_dbase;
		tocachefnc = even_to_cache;
	} else { /* X */
		getreffnc = getxxref;
		todbasefnc = othr_to_dbase;
		tocachefnc = othr_to_cache;
	}

/* Create template for user to edit */
	if (!(fp = fopen(editfile, LLWRITETEXT))) {
		msg_error(_(qSnofopn), editfile);
		return FALSE;
	}
	prefix_file_for_edit(fp);
	fprintf(fp, "%s\n", recstr);

/* Have user edit new record */
	fclose(fp);
	do_edit();
	while (TRUE) {
		INT cnt;
		node = file_to_node(editfile, ttmi, &msg, &emp);
		if (!node) {
			if (ask_yes_or_no_msg(msg, redt)) { /* yes, edit again */
				do_edit();
				continue;
			} 
			break;
		}
		cnt = resolve_refn_links(node);
		/* check validation & allow user to reedit if invalid */
		/* this is a showstopper, so alternative is to abort */
		if (!valid_node_type(node, ntype, &msg, NULL)) {
			if (ask_yes_or_no_msg(msg, redt)) {
				do_edit();
				continue;
			}
			free_nodes(node);
			node = NULL; /* fail out */
			break;
		}
		/* Allow user to reedit if desired if any refn links unresolved */
		/* this is not a showstopper, so alternative is to continue */
		if (cnt > 0) {
			char msgb[120];
			snprintf(msgb, sizeof(msgb)
				, get_unresolved_ref_error_string(cnt), cnt);
			if (ask_yes_or_no_msg(msgb, redtopt)) {
				write_node_to_editfile(node);
				do_edit();
				continue;
			}
		}
		break;
	}
	if (!node || !ask_yes_or_no(cfrm)) {
		if (node) free_nodes(node);
		return NULL;
	}
	nxref(node) = strsave((STRING)(*getreffnc)());
	key = rmvat(nxref(node));
	for (refn = nchild(node); refn; refn = nsibling(refn)) {
		if (eqstr("REFN", ntag(refn)) && nval(refn))
			add_refn(nval(refn), key);
	}
	(*todbasefnc)(node);
	(*tocachefnc)(node);
	return key_to_record(key);
}