/*=============================================== * index_by_refn - Index node tree by REFN values * Adds all REFN values in node tree to refn index * Assumes all are new (only for use with brand new records) *=============================================*/ void index_by_refn (NODE node, STRING key) { if (!node || !key) return; for (node = nchild(node); node; node = nsibling(node)) { if (eqstr("REFN", ntag(node)) && nval(node)) add_refn(nval(node), key); } }
/*================================================================ * 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); }
/*======================================= * 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); }