From 379830cf651c9d5fee020e36da9110756d66d468 Mon Sep 17 00:00:00 2001
From: Don Allingham <don@gramps-project.org>
Date: Sat, 6 Oct 2001 18:25:31 +0000
Subject: [PATCH] Faster GEDCOM imports, source lists

svn: r448
---
 gramps/src/EditPerson.glade       | 155 +++++--------------
 gramps/src/EditPerson.py          | 129 ++++++++--------
 gramps/src/EditPlace.py           |  22 +--
 gramps/src/GrampsParser.py        |  28 ++--
 gramps/src/Marriage.py            |  64 ++------
 gramps/src/RelLib.py              |  46 ++++--
 gramps/src/Sources.py             | 118 +++++++++-----
 gramps/src/TarFile.py             |  48 +++++-
 gramps/src/WriteXML.py            |  60 ++++----
 gramps/src/const.py               |   3 +
 gramps/src/dialog.glade           | 140 +++--------------
 gramps/src/gramps.glade           | 245 +++++++++++++++++++++++++++++-
 gramps/src/gramps_main.py         |  20 ++-
 gramps/src/latin_ansel.py         |  39 ++---
 gramps/src/plugins/ReadGedcom.py  | 121 +++++++++------
 gramps/src/plugins/WebPage.py     |   6 +-
 gramps/src/plugins/WriteGedcom.py |  50 ++++--
 gramps/src/utils.py               |   4 +-
 18 files changed, 738 insertions(+), 560 deletions(-)

diff --git a/gramps/src/EditPerson.glade b/gramps/src/EditPerson.glade
index fa5304a3a..f93cd1a8d 100644
--- a/gramps/src/EditPerson.glade
+++ b/gramps/src/EditPerson.glade
@@ -740,6 +740,21 @@
 		  <fill>False</fill>
 		</child>
 	      </widget>
+
+	      <widget>
+		<class>GtkRadioButton</class>
+		<name>genderUnknown</name>
+		<can_focus>True</can_focus>
+		<label>unknown</label>
+		<active>False</active>
+		<draw_indicator>True</draw_indicator>
+		<group>gender</group>
+		<child>
+		  <padding>0</padding>
+		  <expand>False</expand>
+		  <fill>False</fill>
+		</child>
+	      </widget>
 	    </widget>
 	  </widget>
 
@@ -4116,7 +4131,7 @@
       <widget>
 	<class>GtkTable</class>
 	<name>table23</name>
-	<rows>6</rows>
+	<rows>5</rows>
 	<columns>2</columns>
 	<homogeneous>False</homogeneous>
 	<row_spacing>0</row_spacing>
@@ -4179,32 +4194,6 @@
 	  </child>
 	</widget>
 
-	<widget>
-	  <class>GtkLabel</class>
-	  <name>label182</name>
-	  <label>Source</label>
-	  <justify>GTK_JUSTIFY_CENTER</justify>
-	  <wrap>False</wrap>
-	  <xalign>1</xalign>
-	  <yalign>0.5</yalign>
-	  <xpad>5</xpad>
-	  <ypad>8</ypad>
-	  <child>
-	    <left_attach>0</left_attach>
-	    <right_attach>1</right_attach>
-	    <top_attach>3</top_attach>
-	    <bottom_attach>4</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
-
 	<widget>
 	  <class>GtkScrolledWindow</class>
 	  <name>scrolledwindow23</name>
@@ -4217,8 +4206,8 @@
 	  <child>
 	    <left_attach>1</left_attach>
 	    <right_attach>2</right_attach>
-	    <top_attach>5</top_attach>
-	    <bottom_attach>6</bottom_attach>
+	    <top_attach>4</top_attach>
+	    <bottom_attach>5</bottom_attach>
 	    <xpad>3</xpad>
 	    <ypad>3</ypad>
 	    <xexpand>False</xexpand>
@@ -4251,8 +4240,8 @@
 	  <child>
 	    <left_attach>0</left_attach>
 	    <right_attach>1</right_attach>
-	    <top_attach>5</top_attach>
-	    <bottom_attach>6</bottom_attach>
+	    <top_attach>4</top_attach>
+	    <bottom_attach>5</bottom_attach>
 	    <xpad>0</xpad>
 	    <ypad>0</ypad>
 	    <xexpand>False</xexpand>
@@ -4285,13 +4274,12 @@
 	  </child>
 
 	  <widget>
-	    <class>GtkEntry</class>
-	    <name>alt_source</name>
+	    <class>GtkCheckButton</class>
+	    <name>priv</name>
 	    <can_focus>True</can_focus>
-	    <editable>False</editable>
-	    <text_visible>True</text_visible>
-	    <text_max_length>0</text_max_length>
-	    <text></text>
+	    <label>Private Record</label>
+	    <active>False</active>
+	    <draw_indicator>True</draw_indicator>
 	    <child>
 	      <padding>3</padding>
 	      <expand>True</expand>
@@ -4431,29 +4419,6 @@
 	    <yfill>False</yfill>
 	  </child>
 	</widget>
-
-	<widget>
-	  <class>GtkCheckButton</class>
-	  <name>priv</name>
-	  <can_focus>True</can_focus>
-	  <label>Private Record</label>
-	  <active>False</active>
-	  <draw_indicator>True</draw_indicator>
-	  <child>
-	    <left_attach>1</left_attach>
-	    <right_attach>2</right_attach>
-	    <top_attach>4</top_attach>
-	    <bottom_attach>5</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
       </widget>
     </widget>
   </widget>
@@ -4572,7 +4537,7 @@
       <widget>
 	<class>GtkTable</class>
 	<name>table26</name>
-	<rows>9</rows>
+	<rows>8</rows>
 	<columns>2</columns>
 	<homogeneous>False</homogeneous>
 	<row_spacing>0</row_spacing>
@@ -4635,32 +4600,6 @@
 	  </child>
 	</widget>
 
-	<widget>
-	  <class>GtkLabel</class>
-	  <name>label211</name>
-	  <label>Source</label>
-	  <justify>GTK_JUSTIFY_CENTER</justify>
-	  <wrap>False</wrap>
-	  <xalign>1</xalign>
-	  <yalign>0.5</yalign>
-	  <xpad>5</xpad>
-	  <ypad>8</ypad>
-	  <child>
-	    <left_attach>0</left_attach>
-	    <right_attach>1</right_attach>
-	    <top_attach>6</top_attach>
-	    <bottom_attach>7</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
-
 	<widget>
 	  <class>GtkEntry</class>
 	  <name>street</name>
@@ -4697,8 +4636,8 @@
 	  <child>
 	    <left_attach>1</left_attach>
 	    <right_attach>2</right_attach>
-	    <top_attach>8</top_attach>
-	    <bottom_attach>9</bottom_attach>
+	    <top_attach>7</top_attach>
+	    <bottom_attach>8</bottom_attach>
 	    <xpad>3</xpad>
 	    <ypad>3</ypad>
 	    <xexpand>False</xexpand>
@@ -4731,8 +4670,8 @@
 	  <child>
 	    <left_attach>0</left_attach>
 	    <right_attach>1</right_attach>
-	    <top_attach>8</top_attach>
-	    <bottom_attach>9</bottom_attach>
+	    <top_attach>7</top_attach>
+	    <bottom_attach>8</bottom_attach>
 	    <xpad>0</xpad>
 	    <ypad>0</ypad>
 	    <xexpand>False</xexpand>
@@ -4765,13 +4704,12 @@
 	  </child>
 
 	  <widget>
-	    <class>GtkEntry</class>
-	    <name>addr_source</name>
+	    <class>GtkCheckButton</class>
+	    <name>priv</name>
 	    <can_focus>True</can_focus>
-	    <editable>False</editable>
-	    <text_visible>True</text_visible>
-	    <text_max_length>0</text_max_length>
-	    <text></text>
+	    <label>Private Record</label>
+	    <active>False</active>
+	    <draw_indicator>True</draw_indicator>
 	    <child>
 	      <padding>3</padding>
 	      <expand>True</expand>
@@ -5025,29 +4963,6 @@
 	    <yfill>False</yfill>
 	  </child>
 	</widget>
-
-	<widget>
-	  <class>GtkCheckButton</class>
-	  <name>priv</name>
-	  <can_focus>True</can_focus>
-	  <label>Private Record</label>
-	  <active>False</active>
-	  <draw_indicator>True</draw_indicator>
-	  <child>
-	    <left_attach>1</left_attach>
-	    <right_attach>2</right_attach>
-	    <top_attach>7</top_attach>
-	    <bottom_attach>8</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
       </widget>
     </widget>
   </widget>
diff --git a/gramps/src/EditPerson.py b/gramps/src/EditPerson.py
index d7a2fc1eb..44a632fce 100644
--- a/gramps/src/EditPerson.py
+++ b/gramps/src/EditPerson.py
@@ -143,6 +143,8 @@ class EditPerson:
         self.dplace = self.get_widget("deathPlace")
         self.is_male = self.get_widget("genderMale")
         self.is_female = self.get_widget("genderFemale")
+        self.is_unknown = self.get_widget("genderUnknown")
+        self.addr_note = self.get_widget("addr_note")
         self.addr_note = self.get_widget("addr_note")
         self.addr_source = self.get_widget("addr_source")
         self.attr_note = self.get_widget("attr_note")
@@ -246,8 +248,10 @@ class EditPerson:
 
         if person.getGender() == Person.male:
             self.is_male.set_active(1)
-        else:
+        elif person.getGender() == Person.male:
             self.is_female.set_active(1)
+        else:
+            self.is_unknown.set_active(1)
 
         self.nick.set_text(person.getNickName())
         self.title.set_text(self.pname.getTitle())
@@ -399,7 +403,6 @@ class EditPerson:
             self.person.setAddressList(self.plist)
             utils.modified()
 
-
 #-------------------------------------------------------------------------
 #
 # PersonImageSelect class
@@ -491,7 +494,9 @@ def did_data_change(obj):
     bplace = string.strip(epo.bplace.get_text())
     ddate  = epo.ddate.get_text()
     dplace = epo.dplace.get_text()
-    gender = epo.is_male.get_active()
+    male = epo.is_male.get_active()
+    female = epo.is_female.get_active()
+    unknown = epo.is_unknown.get_active()
     text = epo.notes_field.get_chars(0,-1)
     idval = epo.gid.get_text()
 
@@ -508,8 +513,6 @@ def did_data_change(obj):
         changed = 1
     if epo.pname.getNote() != name.getNote():
         changed = 1
