Teach modify the new "add_from_zip" command and retire standalone tool.
Adapt tests.
diff --git a/.hgignore b/.hgignore
index 08e4a0f..2e62857 100644
--- a/.hgignore
+++ b/.hgignore
@@ -19,9 +19,6 @@
 ^man/.*\.html$
 ^regress/add_from_buffer$
 ^regress/add_from_filep$
-^regress/add_from_zip$
-^regress/cp437$
-^regress/encoding$
 ^regress/fopen_unchanged$
 ^regress/fread$
 ^regress/modify$
diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt
index c71ec18..a07d7a2 100644
--- a/regress/CMakeLists.txt
+++ b/regress/CMakeLists.txt
@@ -3,7 +3,6 @@
 SET(STANDALONE_TEST_PROGRAMS
   add_from_buffer
   add_from_filep
-  add_from_zip
   fopen_unchanged
   fread
   name_locate
diff --git a/regress/Makefile.am b/regress/Makefile.am
index 9b29657..71df741 100644
--- a/regress/Makefile.am
+++ b/regress/Makefile.am
@@ -1,7 +1,6 @@
 noinst_PROGRAMS= \
 	add_from_buffer \
 	add_from_filep \
-	add_from_zip \
 	fopen_unchanged \
 	fread \
 	modify \
diff --git a/regress/add_from_zip.c b/regress/add_from_zip.c
deleted file mode 100644
index bdea8c5..0000000
--- a/regress/add_from_zip.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-  add_from_zip.c -- test case for adding file from archive to archive
-  Copyright (C) 2010 Dieter Baron and Thomas Klausner
-
-  This file is part of libzip, a library to manipulate ZIP archives.
-  The authors can be contacted at <libzip@nih.at>
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-  2. Redistributions in binary form must reproduce the above copyright
-     notice, this list of conditions and the following disclaimer in
-     the documentation and/or other materials provided with the
-     distribution.
-  3. The names of the authors may not be used to endorse or promote
-     products derived from this software without specific prior
-     written permission.
- 
-  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "zip.h"
-
-static const char *prg;
-
-int
-main(int argc, char *argv[])
-{
-    const char *source;
-    const char *archive;
-    const char *file;
-    int file_idx;
-    struct zip *z_in;
-    struct zip *z_out;
-    struct zip_source *zs;
-    char buf[100];
-    int err;
-
-    prg = argv[0];
-
-    if (argc != 4) {
-	fprintf(stderr, "usage: %s source-archive target-archive file\n", prg);
-	return 1;
-    }
-
-    source = argv[1];
-    archive = argv[2];
-    file = argv[3];
-
-    if ((z_in=zip_open(source, ZIP_CHECKCONS, &err)) == NULL) {
-	zip_error_to_str(buf, sizeof(buf), err, errno);
-	fprintf(stderr, "%s: can't open source zip archive `%s': %s\n", prg,
-		source, buf);
-	return 1;
-    }
-
-    if ((file_idx=zip_name_locate(z_in, file, 0)) == -1) {
-	zip_error_to_str(buf, sizeof(buf), err, errno);
-	fprintf(stderr, "%s: can't find file `%s' in source zip archive %s: %s\n",
-		prg, file, source, buf);
-	return 1;
-    }
-
-    if ((z_out=zip_open(archive, ZIP_CREATE, &err)) == NULL) {
-	zip_error_to_str(buf, sizeof(buf), err, errno);
-	fprintf(stderr, "%s: can't open target zip archive %s: %s\n", prg,
-		archive, buf);
-	return 1;
-    }
-
-    if ((zs=zip_source_zip(z_out, z_in, file_idx, 0, 0, -1)) == NULL) {
-	fprintf(stderr, "%s: error creating file source for `%s': %s\n", prg,
-		file, zip_strerror(z_out));
-	return 1;
-    }
-
-    if (zip_add(z_out, file, zs) == -1) {
-	zip_source_free(zs);
-	fprintf(stderr, "%s: can't add file `%s': %s\n", prg,
-		file, zip_strerror(z_out));
-	return 1;
-    }
-
-    if (zip_close(z_out) == -1) {
-	fprintf(stderr, "%s: can't close zip archive `%s': %s\n", prg,
-		archive, zip_strerror(z_out));
-	return 1;
-    }
-
-    return 0;
-}
diff --git a/regress/add_from_zip_deflated.test b/regress/add_from_zip_deflated.test
index 0e1a24a..240c66c 100644
--- a/regress/add_from_zip_deflated.test
+++ b/regress/add_from_zip_deflated.test
@@ -1,6 +1,6 @@
 # add deflated file from zip to zip
-program add_from_zip
+program modify
 return 0
-args testdeflated.zzip testfile.zip abac-repeat.txt
+args testfile.zip   add_from_zip abac-repeat.txt testdeflated.zzip 0 0 -1
 file testdeflated.zzip testdeflated.zip testdeflated.zip
 file-new testfile.zip testdeflated.zip
diff --git a/regress/add_from_zip_stored.test b/regress/add_from_zip_stored.test
index c327b33..1d687ee 100644
--- a/regress/add_from_zip_stored.test
+++ b/regress/add_from_zip_stored.test
@@ -1,6 +1,6 @@
 # add stored file from zip to zip
-program add_from_zip
+program modify
 return 0
-args teststored.zzip testfile.zip abac-repeat.txt
+args testfile.zip   add_from_zip abac-repeat.txt teststored.zzip 0 0 -1
 file teststored.zzip teststored.zip teststored.zip
 file-new testfile.zip teststored.zip
diff --git a/regress/modify.c b/regress/modify.c
index 7549f4a..cc972c4 100644
--- a/regress/modify.c
+++ b/regress/modify.c
@@ -51,6 +51,7 @@
     "\tadd name content\n"
     "\tadd_dir name\n"
     "\tadd_file name filename offset len\n"
+    "\tadd_from_zip name archivename index offset len\n"
     "\tdelete index\n"
     "\tget_archive_comment\n"
     "\tget_file_comment index\n"
@@ -62,7 +63,7 @@
 main(int argc, char *argv[])
 {
     const char *archive;
-    struct zip *za;
+    struct zip *za, *z_in;
     struct zip_source *zs;
     char buf[100], c;
     int arg, err, flags, idx;
@@ -147,6 +148,30 @@
 		break;
 	    }
 	    arg += 5;
+	} else if (strcmp(argv[arg], "add_from_zip") == 0 && arg+5 < argc) {
+	    /* add from another zip file */
+	    int idx;
+	    idx = atoi(argv[arg+3]);
+	    if ((z_in=zip_open(argv[arg+2], ZIP_CHECKCONS, &err)) == NULL) {
+		zip_error_to_str(buf, sizeof(buf), err, errno);
+		fprintf(stderr, "can't open source zip archive `%s': %s\n", argv[arg+2], buf);
+		err = 1;
+		break;
+	    }
+	    if ((zs=zip_source_zip(za, z_in, idx, 0, atoi(argv[arg+4]), atoi(argv[arg+5]))) == NULL) {
+		fprintf(stderr, "error creating file source from `%s' index '%d': %s\n", argv[arg+2], idx, zip_strerror(za));
+		zip_close(z_in);
+		err = 1;
+		break;
+	    }
+	    if (zip_add(za, argv[arg+1], zs) == -1) {
+		fprintf(stderr, "can't add file `%s': %s\n", argv[arg+1], zip_strerror(za));
+		zip_source_free(zs);
+		zip_close(z_in);
+		err = 1;
+		break;
+	    }
+	    arg += 6;
 	} else if (strcmp(argv[arg], "delete") == 0 && arg+1 < argc) {
 	    /* delete */
 	    idx = atoi(argv[arg+1]);