// Extracts the data from the DEAT event for the given individual and adds it if it was an event in the current individual's lifetime.
        private string AddSpouseDeath( CIndividualRecord spouse, string spouseLink )
        {
            string sourceRefs = "";
              string place = "";
              if (spouse.Visibility() == CIndividualRecord.EVisibility.Visible)
              {
            // Record death of irSubject if within this person's lifetime
            CPGDate spouseDeathDate = null;
            foreach (CIndividualEventStructure ies in spouse.m_alIndividualEventStructures)
            {
              if (ies.Type == "DEAT")
              {
            if (ies.m_eventDetail != null)
            {
              spouseDeathDate = ies.m_eventDetail.m_dateValue;
              if (spouseDeathDate != null)
              {
                if (m_qdateInferredDeathday == null || m_qdateInferredDeathday.m_date == null || spouseDeathDate.CompareTo(m_qdateInferredDeathday.m_date) <= 0)
                {
                  if (ies.m_eventDetail.m_placeStructure != null)
                  {
                    if (ies.m_eventDetail.m_placeStructure.m_sPlaceName != "")
                      place = String.Concat(" ", MainForm.s_config.m_sPlaceWord, " ", EscapeHTML(ies.m_eventDetail.m_placeStructure.m_sPlaceName, false));
                  }

                  sourceRefs = AddSources(ref m_alReferenceList, ies.m_eventDetail.m_alSourceCitations);

                  if (spouseDeathDate != null)
                  {
                    CIEvent iEvent = new CIEvent(spouseDeathDate, "_SPOUSEDIED", String.Concat("death of ", spouseLink, place, ".", sourceRefs), "", null, false, MainForm.s_config.m_bCapitaliseEventDescriptions);
                    m_alEventList.Add(iEvent);
                  }
                  // else its an attribute.
                  else
                  {
                    CIEvent iEvent = new CIEvent(null, "_SPOUSEDIED", String.Concat("death of ", spouseLink, place, ".", sourceRefs), "", null, false, MainForm.s_config.m_bCapitaliseEventDescriptions);
                    m_alAttributeList.Add(iEvent);
                  }
                }
                break;
              }
            }
              }
            }
              }
              return sourceRefs;
        }
        // Adds birth, baptism, death etc of the children in the given fr.
        private void AddChildrensEvents( CFamilyRecord fr )
        {
            // Find out all the children.
              foreach (CChild ch in fr.m_alChildren)
              {
            CIndividualRecord child = ch.m_ir;
            if (child.Visibility() == CIndividualRecord.EVisibility.Invisible)
            {
              continue;
            }
            if (child != null)
            {
              bool childConcealed = (child.Visibility() == CIndividualRecord.EVisibility.Restricted);

              string childSex = "child";
              if (!childConcealed)
              {
            if (child.Sex == 'M')
            {
              childSex = "son";
            }
            else if (child.Sex == 'F')
            {
              childSex = "daughter";
            }
              }

              string childLink = MakeLink(child);
              string sourceRefs = "";

              if (!childConcealed)
              {
            // Add death of children if happened in irSubject's lifetime.
            // Note this is done before birth because the way the subsequent sort works it will put death after birth.
            CEventDetail childDeathday = child.GetEvent("DEAT");
            if (childDeathday == null)
            {
              childDeathday = child.GetEvent("BURI");
            }
            if (childDeathday == null)
            {
              childDeathday = child.GetEvent("CREM");
            }

            string deathPlace = "";
            CPGDate childDeathdate = null;

            if (childDeathday != null)
            {
              childDeathdate = childDeathday.m_dateValue;

              if (childDeathday.m_placeStructure != null)
              {
                if (childDeathday.m_placeStructure.m_sPlaceName != "")
                {
                  deathPlace = String.Concat(" ", MainForm.s_config.m_sPlaceWord, " ", EscapeHTML(childDeathday.m_placeStructure.m_sPlaceName, false));
                }
              }
            }

            if (childDeathdate != null && m_qdateInferredDeathday != null && m_qdateInferredDeathday.m_date != null && (childDeathdate.CompareTo(m_qdateInferredDeathday.m_date) <= 0))
            {
              sourceRefs = AddSources(ref m_alReferenceList, childDeathday.m_alSourceCitations);
              CIEvent iEvent = new CIEvent(childDeathdate, "_CHILDDIED", String.Concat("death of ", childSex, " ", childLink, deathPlace, ".", sourceRefs), "", null, false, MainForm.s_config.m_bCapitaliseEventDescriptions);
              m_alEventList.Add(iEvent);
            }
              }

              // Add birth of children.
              // Note this is done after deaths because the way the subsequent sort works it will put death after birth.
              CEventDetail childBirthday = child.GetEvent("BIRT");
              if (childBirthday == null)
              {
            childBirthday = child.GetEvent("CHR");
              }
              if (childBirthday == null)
              {
            childBirthday = child.GetEvent("BAPM");
              }

              string birthPlace = "";
              CPGDate childBirthdate = null;
              sourceRefs = "";

              if (childBirthday != null && !childConcealed)
              {
            childBirthdate = childBirthday.m_dateValue;

            if (childBirthday.m_placeStructure != null)
            {
              if (childBirthday.m_placeStructure.m_sPlaceName != "")
              {
                birthPlace = String.Concat(" ", MainForm.s_config.m_sPlaceWord, " ", EscapeHTML(childBirthday.m_placeStructure.m_sPlaceName, false));
              }
            }
            sourceRefs = AddSources(ref m_alReferenceList, childBirthday.m_alSourceCitations);
              }

              if (childBirthdate == null)
              {
            CIEvent iEvent = new CIEvent(null, "_CHILDBORN", String.Concat("birth of ", childSex, " ", childLink, birthPlace, ".", sourceRefs), "", null, true, MainForm.s_config.m_bCapitaliseEventDescriptions);
            m_alAttributeList.Add(iEvent);
              }
              else
              {
            CIEvent iEvent = new CIEvent(childBirthdate, "_CHILDBORN", String.Concat("birth of ", childSex, " ", childLink, birthPlace, ".", sourceRefs), "", null, true, MainForm.s_config.m_bCapitaliseEventDescriptions);
            m_alEventList.Add(iEvent);
              }
            }
              }
        }
        // Adds the marriage associated with the fr record to the list of events. Also adds irSubject death if within this person's lifetime.
        private void AddMarriage( CIndividualRecord spouse, string spouseLink, CFamilyRecord fr )
        {
            // Find wedding date
              if (spouse != null)
              {
            string sourceRefs = AddSpouseDeath(spouse, spouseLink);

            CPGDate marriageDate;
            string marriageNote;
            string marriagePlace;
            sourceRefs = AddMarriageEvent(fr, sourceRefs, out marriageDate, out marriageNote, out marriagePlace);

            marriageNote = BuildMaritalStatusNote(fr, marriageNote);

            // Add fr record notes to marriage event
            if (fr.m_alNoteStructures != null)
            {
              foreach (CNoteStructure ns in fr.m_alNoteStructures)
              {
            if (ns.Text != null && ns.Text.Length > 0)
            {
              if (marriageNote != "")
              {
                marriageNote += "\n";
              }
              if (MainForm.s_config.m_bObfuscateEmails)
              {
                marriageNote += ObfuscateEmail(ns.Text);
              }
              else
              {
                marriageNote += ns.Text;
              }
            }
              }
            }
            string marriedString = "married ";
            if (fr.WereTheyReallyMarried() == false)
            {
              marriedString = "partner of ";
            }
            if (marriageDate != null)
            {
              CIEvent iEvent = new CIEvent(marriageDate, "_MARRIAGE", String.Concat(marriedString, spouseLink, marriagePlace, ".", sourceRefs), "", marriageNote, true, MainForm.s_config.m_bCapitaliseEventDescriptions);
              m_alEventList.Add(iEvent);
            }
            // else its an attribute.
            else
            {
              CIEvent iEvent = new CIEvent(marriageDate, "_MARRIAGE", String.Concat(marriedString, spouseLink, marriagePlace, ".", sourceRefs), "", marriageNote, true, MainForm.s_config.m_bCapitaliseEventDescriptions);
              // Marriages go at the front of the list so that they appear first in "Other facts"
              m_alAttributeList.Insert(0, iEvent);
            }

              } // end if (irSubject != null )
        }
        // Extracts the data from the given event, and creates a CIEvent instance for it and adds it to the list of events.
        // Does specific processing if appropriate to the event.
        // linkToOtherParty is an href link to the other party concerned in the event. Typically this is for fr events such as engagement, marriage etc where
        // the other party would be the partner.
        private void ProcessEvent(CEventStructure es, string linkToOtherParty )
        {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Note, String.Format("ProcessEvent( {0}, {1} )", es.Type != null ? es.Type : "null", es.Value != null ? es.Value : "null"));

              if (es.Type == null)
              {
            return;
              }
              string utype = es.Type.ToUpper();
              string subtype = es.m_sSubtype;

              // Strip trailing _ that FTM seems sometimes to include
              while (subtype.Length > 0 && subtype.Substring(subtype.Length - 1, 1) == "_")
              {
            subtype = subtype.Substring(0, subtype.Length - 1);
              }

              // Useful holder vars
              CPGDate date;
              string place;
              string escaped_description = "";
              string address = "";
              string url = "";
              string cause = "";

              bool important = false;
              date = null;
              place = "";
              string place_word = MainForm.s_config.m_sPlaceWord;
              string alternative_place_word = "and"; // For want of anything better...
              string alternative_place = "";
              if (es.m_eventDetail != null)
              {
            date = es.m_eventDetail.m_dateValue;
            if (es.m_eventDetail.m_placeStructure != null)
            {
              place = es.m_eventDetail.m_placeStructure.m_sPlaceName;
            }
            alternative_place = es.m_eventDetail.m_sAlternativePlace;

            if (es.m_eventDetail.m_addressStructure != null)
            {
              address = es.m_eventDetail.m_addressStructure.ToString();
              url = es.m_eventDetail.m_addressStructure.GetUrl();
            }

            cause = es.m_eventDetail.m_sCauseOfEvent;
              }

              string sourceRefs = "";
              if (es.m_eventDetail != null && es.Type != "MARR" && es.Type != "TITL") // Marriage handled separately later.
              {
            sourceRefs = AddSources(ref m_alReferenceList, es.m_eventDetail.m_alSourceCitations);
              }

              bool bNeedValue = false;
              bool bOnlyIncludeIfNotePresent = false;
              bool bIncludeOccupation = false;

              // First occurrence of an event in GEDCOM is the "preferred" one, where in real life there can be only one of the event (e.g. BIRT)
              bool bTypeIsAOneOff = false;

              // Fix for Family Tree Maker 2008 which exports occupation as generic EVEN events.
              // It also puts occupation in PLAC field, but this is already accommodated later.
              if (es.Type == "EVEN" && subtype.ToLower() == "occupation")
              {
            es.Type = "OCCU";
              }

              switch (utype)
              {
            case "BIRT":
              if (es is CIndividualEventStructure)
              {
            bTypeIsAOneOff = true;
            if (m_qdateInferredBirthday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredBirthday.m_eqQualification > CPGQualifiedDate.EQualification.Birth) // ">" here means "further from the truth".
              {
                m_qdateInferredBirthday = null;
              }
            }
            if (m_qdateInferredBirthday == null) // Take first BIRT we come across. In GEDCOM this means it is the preferred event.
            {
              m_qdateInferredBirthday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Birth);
            }
            m_sBirthdaySourceRefs = sourceRefs;
              }
              escaped_description = "born";
              important = true;
              break;

            case "CHR":
              if (es is CIndividualEventStructure)
              {
            if (m_qdateInferredBirthday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredBirthday.m_eqQualification > CPGQualifiedDate.EQualification.Christening) // ">" here means "further from the truth".
              {
                m_qdateInferredBirthday = null;
              }
            }
            if (m_qdateInferredBirthday == null) // In the absence of a BIRT event this will have to do.
            {
              m_qdateInferredBirthday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Christening);
              m_sBirthdaySourceRefs = sourceRefs;
            }
              }
              escaped_description = "christened";
              break;

            case "BAPM":
              if (es is CIndividualEventStructure)
              {
            if (m_qdateInferredBirthday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredBirthday.m_eqQualification > CPGQualifiedDate.EQualification.Baptism) // ">" here means "further from the truth".
              {
                m_qdateInferredBirthday = null;
              }
            }
            if (m_qdateInferredBirthday == null) // In the absence of a BIRT event this will have to do.
            {
              m_qdateInferredBirthday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Baptism);
              m_sBirthdaySourceRefs = sourceRefs;
            }
              }
              escaped_description = "baptised";
              break;

            case "DEAT":
              bTypeIsAOneOff = true;
              if (es is CIndividualEventStructure)
              {
            if (m_qdateInferredDeathday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredDeathday.m_eqQualification > CPGQualifiedDate.EQualification.Death) // ">" here means "further from the truth".
              {
                m_qdateInferredDeathday = null;
              }
            }
            if (m_qdateInferredDeathday == null) // Take first DEAT we come across. In GEDCOM this means it is the preferred event.
            {
              m_qdateInferredDeathday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Death);
            }
            m_sDeathdaySourceRefs = sourceRefs;
              }
              escaped_description = "died";
              important = true;
              break;

            case "BURI":
              bTypeIsAOneOff = true;
              if (es is CIndividualEventStructure)
              {
            if (m_qdateInferredDeathday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredDeathday.m_eqQualification > CPGQualifiedDate.EQualification.Burial) // ">" here means "further from the truth".
              {
                m_qdateInferredDeathday = null;
              }
            }
            if (m_qdateInferredDeathday == null) // In the absence of a DEAT event this will have to do.
            {
              m_qdateInferredDeathday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Burial);
              m_sDeathdaySourceRefs = sourceRefs;
            }
              }
              escaped_description = "buried";
              break;

            case "CREM":
              bTypeIsAOneOff = true;
              if (es is CIndividualEventStructure)
              {
            if (m_qdateInferredDeathday != null)
            {
              // Throw away lesser qualified birthday inferences.
              if (m_qdateInferredDeathday.m_eqQualification > CPGQualifiedDate.EQualification.Cremation) // ">" here means "further from the truth".
              {
                m_qdateInferredDeathday = null;
              }
            }
            if (m_qdateInferredDeathday == null) // In the absence of a DEAT event this will have to do.
            {
              m_qdateInferredDeathday = new CPGQualifiedDate(date, CPGQualifiedDate.EQualification.Cremation);
              m_sDeathdaySourceRefs = sourceRefs;
            }
              }
              escaped_description = "cremated";
              break;

            case "ADOP":
              escaped_description = "adopted";
              if (es.m_eventDetail != null)
              {
            CFamilyRecord adopFam = m_gedcom.GetFamilyRecord(es.m_eventDetail.m_xrefFam);
            CIndividualRecord adopHusb = null;
            CIndividualRecord adopWife = null;
            if (adopFam != null && es.m_eventDetail != null)
            {
              if (es.m_eventDetail.m_bAdoptedByHusband)
              {
                adopHusb = m_gedcom.GetIndividualRecord(adopFam.m_xrefHusband);
              }

              if (es.m_eventDetail.m_bAdoptedByWife)
              {
                adopWife = m_gedcom.GetIndividualRecord(adopFam.m_xrefWife);
              }

              if (adopHusb != null || adopWife != null)
              {
                escaped_description += " by ";
                if (adopHusb != null && adopHusb.Visibility() != CIndividualRecord.EVisibility.Invisible)
                {
                  escaped_description += MakeLink(adopHusb);
                  if (adopWife != null)
                  {
                    escaped_description += " and ";
                  }
                }
                if (adopWife != null && adopWife.Visibility() != CIndividualRecord.EVisibility.Invisible)
                {
                  escaped_description += MakeLink(adopWife);
                }
              }
            }
              }

              break;

            case "BARM":
              escaped_description = "bar mitzvah";
              break;

            case "BASM":
              escaped_description = "bat mitzvah";
              break;

            case "BLES":
              escaped_description = "blessing";
              break;

            case "CHRA":
              escaped_description = "christened (as adult)";
              break;

            case "CONF":
              escaped_description = "confirmed";
              break;

            case "FCOM":
              escaped_description = "first communion";
              break;

            case "ORDN":
              escaped_description = "ordained";
              break;

            case "NATU":
              escaped_description = "naturalized";
              break;

            case "EMIG":
              escaped_description = "emigrated";
              place_word = "from";
              alternative_place_word = "to";
              break;

            case "IMMI":
              escaped_description = "immigrated";
              place_word = "to";
              alternative_place_word = "from";
              break;
            /*  handled as fr event below
                case "CENS":
                  escaped_description = "recorded in census";
                  break;*/

            case "PROB":
              escaped_description = "probate";
              break;

            case "WILL":
              escaped_description = "wrote will";
              break;

            case "GRAD":
              escaped_description = "graduated";
              break;

            case "RETI":
              escaped_description = "retired";
              break;

            case "EVEN":
              if (subtype != null && subtype != "")
              {
            escaped_description = EscapeHTML(subtype, false);
              }
              else
              {
            escaped_description = "other event";
              }
              if (es.Value != null && es.Value != "")
              {
              escaped_description += ": " + es.Value;
              }
              break;

            case "CAST":
              escaped_description = "caste";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "DSCR":
              escaped_description = "physical description";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "EDUC":
              escaped_description = "educated";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "IDNO":
              escaped_description = "ID number";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "NATI":
              escaped_description = "nationality";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "NCHI":
              bTypeIsAOneOff = true;
              escaped_description = "number of children";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "NMR":
              bTypeIsAOneOff = true;
              escaped_description = "number of marriages";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;

              break;

            case "OCCU":
              escaped_description = "occupation";
              if (es.Value != null && es.Value != "")
              {
            COccupationCounter oc = new COccupationCounter(EscapeHTML(es.Value, false) + sourceRefs, date);
            m_alOccupations.Add(oc);
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
            bIncludeOccupation = true;
              }
              else
            bNeedValue = true;
              break;

            case "PROP":
              escaped_description = "property";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "RELI":
              escaped_description = "religion";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "RESI":
              escaped_description = "resident";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = false; // Special case, we need the "at" word left in for this.
              break;

            case "SSN":
              escaped_description = "Social Security number";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "TITL":
              /* This is handled as a special case outside of event processing*/
              place = ""; // Clear place to avoid creating spurious event entry
              break;

            case "FACT":
              escaped_description = "other fact";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "_NMR": // _NMR Brother's Keeper
              bTypeIsAOneOff = true;
              escaped_description = "never married";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            case "_AKA": // _AKA Brother's Keeper
            case "_AKAN": // _AKAN Brother's Keeper
              escaped_description = "also known as";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;

            // Now the fr events:
            case "ANUL":
              escaped_description = "annulment of marriage";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }

              break;

            case "CENS":
              escaped_description = "recorded in census";
              break;

            case "DIV":
              if (es.Value != null && (es.Value == "N" || es.Value == "n"))
              {
            place = ""; // Clear place to prevent this event being shown
              }
              else
              {
            escaped_description = "divorced";
            if (linkToOtherParty != null && linkToOtherParty != "")
            {
              escaped_description = String.Concat(escaped_description, " from ", linkToOtherParty);
            }
              }

              break;

            case "DIVF":
              escaped_description = "filing of divorce";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " from ", linkToOtherParty);
              }
              break;

            case "ENGA":
              escaped_description = "engagement";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }
              break;

            case "MARB":
              escaped_description = "publication of banns of marriage";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }

              break;

            case "MARC":
              escaped_description = "contract of marriage";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }

              break;

            case "MARR":
              /* This is handled as a special case outside of event processing*/
              place = ""; // Clear place to avoid creating spurious event entry
              break;

            case "MARL":
              escaped_description = "licence obtained for marriage";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }

              break;

            case "MARS":
              escaped_description = "settlement of marriage";
              if (linkToOtherParty != null && linkToOtherParty != "")
              {
            escaped_description = String.Concat(escaped_description, " to ", linkToOtherParty);
              }

              break;

            case "GEDMILL_ADOPTION_OF_CHILD":
              if (es.m_eventDetail != null)
              {
            CIndividualRecord adoptedChild = m_gedcom.GetIndividualRecord(es.m_eventDetail.m_xrefAdoptedChild);
            if (adoptedChild != null)
            {
              escaped_description = String.Concat("adopted ", MakeLink(adoptedChild));
            }
              }
              break;

            default:
              escaped_description = "unknown event";
              if (es.Value != null && es.Value != "")
            escaped_description = String.Concat(escaped_description, " ", EscapeHTML(es.Value, false));
              else
            bNeedValue = true;
              break;
              }

              if (MainForm.s_config.m_bCapitaliseEventDescriptions)
              {
            Capitalise(ref escaped_description);
              }

              if (place != "")
              {
            // It seems some earlier GEDCOM has PLAC value filled with the event value, and the event value blank. Accomodate this:
            if ((es.Value == null || es.Value == "") && bNeedValue)
            {
              escaped_description += " " + EscapeHTML(place, false);
              if (utype == "OCCU")
              {
            COccupationCounter oc = new COccupationCounter(place,date);
            m_alOccupations.Add(oc);
              }
              place = "";
              bIncludeOccupation = true; // Needed to include occupation event, (without date or place), in page.
            }
            else
            {
              escaped_description += String.Concat(" ", place_word, " ", EscapeHTML(place, false));
              if (alternative_place != null && alternative_place.Length > 0)
              {
            escaped_description += String.Concat(" ", alternative_place_word, " ", EscapeHTML(alternative_place, false));
              }
            }
              }

              if (address != "")
              {
            if (escaped_description.Length > 0)
            {
              escaped_description += " (" + EscapeHTML(address, false) + ")";
            }
            else
            {
              escaped_description = EscapeHTML(address, false);
            }
              }

              if (url != "")
              {
            if (escaped_description.Length > 0)
            {
              escaped_description += " (<a href=\"" + (url) + "\">" + (url) + "</a>)";
            }
            else
            {
              escaped_description = "<a href=\"" + (url) + "\">" + (url) + "</a>";
            }
              }

              string overview = "";
              if (es.m_eventDetail != null && es.m_eventDetail.m_sOverview != null && es.m_eventDetail.m_sOverview != "")
              {
            overview = es.m_eventDetail.m_sOverview;
              }

              if (escaped_description == "")
              {
            return; // In the case of MARR and TITL and DIV N we don't want to add anything here.
              }

              escaped_description += ".";
              escaped_description += sourceRefs;

              string eventNote = "";

              if (cause != "")
              {
            cause = EscapeHTML(cause, false);
            if (MainForm.s_config.m_bCapitaliseEventDescriptions)
            {
              Capitalise(ref cause);
            }
            if (eventNote.Length > 0)
            {
              eventNote += "\n";
            }
            if (MainForm.s_config.m_bObfuscateEmails)
            {
              eventNote += ObfuscateEmail(cause);
            }
            else
            {
              eventNote += cause;
            }
              }

              if (es.m_eventDetail != null)
              {
            if (es.m_eventDetail.m_alNoteStructures != null)
            {
              foreach (CNoteStructure ns in es.m_eventDetail.m_alNoteStructures)
              {
            if (ns.Text != null && ns.Text.Length > 0)
            {
              if (eventNote != "")
              {
                eventNote += "\n";
              }
              if (MainForm.s_config.m_bObfuscateEmails)
              {
                eventNote += ObfuscateEmail(ns.Text);
              }
              else
              {
                eventNote += ns.Text;
              }
            }
              }
            }
              }

              CIEvent iEvent = null;

              if (!bOnlyIncludeIfNotePresent || eventNote != "")
              {
            if (date != null)
            {
              iEvent = new CIEvent(date, utype, escaped_description, overview, eventNote, important, MainForm.s_config.m_bCapitaliseEventDescriptions);
              m_alEventList.Add(iEvent);
            }
            // else its an attribute.
            else
            {
              // Don't include plain "Died" and nothing else. Roots Magic seems to use this just to signify that person died. But it appears on every single page and looks silly.
              // GSP Family Tree puts lots of blank tags (OCCU, CHR, SEX, NOTE, etc.etc). Don't display those without meaning
              // Note CHR is contentious, as other s/w may use a CHR with no other info to mean that they were christened. GSP it appears puts a CHR for everyone?
              if ((utype != "DEAT" && utype != "BIRT" && utype != "CHR" && utype != "OCCU") || place != "" || eventNote != "" || bIncludeOccupation)
              {
            iEvent = new CIEvent(null, utype, escaped_description, overview, eventNote, important, MainForm.s_config.m_bCapitaliseEventDescriptions);
            m_alAttributeList.Add(iEvent);
              }
            }
              }

              if (iEvent != null && bTypeIsAOneOff)
              {
            if (m_htFirstFoundEvent.ContainsKey(utype))
            {
              // We have multiple occurences of this event. Mark the one we saw first as 'preferred'.
              CIEvent firstEvent = (CIEvent)m_htFirstFoundEvent[utype];
              if (firstEvent != null)
              {
            firstEvent.Preference = CIEvent.EPreference.First;
            iEvent.Preference = CIEvent.EPreference.Subsequent;
              }
            }
            else
            {
              m_htFirstFoundEvent[utype] = iEvent;
            }
              }
        }