-    if not epo.pname.getSourceRef().are_equal(name.getSourceRef()):
-        changed = 1
 
     if not epo.birth.are_equal(epo.person.getBirth()):
         changed = 1
@@ -517,9 +520,11 @@ def did_data_change(obj):
     if not epo.death.are_equal(epo.person.getDeath()):
         changed = 1
 
-    if gender and person.getGender() == Person.female:
+    if male and person.getGender() != Person.male:
         changed = 1
-    if not gender and person.getGender() == Person.male:
+    elif female and person.getGender() != Person.female:
+        changed = 1
+    elif unknown and person.getGender() != Person.unknown:
         changed = 1
     if text != person.getNote() or epo.lists_changed:
         changed = 1
@@ -1162,9 +1167,11 @@ def save_person(obj):
     if not person.getDeath().are_equal(epo.death):
         person.setDeath(epo.death)
 
-    gender = epo.is_male.get_active()
+    male = epo.is_male.get_active()
+    female = epo.is_female.get_active()
+    unknown = epo.is_unknown.get_active()
     error = 0
-    if gender and person.getGender() == Person.female:
+    if male and person.getGender() != Person.male:
         person.setGender(Person.male)
         for temp_family in person.getFamilyList():
             if person == temp_family.getMother():
@@ -1174,7 +1181,7 @@ def save_person(obj):
                     temp_family.setMother(None)
                     temp_family.setFather(person)
         utils.modified()
-    elif not gender and person.getGender() == Person.male:
+    elif female and person.getGender() != Person.female:
         person.setGender(Person.female)
         for temp_family in person.getFamilyList():
             if person == temp_family.getFather():
@@ -1184,6 +1191,23 @@ def save_person(obj):
                     temp_family.setFather(None)
                     temp_family.setMother(person)
         utils.modified()
+    elif unknown and person.getGender() != Person.unknown:
+        person.setGender(Person.unknown)
+        for temp_family in person.getFamilyList():
+            if person == temp_family.getFather():
+                if temp_family.getMother() != None:
+                    error = 1
+                else:
+                    temp_family.setFather(None)
+                    temp_family.setMother(person)
+            if person == temp_family.getMother():
+                if temp_family.getFather() != None:
+                    error = 1
+                else:
+                    temp_family.setMother(None)
+                    temp_family.setFather(person)
+        utils.modified()
+
 
     if error == 1:
         msg = _("Changing the gender caused problems with marriage information.")
@@ -1270,7 +1294,7 @@ def on_death_note_clicked(obj):
 #-------------------------------------------------------------------------
 def on_death_source_clicked(obj):
     epo = obj.get_data(EDITPERSON)
-    Sources.SourceEditor(epo.death.getSourceRef(),epo.db)
+    Sources.SourceSelector(epo.death.getSourceRefList(),epo,src_changed)
 
 #-------------------------------------------------------------------------
 #
@@ -1279,7 +1303,7 @@ def on_death_source_clicked(obj):
 #-------------------------------------------------------------------------
 def on_primary_name_source_clicked(obj):
     epo = obj.get_data(EDITPERSON)
-    Sources.SourceEditor(epo.pname.getSourceRef(),epo.db)
+    Sources.SourceSelector(epo.pname.getSourceRefList(),epo,src_changed)
 
 #-------------------------------------------------------------------------
 #
@@ -1288,7 +1312,7 @@ def on_primary_name_source_clicked(obj):
 #-------------------------------------------------------------------------
 def on_birth_source_clicked(obj):
     epo = obj.get_data(EDITPERSON)
-    Sources.SourceEditor(epo.birth.getSourceRef(),epo.db)
+    Sources.SourceSelector(epo.birth.getSourceRefList(),epo,src_changed)
 
 #-------------------------------------------------------------------------
 #
@@ -1409,10 +1433,10 @@ class EventEditor:
     def __init__(self,parent,event):
         self.parent = parent
         self.event = event
-        if self.event:
-            self.srcref = SourceRef(self.event.getSourceRef())
+        if event:
+            self.srcreflist = self.event.getSourceRefList()
         else:
-            self.srcref = SourceRef()
+            self.srcreflist = []
         self.top = libglade.GladeXML(const.dialogFile, "event_edit")
         self.window = self.top.get_widget("event_edit")
         self.name_field  = self.top.get_widget("eventName")
@@ -1423,7 +1447,6 @@ class EventEditor:
         self.descr_field = self.top.get_widget("eventDescription")
         self.note_field = self.top.get_widget("eventNote")
         self.event_menu = self.top.get_widget("personalEvents")
-        self.source_field = self.top.get_widget("event_source")
         self.priv = self.top.get_widget("priv")
         
         name = parent.person.getPrimaryName().getName()
@@ -1449,12 +1472,6 @@ class EventEditor:
             self.descr_field.set_text(event.getDescription())
             self.priv.set_active(event.getPrivacy())
             
-            srcref_base = self.event.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
-                 
             self.note_field.set_point(0)
             self.note_field.insert_defaults(event.getNote())
             self.note_field.set_word_wrap(1)
@@ -1475,7 +1492,7 @@ class EventEditor:
 #-------------------------------------------------------------------------
 def on_edit_source_clicked(obj):
     ee = obj.get_data(OBJECT)
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
             
 #-------------------------------------------------------------------------
 #
@@ -1497,6 +1514,7 @@ def on_event_edit_ok_clicked(obj):
 
     if event == None:
         event = Event()
+        event.setSourceRefList(ee.srcreflist)
         ee.parent.elist.append(event)
 
     if eplace_obj == None and eplace != "":
@@ -1507,10 +1525,6 @@ def on_event_edit_ok_clicked(obj):
     if update_event(event,ename,edate,eplace_obj,edesc,enote,epriv,ecause):
         ee.parent.lists_changed = 1
         
-    if not event.getSourceRef().are_equal(ee.srcref):
-        event.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-        
     ee.parent.redraw_event_list()
     ee.parent.update_birth_death()
     utils.destroy_passed_object(obj)
@@ -1531,12 +1545,11 @@ class AttributeEditor:
         self.value_field = self.top.get_widget("attr_value")
         self.note_field = self.top.get_widget("attr_note")
         self.attrib_menu = self.top.get_widget("attr_menu")
-        self.source_field = self.top.get_widget("attr_source")
         self.priv = self.top.get_widget("priv")
         if self.attrib:
-            self.srcref = SourceRef(self.attrib.getSourceRef())
+            self.srcreflist = self.attrib.getSourceRefList()
         else:
-            self.srcref = SourceRef()
+            self.srcreflist = []
 
         # Typing CR selects OK button
         self.window.editable_enters(self.type_field);
@@ -1550,11 +1563,6 @@ class AttributeEditor:
         if attrib != None:
             self.type_field.set_text(attrib.getType())
             self.value_field.set_text(attrib.getValue())
-            srcref_base = self.attrib.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
             self.priv.set_active(attrib.getPrivacy())
 
             self.note_field.set_point(0)
@@ -1575,7 +1583,7 @@ class AttributeEditor:
 #-------------------------------------------------------------------------
 def on_attrib_source_clicked(obj):
     ee = obj.get_data(OBJECT)
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
             
 #-------------------------------------------------------------------------
 #
@@ -1593,15 +1601,12 @@ def on_attrib_edit_ok_clicked(obj):
 
     if attrib == None:
         attrib = Attribute()
+        attrib.setSourceRefList(ee.srcreflist)
         ee.parent.alist.append(attrib)
         
     if update_attrib(attrib,type,value,note,priv):
         ee.parent.lists_changed = 1
         
-    if not attrib.getSourceRef().are_equal(ee.srcref):
-        attrib.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-
     ee.parent.redraw_attr_list()
     utils.destroy_passed_object(obj)
 
@@ -1621,13 +1626,13 @@ class NameEditor:
         self.surname_field = self.top.get_widget("alt_last")
         self.suffix_field = self.top.get_widget("alt_suffix")
         self.note_field = self.top.get_widget("alt_note")
-        self.source_field = self.top.get_widget("alt_source")
         self.top.get_widget("alt_surname_list").set_popdown_strings(const.surnames)
         self.priv = self.top.get_widget("priv")
+
         if self.name:
-            self.srcref = SourceRef(self.name.getSourceRef())
+            self.srcreflist = self.name.getSourceRefList()
         else:
-            self.srcref = SourceRef()
+            self.srcreflist = []
 
         full_name = parent.person.getPrimaryName().getName()
         
@@ -1643,11 +1648,6 @@ class NameEditor:
             self.given_field.set_text(name.getFirstName())
             self.surname_field.set_text(name.getSurname())
             self.suffix_field.set_text(name.getSuffix())
-            srcref_base = self.name.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
             self.priv.set_active(name.getPrivacy())
             self.note_field.set_point(0)
             self.note_field.insert_defaults(name.getNote())
@@ -1667,7 +1667,7 @@ class NameEditor:
 #-------------------------------------------------------------------------
 def on_name_source_clicked(obj):
     ee = obj.get_data(OBJECT)
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
             
 #-------------------------------------------------------------------------
 #
@@ -1686,15 +1686,12 @@ def on_name_edit_ok_clicked(obj):
 
     if name == None:
         name = Name()
+        name.setSourceRefList(ee.srcreflist)
         ee.parent.nlist.append(name)
         
     if update_name(name,first,last,suffix,note,priv):
         ee.parent.lists_changed = 1
 
-    if not name.getSourceRef().are_equal(ee.srcref):
-        name.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-
     ee.parent.redraw_name_list()
     utils.destroy_passed_object(obj)
 
@@ -1717,12 +1714,12 @@ class AddressEditor:
         self.country = self.top.get_widget("country")
         self.postal = self.top.get_widget("postal")
         self.note_field = self.top.get_widget("addr_note")
-        self.source_field = self.top.get_widget("addr_source")
         self.priv = self.top.get_widget("priv")
+
         if self.addr:
-            self.srcref = SourceRef(self.addr.getSourceRef())
+            self.srcreflist = self.addr.getSourceRefList()
         else:
-            self.srcref = SourceRef()
+            self.srcreflist = []
 
         name = parent.person.getPrimaryName().getName()
         text = _("Address Editor for %s") % name
@@ -1735,7 +1732,6 @@ class AddressEditor:
         self.window.editable_enters(self.state);
         self.window.editable_enters(self.country);
         self.window.editable_enters(self.postal);
-        self.window.editable_enters(self.source_field);
         self.window.editable_enters(self.note_field);
         
         if addr != None:
@@ -1744,11 +1740,6 @@ class AddressEditor:
             self.state.set_text(addr.getState())
             self.country.set_text(addr.getCountry())
             self.postal.set_text(addr.getPostal())
