~ubuntu-branches/ubuntu/trusty/lifelines/trusty

« back to all changes in this revision

Viewing changes to src/liflines/merge.c

  • Committer: Bazaar Package Importer
  • Author(s): Felipe Augusto van de Wiel (faw)
  • Date: 2007-08-14 00:02:04 UTC
  • mfrom: (1.1.4 upstream) (3.1.4 gutsy)
  • Revision ID: james.westby@ubuntu.com-20070814000204-mpv5faygl0dgq3qi
Tags: 3.0.61-1
* New upstream release. (Closes: #387856).
* Fixing documentation build problems also fixes FTBFS if built twice in a
  row. (Closes: #424543).
* Adding lynx as a build dependency. This is necessary to generate txt files
  from html, discovered while fixing #424543.
* Upstream fix: charset for gedcom file in unicode. (Closes: #396206).
* Upstream fim: updating documentation about desc-tex2. (Closes: #405501).
* Bumping Standards-Version to 3.7.2 without package changes.
* Dropping local debian patches added upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include "llinesi.h"
42
42
#include "feedback.h"
43
43
 
 
44
/*********************************************
 
45
 * external/imported variables
 
46
 *********************************************/
44
47
 
45
48
extern BOOLEAN traditional;
46
49
extern STRING qSiredit, qScfpmrg, qSnopmrg, qSnoqmrg, qSnoxmrg, qSnofmrg;
51
54
static NODE remove_dupes(NODE, NODE);
52
55
static NODE sort_children(NODE, NODE);
53
56
 
 
57
 
 
58
/*********************************************
 
59
 * local function prototypes
 
60
 *********************************************/
 
61
 
 
62
/* alphabetical */
 
63
static void check_indi_lineage_links(NODE indi);
 
64
static void check_fam_lineage_links(NODE fam);
 
65
 
 
66
 
54
67
/*================================================================
55
68
 * merge_two_indis -- Merge first person to second; data from both
56
69
 *   are put in file that user edits; first person removed
85
98
 
86
99
/* Do start up checks */
87
100
 
88
 
        ASSERT(indi1 && indi2);
 
101
        ASSERT(indi1);
 
102
        ASSERT(indi2);
89
103
        ASSERT(eqstr("INDI", ntag(indi1)));
90
104
        ASSERT(eqstr("INDI", ntag(indi2)));
91
105
        if (readonly) {
102
116
        famc1 = FAMC(indi1);
103
117
        famc2 = FAMC(indi2);
104
118
/*LOOSEEND -- THIS CHECK IS NOT GOOD ENOUGH */
 
119
/* comment from merge.c 1.2 2000-01-03 nozell */
105
120
        if (traditional) {
106
121
                if (famc1 && famc2 && nestr(nval(famc1), nval(famc2))) {
107
122
                        if (!ask_yes_or_no_msg(_(qSmgsfam), _(qSmgconf))) {
117
132
                return NULL;
118
133
        }
119
134
 
 
135
 
 
136
/* sanity check lineage links */
 
137
        check_indi_lineage_links(indi1);
 
138
        check_indi_lineage_links(indi2);
 
139
 
120
140
/* Split original persons */
121
141
 
122
142
        /* If we are successful, the original indi1 will be deleted
395
415
        free_nodes(indi4);
396
416
 
397
417
        remove_indi_by_root(indi01);    /* this is the original indi1 */
 
418
 
 
419
/* sanity check lineage links */
 
420
        check_indi_lineage_links(indi02);
 
421
 
398
422
        return node_to_record(indi02);   /* this is the updated indi2 */
399
423
}
400
424
/*=================================================================
401
425
 * merge_two_fams -- Merge first family into second; data from both
402
426
 *   are put in file that user edits; first family removed
 
427
 *---------------------------------------------------------------
 
428
 *  These are the four main variables
 
429
 *   fam1 - upper family in database -- fam1 is merged into fam2
 
430
 *   fam2 - lower family in database -- fam1 is merged into this person
 
431
 *   fam3 - temporary which is the merged version for the user to edit
 
432
 *   fam4 - merged version of the two persons after editing
 
433
 *     the nodes inside fam4 are stored into fam2 & to dbase at the very end
403
434
 *===============================================================*/
404
435
RECORD
405
 
merge_two_fams (NODE fam1,
406
 
                NODE fam2)
 
436
merge_two_fams (NODE fam1, NODE fam2)
407
437
{
408
438
        NODE husb1, wife1, chil1, rest1, husb2, wife2, chil2, rest2;
409
439
        NODE fref1, fref2;
419
449
                message(_(qSronlym));
420
450
                return NULL;
421
451
        }
422
 
        ASSERT(fam1 && fam2);
 
452
        ASSERT(fam1);
 
453
        ASSERT(fam2);
423
454
        ASSERT(eqstr("FAM", ntag(fam1)));
424
455
        ASSERT(eqstr("FAM", ntag(fam2)));
425
456
        if (fam1 == fam2) {
427
458
                return NULL;
428
459
        }
429
460
 
 
461
/* sanity check lineage links */
 
462
        check_fam_lineage_links(fam1);
 
463
        check_fam_lineage_links(fam2);
 
464
 
430
465
/* Check restrictions on families */
431
466
        split_fam(fam1, &fref1, &husb1, &wife1, &chil1, &rest1);
432
467
        split_fam(fam2, &fref2, &husb2, &wife2, &chil2, &rest2);
433
468
        if (traditional) {
 
469
                BOOLEAN ok = TRUE;
434
470
                if (husb1 && husb2 && nestr(nval(husb1), nval(husb2))) {
435
471
                        message(_(qSdhusb));
436
 
                        join_fam(fam1, fref1, husb1, wife1, chil1, rest1);
437
 
                        join_fam(fam2, fref2, husb2, wife2, chil2, rest2);
438
 
                        return NULL;
 
472
                        ok = FALSE;
439
473
                }
440
 
                if (wife1 && wife2 && nestr(nval(wife1), nval(wife2))) {
 
474
                if (ok && wife1 && wife2 && nestr(nval(wife1), nval(wife2))) {
441
475
                        message(_(qSdwife));
 
476
                        ok = FALSE;
 
477
                }
 
478
                if (!ok) {
442
479
                        join_fam(fam1, fref1, husb1, wife1, chil1, rest1);
443
480
                        join_fam(fam2, fref2, husb2, wife2, chil2, rest2);
444
481
                        return NULL;
518
555
        join_fam(fam2, fref4, husb4, wife4, chil4, rest4);
519
556
        resolve_refn_links(fam2);
520
557
        fam_to_dbase(fam2);
 
558
 
 
559
 
 
560
/* sanity check lineage links */
 
561
        check_fam_lineage_links(fam2);
 
562
        
521
563
        return node_to_record(fam2);
522
564
}
523
565
/*================================================================
610
652
        NODE copy1, copy2, chil3, prev, kid1, kid2;
611
653
        STRING year1, year2;
612
654
        INT int1, int2;
 
655
        /* copy1 contains all children in chil1 not in chil2 */
613
656
        copy1 = remove_dupes(chil1, chil2);
614
657
        copy2 = copy_nodes(chil2, TRUE, TRUE);
615
658
        int1 = int2 = 1;
661
704
}
662
705
/*=================================================
663
706
 * remove_dupes -- Return all in list1 not in list2
 
707
 *  Creates a copy of list1 then traverses it
 
708
 *   removing any items which are in list2
 
709
 *  Then returns this new trimmed list.
 
710
 * This is pretty inefficient algorithm, as every item
 
711
 *  in list1 is compared against every item in list2
 
712
 * It would be more efficient to make a table of items
 
713
 *  on list2 first, and then use that to check each item
 
714
 *  in list1.
664
715
 *===============================================*/
665
716
static NODE
666
 
remove_dupes (NODE list1,
667
 
              NODE list2)
 
717
remove_dupes (NODE list1, NODE list2)
668
718
{
669
719
        NODE copy1 = copy_nodes(list1, TRUE, TRUE);
670
720
        NODE prev1, next1, curs1, curs2;
690
740
        }
691
741
        return copy1;
692
742
}
 
743
/*=================================================
 
744
 * check_indi_lineage_links -- Check all families of
 
745
 *  this person to make sure they point back to this person
 
746
 *===============================================*/
 
747
static void
 
748
check_indi_lineage_links (NODE indi)
 
749
{
 
750
        NODE name=0, refn=0, sex=0, body=0, famc=0, fams=0;
 
751
        NODE curs=0; /* for travesing node lists */
 
752
        TABLE memtab = memtab = create_table_int();
 
753
        TABLE_ITER tabit=0;
 
754
        CNSTRING famkey=0; /* used inside traversal loops */
 
755
        INT count=0;
 
756
        CNSTRING ikey = nxref(indi);
 
757
 
 
758
        /* sanity check record is not deleted */
 
759
        ASSERT(is_key_in_use(ikey));
 
760
 
 
761
/* Now validate lineage links of this person */
 
762
        split_indi_old(indi, &name, &refn, &sex, &body, &famc, &fams);
 
763
 
 
764
        /*
 
765
        Make table listing all families this person is spouse in
 
766
        (& how many times each)
 
767
        */
 
768
        for (curs = fams; curs; curs = nsibling(curs)) {
 
769
                famkey = rmvat(nval(curs));
 
770
                if (!eqstr(ntag(curs), "FAMS")) {
 
771
                        char msg[512];
 
772
                        snprintf(msg, sizeof(msg)/sizeof(msg[0]), _("Bad spouse tag: %s"), ntag(curs));
 
773
                        FATAL2(msg);
 
774
                }
 
775
                increment_table_int(memtab, famkey);
 
776
        }
 
777
 
 
778
        /*
 
779
        Check that all listed families contain person as spouse as many times
 
780
        as expected
 
781
        */
 
782
        tabit = begin_table_iter(memtab);
 
783
        while (next_table_int(tabit, &famkey, &count)) {
 
784
                NODE fam = key_to_fam(famkey);
 
785
                /*
 
786
                count how many times our main person (ikey)
 
787
                occurs in this family (fam) as a spouse (HUSB or WIFE)
 
788
                */
 
789
                INT occur = 0;
 
790
                for (curs = nchild(fam); curs; curs = nsibling(curs)) {
 
791
                        if (eqstr(ntag(curs), "HUSB") || eqstr(ntag(curs), "WIFE")) {
 
792
                                if (eqstr(nval(curs), ikey)) {
 
793
                                        ++occur;
 
794
                                }
 
795
                        }
 
796
                }
 
797
                if (count != occur) {
 
798
                        char msg[512];
 
799
                        snprintf(msg, sizeof(msg)/sizeof(msg[0])
 
800
                                , _("Mismatched lineage spouse links between %s and %s: %ld and %ld")
 
801
                                , ikey, famkey, count, occur);
 
802
                        FATAL2(msg);
 
803
                }
 
804
        }
 
805
        destroy_table(memtab);
 
806
        memtab = create_table_int();
 
807
 
 
808
        /*
 
809
        Make table listing all families this person is child in
 
810
        (& how many times each)
 
811
        */
 
812
        for (curs = famc; curs; curs = nsibling(curs)) {
 
813
                famkey = rmvat(nval(curs));
 
814
                if (!eqstr(ntag(curs), "FAMC")) {
 
815
                        char msg[512];
 
816
                        snprintf(msg, sizeof(msg)/sizeof(msg[0]), _("Bad child tag: %s"), ntag(curs));
 
817
                        FATAL2(msg);
 
818
                }
 
819
                increment_table_int(memtab, famkey);
 
820
        }
 
821
 
 
822
        /*
 
823
        Check that all listed families contain person as child (CHIL) as many times
 
824
        as expected
 
825
        */
 
826
        tabit = begin_table_iter(memtab);
 
827
        while (next_table_int(tabit, &famkey, &count)) {
 
828
                NODE fam = key_to_fam(famkey);
 
829
                /*
 
830
                count how many times our main person (ikey)
 
831
                occurs in this family (fam) as a child (CHIL)
 
832
                */
 
833
                INT occur = 0;
 
834
                for (curs = nchild(fam); curs; curs = nsibling(curs)) {
 
835
                        if (eqstr(ntag(curs), "CHIL")) {
 
836
                                if (eqstr(nval(curs), ikey)) {
 
837
                                        ++occur;
 
838
                                }
 
839
                        }
 
840
                }
 
841
                if (count != occur) {
 
842
                        char msg[512];
 
843
                        snprintf(msg, sizeof(msg)/sizeof(msg[0])
 
844
                                , _("Mismatched lineage child links between %s and %s: %ld and %ld")
 
845
                                , ikey, famkey, count, occur);
 
846
                        FATAL2(msg);
 
847
                }
 
848
        }
 
849
 
 
850
        join_indi(indi, name, refn, sex, body, famc, fams);
 
851
        destroy_table(memtab);
 
852
}
 
853
/*=================================================
 
854
 * check_fam_lineage_links -- Check all persons of
 
855
 *  this family to make sure they point back to this family
 
856
 *===============================================*/
 
857
static void
 
858
check_fam_lineage_links (NODE fam)
 
859
{
 
860
        NODE fref=0, husb=0, wife=0, chil=0, rest=0;
 
861
        NODE curs=0; /* for travesing node lists */
 
862
        TABLE memtab = memtab = create_table_int();
 
863
        TABLE_ITER tabit=0;
 
864
        CNSTRING indikey=0; /* used inside traversal loops */
 
865
        INT count=0;
 
866
        CNSTRING fkey = nxref(fam);
 
867
 
 
868
        /* sanity check record is not deleted */
 
869
        ASSERT(is_key_in_use(fkey));
 
870
        
 
871
/* Now validate lineage links of this family */
 
872
        split_fam(fam, &fref, &husb, &wife, &chil, &rest);
 
873
 
 
874
        /*
 
875
        Make table listing all spouses in this family
 
876
        (& how many times each)
 
877
        */
 
878
        for (curs = husb; curs; curs = nsibling(curs)) {
 
879
                indikey = rmvat(nval(curs));
 
880
                if (!eqstr(ntag(curs), "HUSB")) {
 
881
                        char msg[512];
 
882
                        snprintf(msg, sizeof(msg)/sizeof(msg[0]), _("Bad HUSB tag: %s"), ntag(curs));
 
883
                        FATAL2(msg);
 
884
                }
 
885
                increment_table_int(memtab, indikey);
 
886
        }
 
887
        for (curs = wife; curs; curs = nsibling(curs)) {
 
888
                indikey = rmvat(nval(curs));
 
889
                if (!eqstr(ntag(curs), "WIFE")) {
 
890
                        char msg[512];
 
891
                        snprintf(msg, sizeof(msg)/sizeof(msg[0]), _("Bad HUSB tag: %s"), ntag(curs));
 
892
                        FATAL2(msg);
 
893
                }
 
894
                increment_table_int(memtab, indikey);
 
895
        }
 
896
 
 
897
        /*
 
898
        Check that all listed persons contain family as FAMS as many times
 
899
        as expected
 
900
        */
 
901
        tabit = begin_table_iter(memtab);
 
902
        while (next_table_int(tabit, &indikey, &count)) {
 
903
                NODE indi = key_to_indi(indikey);
 
904
                /*
 
905
                count how many times our main family (fkey)
 
906
                occurs in this person (indi) as a spousal family (FAMS)
 
907
                */
 
908
                INT occur = 0;
 
909
                for (curs = nchild(indi); curs; curs = nsibling(curs)) {
 
910
                        if (eqstr(ntag(curs), "FAMS")) {
 
911
                                if (eqstr(nval(curs), fkey)) {
 
912
                                        ++occur;
 
913
                                }
 
914
                        }
 
915
                }
 
916
                if (count != occur) {
 
917
                        char msg[512];
 
918
                        snprintf(msg, sizeof(msg)/sizeof(msg[0])
 
919
                                , _("Mismatched lineage spouse links between %s and %s: %ld and %ld")
 
920
                                , fkey, indikey, count, occur);
 
921
                        FATAL2(msg);
 
922
                }
 
923
        }
 
924
        destroy_table(memtab);
 
925
        memtab = create_table_int();
 
926
 
 
927
        /*
 
928
        Make table listing all families this person is child in
 
929
        (& how many times each)
 
930
        */
 
931
        for (curs = chil; curs; curs = nsibling(curs)) {
 
932
                indikey = rmvat(nval(curs));
 
933
                if (!eqstr(ntag(curs), "CHIL")) {
 
934
                        char msg[512];
 
935
                        snprintf(msg, sizeof(msg)/sizeof(msg[0]), _("Bad child tag: %s"), ntag(curs));
 
936
                        FATAL2(msg);
 
937
                }
 
938
                increment_table_int(memtab, indikey);
 
939
        }
 
940
 
 
941
        /*
 
942
        Check that all listed families contain person as FAMC as many times
 
943
        as expected
 
944
        */
 
945
        tabit = begin_table_iter(memtab);
 
946
        while (next_table_int(tabit, &indikey, &count)) {
 
947
                NODE indi = key_to_indi(indikey);
 
948
                /*
 
949
                count how many times our main family (fkey)
 
950
                occurs in this person (indi) as a parental family (FAMC)
 
951
                */
 
952
                INT occur = 0;
 
953
                for (curs = nchild(indi); curs; curs = nsibling(curs)) {
 
954
                        if (eqstr(ntag(curs), "FAMC")) {
 
955
                                if (eqstr(nval(curs), fkey)) {
 
956
                                        ++occur;
 
957
                                }
 
958
                        }
 
959
                }
 
960
                if (count != occur) {
 
961
                        char msg[512];
 
962
                        snprintf(msg, sizeof(msg)/sizeof(msg[0])
 
963
                                , _("Mismatched lineage child links between %s and %s: %ld and %ld")
 
964
                                , fkey, indikey, count, occur);
 
965
                        FATAL2(msg);
 
966
                }
 
967
        }
 
968
        
 
969
        
 
970
        join_fam(fam, fref, husb, wife, chil, rest);
 
971
}