Refactoring of XRef table write support (in preparation for XRef stream write support)

 - Trailer dictionary creation now lives in its own function "createTrailerDict"
   (that will be used by XRef stream creation too)
 - writeXRefTableTrailer (WAS writeTrailer) now takes care of writing the XRef
   table too (previously it was demanded to the caller)
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 898bcbb..9c977a6 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -716,12 +716,14 @@
   page.free();
 
   Guint uxrefOffset = outStr->getPos();
-  yRef->writeToFile(outStr, gFalse /* do not write unnecessary entries */);
-
   Ref ref;
   ref.num = rootNum;
   ref.gen = 0;
-  writeTrailer(uxrefOffset, objectsCount, outStr, gFalse, 0, &ref, getXRef(), name->getCString(), outStr->getPos());
+  Dict *trailerDict = createTrailerDict(objectsCount, gFalse, 0, &ref, getXRef(),
+                                        name->getCString(), uxrefOffset);
+  writeXRefTableTrailer(trailerDict, yRef, gFalse /* do not write unnecessary entries */,
+                        uxrefOffset, outStr, getXRef());
+  delete trailerDict;
 
   outStr->close();
   fclose(f);
@@ -862,10 +864,8 @@
   }
 
   Guint uxrefOffset = outStr->getPos();
-  uxref->writeToFile(outStr, gFalse /* do not write unnecessary entries */);
-
-  writeTrailer(uxrefOffset, xref->getNumObjects(), outStr, gTrue);
-
+  writeXRefTableTrailer(uxrefOffset, uxref, gFalse /* do not write unnecessary entries */,
+                        xref->getNumObjects(), outStr, gTrue /* incremental update */);
   delete uxref;
 }
 
@@ -902,13 +902,9 @@
     }
   }
   Guint uxrefOffset = outStr->getPos();
-  uxref->writeToFile(outStr, gTrue /* write all entries */);
-
-  writeTrailer(uxrefOffset, uxref->getNumObjects(), outStr, gFalse);
-
-
+  writeXRefTableTrailer(uxrefOffset, uxref, gTrue /* write all entries */,
+                        uxref->getNumObjects(), outStr, gFalse /* complete rewrite */);
   delete uxref;
-
 }
 
 void PDFDoc::writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset)
@@ -1109,10 +1105,8 @@
   return offset;
 }
 
-void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize, 
-			  OutStream* outStr, GBool incrUpdate,
-			  Guint startxRef, Ref *root, XRef *xRef, const char *fileName,
-			  Guint fileSize)
+Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Guint startxRef,
+                                Ref *root, XRef *xRef, const char *fileName, Guint fileSize)
 {
   Dict *trailerDict = new Dict(xRef);
   Object obj1;
@@ -1120,7 +1114,6 @@
   trailerDict->set("Size", &obj1);
   obj1.free();
 
-
   //build a new ID, as recommended in the reference, uses:
   // - current time
   // - file name
@@ -1130,7 +1123,9 @@
   char buffer[256];
   sprintf(buffer, "%i", (int)time(NULL));
   message.append(buffer);
-  message.append(fileName);
+
+  if (fileName)
+    message.append(fileName);
 
   sprintf(buffer, "%i", fileSize);
   message.append(buffer);
@@ -1162,7 +1157,7 @@
     //only update the second part of the array
     xRef->getTrailerDict()->getDict()->lookup("ID", &obj4);
     if (!obj4.isArray()) {
-      error(errSyntaxWarning, -1, "PDFDoc::writeTrailer original file's ID entry isn't an array. Trying to continue");
+      error(errSyntaxWarning, -1, "PDFDoc::createTrailerDict original file's ID entry isn't an array. Trying to continue");
     } else {
       //Get the first part of the ID
       obj4.arrayGet(0,&obj3); 
@@ -1194,24 +1189,25 @@
       trailerDict->set("Info", &obj5);
     }
   }
-  
+
+  return trailerDict;
+}
+
+void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAllEntries, Guint uxrefOffset, OutStream* outStr, XRef *xRef)
+{
+  uxref->writeTableToFile( outStr, writeAllEntries );
   outStr->printf( "trailer\r\n");
   writeDictionnary(trailerDict, outStr, xRef, 0);
   outStr->printf( "\r\nstartxref\r\n");
   outStr->printf( "%i\r\n", uxrefOffset);
   outStr->printf( "%%%%EOF\r\n");
-
-  delete trailerDict;
 }
 
