// Constructor
 public CMultimediaFileReference( CGedcom gedcom )
     : base(gedcom)
 {
     m_bFromGEDCOM = true;
     m_bVisible = true;
     m_nOrderIndex = 0;
     m_mfrOriginal = null;
     m_asidPair = null;
     m_xrefEmbedded = "";
     m_sMultimediaFileReference = "";
 }
 // Saves the MFR to the changes file (MFR here is for the user's modifications to the multimedia attached to a record)
 private void SaveMFR(StreamWriter sw, CMultimediaFileReference mfr)
 {
     sw.WriteLine(" 1 OBJE");
     sw.WriteLine(String.Concat(" 2 FORM ", mfr.m_sMultimediaFormat));
     sw.WriteLine(String.Concat(" 2 TITL ", mfr.m_sDescriptiveTitle));
     string sPicFilename = mfr.m_sMultimediaFileReference.Replace('\\', '/'); ;
     if (!mfr.m_bEmbedded)
     {
         sw.WriteLine(String.Concat(" 2 FILE ", sPicFilename));
     }
     else
     {
         sw.WriteLine(" 2 FILE inline");
     }
     sw.WriteLine(String.Concat(" 2 _ORDER ", mfr.m_nOrderIndex.ToString()));
     sw.WriteLine(String.Concat(" 2 _VISIBLE ", mfr.m_bVisible ? "true" : "false"));
     sw.WriteLine(String.Concat(" 2 _GEDCOM ", mfr.m_bFromGEDCOM ? "true" : "false"));
     if (mfr.m_bEmbedded)
     {
         sw.WriteLine(String.Concat(" 2 _INLINE ", mfr.m_xrefEmbedded));
     }
     if (mfr.m_asidPair != null)
     {
         sw.WriteLine(String.Concat(" 2 _REGION ", mfr.m_asidPair.m_sAsid, ",{", mfr.m_asidPair.m_rectArea.Top, ",", mfr.m_asidPair.m_rectArea.Left, ",", mfr.m_asidPair.m_rectArea.Bottom, ",", mfr.m_asidPair.m_rectArea.Right, "}"));
     }
 }
        // Helps in parsing the changes file
        private void ParseSecondary(ref CISRecordChanges isrc, string sSecondary)
        {
            string sCmd = "";
            string sArg = "";
            string sNum = "";
            int nState = 0;
            foreach (char c in sSecondary)
            {
                switch (nState)
                {
                    case 0:
                        // Leading whitespace
                        if (!char.IsWhiteSpace(c))
                        {
                            sNum += c;
                            nState = 1;
                        }
                        break;
                    case 1:
                        // Number
                        if (char.IsDigit(c))
                        {
                            sNum += c;
                        }
                        else
                        {
                            if (!char.IsWhiteSpace(c))
                            {
                                sCmd += c;
                                nState = 3;
                            }
                            nState = 2;
                        }
                        break;
                    case 2:
                        // Space after number
                        if (!char.IsWhiteSpace(c))
                        {
                            sCmd += c;
                            nState = 3;
                        }
                        break;
                    case 3:
                        if (!char.IsWhiteSpace(c))
                        {
                            sCmd += c;
                        }
                        else
                        {
                            nState = 4;
                        }
                        break;
                    case 4:
                        // Space after cmd
                        if (!char.IsWhiteSpace(c))
                        {
                            sArg += c;
                            nState = 5;
                        }
                        break;
                    case 5:
                        sArg += c;
                        break;
                }

                if (nState == 99)
                {
                    // End of string parsing
                    break;
                }
            }

            if (isrc != null)
            {
                switch (sCmd)
                {
                    case "OBJE":
                        {
                            CMultimediaFileReference mfr = new CMultimediaFileReference(m_gedcom);
                            mfr.m_bFromGEDCOM = false;
                            isrc.m_alMfrs.Add(mfr);
                            isrc.m_mfrCurrent = mfr;
                            break;
                        }
                    case "FILE":
                        if (isrc.m_mfrCurrent != null)
                        {
                            sArg = sArg.Replace('/', '\\');
                            isrc.m_mfrCurrent.m_sMultimediaFileReference = sArg;
                        }
                        break;
                    case "FORM":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_sMultimediaFormat = sArg;
                        }
                        break;
                    case "TITL":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_sDescriptiveTitle = sArg;
                        }
                        break;
                    case "_ORDER":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_nOrderIndex = int.Parse(sArg);
                        }
                        break;
                    case "_VISIBLE":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_bVisible = (sArg.ToUpper() == "TRUE") ? true : false;
                        }
                        break;
                    case "_GEDCOM":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_bFromGEDCOM = (sArg.ToUpper() == "TRUE") ? true : false;
                        }
                        break;
                    case "_INLINE":
                        if (isrc.m_mfrCurrent != null)
                        {
                            isrc.m_mfrCurrent.m_bEmbedded = true;
                            isrc.m_mfrCurrent.m_xrefEmbedded = sArg;
                        }
                        break;
                    case "_REGION":
                        if (isrc.m_mfrCurrent != null)
                        {
                            int nFirstComma = sArg.IndexOf(',');
                            if (nFirstComma > 0 && nFirstComma + 1 < sArg.Length)
                            {
                                string sAsid = sArg.Substring(0, nFirstComma);
                                string sArea = sArg.Substring(nFirstComma + 1);
                                CAsidPair asidPair = new CAsidPair(sAsid, sArea);
                                isrc.m_mfrCurrent.m_asidPair = asidPair;
                            }
                        }
                        break;
                }
            }
            return;
        }
        // Parser
        public static CMultimediaRecord Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;
            bool bParsingFinished;

            // Without an xref header, we can't continue
            if ((gedcomLine = gedcom.GetLine(nLevel, "OBJE")) == null)
            {
                // Not one of us
                return null;
            }

            CMultimediaRecord mr = new CMultimediaRecord( gedcom );
            mr.m_xref = gedcomLine.XrefID;
            gedcom.IncrementLineIndex(1);
            CMultimediaFileReference mfr = null;

            CNoteStructure ns;
            CSourceCitation sc;
            System.Text.StringBuilder blob = new System.Text.StringBuilder(256);

            do
            {
                bParsingFinished = true;

                // Family Historian style. Underscore, so check for this first
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "_FILE" )) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFileReference = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }

                // Let Record have a go at parsing the rest
                else if( mr.ParseRecord( gedcom, nLevel ) )
                {
                    bParsingFinished = false;
                    continue;
                }

                // 5.5 style
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "FORM")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFormat = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);

                    // There may be one of these, standard specifies {0:1}
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "TITL")) != null )
                    {
                        mfr.m_sDescriptiveTitle = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "BLOB")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_bEmbedded = true;

                    gedcom.IncrementLineIndex(1);

                    while( (gedcomLine = gedcom.GetLine(nLevel+2, "CONT")) != null )
                    {
                        blob.Append( gedcomLine.LineItem );
                        gedcom.IncrementLineIndex(1);
                    }
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "OBJE")) != null  )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_xrefObj = gedcomLine.LinePointer;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                // GEDCOM 5.5 style
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "FILE" )) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sMultimediaFileReference = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                // GEDCOM 5.5.1 style
                else if( (mfr == null) && ((mfr = CMultimediaFileReference.Parse( gedcom, nLevel+1 )) != null) )
                {
                    bParsingFinished = false;
                }
                else if( (ns = CNoteStructure.Parse( gedcom, nLevel+1 )) != null )
                {
                    mr.m_alNoteStructures.Add( ns );
                    bParsingFinished = false;
                }
                else if( (sc = CSourceCitation.Parse( gedcom, nLevel+1 )) != null )
                {
                    mr.m_alSourceCitations.Add( sc );
                    bParsingFinished = false;
                }
                else if( (gedcomLine = gedcom.GetLine(nLevel+1, "TITL")) != null )
                {
                    if( mfr == null )
                        mfr = new CMultimediaFileReference( gedcom );

                    mfr.m_sDescriptiveTitle = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            if (mfr != null)
            {
                mr.m_alMultimediaFileReferences.Add(mfr);
            }

            // Family Historian style
            // If any of the notes contain only _ASID and _AREA, move these values to the m_asidPairs
            ArrayList notesToRemove = new ArrayList();
            foreach( CNoteStructure nss in mr.m_alNoteStructures )
            {
                if( nss is CNoteStructureInLine )
                {
                    if( ((CNoteStructureInLine)nss).m_sSubmitterText == null || ((CNoteStructureInLine)nss).m_sSubmitterText == "" )
                    {
                        if( ((CNoteStructureInLine)nss).m_sAsid != ""
                            || ((CNoteStructureInLine)nss).m_sArea != "" )
                        {
                            string asid = ((CNoteStructureInLine)nss).m_sAsid;
                            CAsidPair asidPair = new CAsidPair( asid, ((CNoteStructureInLine)nss).m_sArea );
                            mr.m_htAsidPairs.Add( asid, asidPair );
                            notesToRemove.Add( nss );
                        }
                    }
                }
            }
            foreach( CNoteStructure nsss in notesToRemove )
            {
                mr.m_alNoteStructures.Remove( nsss );
            }

            if( blob.Length > 0 )
            {
                // Decode blob and overwrite sFilename with decoded blob sFilename
                try
                {
                    mfr.m_sMultimediaFileReference = gedcom.DecodeBlob( blob.ToString() );
                }
                catch( CBlobException )
                {
                    // Error decoding blob
                    mfr.m_sMultimediaFileReference = null;
                }
            }

            return mr;
        }
        // Constructor
        public CListableMFR(CMultimediaFileReference mfr)
        {
            m_mfr = mfr;

            base.Text = ToString();
        }
 // Constructor
 public CISRecordChanges( bool bIncludeInWebsite )
 {
     m_bIncludeInWebsite = bIncludeInWebsite;
     m_alMfrs = new ArrayList();
     m_mfrCurrent = null;
 }
        // Copy constructor
        public CMultimediaFileReference( CMultimediaFileReference mfr, bool bKeepRefToOriginal )
            : base(mfr.Gedcom)
        {
            CopyFrom( mfr );

            if( bKeepRefToOriginal )
            {
                m_mfrOriginal = mfr;
            }
            else
            {
                m_mfrOriginal = null;
            }
        }
        // Assignment
        public void CopyFrom( CMultimediaFileReference mfr )
        {
            m_sMultimediaFileReference = mfr.m_sMultimediaFileReference;
            m_sMultimediaFormat = mfr.m_sMultimediaFormat;
            m_sDescriptiveTitle = mfr.m_sDescriptiveTitle;
            m_xrefObj = mfr.m_xrefObj;
            if( mfr.m_asidPair != null )
            {
                m_asidPair = new CAsidPair( mfr.m_asidPair );
            }
            else
            {
                m_asidPair = null;
            }
            m_bFromGEDCOM = mfr.m_bFromGEDCOM;
            m_bEmbedded = mfr.m_bEmbedded;
            m_bVisible = mfr.m_bVisible;
            m_nOrderIndex = mfr.m_nOrderIndex;
            m_xrefEmbedded = mfr.m_xrefEmbedded;

            m_mfrOriginal = null;
        }
        // Parser
        public static CMultimediaFileReference Parse( CGedcom gedcom, int nLevel )
        {
            CGedcomLine gedcomLine;

            // Temporary holders for class members. Saves constructing a class early.
            string sMultimediaFileReference;
            string sMultimediaFormat = "";
            string sSourceMediaType = "";

            // There must be one of these, it defines the object.
            if ((gedcomLine = gedcom.GetLine(nLevel, "FILE")) == null)
            {
                // Not one of us
                return null;
            }
            sMultimediaFileReference = gedcomLine.LineItem;
            gedcom.IncrementLineIndex(1);

            bool bParsingFinished;
            do
            {
                bParsingFinished = true;

                // There must be one of these, standard specifies {1:1}
                if( (gedcomLine = gedcom.GetLine(nLevel+1, "FORM")) != null )
                {
                    sMultimediaFormat = gedcomLine.LineItem;
                    gedcom.IncrementLineIndex(1);

                    // There may be one of these, standard specifies {0:1}
                    if( (gedcomLine = gedcom.GetLine(nLevel+2, "TYPE")) != null )
                    {
                        sSourceMediaType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }
                    else if( (gedcomLine = gedcom.GetLine(nLevel+2, "MEDI")) != null )
                    {
                        sSourceMediaType = gedcomLine.LineItem;
                        gedcom.IncrementLineIndex(1);
                    }

                    bParsingFinished = false;
                }
                else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel )
                {
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" );
                    LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() );
                    gedcom.IncrementLineIndex(1);
                    bParsingFinished = false;
                }
            }
            while( !bParsingFinished );

            // Parsing went ok. Construct a new object and return it.
            CMultimediaFileReference mfr = new CMultimediaFileReference( gedcom );
            mfr.m_sMultimediaFileReference = sMultimediaFileReference;
            mfr.m_sMultimediaFormat = sMultimediaFormat;
            return mfr;
        }
        // Constructor
        public PicturesForm( CISRecord r, CGedcom gedcom )
        {
            Cursor.Current = Cursors.WaitCursor;
            Cursor.Show();

            m_bExtraUserInfoAdded = false;
            m_bDisablePictureListCheckEvent = true;
            m_record = r;
            // Add pictures
            // Copy MFRs to a new list
            m_alMultimediaFileRefs = new ArrayList();
            foreach( CMultimediaFileReference mfr in m_record.m_alUniqueFileRefs )
            {
                CAsidPair mmasidPair = mfr.m_asidPair;
                CMultimediaFileReference new_mfr = new CMultimediaFileReference( mfr, true ); // Make copy
                m_alMultimediaFileRefs.Add( new_mfr );
            }

            m_gedcom = gedcom;

            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            m_listviewPictures.View = View.Details;
            m_listviewPictures.Columns.Add("Title", (m_listviewPictures.Width-6) * 40 / 100, HorizontalAlignment.Left);
            m_listviewPictures.Columns.Add("Filename", (m_listviewPictures.Width-6) * 60 / 100, HorizontalAlignment.Left);

            m_sizePictureBox = m_picturebox.Size;

            // Add pictures
            FillPicturesList( m_listviewPictures, m_alMultimediaFileRefs );
            EnableButtons();

            // Select first checked picture
            int index = 0;
            foreach( CListableMFR lmfr in m_listviewPictures.Items )
            {
                if( lmfr.Checked )
                {
                    index = lmfr.Index;
                    break;
                }
            }
            SetPicture(index);

            Cursor.Current = Cursors.Default;
            Cursor.Show();
        }
        // Event handler for the add pictures button
        private void addButton_Click(object sender, System.EventArgs e)
        {
            m_bExtraUserInfoAdded = true;
            string sFileName = "";
            string sFileDir = MainForm.s_config.m_sLastPictureAddedDir;
            if( sFileDir.Length == 0 || Directory.Exists( sFileDir ) == false )
            {
                // Use path from input GEDCOM file
                sFileDir = Path.GetDirectoryName( MainForm.m_mainForm.InputFile );
            }
            ArrayList alFilterExtensions = new ArrayList();
            alFilterExtensions.Add( ".jpg" );
            alFilterExtensions.Add( ".jpeg" );
            alFilterExtensions.Add( ".gif" );
            alFilterExtensions.Add( ".bmp" );
            alFilterExtensions.Add( ".png" );
            if( MainForm.SelectFile( ref sFileDir, ref sFileName, "Select picture", "", true, "Picture files", alFilterExtensions ) )
            {
                MainForm.s_config.m_sLastPictureAddedDir = sFileDir;

                CMultimediaFileReference mfr = new CMultimediaFileReference( m_gedcom );
                mfr.m_sDescriptiveTitle = "";

                mfr.m_sMultimediaFileReference = sFileDir + "\\" + sFileName;
                mfr.m_bFromGEDCOM = false;
                mfr.m_bVisible = true;
                mfr.m_nOrderIndex = m_listviewPictures.Items.Count;
                m_alMultimediaFileRefs.Add( mfr );

                FillPicturesList( m_listviewPictures, m_alMultimediaFileRefs );
                EnableButtons();
            }
        }
        // Create a list of MFRs unique to the record
        public void ConvertMultimediaLinks( ArrayList alMultimediaLinks, ref ArrayList alUniqueFileRefs )
        {
            int nFileOrder = 0;
            alUniqueFileRefs.Clear();
            string xref = "";
            string sInputPath = Path.GetDirectoryName( MainForm.s_config.m_sInputFilename );

            foreach( CMultimediaLink ml in alMultimediaLinks )
            {
                CAsidPair asidPair = null;
                if( ml is CMultimediaLinkXref )
                {
                    // The only sort of ml that supports asids
                    CMultimediaLinkXref mlx = (CMultimediaLinkXref)ml;
                    string sAsid = mlx.m_sAsid;
                    if( sAsid != null && sAsid.Length > 0 )
                    {
                        xref = mlx.m_xref;
                        CMultimediaRecord mr = GetMultimediaRecord( xref );
                        if( mr != null )
                        {
                            if( mr.m_htAsidPairs.ContainsKey( sAsid ) )
                            {
                                asidPair = (CAsidPair)mr.m_htAsidPairs[ sAsid ];
                            }
                        }
                    }
                }

                ArrayList alFileRefs = ml.GetFileReferences();
                if( alFileRefs != null )
                {
                    foreach( CMultimediaFileReference mfr in alFileRefs )
                    {
                        if( mfr == null || mfr.m_sMultimediaFileReference == null || mfr.m_sMultimediaFileReference == "" )
                        {
                            continue;
                        }
                        // Correct pics that are missing a path
                        string path="" ;
                        try
                        {
                            path = Path.GetDirectoryName( mfr.m_sMultimediaFileReference );
                        }
                        catch( Exception e )
                        {
                            LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Error,  String.Format( "ConvertMultimediaLinks() Exception {0} caught for {1}.", e.Message, mfr.m_sMultimediaFileReference ) );
                        }

                        if( sInputPath != null && sInputPath.Length > 0 && (path == null || path.Length == 0) )
                        {
                            mfr.m_sMultimediaFileReference = Path.Combine( sInputPath, mfr.m_sMultimediaFileReference );
                        }

                        CMultimediaFileReference mfrUnique = new CMultimediaFileReference( mfr, false );
                        alUniqueFileRefs.Add( mfrUnique );

                        mfrUnique.m_nOrderIndex = nFileOrder++;
                        mfrUnique.m_asidPair = asidPair;
                        if( mfr.m_bEmbedded )
                        {
                            mfrUnique.m_xrefEmbedded = xref;
                        }
                        else
                        {
                            mfrUnique.m_xrefEmbedded = "";
                        }
                    }
                }
            }
        }