Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 djvulibre (3.5.27.1-6) unstable; urgency=medium
 .
   * track upstream fixes and updates, including to djvudigital
   * bump standards version
   * enable hardening
Author: Barak A. Pearlmutter <bap@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- djvulibre-3.5.27.1.orig/COPYING
+++ djvulibre-3.5.27.1/COPYING
@@ -1,12 +1,12 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
+                            Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is f
 General Public License applies to most of the Free Software
 Foundation's software and to any other program whose authors commit to
 using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
+the GNU Lesser General Public License instead.)  You can apply it to
 your programs, too.
 
   When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's f
 
   The precise terms and conditions for copying, distribution and
 modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
+
+                    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all o
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
-
+
 These requirements apply to the modified work as a whole.  If
 identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place,
 access to copy the source code from the same place counts as
 distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-
+
   4. You may not copy, modify, sublicense, or distribute the Program
 except as expressly provided under this License.  Any attempt
 otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-
+
   8. If the distribution and/or use of the Program is restricted in
 certain countries either by patents or by copyrighted interfaces, the
 original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this.  Our decision
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-			    NO WARRANTY
+                            NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and ea
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
+    Copyright (C) <year>  <name of author>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to wh
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@ necessary.  Here is a sample; alter the
 This General Public License does not permit incorporating your program into
 proprietary programs.  If your program is a subroutine library, you may
 consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
+library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.
--- djvulibre-3.5.27.1.orig/NEWS
+++ djvulibre-3.5.27.1/NEWS
@@ -3,6 +3,12 @@ NEW IN VERSION 3.5.27
 - simplified configuration scripts
 - deadlock fixes
 - miniexp under win32 uses tlsalloc instead of _thread vars (pb under xp)
+- djvudigital can extract text and metadata using pdftotext.
+- duplicate page titles are accepted
+- bug fixes: overflow in bitmap/pixmap/iw44image sizes
+- big fixes: handling INCL chunks in djvumake
+- bug fixes: better support for large files (2gb) 
+
 
 NEW IN VERSION 3.5.26
 ------------------------
--- djvulibre-3.5.27.1.orig/config/acinclude.m4
+++ djvulibre-3.5.27.1/config/acinclude.m4
@@ -16,8 +16,7 @@ dnl MERCHANTABILITY or FITNESS FOR A PAR
 dnl GNU General Public License for more details.
 dnl
 dnl You should have received a copy of the GNU General Public License
-dnl along with this program; if not, write to the Free Software
-dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111 USA
+dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.
 dnl
 
 dnl -------------------------------------------------------
--- djvulibre-3.5.27.1.orig/config/pkg.m4
+++ djvulibre-3.5.27.1/config/pkg.m4
@@ -14,8 +14,7 @@
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
--- djvulibre-3.5.27.1.orig/configure.ac
+++ djvulibre-3.5.27.1/configure.ac
@@ -41,7 +41,7 @@ AC_CONFIG_SRCDIR(libdjvu/ddjvuapi.cpp)
 AC_CONFIG_HEADER(config.h:config/config.h.in)
 AC_CANONICAL_HOST
 
-AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz])
+AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz -Wall])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 
--- djvulibre-3.5.27.1.orig/desktopfiles/Makefile.am
+++ djvulibre-3.5.27.1/desktopfiles/Makefile.am
@@ -61,7 +61,7 @@ else
 endif
 
 svg_process =\
-cat $< | gzip >$@
+cat $< | gzip -n >$@
 
 svg_verbose = $(svg_verbose_@AM_V@)
 svg_verbose_ = $(svg_verbose_@AM_DEFAULT_V@)
--- djvulibre-3.5.27.1.orig/doc/djvuchanges.txt
+++ djvulibre-3.5.27.1/doc/djvuchanges.txt
@@ -39,6 +39,15 @@ To maximize compatibility with earlier v
 values different from {1,6,2,5} should be ignored
 and interpreted as 1 : rightside up orientation.
 
+1.4- ORDERING OF THE DJBZ AND SJBZ CHUNK
+
+Although the specification does not make it clear, when a FORM:DJVU chunk
+contains a bitonal image represented by a Sjbz chunk that uses a shape
+dictionary represented by a Djbz chunk, the Djbz chunk must appear before the
+Sjbz chunk that references it.  This also holds when the chunks is accessed
+indirectly via INCL chunks. For instance, an INCL chunk that refers to a
+shared Djbz shape dictionary must be placed before the corresponding Sjbz
+chunk.
 
 
 2- ESCAPE SEQUENCES IN ANNOTATION CHUNK STRINGS.
@@ -130,7 +139,7 @@ DjVuLibre has introduced metadata annota
 Metadata entries for each page are represent by key/value pairs
 located in a metadata directive in the annotation chunk.
 Metadata entries for the document are represented similarly
-using the methods described in the next section.
+using the methods described in the section 4.3.
 
 The metadata directive has the form
 
--- djvulibre-3.5.27.1.orig/doc/minilisp/minilisp.cpp
+++ djvulibre-3.5.27.1/doc/minilisp/minilisp.cpp
@@ -675,10 +675,12 @@ DEFUN("/",div,1,9999) {
   while (i<argc && miniexp_doublep(argv[i]) && miniexp_to_double(argv[i]))
     s /= miniexp_to_double(argv[i++]);
   if (i < argc)
-    if (miniexp_doublep(argv[i]))
-      error("/: division by zero", argv[i]);
-    else
-      error("/: number expected", argv[i]);
+    {
+      if (miniexp_doublep(argv[i]))
+        error("/: division by zero", argv[i]);
+      else
+        error("/: number expected", argv[i]);
+    }
   return miniexp_double(s);
 }
 
@@ -690,14 +692,25 @@ static bool
 equal(miniexp_t a, miniexp_t b)
 {
   if (a == b)
-    return true;
+    {
+      return true;
+    }
   else if (miniexp_consp(a) && miniexp_consp(b))
-    return equal(miniexp_car(a),miniexp_car(b))
-      &&   equal(miniexp_cdr(a),miniexp_cdr(b));
-  else if (miniexp_stringp(a) && miniexp_stringp(b))
-    return !strcmp(miniexp_to_str(a), miniexp_to_str(b));
+    {
+      return equal(miniexp_car(a),miniexp_car(b))
+        && equal(miniexp_cdr(a),miniexp_cdr(b));
+    }
   else if (miniexp_doublep(a) && miniexp_doublep(b))
-    return miniexp_to_double(a) == miniexp_to_double(b);
+    {
+      return miniexp_to_double(a) == miniexp_to_double(b);
+    }
+  else if (miniexp_stringp(a) && miniexp_stringp(b)) 
+    {
+      const char *sa, *sb;
+      int la = miniexp_to_lstr(a, &sa);
+      int lb = miniexp_to_lstr(b, &sb);
+      return (la == lb) && ! memcmp(sa, sb, la);
+    } 
   return false;
 }
 
@@ -716,17 +729,17 @@ compare(miniexp_t a, miniexp_t b)
     {
       double na = miniexp_to_double(a);
       double nb = miniexp_to_double(b);
-      if (na < nb)
-	return -1;
-      else if (na > nb)
-	return 1;
-      return 0;
+      return (na < nb) ? -1 : (na > nb) ? +1 : 0;
     }
   else if (miniexp_stringp(a) && miniexp_stringp(b))
     {
-      const char *sa = miniexp_to_str(a);
-      const char *sb = miniexp_to_str(b);
-      return strcmp(sa, sb);
+      const char *sa, *sb;
+      int la = miniexp_to_lstr(a, &sa);
+      int lb = miniexp_to_lstr(b, &sb);
+      int r = memcmp(sa, sb, (la < lb) ? la : lb);
+      if (r == 0) 
+        return (la < lb) ? -1 : (la > lb) ? +1 : 0;
+      return r;
     }
   else
     error("compare: cannot rank these arguments");
