示例#1
0
static void update_toc(GooList* items, int level)
{
	unsigned short ucs[256];
	char label[256];
	int i, j;

	if (! items) return;
	if (items->getLength() < 1) return;

	for (i = 0; i < items->getLength(); i++)
	{
		OutlineItem* outlineItem = (OutlineItem*)items->get(i);
		Unicode* title = outlineItem->getTitle();
		int tlen = outlineItem->getTitleLength();
		if (tlen > sizeof(ucs) - 1) tlen = sizeof(ucs) - 1;
		for (j = 0; j < tlen; j++) ucs[j] = (unsigned short)title[j];
		ucs[j] = 0;
		ucs2utf(ucs, label, sizeof(label));

		LinkAction* a = outlineItem->getAction();
		if (a && (a->getKind() == actionGoTo))
		{
			// page number is contained/referenced in a LinkGoTo
			LinkGoTo* g = static_cast< LinkGoTo* >(a);
			LinkDest* destination = g->getDest();
			if (!destination && g->getNamedDest())
			{
				GooString* s = g->getNamedDest();
				if (named_size <= named_count + 1)
				{
					named_size += 64;
					named_dest = (char**) realloc(named_dest, named_size * sizeof(char*));
				}
				named_dest[named_count] = strdup(s->getCString());
				add_toc_item(level, label, -1, 100000 + named_count);
				named_count++;
			}
			else if (destination && destination->isOk() && destination->isPageRef())
			{
				Ref page_ref = destination->getPageRef();
				int num = doc->findPage(page_ref.num, page_ref.gen);
				add_toc_item(level, label, num, num);
			}
			else
			{
				add_toc_item(level, label, -1, -1);
			}
		}
		else
		{
			add_toc_item(level, label, -1, -1);
		}
		outlineItem->open();
		GooList* children = outlineItem->getKids();
		if (children) update_toc(children, level + 1);
		outlineItem->close();
	}
}
void NSRPopplerDocument::renderPage(int page)
{
	double dpix, dpiy;

	if (_doc == NULL || page > getNumberOfPages() || page < 1)
		return;

	_page = _catalog->getPage(page);

	if (isTextOnly()) {
		PDFRectangle	*rect;
		GooString	*text;
		TextOutputDev	*dev;

		dev = new TextOutputDev (0, gFalse, gFalse, gFalse);

		_doc->displayPageSlice(dev, _page->getNum(), 72, 72, 0, gFalse, gTrue, gFalse, -1, -1, -1, -1);

		rect = _page->getCropBox();
		text = dev->getText(rect->x1, rect->y1, rect->x2, rect->y2);
		_text = processText(QString::fromUtf8(text->getCString()));

		delete text;
		delete dev;
		_readyForLoad = true;

		return;
	}

	if (isZoomToWidth()) {
		double wZoom = ((double) getScreenWidth() / (double) _page->getCropWidth() * 100.0);
		setZoomSilent((int) wZoom);
	}

	if (getZoom() > getMaxZoom())
		setZoomSilent (getMaxZoom());
	else if (getZoom() < getMinZoom())
		setZoomSilent (getMinZoom());

	if (_readyForLoad)
		_dev->startPage(0, NULL);

	dpix = _dpix * getZoom() / 100.0;
	dpiy = _dpiy * getZoom() / 100.0;

	_page->display(_dev, dpix, dpiy, getRotation(), gFalse, gFalse, gTrue, _catalog);

	_readyForLoad = true;
}
示例#3
0
OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
  Object obj1;
  GooString *s;
  int i;

  xref = xrefA;
  title = NULL;
  action = NULL;
  kids = NULL;

  if (dict->lookup("Title", &obj1)->isString()) {
    s = obj1.getString();
    if ((s->getChar(0) & 0xff) == 0xfe &&
	(s->getChar(1) & 0xff) == 0xff) {
      titleLen = (s->getLength() - 2) / 2;
      title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
      for (i = 0; i < titleLen; ++i) {
	title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
	           (s->getChar(3 + 2*i) & 0xff);
      }
    } else {
      titleLen = s->getLength();
      title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
      for (i = 0; i < titleLen; ++i) {
	title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
      }
    }
  } else {
    titleLen = 0;
  }
  obj1.free();

  if (!dict->lookup("Dest", &obj1)->isNull()) {
    action = LinkAction::parseDest(&obj1);
  } else {
      obj1.free();
    if (!dict->lookup("A", &obj1)->isNull()) {
        action = LinkAction::parseAction(&obj1);
  }
  }
  obj1.free();

  dict->lookupNF("First", &firstRef);
  dict->lookupNF("Last", &lastRef);
  dict->lookupNF("Next", &nextRef);

  startsOpen = gFalse;
  if (dict->lookup("Count", &obj1)->isInt()) {
    if (obj1.getInt() > 0) {
      startsOpen = gTrue;
    }
  }
  obj1.free();
}
示例#4
0
GDir::GDir(char *name, GBool doStatA) {
    path = new GooString(name);
    doStat = doStatA;
#if defined(WIN32)
    GooString *tmp;

    tmp = path->copy();
    tmp->append("/*.*");
    hnd = FindFirstFile(tmp->getCString(), &ffd);
    delete tmp;
#elif defined(ACORN)
#elif defined(MACOS)
#else
    dir = opendir(name);
#ifdef VMS
    needParent = strchr(name, '[') != NULL;
#endif
#endif
}
示例#5
0
void GDir::rewind() {
#ifdef WIN32
    GooString *tmp;

    if (hnd != INVALID_HANDLE_VALUE)
        FindClose(hnd);
    tmp = path->copy();
    tmp->append("/*.*");
    hnd = FindFirstFile(tmp->getCString(), &ffd);
    delete tmp;
#elif defined(ACORN)
#elif defined(MACOS)
#else
    if (dir)
        rewinddir(dir);
#ifdef VMS
    needParent = strchr(path->getCString(), '[') != NULL;
#endif
#endif
}
示例#6
0
void TestGooString::testInsert()
{
    {
    GooString goo;
    goo.insert(0, ".");
    goo.insert(0, "This is a very long long test string");
    QCOMPARE(goo.getCString(), "This is a very long long test string.");
    }
    {
    GooString goo;
    goo.insert(0, "second-part-third-part");
    goo.insert(0, "first-part-");
    QCOMPARE(goo.getCString(), "first-part-second-part-third-part");
    }
}
示例#7
0
void *StandardSecurityHandler::getAuthData() {
#if HAVE_XPDFCORE
    XPDFCore *core;
    GooString *password;

    if (!(core = (XPDFCore *)doc->getGUIData()) ||
            !(password = core->getPassword())) {
        return NULL;
    }
    return new StandardAuthData(password, password->copy());
#elif HAVE_WINPDFCORE
    WinPDFCore *core;
    GooString *password;

    if (!(core = (WinPDFCore *)doc->getGUIData()) ||
            !(password = core->getPassword())) {
        return NULL;
    }
    return new StandardAuthData(password, password->copy());
#else
    return NULL;
#endif
}
示例#8
0
static char *
unicode_to_char (Unicode *unicode,
		 int      len)
{
  static UnicodeMap *uMap = NULL;

  if (uMap == NULL) {
    GooString *enc = new GooString ("UTF-8");
    uMap = globalParams->getUnicodeMap (enc);
    uMap->incRefCnt ();
    delete enc;
  }

  GooString gstr;
  char buf[8]; /* 8 is enough for mapping an unicode char to a string */
  int i, n;

  for (i = 0; i < len; ++i) {
    n = uMap->mapUnicode (unicode[i], buf, sizeof (buf));
    gstr.append (buf, n);
  }

  return strdup (gstr.getCString ());
}
示例#9
0
int main(int argc, char *argv[])
{
  // parse args
  bool ok = parseArgs(argDesc, &argc, argv);
  if (!ok || argc < 2 || argc > 3 || printHelp) {
    fprintf(stderr, "pdftoipe version %s\n", PDFTOIPE_VERSION);
    printUsage("pdftoipe", "<PDF-file> [<XML-file>]", argDesc);
    return 1;
  }

  GooString *fileName = new GooString(argv[1]);

  globalParams = new GlobalParams();
  if (quiet)
    globalParams->setErrQuiet(quiet);

  GooString *ownerPW, *userPW;
  if (ownerPassword[0]) {
    ownerPW = new GooString(ownerPassword);
  } else {
    ownerPW = 0;
  }
  if (userPassword[0]) {
    userPW = new GooString(userPassword);
  } else {
    userPW = 0;
  }

  // open PDF file
  PDFDoc *doc = new PDFDoc(fileName, ownerPW, userPW);
  delete userPW;
  delete ownerPW;

  if (!doc->isOk())
    return 1;
  
  // construct XML file name
  std::string xmlFileName;
  if (argc == 3) {
    xmlFileName = argv[2];
  } else {
    const char *p = fileName->c_str() + fileName->getLength() - 4;
    if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")) {
        xmlFileName = std::string(fileName->c_str(),
                                  fileName->getLength() - 4);
    } else {
      xmlFileName = fileName->c_str();
    }
    xmlFileName += ".ipe";
  }

  // get page range
  if (firstPage < 1)
    firstPage = 1;

  if (lastPage < 1 || lastPage > doc->getNumPages())
    lastPage = doc->getNumPages();

  // write XML file
  XmlOutputDev *xmlOut = 
    new XmlOutputDev(xmlFileName, doc->getXRef(),
                     doc->getCatalog(), firstPage, lastPage);

  // tell output device about text handling
  xmlOut->setTextHandling(math, notext, literal, mergeLevel, unicodeLevel);
  
  int exitCode = 2;
  if (xmlOut->isOk()) {
    doc->displayPages(xmlOut, firstPage, lastPage, 
		      // double hDPI, double vDPI, int rotate,
		      // bool useMediaBox, bool crop, bool printing,
		      72.0, 72.0, 0, false, false, false);
    exitCode = 0;
  }

  if (xmlOut->hasUnicode()) {
    fprintf(stderr, "The document contains Unicode (non-ASCII) text.\n");
    if (unicodeLevel <= 1)
      fprintf(stderr, "Unknown Unicode characters were replaced by [U+XXX].\n");
    else
      fprintf(stderr, "UTF-8 was set as document encoding in the preamble.\n");
  }

  // clean up
  delete xmlOut;
  delete doc;
  delete globalParams;

  return exitCode;
}
示例#10
0
GooString *appendToPath(GooString *path, char *fileName) {
#if defined(VMS)
    //---------- VMS ----------
    //~ this should handle everything necessary for file
    //~ requesters, but it's certainly not complete
    char *p0, *p1, *p2;
    char *q1;

    p0 = path->getCString();
    p1 = p0 + path->getLength() - 1;
    if (!strcmp(fileName, "-")) {
        if (*p1 == ']') {
            for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
            if (*p2 == '[')
                ++p2;
            path->del(p2 - p0, p1 - p2);
        } else if (*p1 == ':') {
            path->append("[-]");
        } else {
            path->clear();
            path->append("[-]");
        }
    } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
        if (*p1 == ']') {
            path->insert(p1 - p0, '.');
            path->insert(p1 - p0 + 1, fileName, q1 - fileName);
        } else if (*p1 == ':') {
            path->append('[');
            path->append(']');
            path->append(fileName, q1 - fileName);
        } else {
            path->clear();
            path->append(fileName, q1 - fileName);
        }
    } else {
        if (*p1 != ']' && *p1 != ':')
            path->clear();
        path->append(fileName);
    }
    return path;

