summaryrefslogtreecommitdiffstats
path: root/kviewshell/plugins/djvu/libdjvu/DjVuFile.h
blob: 5648184ef16ffa0f2ce6a263f8046f3cf8601870 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
//C- -------------------------------------------------------------------
//C- DjVuLibre-3.5
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
//C- Copyright (c) 2001  AT&T
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, Version 2. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- This program is distributed in the hope that it will be useful,
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//C- GNU General Public License for more details.
//C- 
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
//C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
//C- Software authorized us to replace the original DjVu(r) Reference 
//C- Library notice by the following text (see doc/lizard2002.djvu):
//C-
//C-  ------------------------------------------------------------------
//C- | DjVu (r) Reference Library (v. 3.5)
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
//C- | 6,058,214 and patents pending.
//C- |
//C- | This software is subject to, and may be distributed under, the
//C- | GNU General Public License, Version 2. The license should have
//C- | accompanied the software or you may obtain a copy of the license
//C- | from the Free Software Foundation at http://www.fsf.org .
//C- |
//C- | The computer code originally released by LizardTech under this
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
//C- | General Public License.   This grant only confers the right to 
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
//C- | the extent such infringement is reasonably necessary to enable 
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
//C- | any greater extent that may be necessary to utilize further 
//C- | modifications or combinations.
//C- |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C- +------------------------------------------------------------------
// 
// $Id: DjVuFile.h,v 1.9 2003/11/07 22:08:20 leonb Exp $
// $Name: release_3_5_15 $

#ifndef _DJVUFILE_H
#define _DJVUFILE_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma interface
#endif


#include "DjVuInfo.h"
#include "DjVuPalette.h"
#include "DjVuPort.h"

#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif

class DjVuTXT;
class ByteStream;
class DataPool;
class JB2Image;
class JB2Dict;
class IW44Image;
class IFFByteStream;
class GPixmap;
class DjVuNavDir;


/** @name DjVuFile.h
    Files #"DjVuFile.h"# and #"DjVuFile.cpp"# contain implementation of the
    \Ref{DjVuFile} class, which takes the leading role in decoding of
    \Ref{DjVuImage}s.

    In the previous releases of the library the work of decoding has been
    entirely done in \Ref{DjVuImage}. Now, due to the introduction of multipage
    documents, the decoding procedure became significantly more complex and
    has been moved out from \Ref{DjVuImage} into \Ref{DjVuFile}.

    There is not much point though in creating just \Ref{DjVuFile} alone.
    The maximum power of the decoder is achieved when you create the
    \Ref{DjVuDocument} and work with {\bf it} when decoding the image.

    @memo Classes representing DjVu files.
    @author Andrei Erofeev <[email protected]>
    @version #$Id: DjVuFile.h,v 1.9 2003/11/07 22:08:20 leonb Exp $#
*/

//@{