-            srcref_base = self.addr.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
                  
             self.priv.set_active(addr.getPrivacy())
             self.note_field.set_point(0)
@@ -1769,8 +1760,11 @@ class AddressEditor:
 #-------------------------------------------------------------------------
 def on_addr_source_clicked(obj):
     ee = obj.get_data(OBJECT)
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
-            
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
+
+def src_changed(parent):
+    parent.list_changed = 1
+    
 #-------------------------------------------------------------------------
 #
 #
@@ -1791,15 +1785,12 @@ def on_addr_edit_ok_clicked(obj):
 
     if addr == None:
         addr = Address()
+        addr.setSourceRefList(ee.srcreflist)
         ee.parent.plist.append(addr)
         
     if update_address(addr,date,street,city,state,country,postal,note,priv):
         ee.parent.lists_changed = 1
         
-    if not addr.getSourceRef().are_equal(ee.srcref):
-        addr.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-
     ee.parent.redraw_addr_list()
     utils.destroy_passed_object(obj)
 
diff --git a/gramps/src/EditPlace.py b/gramps/src/EditPlace.py
index 3dfa43ef9..954c6cc70 100644
--- a/gramps/src/EditPlace.py
+++ b/gramps/src/EditPlace.py
@@ -69,8 +69,12 @@ class EditPlace:
         self.callback = func
         self.path = db.getSavePath()
         self.not_loaded = 1
-        self.sref = SourceRef(place.getSourceRef())
-
+        self.list_changed = 0
+        if place:
+            self.srcreflist = place.getSourceRefList()
+        else:
+            self.srcreflist = []
+            
         self.selectedIcon = -1
         self.currentImages = []
         self.top_window = libglade.GladeXML(const.placesFile,"placeEditor")
@@ -87,7 +91,6 @@ class EditPlace:
         self.web_url = self.top_window.get_widget("web_url")
         self.web_go = self.top_window.get_widget("web_go")
         self.web_description = self.top_window.get_widget("url_des")
-        self.source_field = self.top_window.get_widget("source_field")
         
         self.loc_list = self.top_window.get_widget("loc_list")
         self.loc_city = self.top_window.get_widget("loc_city")
@@ -107,10 +110,6 @@ class EditPlace:
         self.country.set_text(mloc.get_country())
         self.longitude.set_text(place.get_longitude())
         self.latitude.set_text(place.get_latitude())
-        if self.sref.getBase():
-            self.source_field.set_text(self.sref.getBase().getTitle())
-        else:
-            self.source_field.set_text("")
 
         self.note.set_point(0)
         self.note.insert_defaults(place.getNote())
@@ -281,8 +280,8 @@ def on_place_apply_clicked(obj):
         mloc.set_city(city)
         utils.modified()
 
-    if not edit.place.getSourceRef().are_equal(edit.sref):
-        edit.place.setSourceRef(edit.sref)
+    if edit.list_changed:
+        edit.place.setSourceRefList(edit.srcreflist)
         utils.modified()
 
     if state != mloc.get_state():
@@ -535,7 +534,10 @@ def on_add_loc_clicked(obj):
 #-------------------------------------------------------------------------
 def on_source_clicked(obj):
     epo = obj.get_data(_PLACE)
-    Sources.SourceEditor(epo.sref,epo.db,epo.source_field)
+    Sources.SourceSelector(epo.srcreflist,epo,src_changed)
+
+def src_changed(parent):
+    parent.list_changed = 1
 
 #-------------------------------------------------------------------------
 #
diff --git a/gramps/src/GrampsParser.py b/gramps/src/GrampsParser.py
index 34887f44a..dfc404383 100644
--- a/gramps/src/GrampsParser.py
+++ b/gramps/src/GrampsParser.py
@@ -414,15 +414,15 @@ class GrampsParser(handler.ContentHandler):
             self.source_ref.confidence = self.conf
         self.source_ref.setBase(source)
         if self.event:
-            self.event.setSourceRef(self.source_ref)
+            self.event.addSourceRef(self.source_ref)
         elif self.address:
-            self.address.setSourceRef(self.source_ref)
+            self.address.addSourceRef(self.source_ref)
         elif self.name:
-            self.name.setSourceRef(self.source_ref)
+            self.name.addSourceRef(self.source_ref)
         elif self.attribute:
-            self.attribute.setSourceRef(self.source_ref)
+            self.attribute.addSourceRef(self.source_ref)
         elif self.placeobj:
-            self.placeobj.setSourceRef(self.source_ref)
+            self.placeobj.addSourceRef(self.source_ref)
         else: 
             print "Sorry, I'm lost"
 
@@ -638,7 +638,13 @@ class GrampsParser(handler.ContentHandler):
     #
     #---------------------------------------------------------------------
     def stop_gender(self,tag):
-        self.person.gender = (u2l(tag) == "M")
+        t = u2l(tag)
+        if t == "M":
+            self.person.gender = Person.male
+        elif t == "F":
+            self.person.gender = Person.female
+        else:
+            self.person.gender = Person.unknown
 
     #---------------------------------------------------------------------
     #
@@ -1107,15 +1113,15 @@ class GrampsImportParser(GrampsParser):
         self.source = self.db.findSource(u2l(attrs["ref"]),self.smap)
         self.source_ref.setBase(self.source)
         if self.address:
-            self.address.setSourceRef(self.source_ref)
+            self.address.addSourceRef(self.source_ref)
         elif self.name:
-            self.name.setSourceRef(self.source_ref)
+            self.name.addSourceRef(self.source_ref)
         elif self.event:
-            self.event.setSourceRef(self.source_ref)
+            self.event.addSourceRef(self.source_ref)
         elif self.attribute:
-            self.attribute.setSourceRef(self.source_ref)
+            self.attribute.addSourceRef(self.source_ref)
         elif self.placeobj:
-            self.placeobj.setSourceRef(self.source_ref)
+            self.placeobj.addSourceRef(self.source_ref)
         else: 
             print "Sorry, I'm lost"
 
diff --git a/gramps/src/Marriage.py b/gramps/src/Marriage.py
index e9e2e1c9f..e42f53df7 100644
--- a/gramps/src/Marriage.py
+++ b/gramps/src/Marriage.py
@@ -682,10 +682,7 @@ class EventEditor:
     def __init__(self,parent,event):
         self.parent = parent
         self.event = event
-        if self.event:
-            self.srcref = SourceRef(self.event.getSourceRef())
-        else:
-            self.srcref = SourceRef()
+        self.srcreflist = self.event.getSourceRefList()
         self.top = libglade.GladeXML(const.dialogFile, "event_edit")
         self.window = self.top.get_widget("event_edit")
         self.name_field  = self.top.get_widget("eventName")
@@ -697,7 +694,6 @@ class EventEditor:
         self.descr_field = self.top.get_widget("eventDescription")
         self.note_field = self.top.get_widget("eventNote")
         self.event_menu = self.top.get_widget("personalEvents")
-        self.source_field = self.top.get_widget("event_source")
         self.priv = self.top.get_widget("priv")
 
         father = parent.family.getFather()
@@ -731,12 +727,6 @@ class EventEditor:
             self.descr_field.set_text(event.getDescription())
             self.priv.set_active(event.getPrivacy())
             
-            srcref_base = self.event.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
-                 
             self.note_field.set_point(0)
             self.note_field.insert_defaults(event.getNote())
             self.note_field.set_word_wrap(1)
@@ -757,7 +747,10 @@ class EventEditor:
 #-------------------------------------------------------------------------
 def on_edit_source_clicked(obj):
     ee = obj.get_data("o")
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
+
+def src_changed(parent):
+    parent.list_changed = 1
             
 #-------------------------------------------------------------------------
 #
@@ -779,6 +772,7 @@ def on_event_edit_ok_clicked(obj):
 
     if event == None:
         event = Event()
+        event.setSourceRefList(ee.srcreflist)
         ee.parent.elist.append(event)
         
     if eplace_obj == None and eplace != "":
@@ -789,10 +783,6 @@ def on_event_edit_ok_clicked(obj):
     if update_event(event,ename,edate,eplace_obj,edesc,enote,epriv,ecause):
         ee.parent.lists_changed = 1
         
-    if not source_refs_equal(event.getSourceRef(),ee.srcref):
-        event.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-
     ee.parent.redraw_events()
     utils.destroy_passed_object(obj)
 
@@ -814,11 +804,12 @@ class AttributeEditor:
         self.attrib_menu = self.top.get_widget("attr_menu")
         self.source_field = self.top.get_widget("attr_source")
         self.priv = self.top.get_widget("priv")
-        if self.attrib:
-            self.srcref = SourceRef(self.attrib.getSourceRef())
-        else:
-            self.srcref = SourceRef()
         
+        if attrib:
+            self.srcreflist = self.attrib.getSourceRefList()
+        else:
+            self.srcreflist = []
+
         # Typing CR selects OK button
         self.window.editable_enters(self.type_field);
         self.window.editable_enters(self.value_field);
@@ -841,12 +832,6 @@ class AttributeEditor:
         if attrib != None:
             self.type_field.set_text(attrib.getType())
             self.value_field.set_text(attrib.getValue())
-            srcref_base = self.attrib.getSourceRef().getBase()
-            if srcref_base:
-                self.source_field.set_text(srcref_base.getTitle())
-            else:
-                self.source_field.set_text("")
-                 
             self.priv.set_active(attrib.getPrivacy())
 
             self.note_field.set_point(0)
@@ -867,7 +852,7 @@ class AttributeEditor:
 #-------------------------------------------------------------------------
 def on_attrib_source_clicked(obj):
     ee = obj.get_data("o")
-    Sources.SourceEditor(ee.srcref,ee.parent.db,ee.source_field)
+    Sources.SourceSelector(ee.srcreflist,ee.parent,src_changed)
             
 #-------------------------------------------------------------------------
 #
@@ -885,38 +870,15 @@ def on_attrib_edit_ok_clicked(obj):
 
     if attrib == None:
         attrib = Attribute()
+        attrib.setSourceRefList(ee.srcreflist)
         ee.parent.alist.append(attrib)
         
     if update_attrib(attrib,type,value,note,priv):
         ee.parent.lists_changed = 1
         
-    if not source_refs_equal(attrib.getSourceRef(),ee.srcref):
-        attrib.setSourceRef(ee.srcref)
-        ee.parent.lists_changed = 1
-
     ee.parent.redraw_attr_list()
     utils.destroy_passed_object(obj)
 