#elif defined(WIN32)
    //---------- Win32 ----------
    GooString *tmp;
    char buf[256];
    char *fp;

    tmp = new GooString(path);
    tmp->append('/');
    tmp->append(fileName);
    GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
    delete tmp;
    path->clear();
    path->append(buf);
    return path;

#elif defined(ACORN)
    //---------- RISCOS ----------
    char *p;
    int i;

    path->append(".");
    i = path->getLength();
    path->append(fileName);
    for (p = path->getCString() + i; *p; ++p) {
        if (*p == '/') {
            *p = '.';
        } else if (*p == '.') {
            *p = '/';
        }
    }
    return path;

#elif defined(MACOS)
    //---------- MacOS ----------
    char *p;
    int i;

    path->append(":");
    i = path->getLength();
    path->append(fileName);
    for (p = path->getCString() + i; *p; ++p) {
        if (*p == '/') {
            *p = ':';
        } else if (*p == '.') {
            *p = ':';
        }
    }
    return path;

#elif defined(__EMX__)
    //---------- OS/2+EMX ----------
    int i;

    // appending "." does nothing
    if (!strcmp(fileName, "."))
        return path;

    // appending ".." goes up one directory
    if (!strcmp(fileName, "..")) {
        for (i = path->getLength() - 2; i >= 0; --i) {
            if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
                    path->getChar(i) == ':')
                break;
        }
        if (i <= 0) {
            if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
                path->del(1, path->getLength() - 1);
            } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
                path->del(2, path->getLength() - 2);
            } else {
                path->clear();
                path->append("..");
            }
        } else {
            if (path->getChar(i-1) == ':')
                ++i;
            path->del(i, path->getLength() - i);
        }
        return path;
    }

    // otherwise, append "/" and new path component
    if (path->getLength() > 0 &&
            path->getChar(path->getLength() - 1) != '/' &&
            path->getChar(path->getLength() - 1) != '\\')
        path->append('/');
    path->append(fileName);
    return path;

