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