GMap<GUTF8String, GUTF8String>
DjVuANT::get_metadata(GLParser & parser)
{
  DEBUG_MSG("DjVuANT::get_map_areas(): forming and returning back list of map areas\n");
  DEBUG_MAKE_INDENT(3);
  
  GMap<GUTF8String, GUTF8String> mdata;
  
  GPList<GLObject> list=parser.get_list();
  for(GPosition pos=list;pos;++pos)
    {
      GLObject & obj=*list[pos];
      if (obj.get_type()==GLObject::LIST && obj.get_name()==METADATA_TAG)  
        { 
          G_TRY 
            {
              for(int obj_num=0;obj_num<obj.get_list().size();obj_num++)
                {
                  GLObject & el=*obj[obj_num];
                  const int type = el.get_type();
                  if (type == GLObject::LIST)
                    { 
                      const GUTF8String & name=el.get_name();  
                      mdata[name]=(el[0])->get_string();
                    }
                }
            } 
          G_CATCH_ALL { } G_ENDCATCH;
        }
    }
void
GIFFChunk::set_name(GUTF8String name)
{
  DEBUG_MSG("GIFFChunk::set_name(): name='" << name << "'\n");
  DEBUG_MAKE_INDENT(3);

  const int colon=name.search(':');
  if(colon>=0)
  {
    type=name.substr(0,colon);
    name=name.substr(colon+1,(unsigned int)-1);
    if(name.search(':')>=0)
      G_THROW( ERR_MSG("GIFFManager.one_colon") );
  }

  DEBUG_MSG("auto-setting type to '" << type << "'\n");

  if (name.contains(".[]")>=0)
    G_THROW( ERR_MSG("GIFFManager.bad_char") );

  strncpy(GIFFChunk::name, (const char *)name, 4);
  GIFFChunk::name[4]=0;
  for(int i=strlen(GIFFChunk::name);i<4;i++)
    GIFFChunk::name[i]=' ';
}
void
QDBase::createCursors(void)
{
   DEBUG_MSG("QDBase::createCursors(): loading cursors...\n");
   DEBUG_MAKE_INDENT(3);
#ifdef UNIX
   QSize wait_size(wait_width, wait_height);
   cur_wait=new QCursor(QBitmap(wait_size, (u_char *) wait_bits, TRUE),
		    QBitmap(wait_size, (u_char *) wait_mask_bits, TRUE),
		    wait_x, wait_y);

   QSize hand1_size(hand1_width, hand1_height);
   cur_hand1=new QCursor(QBitmap(hand1_size, (u_char *) hand1_bits, TRUE),
		     QBitmap(hand1_size, (u_char *) hand1_mask_bits, TRUE),
		     hand1_x, hand1_y);

   QSize hand2_size(hand2_width, hand2_height);
   cur_hand2=new QCursor(QBitmap(hand2_size, (u_char *) hand2_bits, TRUE),
		     QBitmap(hand2_size, (u_char *) hand2_mask_bits, TRUE),
		     hand2_x, hand2_y);

   QSize zoom_select_size(zoom_select_width, zoom_select_height);
   cur_zoom_select=new QCursor(QBitmap(zoom_select_size, 
                                       (u_char *) zoom_select_bits, TRUE),
                               QBitmap(zoom_select_size, 
                                       (u_char *) zoom_select_mask_bits, TRUE),
		     zoom_select_x, zoom_select_y);

   cur_hand_hl=new QCursor(ArrowCursor);	// TODO: get X11 cursor instead
   cur_ptr=new QCursor(ArrowCursor);
   cur_blank=new QCursor(BlankCursor);
#endif
}
void
QDBase::slotDisableDisplayAllHLinks(void)
{
   DEBUG_MSG("QDBase::slotDisableDisplayAllHLinks() called\n");
   DEBUG_MAKE_INDENT(3);

   try
   {
      if (!display_all_hlinks)
      {
	 DEBUG_MSG("already disabled => returning\n");
	 return;
      }

      GRect grect;
      grect.intersect(rectVisible, rectDocument);

	 // We want to hide here
      for(GPosition pos=map_areas;pos;++pos)
      {
	 GP<MapArea> ma=map_areas[pos];
	 ma->setForceAlwaysActive(false);
	 ma->setActive(false, true);
      }

      display_all_hlinks=0;
   } catch(const GException & exc)
   {
      showError(this, tr("DjVu Error"), exc);
   }
}
int
GIFFManager::get_chunks_number(void)
{
  DEBUG_MSG("GIFFManager::get_chunks_number()\n");
  DEBUG_MAKE_INDENT(3);
  return top_level->get_chunks_number();
}
void
GIFFChunk::save(IFFByteStream & istr, bool use_trick)
{
  DEBUG_MSG("GIFFChunk::save(): saving chunk '" << get_full_name() << "'\n");
  DEBUG_MAKE_INDENT(3);

  if (is_container())
  {
    istr.put_chunk(get_full_name(), use_trick);
    if (chunks.size())
    {
      GPosition pos;
      for(pos=chunks;pos;++pos)
        if (chunks[pos]->get_type()=="PROP")
          chunks[pos]->save(istr);
      for(pos=chunks;pos;++pos)
        if (chunks[pos]->get_type()!="PROP")
          chunks[pos]->save(istr);
    } else
    {
      DEBUG_MSG("but it's empty => saving empty container.\n");
    }
    istr.close_chunk();
  } else
  {
    istr.put_chunk(get_name(), use_trick);
    istr.get_bytestream()->writall((const char *) data, data.size());
    istr.close_chunk();
  }
}
void
GIFFChunk::add_chunk(const GP<GIFFChunk> & chunk, int position)
{
  DEBUG_MSG("GIFFChunk::add_chunk(): Adding chunk to '" << get_name() <<
     "' @ position=" << position << "\n");
  DEBUG_MAKE_INDENT(3);

  if (!type.length())
  {
    DEBUG_MSG("Converting the parent to FORM\n");
    type="FORM";
  }

  if (chunk->get_type()=="PROP")
  {
    DEBUG_MSG("Converting the parent to LIST\n");
    type="LIST";
  }

  GPosition pos;
  if (position>=0 && chunks.nth(position, pos))
  {
    chunks.insert_before(pos, chunk);
  }else
  {
    chunks.append(chunk);
  }
}
Exemplo n.º 8
0
void
DjVuFileCache::add_file(const GP<DjVuFile> & file)
{
   DEBUG_MSG("DjVuFileCache::add_file(): trying to add a new item\n");
   DEBUG_MAKE_INDENT(3);

   GCriticalSectionLock lock(&class_lock);

      // See if the file is already cached
   GPosition pos;
   for(pos=list;pos;++pos)
      if (list[pos]->get_file()==file) break;
   
   if (pos) list[pos]->refresh();	// Refresh the timestamp
   else
   {
	 // Doesn't exist in the list yet
      int _max_size=enabled ? max_size : 0;
      if (max_size<0) _max_size=max_size;

      int add_size=file->get_memory_usage();
   
      if (_max_size>=0 && add_size>_max_size)
      {
	 DEBUG_MSG("but this item is way too large => doing nothing\n");
	 return;
      }

      if (_max_size>=0) clear_to_size(_max_size-add_size);

      list.append(new Item(file));
      cur_size+=add_size;
      file_added(file);
   }
}
void
GIFFChunk::del_chunk(const GUTF8String &name)
   // The name may contain brackets to specify the chunk number
{
  DEBUG_MSG("GIFFChunk::del_chunk(): Deleting chunk '" << name <<
     "' from '" << get_name() << "'\n");
  DEBUG_MAKE_INDENT(3);

  int number;
  const GUTF8String short_name=decode_name(name,number);

  GPosition pos=chunks;
  for(int num=0;pos;++pos)
  {
    if ((chunks[pos]->get_name()==short_name)&&(num++ == number))
    {
      chunks.del(pos);
      break;
    }
  }
  if(! pos)
  {
    G_THROW( ERR_MSG("GIFFManager.no_chunk") "\t"+short_name+"\t"+GUTF8String(number)+"\t"+get_name());
  }
}
void
DjVuViewer::attach(QWidget * parent)
{
   DEBUG_MSG("DjVuViewer::attach(): attaching to parent=" << parent << "\n");
   DEBUG_MAKE_INDENT(3);

   qeApp->killWidget(viewer); viewer=0;
   
   if (!doc_pool)
   {
	 // Postpone attachment until the data is known.
      attach_postpone=true;
      attach_parent=parent;
   } else
   {
      viewer=new QDViewer(in_netscape, plugin_data, parent, "qd_viewer");
      connect(viewer, SIGNAL(destroyed(void)), this, SLOT(slotViewerDestroyed(void)));
      connect(viewer, SIGNAL(sigShowStatus(const QString &)),
	      this, SIGNAL(sigShowStatus(const QString &)));
      connect(viewer, SIGNAL(sigGetURL(const GURL &, const GUTF8String &)),
	      this, SIGNAL(sigGetURL(const GURL &, const GUTF8String &)));

      viewer->resize(parent->size());
      viewer->show();
      parent->installEventFilter(this);

	 // What if we're being reattached by Netscape? Set DjVuImage immediately.
      if (document)
        viewer->setDjVuDocument(document, plugin_data.page_id);
   }
}
DjVuViewer::DjVuViewer(int _in_netscape, const QDViewer::PluginData & _plugin_data) :
      QObject(0, "djvu_viewer"), plugin_data(_plugin_data), in_netscape(_in_netscape)
{
   DEBUG_MSG("DjVuViewer::DjVuViewer(): initializing class...\n");
   DEBUG_MAKE_INDENT(3);

   request_data_cb=0;
   request_data_cl_data=0;

   attach_postpone=false;
   
   port=new DjVuViewerPort(this);
   
   viewer=0;

#if THREADMODEL==COTHREADS
   if (!QDThrYielder::isInitialized()) QDThrYielder::initialize();
#endif

   messenger.setLookAhead(1);
   
      // Connect signals of the QDMessenger
   connect(&messenger, SIGNAL(sigGetURL(const GURL &, const GUTF8String &)),
	   this, SIGNAL(sigGetURL(const GURL &, const GUTF8String &)));
   connect(&messenger, SIGNAL(sigShowError(const GUTF8String &, const GUTF8String &)),
	   this, SLOT(slotShowError(const GUTF8String &, const GUTF8String &)));
   connect(&messenger, SIGNAL(sigShowStatus(const QString &)),
	   this, SIGNAL(sigShowStatus(const QString &)));
}
unsigned long int
DjVuANT::get_bg_color(GLParser & parser)
{
  unsigned long retval=default_bg_color;
  DEBUG_MSG("DjVuANT::get_bg_color(): getting background color ...\n");
  DEBUG_MAKE_INDENT(3);
  G_TRY
  {
    GP<GLObject> obj=parser.get_object(BACKGROUND_TAG);
    if (obj && obj->get_list().size()==1)
    {
      GUTF8String color=(*obj)[0]->get_symbol();
      DEBUG_MSG("color='" << color << "'\n");
      retval=cvt_color(color, 0xffffff);
    }
#ifndef NDEBUG
    if(retval == default_bg_color)
    {
      DEBUG_MSG("can't find any.\n");
    }
#endif // NDEBUG
  } G_CATCH_ALL {} G_ENDCATCH;
#ifndef NDEBUG
  if(retval == default_bg_color)
  {
    DEBUG_MSG("resetting color to 0xffffffff (UNSPEC)\n");
  }
#endif // NDEBUG
  return retval;
}
GP<GIFFChunk>
GIFFChunk::get_chunk(const GUTF8String &name, int * pos_ptr)
   // The name may contain brackets to specify the chunk number
{
  DEBUG_MSG("GIFFChunk::get_chunk(): Returning chunk '" << name <<
     "' from '" << get_name() << "'\n");
  DEBUG_MAKE_INDENT(3);

  int number;
  const GUTF8String short_name=decode_name(name,number);

  int num=0;
  int pos_num;
  GP<GIFFChunk> retval;
  GPosition pos;
  for(pos=chunks, pos_num=0;pos;++pos, pos_num++)
  {
    if (chunks[pos]->get_name()==short_name && num++==number)
    {
      if (pos_ptr)
        *pos_ptr=pos_num;
      retval=chunks[pos];
      break;
    }
  }
  return retval;
}
void
GIFFManager::load_chunk(IFFByteStream & istr, GP<GIFFChunk> chunk)
{
  DEBUG_MSG("GIFFManager::load_chunk(): loading contents of chunk '" <<
    chunk->get_name() << "'\n");
  DEBUG_MAKE_INDENT(3);
   
  int chunk_size;
  GUTF8String chunk_id;
  while ((chunk_size=istr.get_chunk(chunk_id)))
  {
    if (istr.check_id(chunk_id))
    {
      GP<GIFFChunk> ch=GIFFChunk::create(chunk_id);
      load_chunk(istr, ch);
      chunk->add_chunk(ch);
    } else
    {
      TArray<char> data(chunk_size-1);
      istr.get_bytestream()->readall( (char*)data, data.size());
      GP<GIFFChunk> ch=GIFFChunk::create(chunk_id, data);
      chunk->add_chunk(ch);
    }
    istr.close_chunk();
  }
}
void
QDBase::decodeAnno(bool allow_redraw)
      // Will create DjVuAnno and call processAnno()
{
   DEBUG_MSG("QDBase::decodeAnno(): decoding...\n");
   DEBUG_MAKE_INDENT(3);
   
   if ( !dimg ) return;
   G_TRY {
      bool anno_processed=false;
      anno=dimg->get_decoded_anno();
      
      if (anno && anno->ant)
      {
	 processAnno(allow_redraw);
	 anno_processed=true;
      }
      if (!anno_processed)
      {
	 // If we didn't find anything to process, clean annotations
	 // from the previous (if any) page.
	 cleanAnno(allow_redraw);
      }
   } G_CATCH(exc) {
      anno=0;
      showError(this, exc);
   } G_ENDCATCH;
}
void
GIFFManager::del_chunk(void)
{
  DEBUG_MSG("GIFFManager::del_chunk(): Deleting chunk\n");
  DEBUG_MAKE_INDENT(3);
   
  G_THROW( ERR_MSG("GIFFManager.del_empty") );
}
int
GIFFChunk::get_chunks_number(void)
{
  DEBUG_MSG("GIFFChunk::get_chunks_number(): Returning number of chunks '" << name <<
     "' in '" << get_name() << "'\n");
  DEBUG_MAKE_INDENT(3);
  return chunks.size();
}
void
DjVuViewer::newStream(const GURL & _url, const GP<DataPool> & pool)
      // This function should be called from the main thread ONLY
{
   DEBUG_MSG("DjVuViewer::newStream(): Got stream for URL=" << _url << "\n");
   DEBUG_MAKE_INDENT(3);

   static const QString qspace(" ");
   showStatus(qspace);	// To kill messages like "Requesting directory..."

   GURL url=_url;

   if (!document)
   {
      DEBUG_MSG("First stream => decode thread should be started...\n");

      GUTF8String key=url.hash_argument();
      if (key.length()) plugin_data.page_id=key;
      else if (url.cgi_arguments())
      {
	 DArray<GUTF8String> cgi_names=url.djvu_cgi_names();
	 DArray<GUTF8String> cgi_values=url.djvu_cgi_values();
	 if (cgi_names.size()>0)
	 {
	    plugin_data.parse(cgi_names, cgi_values);
	 }
      }

      DjVuFileCache * cache=get_file_cache();

      GUTF8String ext=url.extension();
      
      if (ext!="djvu" && ext!="djv")
	 if (plugin_data.cache!=QDViewer::PluginData::CACHE_ON)
	    plugin_data.cache=QDViewer::PluginData::CACHE_OFF;
      
      if (plugin_data.cache==QDViewer::PluginData::CACHE_OFF) cache=0;
      
      url.clear_all_arguments();
      doc_pool=pool;
      doc_url=url;

      document=DjVuDocument::create(url, (DjVuPort *) port, cache);
      
      if (attach_postpone)
      {
	 attach_postpone=false;
	 attach(attach_parent);
      } else if (viewer)
      {
	 viewer->setDjVuDocument(document, plugin_data.page_id);
      }
   } else
   {
      DEBUG_MSG("Unexpected stream for url='" << url << "' :(\n");
   }
}
void
MapArea::attachWindow(QWidget * _pane, GRectMapper * _mapper)
{
   DEBUG_MSG("MapArea::attachWindow(): attaching the window...\n");
   DEBUG_MAKE_INDENT(3);

   pane=_pane; mapper=_mapper;
   
   initBorder();
}
void
MapArea::detachWindow(void)
   // This function is called from destructor too.
{
   DEBUG_MSG("MapArea::detachWindow(): detaching the window...\n");
   DEBUG_MAKE_INDENT(3);
   
   mapper=0; pane=0;
   pieces.empty();
}
QDViewerPrefs::QDViewerPrefs(DjVuPrefs * _prefs, QWidget * parent,
			     const char * name, bool modal) :
      QeDialog(parent, name, modal), cache_disabled(false), prefs(_prefs)
{
   DEBUG_MSG("QDViewerPrefs::QDViewerPrefs(): Creating Viewer Prefs dialog...\n");
   DEBUG_MAKE_INDENT(3);

   setCaption(tr("DjVu: Viewer Preferences"));
   QWidget *start = startWidget();
   QVBoxLayout * top_vlay=new QVBoxLayout(start, 10, 5, "top_vlay");
   QTabWidget *tabwidget = new QTabWidget(start, "tabwidget");
   top_vlay->addWidget(tabwidget);
   
      // *** Tabs
   gamma_prefs = new QDGammaPrefs(_prefs, tabwidget, "gamma_prefs");
   tabwidget->addTab(gamma_prefs, tr("Gamma"));
   tbar_prefs=new QDTbarPrefs(_prefs, tabwidget, "tbar_prefs");
   tabwidget->addTab(tbar_prefs, tr("Toolbar"));
   hlink_prefs=new QDHlinkPrefs(_prefs, tabwidget, "hlink_prefs");
   tabwidget->addTab(hlink_prefs, tr("Links"));
   lens_prefs=new QDLensPrefs(_prefs, tabwidget, "lens_prefs");
   tabwidget->addTab(lens_prefs, tr("Lens"));
   cache_prefs=new QDCachePrefs(_prefs, true, tabwidget, "cache_prefs");
   tabwidget->addTab(cache_prefs, tr("Cache"));
   optim_prefs=new QDOptimPrefs(_prefs, tabwidget, "optim_prefs");
   tabwidget->addTab(optim_prefs, tr("Optimization"));

      // ** Bottom Row
   QHBoxLayout * butt_lay=new QHBoxLayout(top_vlay, 2);
   global_butt=new QCheckBox(tr("Save preferences."), start, "global_butt");
   global_butt->setChecked(TRUE);
   butt_lay->addWidget(global_butt);
   butt_lay->addStretch(1);
#ifndef QT1
   QPushButton * help_butt=new QPushButton(tr("Help"), start, "ok_butt");
   butt_lay->addWidget(help_butt);
#endif
   QPushButton * ok_butt=new QPushButton(tr("&OK"), start, "ok_butt");
   ok_butt->setDefault(TRUE);
   butt_lay->addWidget(ok_butt);
   QPushButton * cancel_butt=new QPushButton(tr("&Cancel"), start, "cancel_butt");
   butt_lay->addWidget(cancel_butt);

      // Connecting signals and slots
#ifndef QT1
   connect(help_butt, SIGNAL(clicked(void)), this, SLOT(slotHelp(void)));
#endif
   connect(ok_butt, SIGNAL(clicked(void)), this, SLOT(accept(void)));
   connect(cancel_butt, SIGNAL(clicked(void)), this, SLOT(reject(void)));
   connect(global_butt, SIGNAL(toggled(bool)), this, SLOT(slotGlobalToggled(bool)));
   connect(hlink_prefs, SIGNAL(sigHotKeyChanged(DjVuPrefs::HLButtType)),
	   lens_prefs, SLOT(slotHlHotKeyChanged(DjVuPrefs::HLButtType)));
   connect(lens_prefs, SIGNAL(sigHotKeyChanged(DjVuPrefs::MagButtType)),
	   hlink_prefs, SLOT(slotMagHotKeyChanged(DjVuPrefs::MagButtType)));
}
DjVuViewer::~DjVuViewer(void)
{
   DEBUG_MSG("DjVuViewer::~DjVuViewer(): destroying class\n");
   DEBUG_MAKE_INDENT(3);

   port->disabled=1;
   port=0;
   
   if (document) document->stop_init();
   detach();
}
int
DjVuANT::get_zoom(GLParser & parser)
      // Returns:
      //   <0 - special zoom (like ZOOM_STRETCH)
      //   =0 - not set
      //   >0 - numeric zoom (%%)
{
  int retval=ZOOM_UNSPEC;
  DEBUG_MSG("DjVuANT::get_zoom(): getting zoom factor ...\n");
  DEBUG_MAKE_INDENT(3);
  G_TRY
  {
    GP<GLObject> obj=parser.get_object(ZOOM_TAG);
    if (obj && obj->get_list().size()==1)
    {
      const GUTF8String zoom((*obj)[0]->get_symbol());
      DEBUG_MSG("zoom='" << zoom << "'\n");
     
      for(int i=0;(i<zoom_strings_size);++i)
      {
        if(zoom == zoom_strings[i])
        {
          retval=(-i);
          break;
        }
      }
      if(retval == ZOOM_UNSPEC)
      {
        if (zoom[0]!='d')
        {
          G_THROW( ERR_MSG("DjVuAnno.bad_zoom") );
        }else
        {
          retval=zoom.substr(1, zoom.length()).toInt(); //atoi((const char *) zoom+1);
        }
      }
    }
#ifndef NDEBUG
    if(retval == ZOOM_UNSPEC)
    {
      DEBUG_MSG("can't find any.\n");
    }
#endif // NDEBUG
  } G_CATCH_ALL {} G_ENDCATCH;
#ifndef NDEBUG
  if(retval == ZOOM_UNSPEC)
  {
    DEBUG_MSG("resetting zoom to 0 (UNSPEC)\n");
  }
#endif // NDEBUG
  return retval;
}
Exemplo n.º 24
0
void
DjVuFileCache::set_max_size(int xmax_size)
{
   DEBUG_MSG("DjVuFileCache::set_max_size(): resizing to " << xmax_size << "\n");
   DEBUG_MAKE_INDENT(3);

   GCriticalSectionLock lock(&class_lock);
   
   max_size=xmax_size;
   cur_size=calculate_size();

   if (max_size>=0) clear_to_size(enabled ? max_size : 0);
}
void
QDViewerPrefs::done(int rc)
{
   DEBUG_MSG("QDViewerPrefs::done() called\n");
   DEBUG_MAKE_INDENT(3);
   
   if (rc==Accepted)
   {
      DEBUG_MSG("OK pressed. Updating preferences structure\n");

      DjVuPrefs disk_prefs;
      disk_prefs.dScreenGamma=prefs->dScreenGamma
        =gamma_prefs->displGamma();
      disk_prefs.dPrinterGamma=prefs->dPrinterGamma
        = ((gamma_prefs->match()) ? 0 : gamma_prefs->printGamma());
      disk_prefs.fastZoom=prefs->fastZoom
        =optim_prefs->fastZoom();
      disk_prefs.fastThumb=prefs->fastThumb
        =optim_prefs->fastThumb();
      disk_prefs.optimizeLCD=prefs->optimizeLCD
        =optim_prefs->optimizeLCD();
      disk_prefs.hlinksPopup=prefs->hlinksPopup
        =!hlink_prefs->disablePopup();
      disk_prefs.hlinksBorder=prefs->hlinksBorder
        =hlink_prefs->simpleBorder();
      disk_prefs.hlb_num=prefs->hlb_num
        =hlink_prefs->hlinkKey();
      disk_prefs.magnifierSize=prefs->magnifierSize
        =lens_prefs->size();
      disk_prefs.magnifierScale=prefs->magnifierScale
        =lens_prefs->scale();
      disk_prefs.magnifierHotKey=prefs->magnifierHotKey
        =lens_prefs->hotKey();
      disk_prefs.mcacheSize=prefs->mcacheSize
        =cache_prefs->mcacheSize();
      disk_prefs.pcacheSize=prefs->pcacheSize
        =cache_prefs->pcacheSize();
      disk_prefs.toolBarOn=prefs->toolBarOn
        =tbar_prefs->enabled();
      disk_prefs.toolBarAlwaysVisible=prefs->toolBarAlwaysVisible
        =tbar_prefs->visible();
      disk_prefs.toolBarDelay=prefs->toolBarDelay
        =tbar_prefs->delay();

      if (global_butt->isChecked()) disk_prefs.save();
   } else
   {
      DEBUG_MSG("Cancel pressed.\n");
   }
   QeDialog::done(rc);
}
SavedData
DjVuViewer::getSavedData(void)
{
   DEBUG_MSG("DjVuViewer::getSavedData(): returning saved_data:\n");
   DEBUG_MAKE_INDENT(3);
   
   if (viewer) plugin_data.saved=viewer->getSavedData();

   DEBUG_MSG("cmd_mode=" << plugin_data.saved.cmd_mode << "\n");
   DEBUG_MSG("cmd_zoom=" << plugin_data.saved.cmd_zoom << "\n");
   DEBUG_MSG("imgx=" << plugin_data.saved.imgx << "\n");
   DEBUG_MSG("imgy=" << plugin_data.saved.imgy << "\n");
   return plugin_data.saved;
}
QDHlinkPrefs::QDHlinkPrefs(DjVuPrefs * prefs, QWidget * parent, const char * name) :
      QWidget(parent, name)
{
   DEBUG_MSG("QDHlinkPrefs::QDHlinkOptimPrefs(): ...\n");
   DEBUG_MAKE_INDENT(3);

   QVBoxLayout * vlay=new QVBoxLayout(this, 10, 5, "hlink_vlay");
   vlay->addSpacing(fontMetrics().height());
   vlay->addStretch(1);
   popup_butt=new QCheckBox(tr("Disable hyperlink popup messages."),
			     this, "popup_butt");
   popup_butt->setChecked(!prefs->hlinksPopup);
   vlay->addWidget(popup_butt);
   
   border_butt=new QCheckBox(tr("Draw hyperlinks using simple border."), 
			      this, "border_butt");
   border_butt->setChecked(prefs->hlinksBorder);
   vlay->addWidget(border_butt);
   vlay->addStretch(1);
   QHBoxLayout * hlay=new QHBoxLayout(vlay, 5);
   QLabel * key_label=new QLabel(tr("\"Show all hyperlinks\" key:"), this);
   hlay->addWidget(key_label);
   key_menu=new QComboBox(this, "key_menu");
   for(int i=0;i<DjVuPrefs::HLB_ITEMS;i++)
      key_menu->insertItem(DjVuPrefs::hlb_names[i], i);
   key_menu->setCurrentItem(prefs->hlb_num);
   hlay->addWidget(key_menu);
   vlay->addStretch(2);

   connect(key_menu, SIGNAL(activated(int)),
	   this, SLOT(slotHotKeyChanged(int)));

#ifndef QT1
   QWhatsThis::add(this,
                   tr("<b>Hyperlinks:</b><ul>"
                      "<li>Hyperlinks are hilited when the mouse hovers"
                      " above the hyperlink region or when the"
                      " the key combination specified"
                      " in the <i>show all hyperlinks</i> box"
                      " is depressed.</li>"
                      "<li>The <i>disable hyperlink popups</i> option"
                      " hides the popup messages optionally associated with"
                      " the hyperlinks.</li>"
                      "<li>The <i>draw using simple border</i> option"
                      " selects simpler hiliting effects.</li>"
                      "</ul>"));
#endif

}
void
GIFFManager::del_chunk(GUTF8String name)
      // "name" should be fully qualified, that is contain dots.
      // It may also end with [] to set the chunk order number
{
  DEBUG_MSG("GIFFManager::del_chunk(): Deleting chunk '" << name << "'\n");
  DEBUG_MAKE_INDENT(3);
   
  if (!name.length())
    G_THROW( ERR_MSG("GIFFManager.del_empty") );

  if (name[0]=='.')
  {
    const int next_dot=name.search('.',1);
    if (next_dot < 0)
    {
      if (top_level->check_name(name.substr(1,(unsigned int)-1)))
      {
        DEBUG_MSG("Removing top level chunk..\n");
        top_level=GIFFChunk::create();
        return;
      }
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+name.substr(1,(unsigned int)-1));
    }
    const GUTF8String top_name=name.substr(1,next_dot-1);
    if (!top_level->check_name(top_name))
      G_THROW( ERR_MSG("GIFFManager.wrong_name2") "\t"+top_name);
    name=name.substr(next_dot+1,(unsigned int)-1);
  }
   
  GP<GIFFChunk> cur_sec=top_level;
  const char * start, * end=(const char *)name-1;
  do
  {
    for(start=++end;*end&&(*end!='.');end++)
      EMPTY_LOOP;
    if (end>start && *end=='.')
      cur_sec=cur_sec->get_chunk(GUTF8String(start, end-start));
    if (!cur_sec)
      G_THROW( ERR_MSG("GIFFManager.cant_find") "\t"+GUTF8String(name));
  } while(*end);
   
  if (!start[0])
  {
    G_THROW(GUTF8String( ERR_MSG("GIFFManager.malformed") "\t")+name);
  }
   
  cur_sec->del_chunk(start);
}
GP<DjVuImage>
QDDecoder::getPageImage(int page_num)
{
    DEBUG_MSG("QDDecoder::getPageImage(): page_num=" << page_num << "\n");
    DEBUG_MAKE_INDENT(3);

    last_done=0;
    if (progress_dlg) progress_dlg->setProgress(0);

    image=document->get_page(page_num, false, port.getPort());
    waitTillDecodingEnds();

    if (image->get_djvu_file()->is_decode_ok()) return image;
    else return 0;
}
void
GLParser::parse(const char * str)
{
   DEBUG_MSG("GLParser::parse(): parsing string contents\n");
   DEBUG_MAKE_INDENT(3);
   
   G_TRY
   {
      check_compat(str);
      parse("toplevel", list, str);
   } G_CATCH(exc)
   {
      if (exc.cmp_cause(ByteStream::EndOfFile))
        G_RETHROW;
   } G_ENDCATCH;
}