// Adds an HTML page footer (Record date, W3C sticker, GEDmill credit etc.)
        protected void OutputFooter( CHTMLFile f, CRecord r )
        {
            f.m_sw.WriteLine("      <div id=\"footer\">");
              if ( (r.m_alUserReferenceNumbers.Count > 0)
            || (r.m_sAutomatedRecordId != null && r.m_sAutomatedRecordId != "")
            || (r.m_changeDate != null)
            || (MainForm.s_config.m_sCustomFooter != ""))
              {
            foreach( CUserReferenceNumber urn in r.m_alUserReferenceNumbers )
            {
              string idType = EscapeHTML( urn.m_sUserReferenceType, false );
              if( idType == "" )
              {
            idType = "User reference number";
              }
              f.m_sw.WriteLine( String.Concat("        <p>", idType, ": ", EscapeHTML(urn.m_sUserReferenceNumber, false), "</p>") );
            }

            if (r.m_sAutomatedRecordId != null && r.m_sAutomatedRecordId != "")
            {
              f.m_sw.WriteLine(String.Concat("        <p>Record ", r.m_sAutomatedRecordId, "</p>"));
            }
            if (r.m_changeDate != null)
            {
              CPGDate changeDate = CPGDate.Parse(r.m_changeDate.m_sChangeDate);
              string changeTime = r.m_changeDate.m_sTimeValue;
              if (changeDate != null && changeTime != null)
              {
            if (changeTime != "")
            {
              changeTime = " " + changeTime;
            }
            f.m_sw.WriteLine(String.Concat("        <p id=\"changedate\">Record last changed ", changeDate.ToString(), changeTime, "</p>"));
              }
            }
            if (MainForm.s_config.m_sCustomFooter != "")
            {
              if (MainForm.s_config.m_bFooterIsHtml)
              {
            f.m_sw.WriteLine(String.Concat("        <p>", MainForm.s_config.m_sCustomFooter, "</p>"));
              }
              else
              {
            f.m_sw.WriteLine(String.Concat("        <p>", EscapeHTML(MainForm.s_config.m_sCustomFooter, false), "</p>"));
              }
            }
              }
              f.m_sw.WriteLine("      </div> <!-- footer -->");

              f.m_sw.WriteLine("<p class=\"plain\">Page created using GEDmill " + MainForm.m_sSoftwareVersion + "</p>");

              if (MainForm.s_config.m_bIncludeValiditySticker)
              {
            OutputValiditySticker(f);
              }
        }
        // Outputs the HTML for the Life History section of the page.
        private void OutputEvents(CHTMLFile f)
        {
            if (m_alEventList.Count > 0)
              {
            f.m_sw.WriteLine("        <div id=\"events\">");
            f.m_sw.WriteLine("          <h1>Life History</h1>");
            f.m_sw.WriteLine("          <table>");

            for (int i = 0; i < m_alEventList.Count; i++)
            {
              CIEvent iEvent = (CIEvent)m_alEventList[i];

              string importance;
              if (iEvent.Important)
              {
            importance = " class=\"important\"";
              }
              else
              {
            importance = "";
              }

              string eventNote = "";
              string overviewString = iEvent.Overview;
              if (overviewString != null && overviewString != "")
              {
            eventNote = String.Concat("<p class=\"eventNote\">", EscapeHTML(overviewString, false), "</p>");
              }
              string noteString = iEvent.Note;
              if (noteString != null && noteString != "")
              {
            eventNote += String.Concat("<p class=\"eventNote\">", EscapeHTML(noteString, false), "</p>");
              }
              string preference = "";
              if (iEvent.Preference == CIEvent.EPreference.First)
              {
            preference = " (most likely)";
              }
              else if (iEvent.Preference == CIEvent.EPreference.Subsequent)
              {
            preference = " (less likely)";
              }
              f.m_sw.WriteLine("            <tr>");
              f.m_sw.WriteLine("              <td class=\"date\"><p{0}>{1}</p></td>", importance, EscapeHTML(iEvent.Date, false));
              f.m_sw.WriteLine("              <td class=\"event\"><p{0}>{1}</p>{2}{3}</td>", importance, iEvent.ToString(), preference, eventNote);
              f.m_sw.WriteLine("            </tr>");

            }
            f.m_sw.WriteLine("          </table>");
            f.m_sw.WriteLine("        </div> <!-- events -->");
              }
        }
        // Outputs the HTML for the Other Facts section of the page.
        private void OutputAttributes(CHTMLFile f)
        {
            if (m_alAttributeList.Count > 0)
              {
            f.m_sw.WriteLine("        <div id=\"facts\">");
            f.m_sw.WriteLine("          <h1>Other facts</h1>");
            f.m_sw.WriteLine("          <table>");

            for (int i = 0; i < m_alAttributeList.Count; i++)
            {
              CIEvent iEvent = (CIEvent)m_alAttributeList[i];

              string importance;
              if (iEvent.Important)
              {
            importance = " class=\"important\"";
              }
              else
              {
            importance = "";
              }

              string attrNote = "";
              string noteString = iEvent.Note;
              if (noteString != null)
              {
            attrNote = String.Concat("<p class=\"eventNote\">", EscapeHTML(noteString, false), "</p>");
              }

              f.m_sw.WriteLine("            <tr>");
              f.m_sw.WriteLine("              <td class=\"date\"><p>&nbsp;</p></td>");
              f.m_sw.WriteLine("              <td class=\"event\"><p{0}>{1}</p>{2}</td>", importance, iEvent.ToString(), attrNote);
              f.m_sw.WriteLine("            </tr>");

            }
            f.m_sw.WriteLine("          </table>");
            f.m_sw.WriteLine("        </div> <!-- facts -->");
              }
        }
        // Outputs the HTML for the list of Sources referenced in the page.
        private void OutputSourceReferences(CHTMLFile f)
        {
            if (m_alReferenceList.Count > 0)
              {
            f.m_sw.WriteLine("        <div id=\"references\">");
            f.m_sw.WriteLine("          <h1>Sources</h1>");
            f.m_sw.WriteLine("          <ul>");

            for (uint i = 0; i < m_alReferenceList.Count; i++)
            {
              CSourceCitation sc = (CSourceCitation)(m_alReferenceList[(int)i]);

              string extraInfo = "";
              CSourceRecord sr = m_gedcom.GetSourceRecord(sc.GetXref());

              // Publication facts //
              if (sr != null && sr.m_sSourcePublicationFacts != null && sr.m_sSourcePublicationFacts != "")
              {
            string pubFacts;
            if (MainForm.s_config.m_bObfuscateEmails)
            {
              pubFacts = ObfuscateEmail(sr.m_sSourcePublicationFacts);
            }
            else
            {
              pubFacts = sr.m_sSourcePublicationFacts;
            }

            if (pubFacts.Length > 7 && pubFacts.ToUpper().Substring(0, 7) == "HTTP://")
            {
              pubFacts = String.Concat("<a href=\"", pubFacts, "\">", EscapeHTML(pubFacts, false), "</a>");
              extraInfo += String.Concat("\n                <li>", pubFacts, "</li>");
            }
            else
            {
              extraInfo += String.Concat("\n                <li>", EscapeHTML(pubFacts, false), "</li>");
            }
              }

              // Where within source //
              string whereWithinSource = sc.GetWhereWithinSource();
              if (whereWithinSource != null && whereWithinSource.Length > 0)
              {
            extraInfo += String.Concat("\n                <li>", EscapeHTML(whereWithinSource, false), "</li>");
              }

              // Certainty assessment //
              string certaintyAssessment = sc.GetCertaintyAssessment();
              if (certaintyAssessment != null && certaintyAssessment.Length > 0)
              {
            extraInfo += String.Concat("\n                <li>", EscapeHTML(certaintyAssessment, false), "</li>");
              }

              // Surround any extra info in its own list
              if (extraInfo.Length > 0)
              {
            extraInfo = String.Concat("\n              <ul>", extraInfo, "\n              </ul>");
              }

              // Finally write source link and extra info
              f.m_sw.WriteLine(String.Concat("            <li>", sc.MakeLinkText(i + 1), extraInfo, "</li>"));
            }
            f.m_sw.WriteLine("          </ul>");
            f.m_sw.WriteLine("        </div> <!-- references -->");
              }
        }
        // Writes the "Parents" section of the page to the HTML file.
        private void OutputParentNames(CHTMLFile f)
        {
            if (m_alParents.Count > 0)
              {
            f.m_sw.WriteLine("        <div id=\"parents\">");
            f.m_sw.WriteLine("          <h1>Parents</h1>");

            string sChild = "Child";
            if (m_ir.Sex == 'M')
            {
              sChild = "Son";
            }
            else if (m_ir.Sex == 'F')
            {
              sChild = "Daughter";
            }

            for (int i = 0; i < m_alParents.Count; i++)
            {
              CHusbandAndWife parents = (CHusbandAndWife)m_alParents[i];
              string sParents = "";
              if (parents.m_irHusband != null && parents.m_irHusband.Visibility() == CIndividualRecord.EVisibility.Visible)
              {
            sParents = MakeLink(parents.m_irHusband);
              }
              if (parents.m_irWife != null && parents.m_irWife.Visibility() == CIndividualRecord.EVisibility.Visible)
              {
            string wifeName = MakeLink(parents.m_irWife);
            if (sParents == "")
            {
              sParents = wifeName;
            }
            else
            {
              sParents += " & " + wifeName;
            }
              }
              if (sParents != "")
              {
            f.m_sw.WriteLine(String.Concat("          <p>", sChild, " of ", sParents, ".</p>"));
              }
            }
            f.m_sw.WriteLine("        </div> <!-- parents -->");
              }
        }
        // Outputs the HTML for the Notes section of the page
        private void OutputNotes(CHTMLFile f)
        {
            if (m_ir.m_alNoteStructures.Count > 0)
              {
            // Generate notes list into a local array before adding header title. This is to cope with the case where all notes are nothing but blanks.
            ArrayList note_strings = new ArrayList(m_ir.m_alNoteStructures.Count);

            foreach (CNoteStructure ns in m_ir.m_alNoteStructures)
            {
              if (ns.Text != null && ns.Text.Length > 0)
              {
            string noteText;
            if (MainForm.s_config.m_bObfuscateEmails)
            {
              noteText = ObfuscateEmail(ns.Text);
            }
            else
            {
              noteText = ns.Text;
            }

            string sourceRefs = "";
            if (ns.m_alSourceCitations != null)
            {
              sourceRefs = AddSources(ref m_alReferenceList, ns.m_alSourceCitations);
            }
            note_strings.Add(String.Concat("            <li>", EscapeHTML(noteText, false), sourceRefs, "</li>"));
              }
            }

            if (note_strings.Count > 0)
            {
              f.m_sw.WriteLine("        <div id=\"notes\">");
              f.m_sw.WriteLine("          <h1>Notes</h1>");
              f.m_sw.WriteLine("          <ul>");

              foreach (string note_string in note_strings)
              {
            f.m_sw.WriteLine(note_string);
              }

              f.m_sw.WriteLine("          </ul>");
              f.m_sw.WriteLine("        </div> <!-- notes -->");
            }
              }
        }
        // The main method that causes the help page to be created.
        public void Create()
        {
            FileStream fsHelpSource = null;
              StreamReader srHelpSource = null;
              try
              {
            fsHelpSource = new FileStream( MainForm.s_config.m_sApplicationPath + "\\helpsource.html", FileMode.Open );
            srHelpSource = new StreamReader( fsHelpSource, System.Text.Encoding.UTF8 );
              }
              catch( IOException e )
              {
            LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, String.Format("Caught io exception while loading help file source: {0}", e.ToString() ) );
            fsHelpSource = null;
            srHelpSource = null;
              }

              if( fsHelpSource != null && srHelpSource != null )
              {

            string sPageDescription = "GEDmill GEDCOM to HTML family history website";
            string sKeywords = "family tree history " + MainForm.s_config.m_sOwnersName;
            string sTitle = MainForm.s_config.m_sTitle;

            CHTMLFile f = null;
            try
            {
              // Create a new file and put standard header html into it.
              f = new CHTMLFile( MainForm.s_config.HelppageURL, sTitle, sPageDescription, sKeywords );

              OutputPageHeader(f.m_sw, "", "", true, false);

              f.m_sw.WriteLine("  <div id=\"page\"> <!-- page -->");

              // Copy in the help html source
              string sHelpLine;
              while( null!= (sHelpLine = srHelpSource.ReadLine()) )
              {
            f.m_sw.WriteLine( sHelpLine );
              }

              f.m_sw.WriteLine("  </div> <!-- page -->");
            }
            catch( IOException e )
            {
              LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught IO Exception : " + e.ToString() );
            }
            catch( ArgumentException e )
            {
              LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught Argument Exception : " + e.ToString() );
            }
            finally
            {
              if( f != null )
              {
            // Add standard footer to the file
            f.Close();
              }
            }
              }
              if( srHelpSource != null )
              {
            srHelpSource.Close();
              }
              if( fsHelpSource != null )
              {
            fsHelpSource.Close();
              }
        }
        // Writes the HTML for the multimedia files associated with this record.
        private void OutputMultimedia(CHTMLFile f)
        {
            string sNonPicMainFilename = "";
              if( m_alMultimediaList.Count > 0 )
              {
            f.m_sw.WriteLine("        <div id=\"sourcePics\">");
            foreach( CIMultimedia iMultimedia in m_alMultimediaList )
            {
              sNonPicMainFilename = "multimedia/" + MainForm.NonPicFilename( iMultimedia.m_sFormat, false, MainForm.s_config.m_bLinkOriginalPicture );

              string sImageTitle = "";
              string sAltName = "";
              if( iMultimedia.m_sTitle != null )
              {
            sImageTitle = iMultimedia.m_sTitle;
            sAltName = iMultimedia.m_sTitle;
              }

              f.m_sw.WriteLine(String.Concat("          <p>"));

              if( iMultimedia.m_nWidth != 0 && iMultimedia.m_nHeight != 0 )
              {
            // Must be a picture.
            if( sAltName == "" )
            {
              sAltName = "Image for this source";
            }
            if( iMultimedia.m_sLargeFilename.Length > 0 )
            {
              f.m_sw.WriteLine(String.Concat("            <a href=\"",iMultimedia.m_sLargeFilename,"\"><img src=\"",iMultimedia.m_sFilename,"\" alt=\"", sAltName, "\" /></a>")); // TODO: clip and scale properly. Use MainForm.s_config to set a max scale
            }
            else
            {
              f.m_sw.WriteLine(String.Concat("            <img src=\"",iMultimedia.m_sFilename,"\" alt=\"", sAltName, "\" />")); // TODO: clip and scale properly. Use MainForm.s_config to set a max scale
            }
              }
              else
              {
            // Other multimedia
            if( sAltName == "" )
            {
              sAltName = "Media for this source";
            }

            if( MainForm.s_config.m_bLinkOriginalPicture )
            {
              f.m_sw.WriteLine(String.Concat("            <a href=\"",iMultimedia.m_sFilename,"\"><img src=\"",sNonPicMainFilename,"\" alt=\"", sAltName, "\" /></a>")); // TODO: clip and scale properly. Use MainForm.s_config to set a max scale
            }
            else
            {
              f.m_sw.WriteLine(String.Concat("            <img src=\"",sNonPicMainFilename,"\" alt=\"", sAltName, "\" />")); // TODO: clip and scale properly. Use MainForm.s_config to set a max scale
            }
              }
              f.m_sw.WriteLine(String.Concat("          </p>"));
              if( sImageTitle != "" )
              {
            f.m_sw.WriteLine(String.Concat("          <p id=\"sourcepic_title\">",sImageTitle,"</p>"));
              }
            }
            f.m_sw.WriteLine("        </div> <!-- sourcePics -->");
              }
        }
        // Writes the HTML for the mini tree diagram, including the image alMap data.
        private void OutputMiniTree(CHTMLFile f)
        {
            System.Drawing.Imaging.ImageFormat imageFormat;
              string miniTreeExtn;
              string imageFormatString = MainForm.s_config.m_sMiniTreeImageFormat;
              switch (imageFormatString)
              {
            case "png":
              imageFormat = System.Drawing.Imaging.ImageFormat.Png;
              miniTreeExtn = "png";
              break;
            default:
              imageFormat = System.Drawing.Imaging.ImageFormat.Gif;
              miniTreeExtn = "gif";
              break;
              }

              CTreeDrawer treeDrawer = new CTreeDrawer(m_gedcom);
              string relativeTreeFilename = String.Concat("tree", m_ir.m_xref, ".", miniTreeExtn);
              string fullTreeFilename = String.Concat(MainForm.s_config.m_sOutputFolder, "\\", relativeTreeFilename);
              ArrayList map = treeDrawer.CreateMiniTree(m_paintbox, m_ir, fullTreeFilename, MainForm.s_config.m_nTargetTreeWidth, imageFormat);
              if (map != null)
              {
            // Add space to height so that IE's horiz scroll bar has room and doesn't create a vertical scroll bar.
            f.m_sw.WriteLine(String.Format("    <div id=\"minitree\" style=\"height:{0}px;\">", treeDrawer.Height + 20));
            f.m_sw.WriteLine("      <map name=\"treeMap\" id=\"tree\">");
            foreach (CMiniTreeMap mapItem in map)
            {
              if (mapItem.m_bLinkable)
              {
            string href = GetIndividualHTMLFilename(mapItem.m_ir);
            f.m_sw.WriteLine(String.Concat("        <area alt=\"", mapItem.m_sName, "\" coords=\"", mapItem.m_x1, ",", mapItem.m_y1, ",", mapItem.m_x2, ",", mapItem.m_y2, "\" href=\"", href, "\" shape=\"rect\" />"));
              }
            }
            f.m_sw.WriteLine("      </map>");
            f.m_sw.WriteLine(String.Concat("      <img src=\"", relativeTreeFilename, "\"  usemap=\"#treeMap\" alt=\"Mini tree diagram\"/>"));
            f.m_sw.WriteLine("    </div>");
              }
        }
        // Writes the individual's lifespan and occupation to the HTML file.
        private void OutputIndividualSummary(CHTMLFile f)
        {
            f.m_sw.WriteLine("          <div id=\"individualSummary\">");

              string sBirthday;
              if (m_dateActualBirthday != null)
              {
            sBirthday = m_dateActualBirthday.ToString() + m_sBirthdaySourceRefs;
              }
              else
              {
            sBirthday = "";
              }

              string sDeathday;
              if (m_dateActualDeathday != null)
              {
            sDeathday = m_dateActualDeathday.ToString() + m_sDeathdaySourceRefs;
              }
              else
              {
            sDeathday = "";
              }

              if (m_dateActualBirthday != null || m_dateActualDeathday != null)
              {
            f.m_sw.WriteLine(String.Concat("            <p>", sBirthday, " - ", sDeathday, "</p>"));
              }
              if (MainForm.s_config.m_bOccupationHeadline && m_sOccupation != null && m_sOccupation != "")
              {
            f.m_sw.WriteLine(String.Concat("            <p>", m_sOccupation, "</p>"));
              }
              if (m_bConcealed)
              {
            f.m_sw.WriteLine("            <p>Information about this individual has been withheld.</p>");
              }
              f.m_sw.WriteLine("          </div> <!-- individualSummary -->");
        }
        // Creates a file and writes into it the HTML for the individual's page.
        private void OutputHTML( string title )
        {
            CHTMLFile f = null;
              string pageDescription = "GEDmill GEDCOM to HTML page for " + m_sName;
              string keywords = "family tree history " + m_sName;
              string relativeFilename = GetIndividualHTMLFilename(m_ir);
              string fullFilename = String.Concat(MainForm.s_config.m_sOutputFolder, "\\", relativeFilename);

              try
              {
            f = new CHTMLFile(fullFilename, title, pageDescription, keywords); // Creates a new file, and puts standard header html into it.

            if (f != null)
            {
              OutputPageHeader(f.m_sw, m_sPreviousChildLink, m_sNextChildLink, true, true);

              if (MainForm.s_config.m_bShowMiniTrees)
              {
            OutputMiniTree(f);
              }
              f.m_sw.WriteLine("    <div class=\"hr\" />");
              f.m_sw.WriteLine("");
              f.m_sw.WriteLine("    <div id=\"page\"> <!-- page -->");

              OutputMultimedia(f);

              f.m_sw.WriteLine("      <div id=\"main\">");

              f.m_sw.WriteLine("        <div id=\"summary\">");
              OutputNames(f);
              OutputIndividualSummary(f);
              f.m_sw.WriteLine("        </div> <!-- summary -->");

              if (!MainForm.s_config.m_bShowMiniTrees)
              {
            OutputParentNames(f);
              }

              if (!m_bConcealed)
              {
            m_alEventList.Sort();
            OutputEvents(f);

            OutputAttributes(f);
            OutputNotes(f);
            OutputSourceReferences(f);
              }

              f.m_sw.WriteLine("      </div> <!-- main -->");

              f.m_sw.WriteLine("");

              // Add footer (Record date, W3C sticker, GEDmill credit etc.)
              OutputFooter( f, m_ir );

              f.m_sw.WriteLine("    </div> <!-- page -->");
            }
              }
              catch (IOException e)
              {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught IO Exception(4) : " + e.ToString());
              }
              catch (ArgumentException e)
              {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught Argument Exception(4) : " + e.ToString());
              }
              finally
              {
            if (f != null)
            {
              // Close adds the standard footer to the file
              f.Close();
            }
              }
        }
        // Generates the HTML file for the given page of the index.
        private static void OutputIndividualsIndexPage(CGedcom gedcom, string sHeadingsLinks, CIndexPage indexpage)
        {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Note, "OutputIndividualsIndexPage()");

              string sOwner = MainForm.s_config.m_sOwnersName;
              if (sOwner != "")
              {
              sOwner = " of " + sOwner;
              }

              string sFullFilename = MainForm.s_config.m_sOutputFolder;
              if (sFullFilename != "")
              {
              sFullFilename += "\\";
              }
              sFullFilename += indexpage.m_sFilename;

              CHTMLFile f = null;
              try
              {
            f = new CHTMLFile(sFullFilename, MainForm.s_config.m_sIndexTitle, "Index of all individuals in the family tree" + sOwner, "individuals index family tree people history dates"); // Creates a new file, and puts standard header html into it.

            OutputPageHeader(f.m_sw, "", "", false, true);

            f.m_sw.WriteLine("    <div class=\"hr\" />");
            f.m_sw.WriteLine("");

            f.m_sw.WriteLine("  <div id=\"page\">");
            f.m_sw.WriteLine(String.Concat("    <h1 class=\"centred\">", MainForm.s_config.m_sIndexTitle, "</h1>"));

            if (sHeadingsLinks != "")
            {
              f.m_sw.WriteLine("    <div id=\"headingsLinks\">");
              f.m_sw.WriteLine(String.Concat("      <p>", sHeadingsLinks, "</p>"));
              f.m_sw.WriteLine("    </div>");
            }

            OutputIndexPage(indexpage, f);

            f.m_sw.WriteLine("  </div> <!-- page -->");
              }
              catch (IOException e)
              {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught IO Exception(3) : " + e.ToString());
              }
              catch (ArgumentException e)
              {
            LogFile.TheLogFile.WriteLine(LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught Argument Exception(3) : " + e.ToString());
              }
              finally
              {
            if (f != null)
            {
              f.Close();
            }
              }
        }
        // Outputs the HTML table that lists the names in two columns.
        private static void OutputIndexPageColumns(CHTMLFile f, ArrayList alFirstHalf, ArrayList alSecondHalf)
        {
            f.m_sw.WriteLine("    <table id=\"index\">");
              int i = 0, j = 0;
              while (i < alFirstHalf.Count || j < alSecondHalf.Count)
              {
            string sLink1 = "&nbsp;";
            string sLink2 = "&nbsp;";
            string sExtras1 = "&nbsp;";
            string sExtras2 = "&nbsp;";
            if (i < alFirstHalf.Count)
            {
              CStringTuple tuple = (CStringTuple)alFirstHalf[i];
              string sName = EscapeHTML(tuple.m_sFirst, true);
              if (sName.Length >= 7 && sName.Substring(0, 7) == ",&nbsp;") // Hack for no surname.
              {
            if (sName.Length == 7)
            {
              sName = MainForm.s_config.m_sUnknownName;
            }
            else
            {
              sName = sName.Substring(7);
            }
              }
              else if (sName.Length >= 6 && sName.Substring(0, 6) == ",_&lt;")// Hack for unknown name.
              {
            sName = sName.Substring(2);
              }
              string sLink = tuple.m_sSecond;
              if (sLink != "")
              {
              sLink1 = String.Concat("<a href=\"", sLink, "\">", sName, "</a>");
              }
              else if (sName == MainForm.s_config.m_sNoSurname) // Hack for no surname.
              {
              sLink1 = String.Concat("<h2 id=\"-\">", sName, "</h2>");
              }
              else
              {
              sLink1 = String.Concat("<h2 id=\"", sName[0], "\">", sName, "</h2>");
              }

              sExtras1 = tuple.m_sThird;
              ++i;
            }
            if (j < alSecondHalf.Count)
            {
              CStringTuple tuple = (CStringTuple)alSecondHalf[j];
              string sName = EscapeHTML(tuple.m_sFirst, true);
              if (sName.Length >= 7 && sName.Substring(0, 7) == ",&nbsp;") // Hack for no surname.
              {
            if (sName.Length == 7)
            {
              sName = MainForm.s_config.m_sUnknownName;
            }
            else
            {
              sName = sName.Substring(7);
            }
              }
              else if (sName.Length >= 6 && sName.Substring(0, 6) == ",_&lt;")// Hack for unknown name.
              {
            sName = sName.Substring(2);
              }

              string sLink = tuple.m_sSecond;
              if (sLink != "")
              {
              sLink2 = String.Concat("<a href=\"", sLink, "\">", sName, "</a>");
              }
              else if (sName == MainForm.s_config.m_sNoSurname) // Hack for no surname.
              {
              sLink2 = String.Concat("<h2 id=\"-\">", sName, "</h2>");
              }
              else
              {
              sLink2 = String.Concat("<h2 id=\"", sName[0], "\">", sName, "</h2>");
              }

              sExtras2 = tuple.m_sThird;
              ++j;
            }
            if (MainForm.s_config.m_bIncludeUserRefInIndex)
            {
              f.m_sw.WriteLine(String.Concat("        <tr><td>", sExtras1, "</td><td>", sLink1, "</td><td>", sExtras2, "</td><td>", sLink2, "</td></tr>"));
            }
            else
            {
              f.m_sw.WriteLine(String.Concat("        <tr><td>", sLink1, "</td><td>", sLink2, "</td></tr>"));
            }
              }
              f.m_sw.WriteLine("    </table>");
        }
        // Generates the core of the HTML file for the given page of the index.
        private static void OutputIndexPage(CIndexPage indexpage, CHTMLFile f)
        {
            int nTotal = indexpage.m_nTotalIndis + indexpage.m_alLetters.Count;

              if (indexpage.m_alLetters.Count > 0)
              {
            ArrayList alFirstHalf = new ArrayList();
            ArrayList alSecondHalf = new ArrayList();
            ArrayList alCurrentHalf = alFirstHalf;

            int nHalfWay;
            if (nTotal < 20)
            {
              // If less than 20 individuals, list them in one nColumn.
              // Set half-way pointer beyond end so that it is never reached.
              nHalfWay = nTotal + 1;
            }
            else
            {
              nHalfWay = (nTotal + 1) / 2;
            }
            int nAdded = 0;

            foreach (CIndexLetter letter in indexpage.m_alLetters)
            {
              if (nAdded == nHalfWay)
              {
            // Don't add heading letter to bottom of first half.
            alCurrentHalf = alSecondHalf;
              }

              // Add heading letter.
              alCurrentHalf.Add(new CStringTuple(letter.m_sTitle, ""));
              ++nAdded;

              // Add indis.
              foreach (CStringTuple tuple in letter.m_alItems)
              {
            if (nAdded == nHalfWay)
            {
              alCurrentHalf = alSecondHalf;
            }
            alCurrentHalf.Add(tuple);
            ++nAdded;
              }
            }

            // Output HTML.
            OutputIndexPageColumns(f, alFirstHalf, alSecondHalf);
              }
              else
              {
            f.m_sw.WriteLine("    <p>There are no individuals to list.</p>");
              }
        }
 // Outputs the HTML to display the W3C Valid XHTML image on the page.
 protected void OutputValiditySticker(CHTMLFile f)
 {
     f.m_sw.WriteLine("<p class=\"plain\">");
       f.m_sw.WriteLine("<a href=\"http://validator.w3.org/check?uri=referer\"><img");
       f.m_sw.WriteLine("src=\"" + m_sW3CFile + "\"");
       f.m_sw.WriteLine("style=\"margin-top:4px\"");
       f.m_sw.WriteLine("alt=\"Valid XHTML 1.0 Strict\" height=\"31\" width=\"88\" /></a>");
       f.m_sw.WriteLine("</p>");
 }
        // The main method that causes the front page to be created.
        public void Create()
        {
            string sPageDescription = "GEDmill GEDCOM to HTML family history website";
              string sKeywords = "family tree history " + MainForm.s_config.m_sOwnersName;
              string sTitle = MainForm.s_config.m_sTitle;

              CHTMLFile f = null;
              try
              {
            f = new CHTMLFile( MainForm.s_config.FrontPageURL, sTitle, sPageDescription, sKeywords ); // Creates a new file, and puts standard header html into it.
            f.m_sw.WriteLine("  <div id=\"page\"> <!-- page -->");
            f.m_sw.WriteLine("    <div id=\"cover\"> <!-- cover -->");

            f.m_sw.WriteLine(String.Concat("       <h1>", EscapeHTML(sTitle,false ), "</h1>"));

            if( MainForm.s_config.m_sFrontPageImageFilename != "" )
            {
              Rectangle newArea = new Rectangle( 0,0,0,0 );
              string pictureFile = CopyMultimedia( MainForm.s_config.m_sFrontPageImageFilename, "", 0, 0, ref newArea, null );
              if( pictureFile != null && pictureFile != "" )
              {
            f.m_sw.WriteLine(String.Concat("       <p><img src=\"" + pictureFile + "\" alt=\"Front page image\" /></p>"));
              }
            }

            if( MainForm.s_config.m_sCommentaryText!=null && MainForm.s_config.m_sCommentaryText!="" )
            {
              if( MainForm.s_config.m_bCommentaryIsHtml )
              {
            f.m_sw.WriteLine(String.Concat("       <p>", MainForm.s_config.m_sCommentaryText, "</p>" ));
              }
              else
              {
            f.m_sw.WriteLine(String.Concat("       <p>", EscapeHTML( MainForm.s_config.m_sCommentaryText, false ), "</p>" ));
              }
            }

            if( MainForm.s_config.m_bFrontPageStats )
            {
              string sIndividuals;
              if( m_stats.m_unIndividuals == 0 )
              {
            sIndividuals = "no";
              }
              else
              {
            sIndividuals = m_stats.m_unIndividuals.ToString();
              }
              sIndividuals += " individual";
              if( m_stats.m_unIndividuals != 1 )
              {
            sIndividuals += "s";
              }

              string sSources;
              if( m_stats.m_unSources == 0 )
              {
            sSources = "";
              }
              else
              {
            sSources = String.Concat(", cross-referenced to ", m_stats.m_unSources.ToString(), " source" );
              }
              if( m_stats.m_unSources > 1 )
              {
            sSources += "s";
              }

              string sMultimedia;
              string sFileType;
              if( m_stats.m_bNonPicturesIncluded )
              {
            sFileType = "multimedia file";
              }
              else
              {
            sFileType = "image";
              }
              if( m_stats.m_unMultimediaFiles == 0 )
              {
            sMultimedia = "";
              }
              else
              {
            sMultimedia = String.Concat(". There are links to ", m_stats.m_unMultimediaFiles.ToString(), " ", sFileType );
              }
              if( m_stats.m_unMultimediaFiles > 1 )
              {
            sMultimedia += "s";
              }

              f.m_sw.WriteLine(String.Concat("       <p>This website contains records on ",sIndividuals,sSources,sMultimedia, ".</p>" ));
            } // End front page stats

            f.m_sw.WriteLine("       <div id=\"links\"> <!-- links -->");
            f.m_sw.WriteLine(String.Concat("         <p><a href=\"individuals1.",MainForm.s_config.m_sHtmlExtension,"\">", MainForm.s_config.m_sIndexTitle, "</a></p>"));
            f.m_sw.WriteLine("       </div> <!-- links -->");
            if( MainForm.s_config.m_alKeyIndividuals != null && MainForm.s_config.m_alKeyIndividuals.Count > 0 )
            {
              // Although in theory you might want a restricted individual as a key individual, (they still form part of the tree), in practice this isn't allowed:
              ArrayList alCensoredKeyIndividuals = new ArrayList(MainForm.s_config.m_alKeyIndividuals.Count);

              foreach( string keyXref in MainForm.s_config.m_alKeyIndividuals )
              {
            CIndividualRecord air = m_gedcom.GetIndividualRecord( keyXref );
            if( air != null )
            {
              alCensoredKeyIndividuals.Add( MakeLink(air) );
            }
              }

              if( alCensoredKeyIndividuals.Count > 0 )
              {
            string plural = "";
            if( alCensoredKeyIndividuals.Count > 1 )
            {
              plural = "s";
            }
            f.m_sw.WriteLine( "         <div id=\"keyindividuals\">");
            f.m_sw.WriteLine(String.Concat("           <p>Key Individual",plural,":</p>"));
            f.m_sw.WriteLine( "           <ul>");
            foreach( string air_link in alCensoredKeyIndividuals )
            {
              f.m_sw.WriteLine( String.Concat("             <li>", air_link, "</li>") );
            }
            f.m_sw.WriteLine( "           </ul>");
            f.m_sw.WriteLine( "         </div> <!-- keyindividuals -->");
              }
            }

            string byEmail = "";
            // Email contact address
            if( MainForm.s_config.m_sUserEmailAddress != null && MainForm.s_config.m_sUserEmailAddress.Length > 0  )
            {
              byEmail = String.Concat(" by <a href=\"mailto:",MainForm.s_config.m_sUserEmailAddress,"\">",EscapeHTML(MainForm.s_config.m_sUserEmailAddress, false),"</a>" );
            }

            // Add brand and contact label
            f.m_sw.WriteLine(String.Concat("       <p>Website created",byEmail," using GEDmill.</p>"));
            // Add last update string
            if( MainForm.s_config.m_bAddHomePageCreateTime )
            {
              DateTime dt = DateTime.Now;
              string update_date_string = dt.ToString("dd MMMM yyyy", DateTimeFormatInfo.InvariantInfo);

              f.m_sw.WriteLine(String.Concat("       <p>Created on ",update_date_string,".</p>"));
            }

            // Add link to users main website
            if( MainForm.s_config.m_sMainWebsiteLink != "" )
            {
              f.m_sw.WriteLine( String.Concat("    <p><a href=\"", MainForm.s_config.m_sMainWebsiteLink, "\">Return to main site</a></p>") );
            }

            f.m_sw.WriteLine("    </div> <!-- cover -->");
            f.m_sw.WriteLine("  </div> <!-- page -->");
              }
              catch( IOException e )
              {
            LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught IO Exception(7) : " + e.ToString() );
              }
              catch( ArgumentException e )
              {
            LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught Argument Exception(7) : " + e.ToString() );
              }
              finally
              {
            if( f != null )
            {
              // Add standard footer to the file
              f.Close();
            }
              }
        }
        // Writes the HTML for the multimedia files associated with this record.
        private void OutputMultimedia(CHTMLFile f)
        {
            if (m_alMultimediaList.Count > 0)
              {
            CIMultimedia iMultimedia = (CIMultimedia)m_alMultimediaList[0];
            f.m_sw.WriteLine("    <div id=\"photos\">");
            f.m_sw.WriteLine("      <div id=\"mainphoto\">");
            string non_pic_small_filename = "multimedia/" + MainForm.NonPicFilename(iMultimedia.m_sFormat, true, MainForm.s_config.m_bLinkOriginalPicture);
            string non_pic_main_filename = "multimedia/" + MainForm.NonPicFilename(iMultimedia.m_sFormat, false, MainForm.s_config.m_bLinkOriginalPicture);
            string image_title = "";
            string alt_name = m_sFullName;
            if (iMultimedia.m_sTitle != null)
            {
              image_title = iMultimedia.m_sTitle;
              alt_name = iMultimedia.m_sTitle;
            }
            if (MainForm.s_config.m_bLinkOriginalPicture)
            {
              if (iMultimedia.m_nWidth != 0 && iMultimedia.m_nHeight != 0)
              {
            // Must be a picture.
            if (iMultimedia.m_sLargeFilename.Length > 0)
            {
              f.m_sw.WriteLine(String.Concat("        <a href=\"", iMultimedia.m_sLargeFilename, "\" id=\"mainphoto_link\"><img id=\"mainphoto_img\" src=\"", iMultimedia.m_sFilename, "\" alt=\"", alt_name, "\" /></a>"));
            }
            else
            {
              f.m_sw.WriteLine(String.Concat("        <img id=\"mainphoto_img\" src=\"", iMultimedia.m_sFilename, "\" alt=\"I", alt_name, "\" />"));
            }
              }
              else
              {
            // Must be a non-picture multimedia file.
            if (iMultimedia.m_sLargeFilename.Length > 0)
            {
              f.m_sw.WriteLine(String.Concat("        <a href=\"", iMultimedia.m_sLargeFilename, "\" id=\"mainphoto_link\"><img id=\"mainphoto_img\" src=\"", non_pic_main_filename, "\" alt=\"", alt_name, "\" /></a>"));
            }
            else
            {
              f.m_sw.WriteLine(String.Concat("        <img id=\"mainphoto_img\" src=\"", non_pic_main_filename, "\" alt=\"", alt_name, "\" />"));
            }
              }

            }
            else // Not linking to original picture.
            {
              if (iMultimedia.m_nWidth != 0 && iMultimedia.m_nHeight != 0)
              {
            // Must be a picture.
            f.m_sw.WriteLine(String.Concat("        <img id=\"mainphoto_img\" src=\"", iMultimedia.m_sFilename, "\" alt=\"", alt_name, "\" />"));
              }
              else
              {
            // Must be a non-picture multimedia file.
            f.m_sw.WriteLine(String.Concat("        <img id=\"mainphoto_img\" src=\"", non_pic_main_filename, "\" alt=\"", alt_name, "\" />"));
              }
            }
            f.m_sw.WriteLine(String.Concat("        <p id=\"mainphoto_title\">", image_title, "</p>"));
            f.m_sw.WriteLine("      </div>");

            if (m_alMultimediaList.Count > 1 && MainForm.s_config.m_bAllowMultipleImages)
            {
              f.m_sw.WriteLine("      <div id=\"miniphotos\">");

              for (int i = 0; i < m_alMultimediaList.Count; i++)
              {
            iMultimedia = (CIMultimedia)m_alMultimediaList[i];

            non_pic_small_filename = "multimedia/" + MainForm.NonPicFilename(iMultimedia.m_sFormat, true, MainForm.s_config.m_bLinkOriginalPicture);
            non_pic_main_filename = "multimedia/" + MainForm.NonPicFilename(iMultimedia.m_sFormat, false, MainForm.s_config.m_bLinkOriginalPicture);

            string largeFilenameArg;
            if (iMultimedia.m_sLargeFilename != null && iMultimedia.m_sLargeFilename.Length > 0)
            {
              largeFilenameArg = String.Concat("'", iMultimedia.m_sLargeFilename, "'");
            }
            else
            {
              largeFilenameArg = "null";
            }

            f.m_sw.WriteLine("         <div class=\"miniphoto\">");
            if (iMultimedia.m_nWidth != 0 && iMultimedia.m_nHeight != 0)
            {
              // Must be a picture.
              // Scale mini pic down to thumbnail.
              Rectangle newArea = new Rectangle(0, 0, iMultimedia.m_nWidth, iMultimedia.m_nHeight);
              MainForm.ScaleAreaToFit(ref newArea, MainForm.s_config.m_uMaxThumbnailImageWidth, MainForm.s_config.m_uMaxThumbnailImageHeight);

              f.m_sw.WriteLine(String.Concat("          <img style=\"width:", newArea.Width, "px; height:", newArea.Height, "px; margin-bottom:", MainForm.s_config.m_uMaxThumbnailImageHeight - newArea.Height, "px;\" class=\"miniphoto_img\" src=\"", iMultimedia.m_sFilename, "\" alt=\"Click to select\" onclick=\"updateMainPhoto('", iMultimedia.m_sFilename, "','", EscapeJavascript(iMultimedia.m_sTitle), "',", largeFilenameArg, ")\" />"));
            }
            else
            {
              // Other multimedia.
              f.m_sw.WriteLine(String.Concat("          <img style=\"width:", MainForm.s_config.m_uMaxThumbnailImageWidth, "px; height:", MainForm.s_config.m_uMaxThumbnailImageHeight, "px;\" class=\"miniphoto_img\" src=\"", non_pic_small_filename, "\" alt=\"Click to select\" onclick=\"updateMainPhoto('", non_pic_main_filename, "','", EscapeJavascript(iMultimedia.m_sTitle), "',", largeFilenameArg, ")\" />"));
            }
            f.m_sw.WriteLine("         </div>");
              }

              f.m_sw.WriteLine("      </div>");
            }
            f.m_sw.WriteLine("    </div> <!-- photos -->");
              }
        }
        // The main method that causes the page to be created.
        public bool Create(CStats stats)
        {
            // Sanity check
              if( m_sr == null )
              {
            return false;
              }

              // Create the strings to use for the HTML file.
              string sPageDescription = "GEDmill GEDCOM to HTML page for " + m_sr.m_sSourceDescriptiveTitle;
              string sKeywords = "family tree history " + m_sr.m_sSourceDescriptiveTitle;
              string sFilename = String.Concat( MainForm.s_config.m_sOutputFolder, "\\sour", m_sr.m_xref );
              string sFullFilename = String.Concat(sFilename, ".", MainForm.s_config.m_sHtmlExtension);

              CHTMLFile f = null;
              try
              {
            // Create a new file with an HTML header.
            f = new CHTMLFile( sFullFilename, m_sr.DescriptiveTitle, sPageDescription, sKeywords );

            // Create a navbar to main site, front page etc.
            OutputPageHeader( f.m_sw, "", "", true, true );

            f.m_sw.WriteLine("    <div class=\"hr\"></div>");
            f.m_sw.WriteLine("");
            f.m_sw.WriteLine("    <div id=\"page\"> <!-- page -->");

            // Write the page's title text.
            f.m_sw.WriteLine("      <div id=\"main\">");
            f.m_sw.WriteLine("        <div id=\"summary\">");
            f.m_sw.WriteLine("          <div id=\"names\">");
            string sName = m_sr.DescriptiveTitle;
            if( sName == "" )
            {
              sName = "Source ";
              bool bGotSourceName = false;
              // Try user reference number
              foreach( CUserReferenceNumber urn in m_sr.m_alUserReferenceNumbers )
              {
            if( urn.m_sUserReferenceNumber != "" )
            {
              sName += urn.m_sUserReferenceNumber;
              bGotSourceName = true;
              break;
            }
              }
              if( !bGotSourceName && m_sr.m_sAutomatedRecordId != null && m_sr.m_sAutomatedRecordId != "" )
              {
            sName += m_sr.m_sAutomatedRecordId;
              }
              else if( !bGotSourceName )
              {
            sName += m_sr.m_xref;
              }
            }
            f.m_sw.WriteLine(String.Concat("            <h1>",EscapeHTML(sName,false ),"</h1>"));

            // Add repository information
            foreach( CSourceRepositoryCitation src in m_sr.m_alSourceRepositoryCitations )
            {
              string xrefRepo = src.m_xrefRepo;
              CRepositoryRecord rr = m_gedcom.GetRepositoryRecord( xrefRepo );
              if( rr != null )
              {
              if (rr.m_sNameOfRepository != null && rr.m_sNameOfRepository != "")
              {
                  f.m_sw.WriteLine(String.Concat("            <h2>", EscapeHTML(rr.m_sNameOfRepository, false), "</h2>"));
              }
            if( rr.m_alNoteStructures != null && rr.m_alNoteStructures.Count > 0 )
            {
              foreach( CNoteStructure ns in rr.m_alNoteStructures )
              {
                string noteText;
                if( MainForm.s_config.m_bObfuscateEmails )
                {
                  noteText = ObfuscateEmail( ns.Text );
                }
                else
                {
                  noteText = ns.Text;
                }
                f.m_sw.WriteLine(String.Concat("            <p>", EscapeHTML( noteText, false ), "</p>" ) );
              }
            }
              }
              if( src.m_alNoteStructures != null && src.m_alNoteStructures.Count > 0 )
              {
            foreach( CNoteStructure ns in src.m_alNoteStructures )
            {
              string noteText;
              if( MainForm.s_config.m_bObfuscateEmails )
              {
                noteText = ObfuscateEmail( ns.Text );
              }
              else
              {
                noteText = ns.Text;
              }

              f.m_sw.WriteLine(String.Concat("            <p>", EscapeHTML( noteText, false ), "</p>" ) );
            }
              }

            }

            // Add Publication Information
            string sPubFacts;
            if( MainForm.s_config.m_bObfuscateEmails )
            {
              sPubFacts = ObfuscateEmail( m_sr.m_sSourcePublicationFacts );
            }
            else
            {
              sPubFacts = m_sr.m_sSourcePublicationFacts;
            }
            if( sPubFacts != null && sPubFacts != "" )
            {
              if( sPubFacts.Length > 7 && sPubFacts.ToUpper().Substring(0,7) == "HTTP://" )
              {
            f.m_sw.WriteLine(String.Concat("            <h2>","<a href=\"", sPubFacts, "\">", EscapeHTML(sPubFacts,false), "</a>","</h2>"));
              }
              else
              {
            f.m_sw.WriteLine(String.Concat("            <h2>",EscapeHTML(sPubFacts,false),"</h2>"));
              }
            }

            f.m_sw.WriteLine("          </div> <!-- names -->");
            f.m_sw.WriteLine("        </div> <!-- summary -->");

            // Collect together multimedia links.
            if( MainForm.s_config.m_bAllowMultimedia && m_sr.m_alUniqueFileRefs != null )
            {
              m_sr.m_alUniqueFileRefs.Sort( new CMultimediaFileReference.OrderComparer() );

              // Fill m_alMultimediaList:
              AddMultimedia( null, m_sr.m_alUniqueFileRefs, String.Concat(m_sr.m_xref,"mms"), String.Concat(m_sr.m_xref,"mos"), MainForm.s_config.m_uMaxSourceImageWidth, MainForm.s_config.m_uMaxSourceImageHeight, stats );
            }

            // Add pics
            OutputMultimedia(f);

            // Add textFromSource
            string sCleanText = m_sr.m_sTextFromSource;
            CGedcom.ParseWhitespace( ref sCleanText );
            if( MainForm.s_config.m_bObfuscateEmails )
            {
              sCleanText = ObfuscateEmail( sCleanText );
            }
            if( sCleanText != null && sCleanText != "" )
            {
              f.m_sw.WriteLine("        <div id=\"text\">");
              f.m_sw.WriteLine("          <h1>Text</h1>");
              f.m_sw.WriteLine("          <p class=\"pretext\">");
              f.m_sw.WriteLine( EscapeHTML( sCleanText,false) );
              f.m_sw.WriteLine("            </p>");
              f.m_sw.WriteLine("        </div> <!-- text -->");
            }

            // Add notes
            if( m_sr.m_alNoteStructures.Count > 0 )
            {
              // Generate notes list into a local array before adding header title. This is to cope with the case where all notes are nothing but blanks.
              ArrayList alNoteStrings = new ArrayList(m_sr.m_alNoteStructures.Count);

              foreach( CNoteStructure ns in m_sr.m_alNoteStructures )
              {
            if( ns.Text != null && ns.Text.Length > 0 )
            {
              string sNoteText;
              if( MainForm.s_config.m_bObfuscateEmails )
              {
                sNoteText = ObfuscateEmail( ns.Text );
              }
              else
              {
                sNoteText = ns.Text;
              }

              string sourceRefs = "";
              alNoteStrings.Add( String.Concat("          <li>",EscapeHTML(sNoteText,false),sourceRefs,"</li>") );
            }
              }

              if( alNoteStrings.Count > 0 )
              {
            f.m_sw.WriteLine("        <div id=\"notes\">");
            f.m_sw.WriteLine("          <h1>Notes</h1>");
            f.m_sw.WriteLine("          <ul>");

            foreach( string note_string in alNoteStrings )
            {
              f.m_sw.WriteLine(note_string);
            }

            f.m_sw.WriteLine("          </ul>");
            f.m_sw.WriteLine("        </div> <!-- notes -->");
              }
            }

            if( MainForm.s_config.m_bSupressBackreferences == false )
            {
              if( m_sr.m_alBackreferences != null && m_sr.m_alBackreferences.Count > 0 )
              {
            f.m_sw.WriteLine("        <div id=\"citations\">" );
            f.m_sw.WriteLine("          <h1>Citations</h1>");
            f.m_sw.WriteLine("          <ul>");

            Hashtable htBackrefs = m_sr.MakeBackRefList();

            IDictionaryEnumerator enumerator = htBackrefs.GetEnumerator();
            while( enumerator.MoveNext() )
            {
              CIndividualRecord ir = (CIndividualRecord)(enumerator.Value);
              if( ir != null && !ir.Restricted )
              {
                string link = MakeLink(ir);
                if( link != "" )
                {
                  f.m_sw.WriteLine( String.Concat( "            <li>", link, "</li>" ) );
                }
              }
            }

            f.m_sw.WriteLine("          </ul>");
            f.m_sw.WriteLine("        </div> <!-- citations -->");

              }
            }

            f.m_sw.WriteLine("      </div> <!-- main -->");

            // Add footer (Record date, W3C sticker, GEDmill credit etc.)
            OutputFooter( f, m_sr );

            f.m_sw.WriteLine("    </div> <!-- page -->");
              }
              catch( IOException e )
              {
            LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught IO Exception(6) : " + e.ToString() );
              }
              catch( ArgumentException e )
              {
            LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.Error, "Caught Argument Exception(6) : " + e.ToString() );
              }
              finally
              {
            if( f != null )
            {
              f.Close(); // Adds standard footer to the file
            }
              }
              return true;
        }
 // Writes the individual's names to the HTML file.
 private void OutputNames(CHTMLFile f)
 {
     f.m_sw.WriteLine("          <div id=\"names\">");
       if (m_sFullName != m_sName)
       {
     f.m_sw.WriteLine(String.Concat("            <h2>", EscapeHTML(m_sFullName, false), "</h2>"));
       }
       if (m_sUsedName != "" && m_sNickName != "")
       {
     m_sUsedName += ", ";
       }
       string nicknames = "";
       if (m_sUsedName != "" || m_sNickName != "")
       {
     nicknames = String.Concat(" <span class=\"nicknames\">(", EscapeHTML(m_sUsedName, false), EscapeHTML(m_sNickName, false), ")</span>");
       }
       f.m_sw.WriteLine(String.Concat("            <h1>", EscapeHTML(m_sName, false), m_sNameSources, nicknames, "</h1>"));
       foreach (CNameAndSource other_name in m_alOtherNames)
       {
     f.m_sw.WriteLine(String.Concat("            <h2>also known as ", EscapeHTML(other_name.m_sName, false), other_name.m_sSourceHtml, "</h2>"));
       }
       f.m_sw.WriteLine("          </div> <!-- names -->");
 }