/** #DjVuFile# plays the central role in decoding \Ref{DjVuImage}s.
    First of all, it represents a DjVu file whether it's part of a
    multipage all-in-one-file DjVu document, or part of a multipage
    DjVu document where every page is in a separate file, or the whole
    single page document. #DjVuFile# can read its contents from a file
    and store it back when necessary.

    Second, #DjVuFile# does the greatest part of decoding work. In the
    past this was the responsibility of \Ref{DjVuImage}. Now, with the
    introduction of the multipage DjVu formats, the decoding routines
    have been extracted from the \Ref{DjVuImage} and put into this separate
    class #DjVuFile#.

    As \Ref{DjVuImage} before, #DjVuFile# now contains public class
    variables corresponding to every component, that can ever be decoded
    from a DjVu file (such as #INFO# chunk, #BG44# chunk, #SJBZ# chunk, etc.).

    As before, the decoding is initiated by a single function
    (\Ref{start_decode}() in this case, and \Ref{DjVuImage::decode}() before).
    The difference is that #DjVuFile# now handles threads creation itself.
    When you call the \Ref{start_decode}() function, it creates the decoding
    thread, which starts decoding, and which can create additional threads:
    one per each file included into this one.

    {\bf Inclusion} is also a new feature specifically designed for a
    multipage document. Indeed, inside a given document there can be a lot
    of things shared between its pages. Examples can be the document
    annotation (\Ref{DjVuAnno}) and other things like shared shapes and
    dictionary (to be implemented). To avoid putting these chunks into
    every page, we have invented new chunk called #INCL# which purpose is
    to make the decoder open the specified file and decode it.
    
    {\bf Source of data.} The #DjVuFile# can be initialized in two ways:
    \begin{itemize}
       \item With #URL# and \Ref{DjVuPort}. In this case #DjVuFile# will
             request its data thru the communication mechanism provided by
	     \Ref{DjVuPort} in the constructor. If this file references
	     (includes) any other file, data for them will also be requested
	     in the same way.
       \item With \Ref{ByteStream}. In this case the #DjVuFile# will read
             its data directly from the passed stream. This constructor
	     has been added to simplify creation of #DjVuFile#s, which do
	     no include anything else. In this case the \Ref{ByteStream}
	     is enough for the #DjVuFile# to initialize.
    \end{itemize}
	     
    {\bf Progress information.} #DjVuFile# does not do decoding silently.
    Instead, it sends a whole set of notifications through the mechanism
    provided by \Ref{DjVuPort} and \Ref{DjVuPortcaster}. It tells the user
    of the class about the progress of the decoding, about possible errors,
    chunk being decoded, etc. The data is requested using this mechanism too.

    {\bf Creating.} Depending on where you have data of the DjVu file, the
    #DjVuFile# can be initialized in two ways:
    \begin{itemize}
       \item By providing #URL# and pointer to \Ref{DjVuPort}. In this case
             #DjVuFile# will request data using communication mechanism
	     provided by \Ref{DjVuPort}. This is useful when the data is on
	     the web or when this file includes other files.
       \item By providing a \Ref{ByteStream} with the data for the file. Use
             it only when the file doesn't include other files.
    \end{itemize}
    There is also a bunch of functions provided for composing
    the desired \Ref{DjVuDocument} and modifying #DjVuFile# structure. The
    examples are \Ref{delete_chunks}(), \Ref{insert_chunk}(),
    \Ref{include_file}() and \Ref{unlink_file}().

    {\bf Caching.} In the case of plugin it's important to do the caching
    of decoded images or files. #DjVuFile# appears to be the best candidate
    for caching, and that's why it supports this procedure. Whenever a
    #DjVuFile# is successfully decoded, it's added to the cache by
    \Ref{DjVuDocument}. Next time somebody needs it, it will be extracted
    from the cache directly by \Ref{DjVuDocument} and won't be decoded again.

    {\bf URLs.} Historically the biggest strain is put on making the decoder
    available for Netscape and IE plugins where the original files reside
    somewhere in the net. That is why #DjVuFile# uses {\bf URLs} to
    identify itself and other files. If you're working with files on the
    hard disk, you have to use the local URLs instead of file names.
    A good way to do two way conversion is the \Ref{GOS} class. Sometimes it
    happens that a given file does not reside anywhere but the memory. No
    problem in this case either. There is a special port \Ref{DjVuMemoryPort},
    which can associate any URL with the corresponding data in the memory.
    All you need to do is to invent your own URL prefix for this case.
    "#memory:#" will do. The usage of absolute URLs has many advantages among
    which is the capability to cache files with their URL being the cache key.

    Please note, that the #DjVuFile# class has been designed to work closely
    with \Ref{DjVuDocument}. So please review the documentation on this class
    too. */

class DjVuFile : public DjVuPort
{
public:
   enum { DECODING=1, DECODE_OK=2, DECODE_FAILED=4, DECODE_STOPPED=8,
	  DATA_PRESENT=16, ALL_DATA_PRESENT=32, INCL_FILES_CREATED=64,
          MODIFIED=128, DONT_START_DECODE=256, STOPPED=512,
	  BLOCKED_STOPPED=1024, CAN_COMPRESS=2048, NEEDS_COMPRESSION=4096 };
   enum { STARTED=1, FINISHED=2 };