-#-------------------------------------------------------------------------
-#
-#
-#
-#-------------------------------------------------------------------------
-def source_refs_equal(one,two):
-    if not one or not two:
-        return 0
-    if one.ref != two.ref:
-        return 0
-    if one.page != two.page:
-        return 0
-    if one.date != two.date:
-        return 0
-    if one.comments != two.comments:
-        return 0
-    if one.text != two.text:
-        return 0
-    return 1
-
 #-------------------------------------------------------------------------
 #
 # 
diff --git a/gramps/src/RelLib.py b/gramps/src/RelLib.py
index 67c70a0d7..fdc985953 100644
--- a/gramps/src/RelLib.py
+++ b/gramps/src/RelLib.py
@@ -37,28 +37,30 @@ class SourceNote:
     def __init__(self,source=None):
         """Create a new SourceNote, copying from source if not None"""
         
+        self.source_list = []
+
         if source:
-            if source.source_ref:
-                self.source_ref = SourceRef(source.source_ref)
-            else:
-                self.source_ref = None
+            if len(source.source_list) > 0:
+                for sref in source.source_list:
+                    self.source_list.append(SourceRef(sref))
             if source.note:
                 self.note = Note(source.note.get())
             else:
                 self.note = None
         else:
-            self.source_ref = None
             self.note = None
 
-    def setSourceRef(self,id) :
+    def addSourceRef(self,id) :
         """Set the source reference"""
-        self.source_ref = id
+        self.source_list.append(id)
 
-    def getSourceRef(self) :
+    def getSourceRefList(self) :
         """Return the source reference"""
-        if not self.source_ref:
-            self.source_ref = SourceRef()
-        return self.source_ref
+        return self.source_list
+
+    def setSourceRefList(self,list) :
+        """Replaces the source reference"""
+        self.source_list = list
 
     def setNote(self,text):
         """Set the note to the given text"""
@@ -583,8 +585,15 @@ class Name(DataObj):
             return 0
         if self.getNote() != other.getNote():
             return 0
-        if not self.getSourceRef().are_equal(other.getSourceRef()):
+        if len(self.getSourceRefList()) != len(other.getSourceRefList()):
             return 0
+        index = 0
+        olist = other.getSourceRefList()
+        for a in self.getSourceRefList():
+            if not a.are_equal(olist[index]):
+                return 0
+            index = index + 1
+            
         return 1
 
 class Url:
@@ -629,6 +638,7 @@ class Url:
 class Person:
     """Represents an individual person in the gramps database"""
     
+    unknown = 2
     male = 1
     female = 0
 
@@ -644,7 +654,7 @@ class Person:
         self.photoList = []
         self.nickname = ""
         self.alternateNames = []
-        self.gender = 0
+        self.gender = 2
         self.death = None
         self.birth = None
         self.addressList = []
@@ -930,8 +940,16 @@ class Event(DataObj):
             return 0
         if self.private != other.private:
             return 0
-        if not self.getSourceRef().are_equal(other.getSourceRef()):
+
+        if len(self.getSourceRefList()) != len(other.getSourceRefList()):
             return 0
+        index = 0
+        olist = other.getSourceRefList()
+        for a in self.getSourceRefList():
+            if not a.are_equal(olist[index]):
+                return 0
+            index = index + 1
+
         return 1
         
     def setName(self,name):
diff --git a/gramps/src/Sources.py b/gramps/src/Sources.py
index 0324d68c6..c050fbe33 100644
--- a/gramps/src/Sources.py
+++ b/gramps/src/Sources.py
@@ -48,6 +48,78 @@ ACTIVESRC  = "a"
 INDEX      = "i"
 MENUVAL    = "a"
 
+class SourceSelector:
+
+    def __init__(self,srclist,parent,update=None):
+        self.db = parent.db
+        self.parent = parent
+        self.orig = srclist
+        self.list = []
+        for s in self.orig:
+            self.list.append(SourceRef(s))
+        self.update=update
+        self.top = libglade.GladeXML(const.gladeFile,"sourcesel")
+        self.top.signal_autoconnect({
+            "destroy_passed_object" : utils.destroy_passed_object,
+            "on_add_src_clicked"    : on_add_src_clicked,
+            "on_del_src_clicked"    : on_del_src_clicked,
+            "on_edit_src_clicked"   : on_edit_src_clicked,
+            "on_src_ok_clicked"     : on_src_ok_clicked,
+            })
+        self.sourcesel = self.top.get_widget("sourcesel")
+        self.slist = self.top.get_widget("slist")
+        self.slist.set_data("o",self)
+        self.redraw()
+        self.sourcesel.show()
+
+    def redraw(self):
+        index = 0
+        self.slist.freeze()
+        self.slist.clear()
+        for s in self.list:
+            base = s.getBase()
+            self.slist.append([base.getId(),base.getTitle()])
+            self.slist.set_row_data(index,s)
+            index = index + 1
+        self.slist.thaw()
+
+def on_src_ok_clicked(obj):
+    top = obj.get_data("o")
+    del top.orig[:]
+    for s in top.list:
+        top.orig.append(s)
+    top.update(top.parent)
+    utils.destroy_passed_object(top.sourcesel)
+    
+def on_edit_src_clicked(obj):
+    sel = obj.selection
+    if len(sel) > 0:
+        row = sel[0]
+        src = obj.get_row_data(row)
+        inst = obj.get_data("o")
+        SourceEditor(src,inst.db,update_clist,inst)
+
+def update_clist(inst,ref):
+    inst.redraw()
+
+def on_add_src_clicked(obj):
+    inst = obj.get_data("o")
+    src = SourceRef()
+    SourceEditor(src,inst.db,add_ref,inst)
+
+def add_ref(inst,ref):
+    inst.list.append(ref)
+    inst.redraw()
+
+def on_del_src_clicked(obj):
+    inst = obj.get_data("o")
+    
+    sel = obj.selection
+    if len(sel) > 0:
+        row = sel[0]
+        del inst.list[row]
+        inst.redraw()
+        
 #-------------------------------------------------------------------------
 #
 # SourceEditor
@@ -60,9 +132,10 @@ class SourceEditor:
     # __init__ - Creates a source editor window associated with an event
     #
     #---------------------------------------------------------------------
-    def __init__(self,srcref,database,update=None):
+    def __init__(self,srcref,database,update=None,parent=None):
 
         self.db = database
+        self.parent = parent
         self.update = update
         self.source_ref = srcref
         self.showSource = libglade.GladeXML(const.gladeFile, "sourceDisplay")
@@ -134,23 +207,11 @@ class SourceEditor:
             self.author_field.set_text("")
             self.pub_field.set_text("")
 
-        if self.active_source:
-            active = 1
-        else:
-            active = 0
-
         values = self.db.getSourceMap().values()
         values.sort(by_title)
-        l = GtkLabel("-- No Source --")
-        l.show()
-        l.set_alignment(0,0.5)
-        c = GtkListItem()
-        c.add(l)
-        c.set_data("s",None)
-        c.show()
-        sel_child = c
-        list = [c]
 
+        sel_child = None
+        list = []
         for src in values:
             l = GtkLabel("%s [%s]" % (src.getTitle(),src.getId()))
             l.show()
@@ -160,15 +221,13 @@ class SourceEditor:
             c.set_data("s",src)
             c.show()
             list.append(c)
-            if src == self.active_source:
+            if self.active_source == None:
+                self.active_source = src
                 sel_child = c
 
         self.title_menu.list.append_items(list)
-        self.title_menu.list.select_child(sel_child)
-        self.get_widget("spage").set_sensitive(active)
-        self.get_widget("sdate").set_sensitive(active)
-        self.get_widget("stext").set_sensitive(active)
-        self.get_widget("scomment").set_sensitive(active)
+        if sel_child != None:
+            self.title_menu.list.select_child(sel_child)
 
 #-------------------------------------------------------------------------
 #
@@ -203,11 +262,7 @@ def on_sourceok_clicked(obj):
     src_edit.source_ref.setConfidence(conf)
 
     if src_edit.update:
-        if src_edit.source_ref.getBase():
-            val = src_edit.source_ref.getBase().getTitle()
-        else:
-            val = ""
-        src_edit.update.set_text(val)
+        src_edit.update(src_edit.parent,src_edit.source_ref)
         
     utils.modified()
     utils.destroy_passed_object(obj)
@@ -223,16 +278,5 @@ def on_source_changed(obj):
     src_entry.active_source = obj.list.get_selection()[0].get_data("s")
 
     if src_entry.active_source == None:
-        active = 0
-        src_entry.author_field.set_text("")
-        src_entry.pub_field.set_text("")
-    else:
-        active = 1
         src_entry.author_field.set_text(src_entry.active_source.getAuthor())
         src_entry.pub_field.set_text(src_entry.active_source.getPubInfo())
-
-    src_entry.get_widget("spage").set_sensitive(active)
-    src_entry.get_widget("sdate").set_sensitive(active)
-    src_entry.get_widget("stext").set_sensitive(active)
-    src_entry.get_widget("scomment").set_sensitive(active)
-    src_entry.get_widget("conf").set_sensitive(active)
diff --git a/gramps/src/TarFile.py b/gramps/src/TarFile.py
index c72b75f8f..3f3c530e8 100644
--- a/gramps/src/TarFile.py
+++ b/gramps/src/TarFile.py
@@ -22,11 +22,6 @@ import gzip
 _BLKSIZE=512
 nul = '\0'
 
-#------------------------------------------------------------------------
-#
-# 
-#
-#------------------------------------------------------------------------
 class TarFile:
     def __init__(self,name):
         self.name = name
@@ -78,3 +73,46 @@ class TarFile:
             self.f.write('\0' * rem)
         self.f.close()
 
+
+class ReadTarFile:
+    def __init__(self,name,wd):
+        self.name = name
+	self.wd = wd
+        self.f = gzip.open(name,"rb")
+        self.pos = 0
+        
+    def extract(self):
+	while 1:
+	    buf = self.f.read(100)
+            if buf == '':
+	        return
+            index = 0
+	    for b in buf:
+	        if b != '\0':
+		    index = index + 1
+	        else:
+		    if index == 0:
+                        return
+		    continue
+	    filename = buf[0:index]
+	    self.f.read(24) # modes
+            l = self.f.read(12)
+            length = int(l,8) 
+	    self.f.read(12)
+	    self.f.read(6)
+	    self.f.read(111)
+
+	    self.f.read(64)
+	    self.f.read(183)
+            foo = open(filename,"wb")
+	    foo.write(self.f.read(length))
+	    foo.close()
+	    self.f.read(_BLKSIZE-(length%_BLKSIZE))
+
+    def close(self):
+        self.f.close()
+
+if __name__ == "__main__":
+	a = ReadTarFile("out.gpkg",".")
+	a.extract()
+	a.close()
\ No newline at end of file
diff --git a/gramps/src/WriteXML.py b/gramps/src/WriteXML.py
index 21a5aa92d..3055a3713 100644
--- a/gramps/src/WriteXML.py
+++ b/gramps/src/WriteXML.py
@@ -120,7 +120,8 @@ def dump_my_event(g,name,event,index=1):
     if event.getNote() != "":
         writeNote(g,"note",event.getNote(),index+1)
 