@@ -763,15 +776,14 @@ DEFUN("ceil",ceil,1,0) {
 DEFUN("strlen",strlen,1,1) {
   if (! miniexp_stringp(argv[0]))
     error("strlen: string expected", argv[0]);
-  const char *s = miniexp_to_str(argv[0]);
-  return miniexp_number(strlen(s));
+  return miniexp_number(miniexp_to_lstr(argv[0], 0));
 }
 
 DEFUN("substr",substr,2,1) {
   if (! miniexp_stringp(argv[0]))
     error("substr: string expected", argv[0]);
-  const char *s = miniexp_to_str(argv[0]);
-  int l = strlen(s);
+  const char *s;
+  int l = miniexp_to_lstr(argv[0], &s);
   if (! miniexp_numberp(argv[1]))
     error("substr: integer number expected", argv[1]);
   int f = miniexp_to_double(argv[1]);
@@ -785,7 +797,7 @@ DEFUN("substr",substr,2,1) {
       f = miniexp_to_double(argv[2]);
       l = (f > l) ? l : (f < 0) ? 0 : f;
     }
-  return miniexp_substring(s,l);
+  return miniexp_lstring(l,s);
 }
 
 DEFUN("concat",concat,0,9999) {
--- djvulibre-3.5.27.1.orig/libdjvu/DjVmDir.cpp
+++ djvulibre-3.5.27.1/libdjvu/DjVmDir.cpp
@@ -223,7 +223,6 @@ DjVmDir::decode(const GP<ByteStream> &gs
    page2file.resize(-1);
    name2file.empty();
    id2file.empty();
-   title2file.empty();
 
    int ver=str.read8();
    bool bundled=(ver & 0x80)!=0;
@@ -375,18 +374,6 @@ DjVmDir::decode(const GP<ByteStream> &gs
 	          G_THROW( ERR_MSG("DjVmDir.dupl_id") "\t" + file->id);
 	       id2file[file->id]=file;
       }
-
-         // Generate title2file map
-      for(pos=files_list;pos;++pos)
-      {
-	       GP<File> file=files_list[pos];
-	       if (file->title.length())
-	       {
-	          if (title2file.contains(file->title))
-	             G_THROW( ERR_MSG("DjVmDir.dupl_title") "\t" + file->title);
-	          title2file[file->title]=file;
-	       }
-      }
    }
 }
 
@@ -556,11 +543,19 @@ DjVmDir::id_to_file(const GUTF8String &i
 }
 
 GP<DjVmDir::File>
-DjVmDir::title_to_file(const GUTF8String &title) const
+DjVmDir::title_to_file(const GUTF8String &title, GPosition spos) const
 {
-   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
-   GPosition pos;
-   return (title2file.contains(title, pos))?title2file[pos]:(GP<DjVmDir::File>(0));
+  if (! title)
+    return 0;
+  GCriticalSectionLock lock((GCriticalSection *) &class_lock);
+  if (! spos)
+    for (GPosition pos = spos; pos; ++pos)
+      if (files_list[pos]->is_page() && files_list[pos]->title == title)
+        return files_list[pos];
+  for (GPosition pos = files_list; pos; ++pos)
+    if (files_list[pos]->is_page() && files_list[pos]->title == title)
+      return files_list[pos];
+  return 0;
 }
 
 GP<DjVmDir::File>
@@ -661,14 +656,7 @@ DjVmDir::insert_file(const GP<File> & fi
      G_THROW( ERR_MSG("DjVmDir.dupl_name2") "\t" + file->name);
    name2file[file->name]=file;
    id2file[file->id]=file;
-   if (file->title.length())
-     {
-       if (title2file.contains(file->title))  
-         // duplicate titles may become ok some day
-         G_THROW( ERR_MSG("DjVmDir.dupl_title2") "\t" + file->title);
-       title2file[file->title]=file;
-     }
-
+   
       // Make sure that there is no more than one file with shared annotations
    if (file->is_shared_anno())
    {
@@ -727,7 +715,6 @@ DjVmDir::delete_file(const GUTF8String &
       {
          name2file.del(f->name);
          id2file.del(f->id);
-         title2file.del(f->title);
          if (f->is_page())
          {
             for(int page=0;page<page2file.size();page++)
@@ -788,9 +775,7 @@ DjVmDir::set_file_title(const GUTF8Strin
    if (!id2file.contains(id, pos))
       G_THROW( ERR_MSG("DjVmDir.no_info") "\t" + GUTF8String(id));
    GP<File> file=id2file[pos];
-   title2file.del(file->title);
    file->title=title;
-   title2file[title]=file;
 }
 
 GPList<DjVmDir::File>
--- djvulibre-3.5.27.1.orig/libdjvu/DjVmDir.h
+++ djvulibre-3.5.27.1/libdjvu/DjVmDir.h
@@ -181,7 +181,8 @@ public:
       /** Translates file IDs to file records. */
    GP<File> id_to_file(const GUTF8String &id) const;
       /** Translates file shortcuts to file records. */
-   GP<File> title_to_file(const GUTF8String &title) const;
+   GP<File> title_to_file(const GUTF8String &title, GPosition spos) const;
+   GP<File> title_to_file(const GUTF8String &title) const; 
       /** Access file record by position. */
    GP<File> pos_to_file(int fileno, int *ppageno=0) const;
       /** Returns position of the file in the directory. */
@@ -216,7 +217,6 @@ private:
    GPArray<File> page2file;
    GPMap<GUTF8String, File> name2file;
    GPMap<GUTF8String, File> id2file;
-   GPMap<GUTF8String, File> title2file;
 private: //dummy stuff
    static void decode(ByteStream *);
    static void encode(ByteStream *);
@@ -440,6 +440,13 @@ DjVmDir::is_indirect(void) const
            files_list[files_list]->offset==0 );
 }
 
+inline GP<DjVmDir::File> 
+DjVmDir::title_to_file(const GUTF8String &title) const
+{
+  GPosition pos;
+  return title_to_file(title, pos);
+}
+
 
 
 // ----- THE END
--- djvulibre-3.5.27.1.orig/libdjvu/DjVuDocument.cpp
+++ djvulibre-3.5.27.1/libdjvu/DjVuDocument.cpp
@@ -805,11 +805,9 @@ DjVuDocument::id_to_url(const GUTF8Strin
 	    {
 	      GP<DjVmDir::File> file=djvm_dir->id_to_file(id);
 	      if (!file)
-              {
                 file=djvm_dir->name_to_file(id);
-	        if (!file)
-                  file=djvm_dir->title_to_file(id);
-              }
+	      if (!file)
+                file=djvm_dir->title_to_file(id);
 	      if (file)
 	        return GURL::UTF8(file->get_load_name(),init_url);
 	    }
@@ -819,11 +817,9 @@ DjVuDocument::id_to_url(const GUTF8Strin
 	    {
 	       GP<DjVmDir::File> file=djvm_dir->id_to_file(id);
 	       if (!file)
-               {
                  file=djvm_dir->name_to_file(id);
-	         if (!file)
-                   file=djvm_dir->title_to_file(id);
-               }
+	      if (!file)
+                file=djvm_dir->title_to_file(id);
 	       if (file)
 	         return GURL::UTF8(file->get_load_name(),init_url.base());
 	    }
@@ -838,7 +834,12 @@ DjVuDocument::id_to_url(const GUTF8Strin
 	    break;
 	 case OLD_INDEXED:
 	 case SINGLE_PAGE:
-	    return GURL::UTF8(id,init_url.base());
+	    {
+	       GURL url = GURL::UTF8(id,init_url.base());
+	       if (url.fname() == "-")
+	          G_THROW("Illegal include chunk (corrupted file?)");
+	       return url;
+	    }
 	    break;
       }
    return GURL();
--- djvulibre-3.5.27.1.orig/libdjvu/DjVuDocument.h
+++ djvulibre-3.5.27.1/libdjvu/DjVuDocument.h
@@ -524,7 +524,6 @@ public:
 		   \begin{enumerate}
 		      \item File ID from the \Ref{DjVmDir}
 		      \item File name from the \Ref{DjVmDir}
-		      \item File title from the \Ref{DjVmDir}
 		   \end{enumerate}
 		   Then for #BUNDLED# document the URL is obtained by
 		   appending the #name# of the found file to the document's
--- djvulibre-3.5.27.1.orig/libdjvu/DjVuMessageLite.h
+++ djvulibre-3.5.27.1/libdjvu/DjVuMessageLite.h
@@ -89,8 +89,8 @@ class ByteStream;
     separator ::= newline |
                   newline | separator
     
-    single_message ::= message_ID |
-                       message_ID parameters
+    single_message ::= CTRLC message_ID |
+                       CTRLC message_ID parameters
     
     parameters ::= tab string |
                    tab string parameters
--- djvulibre-3.5.27.1.orig/libdjvu/GContainer.h
+++ djvulibre-3.5.27.1/libdjvu/GContainer.h
@@ -848,7 +848,7 @@ GListImpl<TI>::newnode(const TI &elt)
 {
   LNode  *n = (LNode *) operator new (sizeof(LNode ));
 #if GCONTAINER_ZERO_FILL
-  memset(n, 0, sizeof(LNode ));
+  memset((void*)n, 0, sizeof(LNode ));
 #endif
   new ((void*)&(n->val)) TI(elt);
   return (Node*) n;
--- djvulibre-3.5.27.1.orig/libdjvu/GOS.cpp
+++ djvulibre-3.5.27.1/libdjvu/GOS.cpp
@@ -154,13 +154,6 @@ strerror(int errno)
 #endif
 
 
-static const char slash='/';
-static const char percent='%';
-static const char backslash='\\';
-static const char colon=':';
-static const char dot='.';
-static const char nillchar=0;
-
 
 // -----------------------------------------
 // Functions for dealing with filenames
@@ -193,18 +186,18 @@ GOS::basename(const GUTF8String &gfname,
   const char *fname=gfname;
 #if defined(_WIN32) || defined(OS2)
   // Special cases
-  if (fname[1] == colon)
+  if (fname[1] == ':')
   {
     if(!fname[2])
     {
       return gfname;
     }
-    if (!fname[3] && (fname[2]== slash || fname[2]== backslash))
+    if (!fname[3] && (fname[2]== '/' || fname[2]== '\\'))
     {
       char string_buffer[4];
       string_buffer[0] = fname[0];
-      string_buffer[1] = colon;
-      string_buffer[2] = backslash; 
+      string_buffer[1] = ':';
+      string_buffer[2] = '\\';
       string_buffer[3] = 0; 
       return string_buffer;
     }
@@ -219,7 +212,7 @@ GOS::basename(const GUTF8String &gfname,
   // Process suffix
   if (suffix)
   {
-    if (suffix[0]== dot )
+    if (suffix[0]== '.' )
       suffix ++;
     if (suffix[0])
     {
@@ -229,7 +222,7 @@ GOS::basename(const GUTF8String &gfname,
       if (s > fname + sl)
       {
         s = s - (sl + 1);
-        if(*s == dot && (GUTF8String(s+1).downcase() == gsuffix.downcase()))
+        if(*s == '.' && (GUTF8String(s+1).downcase() == gsuffix.downcase()))
         {
           retval.setat((int)((size_t)s-(size_t)fname),0);
         }
@@ -335,7 +328,7 @@ GOS::cwd(const GUTF8String &dirname)
   char drv[2];
   if (dirname.length() && _chdir(dirname.getUTF82Native())==-1)//MBCS cvt
     G_THROW(errmsg());
-  drv[0]= dot ; drv[1]=0;
+  drv[0]= '.' ; drv[1]=0;
   char *string_buffer;
   GPBuffer<char> gstring_buffer(string_buffer,MAXPATHLEN+1);
   char *result = getcwd(string_buffer,MAXPATHLEN);
--- djvulibre-3.5.27.1.orig/libdjvu/GString.cpp
+++ djvulibre-3.5.27.1/libdjvu/GString.cpp
@@ -273,7 +273,9 @@ public:
   ~ChangeLocale();
 private:
   GUTF8String locale;
+#if DO_CHANGELOCALE
   int category;
+#endif
 };
 
 class GStringRep::Native : public GStringRep
@@ -452,7 +454,9 @@ GStringRep::Native::ncopy(
 }
 
 GStringRep::ChangeLocale::ChangeLocale(const int xcategory, const char xlocale[] )
+#if DO_CHANGELOCALE
   : category(xcategory)
+#endif
 {
 #if DO_CHANGELOCALE
   // This is disabled under UNIX because 
--- djvulibre-3.5.27.1.orig/libdjvu/GURL.cpp
+++ djvulibre-3.5.27.1/libdjvu/GURL.cpp
@@ -170,7 +170,6 @@ namespace DJVU {
 
 static const char djvuopts[]="DJVUOPTS";
 static const char localhost[]="file://localhost/";
-static const char backslash='\\';  
 static const char colon=':';
 static const char dot='.';
 static const char filespecslashes[] = "file://";
@@ -179,13 +178,14 @@ static const char slash='/';
 static const char percent='%';
 static const char localhostspec1[] = "//localhost/";
 static const char localhostspec2[] = "///";
-static const char nillchar=0;
 #if defined(UNIX)
   static const char tilde='~';
   static const char root[] = "/";
 #elif defined(_WIN32) || defined(OS2)
   static const char root[] = "\\";
+  static const char backslash='\\';  
 #elif defined(macintosh)
+  static const char nillchar=0;
   static char const * const root = &nillchar; 
 #else
 #error "Define something here for your operating system"
--- djvulibre-3.5.27.1.orig/libdjvu/IW44EncodeCodec.cpp
+++ djvulibre-3.5.27.1/libdjvu/IW44EncodeCodec.cpp
@@ -125,7 +125,7 @@ static const float iw_norm[16] = {
 };
 
 static const int iw_shift  = 6;
-static const int iw_round  = (1<<(iw_shift-1));
+// static const int iw_round  = (1<<(iw_shift-1));
 
 static const struct { int start; int size; }  
 bandbuckets[] = 
--- djvulibre-3.5.27.1.orig/libdjvu/IW44Image.cpp
+++ djvulibre-3.5.27.1/libdjvu/IW44Image.cpp
@@ -125,15 +125,6 @@ static const int iw_quant[16] = {
   0x040000, 0x040000, 0x080000
 };
 
-static const float iw_norm[16] = {
-  2.627989e+03F,
-  1.832893e+02F, 1.832959e+02F, 5.114690e+01F,
-  4.583344e+01F, 4.583462e+01F, 1.279225e+01F,
-  1.149671e+01F, 1.149712e+01F, 3.218888e+00F,
-  2.999281e+00F, 2.999476e+00F, 8.733161e-01F,
-  1.074451e+00F, 1.074511e+00F, 4.289318e-01F
-};
-
 static const int iw_border = 3;
 static const int iw_shift  = 6;
 static const int iw_round  = (1<<(iw_shift-1));
@@ -604,7 +595,7 @@ IW44Image::Map::Map(int w, int h)
 {
   bw = (w+0x20-1) & ~0x1f;
   bh = (h+0x20-1) & ~0x1f;
-  nb = (bw * bh) / (32 * 32);
+  nb = (unsigned int)(bw*bh) / (32 * 32);
   blocks = new IW44Image::Block[nb];
   top = IWALLOCSIZE;
 }
--- djvulibre-3.5.27.1.orig/libdjvu/ddjvuapi.cpp
+++ djvulibre-3.5.27.1/libdjvu/ddjvuapi.cpp
@@ -1578,6 +1578,12 @@ ddjvu_page_create(ddjvu_document_t *docu
         p->img = doc->get_page(GNativeString(pageid), false, job);
       else
         p->img = doc->get_page(pageno, false, job);
+      // synthetize msgs for pages found in the cache
+      ddjvu_status_t status = p->status();
+      if (status == DDJVU_JOB_OK)
+        p->notify_redisplay(p->img);
+      if (status >= DDJVU_JOB_OK)
+        p->notify_file_flags_changed(p->img->get_djvu_file(), 0, 0);
     }
   G_CATCH(ex)
     {
--- djvulibre-3.5.27.1.orig/libdjvu/ddjvuapi.h
+++ djvulibre-3.5.27.1/libdjvu/ddjvuapi.h
@@ -111,6 +111,9 @@ extern "C" {
 
    Version   Change
    -----------------------------
+     24    Added:
+              miniexp_lstring()
+              miniexp_to_lstr()
      23    Added:
               miniexp_mutate()
      22    Changed
--- djvulibre-3.5.27.1.orig/libdjvu/miniexp.cpp
+++ djvulibre-3.5.27.1/libdjvu/miniexp.cpp
@@ -3,8 +3,8 @@
 // MiniExp - Library for handling lisp expressions
 // Copyright (c) 2005  Leon Bottou
 //
-// This software is subject to, and may be distributed under, the
-// GNU General Public License, either version 2 of the license
+// This software is subject to, and may be distributed under, the GNU
+// Lesser General Public License, either Version 2.1 of the license,
 // or (at your option) any later version. The license should have
 // accompanied the software or you may obtain a copy of the license
 // from the Free Software Foundation at http://www.fsf.org .
@@ -899,6 +899,18 @@ miniobj_t::pname() const
   return res;
 }
 
+bool
+miniobj_t::stringp(const char* &, size_t &) const
+{
+  return false;
+}
+
+bool
+miniobj_t::doublep(double&) const
+{
+  return false;
+}
+
 miniexp_t 
 miniexp_object(miniobj_t *obj)
 {
@@ -939,12 +951,13 @@ class ministring_t : public miniobj_t
   MINIOBJ_DECLARE(ministring_t,miniobj_t,"string");
 public:
   ~ministring_t();
-  ministring_t(const char *s);
-  ministring_t(char *s, bool steal);
+  ministring_t(size_t len, const char *s);
+  ministring_t(size_t len, char *s, bool steal);
   operator const char*() const { return s; }
-  virtual char *pname() const;
+  virtual bool stringp(const char* &s, size_t &l) const;
 private:
   char *s;
+  size_t l;
 private:
   ministring_t(const ministring_t &);
   ministring_t& operator=(const ministring_t &);
@@ -957,18 +970,29 @@ ministring_t::~ministring_t()
   delete [] s;
 }
 
-ministring_t::ministring_t(const char *str) 
-  : s(new char[strlen(str)+1])
+ministring_t::ministring_t(size_t len, const char *str)
+  : s(0), l(len)
 {
-  strcpy(s,str);
+  s = new char[l+1];
+  memcpy(s, str, l);
+  s[l] = 0;
 }
 
-ministring_t::ministring_t(char *str, bool steal) 
-  : s(str)
+ministring_t::ministring_t(size_t len, char *str, bool steal)
+  : s(str), l(len)
 {
   ASSERT(steal);
 }
 
+bool
+ministring_t::stringp(const char* &rs, size_t &rl) const
+{
+  rs = s;
+  rl = l;
+  return true;
+}
+
+
 END_ANONYMOUS_NAMESPACE
 
 static bool
@@ -1019,13 +1043,14 @@ char_out(int c, char* &d, int &n)
 }
 
 static int
-print_c_string(const char *s, char *d, int flags = 0)
+print_c_string(const char *s, char *d, int flags, size_t len)
 {
   int c;
   int n = 0;
   char_out('\"', d, n);
-  while ((c = (unsigned char)(*s++)))
+  while (len-- > 0) 
     {
+      c = (unsigned char)(*s++);
       if (char_quoted(c, flags))
         {
           char buffer[10];
@@ -1049,6 +1074,9 @@ print_c_string(const char *s, char *d, i
                         0xd800+(((c-0x10000)>>10)&0x3ff), 
                         0xdc00+(c&0x3ff));
             }
+          if (buffer[0] == 0 && c == 0)
+            if (*s < '0' || *s > '7')
+              buffer[0] = '0';
           if (buffer[0] == 0)
             sprintf(buffer, "%03o", c);
           for (int i=0; buffer[i]; i++)
@@ -1062,68 +1090,74 @@ print_c_string(const char *s, char *d, i
   return n;
 }
 
-char *
-ministring_t::pname() const
-{
-  int n = print_c_string(s, 0);
-  char *d = new char[n];
-  if (d) print_c_string(s, d);
-  return d;
-}
-
 int 
 miniexp_stringp(miniexp_t p)
 {
-  return miniexp_isa(p, ministring_t::classname) ? 1 : 0;
+  const char *s; size_t l;
+  if (miniexp_objectp(p) && miniexp_to_obj(p)->stringp(s,l))
+    return 1;
+  return 0;
 }
 
 const char *
 miniexp_to_str(miniexp_t p)
 {
-  miniobj_t *obj = miniexp_to_obj(p);
-  if (miniexp_stringp(p))
-    return (const char*) * (ministring_t*) obj;
-  return 0;
+  const char *s = 0;
+  size_t l = miniexp_to_lstr(p, &s);
+  return s;
 }
 
-miniexp_t 
+size_t
+miniexp_to_lstr(miniexp_t p, const char **sp)
+{
+  const char *s = 0;
+  size_t l = 0;
+  if (miniexp_objectp(p))
+    miniexp_to_obj(p)->stringp(s,l);
+  if (sp)
+    *sp = s;
+  return l;
+}
+
+miniexp_t
 miniexp_string(const char *s)
 {
-  ministring_t *obj = new ministring_t(s);
-  return miniexp_object(obj);
+  return miniexp_lstring(strlen(s), s);
 }
 
 miniexp_t 
-miniexp_substring(const char *s, int n)
+miniexp_lstring(size_t len, const char *s)
 {
-  int l = strlen(s);
-  n = (n < l) ? n : l;
-  char *b = new char[n+1];
-  strncpy(b, s, n);
-  b[n] = 0;
-  ministring_t *obj = new ministring_t(b, true);
+  ministring_t *obj = new ministring_t(len,s);
   return miniexp_object(obj);
 }
 
 miniexp_t 
+miniexp_substring(const char *s, int len)
+{
+  size_t l = strlen(s);
+  size_t n = (size_t)len;
+  return miniexp_lstring((l < n) ? l : n, s);
+}
+
+miniexp_t 
 miniexp_concat(miniexp_t p)
 {
   miniexp_t l = p;
   const char *s;
-  int n = 0;
+  size_t n = 0;
   if (miniexp_length(l) < 0)
     return miniexp_nil;
   for (p=l; miniexp_consp(p); p=cdr(p))
-    if ((s = miniexp_to_str(car(p))))
-      n += strlen(s);
+    n += miniexp_to_lstr(car(p), 0);
   char *b = new char[n+1];
   char *d = b;
   for (p=l; miniexp_consp(p); p=cdr(p))
-    if ((s = miniexp_to_str(car(p)))) {
-      strcpy(d, s);
-      d += strlen(d);
+    if ((n = miniexp_to_lstr(car(p), &s))) {
+      memcpy(d, s, n);
+      d += n;
     }
-  ministring_t *obj = new ministring_t(b, true);
+  ministring_t *obj = new ministring_t(d-b, b, true);
   return miniexp_object(obj);
 }
 
@@ -1142,6 +1176,7 @@ public:
   minifloat_t(double x) : val(x) {}
   operator double() const { return val; }
   virtual char *pname() const;
+  virtual bool doublep(double &d) const { d=val; return true; }
 private:
   double val;
 };
@@ -1164,14 +1199,25 @@ miniexp_floatnum(double x)
   return miniexp_object(obj);
 }
 
+int
+miniexp_doublep(miniexp_t p)
+{
+  double v = 0.0;
+  if (miniexp_numberp(p) ||
+      (miniexp_objectp(p) && miniexp_to_obj(p)->doublep(v)) )
+    return 1;
+  return 0;
+}
+
 double 
 miniexp_to_double(miniexp_t p)
 {
+  double v = 0.0;
   if (miniexp_numberp(p))
-    return (double) miniexp_to_int(p);
-  else if (miniexp_floatnump(p))
-    return (double) * (minifloat_t*) miniexp_to_obj(p);
-  return 0.0;
+    v = (double) miniexp_to_int(p);
+  else if (miniexp_objectp(p))
+    miniexp_to_obj(p)->doublep(v);
+  return v;
 }
 
 miniexp_t 
@@ -1418,11 +1464,12 @@ printer_t::print(miniexp_t p)
     }
   else if (miniexp_stringp(p))
     {
-      const char *s = miniexp_to_str(p);
-      int n = print_c_string(s, 0, flags);
+      const char *s;
+      size_t len = miniexp_to_lstr(p, &s);
+      int n = print_c_string(s, 0, flags, len);
       char *d = new char[n];
       if (d) 
-        print_c_string(s, d, flags);
+        print_c_string(s, d, flags, len);
       mlput(d);
       delete [] d;
     }
@@ -1644,7 +1691,7 @@ miniexp_pname(miniexp_t p, int width)
 /* ---- INPUT */
 
 static void
-grow(char* &s, int &l, int &m)
+grow(char* &s, size_t &l, size_t &m)
 {
   int nm = ((m<256)?256:m) + ((m>32000)?32000:m);
   char *ns = new char[nm+1];
@@ -1655,7 +1702,7 @@ grow(char* &s, int &l, int &m)
 }
 
 static void
-append(int c, char* &s, int &l, int &m)
+append(int c, char* &s, size_t &l, size_t &m)
 {
   if (l >= m)
     grow(s, l, m);
@@ -1664,7 +1711,7 @@ append(int c, char* &s, int &l, int &m)
 }
 
 static void
-append_utf8(int x, char *&s, int &l, int &m)
+append_utf8(int x, char *&s, size_t &l, size_t &m)
 {
   if (x >= 0 && x <= 0x10ffff)
     { 
@@ -1745,8 +1792,8 @@ read_c_string(miniexp_io_t *io, int &c)
 {
   miniexp_t r;
   char *s = 0;
-  int l = 0;
-  int m = 0;
+  size_t l = 0;
+  size_t m = 0;
   ASSERT(c == '\"');
   c = io->fgetc(io);
   for(;;)
@@ -1819,8 +1866,8 @@ read_c_string(miniexp_io_t *io, int &c)
               io->ungetc(io, c);
               c = d;
             }
-          static const char *tr1 = "tnrbfva";
-          static const char *tr2 = "\t\n\r\b\f\013\007";
+          static const char *tr1 = "tnrbfvae?";
+          static const char *tr2 = "\t\n\r\b\f\013\007\033?";
           for (int i=0; tr1[i]; i++)
             if (c == tr1[i])
               c = tr2[i];
@@ -1829,7 +1876,7 @@ read_c_string(miniexp_io_t *io, int &c)
       c = io->fgetc(io);
     }
   c = io->fgetc(io);
-  r = miniexp_string(s ? s : "");
+  r = miniexp_lstring(l, s);
   delete [] s;
   return r;
 }
@@ -1839,8 +1886,8 @@ read_quoted_symbol(miniexp_io_t *io, int
 {
   miniexp_t r;
   char *s = 0;
-  int l = 0;
-  int m = 0;
+  size_t l = 0;
+  size_t m = 0;
   ASSERT(c == '|');
   for(;;)
     {
@@ -1862,8 +1909,8 @@ read_symbol_or_number(miniexp_io_t *io,
 {
   miniexp_t r;
   char *s = 0;
-  int l = 0;
-  int m = 0;
+  size_t l = 0;
+  size_t m = 0;
   for(;;)
     {
       if (c==EOF || c=='(' || c==')' || c=='|' || c=='\"'  
--- djvulibre-3.5.27.1.orig/libdjvu/miniexp.h
+++ djvulibre-3.5.27.1/libdjvu/miniexp.h
@@ -3,8 +3,8 @@
 // MiniExp - Library for handling lisp expressions
 // Copyright (c) 2005  Leon Bottou
 //
-// This software is subject to, and may be distributed under, the
-// GNU General Public License, either Version 2 of the license,
+// This software is subject to, and may be distributed under, the GNU
+// Lesser General Public License, either Version 2.1 of the license,
 // or (at your option) any later version. The license should have
 // accompanied the software or you may obtain a copy of the license
 // from the Free Software Foundation at http://www.fsf.org .
@@ -269,16 +269,28 @@ MINILISPAPI int miniexp_stringp(miniexp_
 
 MINILISPAPI const char *miniexp_to_str(miniexp_t p);
 
+/* miniexp_to_lstr ---- 
+   Returns the length of the string represented by the expression.
+   Optionally returns the c string into *sp.  
+   Return 0 and makes *sp null if the expression is not a string. */
+
+MINILISPAPI size_t miniexp_to_lstr(miniexp_t p, const char **sp);
+
 /* miniexp_string --
-   Constructs a string expression by copying string s. */
+   Constructs a string expression by copying zero terminated string s. */
 
 MINILISPAPI miniexp_t miniexp_string(const char *s);
 
+/* miniexp_lstring --
+   Constructs a string expression by copying len bytes from s. */
+
+MINILISPAPI miniexp_t miniexp_lstring(size_t len, const char *s);
+
 /* miniexp_substring --
-   Constructs a string expression by copying 
-   at most n character from string s. */
+   Constructs a string expression by copying at most len bytes 
+   from zero terminated string s. */
 
-MINILISPAPI miniexp_t miniexp_substring(const char *s, int n);
+MINILISPAPI miniexp_t miniexp_substring(const char *s, int len);
 
 /* miniexp_concat --
    Concat all the string expressions in list <l>. */
@@ -304,13 +316,11 @@ MINILISPAPI miniexp_t miniexp_floatnum(d
    Tests if an expression can be converted
    to a double precision number. */
 
-static inline int miniexp_doublep(miniexp_t p) {
-  return miniexp_numberp(p) || miniexp_floatnump(p);
-}
+MINILISPAPI int miniexp_doublep(miniexp_t p);
 
 /* miniexp_to_double --
    Returns a double precision number corresponding to 
-   a lisp expression (a number or a floatnum.) */
+   a lisp expression. */
 
 MINILISPAPI double miniexp_to_double(miniexp_t p);
 
@@ -721,6 +731,11 @@ miniobj_t {
   /* pname: returns a printable name for this object.
      The caller must deallocate the result with delete[]. */
   virtual char *pname() const;
+  /* stringp, doublep: tells whether this object should be
+     interpreted/printed as a generic string (for miniexp_strinp) 
+     or a double (for miniexp_doublep). */
+  virtual bool stringp(const char* &s, size_t &l) const;
+  virtual bool doublep(double &d) const;
   /* mark: calls action() on all member miniexps of the object,
      for garbage collecting purposes. */
   virtual void mark(minilisp_mark_t *action);
--- djvulibre-3.5.27.1.orig/tools/csepdjvu.1
+++ djvulibre-3.5.27.1/tools/csepdjvu.1
@@ -188,22 +188,21 @@ Pixels are ordered in left to right, top
 
 .SS Comments in separated files
 
-Each page is followed by an arbitrary number of comment lines 
-starting with character "#" and terminated by a linefeed character. 
-Comment lines whose first word starts with a capital letter have 
-special meanings. The following constructs are currently defined:
+Each page is followed by an arbitrary number of comment lines starting with
+character "#" and terminated by a linefeed character.  Certain comment lines
+have special meanings. In the following constructs, all the strings are UTF-8
+encoded and represent in the style of Postscript strings, that is, surrounded
+with parenthesis and using C-style escape sequences introduced by a backslash.
 .IP "*" 3
 .BI "# T " px ":" py " " dx ":" dy " " w "x" h "+" x "+" y " (" string ")"
 .br
-This constructs indicates that the piece of text
+Such a comment line indicates that the piece of text
 .I string
 must be associated with an area of size
 .IR w "x" h
 at position 
 .IR x "," y
 relative to the lower left corner of the page.
-The string is UTF-8 encoded. Special characters
-can be escaped as in PostScript using the backslash character.
 Integers
 .IR px ", and " py
 represent the position of the current point on the text baseline
@@ -218,7 +217,7 @@ corresponding pages.
 .IP "*" 3
 .BI "# L " w "x" h "+" x "+" y " (" url ")"
 .br
-This construct indicates that an hyperlink to url
+Such a comment line indicates that an hyperlink to url
 .I url
 should be associated with area of size
 .IR w "x" h
@@ -231,7 +230,7 @@ containing the specified hyperlinks.
 .IP "*" 3
 .BI "# B " count " (" string ") (#" pageno ")"
 .br
-This constructs provides outline information for the document.
+Such a comment line provides outline information for the document.
 An outline entry entitled
 .I string
 is associated with page
@@ -244,7 +243,12 @@ When such comments are present in the fi
 .BR csepdjvu 
 produces an navigation chunk with 
 the specified outline.
-
+.IP "*" 3
+.BI "# P (" string ")"
+.br
+Such a comment line provides a title
+.I string
+for the current page.
 .SH CREDITS
 
 This program was initially written by L\('eon Bottou
--- djvulibre-3.5.27.1.orig/tools/csepdjvu.cpp
+++ djvulibre-3.5.27.1/tools/csepdjvu.cpp
@@ -1121,6 +1121,7 @@ public:
   bool parse_comment_line(BufferByteStream &bs);
   void make_chunks(IFFByteStream &iff);
   GP<DjVmNav> get_djvm_nav();
+  GUTF8String get_pagetitle();
 protected:
   int w;
   int h;
@@ -1143,6 +1144,7 @@ protected:
   };
   GPList<LnkMark> links;
   GP<DjVmNav> nav;
+  GUTF8String pagetitle;
 protected:
   bool allspace(const TxtMark *mark);
   void textmark(GP<TxtMark> mark);
@@ -1255,6 +1257,15 @@ Comments::parse_comment_line(BufferByteS
         nav->append(b);
       return true;
     }
+  // Page title comment
+  if (c == 'P')
+    {
+      if (pagetitle.length())
+        G_THROW("csepdjvu: corrupted file (multiple page title comments)");
+      if (! (bs.skip(" \t") && bs.read_ps_string(pagetitle) ))
+	G_THROW("csepdjvu: corrupted file (syntax error in title comment)");
+      return true;
+    }
   // Unrecognized
   bs.unget(c);
   return false;
@@ -1487,6 +1498,12 @@ Comments::get_djvm_nav()
   return 0;
 }
 
+GUTF8String
+Comments::get_pagetitle()
+{
+  return pagetitle;
+}
+
 
 // --------------------------------------------------
 // MAIN COMPRESSION ROUTINE
@@ -1500,6 +1517,7 @@ void
 csepdjvu_page(BufferByteStream &bs, 
               GP<ByteStream> obs, 
               GP<DjVmNav> &nav,
+	      GUTF8String &pagetitle,
               const csepdjvuopts &opts)
 {
   // Read rle data from separation file
@@ -1671,7 +1689,8 @@ csepdjvu_page(BufferByteStream &bs,
   // -- terminate main composite chunk
   coms.make_chunks(iff);
   iff.close_chunk();
-  // -- store outline
+  // -- returns page title and outline
+  pagetitle = coms.get_pagetitle();
   if (! nav) 
     nav = coms.get_djvm_nav();
 }  
@@ -1765,6 +1784,7 @@ main(int argc, const char **argv)
     {
       GP<DjVmDoc> gdoc=DjVmDoc::create();
       GP<DjVmNav> gnav;
+      GUTF8String pagetitle;
       DjVmDoc &doc=*gdoc;
       GURL outputurl;
       GP<ByteStream> goutputpage=ByteStream::create();
@@ -1821,7 +1841,7 @@ main(int argc, const char **argv)
                 // Compress page 
                 goutputpage=ByteStream::create();
                 ByteStream &outputpage=*goutputpage;
-                csepdjvu_page(ibs, goutputpage, gnav, opts);
+                csepdjvu_page(ibs, goutputpage, gnav, pagetitle, opts);
                 if (opts.verbose) {
                   DjVuPrintErrorUTF8("csepdjvu: %d bytes for page %d",
                                      outputpage.size(), pageno);
@@ -1834,12 +1854,12 @@ main(int argc, const char **argv)
                 // Insert page into document
                 outputpage.seek(0);
                 doc.insert_file(outputpage, DjVmDir::File::PAGE, 
-                                pagename, pagename);
+                                pagename, pagename, pagetitle);
               } while (check_for_another_page(ibs, opts));
             }
         } 
       // Save file
-      if (pageno == 1 && ! gnav) 
+      if (pageno == 1 && ! gnav && ! pagetitle) 
         {
           ByteStream &outputpage=*goutputpage;
           // Save as a single page 
--- djvulibre-3.5.27.1.orig/tools/ddjvu.cpp
+++ djvulibre-3.5.27.1/tools/ddjvu.cpp
@@ -691,7 +691,7 @@ closefile(int pageno)
       args[1] = "-o";
       args[2] = filename;
       if (tiff2pdf(tiff, fout, 3, args) != EXIT_SUCCESS)
-        die(i18n("Error occured while creating PDF file."));
+        die(i18n("Error occurred while creating PDF file."));
       TIFFClose(tiff);
       tiff = 0;
 #ifndef _WIN32
--- djvulibre-3.5.27.1.orig/tools/djvudigital
+++ djvulibre-3.5.27.1/tools/djvudigital
@@ -54,7 +54,18 @@
 #C- +------------------------------------------------------------------
 #C--------------------------------------------------------------------
 
-# Step 1 -- utilities
+
+# Step 1a -- temporary directory
+
+tempdir=`mktemp -d --tmpdir djXXXXXX 2>/dev/null` || tempdir=''
+while [ ! -d "$tempdir" -o ! -r "$tempdir" ] ; do
+    tempdir="/tmp/dj"`awk 'BEGIN{srand();printf("%d",rand()*100000)}'`
+    mkdir "$tempdir" || tempdir=''
+done
+trap 'rm -rf 2>/dev/null "$tempdir"' EXIT INT HUP QUIT
+
+
+# Step 1b -- utilities
 
 usage()
 {
@@ -97,8 +108,7 @@ checkps2utf8()
         if ( "$gsdjvu" 2>&1 -dNODISPLAY -c '(ps2utf8.ps) runlibfile quit' | \
               grep -q WRITESYSTEMDICT )
         then
-            djvutext="/tmp/dj$$.ps"
-            trap "rm 2>/dev/null $djvutext" 0
+            djvutext="$tempdir/djvutext.ps"
             cat > $djvutext <<\EOF
 (ps2utf8.ps) runlibfile currentglobal /setglobal load true setglobal 
 .ps2utf8 begin /onpage { } bind def /onfont { pop pop pop } bind def
@@ -111,7 +121,7 @@ EOF
 }
 
 
-# Step 1 -- locate gsdjvu executable
+# Step 2a -- locate gsdjvu executable
 
 gsdjvu=
 for gs in ${GSDJVU} `pathexpand gs` `pathexpand gsdjvu`
@@ -135,8 +145,7 @@ EOF
     exit 10
 fi
 
-
-# Step 2 -- locate csepdjvu executable
+# Step 2b -- locate csepdjvu executable
 
 csepdjvu=
 for cs in ${CSEPDJVU} `pathexpand csepdjvu` `pathexpand msepdjvu`
@@ -159,6 +168,30 @@ EOF
     exit 10
 fi
 
+# Step 2c -- locate djvused executable
+
+djvused=
+for ds in ${DJVUSED} `pathexpand djvused`
+do
+    if [ -z "$djvused" ] && ( "$ds" 2>&1 | grep -q -i djvulibre )
+    then
+        djvused="$ds"
+    fi
+done
+
+# Step 2d -- locate pdftotext executable
+
+pdftotext=
+for pt in ${PDFTOTEXT} `pathexpand pdftotext`
+do
+  if [ -z "$pdftotext" ] && \
+     ( "$pt" -bbox foo.pdf 2>&1 | grep -q foo.pdf )
+     ( "$pt" -v 2>&1 | grep -q Poppler )
+  then
+      pdftotext="$pt"
+  fi
+done
+
 
 # Step 3 -- process arguments
 
@@ -171,11 +204,14 @@ gsprinted="-dPrinted"
 gsepsf="-dEPSCrop"
 gsverbosity=
 csepverbosity='-v'
+dsedverbosity=
 djvutext=
 infile=
 outfile=
 run=
 sepfile=
+popplertext=0
+popplermeta=0
 
 for n
 do
@@ -194,6 +230,8 @@ do
       --check)
           echo 1>&2 "Using: $gsdjvu"
           echo 1>&2 "  and: $csepdjvu"
+          test -n "$pdftotext" && echo 1>&2 "  and: $pdftotext"
+          test -n "$djvused" && echo 1>&2 "  and: $djvused"
           exit 0
           ;;
       --dpi=[0-9]*)
@@ -202,9 +240,10 @@ do
       --verbose|--v)
           gsverbosity=''
           csepverbosity='-vv'
+          dsedverbosity='-v'
           ;;
       --dryrun)
-          run=echo
+          run="echo +"
           ;;
       --sepfile)
           sepfile=yes
@@ -254,6 +293,16 @@ do
           fi
           csepargs="$csepargs -t"
           ;;
+      --poppler=*)
+          for arg in `getargs $n` ; do
+            case "$arg" in 
+              text) popplertext=1 ;;
+              meta) popplermeta=1 ;;
+                 *) echo 1>&2 "djvudigital: unrecognized option --poppler=$arg"
+                    usage ;; 
+            esac
+          done
+          ;;
       --pdf=screen)
           gsprinted="-dPrinted=false"
           ;;
@@ -285,6 +334,7 @@ do
           csepargs="$csepargs `getargs $n`"
           ;;
       -*)
+          echo 1>&2 "djvudigital: unrecognized option $n"
           usage
           ;;
       *)
@@ -339,7 +389,7 @@ if [ "$sepfile" = "yes" ]
 then
   backend="$outfile"
 else
-  backend="|$csepdjvu -d "'"'"$dpi"'"'
+  backend="| "'"'"$csepdjvu"'"'" -d $dpi"
   backend="$backend $csepverbosity $csepargs - "'"'"$outfile"'"'
 fi
 
@@ -348,26 +398,268 @@ case "$infile" in
     *.gz|*.GZ)
         if test -z "$run" ; then
           gzip -d -c "$infile" | \
-          $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf \
+          "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf \
             "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 -_ -c quit
         else
-          echo -n gzip -d -c '"'"$infile"'"' '|' ""
-          echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf ""
-          echo -n "-sOutputFile=""'""$backend""'" ""
-          echo -n $gsarg0 $gsarg1 $gsarg2 -_ -c quit
-          echo
+          $run gzip -d -c '"'"$infile"'"' '|' "" \
+             "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \
+             "-sOutputFile=""'""$backend""'" "" \
+             $gsarg0 $gsarg1 $gsarg2 -_ -c quit
         fi
         ;;
     *)
         if test -z "$run" ; then
-          $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf \
+          "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf \
             "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 \
             -f "$infile" -c quit
         else
-          echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf ""
-          echo -n "-sOutputFile=""'""$backend""'" ""
-          echo -n $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit
-          echo
+          $run "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \
+             "-sOutputFile=""'""$backend""'" "" \
+             $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit
         fi
         ;;
 esac
+
+
+# Step 6 -- Postprocess djvu file with metadata/text found by poppler
+
+if ( file "$infile" | grep -q -i pdf ) \
+    && test "$popplertext$popplermeta" != "00"
+then
+
+    # check for djvused
+    if [ -z "$djvused" ]
+    then
+        cat 1>&2 <<\EOF
+djvudigital: cannot locate djvused executable.
++--------------------------------------------------------------------+
+| DjVuDigital was not able to locate the djvulibre tool "djvused".   |
+| This tool is needed to use the --poppler=(text,data) options.      |
+| Please make sure that the djvulibre tools are properly installed.  |
++--------------------------------------------------------------------+
+EOF
+        exit 10
+    fi
+
+    # check for pdftotext
+    if [ -z "$pdftotext" ] 
+    then
+        cat 1>&2 <<\EOF
+djvudigital: cannot locate pdftotext executable.
++--------------------------------------------------------------------+
+| DjVuDigital was not able to locate the poppler tool "pdftotext".   |
+| This tool is needed to use the --poppler=(text,data) options.      |
+| Please make sure that the poppler tools are properly installed.    |
++--------------------------------------------------------------------+
+EOF
+        exit 10
+    fi
+
+    # xml parser for awk :-)
+    xml2dsed="$tempdir/xml2dsed.awk"
+    cat > "$xml2dsed" <<\EOF
+
+# initializations
+
+function _esc_init() {
+    _ctrl = ""
+    for (i=1; i<32; i++) { _ctrl = _ctrl sprintf("%c",i) }
+    _esc = "[\"\\&" _ctrl "]"
+    _ctrl = "[" _ctrl "]"
+}
+
+function _ord_init() {
+    for (i=0; i<256; i++) {
+	_ord[sprintf("%c",i)]=i
+    }
+}
+
+function _amp_init() {
+    _amp["&amp;"] = "&"
+    _amp["&lt;"] = "<"
+    _amp["&gt;"] = ">"
+    _amp["&apos;"] = "'"
+    _amp["&quot;"] = "\\\""
+}
+
+BEGIN {
+    _esc_init()
+    _ord_init()
+    _amp_init()
+    delete meta
+    pheight=0
+    pwidth=0
+    location=""
+    context=""
+    content=""
+    pageno=0
+    dpi = 300 # use awk -f xml2dsed.awk dpi=xxx to override
+    dometa=1  # use awk -f xml2dsed.awk dometa=0 to override
+    dotext=1  # use awk -f xml2dsed.awk dotext=0 to override
+    RS=">"    # xml parsing wants record delimiter set to ">"
+}
+
+# return character code
+
+function ord(str) {
+    return _ord[substr(str,1,1)]
+}
+
+# print properly escaped c string
+
+function pstr(str,tmp) {
+    printf("\"")
+    while (str) {
+	tmp = match(str,_esc) # char classes do not always work
+	if (tmp == 0) {
+	    printf("%s",str)
+	    str = ""
+	} else if (tmp > 1) {
+	    printf("%s",substr(str,1,tmp-1))
+	    str = substr(str,tmp)
+	} else {
+	    tmp = match(str,"^&[a-z]*;")
+	    if (tmp != 1) { tmp = "" }
+	    if (tmp) { tmp = _amp[substr(str,RSTART,RLENGTH)] }
+	    if (tmp) {
+		printf("%s",tmp)
+		str = substr(str,RLENGTH+1)
+	    } else {
+		printf("\\%03o", ord(str))
+		str = substr(str,2)
+	    }
+	}
+    }
+    printf("\"")
+}
+
+# sax-like callbacks
+
+function charData(str) {
+    if (context == "title") {
+	meta["Title"] = str
+    } else if (context == "word") {
+	gsub(_ctrl," ",str)      # kill control characters
+	gsub("\302\240"," ",str) # nbsp in utf-8
+	gsub(/  */," ",str)      # simplify spaces
+	gsub(/^ /,"",str)        # simplify spaces
+	gsub(/ $/,"",str)        # simplify spaces
+	if (match(str,/[^ ]/)) { content = str } else { content = "" }
+    }
+}
+
+function startElement(tag,attrs) {
+    if (tag=="head" && ! context && dometa) {
+	context = "head"
+    } else if (tag=="title" && context=="head") {
+	context = "title"
+    } else if (tag=="meta" && attrs["name"] && attrs["content"] ) {
+	meta[attrs["name"]] = attrs["content"]
+    } else if (tag=="body" && ! context && dotext) {
+	context = "body"
+    } else if (tag=="page" && context == "body") {
+	pageno = pageno + 1
+	pwidth = attrs["width"] * dpi / 72
+	pheight = attrs["height"] * dpi / 72
+	context = "page"
+	printf("select %d\n", pageno)
+	printf("set-txt\n")
+	printf("(page %d %d %d %d\n", 0, 0, pwidth, pheight)
+    } else if (tag=="word" && context == "page") {
+	if (attrs["xMin"] && attrs["xMax"] && attrs["yMin"] && attrs["yMax"]) {
+	    context = "word"
+	    location = sprintf("%d %d %d %d",
+			       attrs["xMin"] * dpi / 72,
+			       pheight - attrs["yMin"] * dpi / 72,
+			       attrs["xMax"] * dpi / 72,
+			       pheight - attrs["yMax"] * dpi / 72 )
+	}
+    }
+}
+
+function endElement(tag) {
+    if (tag == "title" && context == "title") {
+	context = "head"
+    } else if (tag == "head" && context == "head" && length(meta)>0) {
+	context = ""
+	printf("create-shared-ant\n")
+	printf("set-meta\n")
+	for (i in meta) {
+	    printf("%s\t",i)
+	    pstr(meta[i])
+	    printf("\n")
+	}
+	printf(".\n")
+    } else if (tag == "page" && context == "page") {
+	context = "body"
+	printf(")\n.\n")
+    } else if (tag == "word" && context == "word" && content) {
+	context = "page"
+	printf("  (word %s ", location)
+	pstr(content)
+	printf(")\n")
+	content = ""
+    }
+}
+
+# xml parser (for pdftotext!)
+{
+    str = $0
+    match(str,/^[ \n\r\t\f]*/)
+    if (RSTART == 1 && RLENGTH > 0) {
+	str = substr(str,RLENGTH+1)
+    }
+    if (! match(str,/</)) {
+	charData(str)
+    } else {
+	if (RSTART > 1) {
+	    arg = substr(str,1,RSTART-1)
+	    str = substr(str,RSTART)
+	    charData(arg)
+	}
+	match(str, "^</?[a-zA-Z][a-zA-Z0-9_]*")
+	if (RSTART == 1) {
+	    tag = substr(str,2,RLENGTH-1)
+	    arg = substr(str,RLENGTH+1)
+	    # parse attrs
+	    delete attrs
+	    if (match(arg,"/$")) { arg = substr(arg,1,RSTART-1) }
+	    while (arg && match(arg,/[a-zA-Z][a-zA-Z0-9_]*=/)) {
+		attr = substr(arg,RSTART,RLENGTH-1)
+		arg = substr(arg,RSTART+RLENGTH)
+		if (match(arg,/^[ \n\r\f\t]*"/) && match(arg,/"[^"]*"/)) {
+		    attrs[attr] = substr(arg,RSTART+1,RLENGTH-2)
+		    arg = substr(arg,RSTART+RLENGTH)
+		} else if (match(arg,/^[^ \n\r\g\t]*/)) {
+		    attrs[attr] = substr(arg,RSTART,RLENGTH)
+		    arg = substr(arg,RSTART+RLENGTH)
+		}
+	    }
+	    # callbacks
+	    if (match(tag,"^/")) {
+		endElement(substr(tag,2))
+	    } else {
+		startElement(tag,attrs)
+		if (match(str,"/$")) { endElement(tag) }
+	    }
+	} 
+    }	    
+}
+EOF
+
+    # prepare djvused script
+    dsedscript="$tempdir/dsed"
+    if test -z "$run" 
+    then
+        "$pdftotext" -bbox "$infile" "-" \
+            | awk -f $xml2dsed dpi=$dpi dometa=$popplermeta dotext=$popplertext \
+            > "$dsedscript"
+    else
+        $run "$pdftotext" -bbox "$infile" "-" \
+            \| awk -f $xml2dsed dpi=$dpi dometa=$popplermeta dotext=$popplertext \
+            \> "$dsedscript"
+    fi
+    
+    # execute dsed script
+    $run "$djvused" $dsedverbosity -f "$dsedscript" -s "$outfile"
+fi
--- djvulibre-3.5.27.1.orig/tools/djvudigital.1
+++ djvulibre-3.5.27.1/tools/djvudigital.1
@@ -158,6 +158,38 @@ Insert extra arguments on the command li
 program
 .BR csepdjvu " or " msepdjvu "."
 .TP
+.BI "--poppler=" "keywords"
+This option causes
+.B djvudigital
+to extract additional information from PDF files using the tool
+.B pdftotext
+that comes bundled with the Poppler library.
+Selected information is then added to the djvu file
+as a postprocessing step. This option is ignored
+when the input file is not a PDF file.
+Argument
+.I keywords
+is a comma separated list of keywords.
+When this list contains keyword
+.BR meta ,
+the metadata extracted by 
+.B pdftotext
+is inserted into the djvu file.
+When this list contains keyword
+.BR text ,
+the textual information extracted by
+.B pdftotext
+is inserted into the djvu file,
+possibly replacing the information
+gathered using the options
+.BR --words
+or
+.BR --lines .
+This is useful for instance when a scanned
+PDF file contains a hidden text layer that
+is not recognized by Ghostscript and therefore
+not passed to the djvudigital backend.
+.TP
 .BI "--sepfile"
 Produces a separated data file instead of a DjVu file. Program
 .BR csepdjvu 
@@ -227,6 +259,32 @@ by the environment variable
 and continues with command line executables named
 .BR msepdjvu " and " csepdjvu "."
 
+.SH OTHER PROGRAMS
+
+The option
+.BI "--poppler=" "keywords"
+relies on the tool
+.B pdftotext
+that comes with the Poppler library
+and the tool
+.B djvused
+that comes with djvulibre.
+Only recent versions of 
+.B pdftotext
+that accept the option
+.B -bbox
+are supported.
+Both tools are searched by first trying
+the files specified by the environment variables
+.B PDFTOTEXT
+and 
+.BR DJVUSED ,
+and then trying executables named 
+.B pdftotext
+or 
+.B djvused 
+found along the shell executable path.
+
 .SH CREDITS
 
 The first version of this converter was written 
--- djvulibre-3.5.27.1.orig/tools/djvuextract.cpp
+++ djvulibre-3.5.27.1/tools/djvuextract.cpp
@@ -208,6 +208,7 @@ main(int argc, char **argv)
   GArray<GUTF8String> dargv(0,argc-1);
   for(int i=0;i<argc;++i)
     dargv[i]=GNativeString(argv[i]);
+  int retcode = 0;
   G_TRY
     {
       int i;
@@ -217,7 +218,7 @@ main(int argc, char **argv)
       for(i=1;i<argc;i++)
 	 if (!dargv[i].cmp("-page=", 6))
            {
-              page_num = dargv[i].substr(6,dargv[i].length()).toInt() - 1; // atoi(6+(const char *)dargv[i]) - 1;
+	     page_num = dargv[i].substr(6,dargv[i].length()).toInt() - 1;
              for(int j=i;j<argc-1;j++) 
                dargv[j]=dargv[j+1];
              argc--;
@@ -253,6 +254,7 @@ main(int argc, char **argv)
           if (mbs.size() == 0)
             {
               DjVuPrintErrorUTF8("  %s --> not found!\n", (const char *)dargv[i]);
+	      retcode = 64;
             }
           else
             {
@@ -271,5 +273,5 @@ main(int argc, char **argv)
       exit(1);
     }
   G_ENDCATCH;
-  return 0;
+  return retcode;
 }
--- djvulibre-3.5.27.1.orig/tools/djvumake.cpp
+++ djvulibre-3.5.27.1/tools/djvumake.cpp
@@ -356,6 +356,8 @@ analyze_jb2_chunk(const GURL &url)
 void
 analyze_incl_chunk(const GURL &url)
 {
+  if (! url.is_file())
+    return;
   GP<ByteStream> gbs = ByteStream::create(url,"rb");
   char buffer[24];
   memset(buffer, 0, sizeof(buffer));
@@ -955,7 +957,7 @@ main(int argc, char **argv)
             }
           else if (!dargv[i].cmp("INCL=",5))
             {
-              create_incl_chunk(iff, "INCL", GURL::Filename::UTF8(5+(const char *)dargv[i]).fname());
+              create_incl_chunk(iff, "INCL", (const char *)GUTF8String(dargv[i].substr(5,-1)));
               flag_contains_incl = 1;
             }
           else if (!dargv[i].cmp("PPM=",4))
--- djvulibre-3.5.27.1.orig/tools/djvused.cpp
+++ djvulibre-3.5.27.1/tools/djvused.cpp
@@ -66,6 +66,7 @@
 #include "GString.h"
 #include "DjVuDocEditor.h"
 #include "DjVuDumpHelper.h"
+#include "DjVuMessageLite.h"
 #include "BSByteStream.h"
 #include "DjVuText.h"
 #include "DjVuAnno.h"
@@ -2315,7 +2316,8 @@ execute()
       G_CATCH(ex)
         {
           vprint("Error (%s): %s",
-                 (const char*)ToNative(token), ex.get_cause());
+                 (const char*)ToNative(token), 
+                 (const char *)DjVuMessageLite::LookUpUTF8(ex.get_cause()));
           if (! verbose)
             G_RETHROW;
         }
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/classify.cpp
+++ djvulibre-3.5.27.1/tools/jb2cmp/classify.cpp
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/classify.h
+++ djvulibre-3.5.27.1/tools/jb2cmp/classify.h
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/cuts.cpp
+++ djvulibre-3.5.27.1/tools/jb2cmp/cuts.cpp
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/frames.cpp
+++ djvulibre-3.5.27.1/tools/jb2cmp/frames.cpp
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/minidjvu.h
+++ djvulibre-3.5.27.1/tools/jb2cmp/minidjvu.h
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/patterns.cpp
+++ djvulibre-3.5.27.1/tools/jb2cmp/patterns.cpp
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/tools/jb2cmp/patterns.h
+++ djvulibre-3.5.27.1/tools/jb2cmp/patterns.h
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * 
  * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net)
--- djvulibre-3.5.27.1.orig/win32/djvulibre/djvulibre-install.sh
+++ djvulibre-3.5.27.1/win32/djvulibre/djvulibre-install.sh
@@ -23,7 +23,7 @@ echo ---- DjVuLibre tools
 
 djexe="bzz.exe c44.exe cjb2.exe cpaldjvu.exe csepdjvu.exe
        ddjvu.exe djvm.exe djvmcvt.exe djvudump.exe djvuextract.exe 
-       djvumake.exe djvups.exe djvused.exe djvuserve.exe djvutoxml.exe
+       djvumake.exe djvups.exe djvused.exe djvutoxml.exe
        djvutxt.exe djvuxmlparser.exe"
 djdll="libdjvulibre.dll libjpeg.dll libtiff.dll libz.dll"
 for n in $djdll $djexe ; do 
--- djvulibre-3.5.27.1.orig/win32/djvulibre/djvulibre.nsi
+++ djvulibre-3.5.27.1/win32/djvulibre/djvulibre.nsi
@@ -32,8 +32,8 @@ RequestExecutionLevel admin
 !define DJVULIBRE_VERSION "3.5.27"
 !define CLASSES "Software\Classes\"
 !define DJVIEW_NAME "DjView"
-!define DJVIEW_VERSION "4.10"
-!define VI_PRODUCT_VERSION "4.10.0.0"
+!define DJVIEW_VERSION "4.10.4"
+!define VI_PRODUCT_VERSION "4.10.4.0"
 
 !define PRODUCT_NAME "${DJVULIBRE_NAME} ${DJVIEW_NAME}"
 !define UNINST_NAME "${DJVULIBRE_NAME}+${DJVIEW_NAME}" ; for uninstaller