      /** @name Decoded file contents */
      //@{
      /// Pointer to the DjVu file information component.
   GP<DjVuInfo>		info;
      /// Pointer to the background component of DjVu image (IW44 encoded).
   GP<IW44Image>	bg44;
      /// Pointer to the background component of DjVu image (Raw).
   GP<GPixmap>		bgpm;
      /// Pointer to the mask of foreground component of DjVu image (JB2 encoded).
   GP<JB2Image>		fgjb;
      /// Pointer to the optional shape dictionary for the mask (JB2 encoded).
   GP<JB2Dict>		fgjd;
      /// Pointer to a colors layer for the foreground component of DjVu image.
   GP<GPixmap>		fgpm;
      /// Pointer to a colors vector for the foreground component of DjVu image.
   GP<DjVuPalette>	fgbc;
      /// Pointer to collected annotation chunks.
   GP<ByteStream>	anno;
      /// Pointer to collected hiddentext chunks.
   GP<ByteStream>	text;
      /// Pointer to meta data chunks.
   GP<ByteStream>	meta;
      /// Pointer to the *old* navigation directory contained in this file
   GP<DjVuNavDir>	dir;
      /// Description of the file formed during decoding
   GUTF8String		description;
      /// MIME type string describing the DjVu data.
   GUTF8String		mimetype;
      /// Size of the file.
   int			file_size;
      //@}

protected:
      /** Default constructor.  Must follow with an init() */
   DjVuFile(void);
public:
   virtual ~DjVuFile(void);

      /** Initializes a #DjVuFile# object. This is a simplified initializer,
	  which is not supposed to be used for decoding or creating
	  #DjVuFile#s, which include other files.

	  If the file is stored on the hard drive, you may also use the
	  other constructor and pass it the file's URL and #ZERO# #port#.
	  The #DjVuFile# will read the data itself.

	  If you want to receive error messages and notifications, you
	  may connect the #DjVuFile# to your own \Ref{DjVuPort} after
	  it has been constructed.

	  @param str The stream containing data for the file. */
   void init(const GP<ByteStream> & str);

      /** Creator, does the init(ByteStream &str) */
   static GP<DjVuFile> create( const GP<ByteStream> & str,
     const ErrorRecoveryAction recover_action=ABORT,
     const bool verbose_eof=true);
   
      /** Initializes a #DjVuFile# object. As you can notice, the data is not
	  directly passed to this function. The #DjVuFile# will ask for it
	  through the \Ref{DjVuPort} mechanism before the constructor
	  finishes. If the data is stored locally on the hard disk then the
	  pointer to \Ref{DjVuPort} may be set to #ZERO#, which will make
	  #DjVuFile# read all data from the hard disk and report all errors
	  to #stderr#.

	  {\bf Note}. If the file includes (by means of #INCL# chunks) other
	  files then you should be ready to
	  \begin{enumerate}
	     \item Reply to requests \Ref{DjVuPort::id_to_url}() issued to
	           translate IDs (used in #INCL# chunks) to absolute URLs.
		   Usually, when the file is created by \Ref{DjVuDocument}
		   this job is done by it. If you construct such a file
		   manually, be prepared to do the ID to URL translation
	     \item Provide data for all included files.
	  \end{enumerate}

	  @param url The URL assigned to this file. It will be used when
	         the #DjVuFile# asks for data.
	  @param port All communication between #DjVuFile#s and \Ref{DjVuDocument}s
	         is done through the \Ref{DjVuPort} mechanism. If the {\em url}
		 is not local or the data does not reside on the hard disk,
		 the {\em port} parameter must not be #ZERO#. If the {\em port}
		 is #ZERO# then #DjVuFile# will create an internal instance
		 of \Ref{DjVuSimplePort} for accessing local files and
		 reporting errors. It can later be disabled by means
		 of \Ref{disable_standard_port}() function. */
   void init(const GURL & url, GP<DjVuPort> port=0);