-    dump_source_ref(g,event.getSourceRef(),index+1)
+    for s in event.getSourceRefList():
+        dump_source_ref(g,s,index+1)
     g.write("%s</event>\n" % sp)
 
 #-------------------------------------------------------------------------
@@ -129,27 +130,26 @@ def dump_my_event(g,name,event,index=1):
 #
 #-------------------------------------------------------------------------
 def dump_source_ref(g,source_ref,index=1):
-    if source_ref:
-        source = source_ref.getBase()
-        if source:
-            p = source_ref.getPage()
-            c = source_ref.getComments()
-            t = source_ref.getText()
-            d = source_ref.getDate().getSaveDate()
-            q = source_ref.getConfidence()
-            g.write("  " * index)
-            if p == "" and c == "" and t == "" and d == "" and q == 2:
-                g.write('<sourceref ref="%s"/>\n' % source.getId())
+    source = source_ref.getBase()
+    if source:
+        p = source_ref.getPage()
+        c = source_ref.getComments()
+        t = source_ref.getText()
+        d = source_ref.getDate().getSaveDate()
+        q = source_ref.getConfidence()
+        g.write("  " * index)
+        if p == "" and c == "" and t == "" and d == "" and q == 2:
+            g.write('<sourceref ref="%s"/>\n' % source.getId())
+        else:
+            if q == 2:
+                g.write('<sourceref ref="%s">\n' % source.getId())
             else:
-                if q == 2:
-                    g.write('<sourceref ref="%s">\n' % source.getId())
-                else:
-                    g.write('<sourceref ref="%s" conf="%d">\n' % (source.getId(),q))
-                write_line(g,"spage",p,index+1)
-                writeNote(g,"scomments",c,index+1)
-                writeNote(g,"stext",t,index+1)
-                write_line(g,"sdate",d,index+1)
-                g.write("%s</sourceref>\n" % ("  " * index))
+                g.write('<sourceref ref="%s" conf="%d">\n' % (source.getId(),q))
+            write_line(g,"spage",p,index+1)
+            writeNote(g,"scomments",c,index+1)
+            writeNote(g,"stext",t,index+1)
+            write_line(g,"sdate",d,index+1)
+            g.write("%s</sourceref>\n" % ("  " * index))
 
 #-------------------------------------------------------------------------
 #
@@ -215,7 +215,8 @@ def dump_name(g,label,name,index=1):
     write_line(g,"title",name.getTitle(),index+1)
     if name.getNote() != "":
         writeNote(g,"note",name.getNote(),index+1)
-    dump_source_ref(g,name.getSourceRef(),index+1)
+    for s in name.getSourceRefList():
+        dump_source_ref(g,s,index+1)
     
     g.write('%s</%s>\n' % (sp,label))
 
@@ -269,11 +270,12 @@ def dump_location(g,loc):
 
 def write_attribute_list(g, list):
     for attr in list:
-        if attr.getSourceRef() or attr.getNote():
+        if len(attr.getSourceRef()) > 0 or attr.getNote():
             g.write('      <attribute%s>\n' % conf_priv(attr))
             write_line(g,"attr_type",attr.getType(),4)
             write_line(g,"attr_value",attr.getValue(),4)
-            dump_source_ref(g,attr.getSourceRef(),4)
+            for s in attr.getSourceRefList():
+                dump_source_ref(g,s,index+1)
             writeNote(g,"note",attr.getNote(),4)
             g.write('      </attribute>\n')
         else:
@@ -328,7 +330,8 @@ def write_place_obj(g,place):
     write_url_list(g, place.getUrlList())
     if place.getNote() != "":
         writeNote(g,"note",place.getNote(),3)
-    dump_source_ref(g,place.getSourceRef(),3)
+    for s in place.getSourceRefList():
+        dump_source_ref(g,s,index+1)
     g.write("    </placeobj>\n")
 
 #-------------------------------------------------------------------------
@@ -412,8 +415,10 @@ def write_xml_data(database, g, callback, sp):
             write_id(g,"person",person,2)
             if person.getGender() == Person.male:
                 write_line(g,"gender","M",3)
-            else:
+            elif person.getGender() == Person.female:
                 write_line(g,"gender","F",3)
+            else:
+                write_line(g,"gender","U",3)
             dump_name(g,"name",person.getPrimaryName(),3)
             for name in person.getAlternateNames():
                 dump_name(g,"aka",name,3)
@@ -441,7 +446,8 @@ def write_xml_data(database, g, callback, sp):
                     write_line(g,"postal",address.getPostal(),4)
                     if address.getNote() != "":
                         writeNote(g,"note",address.getNote(),4)
-                    dump_source_ref(g,address.getSourceRef(),4)
+                    for s in address.getSourceRefList():
+                        dump_source_ref(g,s,index+1)
                     g.write('      </address>\n')
 
             write_attribute_list(g,person.getAttributeList())
diff --git a/gramps/src/const.py b/gramps/src/const.py
index f4ccf2879..ac56f49e0 100644
--- a/gramps/src/const.py
+++ b/gramps/src/const.py
@@ -97,6 +97,7 @@ thumbScale   = 100.0
 indexFile    = "data.gramps"
 male         = _("male")
 female       = _("female")
+unknown      = _("unknown")
 
 #-------------------------------------------------------------------------
 #
@@ -343,9 +344,11 @@ def save_pattr(st):
 #
 #-------------------------------------------------------------------------
 familyConstantAttributes = {
+    "Number of Children" : "NCHI",
     }
 
 _fa_e2l = {
+    "Number of Children" : _("Number of Children"),
     }
 
 _fa_l2e = {}
diff --git a/gramps/src/dialog.glade b/gramps/src/dialog.glade
index ea6adbea0..77c4a2291 100644
--- a/gramps/src/dialog.glade
+++ b/gramps/src/dialog.glade
@@ -125,7 +125,7 @@
       <widget>
 	<class>GtkTable</class>
 	<name>table21</name>
-	<rows>8</rows>
+	<rows>7</rows>
 	<columns>2</columns>
 	<homogeneous>False</homogeneous>
 	<row_spacing>0</row_spacing>
@@ -308,32 +308,6 @@
 	  </widget>
 	</widget>
 
-	<widget>
-	  <class>GtkLabel</class>
-	  <name>label158</name>
-	  <label>Source</label>
-	  <justify>GTK_JUSTIFY_CENTER</justify>
-	  <wrap>False</wrap>
-	  <xalign>1</xalign>
-	  <yalign>0.5</yalign>
-	  <xpad>5</xpad>
-	  <ypad>8</ypad>
-	  <child>
-	    <left_attach>0</left_attach>
-	    <right_attach>1</right_attach>
-	    <top_attach>5</top_attach>
-	    <bottom_attach>6</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
-
 	<widget>
 	  <class>GtkCombo</class>
 	  <name>personalEvents</name>
@@ -407,8 +381,8 @@
 	  <child>
 	    <left_attach>1</left_attach>
 	    <right_attach>2</right_attach>
-	    <top_attach>7</top_attach>
-	    <bottom_attach>8</bottom_attach>
+	    <top_attach>6</top_attach>
+	    <bottom_attach>7</bottom_attach>
 	    <xpad>3</xpad>
 	    <ypad>3</ypad>
 	    <xexpand>False</xexpand>
@@ -441,8 +415,8 @@
 	  <child>
 	    <left_attach>0</left_attach>
 	    <right_attach>1</right_attach>
-	    <top_attach>7</top_attach>
-	    <bottom_attach>8</bottom_attach>
+	    <top_attach>6</top_attach>
+	    <bottom_attach>7</bottom_attach>
 	    <xpad>0</xpad>
 	    <ypad>0</ypad>
 	    <xexpand>False</xexpand>
@@ -475,13 +449,12 @@
 	  </child>
 
 	  <widget>
-	    <class>GtkEntry</class>
-	    <name>event_source</name>
+	    <class>GtkCheckButton</class>
+	    <name>priv</name>
 	    <can_focus>True</can_focus>
-	    <editable>False</editable>
-	    <text_visible>True</text_visible>
-	    <text_max_length>0</text_max_length>
-	    <text></text>
+	    <label>Private Record</label>
+	    <active>False</active>
+	    <draw_indicator>True</draw_indicator>
 	    <child>
 	      <padding>3</padding>
 	      <expand>True</expand>
@@ -511,29 +484,6 @@
 	  </widget>
 	</widget>
 
-	<widget>
-	  <class>GtkCheckButton</class>
-	  <name>priv</name>
-	  <can_focus>True</can_focus>
-	  <label>Private Record</label>
-	  <active>False</active>
-	  <draw_indicator>True</draw_indicator>
-	  <child>
-	    <left_attach>1</left_attach>
-	    <right_attach>2</right_attach>
-	    <top_attach>6</top_attach>
-	    <bottom_attach>7</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
-
 	<widget>
 	  <class>GtkLabel</class>
 	  <name>causelabel</name>
@@ -701,7 +651,7 @@
       <widget>
 	<class>GtkTable</class>
 	<name>table22</name>
-	<rows>5</rows>
+	<rows>4</rows>
 	<columns>2</columns>
 	<homogeneous>False</homogeneous>
 	<row_spacing>0</row_spacing>
@@ -764,32 +714,6 @@
 	  </child>
 	</widget>
 
-	<widget>
-	  <class>GtkLabel</class>
-	  <name>label175</name>
-	  <label>Source</label>
-	  <justify>GTK_JUSTIFY_CENTER</justify>
-	  <wrap>False</wrap>
-	  <xalign>1</xalign>
-	  <yalign>0.5</yalign>
-	  <xpad>5</xpad>
-	  <ypad>8</ypad>
-	  <child>
-	    <left_attach>0</left_attach>
-	    <right_attach>1</right_attach>
-	    <top_attach>2</top_attach>
-	    <bottom_attach>3</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
-
 	<widget>
 	  <class>GtkCombo</class>
 	  <name>attr_menu</name>
@@ -863,8 +787,8 @@
 	  <child>
 	    <left_attach>1</left_attach>
 	    <right_attach>2</right_attach>