#else
    //---------- Unix ----------
    int i;

    // appending "." does nothing
    if (!strcmp(fileName, "."))
        return path;

    // appending ".." goes up one directory
    if (!strcmp(fileName, "..")) {
        for (i = path->getLength() - 2; i >= 0; --i) {
            if (path->getChar(i) == '/')
                break;
        }
        if (i <= 0) {
            if (path->getChar(0) == '/') {
                path->del(1, path->getLength() - 1);
            } else {
                path->clear();
                path->append("..");
            }
        } else {
            path->del(i, path->getLength() - i);
        }
        return path;
    }

    // otherwise, append "/" and new path component
    if (path->getLength() > 0 &&
            path->getChar(path->getLength() - 1) != '/')
        path->append('/');
    path->append(fileName);
    return path;
#endif
}
示例#11
0
int main(int argc,char **argv)
{
    unsigned int window_width=-1, window_height=-1;  // sage window size

    sage::initUtil();

    // parse command line arguments
    if (argc < 2){
	sage::printLog("PDF> pdfviewer filename [width] [height] [-show_original] [-page num]");
	return 0;
    }
    for (int argNum=2; argNum<argc; argNum++)
    {
	if (strcmp(argv[argNum], "-show_original") == 0) {
	    useDXT = false;
	}
	else if(strcmp(argv[argNum], "-page") == 0) {
	    int p = atoi(argv[argNum+1]);
	    if (p != 0)
		firstPage = p-1;
	    argNum++;
	}
	else if(atoi(argv[argNum]) != 0 && atoi(argv[argNum+1]) != 0) {
	    window_width = atoi( argv[argNum] );
	    window_height = atoi( argv[argNum+1] );
	    argNum++;  // increment because we read two args here
	}
    }


    fileName = string(argv[1]);

#if defined(USE_POPPLER)
#if SAGE_POPPLER_VERSION == 5
  g_type_init();
  sage::printLog("PDF> Poppler version %s", poppler_get_version());
  backend = poppler_get_backend ();
  enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (POPPLER_TYPE_BACKEND), backend);
  sage::printLog ("PDF> Backend is %s", enum_value->value_name);

  error = NULL;
  const string filename = string((const char*)"file://") + string(argv[1]);
  document = poppler_document_new_from_file (filename.c_str(), NULL, &error);
  if (document == NULL) {
    sage::printLog("PDF> error for [%s]: %s", filename.c_str(), error->message);
    exit(0);
  }
  // get the number of pages
  numImages = poppler_document_get_n_pages(document);

  pg_index = 0; // index starts at 0
  page = poppler_document_get_page(document, pg_index);
  if (page == NULL) {
    sage::printLog("PDF> error for [%s]: %s", filename.c_str());
    exit(0);
  }

  // page size
  double mwidth, mheight;
  poppler_page_get_size (page, &mwidth, &mheight);
  sage::printLog ("PDF> page size: %g by %g ", mwidth, mheight);

  x_resolution = 200.0;
  pg_w = mwidth  * (x_resolution / 72.0);
  pg_h = mheight * (x_resolution / 72.0);

  if (pg_w > 4096) {
	pg_w = 4096.0;
	pg_h = 4096.0 / (mwidth/mheight);
	x_resolution = pg_w * 72.0 / mwidth;
  }
  if (pg_h > 4096) {
	pg_w = 4096.0 / (mheight/mwidth);
	pg_h = 4096.0;
	x_resolution = pg_h * 72.0 / mheight;
  }

  width  = (unsigned int)pg_w;
  height = (unsigned int)pg_h;
  sage::printLog("PDF> Crop @ %d DPI: width %d height %d", int(x_resolution), int(pg_w), int(pg_h));

  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
  gdk_pixbuf_fill (pixbuf, 0xffffffff);

  // print some information
  print_document_info (document); 