-void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate)
+void PDFDoc::writeXRefTableTrailer(Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+                                   int uxrefSize, OutStream* outStr, GBool incrUpdate)
 {
-  const char *fileNameA;
-  if (fileName)
-    fileNameA = fileName->getCString();
-  else
-    fileNameA = "streamwithoutfilename.pdf";
-  // file size
+  const char *fileNameA = fileName ? fileName->getCString() : NULL;
+  // file size (doesn't include the trailer)
   unsigned int fileSize = 0;
   int c;
   str->reset();
@@ -1222,7 +1218,10 @@
   Ref ref;
   ref.num = getXRef()->getRootNum();
   ref.gen = getXRef()->getRootGen();
-  writeTrailer(uxrefOffset, uxrefSize, outStr, incrUpdate, getStartXRef(), &ref, getXRef(), fileNameA, fileSize);
+  Dict * trailerDict = createTrailerDict(uxrefSize, incrUpdate, getStartXRef(), &ref,
+                                         getXRef(), fileNameA, fileSize);
+  writeXRefTableTrailer(trailerDict, uxref, writeAllEntries, uxrefOffset, outStr, getXRef());
+  delete trailerDict;
 }
 
 void PDFDoc::writeHeader(OutStream *outStr, int major, int minor)
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index ccb1b22..468f698 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -23,6 +23,7 @@
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
 // Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -244,8 +245,14 @@
   Guint writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset);
   static Guint writeObject (Object *obj, Ref *ref, OutStream* outStr, XRef *xref, Guint numOffset);
   static void writeHeader(OutStream *outStr, int major, int minor);
-  static void writeTrailer (Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate,
-                            Guint startxRef, Ref *root, XRef *xRef, const char *fileName, Guint fileSize);
+
+  // Ownership goes to the caller
+  static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, Guint startxRef,
+                                  Ref *root, XRef *xRef, const char *fileName, Guint fileSize);
+  static void writeXRefTableTrailer (Dict *trailerDict, XRef *uxref, GBool writeAllEntries,
+                                     Guint uxrefOffset, OutStream* outStr, XRef *xRef);
+  static void writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef,
+                                      Guint uxrefOffset, OutStream* outStr, XRef *xRef);
 
 private:
   // insert referenced objects in XRef
@@ -260,7 +267,8 @@
   { writeDictionnary(dict, outStr, getXRef(), 0); }
   static void writeStream (Stream* str, OutStream* outStr);
   static void writeRawStream (Stream* str, OutStream* outStr);
-  void writeTrailer (Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate);
+  void writeXRefTableTrailer (Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+                              int uxrefSize, OutStream* outStr, GBool incrUpdate);
   static void writeString (GooString* s, OutStream* outStr);
   void saveIncrementalUpdate (OutStream* outStr);
   void saveCompleteRewrite (OutStream* outStr);
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index dfc6d73..3b0d7f8 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -1240,7 +1240,7 @@
   e->updated = true;
 }
 
-void XRef::writeToFile(OutStream* outStr, GBool writeAllEntries) {
+void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
   //create free entries linked-list
   if (getEntry(0)->gen != 65535) {
     error(errInternal, -1, "XRef::writeToFile, entry 0 of the XRef is invalid (gen != 65535)\n");
diff --git a/poppler/XRef.h b/poppler/XRef.h
index 4cba474..ab8047c 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -135,7 +135,7 @@
   Ref addIndirectObject (Object* o);
   void removeIndirectObject(Ref r);
   void add(int num, int gen,  Guint offs, GBool used);
-  void writeToFile(OutStream* outStr, GBool writeAllEntries);
+  void writeTableToFile(OutStream* outStr, GBool writeAllEntries);
 
 private:
 
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index 93850a4..212f89b 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -6,6 +6,7 @@
 //
 // Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Arseny Solokha <asolokha@gmx.com>
+// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 //
 //========================================================================
 #include <PDFDoc.h>
@@ -161,13 +162,14 @@
     objectsCount++;
   }
   Guint uxrefOffset = outStr->getPos();
-  yRef->writeToFile(outStr, gFalse /* do not write unnecessary entries */ );
-
   Ref ref;
   ref.num = rootNum;
   ref.gen = 0;
-  PDFDoc::writeTrailer(uxrefOffset, objectsCount, outStr, (GBool) gFalse, 0,
-	&ref, yRef, fileName, outStr->getPos());
+  Dict *trailerDict = PDFDoc::createTrailerDict(objectsCount, gFalse, 0, &ref, yRef,
+                                                fileName, outStr->getPos());
+  PDFDoc::writeXRefTableTrailer(trailerDict, yRef, gFalse /* do not write unnecessary entries */,
+                                uxrefOffset, outStr, yRef);
+  delete trailerDict;
 
   outStr->close();
   fclose(f);