-	    <top_attach>4</top_attach>
-	    <bottom_attach>5</bottom_attach>
+	    <top_attach>3</top_attach>
+	    <bottom_attach>4</bottom_attach>
 	    <xpad>3</xpad>
 	    <ypad>3</ypad>
 	    <xexpand>False</xexpand>
@@ -897,8 +821,8 @@
 	  <child>
 	    <left_attach>0</left_attach>
 	    <right_attach>1</right_attach>
-	    <top_attach>4</top_attach>
-	    <bottom_attach>5</bottom_attach>
+	    <top_attach>3</top_attach>
+	    <bottom_attach>4</bottom_attach>
 	    <xpad>0</xpad>
 	    <ypad>0</ypad>
 	    <xexpand>False</xexpand>
@@ -931,13 +855,12 @@
 	  </child>
 
 	  <widget>
-	    <class>GtkEntry</class>
-	    <name>attr_source</name>
+	    <class>GtkCheckButton</class>
+	    <name>priv</name>
 	    <can_focus>True</can_focus>
-	    <editable>False</editable>
-	    <text_visible>True</text_visible>
-	    <text_max_length>0</text_max_length>
-	    <text></text>
+	    <label>Private Record</label>
+	    <active>False</active>
+	    <draw_indicator>True</draw_indicator>
 	    <child>
 	      <padding>3</padding>
 	      <expand>True</expand>
@@ -966,29 +889,6 @@
 	    </child>
 	  </widget>
 	</widget>
-
-	<widget>
-	  <class>GtkCheckButton</class>
-	  <name>priv</name>
-	  <can_focus>True</can_focus>
-	  <label>Private Record</label>
-	  <active>False</active>
-	  <draw_indicator>True</draw_indicator>
-	  <child>
-	    <left_attach>1</left_attach>
-	    <right_attach>2</right_attach>
-	    <top_attach>3</top_attach>
-	    <bottom_attach>4</bottom_attach>
-	    <xpad>0</xpad>
-	    <ypad>0</ypad>
-	    <xexpand>False</xexpand>
-	    <yexpand>False</yexpand>
-	    <xshrink>False</xshrink>
-	    <yshrink>False</yshrink>
-	    <xfill>True</xfill>
-	    <yfill>False</yfill>
-	  </child>
-	</widget>
       </widget>
     </widget>
   </widget>
diff --git a/gramps/src/gramps.glade b/gramps/src/gramps.glade
index db59ff184..f1d620045 100644
--- a/gramps/src/gramps.glade
+++ b/gramps/src/gramps.glade
@@ -5297,7 +5297,7 @@ Very High
 
 	  <widget>
 	    <class>GtkRadioButton</class>
-	    <name>childGender</name>
+	    <name>childMale</name>
 	    <can_focus>True</can_focus>
 	    <label>male</label>
 	    <active>False</active>
@@ -5312,7 +5312,7 @@ Very High
 
 	  <widget>
 	    <class>GtkRadioButton</class>
-	    <name>radiobutton2</name>
+	    <name>childFemale</name>
 	    <can_focus>True</can_focus>
 	    <label>female</label>
 	    <active>True</active>
@@ -5324,6 +5324,21 @@ Very High
 	      <fill>True</fill>
 	    </child>
 	  </widget>
+
+	  <widget>
+	    <class>GtkRadioButton</class>
+	    <name>childUnknown</name>
+	    <can_focus>True</can_focus>
+	    <label>unknown</label>
+	    <active>True</active>
+	    <draw_indicator>True</draw_indicator>
+	    <group>childGender</group>
+	    <child>
+	      <padding>0</padding>
+	      <expand>False</expand>
+	      <fill>False</fill>
+	    </child>
+	  </widget>
 	</widget>
 
 	<widget>
@@ -6577,4 +6592,230 @@ Unknown
   </widget>
 </widget>
 
+<widget>
+  <class>GnomeDialog</class>
+  <name>sourcesel</name>
+  <title>Gramps - Source Reference Selection</title>
+  <type>GTK_WINDOW_TOPLEVEL</type>
+  <position>GTK_WIN_POS_NONE</position>
+  <modal>False</modal>
+  <allow_shrink>False</allow_shrink>
+  <allow_grow>True</allow_grow>
+  <auto_shrink>False</auto_shrink>
+  <auto_close>False</auto_close>
+  <hide_on_close>False</hide_on_close>
+
+  <widget>
+    <class>GtkVBox</class>
+    <child_name>GnomeDialog:vbox</child_name>
+    <name>dialog-vbox18</name>
+    <homogeneous>False</homogeneous>
+    <spacing>8</spacing>
+    <child>
+      <padding>4</padding>
+      <expand>True</expand>
+      <fill>True</fill>
+    </child>
+
+    <widget>
+      <class>GtkHButtonBox</class>
+      <child_name>GnomeDialog:action_area</child_name>
+      <name>dialog-action_area18</name>
+      <layout_style>GTK_BUTTONBOX_END</layout_style>
+      <spacing>8</spacing>
+      <child_min_width>85</child_min_width>
+      <child_min_height>27</child_min_height>
+      <child_ipad_x>7</child_ipad_x>
+      <child_ipad_y>0</child_ipad_y>
+      <child>
+	<padding>0</padding>
+	<expand>False</expand>
+	<fill>True</fill>
+	<pack>GTK_PACK_END</pack>
+      </child>
+
+      <widget>
+	<class>GtkButton</class>
+	<name>button136</name>
+	<can_default>True</can_default>
+	<can_focus>True</can_focus>
+	<signal>
+	  <name>clicked</name>
+	  <handler>on_src_ok_clicked</handler>
+	  <object>slist</object>
+	  <last_modification_time>Sat, 06 Oct 2001 15:41:23 GMT</last_modification_time>
+	</signal>
+	<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+      </widget>
+
+      <widget>
+	<class>GtkButton</class>
+	<name>button138</name>
+	<can_default>True</can_default>
+	<can_focus>True</can_focus>
+	<signal>
+	  <name>clicked</name>
+	  <handler>destroy_passed_object</handler>
+	  <object>sourcesel</object>
+	  <last_modification_time>Fri, 05 Oct 2001 02:26:38 GMT</last_modification_time>
+	</signal>
+	<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+      </widget>
+    </widget>
+
+    <widget>
+      <class>GtkVBox</class>
+      <name>vbox47</name>
+      <homogeneous>False</homogeneous>
+      <spacing>0</spacing>
+      <child>
+	<padding>0</padding>
+	<expand>True</expand>
+	<fill>True</fill>
+      </child>
+
+      <widget>
+	<class>GtkLabel</class>
+	<name>label253</name>
+	<label>Source Reference Selection</label>
+	<justify>GTK_JUSTIFY_CENTER</justify>
+	<wrap>False</wrap>
+	<xalign>0.5</xalign>
+	<yalign>0.5</yalign>
+	<xpad>0</xpad>
+	<ypad>0</ypad>
+	<child>
+	  <padding>0</padding>
+	  <expand>False</expand>
+	  <fill>False</fill>
+	</child>
+      </widget>
+
+      <widget>
+	<class>GtkHSeparator</class>
+	<name>hseparator27</name>
+	<child>
+	  <padding>5</padding>
+	  <expand>True</expand>
+	  <fill>True</fill>
+	</child>
+      </widget>
+
+      <widget>
+	<class>GtkScrolledWindow</class>
+	<name>scrolledwindow30</name>
+	<width>400</width>
+	<height>150</height>
+	<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+	<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+	<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+	<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+	<child>
+	  <padding>0</padding>
+	  <expand>True</expand>
+	  <fill>True</fill>
+	</child>
+
+	<widget>
+	  <class>GtkCList</class>
+	  <name>slist</name>
+	  <can_focus>True</can_focus>
+	  <columns>2</columns>
+	  <column_widths>80,80</column_widths>
+	  <selection_mode>GTK_SELECTION_SINGLE</selection_mode>
+	  <show_titles>True</show_titles>
+	  <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+	  <widget>
+	    <class>GtkLabel</class>
+	    <child_name>CList:title</child_name>
+	    <name>label254</name>
+	    <label>ID</label>
+	    <justify>GTK_JUSTIFY_CENTER</justify>
+	    <wrap>False</wrap>
+	    <xalign>0.5</xalign>
+	    <yalign>0.5</yalign>
+	    <xpad>0</xpad>
+	    <ypad>0</ypad>
+	  </widget>
+
+	  <widget>
+	    <class>GtkLabel</class>
+	    <child_name>CList:title</child_name>
+	    <name>label255</name>
+	    <label>Title</label>
+	    <justify>GTK_JUSTIFY_CENTER</justify>
+	    <wrap>False</wrap>
+	    <xalign>0.5</xalign>
+	    <yalign>0.5</yalign>
+	    <xpad>0</xpad>
+	    <ypad>0</ypad>
+	  </widget>
+	</widget>
+      </widget>
+
+      <widget>
+	<class>GtkHButtonBox</class>
+	<name>hbuttonbox26</name>
+	<layout_style>GTK_BUTTONBOX_SPREAD</layout_style>
+	<spacing>30</spacing>
+	<child_min_width>85</child_min_width>
+	<child_min_height>27</child_min_height>
+	<child_ipad_x>7</child_ipad_x>
+	<child_ipad_y>0</child_ipad_y>
+	<child>
+	  <padding>0</padding>
+	  <expand>True</expand>
+	  <fill>True</fill>
+	</child>
+
+	<widget>
+	  <class>GtkButton</class>
+	  <name>button139</name>
+	  <can_default>True</can_default>
+	  <can_focus>True</can_focus>
+	  <signal>
+	    <name>clicked</name>
+	    <handler>on_add_src_clicked</handler>
+	    <object>slist</object>
+	    <last_modification_time>Sat, 06 Oct 2001 15:47:16 GMT</last_modification_time>
+	  </signal>
+	  <label>Add</label>
+	  <relief>GTK_RELIEF_NORMAL</relief>
+	</widget>
+
+	<widget>
+	  <class>GtkButton</class>
+	  <name>button140</name>
+	  <can_default>True</can_default>
+	  <can_focus>True</can_focus>
+	  <signal>
+	    <name>clicked</name>
+	    <handler>on_edit_src_clicked</handler>
+	    <object>slist</object>
+	    <last_modification_time>Fri, 05 Oct 2001 02:49:15 GMT</last_modification_time>
+	  </signal>
+	  <label>Edit</label>
+	  <relief>GTK_RELIEF_NORMAL</relief>
+	</widget>
+
+	<widget>
+	  <class>GtkButton</class>
+	  <name>button141</name>
+	  <can_default>True</can_default>
+	  <can_focus>True</can_focus>
+	  <signal>
+	    <name>clicked</name>
+	    <handler>on_del_src_clicked</handler>
+	    <object>slist</object>
+	    <last_modification_time>Sat, 06 Oct 2001 15:39:54 GMT</last_modification_time>
+	  </signal>
+	  <label>Delete</label>
+	  <relief>GTK_RELIEF_NORMAL</relief>
+	</widget>
+      </widget>
+    </widget>
+  </widget>
+</widget>
+
 </GTK-Interface>
