/// <summary>
        ///   Add a ZipEntry for which content is written directly by the application.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   When the application needs to write the zip entry data, use this
        ///   method to add the ZipEntry. For example, in the case that the
        ///   application wishes to write the XML representation of a DataSet into
        ///   a ZipEntry, the application can use this method to do so.
        /// </para>
        ///
        /// <para>
        ///   For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
        ///   cref="Password"/>, <see cref="SetCompression"/>, <see
        ///   cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
        ///   <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
        ///   respective values at the time of this call will be applied to the
        ///   <c>ZipEntry</c> added.
        /// </para>
        ///
        /// <para>
        ///   About progress events: When using the WriteDelegate, DotNetZip does
        ///   not issue any SaveProgress events with <c>EventType</c> = <see
        ///   cref="ZipProgressEventType.Saving_EntryBytesRead">
        ///   Saving_EntryBytesRead</see>. (This is because it is the
        ///   application's code that runs in WriteDelegate - there's no way for
        ///   DotNetZip to know when to issue a EntryBytesRead event.)
        ///   Applications that want to update a progress bar or similar status
        ///   indicator should do so from within the WriteDelegate
        ///   itself. DotNetZip will issue the other SaveProgress events,
        ///   including <see cref="ZipProgressEventType.Saving_Started">
        ///   Saving_Started</see>,
        ///   <see cref="ZipProgressEventType.Saving_BeforeWriteEntry">
        ///   Saving_BeforeWriteEntry</see>, and <see
        ///   cref="ZipProgressEventType.Saving_AfterWriteEntry">
        ///   Saving_AfterWriteEntry</see>.
        /// </para>
        ///
        /// <para>
        ///   Note: When you use PKZip encryption, it's normally necessary to
        ///   compute the CRC of the content to be encrypted, before compressing or
        ///   encrypting it. Therefore, when using PKZip encryption with a
        ///   WriteDelegate, the WriteDelegate CAN BE called twice: once to compute
        ///   the CRC, and the second time to potentially compress and
        ///   encrypt. Surprising, but true. This is because PKWARE specified that
        ///   the encryption initialization data depends on the CRC.
        ///   If this happens, for each call of the delegate, your
        ///   application must stream the same entry data in its entirety. If your
        ///   application writes different data during the second call, it will
        ///   result in a corrupt zip file.
        /// </para>
        ///
        /// <para>
        ///   The double-read behavior happens with all types of entries, not only
        ///   those that use WriteDelegate. It happens if you add an entry from a
        ///   filesystem file, or using a string, or a stream, or an opener/closer
        ///   pair. But in those cases, DotNetZip takes care of reading twice; in
        ///   the case of the WriteDelegate, the application code gets invoked
        ///   twice. Be aware.
        /// </para>
        ///
        /// <para>
        ///   As you can imagine, this can cause performance problems for large
        ///   streams, and it can lead to correctness problems when you use a
        ///   <c>WriteDelegate</c>. This is a pretty big pitfall.  There are two
        ///   ways to avoid it.  First, and most preferred: don't use PKZIP
        ///   encryption.  If you use the WinZip AES encryption, this problem
        ///   doesn't occur, because the encryption protocol doesn't require the CRC
        ///   up front. Second: if you do choose to use PKZIP encryption, write out
        ///   to a non-seekable stream (like standard output, or the
        ///   Response.OutputStream in an ASP.NET application).  In this case,
        ///   DotNetZip will use an alternative encryption protocol that does not
        ///   rely on the CRC of the content.  This also implies setting bit 3 in
        ///   the zip entry, which still presents problems for some zip tools.
        /// </para>
        ///
        /// <para>
        ///   In the future I may modify DotNetZip to *always* use bit 3 when PKZIP
        ///   encryption is in use.  This seems like a win overall, but there will
        ///   be some work involved.  If you feel strongly about it, visit the
        ///   DotNetZip forums and vote up <see
        ///   href="http://dotnetzip.codeplex.com/workitem/13686">the Workitem
        ///   tracking this issue</see>.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <param name="entryName">the name of the entry to add</param>
        /// <param name="writer">the delegate which will write the entry content</param>
        /// <returns>the ZipEntry added</returns>
        ///
        /// <example>
        ///
        ///   This example shows an application filling a DataSet, then saving the
        ///   contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an
        ///   anonymous delegate in C#. The DataSet XML is never saved to a disk file.
        ///
        /// <code lang="C#">
        /// var c1= new System.Data.SqlClient.SqlConnection(connstring1);
        /// var da = new System.Data.SqlClient.SqlDataAdapter()
        ///     {
        ///         SelectCommand=  new System.Data.SqlClient.SqlCommand(strSelect, c1)
        ///     };
        ///
        /// DataSet ds1 = new DataSet();
        /// da.Fill(ds1, "Invoices");
        ///
        /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
        /// {
        ///     zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) );
        ///     zip.Save(zipFileName);
        /// }
        /// </code>
        /// </example>
        ///
        /// <example>
        ///
        /// This example uses an anonymous method in C# as the WriteDelegate to provide
        /// the data for the ZipEntry. The example is a bit contrived - the
        /// <c>AddFile()</c> method is a simpler way to insert the contents of a file
        /// into an entry in a zip file. On the other hand, if there is some sort of
        /// processing or transformation of the file contents required before writing,
        /// the application could use the <c>WriteDelegate</c> to do it, in this way.
        ///
        /// <code lang="C#">
        /// using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ))
        /// {
        ///     using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
        ///     {
        ///         zip.AddEntry(zipEntryName, (name,output) =>
        ///             {
        ///                 byte[] buffer = new byte[BufferSize];
        ///                 int n;
        ///                 while ((n = input.Read(buffer, 0, buffer.Length)) != 0)
        ///                 {
        ///                     // could transform the data here...
        ///                     output.Write(buffer, 0, n);
        ///                     // could update a progress bar here
        ///                 }
        ///             });
        ///
        ///         zip.Save(zipFileName);
        ///     }
        /// }
        /// </code>
        /// </example>
        ///
        /// <example>
        ///
        /// This example uses a named delegate in VB to write data for the given
        /// ZipEntry (VB9 does not have anonymous delegates). The example here is a bit
        /// contrived - a simpler way to add the contents of a file to a ZipEntry is to
        /// simply use the appropriate <c>AddFile()</c> method.  The key scenario for
        /// which the <c>WriteDelegate</c> makes sense is saving a DataSet, in XML
        /// format, to the zip file. The DataSet can write XML to a stream, and the
        /// WriteDelegate is the perfect place to write into the zip file.  There may be
        /// other data structures that can write to a stream, but cannot be read as a
        /// stream.  The <c>WriteDelegate</c> would be appropriate for those cases as
        /// well.
        ///
        /// <code lang="VB">
        /// Private Sub WriteEntry (ByVal name As String, ByVal output As Stream)
        ///     Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
        ///         Dim n As Integer = -1
        ///         Dim buffer As Byte() = New Byte(BufferSize){}
        ///         Do While n &lt;&gt; 0
        ///             n = input.Read(buffer, 0, buffer.Length)
        ///             output.Write(buffer, 0, n)
        ///         Loop
        ///     End Using
        /// End Sub
        ///
        /// Public Sub Run()
        ///     Using zip = New ZipFile
        ///         zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry))
        ///         zip.Save(zipFileName)
        ///     End Using
        /// End Sub
        /// </code>
        /// </example>
        public ZipEntry AddEntry(string entryName, WriteDelegate writer)
        {
            ZipEntry ze = ZipEntry.CreateForWriter(entryName, writer);

            if (Verbose)
            {
                StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
            }
            return(_InternalAddEntry(ze));
        }