      /** Creator, does the init(const GURL &url, GP<DjVuPort> port=0) */
   static GP<DjVuFile> create(
     const GURL & url, GP<DjVuPort> port=0,
     const ErrorRecoveryAction recover_action=ABORT,
     const bool verbose_eof=true);

      /** Disables the built-in port for accessing local files, which may
	  have been created in the case when the #port# argument to
	  the \Ref{DjVuFile::DjVuFile}() constructor is #ZERO# */
   void		disable_standard_port(void);

      /** Looks for #decoded# navigation directory (\Ref{DjVuNavDir}) in this
	  or included files. Returns #ZERO# if nothing could be found.

	  {\bf Note.} This function does {\bf not} attempt to decode #NDIR#
	  chunks. It is looking for predecoded components. #NDIR# can be
	  decoded either during regular decoding (initiated by
	  \Ref{start_decode}() function) or by \Ref{decode_ndir}() function,
	  which processes this and included files recursively in search
	  of #NDIR# chunks and decodes them. */
   GP<DjVuNavDir>	find_ndir(void);

      /** @name #DjVuFile# flags query functions */
      //@{
      /** Returns the #DjVuFile# flags. The value returned is the
	  result of ORing one or more of the following constants:
	  \begin{itemize}
	     \item #DECODING# The decoding is in progress
	     \item #DECODE_OK# The decoding has finished successfully
	     \item #DECODE_FAILED# The decoding has failed
	     \item #DECODE_STOPPED# The decoding has been stopped by
	           \Ref{stop_decode}() function
	     \item #DATA_PRESENT# All data for this file has been received.
	           It's especially important in the case of Netscape or IE
		   plugins when the data is being received while the
		   decoding is done.
	     \item #ALL_DATA_PRESENT# Not only data for this file, but also
	           for all included file has been received.
	     \item #INCL_FILES_CREATED# All #INCL# and #INCF# chunks have been
	           processed and the corresponding #DjVuFile#s created. This
		   is important to know to be sure that the list returned by
		   \Ref{get_included_files}() is OK.
	  \end{itemize} */
   long		get_flags(void) const;
      /// Returns #TRUE# if the file is being decoded.
   bool		is_decoding(void) const;
      /// Returns #TRUE# if decoding of the file has finished successfully.
   bool		is_decode_ok(void) const;
      /// Returns #TRUE# if decoding of the file has failed.
   bool		is_decode_failed(void) const;
      /** Returns #TRUE# if decoding of the file has been stopped by
	  \Ref{stop_decode}() function. */
   bool		is_decode_stopped(void) const;
      /// Returns #TRUE# if this file has received all data.
   bool		is_data_present(void) const;
      /** Returns #TRUE# if this file {\bf and} all included files have
	  received all data. */
   bool		is_all_data_present(void) const;
      /** Returns #TRUE# if all included files have been created. Only when
	  this function returns 1, the \Ref{get_included_files}() returns
	  the correct information. */
   bool		are_incl_files_created(void) const;
   bool		is_modified(void) const;
   bool		needs_compression(void) const;
   bool		can_compress(void) const;
   void		set_modified(bool m);
   void		set_needs_compression(bool m);
   void		set_can_compress(bool m);
      //@}

      /// Returns the URL assigned to this file
   GURL		get_url(void) const;