diff --git a/gramps/src/gramps_main.py b/gramps/src/gramps_main.py
index 34b4b3ff0..cabc1f165 100755
--- a/gramps/src/gramps_main.py
+++ b/gramps/src/gramps_main.py
@@ -560,10 +560,12 @@ def on_addchild_ok_clicked(obj):
     name.setFirstName(given)
     person.setPrimaryName(name)
 
-    if new_child_win.get_widget("childGender").get_active():
+    if new_child_win.get_widget("childMale").get_active():
         person.setGender(Person.male)
-    else:
+    elif new_child_win.get_widget("childFemale").get_active():
         person.setGender(Person.female)
+    else:
+        person.setGender(Person.unknown)
         
     if not active_family:
         active_family = database.newFamily()
@@ -729,7 +731,7 @@ def on_prel_changed(obj):
     father_index = 1
     mother_index = 1
     for person in people:
-        if person == active_person:
+        if person == active_person or person.getGender() == Person.unknown:
             continue
         elif type == "Partners":
             father_list.append([utils.phonebook_name(person),birthday(person)])
@@ -2255,10 +2257,12 @@ def redisplay_person_list(person):
     alt2col[person] = []
     gname = utils.phonebook_from_name
     if DataFilter.compare(person):
-        if person.getGender():
+        if person.getGender() == Person.male:
             gender = const.male
-        else:
+        elif person.getGender() == Person.female:
             gender = const.female
+        else:
+            gender = const.unknown
         bday = person.getBirth().getDateObj()
         dday = person.getDeath().getDateObj()
         name = person.getPrimaryName()
@@ -2992,10 +2996,12 @@ def apply_filter():
             id2col[person] = pos
             new_alt2col[person] = []
 
-            if person.getGender():
+            if person.getGender() == Person.male:
                 gender = const.male
-            else:
+            elif person.getGender() == Person.female:
                 gender = const.female
+            else:
+                gender = const.unknown
 
             bday = person.getBirth().getDateObj()
             dday = person.getDeath().getDateObj()
