/*===================================== * write_indi_to_file_for_edit - write node tree into GEDCOM * file to be edited * (no user interaction) *===================================*/ void write_indi_to_file_for_edit (NODE indi, CNSTRING file, RFMT rfmt) { annotate_with_supplemental(indi, rfmt); write_indi_to_file(indi, file); resolve_refn_links(indi); }
/*===================================== * write_indi_to_file_for_edit - write node tree into GEDCOM * file to be edited * (no user interaction) *===================================*/ void write_fam_to_file_for_edit (NODE fam, CNSTRING file, RFMT rfmt) { annotate_with_supplemental(fam, rfmt); write_fam_to_file(fam, file); resolve_refn_links(fam); }
/*====================================== * 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); }
/*===================================== * 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); }
/*================================================================ * 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; }
/*========================================================== * 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); }
/*========================================================== * add_indi_by_edit -- Add new person to database by editing * (with user interaction) * returns addref'd record *========================================================*/ RECORD add_indi_by_edit (RFMT rfmt) { FILE *fp; RECORD indi0=0; NODE indi=0; STRING str, msg; BOOLEAN emp; XLAT ttmi = transl_get_predefined_xlat(MEDIN); if (readonly) { message(_(qSronlya)); return NULL; } /* Create person template for user to edit */ if (!(fp = fopen(editfile, LLWRITETEXT))) return NULL; prefix_file_for_edit(fp); /* prefer useroption in this db */ if ((str = getlloptstr("INDIREC", NULL))) fprintf(fp, "%s\n", str); else { /* default */ fprintf(fp, "0 INDI\n1 NAME Fname/Surname\n1 SEX MF\n"); fprintf(fp, "1 BIRT\n 2 DATE\n 2 PLAC\n"); fprintf(fp, "1 DEAT\n 2 DATE\n 2 PLAC\n1 SOUR\n"); } /* Have user edit new person record */ fclose(fp); do_edit(); while (TRUE) { INT cnt; if (indi0) { release_record(indi0); indi0=0; } indi0 = file_to_record(editfile, ttmi, &msg, &emp); if (!indi0) { if (ask_yes_or_no_msg(msg, _(qSiredit))) { do_edit(); continue; } break; } indi = nztop(indi0); cnt = resolve_refn_links(indi); /* check validation & allow user to reedit if invalid */ /* this is a showstopper, so alternative is to abort */ if (!valid_indi_tree(indi, &msg, NULL)) { if (ask_yes_or_no_msg(msg, _(qSiredit))) { do_edit(); continue; } release_record(indi0); indi0 = 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]; llstrncpyf(msgb, sizeof(msgb), uu8 , get_unresolved_ref_error_string(cnt), cnt); if (ask_yes_or_no_msg(msgb, _(qSireditopt))) { write_indi_to_file_for_edit(indi, editfile, rfmt); do_edit(); continue; } } break; } if (!indi0 || !ask_yes_or_no(_(qScfpadd))) { if (indi0) release_record(indi0); return NULL; } /* add the new record to the database */ add_new_indi_to_db(indi0); msg_status(_(qSgdpadd), indi_to_name(nztop(indi0), 35)); return indi0; }
/*======================================= * 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; }
/*================================================ * 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); }