      /** @name Decode control routines */
      //@{
      /** Starts decode. If threads are enabled, the decoding will be
	  done in another thread. Be sure to use \Ref{wait_for_finish}()
	  or listen for notifications sent through the \Ref{DjVuPortcaster}
	  to remain in sync. */
   void		start_decode(void);
      /** Start the decode iff not already decoded.  If sync is true, wait
          wait for decode to complete.  Returns true of start_decode is called.
          */
   bool   resume_decode(const bool sync=false);
      /** Stops decode. If #sync# is 1 then the function will not return
	  until the decoding thread actually dies. Otherwise it will
	  just signal the thread to stop and will return immediately.
	  Decoding of all included files will be stopped too. */
   void		stop_decode(bool sync);
      /** Recursively stops all data-related operations.

	  Depending on the value of #only_blocked# flag this works as follows:
	  \begin{itemize}
	     \item If #only_blocked# is #TRUE#, the function will make sure,
	           that any further access to the file's data will result
		   in a #STOP# exception if the desired data is not available
		   (and the thread would normally block).
	     \item If #only_blocked# is #FALSE#, then {\bf any} further
	           access to the file's data will result in immediate
		   #STOP# exception.
	  \end{itemize}

	  The action of this function is recursive, meaning that any #DjVuFile#
	  included into this one will also be stopped.

	  Use this function when you don't need the #DjVuFile# anymore. The
	  results cannot be undone, and the whole idea is to make all threads
	  working with this file exit with the #STOP# exception. */
   void		stop(bool only_blocked);
      /** Wait for the decoding to finish. This will wait for the
	  termination of included files too. */
   void		wait_for_finish(void);
      /** Looks for #NDIR# chunk (navigation directory), and decodes its
	  contents. If the #NDIR# chunk has not been found in {\em this} file,
	  but this file includes others, the procedure will continue
	  recursively. This function is useful to obtain the document
	  navigation directory before any page has been decoded. After it
	  returns the directory can be obtained by calling \Ref{find_ndir}()
	  function.

	  {\bf Warning.} Contrary to \Ref{start_decode}(), this function
	  does not return before it completely decodes the directory.
	  Make sure, that this file and all included files have enough data. */
   GP<DjVuNavDir>	decode_ndir(void);
      /// Clears all decoded components.
   void		reset(void);
      /** Processes #INCL# chunks and creates included files.
	  Normally you won't need to call this function because included
	  files are created automatically when the file is being decoded.
	  But if due to some reason you'd like to obtain the list of included
	  files without decoding this file, this is an ideal function to call.

	  {\bf Warning.} This function does not return before it reads the
	  whole file, which may block your application under some circumstances
	  if not all data is available. */
   void		process_incl_chunks(void);
      //@}
   
      // Function needed by the cache
   unsigned int	get_memory_usage(void) const;

      /** Returns the list of included DjVuFiles.
	  
	  {\bf Warning.} Included files are normally created during decoding.
	  Before that they do not exist.   If you call this function at
	  that time and set #only_created# to #FALSE# then it will have to
	  read all the data from this file in order to find #INCL# chunks,
	  which may block your application, if not all data is available.

	  @param only_created If #TRUE#, the file will not try to process
	         #INCL# chunks and load referenced files. It will return
		 just those files, which have already been created during
		 the decoding procedure. */
   GPList<DjVuFile>	get_included_files(bool only_created=true);

      /** Includes a #DjVuFile# with the specified #id# into this one.
	  This function will also insert an #INCL# chunk at position
	  #chunk_num#. The function will request data for the included
	  file and will create it before returning. */
   void		insert_file(const GUTF8String &id, int chunk_num=1);
      /// Will get rid of included file with the given #id#
   void		unlink_file(const GUTF8String &id);
      /** Will find an #INCL# chunk containing #name# in input #data# and
	  will remove it */
   static GP<DataPool>	unlink_file(const GP<DataPool> & data, const GUTF8String &name);

      /// Returns the number of chunks in the IFF file data
   int		get_chunks_number(void);
      /// Returns the name of chunk number #chunk_num#
   GUTF8String	get_chunk_name(int chunk_num);
      /// Returns 1 if this file contains chunk with name #chunk_name#
   bool		contains_chunk(const GUTF8String &chunk_name);

