Blame libdjvu/DjVmDoc.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include "DjVmDoc.h"
Packit df99a1
#include "DjVmNav.h"
Packit df99a1
#include "DataPool.h"
Packit df99a1
#include "IFFByteStream.h"
Packit df99a1
#include "GOS.h"
Packit df99a1
#include "debug.h"
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
static const char octets[4]={0x41,0x54,0x26,0x54};
Packit df99a1
Packit df99a1
// Save the file to disk, remapping INCL chunks while saving.
Packit df99a1
static void
Packit df99a1
save_file(
Packit df99a1
  IFFByteStream &iff_in, IFFByteStream &iff_out, const DjVmDir &dir,
Packit df99a1
  GMap<GUTF8String,GUTF8String> &incl)
Packit df99a1
{
Packit df99a1
  GUTF8String chkid;
Packit df99a1
  if (iff_in.get_chunk(chkid))
Packit df99a1
  {
Packit df99a1
    iff_out.put_chunk(chkid,true);
Packit df99a1
    if(!chkid.cmp("FORM:",5))
Packit df99a1
    {
Packit df99a1
      for(;iff_in.get_chunk(chkid);iff_in.close_chunk())
Packit df99a1
      {
Packit df99a1
        iff_out.put_chunk(chkid);
Packit df99a1
        if(chkid == "INCL")
Packit df99a1
        {
Packit df99a1
          GUTF8String incl_str;
Packit df99a1
          char buffer[1024];
Packit df99a1
          int length;
Packit df99a1
          while((length=iff_in.read(buffer, 1024)))
Packit df99a1
            incl_str+=GUTF8String(buffer, length);
Packit df99a1
          // Eat '\n' in the beginning and at the end
Packit df99a1
          while(incl_str.length() && incl_str[0]=='\n')
Packit df99a1
          {
Packit df99a1
            incl_str=incl_str.substr(1,(unsigned int)(-1));
Packit df99a1
          }
Packit df99a1
          while(incl_str.length()>0 && incl_str[(int)incl_str.length()-1]=='\n')
Packit df99a1
          {
Packit df99a1
            incl_str.setat(incl_str.length()-1, 0);
Packit df99a1
          }
Packit df99a1
          GPosition pos=incl.contains(incl_str);
Packit df99a1
          if(pos)
Packit df99a1
          { 
Packit df99a1
            iff_out.get_bytestream()->writestring(incl[pos]);
Packit df99a1
          }else
Packit df99a1
          {
Packit df99a1
            GP<DjVmDir::File> incl_file=dir.id_to_file(incl_str); 
Packit df99a1
            if(incl_file)
Packit df99a1
            {
Packit df99a1
              DEBUG_MSG("INCL '"<<(const char *)incl_file->get_save_name()<<"'\n");
Packit df99a1
              const GUTF8String incl_name=incl_file->get_save_name();
Packit df99a1
              incl[incl_str]=incl_name;
Packit df99a1
              iff_out.get_bytestream()->writestring(incl_name);
Packit df99a1
            }else
Packit df99a1
            {
Packit df99a1
              DEBUG_MSG("BOGUS INCL '"<<(const char *)incl_str<<"'\n");
Packit df99a1
              iff_out.copy(*iff_in.get_bytestream());
Packit df99a1
            }
Packit df99a1
          }
Packit df99a1
        }else
Packit df99a1
        {
Packit df99a1
          iff_out.copy(*iff_in.get_bytestream());
Packit df99a1
        }
Packit df99a1
        iff_out.close_chunk();
Packit df99a1
      }
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      iff_out.copy(*iff_in.get_bytestream());
Packit df99a1
    }
Packit df99a1
    iff_out.close_chunk();
Packit df99a1
    iff_in.close_chunk();
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
DjVmDoc::DjVmDoc(void)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::DjVmDoc(): Constructing empty DjVm document.\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::init(void)
Packit df99a1
{
Packit df99a1
  dir=DjVmDir::create();
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<DjVmDoc>
Packit df99a1
DjVmDoc::create(void)
Packit df99a1
{
Packit df99a1
  DjVmDoc *doc=new DjVmDoc();
Packit df99a1
  GP<DjVmDoc> retval=doc;
Packit df99a1
  doc->init();
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::insert_file(const GP<DjVmDir::File> & f,
Packit df99a1
		     GP<DataPool> data_pool, int pos)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::insert_file(): inserting file '" << f->get_load_name() <<
Packit df99a1
	     "' at pos " << pos << "\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
   if (!f)
Packit df99a1
     G_THROW( ERR_MSG("DjVmDoc.no_zero_file") );
Packit df99a1
   if (data.contains(f->get_load_name()))
Packit df99a1
     G_THROW( ERR_MSG("DjVmDoc.no_duplicate") );
Packit df99a1
Packit df99a1
   char buffer[4];
Packit df99a1
   if (data_pool->get_data(buffer, 0, 4)==4 && !memcmp(buffer, octets, 4))
Packit df99a1
   {
Packit df99a1
      data_pool=DataPool::create(data_pool, 4, -1);
Packit df99a1
   } 
Packit df99a1
   data[f->get_load_name()]=data_pool;
Packit df99a1
   dir->insert_file(f, pos);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::insert_file(
Packit df99a1
  ByteStream &data, DjVmDir::File::FILE_TYPE file_type,
Packit df99a1
  const GUTF8String &name, const GUTF8String &id, const GUTF8String &title,
Packit df99a1
  int pos)
Packit df99a1
{
Packit df99a1
   const GP<DjVmDir::File> file(
Packit df99a1
     DjVmDir::File::create(name, id, title, file_type));
Packit df99a1
   const GP<DataPool> pool(DataPool::create());
Packit df99a1
      // Cannot connect to a bytestream.
Packit df99a1
      // Must copy data into the datapool.
Packit df99a1
   int nbytes;
Packit df99a1
   char buffer[1024];
Packit df99a1
   while ((nbytes = data.read(buffer, sizeof(buffer))))
Packit df99a1
      pool->add_data(buffer, nbytes);
Packit df99a1
   pool->set_eof();
Packit df99a1
      // Call low level insert
Packit df99a1
   insert_file(file, pool, pos);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::insert_file(
Packit df99a1
  const GP<DataPool> &pool, DjVmDir::File::FILE_TYPE file_type,
Packit df99a1
  const GUTF8String &name, const GUTF8String &id, const GUTF8String &title,
Packit df99a1
  int pos)
Packit df99a1
{
Packit df99a1
   const GP<DjVmDir::File> file(
Packit df99a1
     DjVmDir::File::create(name, id, title, file_type));
Packit df99a1
      // Call low level insert
Packit df99a1
   insert_file(file, pool, pos);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::delete_file(const GUTF8String &id)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::delete_file(): deleting file '" << id << "'\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
   if (!data.contains(id))
Packit df99a1
      G_THROW(GUTF8String( ERR_MSG("DjVmDoc.cant_delete") "\t") + id);
Packit df99a1
   
Packit df99a1
   data.del(id);
Packit df99a1
   dir->delete_file(id);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
DjVmDoc::set_djvm_nav(GP<DjVmNav> n)
Packit df99a1
{
Packit df99a1
  if (n && ! n->isValidBookmark())
Packit df99a1
    G_THROW("Invalid bookmark data");
Packit df99a1
  nav = n;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<DataPool>
Packit df99a1
DjVmDoc::get_data(const GUTF8String &id) const
Packit df99a1
{
Packit df99a1
  GPosition pos;
Packit df99a1
  if (!data.contains(id, pos))
Packit df99a1
    G_THROW(GUTF8String( ERR_MSG("DjVmDoc.cant_find") "\t") + id);
Packit df99a1
  const GP<DataPool> pool(data[pos]);
Packit df99a1
   // First check that the file is in IFF format
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
    const GP<ByteStream> str_in(pool->get_stream());
Packit df99a1
    const GP<IFFByteStream> giff_in=IFFByteStream::create(str_in);
Packit df99a1
    IFFByteStream &iff_in=*giff_in;
Packit df99a1
    GUTF8String chkid;
Packit df99a1
    int size=iff_in.get_chunk(chkid);
Packit df99a1
    if (size<0 || size>0x7fffffff)
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.not_IFF") "\t" + id);
Packit df99a1
  }
Packit df99a1
  G_CATCH_ALL 
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("DjVmDoc.not_IFF") "\t" + id);
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
  return pool;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::write(const GP<ByteStream> &gstr)
Packit df99a1
{
Packit df99a1
  const GMap<GUTF8String,void *> reserved;
Packit df99a1
  write(gstr,reserved);
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline GUTF8String
Packit df99a1
get_name(const DjVmDir::File &file)
Packit df99a1
{
Packit df99a1
  const GUTF8String save_name(file.get_save_name());
Packit df99a1
  return save_name.length()?save_name:(file.get_load_name());
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::write(const GP<ByteStream> &gstr,
Packit df99a1
               const GMap<GUTF8String,void *> &reserved)
Packit df99a1
{
Packit df99a1
  DEBUG_MSG("DjVmDoc::write(): Storing document into the byte stream.\n");
Packit df99a1
  DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
  GPList<DjVmDir::File> files_list=dir->resolve_duplicates(true);
Packit df99a1
  bool do_rename=false;
Packit df99a1
  GPosition pos(reserved);
Packit df99a1
Packit df99a1
  GMap<GUTF8String,GUTF8String> incl;
Packit df99a1
  DEBUG_MSG("pass 1: looking for reserved names.");
Packit df99a1
  if(pos)
Packit df99a1
  {
Packit df99a1
      // Check if there are any conflicting file names.
Packit df99a1
    for(pos=files_list;pos;++pos)
Packit df99a1
    {
Packit df99a1
      GP<DjVmDir::File> file=files_list[pos];
Packit df99a1
      if((do_rename=(reserved.contains(file->get_load_name())?true:false))
Packit df99a1
		  ||(do_rename=(reserved.contains(file->get_save_name())?true:false)))
Packit df99a1
      {
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    // If there are conflicting file names, check if the save names
Packit df99a1
    // are OK.  If not, generate new save names.
Packit df99a1
    if(do_rename)
Packit df99a1
    {
Packit df99a1
      DEBUG_MSG("pass 1: renaming reserved names.");
Packit df99a1
      for(;;files_list=dir->resolve_duplicates(true))
Packit df99a1
      {
Packit df99a1
        GMap<GUTF8String,void *> this_doc;
Packit df99a1
        for(pos=files_list;pos;++pos)
Packit df99a1
        {
Packit df99a1
          GP<DjVmDir::File> file=files_list[pos];
Packit df99a1
          this_doc[::get_name(*file)]=0;
Packit df99a1
        }
Packit df99a1
        bool need_new_list=false;
Packit df99a1
        for(pos=files_list;pos;++pos)
Packit df99a1
        {
Packit df99a1
          GP<DjVmDir::File> file=files_list[pos];
Packit df99a1
          const GUTF8String name(::get_name(*file));
Packit df99a1
          if(reserved.contains(name))
Packit df99a1
          {
Packit df99a1
            GUTF8String new_name;
Packit df99a1
            int series=0;
Packit df99a1
            do
Packit df99a1
            {
Packit df99a1
              int dot=name.rsearch('.');
Packit df99a1
              if(dot>0)
Packit df99a1
              {
Packit df99a1
                new_name=name.substr(0,dot)+
Packit df99a1
                  "_"+GUTF8String(++series)+name.substr(dot,-1);
Packit df99a1
              }else
Packit df99a1
              {
Packit df99a1
                new_name=name+"_"+GUTF8String(++series);
Packit df99a1
              }
Packit df99a1
            } while(reserved.contains(new_name)||this_doc.contains(new_name));
Packit df99a1
            dir->set_file_name(file->get_load_name(),new_name);
Packit df99a1
            need_new_list=true;
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
        if(!need_new_list)
Packit df99a1
          break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  DEBUG_MSG("pass 2: create dummy DIRM chunk and calculate offsets...\n");
Packit df99a1
  for(pos=files_list;pos;++pos)
Packit df99a1
  {
Packit df99a1
    GP<DjVmDir::File> file=files_list[pos];
Packit df99a1
    file->offset=0xffffffff;
Packit df99a1
    GPosition data_pos=data.contains(file->get_load_name());
Packit df99a1
    if (!data_pos)
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.no_data") "\t" + file->get_load_name());
Packit df99a1
    if(do_rename)
Packit df99a1
    {
Packit df99a1
      GP<ByteStream> gout(ByteStream::create());
Packit df99a1
      {
Packit df99a1
        const GP<IFFByteStream> giff_in(
Packit df99a1
          IFFByteStream::create(data[data_pos]->get_stream()));
Packit df99a1
        const GP<IFFByteStream> giff_out(IFFByteStream::create(gout));
Packit df99a1
        ::save_file(*giff_in,*giff_out,*dir,incl);
Packit df99a1
      }
Packit df99a1
      gout->seek(0L);
Packit df99a1
      data[data_pos]=DataPool::create(gout);
Packit df99a1
    }
Packit df99a1
    file->size=data[data_pos]->get_length();
Packit df99a1
    if (!file->size)
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.zero_file") );
Packit df99a1
  }
Packit df99a1
   
Packit df99a1
  const GP<ByteStream> tmp_str(ByteStream::create());
Packit df99a1
  const GP<IFFByteStream> gtmp_iff(IFFByteStream::create(tmp_str));
Packit df99a1
  IFFByteStream &tmp_iff=*gtmp_iff;
Packit df99a1
  tmp_iff.put_chunk("FORM:DJVM", 1);
Packit df99a1
  tmp_iff.put_chunk("DIRM");
Packit df99a1
  dir->encode(tmp_iff.get_bytestream(),do_rename);
Packit df99a1
  tmp_iff.close_chunk();
Packit df99a1
  if (nav)
Packit df99a1
    {
Packit df99a1
      tmp_iff.put_chunk("NAVM");
Packit df99a1
      nav->encode(tmp_iff.get_bytestream());
Packit df99a1
      tmp_iff.close_chunk();
Packit df99a1
    }
Packit df99a1
  tmp_iff.close_chunk();
Packit df99a1
  int offset=tmp_iff.tell();
Packit df99a1
Packit df99a1
  for(pos=files_list;pos;++pos)
Packit df99a1
  {
Packit df99a1
    if ((offset & 1)!=0)
Packit df99a1
      offset++;
Packit df99a1
      
Packit df99a1
    GP<DjVmDir::File> & file=files_list[pos];
Packit df99a1
    file->offset=offset;
Packit df99a1
    offset+=file->size;	// file->size has been set in the first pass
Packit df99a1
  }
Packit df99a1
Packit df99a1
  DEBUG_MSG("pass 3: store the file contents.\n");
Packit df99a1
Packit df99a1
  GP<IFFByteStream> giff=IFFByteStream::create(gstr);
Packit df99a1
  IFFByteStream &iff=*giff;
Packit df99a1
  iff.put_chunk("FORM:DJVM", 1);
Packit df99a1
  iff.put_chunk("DIRM");
Packit df99a1
  dir->encode(iff.get_bytestream(),do_rename);
Packit df99a1
  iff.close_chunk();
Packit df99a1
  if (nav)
Packit df99a1
    {
Packit df99a1
      iff.put_chunk("NAVM");
Packit df99a1
      nav->encode(iff.get_bytestream());
Packit df99a1
      iff.close_chunk();
Packit df99a1
    }
Packit df99a1
Packit df99a1
  for(pos=files_list;pos;++pos)
Packit df99a1
  {
Packit df99a1
    GP<DjVmDir::File> & file=files_list[pos];
Packit df99a1
Packit df99a1
    const GP<DataPool> pool=get_data(file->get_load_name());
Packit df99a1
    const GP<ByteStream> str_in(pool->get_stream());
Packit df99a1
    if ((iff.tell() & 1)!=0)
Packit df99a1
    {
Packit df99a1
      iff.get_bytestream()->write8(0);
Packit df99a1
    }
Packit df99a1
    iff.copy(*str_in);
Packit df99a1
  }
Packit df99a1
Packit df99a1
  iff.close_chunk();
Packit df99a1
  iff.flush();
Packit df99a1
Packit df99a1
  DEBUG_MSG("done storing DjVm file.\n");
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::read(const GP<DataPool> & pool)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::read(): reading the BUNDLED doc contents from the pool\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
   
Packit df99a1
   const GP<ByteStream> str(pool->get_stream());
Packit df99a1
   
Packit df99a1
   GP<IFFByteStream> giff=IFFByteStream::create(str);
Packit df99a1
   IFFByteStream &iff=*giff;
Packit df99a1
   GUTF8String chkid;
Packit df99a1
   iff.get_chunk(chkid);
Packit df99a1
   if (chkid!="FORM:DJVM")
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.no_form_djvm") );
Packit df99a1
Packit df99a1
   iff.get_chunk(chkid);
Packit df99a1
   if (chkid!="DIRM")
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.no_dirm_chunk") );
Packit df99a1
   dir->decode(iff.get_bytestream());
Packit df99a1
   iff.close_chunk();
Packit df99a1
Packit df99a1
   data.empty();
Packit df99a1
Packit df99a1
   if (dir->is_indirect())
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.cant_read_indr") );
Packit df99a1
Packit df99a1
   GPList<DjVmDir::File> files_list=dir->get_files_list();
Packit df99a1
   for(GPosition pos=files_list;pos;++pos)
Packit df99a1
   {
Packit df99a1
      DjVmDir::File * f=files_list[pos];
Packit df99a1
      
Packit df99a1
      DEBUG_MSG("reading contents of file '" << f->get_load_name() << "'\n");
Packit df99a1
      data[f->get_load_name()]=DataPool::create(pool, f->offset, f->size);
Packit df99a1
   }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::read(ByteStream & str_in)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::read(): reading the BUNDLED doc contents from the stream\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
   GP<DataPool> pool=DataPool::create();
Packit df99a1
   char buffer[1024];
Packit df99a1
   int length;
Packit df99a1
   while((length=str_in.read(buffer, 1024)))
Packit df99a1
      pool->add_data(buffer, length);
Packit df99a1
   pool->set_eof();
Packit df99a1
Packit df99a1
   read(pool);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::read(const GURL &url)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::read(): reading the doc contents from the HDD\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
   GP<DataPool> pool=DataPool::create(url);
Packit df99a1
   const GP<ByteStream> str(pool->get_stream());
Packit df99a1
   GP<IFFByteStream> giff=IFFByteStream::create(str);
Packit df99a1
   IFFByteStream &iff=*giff;
Packit df99a1
   GUTF8String chkid;
Packit df99a1
   iff.get_chunk(chkid);
Packit df99a1
   if (chkid!="FORM:DJVM")
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.no_form_djvm2") );
Packit df99a1
Packit df99a1
   iff.get_chunk(chkid);
Packit df99a1
   if (chkid!="DIRM")
Packit df99a1
      G_THROW( ERR_MSG("DjVmDoc.no_dirm_chunk") );
Packit df99a1
   dir->decode(iff.get_bytestream());
Packit df99a1
   iff.close_chunk();
Packit df99a1
Packit df99a1
   if (dir->is_bundled())
Packit df99a1
     read(pool);
Packit df99a1
   else
Packit df99a1
   {
Packit df99a1
//      GUTF8String full_name=GOS::expand_name(name);
Packit df99a1
//      GUTF8String dir_name=GOS::dirname(GOS::url_to_filename(url.base()));
Packit df99a1
      GURL dirbase=url.base();
Packit df99a1
Packit df99a1
      data.empty();
Packit df99a1
Packit df99a1
      GPList<DjVmDir::File> files_list=dir->get_files_list();
Packit df99a1
      for(GPosition pos=files_list;pos;++pos)
Packit df99a1
      {
Packit df99a1
	 DjVmDir::File * f=files_list[pos];
Packit df99a1
      
Packit df99a1
	 DEBUG_MSG("reading contents of file '" << f->get_load_name() << "'\n");
Packit df99a1
Packit df99a1
         const GURL::UTF8 url(f->get_load_name(),dirbase);
Packit df99a1
	 data[f->get_load_name()]=DataPool::create(url);
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::write_index(const GP<ByteStream> &str)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::write_index(): Storing DjVm index file\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
   GPList<DjVmDir::File> files_list=dir->get_files_list();
Packit df99a1
   for(GPosition pos=files_list;pos;++pos)
Packit df99a1
   {
Packit df99a1
      GP<DjVmDir::File> file=files_list[pos];
Packit df99a1
      file->offset=0;
Packit df99a1
Packit df99a1
      GPosition data_pos=data.contains(file->get_load_name());
Packit df99a1
      if (!data_pos)
Packit df99a1
	G_THROW( ERR_MSG("DjVmDoc.no_data") "\t" + file->get_load_name());
Packit df99a1
      file->size=data[data_pos]->get_length();
Packit df99a1
      if (!file->size)
Packit df99a1
        G_THROW( ERR_MSG("DjVmDoc.zero_file") );
Packit df99a1
   }
Packit df99a1
Packit df99a1
   GP<IFFByteStream> giff=IFFByteStream::create(str);
Packit df99a1
   IFFByteStream &iff=*giff;
Packit df99a1
   iff.put_chunk("FORM:DJVM", 1);
Packit df99a1
   iff.put_chunk("DIRM");
Packit df99a1
   dir->encode(iff.get_bytestream());
Packit df99a1
   iff.close_chunk();
Packit df99a1
   if (nav)
Packit df99a1
     {
Packit df99a1
       iff.put_chunk("NAVM");
Packit df99a1
       nav->encode(iff.get_bytestream());
Packit df99a1
       iff.close_chunk();
Packit df99a1
     }
Packit df99a1
   iff.close_chunk();
Packit df99a1
   iff.flush();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::save_page(
Packit df99a1
  const GURL &codebase, const DjVmDir::File &file) const
Packit df99a1
{
Packit df99a1
  GMap<GUTF8String,GUTF8String> incl;
Packit df99a1
  save_file(codebase,file,&incl;;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::save_page(
Packit df99a1
  const GURL &codebase, const DjVmDir::File &file,
Packit df99a1
  GMap<GUTF8String,GUTF8String> &incl ) const
Packit df99a1
{
Packit df99a1
  save_file(codebase,file,&incl;;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::save_file(
Packit df99a1
  const GURL &codebase, const DjVmDir::File &file) const
Packit df99a1
{
Packit df99a1
  save_file(codebase,file,0);
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String 
Packit df99a1
DjVmDoc::save_file(const GURL &codebase, const DjVmDir::File &file,
Packit df99a1
  GMap<GUTF8String,GUTF8String> &incl, const GP<DataPool> &pool) const
Packit df99a1
{
Packit df99a1
  const GUTF8String save_name(file.get_save_name());
Packit df99a1
  const GURL::UTF8 new_url(save_name,codebase);
Packit df99a1
  DEBUG_MSG("storing file '"<
Packit df99a1
  DataPool::load_file(new_url);
Packit df99a1
  const GP<ByteStream> str_in(pool->get_stream());
Packit df99a1
  const GP<ByteStream> str_out(ByteStream::create(new_url, "wb"));
Packit df99a1
  ::save_file( *IFFByteStream::create(str_in),
Packit df99a1
      *IFFByteStream::create(str_out), *dir, incl);
Packit df99a1
  return save_name;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::save_file(
Packit df99a1
  const GURL &codebase, const DjVmDir::File &file,
Packit df99a1
  GMap<GUTF8String,GUTF8String> *incl) const
Packit df99a1
{
Packit df99a1
  const GUTF8String load_name=file.get_load_name();
Packit df99a1
  if(!incl || !incl->contains(load_name))
Packit df99a1
  {
Packit df99a1
    GMap<GUTF8String,GUTF8String> new_incl;
Packit df99a1
    const GUTF8String save_name(
Packit df99a1
      save_file(codebase,file,new_incl,get_data(load_name)));
Packit df99a1
Packit df99a1
    if(incl)
Packit df99a1
    {
Packit df99a1
      (*incl)[load_name]=save_name;
Packit df99a1
      for(GPosition pos=new_incl;pos;++pos)
Packit df99a1
      {
Packit df99a1
        save_file(codebase,file,incl);
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVmDoc::expand(const GURL &codebase, const GUTF8String &idx_name)
Packit df99a1
{
Packit df99a1
   DEBUG_MSG("DjVmDoc::expand(): Expanding into '" << codebase << "'\n");
Packit df99a1
   DEBUG_MAKE_INDENT(3);
Packit df99a1
Packit df99a1
   // Resolve any name conflicts
Packit df99a1
   // Find the list of all files.
Packit df99a1
   GPList<DjVmDir::File> files_list=dir->resolve_duplicates(false);
Packit df99a1
Packit df99a1
      // store each file
Packit df99a1
   for(GPosition pos=files_list;pos;++pos)
Packit df99a1
   {
Packit df99a1
     save_file(codebase,*files_list[pos]);
Packit df99a1
   }
Packit df99a1
Packit df99a1
   if (idx_name.length())
Packit df99a1
   {
Packit df99a1
      const GURL::UTF8 idx_url(idx_name, codebase);
Packit df99a1
   
Packit df99a1
      DEBUG_MSG("storing index file '" << idx_url << "'\n");
Packit df99a1
Packit df99a1
      DataPool::load_file(idx_url);
Packit df99a1
      GP<ByteStream> str=ByteStream::create(idx_url, "wb");
Packit df99a1
      write_index(str);
Packit df99a1
   }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif