|
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 |
|
|
Packit |
df99a1 |
#include "IW44Image.h"
|
|
Packit |
df99a1 |
#include "GOS.h"
|
|
Packit |
df99a1 |
#include "GString.h"
|
|
Packit |
df99a1 |
#include "DjVuDocEditor.h"
|
|
Packit |
df99a1 |
#include "DjVuDumpHelper.h"
|
|
Packit |
df99a1 |
#include "BSByteStream.h"
|
|
Packit |
df99a1 |
#include "DjVuText.h"
|
|
Packit |
df99a1 |
#include "DjVuAnno.h"
|
|
Packit |
df99a1 |
#include "DjVuInfo.h"
|
|
Packit |
df99a1 |
#include "IFFByteStream.h"
|
|
Packit |
df99a1 |
#include "DataPool.h"
|
|
Packit |
df99a1 |
#include "DjVuPort.h"
|
|
Packit |
df99a1 |
#include "DjVuFile.h"
|
|
Packit |
df99a1 |
#include "DjVmNav.h"
|
|
Packit |
df99a1 |
#include "common.h"
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool modified = false;
|
|
Packit |
df99a1 |
static bool verbose = false;
|
|
Packit |
df99a1 |
static bool save = false;
|
|
Packit |
df99a1 |
static bool nosave = false;
|
|
Packit |
df99a1 |
static bool utf8 = false;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static unsigned char utf8bom[] = { 0xef, 0xbb, 0xbf };
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
struct DJVUSEDGlobal
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Globals that need static initialization
|
|
Packit |
df99a1 |
// are grouped here to work around broken compilers.
|
|
Packit |
df99a1 |
GUTF8String djvufile;
|
|
Packit |
df99a1 |
GP<ByteStream> cmdbs;
|
|
Packit |
df99a1 |
GP<DjVuDocEditor> doc;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> selected;
|
|
Packit |
df99a1 |
GP<DjVuFile> file;
|
|
Packit |
df99a1 |
GUTF8String fileid;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static DJVUSEDGlobal& g(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static DJVUSEDGlobal g;
|
|
Packit |
df99a1 |
return g;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static GUTF8String
|
|
Packit |
df99a1 |
ToNative(GUTF8String s)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (utf8)
|
|
Packit |
df99a1 |
return s;
|
|
Packit |
df99a1 |
// fake the damn GUTF8/GNative type check
|
|
Packit |
df99a1 |
GNativeString n = s;
|
|
Packit |
df99a1 |
return GUTF8String((const char*)n);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
// PARSING BYTESTREAM
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// -- A bytestream that performs buffering and
|
|
Packit |
df99a1 |
// offers a stdio-like interface for reading files.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class ParsingByteStream : public ByteStream
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
private:
|
|
Packit |
df99a1 |
enum { bufsize=512 };
|
|
Packit |
df99a1 |
const GP<ByteStream> &gbs;
|
|
Packit |
df99a1 |
ByteStream &bs;
|
|
Packit |
df99a1 |
unsigned char buffer[bufsize];
|
|
Packit |
df99a1 |
int bufpos;
|
|
Packit |
df99a1 |
int bufend;
|
|
Packit |
df99a1 |
bool goteof;
|
|
Packit |
df99a1 |
ParsingByteStream(const GP<ByteStream> &gbs;;
|
|
Packit |
df99a1 |
int getbom(int c);
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
static GP<ParsingByteStream> create(const GP<ByteStream> &gbs)
|
|
Packit |
df99a1 |
{ return new ParsingByteStream(gbs); }
|
|
Packit |
df99a1 |
size_t read(void *buffer, size_t size);
|
|
Packit |
df99a1 |
size_t write(const void *buffer, size_t size);
|
|
Packit |
df99a1 |
long int tell() const;
|
|
Packit |
df99a1 |
int eof();
|
|
Packit |
df99a1 |
int unget(int c);
|
|
Packit |
df99a1 |
inline int get();
|
|
Packit |
df99a1 |
int get_spaces(bool skipseparator=false);
|
|
Packit |
df99a1 |
GUTF8String get_token(bool skipseparator=false, bool compat=false);
|
|
Packit |
df99a1 |
const char *get_error_context(int c=EOF);
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
ParsingByteStream::ParsingByteStream(const GP<ByteStream> &xgbs)
|
|
Packit |
df99a1 |
: gbs(xgbs),bs(*gbs), bufpos(1), bufend(1), goteof(false)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
ParsingByteStream::eof() // aka. feof
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (bufpos < bufend)
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
if (goteof)
|
|
Packit |
df99a1 |
return true;
|
|
Packit |
df99a1 |
bufend = bufpos = 1;
|
|
Packit |
df99a1 |
while (bs.read(buffer+bufend,1) && ++bufend<(int)bufsize)
|
|
Packit |
df99a1 |
if (buffer[bufend-1]=='\r' || buffer[bufend-1]=='\n')
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
if (bufend == bufpos)
|
|
Packit |
df99a1 |
goteof = true;
|
|
Packit |
df99a1 |
return goteof;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
size_t
|
|
Packit |
df99a1 |
ParsingByteStream::read(void *buf, size_t size)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (size < 1)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
if (bufend == bufpos)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (size >= bufsize)
|
|
Packit |
df99a1 |
return bs.read(buf, size);
|
|
Packit |
df99a1 |
if (eof())
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (bufpos + (int)size > bufend)
|
|
Packit |
df99a1 |
size = bufend - bufpos;
|
|
Packit |
df99a1 |
memcpy(buf, buffer+bufpos, size);
|
|
Packit |
df99a1 |
bufpos += size;
|
|
Packit |
df99a1 |
return size;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
size_t
|
|
Packit |
df99a1 |
ParsingByteStream::write(const void *, size_t )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
G_THROW("Cannot write() into a ParsingByteStream");
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
long int
|
|
Packit |
df99a1 |
ParsingByteStream::tell() const
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
G_THROW("Cannot tell() a ParsingByteStream");
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
ParsingByteStream::getbom(int c)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int i = 0;
|
|
Packit |
df99a1 |
while (c == utf8bom[i++])
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (i >= 3)
|
|
Packit |
df99a1 |
i = 0;
|
|
Packit |
df99a1 |
if (bufpos < bufend || !eof())
|
|
Packit |
df99a1 |
c = buffer[bufpos++];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
while (--i > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
unget(c);
|
|
Packit |
df99a1 |
c = utf8bom[i-1];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return c;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
inline int
|
|
Packit |
df99a1 |
ParsingByteStream::get() // like getc() skipping bom.
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int c = EOF;
|
|
Packit |
df99a1 |
if (bufpos < bufend || !eof())
|
|
Packit |
df99a1 |
c = buffer[bufpos++];
|
|
Packit |
df99a1 |
if (c == utf8bom[0])
|
|
Packit |
df99a1 |
return getbom(c);
|
|
Packit |
df99a1 |
return c;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
ParsingByteStream::unget(int c) // like ungetc()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (bufpos > 0 && c != EOF)
|
|
Packit |
df99a1 |
return buffer[--bufpos] = (unsigned char)c;
|
|
Packit |
df99a1 |
return EOF;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
ParsingByteStream::get_spaces(bool skipseparator)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int c = get();
|
|
Packit |
df99a1 |
while (c==' ' || c=='\t' || c=='\r'
|
|
Packit |
df99a1 |
|| c=='\n' || c=='#' || c==';' )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (c == '#')
|
|
Packit |
df99a1 |
do { c=get(); } while (c!=EOF && c!='\n' && c!='\r');
|
|
Packit |
df99a1 |
if (!skipseparator && (c=='\n' || c=='\r' || c==';'))
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return c;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
const char *
|
|
Packit |
df99a1 |
ParsingByteStream::get_error_context(int c)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static char buffer[22];
|
|
Packit |
df99a1 |
unget(c);
|
|
Packit |
df99a1 |
int len = read((void*)buffer, sizeof(buffer)-1);
|
|
Packit |
df99a1 |
buffer[(len>0)?len:0] = 0;
|
|
Packit |
df99a1 |
for (int i=0; i
|
|
Packit |
df99a1 |
if (buffer[i]=='\n')
|
|
Packit |
df99a1 |
buffer[i] = 0;
|
|
Packit |
df99a1 |
return buffer;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GUTF8String
|
|
Packit |
df99a1 |
ParsingByteStream::get_token(bool skipseparator, bool compat)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String str;
|
|
Packit |
df99a1 |
int c = get_spaces(skipseparator);
|
|
Packit |
df99a1 |
if (c == EOF)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
return str;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (!skipseparator && (c=='\n' || c=='\r' || c==';'))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
unget(c);
|
|
Packit |
df99a1 |
return str;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (c != '\"' && c != '\'')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (c!=' ' && c!='\t' && c!='\r' && c!=';'
|
|
Packit |
df99a1 |
&& c!='\n' && c!='#' && c!=EOF)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
str += c;
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
unget(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int delim = c;
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
while (c != delim && c!=EOF)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (c == '\\')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
if (compat && c!='\"')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
str += '\\';
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (c>='0' && c<='7')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int x = 0;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=0; i<3 && c>='0' && c<='7'; i++)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
x = x * 8 + c - '0';
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
unget(c);
|
|
Packit |
df99a1 |
c = x;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *tr1 = "tnrbfva";
|
|
Packit |
df99a1 |
const char *tr2 = "\t\n\r\b\f\013\007";
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=0; tr1[i]; i++)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (c == tr1[i])
|
|
Packit |
df99a1 |
c = tr2[i];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (c != EOF)
|
|
Packit |
df99a1 |
str += c;
|
|
Packit |
df99a1 |
c = get();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return str;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
// COMMANDS
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
vprint(const char *fmt, ... )
|
|
Packit |
df99a1 |
#ifdef __GNUC__
|
|
Packit |
df99a1 |
__attribute__ ((format (printf, 1, 2)));
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
vprint(const char *fmt, ... )
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (verbose)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String msg("");
|
|
Packit |
df99a1 |
va_list args;
|
|
Packit |
df99a1 |
va_start(args, fmt);
|
|
Packit |
df99a1 |
msg.vformat(fmt, args);
|
|
Packit |
df99a1 |
fprintf(stderr,"djvused: %s\n", (const char*)ToNative(msg));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
verror(const char *fmt, ... )
|
|
Packit |
df99a1 |
#ifdef __GNUC__
|
|
Packit |
df99a1 |
__attribute__ ((format (printf, 1, 2)));
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
verror(const char *fmt, ... )
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String msg;
|
|
Packit |
df99a1 |
va_list args;
|
|
Packit |
df99a1 |
va_start(args, fmt);
|
|
Packit |
df99a1 |
msg.vformat(fmt, args);
|
|
Packit |
df99a1 |
G_THROW((const char*)ToNative(msg));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
get_data_from_file(const char *cmd, ParsingByteStream &pbs, ByteStream &out)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("%s: enter data and terminate with a period on a single line", cmd);
|
|
Packit |
df99a1 |
int c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
char skip[4];
|
|
Packit |
df99a1 |
char term0[4] = "\n.\n";
|
|
Packit |
df99a1 |
char term1[4] = "\r.\r";
|
|
Packit |
df99a1 |
char *s = skip;
|
|
Packit |
df99a1 |
int state = 1;
|
|
Packit |
df99a1 |
while (state < 3)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
c = pbs.get();
|
|
Packit |
df99a1 |
if (c == EOF)
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
if ( c == term0[state] || c == term1[state] )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
state += 1;
|
|
Packit |
df99a1 |
*s++ = c;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (char *m=skip; m
|
|
Packit |
df99a1 |
out.write8(*m);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
s = skip;
|
|
Packit |
df99a1 |
state = 0;
|
|
Packit |
df99a1 |
if (c == '\n')
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
else if (c != EOF)
|
|
Packit |
df99a1 |
out.write8(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> in=ByteStream::create(GURL::Filename::UTF8(fname),"rb");
|
|
Packit |
df99a1 |
out.copy(*in);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
char_unquoted(unsigned char c, bool eightbit)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (eightbit && c>=0x80)
|
|
Packit |
df99a1 |
return true;
|
|
Packit |
df99a1 |
if (c==0x7f || c=='\"' || c=='\\')
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
if (c>=0x20 && c<0x7f)
|
|
Packit |
df99a1 |
return true;
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
print_c_string(const char *data, int length, ByteStream &out, bool eightbit)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out.write("\"",1);
|
|
Packit |
df99a1 |
while (*data && length>0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int span = 0;
|
|
Packit |
df99a1 |
while (span
|
|
Packit |
df99a1 |
span++;
|
|
Packit |
df99a1 |
if (span > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out.write(data, span);
|
|
Packit |
df99a1 |
data += span;
|
|
Packit |
df99a1 |
length -= span;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
char buf[5];
|
|
Packit |
df99a1 |
static const char *tr1 = "\"\\tnrbf";
|
|
Packit |
df99a1 |
static const char *tr2 = "\"\\\t\n\r\b\f";
|
|
Packit |
df99a1 |
sprintf(buf,"\\%03o", (int)(((unsigned char*)data)[0]));
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=0; tr2[i]; i++)
|
|
Packit |
df99a1 |
if (*(char*)data == tr2[i])
|
|
Packit |
df99a1 |
buf[1] = tr1[i];
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (buf[1]<'0' || buf[1]>'3')
|
|
Packit |
df99a1 |
buf[2] = 0;
|
|
Packit |
df99a1 |
out.write(buf, ((buf[2]) ? 4 : 2));
|
|
Packit |
df99a1 |
data += 1;
|
|
Packit |
df99a1 |
length -= 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
out.write("\"",1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_ls(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pagenum = 0;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> lst = g().doc->get_djvm_dir()->get_files_list();
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> f = lst[p];
|
|
Packit |
df99a1 |
if (f->is_page())
|
|
Packit |
df99a1 |
fprintf(stdout,"%4d P ", ++pagenum);
|
|
Packit |
df99a1 |
else if (f->is_include())
|
|
Packit |
df99a1 |
fprintf(stdout," I ");
|
|
Packit |
df99a1 |
else if (f->is_thumbnails())
|
|
Packit |
df99a1 |
continue;
|
|
Packit |
df99a1 |
else if (f->is_shared_anno())
|
|
Packit |
df99a1 |
fprintf(stdout," A ");
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
fprintf(stdout," ? ");
|
|
Packit |
df99a1 |
GUTF8String id = f->get_load_name();
|
|
Packit |
df99a1 |
fprintf(stdout,"%8d %s", f->size, (const char*)ToNative(id));
|
|
Packit |
df99a1 |
GUTF8String name = f->get_save_name();
|
|
Packit |
df99a1 |
if (name != id)
|
|
Packit |
df99a1 |
fprintf(stdout," F=%s", (const char*)ToNative(name));
|
|
Packit |
df99a1 |
GUTF8String title = f->get_title();
|
|
Packit |
df99a1 |
if (title != id && f->is_page())
|
|
Packit |
df99a1 |
fprintf(stdout," T=%s", (const char*)ToNative(title));
|
|
Packit |
df99a1 |
fprintf(stdout,"\n");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (g().doc->get_thumbnails_num() == g().doc->get_pages_num())
|
|
Packit |
df99a1 |
fprintf(stdout," T %8s %s\n", "", "<thumbnails>");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_n(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pagenum = 0;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> lst = g().doc->get_djvm_dir()->get_files_list();
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> f = lst[p];
|
|
Packit |
df99a1 |
if (f->is_page())
|
|
Packit |
df99a1 |
++pagenum;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
fprintf(stdout,"%d\n", pagenum);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_dump(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DataPool> pool;
|
|
Packit |
df99a1 |
// Need to be modified to handle "selected" list.
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
pool = g().file->get_djvu_data(false, false);
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
pool = g().doc->get_init_data_pool();
|
|
Packit |
df99a1 |
DjVuDumpHelper helper;
|
|
Packit |
df99a1 |
GP<ByteStream> bs = helper.dump(pool);
|
|
Packit |
df99a1 |
size_t size = bs->size();
|
|
Packit |
df99a1 |
GUTF8String str;
|
|
Packit |
df99a1 |
char *buf = str.getbuf(size);
|
|
Packit |
df99a1 |
bs->seek(0);
|
|
Packit |
df99a1 |
bs->readall(buf, size);
|
|
Packit |
df99a1 |
GUTF8String ns = ToNative(str);
|
|
Packit |
df99a1 |
GP<ByteStream> obs=ByteStream::create("w");
|
|
Packit |
df99a1 |
obs->writall((const char*)ns, ns.length());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
print_size(const GP<DjVuFile> &file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVuInfo> info = file->info;
|
|
Packit |
df99a1 |
if (! info)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> pbs(file->get_djvu_bytestream(false, false));
|
|
Packit |
df99a1 |
const GP<IFFByteStream> iff(IFFByteStream::create(pbs));
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
if (! iff->get_chunk(chkid))
|
|
Packit |
df99a1 |
verror("Selected file contains no data");
|
|
Packit |
df99a1 |
if (chkid == "FORM:DJVU")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (iff->get_chunk(chkid) && chkid!="INFO")
|
|
Packit |
df99a1 |
iff->close_chunk();
|
|
Packit |
df99a1 |
if (chkid == "INFO")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
info = DjVuInfo::create();
|
|
Packit |
df99a1 |
info->decode(*iff->get_bytestream());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (chkid == "FORM:BM44" || chkid == "FORM:PM44")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (iff->get_chunk(chkid) && chkid!="BM44" && chkid!="PM44")
|
|
Packit |
df99a1 |
iff->close_chunk();
|
|
Packit |
df99a1 |
if (chkid=="BM44" || chkid=="PM44")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<IW44Image> junk=IW44Image::create_decode(IW44Image::COLOR);
|
|
Packit |
df99a1 |
junk->decode_chunk(iff->get_bytestream());
|
|
Packit |
df99a1 |
fprintf(stdout,"width=%d height=%d\n",
|
|
Packit |
df99a1 |
junk->get_width(), junk->get_height());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (info)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
fprintf(stdout,"width=%d height=%d", info->width, info->height);
|
|
Packit |
df99a1 |
if (info->orientation)
|
|
Packit |
df99a1 |
fprintf(stdout, " rotation=%d", info->orientation);
|
|
Packit |
df99a1 |
fprintf(stdout,"\n");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_size(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (lst[p]->is_page())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fileid = g().doc->page_to_id(lst[p]->get_page_num());
|
|
Packit |
df99a1 |
const GP<DjVuFile> f = g().doc->get_djvu_file(fileid);
|
|
Packit |
df99a1 |
print_size(f);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
select_all(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().file = 0;
|
|
Packit |
df99a1 |
g().fileid = "";
|
|
Packit |
df99a1 |
g().selected = g().doc->get_djvm_dir()->get_files_list();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
select_clear(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().file = 0;
|
|
Packit |
df99a1 |
g().fileid = "<all>";
|
|
Packit |
df99a1 |
g().selected.empty();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
select_add(GP<DjVmDir::File> frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPosition selp = g().selected;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> all = g().doc->get_djvm_dir()->get_files_list();
|
|
Packit |
df99a1 |
GPosition allp = all;
|
|
Packit |
df99a1 |
while (allp)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (all[allp] == frec)
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
if ( selp && all[allp] == g().selected[selp])
|
|
Packit |
df99a1 |
++ selp;
|
|
Packit |
df99a1 |
++ allp;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (allp && (!selp || all[allp] != g().selected[selp]))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().selected.insert_before(selp, frec);
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().fileid = frec->get_load_name();
|
|
Packit |
df99a1 |
g().file = g().doc->get_djvu_file(g().fileid);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().fileid = "<multiple>";
|
|
Packit |
df99a1 |
g().file = 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_select(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String pagid = pbs.get_token();
|
|
Packit |
df99a1 |
// Case of NULL
|
|
Packit |
df99a1 |
if (pagid == "")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
select_all();
|
|
Packit |
df99a1 |
vprint("select: selecting entire document");
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Case of a single page number
|
|
Packit |
df99a1 |
if (pagid.is_int())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pageno = atoi(pagid);
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->page_to_file(pageno-1);
|
|
Packit |
df99a1 |
if (!frec)
|
|
Packit |
df99a1 |
verror("page \"%d\" not found", pageno);
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
vprint("select: selecting \"%s\"", (const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Case of a single file id
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->id_to_file(pagid);
|
|
Packit |
df99a1 |
if (!frec)
|
|
Packit |
df99a1 |
frec = g().doc->get_djvm_dir()->name_to_file(pagid);
|
|
Packit |
df99a1 |
if (!frec)
|
|
Packit |
df99a1 |
frec = g().doc->get_djvm_dir()->title_to_file(pagid);
|
|
Packit |
df99a1 |
if (!frec)
|
|
Packit |
df99a1 |
verror("page \"%s\" not found", (const char*)ToNative(pagid));
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
vprint("select: selecting \"%s\"", (const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_select_shared_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (! frec)
|
|
Packit |
df99a1 |
verror("select-shared-ant: no shared annotation file");
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
vprint("select-shared-ant: selecting shared annotation");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_create_shared_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (! frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("create-shared-ant: creating shared annotation file");
|
|
Packit |
df99a1 |
g().doc->create_shared_anno_file();
|
|
Packit |
df99a1 |
frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (!frec) G_THROW("internal error");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
vprint("select-shared-ant: selecting shared annotation");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_showsel(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pagenum = 0;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> f = lst[p];
|
|
Packit |
df99a1 |
if (f->is_page())
|
|
Packit |
df99a1 |
fprintf(stdout,"%4d P ", ++pagenum);
|
|
Packit |
df99a1 |
else if (f->is_include())
|
|
Packit |
df99a1 |
fprintf(stdout," I ");
|
|
Packit |
df99a1 |
else if (f->is_thumbnails())
|
|
Packit |
df99a1 |
fprintf(stdout," T ");
|
|
Packit |
df99a1 |
else if (f->is_shared_anno())
|
|
Packit |
df99a1 |
fprintf(stdout," A ");
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
fprintf(stdout," ? ");
|
|
Packit |
df99a1 |
GUTF8String id = f->get_load_name();
|
|
Packit |
df99a1 |
fprintf(stdout,"%8d %s", f->size, (const char*)ToNative(id));
|
|
Packit |
df99a1 |
GUTF8String name = f->get_save_name();
|
|
Packit |
df99a1 |
if (name != id)
|
|
Packit |
df99a1 |
fprintf(stdout," F=%s", (const char*)ToNative(name));
|
|
Packit |
df99a1 |
GUTF8String title = f->get_title();
|
|
Packit |
df99a1 |
if (title != id && f->is_page())
|
|
Packit |
df99a1 |
fprintf(stdout," T=%s", (const char*)ToNative(title));
|
|
Packit |
df99a1 |
fprintf(stdout,"\n");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (g().doc->get_thumbnails_num() == g().doc->get_pages_num())
|
|
Packit |
df99a1 |
fprintf(stdout," T %8s %s\n", "", "<thumbnails>");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_page_title(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
verror("must select a single page first");
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
verror("must provide a name");
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
GPosition pos = lst;
|
|
Packit |
df99a1 |
if (! lst[pos]->is_page())
|
|
Packit |
df99a1 |
verror("component file is not a page");
|
|
Packit |
df99a1 |
g().doc->set_file_title(g().fileid, fname);
|
|
Packit |
df99a1 |
vprint("set-page-title: modified \"%s\"", (const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GP<DjVuInfo> decode_info(GP<DjVuFile> file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVuInfo> info = file->info;
|
|
Packit |
df99a1 |
if (! info)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> pbs(file->get_djvu_bytestream(false, false));
|
|
Packit |
df99a1 |
const GP<IFFByteStream> iff(IFFByteStream::create(pbs));
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
if (! iff->get_chunk(chkid))
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
if (chkid == "FORM:DJVU")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (iff->get_chunk(chkid) && chkid!="INFO")
|
|
Packit |
df99a1 |
iff->close_chunk();
|
|
Packit |
df99a1 |
if (chkid == "INFO")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
info = DjVuInfo::create();
|
|
Packit |
df99a1 |
info->decode(*iff->get_bytestream());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
file->info = info;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return info;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
bool
|
|
Packit |
df99a1 |
set_rotation(GP<DjVuFile> file, int rot, bool relative)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// decode info
|
|
Packit |
df99a1 |
GP<DjVuInfo> info = decode_info(file);
|
|
Packit |
df99a1 |
if (! info)
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
if (relative)
|
|
Packit |
df99a1 |
rot += info->orientation;
|
|
Packit |
df99a1 |
info->orientation = rot & 3;
|
|
Packit |
df99a1 |
file->set_modified(true);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
return true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_rotation(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String rot = pbs.get_token();
|
|
Packit |
df99a1 |
if (! rot.is_int())
|
|
Packit |
df99a1 |
verror("usage: set-rotation [+-]<rot>");
|
|
Packit |
df99a1 |
int rotation = rot.toInt();
|
|
Packit |
df99a1 |
bool relative = (rot[0]=='+' || rot[0]=='-');
|
|
Packit |
df99a1 |
if (! relative)
|
|
Packit |
df99a1 |
if (rotation < 0 || rotation > 3)
|
|
Packit |
df99a1 |
verror("absolute rotation must be in range 0..3");
|
|
Packit |
df99a1 |
int rcount = 0;
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = g().fileid;
|
|
Packit |
df99a1 |
if (set_rotation(g().file, rotation, relative))
|
|
Packit |
df99a1 |
rcount += 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
if (set_rotation(f, rotation, relative))
|
|
Packit |
df99a1 |
rcount += 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
vprint("rotated %d pages", rcount);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
bool
|
|
Packit |
df99a1 |
set_dpi(GP<DjVuFile> file, int dpi)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// decode info
|
|
Packit |
df99a1 |
GP<DjVuInfo> info = decode_info(file);
|
|
Packit |
df99a1 |
if (! info)
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
info->dpi = dpi;
|
|
Packit |
df99a1 |
file->set_modified(true);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
return true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_dpi(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String sdpi = pbs.get_token();
|
|
Packit |
df99a1 |
if (! sdpi.is_int())
|
|
Packit |
df99a1 |
verror("usage: set-dpi <dpi>");
|
|
Packit |
df99a1 |
int dpi = sdpi.toInt();
|
|
Packit |
df99a1 |
if (dpi < 25 || dpi > 6000)
|
|
Packit |
df99a1 |
verror("resolution should be in range 25..6000dpi");
|
|
Packit |
df99a1 |
int rcount = 0;
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = g().fileid;
|
|
Packit |
df99a1 |
if (set_dpi(g().file, dpi))
|
|
Packit |
df99a1 |
rcount += 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
if (set_dpi(f, dpi))
|
|
Packit |
df99a1 |
rcount += 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
vprint("set dpi on %d pages", rcount);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define DELMETA 1
|
|
Packit |
df99a1 |
#define DELXMP 8
|
|
Packit |
df99a1 |
#define CHKCOMPAT 2
|
|
Packit |
df99a1 |
#define EIGHTBIT 4
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
filter_ant(GP<ByteStream> in,
|
|
Packit |
df99a1 |
GP<ByteStream> out,
|
|
Packit |
df99a1 |
int flags)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int c;
|
|
Packit |
df99a1 |
int plevel = 0;
|
|
Packit |
df99a1 |
bool copy = true;
|
|
Packit |
df99a1 |
bool unchanged = true;
|
|
Packit |
df99a1 |
bool compat = false;
|
|
Packit |
df99a1 |
GP<ByteStream> mem;
|
|
Packit |
df99a1 |
GP<ParsingByteStream> inp;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
if (flags & CHKCOMPAT)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
mem = ByteStream::create();
|
|
Packit |
df99a1 |
mem->copy(*in);
|
|
Packit |
df99a1 |
mem->seek(0);
|
|
Packit |
df99a1 |
char c;
|
|
Packit |
df99a1 |
int state = 0;
|
|
Packit |
df99a1 |
while (!compat && mem->read(&c,1)>0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
switch(state)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
case 0:
|
|
Packit |
df99a1 |
if (c == '\"')
|
|
Packit |
df99a1 |
state = '\"';
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
case '\"':
|
|
Packit |
df99a1 |
if (c == '\"')
|
|
Packit |
df99a1 |
state = 0;
|
|
Packit |
df99a1 |
else if (c == '\\')
|
|
Packit |
df99a1 |
state = '\\';
|
|
Packit |
df99a1 |
else if ((unsigned char)c<0x20 || c==0x7f)
|
|
Packit |
df99a1 |
compat = true;
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
case '\\':
|
|
Packit |
df99a1 |
if (!strchr("01234567tnrbfva\"\\",c))
|
|
Packit |
df99a1 |
compat = true;
|
|
Packit |
df99a1 |
state = '\"';
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
mem->seek(0);
|
|
Packit |
df99a1 |
inp = ParsingByteStream::create(mem);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
inp = ParsingByteStream::create(in);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
while ((c = inp->get()) != EOF)
|
|
Packit |
df99a1 |
if (c!=' ' && c!='\t' && c!='\r' && c!='\n')
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
inp->unget(c);
|
|
Packit |
df99a1 |
while ((c = inp->get()) != EOF)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (plevel == 0)
|
|
Packit |
df99a1 |
if (c !=' ' && c!='\t' && c!='\r' && c!='\n')
|
|
Packit |
df99a1 |
copy = true;
|
|
Packit |
df99a1 |
if (c == '\"')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
inp->unget(c);
|
|
Packit |
df99a1 |
GUTF8String token = inp->get_token(false, compat);
|
|
Packit |
df99a1 |
if (copy)
|
|
Packit |
df99a1 |
print_c_string(token, token.length(), *out, !!(flags & EIGHTBIT));
|
|
Packit |
df99a1 |
if (compat)
|
|
Packit |
df99a1 |
unchanged = false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (c == '(')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while ((c = inp->get()) != EOF)
|
|
Packit |
df99a1 |
if (c!=' ' && c!='\t' && c!='\r' && c!='\n')
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
inp->unget(c);
|
|
Packit |
df99a1 |
if ((flags & DELMETA) && plevel==0 && c=='m')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String token = inp->get_token();
|
|
Packit |
df99a1 |
if (token == "metadata")
|
|
Packit |
df99a1 |
copy = unchanged = false;
|
|
Packit |
df99a1 |
if (copy) {
|
|
Packit |
df99a1 |
out->write8('(');
|
|
Packit |
df99a1 |
out->write((const char*)token, token.length());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if ((flags & DELXMP) && plevel==0 && c=='x')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String token = inp->get_token();
|
|
Packit |
df99a1 |
if (token == "xmp")
|
|
Packit |
df99a1 |
copy = unchanged = false;
|
|
Packit |
df99a1 |
if (copy) {
|
|
Packit |
df99a1 |
out->write8('(');
|
|
Packit |
df99a1 |
out->write((const char*)token, token.length());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (copy)
|
|
Packit |
df99a1 |
out->write8('(');
|
|
Packit |
df99a1 |
plevel += 1;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (c == ')')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (copy)
|
|
Packit |
df99a1 |
out->write8(c);
|
|
Packit |
df99a1 |
if ( --plevel < 0)
|
|
Packit |
df99a1 |
plevel = 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (copy)
|
|
Packit |
df99a1 |
out->write8(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return !unchanged;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
print_ant(GP<IFFByteStream> iff,
|
|
Packit |
df99a1 |
GP<ByteStream> out,
|
|
Packit |
df99a1 |
int flags=CHKCOMPAT)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
bool changed = false;
|
|
Packit |
df99a1 |
if (utf8)
|
|
Packit |
df99a1 |
flags |= EIGHTBIT;
|
|
Packit |
df99a1 |
while (iff->get_chunk(chkid))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (chkid == "ANTa")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
changed = filter_ant(iff->get_bytestream(), out, flags);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (chkid == "ANTz")
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> bsiff =
|
|
Packit |
df99a1 |
BSByteStream::create(iff->get_bytestream());
|
|
Packit |
df99a1 |
changed = filter_ant(bsiff, out, flags);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
iff->close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return changed;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!g().file)
|
|
Packit |
df99a1 |
verror("you must first select a single page");
|
|
Packit |
df99a1 |
GP<ByteStream> out=ByteStream::create("w");
|
|
Packit |
df99a1 |
GP<ByteStream> anno = g().file->get_anno();
|
|
Packit |
df99a1 |
if (! (anno && anno->size())) return;
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
print_ant(iff, out);
|
|
Packit |
df99a1 |
out->write8('\n');
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_merged_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!g().file)
|
|
Packit |
df99a1 |
verror("you must first select a single page");
|
|
Packit |
df99a1 |
GP<ByteStream> out=ByteStream::create("w");
|
|
Packit |
df99a1 |
GP<ByteStream> anno = g().file->get_merged_anno();
|
|
Packit |
df99a1 |
if (! (anno && anno->size())) return;
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
print_ant(iff, out);
|
|
Packit |
df99a1 |
out->write8('\n');
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
modify_ant(const GP<DjVuFile> &f,
|
|
Packit |
df99a1 |
const char *newchunkid,
|
|
Packit |
df99a1 |
const GP<ByteStream> newchunk )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> anno(ByteStream::create());
|
|
Packit |
df99a1 |
if (newchunkid && newchunk && newchunk->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<IFFByteStream> out(IFFByteStream::create(anno));
|
|
Packit |
df99a1 |
newchunk->seek(0);
|
|
Packit |
df99a1 |
out->put_chunk(newchunkid);
|
|
Packit |
df99a1 |
out->copy(*newchunk);
|
|
Packit |
df99a1 |
out->close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
f->anno = anno;
|
|
Packit |
df99a1 |
if (! anno->size())
|
|
Packit |
df99a1 |
f->remove_anno();
|
|
Packit |
df99a1 |
f->set_modified(true);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
file_remove_ant(const GP<DjVuFile> &f, const char *id)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!f) return;
|
|
Packit |
df99a1 |
modify_ant(f, 0, 0);
|
|
Packit |
df99a1 |
vprint("remove_ant: modified \"%s\"", id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> & lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
file_remove_ant(f, id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_ant(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
verror("must select a single page first");
|
|
Packit |
df99a1 |
const GP<ByteStream> ant = ByteStream::create();
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> dsedant = ByteStream::create();
|
|
Packit |
df99a1 |
get_data_from_file("set-ant", pbs, *dsedant);
|
|
Packit |
df99a1 |
dsedant->seek(0);
|
|
Packit |
df99a1 |
GP<ByteStream> bsant = BSByteStream::create(ant,100);
|
|
Packit |
df99a1 |
filter_ant(dsedant, bsant, EIGHTBIT);
|
|
Packit |
df99a1 |
bsant = 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
modify_ant(g().file, "ANTz", ant);
|
|
Packit |
df99a1 |
vprint("set-ant: modified \"%s\"", (const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
print_meta(IFFByteStream &iff, ByteStream &out)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
while (iff.get_chunk(chkid))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
bool ok = false;
|
|
Packit |
df99a1 |
GP<DjVuANT> ant=DjVuANT::create();
|
|
Packit |
df99a1 |
if (chkid == "ANTz") {
|
|
Packit |
df99a1 |
GP<ByteStream> bsiff=BSByteStream::create(iff.get_bytestream());
|
|
Packit |
df99a1 |
ant->decode(*bsiff);
|
|
Packit |
df99a1 |
ok = true;
|
|
Packit |
df99a1 |
} else if (chkid == "ANTa") {
|
|
Packit |
df99a1 |
ant->decode(*iff.get_bytestream());
|
|
Packit |
df99a1 |
ok = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (ok)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition pos=ant->metadata; pos; ++pos)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String tmp;
|
|
Packit |
df99a1 |
tmp=ant->metadata.key(pos);
|
|
Packit |
df99a1 |
out.writestring(tmp);
|
|
Packit |
df99a1 |
out.write8('\t');
|
|
Packit |
df99a1 |
tmp=ant->metadata[pos];
|
|
Packit |
df99a1 |
print_c_string((const char*)tmp, tmp.length(), out, utf8);
|
|
Packit |
df99a1 |
out.write8('\n');
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
iff.close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_meta(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! g().file )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("print-meta: implicitly selecting shared annotations");
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if ( g().file )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> out=ByteStream::create("w");
|
|
Packit |
df99a1 |
GP<ByteStream> anno = g().file->get_anno();
|
|
Packit |
df99a1 |
if (! (anno && anno->size())) return;
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
print_meta(*iff,*out);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
modify_meta(const GP<DjVuFile> &f,
|
|
Packit |
df99a1 |
GMap<GUTF8String,GUTF8String> *newmeta)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
bool changed = false;
|
|
Packit |
df99a1 |
GP<ByteStream> newant = ByteStream::create();
|
|
Packit |
df99a1 |
if (newmeta && !newmeta->isempty())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
newant->writestring(GUTF8String("(metadata"));
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition pos=newmeta->firstpos(); pos; ++pos)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String key = newmeta->key(pos);
|
|
Packit |
df99a1 |
GUTF8String val = (*newmeta)[pos];
|
|
Packit |
df99a1 |
newant->write("\n\t(",3);
|
|
Packit |
df99a1 |
newant->writestring(key);
|
|
Packit |
df99a1 |
newant->write(" ",1);
|
|
Packit |
df99a1 |
print_c_string((const char*)val, val.length(),
|
|
Packit |
df99a1 |
*newant, true);
|
|
Packit |
df99a1 |
newant->write(")",1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
newant->write(" )\n",3);
|
|
Packit |
df99a1 |
changed = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
GP<ByteStream> anno = f->get_anno();
|
|
Packit |
df99a1 |
if (anno && anno->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
if (print_ant(iff, newant, DELMETA|CHKCOMPAT|EIGHTBIT))
|
|
Packit |
df99a1 |
changed = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
const GP<ByteStream> newantz=ByteStream::create();
|
|
Packit |
df99a1 |
if (changed)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
newant->seek(0);
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> bzz = BSByteStream::create(newantz,100);
|
|
Packit |
df99a1 |
bzz->copy(*newant);
|
|
Packit |
df99a1 |
bzz = 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
newantz->seek(0);
|
|
Packit |
df99a1 |
modify_ant(f, "ANTz", newantz);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return changed;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
file_remove_meta(const GP<DjVuFile> &f, const char *id)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (modify_meta(f, 0))
|
|
Packit |
df99a1 |
vprint("remove_meta: modified \"%s\"", id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_meta(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
file_remove_meta(f, id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_meta(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// get metadata
|
|
Packit |
df99a1 |
GP<ByteStream> metastream = ByteStream::create();
|
|
Packit |
df99a1 |
get_data_from_file("set-meta", pbs, *metastream);
|
|
Packit |
df99a1 |
metastream->seek(0);
|
|
Packit |
df99a1 |
// parse metadata
|
|
Packit |
df99a1 |
GMap<GUTF8String,GUTF8String> metadata;
|
|
Packit |
df99a1 |
GP<ParsingByteStream> inp = ParsingByteStream::create(metastream);
|
|
Packit |
df99a1 |
int c;
|
|
Packit |
df99a1 |
while ( (c = inp->get_spaces(true)) != EOF )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String key, val;
|
|
Packit |
df99a1 |
inp->unget(c);
|
|
Packit |
df99a1 |
key = inp->get_token();
|
|
Packit |
df99a1 |
c = inp->get_spaces(false);
|
|
Packit |
df99a1 |
if (c == '\"') {
|
|
Packit |
df99a1 |
inp->unget(c);
|
|
Packit |
df99a1 |
val = inp->get_token();
|
|
Packit |
df99a1 |
} else {
|
|
Packit |
df99a1 |
while (c!='\n' && c!='\r' && c!=EOF) {
|
|
Packit |
df99a1 |
val += c;
|
|
Packit |
df99a1 |
c = inp->get();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (key.length()>0 && val.length()>0)
|
|
Packit |
df99a1 |
metadata[key] = val;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// possibly select shared annotations.
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("set-meta: implicitly selecting shared annotations.");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (metadata.size() > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("set-meta: implicitly creating and selecting shared annotations.");
|
|
Packit |
df99a1 |
g().doc->create_shared_anno_file();
|
|
Packit |
df99a1 |
frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// set metadata
|
|
Packit |
df99a1 |
if (g().file && modify_meta(g().file, &metadata))
|
|
Packit |
df99a1 |
vprint("set-meta: modified \"%s\"",
|
|
Packit |
df99a1 |
(const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
print_xmp(IFFByteStream &iff, ByteStream &out)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
while (iff.get_chunk(chkid))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
bool ok = false;
|
|
Packit |
df99a1 |
GP<DjVuANT> ant=DjVuANT::create();
|
|
Packit |
df99a1 |
if (chkid == "ANTz") {
|
|
Packit |
df99a1 |
GP<ByteStream> bsiff=BSByteStream::create(iff.get_bytestream());
|
|
Packit |
df99a1 |
ant->decode(*bsiff);
|
|
Packit |
df99a1 |
ok = true;
|
|
Packit |
df99a1 |
} else if (chkid == "ANTa") {
|
|
Packit |
df99a1 |
ant->decode(*iff.get_bytestream());
|
|
Packit |
df99a1 |
ok = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (ok && ant->xmpmetadata.length()>0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out.writestring(ant->xmpmetadata);
|
|
Packit |
df99a1 |
out.write8('\n');
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
iff.close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_xmp(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! g().file )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("print-xmp: implicitly selecting shared annotations");
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if ( g().file )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> out=ByteStream::create("w");
|
|
Packit |
df99a1 |
GP<ByteStream> anno = g().file->get_anno();
|
|
Packit |
df99a1 |
if (! (anno && anno->size())) return;
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
print_xmp(*iff,*out);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
modify_xmp(const GP<DjVuFile> &f, GUTF8String *newxmp)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
bool changed = false;
|
|
Packit |
df99a1 |
GP<ByteStream> newant = ByteStream::create();
|
|
Packit |
df99a1 |
if (newxmp && newxmp->length() > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
newant->writestring(GUTF8String("(xmp "));
|
|
Packit |
df99a1 |
print_c_string((const char*)(*newxmp), newxmp->length(), *newant, true);
|
|
Packit |
df99a1 |
newant->write(" )\n",3);
|
|
Packit |
df99a1 |
changed = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
GP<ByteStream> anno = f->get_anno();
|
|
Packit |
df99a1 |
if (anno && anno->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<IFFByteStream> iff=IFFByteStream::create(anno);
|
|
Packit |
df99a1 |
if (print_ant(iff, newant, DELXMP|CHKCOMPAT|EIGHTBIT))
|
|
Packit |
df99a1 |
changed = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
const GP<ByteStream> newantz=ByteStream::create();
|
|
Packit |
df99a1 |
if (changed)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
newant->seek(0);
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<ByteStream> bzz = BSByteStream::create(newantz,100);
|
|
Packit |
df99a1 |
bzz->copy(*newant);
|
|
Packit |
df99a1 |
bzz = 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
newantz->seek(0);
|
|
Packit |
df99a1 |
modify_ant(f, "ANTz", newantz);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return changed;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
file_remove_xmp(const GP<DjVuFile> &f, const char *id)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (modify_xmp(f, 0))
|
|
Packit |
df99a1 |
vprint("remove_xmp: modified \"%s\"", id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_xmp(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
file_remove_xmp(f, id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_xmp(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// get xmpmetadata
|
|
Packit |
df99a1 |
GP<ByteStream> metastream = ByteStream::create();
|
|
Packit |
df99a1 |
get_data_from_file("set-meta", pbs, *metastream);
|
|
Packit |
df99a1 |
metastream->seek(0);
|
|
Packit |
df99a1 |
// read xmpmetadata
|
|
Packit |
df99a1 |
int size = metastream->size();
|
|
Packit |
df99a1 |
char *buffer = new char[size+1];
|
|
Packit |
df99a1 |
metastream->readall(buffer,size);
|
|
Packit |
df99a1 |
buffer[size] = 0;
|
|
Packit |
df99a1 |
GUTF8String xmpmetadata(buffer);
|
|
Packit |
df99a1 |
delete [] buffer;
|
|
Packit |
df99a1 |
// possibly select shared annotations.
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmDir::File> frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("set-xmp: implicitly selecting shared annotations.");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (xmpmetadata.length() > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("set-xmp: implicitly creating and selecting shared annotations.");
|
|
Packit |
df99a1 |
g().doc->create_shared_anno_file();
|
|
Packit |
df99a1 |
frec = g().doc->get_djvm_dir()->get_shared_anno_file();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (frec)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
select_clear();
|
|
Packit |
df99a1 |
select_add(frec);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// set metadata
|
|
Packit |
df99a1 |
if (g().file && modify_xmp(g().file, &xmpmetadata))
|
|
Packit |
df99a1 |
vprint("set-xmp: modified \"%s\"",
|
|
Packit |
df99a1 |
(const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
struct zone_names_struct
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *name;
|
|
Packit |
df99a1 |
DjVuTXT::ZoneType ztype;
|
|
Packit |
df99a1 |
char separator;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static zone_names_struct* zone_names() {
|
|
Packit |
df99a1 |
static zone_names_struct xzone_names[] =
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
{ "page", DjVuTXT::PAGE, 0 },
|
|
Packit |
df99a1 |
{ "column", DjVuTXT::COLUMN, DjVuTXT::end_of_column },
|
|
Packit |
df99a1 |
{ "region", DjVuTXT::REGION, DjVuTXT::end_of_region },
|
|
Packit |
df99a1 |
{ "para", DjVuTXT::PARAGRAPH, DjVuTXT::end_of_paragraph },
|
|
Packit |
df99a1 |
{ "line", DjVuTXT::LINE, DjVuTXT::end_of_line },
|
|
Packit |
df99a1 |
{ "word", DjVuTXT::WORD, ' ' },
|
|
Packit |
df99a1 |
{ "char", DjVuTXT::CHARACTER, 0 },
|
|
Packit |
df99a1 |
{ 0, (DjVuTXT::ZoneType)0 ,0 }
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
return xzone_names;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GP<DjVuTXT>
|
|
Packit |
df99a1 |
get_text(const GP<DjVuFile> &file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String chkid;
|
|
Packit |
df99a1 |
const GP<ByteStream> bs(file->get_text());
|
|
Packit |
df99a1 |
if (bs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
long int i=0;
|
|
Packit |
df99a1 |
const GP<IFFByteStream> iff(IFFByteStream::create(bs));
|
|
Packit |
df99a1 |
while (iff->get_chunk(chkid))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
i++;
|
|
Packit |
df99a1 |
if (chkid == GUTF8String("TXTa"))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVuTXT> txt = DjVuTXT::create();
|
|
Packit |
df99a1 |
txt->decode(iff->get_bytestream());
|
|
Packit |
df99a1 |
return txt;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else if (chkid == GUTF8String("TXTz"))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVuTXT> txt = DjVuTXT::create();
|
|
Packit |
df99a1 |
GP<ByteStream> bsiff=BSByteStream::create(iff->get_bytestream());
|
|
Packit |
df99a1 |
txt->decode(bsiff);
|
|
Packit |
df99a1 |
return txt;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
iff->close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
print_txt_sub(const GP<DjVuTXT> &txt, DjVuTXT::Zone &zone,
|
|
Packit |
df99a1 |
const GP<ByteStream> &out, int indent)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// Indentation
|
|
Packit |
df99a1 |
if (indent)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out->write("\n",1);
|
|
Packit |
df99a1 |
static const char spaces[] = " ";
|
|
Packit |
df99a1 |
if (indent > (int)sizeof(spaces))
|
|
Packit |
df99a1 |
indent = sizeof(spaces);
|
|
Packit |
df99a1 |
out->write(spaces, indent);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Zone header
|
|
Packit |
df99a1 |
int zinfo;
|
|
Packit |
df99a1 |
for (zinfo=0; zone_names()[zinfo].name; zinfo++)
|
|
Packit |
df99a1 |
if (zone.ztype == zone_names()[zinfo].ztype)
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
GUTF8String message = "(bogus";
|
|
Packit |
df99a1 |
if (zone_names()[zinfo].name)
|
|
Packit |
df99a1 |
message.format("(%s %d %d %d %d", zone_names()[zinfo].name,
|
|
Packit |
df99a1 |
zone.rect.xmin, zone.rect.ymin,
|
|
Packit |
df99a1 |
zone.rect.xmax, zone.rect.ymax);
|
|
Packit |
df99a1 |
out->write((const char*)message, message.length());
|
|
Packit |
df99a1 |
// Zone children
|
|
Packit |
df99a1 |
if (zone.children.isempty())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *data = txt->textUTF8.getbuf() + zone.text_start;
|
|
Packit |
df99a1 |
int length = zone.text_length;
|
|
Packit |
df99a1 |
if (data[length-1] == zone_names()[zinfo].separator)
|
|
Packit |
df99a1 |
length -= 1;
|
|
Packit |
df99a1 |
out->write(" ",1);
|
|
Packit |
df99a1 |
print_c_string(data, length, *out, utf8);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
for (GPosition pos=zone.children; pos; ++pos)
|
|
Packit |
df99a1 |
print_txt_sub(txt, zone.children[pos], out, indent + 1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Finish
|
|
Packit |
df99a1 |
out->write(")",1);
|
|
Packit |
df99a1 |
if (!indent)
|
|
Packit |
df99a1 |
out->write("\n", 1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
print_txt(const GP<DjVuTXT> &txt, const GP<ByteStream> &out)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (txt)
|
|
Packit |
df99a1 |
print_txt_sub(txt, txt->page_zone, out, 0);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_txt(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
if (lst[p]->is_page())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
const GP<DjVuTXT> txt(get_text(f));
|
|
Packit |
df99a1 |
if (txt)
|
|
Packit |
df99a1 |
print_txt(txt, out);
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
out->write("(page 0 0 0 0 \"\")\n",18);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_pure_txt(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
GP<DjVuTXT> txt;
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
if ((txt = get_text(f)))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String ntxt = txt->textUTF8;
|
|
Packit |
df99a1 |
out->write((const char*)ntxt, ntxt.length());
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
out->write("\f",1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static void
|
|
Packit |
df99a1 |
modify_txt(const GP<DjVuFile> &f,
|
|
Packit |
df99a1 |
const char *newchunkid,
|
|
Packit |
df99a1 |
const GP<ByteStream> newchunk )
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> text(ByteStream::create());
|
|
Packit |
df99a1 |
if (newchunkid && newchunk && newchunk->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<IFFByteStream> out(IFFByteStream::create(text));
|
|
Packit |
df99a1 |
newchunk->seek(0);
|
|
Packit |
df99a1 |
out->put_chunk(newchunkid);
|
|
Packit |
df99a1 |
out->copy(*newchunk);
|
|
Packit |
df99a1 |
out->close_chunk();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
f->text = text;
|
|
Packit |
df99a1 |
if (! text->size())
|
|
Packit |
df99a1 |
f->remove_text();
|
|
Packit |
df99a1 |
f->set_modified(true);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
file_remove_txt(const GP<DjVuFile> &f, const char *id)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! f) return;
|
|
Packit |
df99a1 |
modify_txt(f, 0, 0);
|
|
Packit |
df99a1 |
vprint("remove-txt: modified \"%s\"", id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_txt(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
file_remove_txt(f, id);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
construct_djvutxt_sub(ParsingByteStream &pbs,
|
|
Packit |
df99a1 |
const GP<DjVuTXT> &txt, DjVuTXT::Zone &zone,
|
|
Packit |
df99a1 |
int mintype, bool exact)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int c;
|
|
Packit |
df99a1 |
GUTF8String token;
|
|
Packit |
df99a1 |
// Get zone type
|
|
Packit |
df99a1 |
c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
if (c != '(')
|
|
Packit |
df99a1 |
verror("syntax error in txt data: expecting '(',\n\tnear '%s'",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
token = pbs.get_token(true);
|
|
Packit |
df99a1 |
int zinfo;
|
|
Packit |
df99a1 |
for (zinfo=0; zone_names()[zinfo].name; zinfo++)
|
|
Packit |
df99a1 |
if (token == zone_names()[zinfo].name)
|
|
Packit |
df99a1 |
break;
|
|
Packit |
df99a1 |
if (! zone_names()[zinfo].name)
|
|
Packit |
df99a1 |
verror("Syntax error in txt data: undefined token '%s',\n\tnear '%s'",
|
|
Packit |
df99a1 |
(const char*)ToNative(token), pbs.get_error_context());
|
|
Packit |
df99a1 |
zone.ztype = zone_names()[zinfo].ztype;
|
|
Packit |
df99a1 |
if (zone.ztype<mintype || (exact && zone.ztype>mintype))
|
|
Packit |
df99a1 |
verror("Syntax error in txt data: illegal zone token '%s',\n\tnear '%s'",
|
|
Packit |
df99a1 |
(const char*)ToNative(token), pbs.get_error_context());
|
|
Packit |
df99a1 |
// Get zone rect
|
|
Packit |
df99a1 |
GUTF8String str;
|
|
Packit |
df99a1 |
str = pbs.get_token(true);
|
|
Packit |
df99a1 |
if (!str || !str.is_int())
|
|
Packit |
df99a1 |
nerror: verror("Syntax error in txt data: number expected,\n\tnear '%s%s'",
|
|
Packit |
df99a1 |
(const char*)ToNative(str), pbs.get_error_context());
|
|
Packit |
df99a1 |
zone.rect.xmin = atoi(str);
|
|
Packit |
df99a1 |
str = pbs.get_token(true);
|
|
Packit |
df99a1 |
if (!str || !str.is_int())
|
|
Packit |
df99a1 |
goto nerror;
|
|
Packit |
df99a1 |
zone.rect.ymin = atoi(str);
|
|
Packit |
df99a1 |
str = pbs.get_token(true);
|
|
Packit |
df99a1 |
if (!str || !str.is_int())
|
|
Packit |
df99a1 |
goto nerror;
|
|
Packit |
df99a1 |
zone.rect.xmax = atoi(str);
|
|
Packit |
df99a1 |
str = pbs.get_token(true);
|
|
Packit |
df99a1 |
if (!str || !str.is_int())
|
|
Packit |
df99a1 |
goto nerror;
|
|
Packit |
df99a1 |
zone.rect.ymax = atoi(str);
|
|
Packit |
df99a1 |
if (zone.rect.xmin > zone.rect.xmax)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int tmp = zone.rect.xmin;
|
|
Packit |
df99a1 |
zone.rect.xmin=zone.rect.xmax;
|
|
Packit |
df99a1 |
zone.rect.xmax=tmp;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (zone.rect.ymin > zone.rect.ymax)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int tmp = zone.rect.ymin;
|
|
Packit |
df99a1 |
zone.rect.ymin=zone.rect.ymax;
|
|
Packit |
df99a1 |
zone.rect.ymax=tmp;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Continue processing
|
|
Packit |
df99a1 |
c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
if (c == '"')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// This is a terminal
|
|
Packit |
df99a1 |
str = pbs.get_token(true);
|
|
Packit |
df99a1 |
zone.text_start = txt->textUTF8.length();
|
|
Packit |
df99a1 |
zone.text_length = str.length();
|
|
Packit |
df99a1 |
txt->textUTF8 += str;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
// This is a non terminal
|
|
Packit |
df99a1 |
while (c != ')')
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (c != '(')
|
|
Packit |
df99a1 |
verror("Syntax error in text data: expecting subzone,\n\tnear '%s'",
|
|
Packit |
df99a1 |
pbs.get_error_context() );
|
|
Packit |
df99a1 |
DjVuTXT::Zone *nzone = zone.append_child();
|
|
Packit |
df99a1 |
construct_djvutxt_sub(pbs, txt, *nzone, zone.ztype+1, false);
|
|
Packit |
df99a1 |
c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
// Skip last parenthesis
|
|
Packit |
df99a1 |
c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
if (c != ')')
|
|
Packit |
df99a1 |
verror("Syntax error in text data: missing parenthesis,\n\tnear '%s'",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GP<DjVuTXT>
|
|
Packit |
df99a1 |
construct_djvutxt(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVuTXT> txt(DjVuTXT::create());
|
|
Packit |
df99a1 |
int c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
if (c == EOF)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
construct_djvutxt_sub(pbs, txt, txt->page_zone, DjVuTXT::PAGE, true);
|
|
Packit |
df99a1 |
if (pbs.get_spaces(true) != EOF)
|
|
Packit |
df99a1 |
verror("Syntax error in txt data: garbage after data");
|
|
Packit |
df99a1 |
txt->normalize_text();
|
|
Packit |
df99a1 |
if (! txt->textUTF8)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
return txt;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_txt(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
verror("must select a single page first");
|
|
Packit |
df99a1 |
const GP<ByteStream> txtbs(ByteStream::create());
|
|
Packit |
df99a1 |
get_data_from_file("set-txt", pbs, *txtbs);
|
|
Packit |
df99a1 |
txtbs->seek(0);
|
|
Packit |
df99a1 |
GP<ParsingByteStream> txtpbs(ParsingByteStream::create(txtbs));
|
|
Packit |
df99a1 |
const GP<DjVuTXT> txt(construct_djvutxt(*txtpbs));
|
|
Packit |
df99a1 |
GP<ByteStream> txtobs=ByteStream::create();
|
|
Packit |
df99a1 |
if (txt)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> bsout(BSByteStream::create(txtobs,1000));
|
|
Packit |
df99a1 |
txt->encode(bsout);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
txtobs->seek(0);
|
|
Packit |
df99a1 |
modify_txt(g().file, "TXTz", txtobs);
|
|
Packit |
df99a1 |
vprint("set-txt: modified \"%s\"", (const char*)ToNative(g().fileid));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
output(const GP<DjVuFile> &f, const GP<ByteStream> &out,
|
|
Packit |
df99a1 |
int flag, const char *id=0, int pageno=0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (f)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> ant(ByteStream::create());
|
|
Packit |
df99a1 |
const GP<ByteStream> txt(ByteStream::create());
|
|
Packit |
df99a1 |
char pagenumber[16];
|
|
Packit |
df99a1 |
sprintf(pagenumber," # page %d", pageno);
|
|
Packit |
df99a1 |
if (flag & 1)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> anno(f->get_anno());
|
|
Packit |
df99a1 |
if (anno && anno->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<IFFByteStream> iff(IFFByteStream::create(anno));
|
|
Packit |
df99a1 |
print_ant(iff, ant);
|
|
Packit |
df99a1 |
ant->seek(0);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (flag & 2)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
print_txt(get_text(f),txt);
|
|
Packit |
df99a1 |
txt->seek(0);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (id && ant->size() + txt->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
static const char msg1[] = "# ------------------------- \nselect \0";
|
|
Packit |
df99a1 |
static const char msg2[] = "\n\0";
|
|
Packit |
df99a1 |
out->write(msg1, strlen(msg1));
|
|
Packit |
df99a1 |
print_c_string(id, strlen(id), *out, utf8);
|
|
Packit |
df99a1 |
if (pageno > 0) out->write(pagenumber, strlen(pagenumber));
|
|
Packit |
df99a1 |
out->write(msg2, strlen(msg2));
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (ant->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out->write("set-ant\n", 8);
|
|
Packit |
df99a1 |
out->copy(*ant);
|
|
Packit |
df99a1 |
out->write("\n.\n", 3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (txt->size())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out->write("set-txt\n", 8);
|
|
Packit |
df99a1 |
out->copy(*txt);
|
|
Packit |
df99a1 |
out->write("\n.\n", 3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_output_ant(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
output(g().file, out, 1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *pre = "select; remove-ant\n";
|
|
Packit |
df99a1 |
out->write(pre, strlen(pre));
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pageno = lst[p]->get_page_num();
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
output(f, out, 1, id, pageno+1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_output_txt(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
output(g().file, out, 2);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *pre = "select; remove-txt\n";
|
|
Packit |
df99a1 |
out->write(pre, strlen(pre));
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pageno = lst[p]->get_page_num();
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
output(f, out, 2, id, pageno+1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_output_all(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
if (g().file)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
output(g().file, out, 3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const char *pre = "select; remove-ant; remove-txt\n";
|
|
Packit |
df99a1 |
out->write(pre, strlen(pre));
|
|
Packit |
df99a1 |
GPList<DjVmDir::File> &lst = g().selected;
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (GPosition p=lst; p; ++p)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pageno = lst[p]->get_page_num();
|
|
Packit |
df99a1 |
GUTF8String id = lst[p]->get_load_name();
|
|
Packit |
df99a1 |
const GP<DjVuFile> f(g().doc->get_djvu_file(id));
|
|
Packit |
df99a1 |
output(f, out, 3, id, pageno+1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
print_outline_sub(const GP<DjVmNav> &nav, int &pos, int count,
|
|
Packit |
df99a1 |
const GP<ByteStream> &out, int indent)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String str;
|
|
Packit |
df99a1 |
GP<DjVmNav::DjVuBookMark> entry;
|
|
Packit |
df99a1 |
while (count > 0 && pos < nav->getBookMarkCount())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
out->write("\n",1);
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=0; i
|
|
Packit |
df99a1 |
out->write(" ",1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
nav->getBookMark(entry, pos++);
|
|
Packit |
df99a1 |
out->write("(",1);
|
|
Packit |
df99a1 |
str = entry->displayname;
|
|
Packit |
df99a1 |
print_c_string(str, str.length(), *out, utf8);
|
|
Packit |
df99a1 |
out->write("\n ",2);
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=0; i
|
|
Packit |
df99a1 |
out->write(" ",1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
str = entry->url;
|
|
Packit |
df99a1 |
print_c_string(str, str.length(), *out, utf8);
|
|
Packit |
df99a1 |
print_outline_sub(nav, pos, entry->count, out, indent+1);
|
|
Packit |
df99a1 |
out->write(" )",2);
|
|
Packit |
df99a1 |
count--;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_print_outline(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmNav> nav = g().doc->get_djvm_nav();
|
|
Packit |
df99a1 |
if (nav)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int pos = 0;
|
|
Packit |
df99a1 |
int count = nav->getBookMarkCount();
|
|
Packit |
df99a1 |
if (count > 0)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> out = ByteStream::create("w");
|
|
Packit |
df99a1 |
out->write("(bookmarks",10);
|
|
Packit |
df99a1 |
print_outline_sub(nav, pos, count, out, 1);
|
|
Packit |
df99a1 |
out->write(" )\n", 3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
construct_outline_sub(ParsingByteStream &pbs, GP<DjVmNav> nav, int &count)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int c;
|
|
Packit |
df99a1 |
GUTF8String name, url;
|
|
Packit |
df99a1 |
GP<DjVmNav::DjVuBookMark> mark;
|
|
Packit |
df99a1 |
if ((c = pbs.get_spaces(true)) != '\"')
|
|
Packit |
df99a1 |
verror("Syntax error in outline: expecting name string,\n\tnear '%s'.",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
name = pbs.get_token();
|
|
Packit |
df99a1 |
if ((c = pbs.get_spaces(true)) != '\"')
|
|
Packit |
df99a1 |
verror("Syntax error in outline: expecting url string,\n\tnear '%s'.",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
pbs.unget(c);
|
|
Packit |
df99a1 |
url = pbs.get_token();
|
|
Packit |
df99a1 |
mark = DjVmNav::DjVuBookMark::create(0, name, url);
|
|
Packit |
df99a1 |
nav->append(mark);
|
|
Packit |
df99a1 |
count += 1;
|
|
Packit |
df99a1 |
while ((c = pbs.get_spaces(true)) == '(')
|
|
Packit |
df99a1 |
construct_outline_sub(pbs, nav, mark->count);
|
|
Packit |
df99a1 |
if (c != ')')
|
|
Packit |
df99a1 |
verror("Syntax error in outline: expecting ')',\n\tnear '%s'.",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
GP<DjVmNav>
|
|
Packit |
df99a1 |
construct_outline(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GP<DjVmNav> nav(DjVmNav::create());
|
|
Packit |
df99a1 |
int c = pbs.get_spaces(true);
|
|
Packit |
df99a1 |
int count = 0;
|
|
Packit |
df99a1 |
if (c == EOF)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
if (c!='(')
|
|
Packit |
df99a1 |
verror("Syntax error in outline data: expecting '(bookmarks'");
|
|
Packit |
df99a1 |
if (pbs.get_token()!="bookmarks")
|
|
Packit |
df99a1 |
verror("Syntax error in outline data: expecting '(bookmarks'");
|
|
Packit |
df99a1 |
while ((c = pbs.get_spaces(true)) == '(')
|
|
Packit |
df99a1 |
construct_outline_sub(pbs, nav, count);
|
|
Packit |
df99a1 |
if (c != ')')
|
|
Packit |
df99a1 |
verror("Syntax error in outline: expecting parenthesis,\n\tnear '%s'.",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
if (pbs.get_spaces(true) != EOF)
|
|
Packit |
df99a1 |
verror("Syntax error in outline: garbage after last ')',\n\tnear '%s'",
|
|
Packit |
df99a1 |
pbs.get_error_context(c) );
|
|
Packit |
df99a1 |
if (nav->getBookMarkCount() < 1)
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
if (!nav->isValidBookmark())
|
|
Packit |
df99a1 |
verror("Invalid outline data!");
|
|
Packit |
df99a1 |
return nav;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_outline(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
const GP<ByteStream> outbs(ByteStream::create());
|
|
Packit |
df99a1 |
get_data_from_file("set-outline", pbs, *outbs);
|
|
Packit |
df99a1 |
outbs->seek(0);
|
|
Packit |
df99a1 |
GP<ParsingByteStream> outpbs(ParsingByteStream::create(outbs));
|
|
Packit |
df99a1 |
GP<DjVmNav> nav(construct_outline(*outpbs));
|
|
Packit |
df99a1 |
if (g().doc->get_djvm_nav() != nav)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().doc->set_djvm_nav(nav);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_outline(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (g().doc->get_djvm_nav())
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().doc->set_djvm_nav(0);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static bool
|
|
Packit |
df99a1 |
callback_thumbnails(int page_num, void *)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("set-thumbnails: processing page %d", page_num+1);
|
|
Packit |
df99a1 |
return false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_set_thumbnails(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String sizestr = pbs.get_token();
|
|
Packit |
df99a1 |
if (! sizestr)
|
|
Packit |
df99a1 |
sizestr = "128";
|
|
Packit |
df99a1 |
if (! sizestr.is_int() )
|
|
Packit |
df99a1 |
verror("expecting integer argument");
|
|
Packit |
df99a1 |
int size = atoi(sizestr);
|
|
Packit |
df99a1 |
if (size<32 || size >256)
|
|
Packit |
df99a1 |
verror("size should be between 32 and 256 (e.g. 128)");
|
|
Packit |
df99a1 |
g().doc->generate_thumbnails(size, callback_thumbnails, NULL);
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_remove_thumbnails(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
g().doc->remove_thumbnails();
|
|
Packit |
df99a1 |
modified = true;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save_page(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
verror("empty filename");
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
verror("must select a single page first");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
vprint("save_page: not saving anything (-n was specified)");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
const GP<ByteStream> bs(g().file->get_djvu_bytestream(false, false));
|
|
Packit |
df99a1 |
const GP<ByteStream> out(ByteStream::create(GURL::Filename::UTF8(fname), "wb"));
|
|
Packit |
df99a1 |
out->writall("AT&T",4);
|
|
Packit |
df99a1 |
out->copy(*bs);
|
|
Packit |
df99a1 |
vprint("saved \"%s\" as \"%s\" (without inserting included files)",
|
|
Packit |
df99a1 |
(const char*)ToNative(g().fileid), (const char*)fname);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save_page_with(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
verror("empty filename");
|
|
Packit |
df99a1 |
if (! g().file)
|
|
Packit |
df99a1 |
verror("must select a single page first");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
vprint("save-page-with: not saving anything (-n was specified)");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
return;
|
|
Packit |
df99a1 |
const GP<ByteStream> bs(g().file->get_djvu_bytestream(true, false));
|
|
Packit |
df99a1 |
const GP<ByteStream> out(ByteStream::create(GURL::Filename::UTF8(fname), "wb"));
|
|
Packit |
df99a1 |
out->writall("AT&T",4);
|
|
Packit |
df99a1 |
out->copy(*bs);
|
|
Packit |
df99a1 |
vprint("saved \"%s\" as \"%s\" (inserting included files)",
|
|
Packit |
df99a1 |
(const char*)ToNative(g().fileid), (const char*)fname);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save_bundled(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
verror("empty filename");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
vprint("save-bundled: not saving anything (-n was specified)");
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
g().doc->save_as(GURL::Filename::UTF8(fname), true);
|
|
Packit |
df99a1 |
modified = false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save_indirect(ParsingByteStream &pbs)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
GUTF8String fname = pbs.get_token();
|
|
Packit |
df99a1 |
if (! fname)
|
|
Packit |
df99a1 |
verror("empty filename");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
vprint("save-indirect: not saving anything (-n was specified)");
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
g().doc->save_as(GURL::Filename::UTF8(fname), false);
|
|
Packit |
df99a1 |
modified = false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!g().doc->can_be_saved())
|
|
Packit |
df99a1 |
verror("cannot save old format (use save-bundled or save-indirect)");
|
|
Packit |
df99a1 |
if (nosave)
|
|
Packit |
df99a1 |
vprint("save: not saving anything (-n was specified)");
|
|
Packit |
df99a1 |
else if (!modified)
|
|
Packit |
df99a1 |
vprint("save: document was not modified");
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
g().doc->save();
|
|
Packit |
df99a1 |
modified = false;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_save(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
command_save();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_help(void)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
fprintf(stderr,
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
"Commands\n"
|
|
Packit |
df99a1 |
"--------\n"
|
|
Packit |
df99a1 |
"The following commands can be separated by newlines or semicolons.\n"
|
|
Packit |
df99a1 |
"Comment lines start with '#'. Commands usually operate on pages and files\n"
|
|
Packit |
df99a1 |
"specified by the \"select\" command. All pages and files are initially selected.\n"
|
|
Packit |
df99a1 |
"A single page must be selected before executing commands marked with a period.\n"
|
|
Packit |
df99a1 |
"Commands marked with an underline do not use the selection\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
" ls -- list all pages/files\n"
|
|
Packit |
df99a1 |
" n -- list pages count\n"
|
|
Packit |
df99a1 |
" dump -- shows IFF structure\n"
|
|
Packit |
df99a1 |
" size -- prints page width and height in html friendly way\n"
|
|
Packit |
df99a1 |
" select -- selects the entire document\n"
|
|
Packit |
df99a1 |
" select <id> -- selects a single page/file by name or page number\n"
|
|
Packit |
df99a1 |
" select-shared-ant -- selects the shared annotations file\n"
|
|
Packit |
df99a1 |
" create-shared-ant -- creates and select the shared annotations file\n"
|
|
Packit |
df99a1 |
" showsel -- displays currently selected pages/files\n"
|
|
Packit |
df99a1 |
" . print-ant -- prints annotations\n"
|
|
Packit |
df99a1 |
" . print-merged-ant -- prints annotations including the shared annotations\n"
|
|
Packit |
df99a1 |
" . print-meta -- prints file metadatas (a subset of the annotations\n"
|
|
Packit |
df99a1 |
" print-txt -- prints hidden text using a lisp syntax\n"
|
|
Packit |
df99a1 |
" print-pure-txt -- print hidden text without coordinates\n"
|
|
Packit |
df99a1 |
" _ print-outline -- print outline (bookmarks)\n"
|
|
Packit |
df99a1 |
" . print-xmp -- print xmp annotations\n"
|
|
Packit |
df99a1 |
" output-ant -- dumps ant as a valid cmdfile\n"
|
|
Packit |
df99a1 |
" output-txt -- dumps text as a valid cmdfile\n"
|
|
Packit |
df99a1 |
" output-all -- dumps ant and text as a valid cmdfile\n"
|
|
Packit |
df99a1 |
" . set-ant [<antfile>] -- copies <antfile> into the annotation chunk\n"
|
|
Packit |
df99a1 |
" . set-meta [<metafile>] -- copies <metafile> into the metadata annotation tag\n"
|
|
Packit |
df99a1 |
" . set-txt [<txtfile>] -- copies <txtfile> into the hidden text chunk\n"
|
|
Packit |
df99a1 |
" . set-xmp [<xmpfile>] -- copies <xmpfile> into the xmp metadata annotation tag\n"
|
|
Packit |
df99a1 |
" _ set-outline [<bmfile>] -- sets outline (bootmarks)\n"
|
|
Packit |
df99a1 |
" _ set-thumbnails [<sz>] -- generates all thumbnails with given size\n"
|
|
Packit |
df99a1 |
" set-rotation [+-]<rot> -- sets page rotation\n"
|
|
Packit |
df99a1 |
" set-dpi <dpi> -- sets page resolution\n"
|
|
Packit |
df99a1 |
" remove-ant -- removes annotations\n"
|
|
Packit |
df99a1 |
" remove-meta -- removes metadatas without changing other annotations\n"
|
|
Packit |
df99a1 |
" remove-txt -- removes hidden text\n"
|
|
Packit |
df99a1 |
" _ remove-outline -- removes outline (bookmarks)\n"
|
|
Packit |
df99a1 |
" . remove-xmp -- removes xmp metadata from annotation chunk\n"
|
|
Packit |
df99a1 |
" _ remove-thumbnails -- removes all thumbnails\n"
|
|
Packit |
df99a1 |
" . set-page-title <title> -- sets an alternate page title\n"
|
|
Packit |
df99a1 |
" . save-page <name> -- saves selected page/file as is\n"
|
|
Packit |
df99a1 |
" . save-page-with <name> -- saves selected page/file, inserting all included files\n"
|
|
Packit |
df99a1 |
" _ save-bundled <name> -- saves as bundled document under fname\n"
|
|
Packit |
df99a1 |
" _ save-indirect <name> -- saves as indirect document under fname\n"
|
|
Packit |
df99a1 |
" _ save -- saves in-place\n"
|
|
Packit |
df99a1 |
" _ help -- prints this message\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
"Interactive example:\n"
|
|
Packit |
df99a1 |
"--------------------\n"
|
|
Packit |
df99a1 |
" Type\n"
|
|
Packit |
df99a1 |
" %% djvused -v file.djvu\n"
|
|
Packit |
df99a1 |
" and play with the commands above\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
"Command line example:\n"
|
|
Packit |
df99a1 |
"---------------------\n"
|
|
Packit |
df99a1 |
" Save all text and annotation chunks as a djvused script with\n"
|
|
Packit |
df99a1 |
" %% djvused file.djvu -e output-all > file.dsed\n"
|
|
Packit |
df99a1 |
" Then edit the script with any text editor.\n"
|
|
Packit |
df99a1 |
" Finally restore the modified text and annotation chunks with\n"
|
|
Packit |
df99a1 |
" %% djvused file.djvu -f file.dsed -s\n"
|
|
Packit |
df99a1 |
" You may use option -v to see more messages\n"
|
|
Packit |
df99a1 |
"\n" );
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
command_help(ParsingByteStream &)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
command_help();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
typedef void (*CommandFunc)(ParsingByteStream &pbs);
|
|
Packit |
df99a1 |
static GMap<GUTF8String,CommandFunc> &command_map() {
|
|
Packit |
df99a1 |
static GMap<GUTF8String,CommandFunc> xcommand_map;
|
|
Packit |
df99a1 |
static bool first=true;
|
|
Packit |
df99a1 |
if(first) {
|
|
Packit |
df99a1 |
first=false;
|
|
Packit |
df99a1 |
xcommand_map["ls"] = command_ls;
|
|
Packit |
df99a1 |
xcommand_map["n"] = command_n;
|
|
Packit |
df99a1 |
xcommand_map["dump"] = command_dump;
|
|
Packit |
df99a1 |
xcommand_map["size"] = command_size;
|
|
Packit |
df99a1 |
xcommand_map["showsel"] = command_showsel;
|
|
Packit |
df99a1 |
xcommand_map["select"] = command_select;
|
|
Packit |
df99a1 |
xcommand_map["select-shared-ant"] = command_select_shared_ant;
|
|
Packit |
df99a1 |
xcommand_map["create-shared-ant"] = command_create_shared_ant;
|
|
Packit |
df99a1 |
xcommand_map["print-ant"] = command_print_ant;
|
|
Packit |
df99a1 |
xcommand_map["print-merged-ant"] = command_print_merged_ant;
|
|
Packit |
df99a1 |
xcommand_map["print-meta"] = command_print_meta;
|
|
Packit |
df99a1 |
xcommand_map["print-txt"] = command_print_txt;
|
|
Packit |
df99a1 |
xcommand_map["print-pure-txt"] = command_print_pure_txt;
|
|
Packit |
df99a1 |
xcommand_map["print-outline"] = command_print_outline;
|
|
Packit |
df99a1 |
xcommand_map["print-xmp"] = command_print_xmp;
|
|
Packit |
df99a1 |
xcommand_map["output-ant"] = command_output_ant;
|
|
Packit |
df99a1 |
xcommand_map["output-txt"] = command_output_txt;
|
|
Packit |
df99a1 |
xcommand_map["output-all"] = command_output_all;
|
|
Packit |
df99a1 |
xcommand_map["set-ant"] = command_set_ant;
|
|
Packit |
df99a1 |
xcommand_map["set-meta"] = command_set_meta;
|
|
Packit |
df99a1 |
xcommand_map["set-txt"] = command_set_txt;
|
|
Packit |
df99a1 |
xcommand_map["set-outline"] = command_set_outline;
|
|
Packit |
df99a1 |
xcommand_map["set-xmp"] = command_set_xmp;
|
|
Packit |
df99a1 |
xcommand_map["set-thumbnails"] = command_set_thumbnails;
|
|
Packit |
df99a1 |
xcommand_map["set-rotation"] = command_set_rotation;
|
|
Packit |
df99a1 |
xcommand_map["set-dpi"] = command_set_dpi;
|
|
Packit |
df99a1 |
xcommand_map["remove-ant"] = command_remove_ant;
|
|
Packit |
df99a1 |
xcommand_map["remove-meta"] = command_remove_meta;
|
|
Packit |
df99a1 |
xcommand_map["remove-txt"] = command_remove_txt;
|
|
Packit |
df99a1 |
xcommand_map["remove-outline"] = command_remove_outline;
|
|
Packit |
df99a1 |
xcommand_map["remove-thumbnails"] = command_remove_thumbnails;
|
|
Packit |
df99a1 |
xcommand_map["remove-xmp"] = command_remove_xmp;
|
|
Packit |
df99a1 |
xcommand_map["set-page-title"] = command_set_page_title;
|
|
Packit |
df99a1 |
xcommand_map["save-page"] = command_save_page;
|
|
Packit |
df99a1 |
xcommand_map["save-page-with"] = command_save_page_with;
|
|
Packit |
df99a1 |
xcommand_map["save-bundled"] = command_save_bundled;
|
|
Packit |
df99a1 |
xcommand_map["save-indirect"] = command_save_indirect;
|
|
Packit |
df99a1 |
xcommand_map["save"] = command_save;
|
|
Packit |
df99a1 |
xcommand_map["help"] = command_help;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return xcommand_map;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
usage()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
DjVuPrintErrorUTF8(
|
|
Packit |
df99a1 |
#ifdef DJVULIBRE_VERSION
|
|
Packit |
df99a1 |
"DJVUSED --- DjVuLibre-" DJVULIBRE_VERSION "\n"
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
"Simple DjVu file manipulation program\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
"Usage: djvused [options] djvufile\n"
|
|
Packit |
df99a1 |
"Executes scripting commands on djvufile.\n"
|
|
Packit |
df99a1 |
"Script command come either from a script file (option -f),\n"
|
|
Packit |
df99a1 |
"from the command line (option -e), or from stdin (default).\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
"Options are\n"
|
|
Packit |
df99a1 |
" -v -- verbose\n"
|
|
Packit |
df99a1 |
" -f <scriptfile> -- take commands from a file\n"
|
|
Packit |
df99a1 |
" -e <script> -- take commands from the command line\n"
|
|
Packit |
df99a1 |
" -s -- save after execution\n"
|
|
Packit |
df99a1 |
" -u -- produces utf8 instead of escaping non ascii chars\n"
|
|
Packit |
df99a1 |
" -n -- do not save anything\n"
|
|
Packit |
df99a1 |
"\n"
|
|
Packit |
df99a1 |
);
|
|
Packit |
df99a1 |
command_help();
|
|
Packit |
df99a1 |
exit(10);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
// MAIN
|
|
Packit |
df99a1 |
// --------------------------------------------------
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
void
|
|
Packit |
df99a1 |
execute()
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!g().cmdbs)
|
|
Packit |
df99a1 |
g().cmdbs = ByteStream::create("r");
|
|
Packit |
df99a1 |
const GP<ParsingByteStream> gcmd(ParsingByteStream::create(g().cmdbs));
|
|
Packit |
df99a1 |
ParsingByteStream &cmd=*gcmd;
|
|
Packit |
df99a1 |
GUTF8String token;
|
|
Packit |
df99a1 |
vprint("type \"help\" to see available commands.");
|
|
Packit |
df99a1 |
vprint("ok.");
|
|
Packit |
df99a1 |
while (!! (token = cmd.get_token(true)))
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
CommandFunc func = command_map()[token];
|
|
Packit |
df99a1 |
G_TRY
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (!func)
|
|
Packit |
df99a1 |
verror("unrecognized command");
|
|
Packit |
df99a1 |
// Cautious execution
|
|
Packit |
df99a1 |
(*func)(cmd);
|
|
Packit |
df99a1 |
// Skip extra arguments
|
|
Packit |
df99a1 |
int c = cmd.get_spaces();
|
|
Packit |
df99a1 |
if (c!=';' && c!='\n' && c!='\r' && c!=EOF)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
while (c!=';' && c!='\n' && c!='\r' && c!=EOF)
|
|
Packit |
df99a1 |
c = cmd.get();
|
|
Packit |
df99a1 |
verror("too many arguments");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
cmd.unget(c);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_CATCH(ex)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
vprint("Error (%s): %s",
|
|
Packit |
df99a1 |
(const char*)ToNative(token), ex.get_cause());
|
|
Packit |
df99a1 |
if (! verbose)
|
|
Packit |
df99a1 |
G_RETHROW;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_ENDCATCH;
|
|
Packit |
df99a1 |
vprint("ok.");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
int
|
|
Packit |
df99a1 |
main(int argc, char **argv)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
DJVU_LOCALE;
|
|
Packit |
df99a1 |
G_TRY
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
{ // extra nesting for windows
|
|
Packit |
df99a1 |
for (int i=1; i
|
|
Packit |
df99a1 |
if (!strcmp(argv[i],"-v"))
|
|
Packit |
df99a1 |
verbose = true;
|
|
Packit |
df99a1 |
else if (!strcmp(argv[i],"-s"))
|
|
Packit |
df99a1 |
save = true;
|
|
Packit |
df99a1 |
else if (!strcmp(argv[i],"-n"))
|
|
Packit |
df99a1 |
nosave = true;
|
|
Packit |
df99a1 |
else if (!strcmp(argv[i],"-u"))
|
|
Packit |
df99a1 |
utf8 = true;
|
|
Packit |
df99a1 |
else if (!strcmp(argv[i],"-f") && i+1
|
|
Packit |
df99a1 |
g().cmdbs = ByteStream::create(GURL::Filename::UTF8(GNativeString(argv[++i])), "r");
|
|
Packit |
df99a1 |
else if (!strcmp(argv[i],"-e") && !g().cmdbs && i+1
|
|
Packit |
df99a1 |
g().cmdbs = ByteStream::create_static(argv[i],strlen(argv[i]));
|
|
Packit |
df99a1 |
else if (argv[i][0] != '-' && !g().djvufile)
|
|
Packit |
df99a1 |
g().djvufile = GNativeString(argv[i]);
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
usage();
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
if (!g().djvufile)
|
|
Packit |
df99a1 |
usage();
|
|
Packit |
df99a1 |
// BOM
|
|
Packit |
df99a1 |
#ifdef _WIN32
|
|
Packit |
df99a1 |
if (utf8)
|
|
Packit |
df99a1 |
fwrite(utf8bom, sizeof(utf8bom), 1, stdout);
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
// Open file
|
|
Packit |
df99a1 |
g().doc = DjVuDocEditor::create_wait(GURL::Filename::UTF8(g().djvufile));
|
|
Packit |
df99a1 |
select_all();
|
|
Packit |
df99a1 |
// Execute
|
|
Packit |
df99a1 |
execute();
|
|
Packit |
df99a1 |
if (modified)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
if (save)
|
|
Packit |
df99a1 |
command_save();
|
|
Packit |
df99a1 |
else
|
|
Packit |
df99a1 |
fprintf(stderr,"djvused: (warning) file was modified but not saved\n");
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_CATCH(ex)
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
ex.perror();
|
|
Packit |
df99a1 |
return 10;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
G_ENDCATCH;
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|