      /** Processes the included files hierarchy and returns merged
	  annotations. This function may be used even when the #DjVuFile#
	  has not been decoded yet. If all data has been received for
	  this #DjVuFile# and all included #DjVuFile#s, it will will
	  gather annotations from them and will return the result.
	  If no annotations have been found, #ZERO# will be returned.
	  If either this #DjVuFile# or any of the included files do not
	  have all the data, the function will use the results of
	  decoding, which may have been started with the \Ref{start_decode}()
	  function. Otherwise #ZERO# will be returned as well.

	  If #max_level_ptr# pointer is not zero, the function will use
	  it to store the maximum level number from which annotations
	  have been obtained. #ZERO# level corresponds to the top-level
	  page file.

	  {\bf Summary:} This function will return complete annotations only
	  when the \Ref{is_all_data_present}() returns #TRUE#. */
   GP<ByteStream>	get_merged_anno(int * max_level_ptr=0);

      /** Returns the annotation chunks (#"ANTa"# and #"ANTz"#).  This
          function may be used even when the #DjVuFile# has not been decoded
          yet. If all data has been received for this #DjVuFile#, it will
          gather hidden text and return the result.  If no hidden text has
          been found, #ZERO# will be returned.

	  {\bf Summary:} This function will return complete annotations
	  only when the \Ref{is_all_data_present}() returns #TRUE#. */
   GP<ByteStream>	get_anno(void);

      /** Returns the text chunks (#"TXTa"# and #"TXTz"#).  This function may
          be used even when the #DjVuFile# has not been decoded yet. If all
          data has been received for this #DjVuFile#, it will gather hidden
          text and return the result.  If no hidden text has been found,
          #ZERO# will be returned.

	  {\bf Summary:} This function will return complete hidden text layers
	  only when the \Ref{is_all_data_present}() returns #TRUE#. */
   GP<ByteStream>	get_text(void);

      /** Returns the meta chunks (#"METa"# and #"METz"#).  This function may
          be used even when the #DjVuFile# has not been decoded yet. If all
          data has been received for this #DjVuFile#, it will gather metadata
          and return the result.  If no hidden text has been found, #ZERO#
          will be returned.

	  {\bf Summary:} This function will return complete meta data only
	  when the \Ref{is_all_data_present}() returns #TRUE#. */
   GP<ByteStream>	get_meta(void);

      /** Goes down the hierarchy of #DjVuFile#s and merges their annotations.
          (shouldn't this one be private?).
	  @param max_level_ptr If this pointer is not ZERO, the function
	         will use it to store the maximum level at which annotations
		 were found. Top-level page files have ZERO #level#.
	  @param ignore_list The function will not process included #DjVuFile#s
	         with URLs matching those mentioned in this #ignore_list#. */
   GP<ByteStream>	get_merged_anno(const GList<GURL> & ignore_list,
					int * max_level_ptr);

      /** Clears this file of all annotations. */
   void	remove_anno(void);

      /** Clears the hidden text. */
   void	remove_text(void);

      /// Clears the meta data.
   void remove_meta(void);

      /** Returns #TRUE# if the file contains annotation chunks.
	  Known annotation chunks at the time of writing this help are:
	  {\bf ANTa}, {\bf ANTz}, {\bf FORM:ANNO}. */
   bool		contains_anno(void);

      /** Returns #TRUE# if the file contains hiddentext chunks.
	  Known hiddentext chunks at the time of writing this help are:
	  {\bf TXTa}, and {\bf TXTz}. */
   bool		contains_text(void);

      /** Returns #TRUE# if the file contains metadata chunks.
	  Known metadata chunks at the time of writing this help are:
	  {\bf METa}, and {\bf METz}. */
   bool		contains_meta(void);

     /** Changes the value of the hiddentext. */
   void change_info(GP<DjVuInfo> info, const bool do_reset=false);
   
     /** Changes the value of the hiddentext. */
   void change_text(GP<DjVuTXT> txt, const bool do_reset=false);
   
     /** Changes the value of the metadata. */
   void change_meta(const GUTF8String &meta, const bool do_reset=false);
   
      /** @name Encoding routines */
      //@{
      /** The main function that encodes data back into binary stream.
	  The data returned will reflect possible changes made into the
	  chunk structure, annotation chunks and navigation directory
	  chunk #NDIR#.

	  {\bf Note:} The file stream will not have the magic
          #0x41,0x54,0x26,0x54#
	  at the beginning.
	  
	  @param included_too Process included files too. */
   GP<ByteStream>	get_djvu_bytestream(const bool included_too, const bool no_ndir=true);

      /** Same as \Ref{get_djvu_bytestream}(), returning a DataPool.
	  @param included_too Process included files too. */
   GP<DataPool>		get_djvu_data(const bool included_too, const bool no_ndir=true );
      //@}

      // Internal. Used by DjVuDocument
   GP<DataPool>		get_init_data_pool(void) const { return data_pool; };

      // Internal. Used by DjVuDocument. May block for data.
   void			move(const GURL & dir_url);

      /** Internal. Used by DjVuDocument. The #name# should {\bf not}
	  be encoded with \Ref{GOS::encode_reserved}(). */
   void			set_name(const GUTF8String &name);

      // Internal. Used by DjVuDocument
   GSafeFlags &		get_safe_flags(void);

      // Internal. Used by DjVuImage
   void                 merge_anno(ByteStream &out);

      // Internal. Used by DjVuImage
   void                 get_text(ByteStream &out);

      // Internal. Used by DjVuImage
   void                 get_meta(ByteStream &out);

      // Internal. Used by DjVuDocEditor
   void			rebuild_data_pool(void);

      // Functions inherited from DjVuPort
   virtual bool		inherits(const GUTF8String &class_name) const;
   virtual void		notify_chunk_done(const DjVuPort * source, const GUTF8String &name);
   virtual void		notify_file_flags_changed(const DjVuFile * source,
						  long set_mask, long clr_mask);
   virtual void		set_recover_errors(const ErrorRecoveryAction=ABORT);
   virtual void		set_verbose_eof(const bool verbose_eof=true);
   virtual void		report_error(const GException &ex,const bool=true);
   static void set_decode_codec(GP<GPixmap> (*codec)(ByteStream &bs));

protected:
   GURL			url;
   GP<DataPool>		data_pool;

   GPList<DjVuFile>	inc_files_list;
   GCriticalSection	inc_files_lock;
   GCriticalSection	anno_lock;
   GCriticalSection	text_lock;
   GCriticalSection	meta_lock;
   ErrorRecoveryAction	recover_errors;
   bool			verbose_eof;
   int			chunks_number;
private:
   bool                 initialized;
   GSafeFlags		flags;

   GThread		* decode_thread;
   GP<DataPool>		decode_data_pool;
   GP<DjVuFile>		decode_life_saver;

   GP<DjVuPort>		simple_port;

   GMonitor		chunk_mon, finish_mon;

      // Functions called when the decoding thread starts
   static void	static_decode_func(void *);
   void	decode_func(void);
   void	decode(const GP<ByteStream> &str);
   GUTF8String decode_chunk(const GUTF8String &chkid,
     const GP<ByteStream> &str, bool djvi, bool djvu, bool iw44);
   int		get_dpi(int w, int h);

      // Functions dealing with the shape directory (fgjd)
   static GP<JB2Dict> static_get_fgjd(void *);
   GP<JB2Dict> get_fgjd(int block=0);

      // Functions used to wait for smth
   void		wait_for_chunk(void);
   bool		wait_for_finish(bool self);

      // INCL chunk processor
   GP<DjVuFile>	process_incl_chunk(ByteStream & str, int file_num=-1);

      // Trigger: called when DataPool has all data
   static void	static_trigger_cb(void *);
   void		trigger_cb(void);
   
      // Progress callback: called from time to time
   static void	progress_cb(int pos, void *);
   static void	get_merged_anno(const GP<DjVuFile> & file,
     const GP<ByteStream> &str_out, const GList<GURL> & ignore_list,
     int level, int & max_level, GMap<GURL, void *> & map);
   static void	get_anno(const GP<DjVuFile> & file,
     const GP<ByteStream> &str_out);
   static void	get_text(const GP<DjVuFile> & file,
     const GP<ByteStream> &str_out);
   static void	get_meta(const GP<DjVuFile> & file,
     const GP<ByteStream> &str_out);