#endif
#if SAGE_POPPLER_VERSION == 12
  GooString *fileName;
  GooString *ownerPW, *userPW;
  Object info;
  UnicodeMap *uMap;

  // read config file
  globalParams = new GlobalParams();

  // get mapping to output encoding
  if (!(uMap = globalParams->getTextEncoding())) {
    sage::printLog("PDF> Couldn't get text encoding");
  }

  fileName = new GooString(argv[1]);
  ownerPW = NULL;
  userPW = NULL;
  doc = new PDFDoc(fileName, ownerPW, userPW, NULL);
  sage::printLog("PDF> file [%s] is OK: %d", argv[1], doc->isOk() );
  numImages = doc->getNumPages();
  sage::printLog("PDF> num pages: %d", numImages );

  SplashColor paperColor;
  paperColor[0] = 255;
  paperColor[1] = 255;
  paperColor[2] = 255;

  splashOut = new SplashOutputDev(splashModeRGB8, 3, gFalse, paperColor);
  splashOut->startDoc(doc->getXRef());

  pg_index = firstPage+1;
  double mwidth  = doc->getPageMediaWidth(pg_index);
  double mheight = doc->getPageMediaHeight(pg_index);
  sage::printLog("PDF> Media width %d height %d", int(mwidth), int(mheight));

  x_resolution = 200.0;
  pg_w = mwidth  * (x_resolution / 72.0);
  pg_h = mheight * (x_resolution / 72.0);

  if (pg_w > 4096) {
	pg_w = 4096.0;
	pg_h = 4096.0 / (mwidth/mheight);
	x_resolution = pg_w * 72.0 / mwidth;
  }
  if (pg_h > 4096) {
	pg_w = 4096.0 / (mheight/mwidth);
	pg_h = 4096.0;
	x_resolution = pg_h * 72.0 / mheight;
  }

  width  = pg_w;
  height = pg_h;
  sage::printLog("PDF> Crop @ %d DPI: width %d height %d", int(x_resolution), int(pg_w), int(pg_h));

  doc->displayPageSlice(splashOut, 1, x_resolution, x_resolution, 0, gTrue, gFalse, gFalse, 0, 0, pg_w, pg_h);

  // print doc info
  doc->getDocInfo(&info);
  if (info.isDict()) {
    printInfoString(info.getDict(), (char*)"Title",        (char*)"Title:          ", uMap);
    printInfoString(info.getDict(), (char*)"Subject",      (char*)"Subject:        ", uMap);
    printInfoString(info.getDict(), (char*)"Keywords",     (char*)"Keywords:       ", uMap);
    printInfoString(info.getDict(), (char*)"Author",       (char*)"Author:         ", uMap);
    printInfoString(info.getDict(), (char*)"Creator",      (char*)"Creator:        ", uMap);
    printInfoString(info.getDict(), (char*)"Producer",     (char*)"Producer:       ", uMap);
    printInfoDate(info.getDict(),   (char*)"CreationDate", (char*)"CreationDate:   ");
    printInfoDate(info.getDict(),   (char*)"ModDate",      (char*)"ModDate:        ");
  }
  info.free();
