1 //C-  -*- C++ -*-
2 //C- -------------------------------------------------------------------
3 //C- DjVuLibre-3.5
4 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5 //C- Copyright (c) 2001  AT&T
6 //C-
7 //C- This software is subject to, and may be distributed under, the
8 //C- GNU General Public License, either Version 2 of the license,
9 //C- or (at your option) any later version. The license should have
10 //C- accompanied the software or you may obtain a copy of the license
11 //C- from the Free Software Foundation at http://www.fsf.org .
12 //C-
13 //C- This program is distributed in the hope that it will be useful,
14 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //C- GNU General Public License for more details.
17 //C-
18 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19 //C- Lizardtech Software.  Lizardtech Software has authorized us to
20 //C- replace the original DjVu(r) Reference Library notice by the following
21 //C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22 //C-
23 //C-  ------------------------------------------------------------------
24 //C- | DjVu (r) Reference Library (v. 3.5)
25 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
27 //C- | 6,058,214 and patents pending.
28 //C- |
29 //C- | This software is subject to, and may be distributed under, the
30 //C- | GNU General Public License, either Version 2 of the license,
31 //C- | or (at your option) any later version. The license should have
32 //C- | accompanied the software or you may obtain a copy of the license
33 //C- | from the Free Software Foundation at http://www.fsf.org .
34 //C- |
35 //C- | The computer code originally released by LizardTech under this
36 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
37 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
38 //C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39 //C- | non-exclusive license to make, use, sell, or otherwise dispose of
40 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42 //C- | General Public License.   This grant only confers the right to
43 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44 //C- | the extent such infringement is reasonably necessary to enable
45 //C- | recipient to make, have made, practice, sell, or otherwise dispose
46 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47 //C- | any greater extent that may be necessary to utilize further
48 //C- | modifications or combinations.
49 //C- |
50 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54 //C- +------------------------------------------------------------------
55 
56 #ifdef HAVE_CONFIG_H
57 # include "config.h"
58 #endif
59 #if NEED_GNUG_PRAGMAS
60 # pragma implementation
61 #endif
62 
63 #include "DjVuPort.h"
64 #include "GOS.h"
65 #include "DjVuImage.h"
66 #include "DjVuDocument.h"
67 #include "DjVuFile.h"
68 #include "DjVuMessageLite.h"
69 #include "DataPool.h"
70 
71 
72 #ifdef HAVE_NAMESPACES
73 namespace DJVU {
74 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
75 }
76 #endif
77 #endif
78 
79 
80 //****************************************************************************
81 //******************************* Globals ************************************
82 //****************************************************************************
83 
84 static DjVuPortcaster *pcaster;
85 
86 DjVuPortcaster *
get_portcaster(void)87 DjVuPort::get_portcaster(void)
88 {
89    if (!pcaster) pcaster = new DjVuPortcaster();
90    return pcaster;
91 }
92 
93 class DjVuPort::DjVuPortCorpse
94 {
95 public:
96    DjVuPort		* port;
97    DjVuPortCorpse	* next;
98 
DjVuPortCorpse(DjVuPort * _port)99    DjVuPortCorpse(DjVuPort * _port) : port(_port), next(0) {}
100 };
101 
102 //****************************************************************************
103 //******************************* DjVuPort ***********************************
104 //****************************************************************************
105 
106 #define MAX_CORPSE_NUM	128
107 
108 // Last MAX_CORPSE_NUM addresses of dead DjVuPorts. We want to maintain this
109 // list because of the way DjVuPort::is_port_alive() works: it accepts an
110 // address and runs it thru its internal maps. The problem will occur if
111 // a new DjVuPort is created exactly on place of another one, which just
112 // died. Here we attempt to remember the last MAX_CORPSE_NUM addresses
113 // of dead DjVuPorts, and take them into account in DjVuPort::operator new();
114 GCriticalSection * DjVuPort::corpse_lock;
115 DjVuPort::DjVuPortCorpse	* DjVuPort::corpse_head;
116 DjVuPort::DjVuPortCorpse	* DjVuPort::corpse_tail;
117 int		DjVuPort::corpse_num;
118 
119 void *
operator new(size_t sz)120 DjVuPort::operator new (size_t sz)
121 {
122   if (!corpse_lock) corpse_lock=new GCriticalSection();
123 
124   // Loop until we manage to allocate smth, which is not mentioned in
125   // the 'corpse' list. Thus we will avoid allocating a new DjVuPort
126   // on place of a dead one. Not *absolutely* secure (only 64 items
127   // in the list) but is still better than nothing.
128   void * addr=0;
129   {
130     GCriticalSectionLock lock(corpse_lock);
131 
132     // Store here addresses, which were found in 'corpse' list.
133     // We will free then in the end
134     int addr_num=0;
135     static void * addr_arr[MAX_CORPSE_NUM];
136 
137     // Make at most MAX_CORPSE_NUM attempts. During each attempt
138     // we try to allocate a block of memory for DjVuPort. If
139     // the address of this block is not in the corpse list, we break
140     // All addresses will be recorder, so that we can delete them
141     // after we're done.
142     for(int attempt=0;attempt<MAX_CORPSE_NUM;attempt++)
143     {
144       void * test_addr=::operator new (sz);
145       addr_arr[addr_num++]=test_addr;
146 
147       // See if 'test_addr' is in the 'corpse' list (was recently used)
148       DjVuPortCorpse * corpse;
149       for(corpse=corpse_head;corpse;corpse=corpse->next)
150         if (test_addr==corpse->port) break;
151       if (!corpse)
152         {
153           addr=test_addr;
154           addr_num--;
155           break;
156         }
157     }
158     // If all attempts failed (all addresses generated are already
159     // in the list of corpses, allocate a new one and proceed
160     // w/o additional checks
161     if (!addr) addr=::operator new(sz);
162 
163     // Here 'addr_arr[0<=i<addr_num]' contains addresses, that we
164     // tried to allocate, and which need to be freed now
165     // 'addr' contains address we want to use.
166     addr_num--;
167     while(addr_num>=0) ::operator delete(addr_arr[addr_num--]);
168   }
169 
170   DjVuPortcaster * pcaster=get_portcaster();
171   GCriticalSectionLock lock(&pcaster->map_lock);
172   pcaster->cont_map[addr]=0;
173   return addr;
174 }
175 
176 void
operator delete(void * addr)177 DjVuPort::operator delete(void * addr)
178 {
179   if (corpse_lock)
180   {
181     GCriticalSectionLock lock(corpse_lock);
182 
183     // Add 'addr' to the list of corpses
184     if (corpse_tail)
185     {
186       corpse_tail->next=new DjVuPortCorpse((DjVuPort *) addr);
187       corpse_tail=corpse_tail->next;
188       corpse_tail->next=0;
189     } else
190     {
191       corpse_head=corpse_tail=new DjVuPortCorpse((DjVuPort *) addr);
192       corpse_tail->next=0;
193     }
194     corpse_num++;
195     if (corpse_num>=MAX_CORPSE_NUM)
196     {
197       DjVuPortCorpse * corpse=corpse_head;
198       corpse_head=corpse_head->next;
199       delete corpse;
200       corpse_num--;
201     }
202   }
203   ::operator delete(addr);
204 }
205 
DjVuPort()206 DjVuPort::DjVuPort()
207 {
208   DjVuPortcaster *pcaster = get_portcaster();
209   GCriticalSectionLock lock(& pcaster->map_lock );
210   GPosition p = pcaster->cont_map.contains(this);
211   if (!p) G_THROW( ERR_MSG("DjVuPort.not_alloc") );
212   pcaster->cont_map[p] = (void*)this;
213 }
214 
DjVuPort(const DjVuPort & port)215 DjVuPort::DjVuPort(const DjVuPort & port)
216 {
217   DjVuPortcaster *pcaster = get_portcaster();
218   GCriticalSectionLock lock(& pcaster->map_lock );
219   GPosition p = pcaster->cont_map.contains(this);
220   if (!p) G_THROW( ERR_MSG("DjVuPort.not_alloc") );
221   pcaster->cont_map[p] = (void*)this;
222   pcaster->copy_routes(this, &port);
223 }
224 
225 DjVuPort &
operator =(const DjVuPort & port)226 DjVuPort::operator=(const DjVuPort & port)
227 {
228    if (this != &port)
229       get_portcaster()->copy_routes(this, &port);
230    return *this;
231 }
232 
~DjVuPort(void)233 DjVuPort::~DjVuPort(void)
234 {
235   get_portcaster()->del_port(this);
236 }
237 
238 
239 //****************************************************************************
240 //**************************** DjVuPortcaster ********************************
241 //****************************************************************************
242 
243 
244 
DjVuPortcaster(void)245 DjVuPortcaster::DjVuPortcaster(void)
246 {
247 }
248 
~DjVuPortcaster(void)249 DjVuPortcaster::~DjVuPortcaster(void)
250 {
251    GCriticalSectionLock lock(&map_lock);
252    for(GPosition pos=route_map;pos;++pos)
253       delete (GList<void *> *) route_map[pos];
254 }
255 
256 GP<DjVuPort>
is_port_alive(DjVuPort * port)257 DjVuPortcaster::is_port_alive(DjVuPort *port)
258 {
259    GP<DjVuPort> gp_port;
260    GCriticalSectionLock lock(&map_lock);
261    GPosition pos=cont_map.contains(port);
262    if (pos && cont_map[pos] && ((DjVuPort *) port)->get_count()>0)
263       gp_port=port;
264    if (gp_port && gp_port->get_count() <= 0)
265       gp_port = 0;
266    return gp_port;
267 }
268 
269 void
add_alias(const DjVuPort * port,const GUTF8String & alias)270 DjVuPortcaster::add_alias(const DjVuPort * port, const GUTF8String &alias)
271 {
272    GCriticalSectionLock lock(&map_lock);
273    a2p_map[alias]=port;
274 }
275 
276 void
clear_all_aliases(void)277 DjVuPortcaster::clear_all_aliases(void)
278 {
279   DjVuPortcaster *p=get_portcaster();
280   GCriticalSectionLock lock(&(p->map_lock));
281   GPosition pos;
282   while((pos=p->a2p_map))
283   {
284     p->a2p_map.del(pos);
285   }
286 }
287 
288 void
clear_aliases(const DjVuPort * port)289 DjVuPortcaster::clear_aliases(const DjVuPort * port)
290 {
291   GCriticalSectionLock lock(&map_lock);
292   for(GPosition pos=a2p_map;pos;)
293     if (a2p_map[pos]==port)
294     {
295       GPosition this_pos=pos;
296       ++pos;
297       a2p_map.del(this_pos);
298     } else ++pos;
299 }
300 
301 GP<DjVuPort>
alias_to_port(const GUTF8String & alias)302 DjVuPortcaster::alias_to_port(const GUTF8String &alias)
303 {
304    GCriticalSectionLock lock(&map_lock);
305    GPosition pos;
306    if (a2p_map.contains(alias, pos))
307    {
308       DjVuPort * port=(DjVuPort *) a2p_map[pos];
309       GP<DjVuPort> gp_port=is_port_alive(port);
310       if (gp_port) return gp_port;
311       else a2p_map.del(pos);
312    }
313    return 0;
314 }
315 
316 GPList<DjVuPort>
prefix_to_ports(const GUTF8String & prefix)317 DjVuPortcaster::prefix_to_ports(const GUTF8String &prefix)
318 {
319   GPList<DjVuPort> list;
320   {
321     int length=prefix.length();
322     if (length)
323     {
324       GCriticalSectionLock lock(&map_lock);
325       for(GPosition pos=a2p_map;pos;++pos)
326         if (!prefix.cmp(a2p_map.key(pos), length))
327         {
328           DjVuPort * port=(DjVuPort *) a2p_map[pos];
329           GP<DjVuPort> gp_port=is_port_alive(port);
330           if (gp_port) list.append(gp_port);
331         }
332     }
333   }
334   return list;
335 }
336 
337 void
del_port(const DjVuPort * port)338 DjVuPortcaster::del_port(const DjVuPort * port)
339 {
340   GCriticalSectionLock lock(&map_lock);
341 
342   GPosition pos;
343 
344   // Update the "aliases map"
345   clear_aliases(port);
346 
347   // Update "contents map"
348   if (cont_map.contains(port, pos)) cont_map.del(pos);
349 
350   // Update "route map"
351   if (route_map.contains(port, pos))
352   {
353     delete (GList<void *> *) route_map[pos];
354     route_map.del(pos);
355   }
356   for(pos=route_map;pos;)
357   {
358     GList<void *> & list=*(GList<void *> *) route_map[pos];
359     GPosition list_pos;
360     if (list.search((void *) port, list_pos)) list.del(list_pos);
361     if (!list.size())
362     {
363       delete &list;
364       GPosition tmp_pos=pos;
365       ++pos;
366       route_map.del(tmp_pos);
367     } else ++pos;
368   }
369 }
370 
371 void
add_route(const DjVuPort * src,DjVuPort * dst)372 DjVuPortcaster::add_route(const DjVuPort * src, DjVuPort * dst)
373       // Adds route src->dst
374 {
375    GCriticalSectionLock lock(&map_lock);
376    if (cont_map.contains(src) && src->get_count()>0 &&
377        cont_map.contains(dst) && dst->get_count()>0)
378    {
379       if (!route_map.contains(src)) route_map[src]=new GList<void *>();
380       GList<void *> & list=*(GList<void *> *) route_map[src];
381       if (!list.contains(dst)) list.append(dst);
382    }
383 }
384 
385 void
del_route(const DjVuPort * src,DjVuPort * dst)386 DjVuPortcaster::del_route(const DjVuPort * src, DjVuPort * dst)
387 // Deletes route src->dst
388 {
389   GCriticalSectionLock lock(&map_lock);
390 
391   if (route_map.contains(src))
392   {
393     GList<void *> & list=*(GList<void *> *) route_map[src];
394     GPosition pos;
395     if (list.search(dst, pos)) list.del(pos);
396     if (!list.size())
397     {
398       delete &list;
399       route_map.del(src);
400     }
401   }
402 }
403 
404 void
copy_routes(DjVuPort * dst,const DjVuPort * src)405 DjVuPortcaster::copy_routes(DjVuPort * dst, const DjVuPort * src)
406       // For every route src->x or x->src, it creates a new one:
407       // dst->x or x->dst respectively. It's useful when you create a copy
408       // of a port and you want the copy to stay connected.
409 {
410   GCriticalSectionLock lock(&map_lock);
411 
412   if (!cont_map.contains(src) || src->get_count()<=0 ||
413     !cont_map.contains(dst) || dst->get_count()<=0) return;
414 
415   for(GPosition pos=route_map;pos;++pos)
416   {
417     GList<void *> & list=*(GList<void *> *) route_map[pos];
418     if (route_map.key(pos) == src)
419       for(GPosition pos=list;pos;++pos)
420         add_route(dst, (DjVuPort *) list[pos]);
421     for(GPosition pos=list;pos;++pos)
422       if ((DjVuPort*)(list[pos]) == src)
423         add_route((DjVuPort *) route_map.key(pos), dst);
424   }
425 }
426 
427 void
add_to_closure(GMap<const void *,void * > & set,const DjVuPort * dst,int distance)428 DjVuPortcaster::add_to_closure(GMap<const void *, void *> & set,
429 			       const DjVuPort * dst, int distance)
430 {
431   // Assuming that the map's already locked
432   // GCriticalSectionLock lock(&map_lock);
433   set[dst]= (void*) (size_t) distance;
434   if (route_map.contains(dst))
435     {
436       GList<void *> & list=*(GList<void *> *) route_map[dst];
437       for(GPosition pos=list;pos;++pos)
438         {
439           DjVuPort * new_dst=(DjVuPort *) list[pos];
440           if (!set.contains(new_dst))
441             add_to_closure(set, new_dst, distance+1);
442         }
443    }
444 }
445 
446 void
compute_closure(const DjVuPort * src,GPList<DjVuPort> & list,bool sorted)447 DjVuPortcaster::compute_closure(const DjVuPort * src, GPList<DjVuPort> &list, bool sorted)
448 {
449    GCriticalSectionLock lock(&map_lock);
450    GMap<const void*, void*> set;
451    if (route_map.contains(src))
452    {
453       GList<void *> & list=*(GList<void *> *) route_map[src];
454       for(GPosition pos=list;pos;++pos)
455       {
456 	       DjVuPort * dst=(DjVuPort *) list[pos];
457 	       if (dst==src) add_to_closure(set, src, 0);
458 	       else add_to_closure(set, dst, 1);
459       }
460    }
461 
462    // Compute list
463    GPosition pos;
464    if (sorted)
465      {
466        // Sort in depth order
467        int max_dist=0;
468        for(pos=set;pos;++pos)
469          if (max_dist < (int)(size_t)set[pos])
470            max_dist = (int)(size_t)set[pos];
471        GArray<GList<const void*> > lists(0,max_dist);
472        for(pos=set;pos;++pos)
473          lists[(int)(size_t)set[pos]].append(set.key(pos));
474        for(int dist=0;dist<=max_dist;dist++)
475          for(pos=lists[dist];pos;++pos)
476            {
477              GP<DjVuPort> p = is_port_alive((DjVuPort*) lists[dist][pos]);
478              if (p) list.append(p);
479            }
480      }
481    else
482      {
483        // Gather ports without order
484        for(pos=set;pos;++pos)
485          {
486            GP<DjVuPort> p = is_port_alive((DjVuPort*) set.key(pos));
487            if (p) list.append(p);
488          }
489      }
490 }
491 
492 GURL
id_to_url(const DjVuPort * source,const GUTF8String & id)493 DjVuPortcaster::id_to_url(const DjVuPort * source, const GUTF8String &id)
494 {
495    GPList<DjVuPort> list;
496    compute_closure(source, list, true);
497    GURL url;
498    for(GPosition pos=list;pos;++pos)
499    {
500       url=list[pos]->id_to_url(source, id);
501       if (!url.is_empty()) break;
502    }
503    return url;
504 }
505 
506 GP<DjVuFile>
id_to_file(const DjVuPort * source,const GUTF8String & id)507 DjVuPortcaster::id_to_file(const DjVuPort * source, const GUTF8String &id)
508 {
509    GPList<DjVuPort> list;
510    compute_closure(source, list, true);
511    GP<DjVuFile> file;
512    for(GPosition pos=list;pos;++pos)
513       if ((file=list[pos]->id_to_file(source, id))) break;
514    return file;
515 }
516 
517 GP<DataPool>
request_data(const DjVuPort * source,const GURL & url)518 DjVuPortcaster::request_data(const DjVuPort * source, const GURL & url)
519 {
520    GPList<DjVuPort> list;
521    compute_closure(source, list, true);
522    GP<DataPool> data;
523    for(GPosition pos=list;pos;++pos)
524      if ((data = list[pos]->request_data(source, url)))
525        break;
526    return data;
527 }
528 
529 bool
notify_error(const DjVuPort * source,const GUTF8String & msg)530 DjVuPortcaster::notify_error(const DjVuPort * source, const GUTF8String &msg)
531 {
532    GPList<DjVuPort> list;
533    compute_closure(source, list, true);
534    for(GPosition pos=list;pos;++pos)
535      if (list[pos]->notify_error(source, msg))
536        return 1;
537    return 0;
538 }
539 
540 bool
notify_status(const DjVuPort * source,const GUTF8String & msg)541 DjVuPortcaster::notify_status(const DjVuPort * source, const GUTF8String &msg)
542 {
543    GPList<DjVuPort> list;
544    compute_closure(source, list, true);
545    for(GPosition pos=list;pos;++pos)
546      if (list[pos]->notify_status(source, msg))
547        return 1;
548    return 0;
549 }
550 
551 void
notify_redisplay(const DjVuImage * source)552 DjVuPortcaster::notify_redisplay(const DjVuImage * source)
553 {
554    GPList<DjVuPort> list;
555    compute_closure(source, list);
556    for(GPosition pos=list; pos; ++pos)
557      list[pos]->notify_redisplay(source);
558 }
559 
560 void
notify_relayout(const DjVuImage * source)561 DjVuPortcaster::notify_relayout(const DjVuImage * source)
562 {
563    GPList<DjVuPort> list;
564    compute_closure(source, list);
565    for(GPosition pos=list; pos; ++pos)
566      list[pos]->notify_relayout(source);
567 }
568 
569 void
notify_chunk_done(const DjVuPort * source,const GUTF8String & name)570 DjVuPortcaster::notify_chunk_done(const DjVuPort * source, const GUTF8String &name)
571 {
572    GPList<DjVuPort> list;
573    compute_closure(source, list);
574    for(GPosition pos=list; pos; ++pos)
575      list[pos]->notify_chunk_done(source, name);
576 }
577 
578 void
notify_file_flags_changed(const DjVuFile * source,long set_mask,long clr_mask)579 DjVuPortcaster::notify_file_flags_changed(const DjVuFile * source,
580 					  long set_mask, long clr_mask)
581 {
582    GPList<DjVuPort> list;
583    compute_closure(source, list);
584    for(GPosition pos=list; pos; ++pos)
585      list[pos]->notify_file_flags_changed(source, set_mask, clr_mask);
586 }
587 
588 void
notify_doc_flags_changed(const DjVuDocument * source,long set_mask,long clr_mask)589 DjVuPortcaster::notify_doc_flags_changed(const DjVuDocument * source,
590 					 long set_mask, long clr_mask)
591 {
592    GPList<DjVuPort> list;
593    compute_closure(source, list);
594    for(GPosition pos=list; pos; ++pos)
595      list[pos]->notify_doc_flags_changed(source, set_mask, clr_mask);
596 }
597 
598 void
notify_decode_progress(const DjVuPort * source,float done)599 DjVuPortcaster::notify_decode_progress(const DjVuPort * source, float done)
600 {
601    GPList<DjVuPort> list;
602    compute_closure(source, list);
603    for(GPosition pos=list; pos; ++pos)
604      list[pos]->notify_decode_progress(source, done);
605 }
606 
607 //****************************************************************************
608 //******************************* DjVuPort ***********************************
609 //****************************************************************************
610 
611 GURL
id_to_url(const DjVuPort *,const GUTF8String &)612 DjVuPort::id_to_url(const DjVuPort *, const GUTF8String &) { return GURL(); }
613 
614 GP<DjVuFile>
id_to_file(const DjVuPort *,const GUTF8String &)615 DjVuPort::id_to_file(const DjVuPort *, const GUTF8String &) { return 0; }
616 
617 GP<DataPool>
request_data(const DjVuPort *,const GURL &)618 DjVuPort::request_data(const DjVuPort *, const GURL &) { return 0; }
619 
620 bool
notify_error(const DjVuPort *,const GUTF8String &)621 DjVuPort::notify_error(const DjVuPort *, const GUTF8String &) { return 0; }
622 
623 bool
notify_status(const DjVuPort *,const GUTF8String &)624 DjVuPort::notify_status(const DjVuPort *, const GUTF8String &) { return 0; }
625 
626 void
notify_redisplay(const DjVuImage *)627 DjVuPort::notify_redisplay(const DjVuImage *) {}
628 
629 void
notify_relayout(const DjVuImage *)630 DjVuPort::notify_relayout(const DjVuImage *) {}
631 
632 void
notify_chunk_done(const DjVuPort *,const GUTF8String &)633 DjVuPort::notify_chunk_done(const DjVuPort *, const GUTF8String &) {}
634 
635 void
notify_file_flags_changed(const DjVuFile *,long,long)636 DjVuPort::notify_file_flags_changed(const DjVuFile *, long, long) {}
637 
638 void
notify_doc_flags_changed(const DjVuDocument *,long,long)639 DjVuPort::notify_doc_flags_changed(const DjVuDocument *, long, long) {}
640 
641 void
notify_decode_progress(const DjVuPort *,float)642 DjVuPort::notify_decode_progress(const DjVuPort *, float) {}
643 
644 //****************************************************************************
645 //*************************** DjVuSimplePort *********************************
646 //****************************************************************************
647 
648 GP<DataPool>
request_data(const DjVuPort * source,const GURL & url)649 DjVuSimplePort::request_data(const DjVuPort * source, const GURL & url)
650 {
651   G_TRY {
652     if (url.is_local_file_url())
653     {
654 //      GUTF8String fname=GOS::url_to_filename(url);
655 //      if (GOS::basename(fname)=="-") fname="-";
656       return DataPool::create(url);
657     }
658   } G_CATCH_ALL {} G_ENDCATCH;
659   return 0;
660 }
661 
662 bool
notify_error(const DjVuPort * source,const GUTF8String & msg)663 DjVuSimplePort::notify_error(const DjVuPort * source, const GUTF8String &msg)
664 {
665    DjVuMessageLite::perror(msg);
666    return 1;
667 }
668 
669 bool
notify_status(const DjVuPort * source,const GUTF8String & msg)670 DjVuSimplePort::notify_status(const DjVuPort * source, const GUTF8String &msg)
671 {
672    DjVuMessageLite::perror(msg);
673    return 1;
674 }
675 
676 
677 
678 
679 
680 //****************************************************************************
681 //*************************** DjVuMemoryPort *********************************
682 //****************************************************************************
683 
684 
685 
686 GP<DataPool>
request_data(const DjVuPort * source,const GURL & url)687 DjVuMemoryPort::request_data(const DjVuPort * source, const GURL & url)
688 {
689    GCriticalSectionLock lk(&lock);
690    GP<DataPool> pool;
691    GPosition pos;
692    if (map.contains(url, pos))
693       pool=map[pos];
694    return pool;
695 }
696 
697 void
add_data(const GURL & url,const GP<DataPool> & pool)698 DjVuMemoryPort::add_data(const GURL & url, const GP<DataPool> & pool)
699 {
700    GCriticalSectionLock lk(&lock);
701    map[url]=pool;
702 }
703 
704 
705 #ifdef HAVE_NAMESPACES
706 }
707 # ifndef NOT_USING_DJVU_NAMESPACE
708 using namespace DJVU;
709 # endif
710 #endif
711 
712