   void          check() const;
   GP<DjVuNavDir>find_ndir(GMap<GURL, void *> & map);
   GP<DjVuNavDir>decode_ndir(GMap<GURL, void *> & map);
   void		add_djvu_data(IFFByteStream & str,
			      GMap<GURL, void *> & map,
			      const bool included_too, const bool no_ndir=true);
   void		move(GMap<GURL, void *> & map, const GURL & dir_url);
private: // dummy stuff
   static void decode(ByteStream *);
   static GUTF8String decode_chunk(const GUTF8String &, ByteStream *,bool,bool,bool);
   static void	get_merged_anno(const GP<DjVuFile> &,ByteStream *,
     const GList<GURL> &, int, int &, GMap<GURL, void *> &);
   static void	get_text(const GP<DjVuFile> &,ByteStream *);
   static void	get_meta(const GP<DjVuFile> &,ByteStream *);

};

inline long
DjVuFile::get_flags(void) const
{
   return flags;
}

inline GSafeFlags &
DjVuFile::get_safe_flags(void)
{
   return flags;
}

inline bool
DjVuFile::is_decoding(void) const
{
   return (flags & DECODING)!=0;
}

inline bool
DjVuFile::is_decode_ok(void) const
{
   return (flags & DECODE_OK)!=0;
}

inline bool
DjVuFile::is_decode_failed(void) const
{
   return (flags & DECODE_FAILED)!=0;
}

inline bool
DjVuFile::is_decode_stopped(void) const
{
   return (flags & DECODE_STOPPED)!=0;
}

inline bool
DjVuFile::is_data_present(void) const
{
   return (flags & DATA_PRESENT)!=0;
}

inline bool
DjVuFile::is_all_data_present(void) const
{
   return (flags & ALL_DATA_PRESENT)!=0;
}

inline bool
DjVuFile::are_incl_files_created(void) const
{
   return (flags & INCL_FILES_CREATED)!=0;
}

inline bool
DjVuFile::is_modified(void) const
{
   return (flags & MODIFIED)!=0;
}

inline void
DjVuFile::set_modified(bool m)
{
  flags=m ? (flags | MODIFIED) : (flags & ~MODIFIED);
}

inline bool
DjVuFile::needs_compression(void) const
{
   return (flags & NEEDS_COMPRESSION)!=0;
}

inline void
DjVuFile::set_needs_compression(bool m)
{
   if (m) flags=flags | NEEDS_COMPRESSION;
   else flags=flags & ~NEEDS_COMPRESSION;
}

inline bool
DjVuFile::can_compress(void) const
{
   return (flags & CAN_COMPRESS)!=0;
}

inline void
DjVuFile::set_can_compress(bool m)
{
   if(info)
   {
     info->compressable=m;
   }
   if (m)
   {
     flags=flags | CAN_COMPRESS;
   } else
   {
     flags=flags & ~CAN_COMPRESS;
   }
}

inline void
DjVuFile::disable_standard_port(void)
{
   simple_port=0;
}

inline bool
DjVuFile::inherits(const GUTF8String &class_name) const
{
   return
      (GUTF8String("DjVuFile") == class_name) ||
      DjVuPort::inherits(class_name);
//      !strcmp("DjVuFile", class_name) ||
//      DjVuPort::inherits(class_name);
}

inline void
DjVuFile::wait_for_finish(void)
{
   while(wait_for_finish(1))
     EMPTY_LOOP;
}

inline GURL
DjVuFile::get_url(void) const
{
   return url;
}

inline void
DjVuFile::set_verbose_eof
(const bool verbose)
{
  verbose_eof=verbose;
}

inline void
DjVuFile::set_recover_errors
(const ErrorRecoveryAction action)
{
  recover_errors=action;
}

//@}


#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif
#endif