#endif
#else
    // read file
    wand=NewMagickWand();  

    // set the resolution (pixel density)
    MagickSetResolution(wand, 200,200);
    
    status=MagickReadImage(wand, fileName.data());
    if (status == MagickFalse)
	ThrowWandException(wand);
    numImages = MagickGetNumberImages(wand);
    MagickSetImageIndex(wand, firstPage);

    // get the image size
    width = MagickGetImageWidth(wand);
    height = MagickGetImageHeight(wand);

    // -------  TODO: need to keep track of images that have been flipped already...

    // crop the image if necessary to make sure it's a multiple of 4
    if (useDXT)
    {
	if (width%4 != 0 || height%4 != 0)
	{
	    fprintf(stderr, "\n**** Image cropped a few pixels to be a multiple of 4 for dxt");
	    width -= width%4;
	    height -= height%4;
	}
	
	// flip the image to have the correct orientation for dxt
	MagickFlipImage(wand);
    }
#endif

    // allocate buffers 
    rgba = (byte*) memalign(16, width*height*4);
    if (useDXT)
	dxt = (byte*) memalign(16, width*height*4/8);

    // get the first page
    getRGBA();

    // if the user didn't specify the window size, use the image size
    if (window_height == -1 && window_width == -1)
    {
	window_width = width;
	window_height = height;
    }
  
    // initialize SAIL

    // Search for a configuration file
    char *tmpconf = getenv("SAGE_APP_CONFIG");
    if (tmpconf) {
      sage::printLog("PDFViewer> found SAGE_APP_CONFIG variable: [%s]", tmpconf);
      scfg.init(tmpconf);
    }
    else {
      sage::printLog("PDFViewer> using default pdfviewer.conf");
      scfg.init((char*)"pdfviewer.conf");
    }

    scfg.setAppName("pdfviewer");

    scfg.resX = width;
    scfg.resY = height;

    // if it hasn't been specified by the config file, use the app-determined size
    if (scfg.winWidth == -1 || scfg.winHeight == -1) {
	scfg.winWidth = window_width;
	scfg.winHeight = window_height;
    }
    
    if (useDXT)
    {
	scfg.pixFmt = PIXFMT_DXT;
	scfg.rowOrd = BOTTOM_TO_TOP;
    }
    else
    {
	scfg.pixFmt = PIXFMT_888;
	scfg.rowOrd = TOP_TO_BOTTOM;
    }

    sageInf.init(scfg);

    // finally swap the first buffer
    swapBuffer();


    // Wait the end
    while (1)
    {
	usleep(50000);  // so that we don't keep spinning too frequently (0.5s)
	sageMessage msg;
	if (sageInf.checkMsg(msg, false) > 0) {
	    char *data = (char*) msg.getData();

	    switch (msg.getCode()) {
	    case APP_QUIT:
		// release the memory
		free(dxt);
		free(rgba);
#if ! defined(USE_POPPLER)
		DestroyMagickWand(wand);
#endif

		sageInf.shutdown();
		exit(1);
		break;

	    case EVT_CLICK:
		// Click event x and y location normalized to size of window
		float clickX, clickY;

		// Ckick device Id, button Id, and is down flag
		int clickDeviceId, clickButtonId, clickIsDown, clickEvent;

		// Parse message
		sscanf(data, 
		       "%d %f %f %d %d %d", 
		       &clickDeviceId, &clickX, &clickY, 
		       &clickButtonId, &clickIsDown, &clickEvent);

		// record the click position so we know how far we moved
		if (clickIsDown && clickEvent == EVT_PAN) {
		    lastX = clickX;
		    lastY = clickY;
		}


		if (clickIsDown) {
		    bool doSwap = false;
#if ! defined(USE_POPPLER)
		    if (clickButtonId==1)
			doSwap = MagickPreviousImage(wand);
		    else if(clickButtonId==2)
			doSwap = MagickNextImage(wand);
#endif
			
		    // if everything went well, swap the new page
		    if (doSwap) {
			getRGBA();
			swapBuffer();
		    }
		}
		

		break;


	    case EVT_PAN: 

		// Pan event properties
		int panDeviceId;
		bool doSwap = false;

		// Pan event x and y location and change in x, y and z direction
		// normalized to size of window
		float startX, startY, panDX, panDY, panDZ;
		sscanf(data, 
		       "%d %f %f %f %f %f", 
		       &panDeviceId, &startX, &startY, &panDX, &panDY, &panDZ);
		
		// keep track of distance
		dist += panDX;

		// we started a new drag
		if (lastX != startX) {
		    lastX = startX;
		    dist = 0;
		}

		// if we dragged more than a certain distance, change a page
		else if( fabs(dist) > 0.07 ) {
#if ! defined(USE_POPPLER)
		    if (dist > 0)
			doSwap = MagickPreviousImage(wand);
		    else
			doSwap = MagickNextImage(wand);
#endif

		    // reset the counter
		    lastX = startX;
		    dist = 0;

		    if (doSwap) {
			getRGBA();
			swapBuffer();
			//sprintf(l, "Page %ld of %d", MagickGetImageIndex(wand)+1, numImages);
		    }
		}

		break;
	    }   // end switch
	}  // end if
    } // end while

    return 0;
}
Eina_List *
epdf_page_text_find (const Epdf_Page *page,
                     const char      *text,
                     unsigned char    is_case_sensitive)
{
    Epdf_Rectangle *match;
    TextOutputDev  *output_dev;
    Eina_List      *matches = NULL;
    double          xMin, yMin, xMax, yMax;
    int             length;
    int             height;


    if (!page || !text)
        return NULL;

    GooString tmp (text);
    Unicode *s;

    {
        length = tmp.getLength();
        s = (Unicode *)gmallocn(length, sizeof(Unicode));
        bool anyNonEncoded = false;
        for (int j = 0; j < length && !anyNonEncoded; ++j) {
            s[j] = pdfDocEncoding[tmp.getChar(j) & 0xff];
            if (!s[j]) anyNonEncoded = true;
        }
        if ( anyNonEncoded )
        {
            for (int j = 0; j < length; ++j) {
                s[j] = tmp.getChar(j);
            }
        }
    }

    length = strlen (text);

    output_dev = new TextOutputDev (NULL, 1, 0, 0);

    epdf_page_size_get (page, NULL, &height);
    page->page->display (output_dev, 72, 72, 0, false,
                         true, false,
                         page->doc->pdfdoc->getCatalog());

    xMin = 0;
    yMin = 0;
#warning you probably want to add backwards as parameters
    while (output_dev->findText (s, tmp.getLength (),
                                 0, 1, // startAtTop, stopAtBottom
                                 1, 0, // startAtLast, stopAtLast
                                 is_case_sensitive, 0, // caseSensitive, backwards
                                 &xMin, &yMin, &xMax, &yMax)) {
        match = (Epdf_Rectangle *)malloc (sizeof (Epdf_Rectangle));
        match->x1 = xMin;
        match->y1 = yMin;//height - yMax;
        match->x2 = xMax;
        match->y2 = yMax;//height - yMin;
        matches = eina_list_append (matches, match);
    }

    delete output_dev;

    return matches;
}