diff --git a/gramps/src/latin_ansel.py b/gramps/src/latin_ansel.py
index 4f2748948..414f449bd 100644
--- a/gramps/src/latin_ansel.py
+++ b/gramps/src/latin_ansel.py
@@ -78,11 +78,22 @@ _t0 = {
 def ansel_to_latin(s):
     buff = cStringIO.StringIO()
     while s:
-        try:
-            head,s = ansel_to_code(s)
-        except Exception:
+        c0 = ord(s[0])
+        if c0 > 127:
+            try:
+                if c0 >= 0xE0:
+                    c1 = ord(s[1])
+                    head = chr(_s1[c0][c1])
+                    s = s[2:]
+                else:
+                    head = chr(_s0[c0])
+                    s = s[1:]
+            except Exception:
+                head = s[0]
+                s = s[1:]
+        else:
             head = s[0]
-            s = s[1:0]
+            s = s[1:]
         buff.write(head)
     ans = buff.getvalue()
     buff.close()
@@ -115,23 +126,3 @@ def latin_to_ansel(s):
     buff.close()
     return ans
 
-#-------------------------------------------------------------------------
-#
-#
-#
-#-------------------------------------------------------------------------
-def ansel_to_code(s):
-    if s == "":
-        return ""
-    if ord(s[0]) < 128:
-        return s[0],s[1:]
-    c0 = ord(s[0])
-    c1 = ord(s[1])
-    if c0 >= 0xE0:
-        return chr(_s1[c0][c1]),s[2:]
-    else:
-        try:
-            return chr(_s0[c0]), s[1:]
-        except:
-            return s[0], s[1:]
-
diff --git a/gramps/src/plugins/ReadGedcom.py b/gramps/src/plugins/ReadGedcom.py
index 9047dd42c..90e8986b8 100644
--- a/gramps/src/plugins/ReadGedcom.py
+++ b/gramps/src/plugins/ReadGedcom.py
@@ -48,6 +48,11 @@ glade_file = None
 clear_data = 0
 is_ftw = 0
 
+def nocnv(s):
+    return s
+
+_cnv = nocnv
+
 photo_types = [ "jpeg", "bmp", "pict", "pntg", "tpic", "png", "gif",
                 "tiff", "pcx" ]
 
@@ -69,6 +74,8 @@ lineRE = re.compile(r"\s*(\d+)\s+(\S+)\s*(.*)$")
 headRE = re.compile(r"\s*(\d+)\s+HEAD")
 nameRegexp = re.compile(r"([\S\s]*\S)?\s*/([^/]+)?/\s*,?\s*([\S]+)?")
 
+placemap = {}
+
 #-------------------------------------------------------------------------
 #
 #
@@ -96,7 +103,9 @@ def find_file(fullname,altpath):
 #
 #
 #-------------------------------------------------------------------------
+
 def importData(database, filename):
+
     global callback
     global topDialog
     global glade_file
@@ -125,12 +134,17 @@ def importData(database, filename):
         GnomeErrorDialog(_("%s could not be opened\n") % filename)
         return
 
+    import time
+    t1 = time.time()
     g.parse_gedcom_file()
+    t2 = time.time()
+    print t2-t1
 
     statusTop.get_widget("close").set_sensitive(1)
 
     utils.modified()
-    callback(1)
+    if callback:
+        callback(1)
 
 #-------------------------------------------------------------------------
 #
@@ -183,9 +197,9 @@ class GedcomParser:
         self.dir_path = os.path.dirname(file)
         self.localref = 0
 
-        f = open(file,"r")
-        self.lines = f.readlines()
-        f.close()
+        self.f = open(file,"r")
+        self.index = 0
+        self.backoff = 0
 
         self.file_obj = window.get_widget("file")
         self.encoding_obj = window.get_widget("encoding")
@@ -200,8 +214,6 @@ class GedcomParser:
         self.error_text_obj.set_word_wrap(0)
         
         self.update(self.file_obj,file)
-        
-	self.index = 0
         self.code = 0
 
     #---------------------------------------------------------------------
@@ -220,24 +232,27 @@ class GedcomParser:
     #
     #---------------------------------------------------------------------
     def get_next(self):
-        line = string.replace(self.lines[self.index],'\r','')
-        if self.code == ANSEL:
-            line = latin_ansel.ansel_to_latin(line)
-        elif self.code == UNICODE:
-            line = latin_utf8.utf8_to_latin(line)
-	match = lineRE.match(line)
-        if not match:
-            msg = _("Warning: line %d was not understood, so it was ignored.") % self.index
-            self.error_text_obj.insert_defaults(msg)
-            msg = "\n\t%s\n" % self.lines[self.index-1]
-            self.error_text_obj.insert_defaults(msg)
-            self.error_count = self.error_count + 1
-            self.update(self.errors_obj,str(self.error_count))
-            match = lineRE.match("999 XXX XXX")
-        
-        self.index = self.index + 1
-    	return match.groups()
-
+        if self.backoff == 0:
+            self.text = _cnv(string.strip(self.f.readline()))
+            self.index = self.index + 1
+            l = string.split(self.text, None, 2)
+            ln = len(l)
+            try:
+                if ln == 2:
+                    self.groups = (int(l[0]),l[1],"")
+                else:
+                    self.groups = (int(l[0]),l[1],l[2])
+            except:
+                msg = _("Warning: line %d was not understood, so it was ignored.") % self.index
+                self.error_text_obj.insert_defaults(msg)
+                msg = "\n\t%s\n" % self.text
+                self.error_text_obj.insert_defaults(msg)
+                self.error_count = self.error_count + 1
+                self.update(self.errors_obj,str(self.error_count))
+                self.groups = (999, "XXX", "XXX")
+        self.backoff = 0
+        return self.groups
+            
     #---------------------------------------------------------------------
     #
     #
@@ -246,7 +261,7 @@ class GedcomParser:
     def barf(self,level):
         msg = _("Warning: line %d was not understood, so it was ignored.") % self.index
         self.error_text_obj.insert_defaults(msg)
-        msg = "\n\t%s\n" % self.lines[self.index-1]
+        msg = "\n\t%s\n" % self.text
         self.error_text_obj.insert_defaults(msg)
         self.error_count = self.error_count + 1
         self.update(self.errors_obj,str(self.error_count))
@@ -268,7 +283,7 @@ class GedcomParser:
     #
     #---------------------------------------------------------------------
     def backup(self):
-        self.index = self.index - 1
+        self.backoff = 1
 
     #---------------------------------------------------------------------
     #
@@ -296,7 +311,8 @@ class GedcomParser:
 
         if matches[1] != "TRLR":
 	    self.barf(0)
-
+        self.f.close()
+        
     #---------------------------------------------------------------------
     #
     #
@@ -325,7 +341,7 @@ class GedcomParser:
     def parse_submitter(self):
 	matches = self.get_next()
 
-        if matches[2] != "SUBN":
+        if matches[2] != "SUBM":
             self.backup()
 	    return
         else:
@@ -414,7 +430,6 @@ class GedcomParser:
                     noteobj.set(text + self.parse_continue_data(1))
                 self.parse_note_data(1)
             elif matches[2] == "OBJE":
-                print "OBJE",matches[1]
                 self.ignore_sub_junk(1)
 	    elif matches[1] == "TRLR":
                 self.backup()
@@ -505,6 +520,11 @@ class GedcomParser:
                         child.setMainFamily(None)
                     child.addAltFamily(self.family,mrel,frel)
 	    elif matches[1] == "NCHI" or matches[1] == "RIN" or matches[1] == "SUBM":  
+                a = Attribute()
+                a.setType("Number of Children")
+                a.setValue(matches[2])
+                self.family.addAttribute(a)
+	    elif matches[1] == "RIN" or matches[1] == "SUBM":  
                 pass
             elif matches[1] == "REFN" or matches[1] == "CHAN":
                 self.ignore_sub_junk(2)
@@ -601,7 +621,9 @@ class GedcomParser:
                         self.nmap[matches[2]] = noteobj
                         self.person.setNoteObj(noteobj)
 	    elif matches[1] == "SEX":
-                if matches[2][0] == "M":
+                if matches[2] == '':
+                    self.person.setGender(Person.unknown)
+                elif matches[2][0] == "M":
                     self.person.setGender(Person.male)
                 else:
                     self.person.setGender(Person.female)
@@ -838,7 +860,7 @@ class GedcomParser:
             elif matches[1] == "SOUR":
                 source_ref = SourceRef()
                 source_ref.setBase(self.db.findSource(matches[2],self.smap))
-                address.setSourceRef(source_ref)
+                address.addSourceRef(source_ref)
                 self.parse_source_reference(source_ref,level+1)
             elif matches[1] == "PLAC":
                 address.setStreet(matches[2])
@@ -937,7 +959,7 @@ class GedcomParser:
                 else:
                     source_ref.setBase(self.db.findSource(matches[2],self.smap))
                     self.parse_source_reference(source_ref,level+1)
-                event.setSourceRef(source_ref)
+                event.addSourceRef(source_ref)
             elif matches[1] == "FAMC":
                 family = self.db.findFamily(matches[2],self.fmap)
                 if event.getName() == "Birth":
@@ -953,11 +975,8 @@ class GedcomParser:
                     event.setDescription(val)
                     self.ignore_sub_junk(level+1)
                 else:
-                    place = None
-                    for p in self.db.getPlaceMap().values():
-                        if val == p.get_title():
-                            place = p
-                            break
+                    if placemap.has_key(val):
+                        place = placemap[val]
                     else:
                         place = Place()
                         place.set_title(matches[2])
@@ -1028,14 +1047,11 @@ class GedcomParser:
                 else:
                     source_ref.setBase(self.db.findSource(matches[2],self.smap))
                     self.parse_source_reference(source_ref,level+1)
-                event.setSourceRef(source_ref)
+                event.addSourceRef(source_ref)
             elif matches[1] == "PLAC":
                 val = matches[2]
-                place = None
-                for p in self.db.getPlaceMap().values():
-                    if val == p.get_title():
-                        place = p
-                        break
+                if placemap.has_key(val):
+                    place = placemap[val]
                 else:
                     place = Place()
                     place.set_title(matches[2])
@@ -1145,7 +1161,7 @@ class GedcomParser:
             elif matches[1] == "SOUR":
                 source_ref = SourceRef()
                 source_ref.setBase(self.db.findSource(matches[2],self.smap))
-                name.setSourceRef(source_ref)
+                name.addSourceRef(source_ref)
                 self.parse_source_reference(source_ref,level+1)
             elif matches[1][0:4] == "NOTE":
                 if matches[2] and matches[2][0] != "@":
@@ -1164,10 +1180,10 @@ class GedcomParser:
 
     def parse_header_head(self):
         """validiates that this is a valid GEDCOM file"""
-        line = string.replace(self.lines[self.index],'\r','')
+        line = string.replace(self.f.readline(),'\r','')
 	match = headRE.search(line)
         if not match:
-	    raise GedcomParser.BadFile, self.lines[self.index]
+	    raise GedcomParser.BadFile, line
         self.index = self.index + 1
 
     #---------------------------------------------------------------------
@@ -1177,6 +1193,7 @@ class GedcomParser:
     #---------------------------------------------------------------------
     def parse_header_source(self):
         global is_ftw
+        global _cnv
         
         while 1:
 	    matches = self.get_next()
@@ -1211,8 +1228,10 @@ class GedcomParser:
                 if matches[2] == "UNICODE" or matches[2] == "UTF-8" or \
                    matches[2] == "UTF8":
                     self.code = UNICODE
+                    _cnv = latin_utf8.utf8_to_latin
                 elif matches[2] == "ANSEL":
                     self.code = ANSEL
+                    _cnv = latin_ansel.ansel_to_latin
                 self.ignore_sub_junk(2)
                 self.update(self.encoding_obj,matches[2])
    	    elif matches[1] == "GEDC":
@@ -1598,3 +1617,13 @@ def readData(database,active_person,cb):
 from Plugins import register_import
 
 register_import(readData,_("Import from GEDCOM"))
+
+if __name__ == "__main__":
+    import profile
+    import sys
+    global db
+
+    glade_file = "plugins/gedcomimport.glade"
+    
+    db = RelDataBase()
+    profile.run('importData(db,sys.argv[1])')
diff --git a/gramps/src/plugins/WebPage.py b/gramps/src/plugins/WebPage.py
index 955232af3..9a3bbd410 100644
--- a/gramps/src/plugins/WebPage.py
+++ b/gramps/src/plugins/WebPage.py
@@ -131,7 +131,7 @@ class IndividualPage:
         self.doc.start_cell("NormalCell")
         self.doc.start_paragraph("Data")
         self.doc.write_text(data)
-        if sref != None and sref.getBase() != None :
+        for sref in srefllist:
             self.doc.start_link("#s%d" % self.scnt)
             self.doc.write_text("<SUP>%d</SUP>" % self.scnt)
             self.doc.end_link()
@@ -244,7 +244,7 @@ class IndividualPage:
             self.doc.end_paragraph()
 
         self.doc.start_table("one","IndTable")
-        self.write_normal_row("%s:" % _("Name"), name, name_obj.getSourceRef())
+        self.write_normal_row("%s:" % _("Name"), name, name_obj.getSourceRefList())
         if self.person.getGender() == Person.male:
             self.write_normal_row("%s:" % _("Gender"), \
                                   _("Male"),None)
@@ -306,7 +306,7 @@ class IndividualPage:
             date = event.getDate()
             descr = event.getDescription()
             place = event.getPlaceName()
-            srcref = event.getSourceRef()
+            srcref = event.getSourceRefList()
 
             if date == "" and descr == "" and place == "" and srcref.getBase() == None:
                 continue
diff --git a/gramps/src/plugins/WriteGedcom.py b/gramps/src/plugins/WriteGedcom.py
index c3437f4bb..a0179044c 100644
--- a/gramps/src/plugins/WriteGedcom.py
+++ b/gramps/src/plugins/WriteGedcom.py
@@ -200,8 +200,28 @@ def add_persons_sources(person):
     for event in elist:
         if private and event.getPrivacy():
             continue
-        source_ref = event.getSourceRef()
-        if source_ref != None:
+        for source_ref in event.getSourceRefList():
+            sbase = source_ref.getBase()
+            if sbase != None and sbase not in source_list:
+                source_list.append(sbase)
+    for event in person.getAddressList():
+        if private and event.getPrivacy():
+            continue
+        for source_ref in event.getSourceRefList():
+            sbase = source_ref.getBase()
+            if sbase != None and sbase not in source_list:
+                source_list.append(sbase)
+    for event in person.getAttibuteList:
+        if private and event.getPrivacy():
+            continue
+        for source_ref in event.getSourceRefList():
+            sbase = source_ref.getBase()
+            if sbase != None and sbase not in source_list:
+                source_list.append(sbase)
+    for name in person.getNameList + [ person.getPrimaryName() ]:
+        if private and event.getPrivacy():
+            continue
+        for source_ref in event.getSourceRefList():
             sbase = source_ref.getBase()
             if sbase != None and sbase not in source_list:
                 source_list.append(sbase)
@@ -215,8 +235,14 @@ def add_familys_sources(family):
     for event in family.getEventList():
         if private and event.getPrivacy():
             continue
-        source_ref = event.getSourceRef()
-        if source_ref != None:
+        for source_ref in event.getSourceRefList():
+            sbase = source_ref.getBase()
+            if sbase != None and sbase not in source_list:
+                source_list.append(sbase)
+    for attr in family.getAttributeList():
+        if private and event.getPrivacy():
+            continue
+        for source_ref in event.getSourceRefList():
             sbase = source_ref.getBase()
             if sbase != None and sbase not in source_list:
                 source_list.append(sbase)
@@ -273,8 +299,8 @@ def dump_event_stats(g,event):
         g.write("2 PLAC %s\n" % cnvtxt(event.getPlaceName()))
     if event.getNote() != "":
         write_long_text(g,"NOTE",2,event.getNote())
-    if event.getSourceRef() != None:
-        write_source_ref(g,2,event.getSourceRef())
+    for srcref in event.getSourceRefList():
+        write_source_ref(g,2,srcref)
         
 def fmtline(text,limit,level):
     new_text = []
@@ -340,8 +366,8 @@ def write_person_name(g,name,nick):
         g.write('2 NICK %s\n' % nick)
     if name.getNote() != "":
         write_long_text(g,"NOTE",2,name.getNote())
-    if name.getSourceRef() != None:
-        write_source_ref(g,2,name.getSourceRef())
+    for srcref in name.getSourceRefList():
+        write_source_ref(g,2,srcref)
 
 #-------------------------------------------------------------------------
 #
@@ -431,8 +457,8 @@ def write_person(g,person):
             g.write("2 PLAC %s\n" % cnvtxt(attr.getValue()))
             if attr.getNote() != "":
                 write_long_text(g,"NOTE",2,attr.getNote())
-            if attr.getSourceRef() != None:
-                write_source_ref(g,2,attr.getSourceRef())
+            for srcref in attr.getSourceRefList():
+                write_source_ref(g,2,srclist)
 
         for addr in person.getAddressList():
             if private and addr.getPrivacy():
@@ -448,8 +474,8 @@ def write_person(g,person):
                 g.write("2 CTRY %s\n" % addr.getCountry())
             if addr.getNote() != "":
                 write_long_text(g,"NOTE",2,addr.getNote())
-            if addr.getSourceRef() != None:
-                write_source_ref(g,2,addr.getSourceRef())
+            for srcref in addr.getSourceRefList():
+                write_source_ref(g,2,srcref)
 
     family = person.getMainFamily()
     if family != None and family in family_list:
diff --git a/gramps/src/utils.py b/gramps/src/utils.py
index 08eaedaba..c0762458b 100644
--- a/gramps/src/utils.py
+++ b/gramps/src/utils.py
@@ -150,7 +150,7 @@ def get_detail_flags(obj):
     if Config.show_detail:
         if obj.getNote() != "":
             detail = "N"
-        if obj.getSourceRef().getBase():
+        if len(obj.getSourceRefList()) > 0:
             detail = detail + "S"
         if obj.getPrivacy():
             detail = detail + "P"
@@ -166,7 +166,7 @@ def get_detail_text(obj):
         details = "%s" % _("Note")
     else:
         details = ""
-    if obj.getSourceRef().getBase() != None:
+    if len(obj.getSourceRefList()) > 0:
         if details == "":
             details = _("Source")
         else: