📄 xpdfcore.cc
字号:
TextOutputDev *textOut; GString *s; if (!doc->okToCopy()) { return NULL; } textOut = new TextOutputDev(NULL, gFalse, gFalse, gFalse); if (!textOut->isOk()) { delete textOut; return NULL; } doc->displayPage(textOut, pageNum, dpi, rotate, gFalse); s = textOut->getText(xMin, yMin, xMax, yMax); delete textOut; return s;}//------------------------------------------------------------------------// hyperlinks//------------------------------------------------------------------------void XPDFCore::doLink(int mx, int my) { double x, y; LinkAction *action; // look for a link out->cvtDevToUser(mx, my, &x, &y); if ((action = doc->findLink(x, y))) { doAction(action); }}void XPDFCore::doAction(LinkAction *action) { LinkActionKind kind; LinkDest *dest; GString *namedDest; char *s; GString *fileName, *fileName2; GString *cmd; GString *actionName; Object movieAnnot, obj1, obj2; GString *msg; int i; switch (kind = action->getKind()) { // GoTo / GoToR action case actionGoTo: case actionGoToR: if (kind == actionGoTo) { dest = NULL; namedDest = NULL; if ((dest = ((LinkGoTo *)action)->getDest())) { dest = dest->copy(); } else if ((namedDest = ((LinkGoTo *)action)->getNamedDest())) { namedDest = namedDest->copy(); } } else { dest = NULL; namedDest = NULL; if ((dest = ((LinkGoToR *)action)->getDest())) { dest = dest->copy(); } else if ((namedDest = ((LinkGoToR *)action)->getNamedDest())) { namedDest = namedDest->copy(); } s = ((LinkGoToR *)action)->getFileName()->getCString(); //~ translate path name for VMS (deal with '/') if (isAbsolutePath(s)) { fileName = new GString(s); } else { fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); } if (loadFile(fileName) != errNone) { if (dest) { delete dest; } if (namedDest) { delete namedDest; } delete fileName; return; } delete fileName; } if (namedDest) { dest = doc->findDest(namedDest); delete namedDest; } if (dest) { displayDest(dest, zoom, rotate, gTrue); delete dest; } else { if (kind == actionGoToR) { displayPage(1, zoom, 0, gFalse, gTrue); } } break; // Launch action case actionLaunch: fileName = ((LinkLaunch *)action)->getFileName(); s = fileName->getCString(); if (!strcmp(s + fileName->getLength() - 4, ".pdf") || !strcmp(s + fileName->getLength() - 4, ".PDF")) { //~ translate path name for VMS (deal with '/') if (isAbsolutePath(s)) { fileName = fileName->copy(); } else { fileName = appendToPath(grabPath(doc->getFileName()->getCString()), s); } if (loadFile(fileName) != errNone) { delete fileName; return; } delete fileName; displayPage(1, zoom, rotate, gFalse, gTrue); } else { fileName = fileName->copy(); if (((LinkLaunch *)action)->getParams()) { fileName->append(' '); fileName->append(((LinkLaunch *)action)->getParams()); }#ifdef VMS fileName->insert(0, "spawn/nowait ");#elif defined(__EMX__) fileName->insert(0, "start /min /n ");#else fileName->append(" &");#endif msg = new GString("About to execute the command:\n"); msg->append(fileName); if (doQuestionDialog("Launching external application", msg)) { system(fileName->getCString()); } delete fileName; delete msg; } break; // URI action case actionURI: if (!(cmd = globalParams->getURLCommand())) { error(-1, "No urlCommand defined in config file"); break; } runCommand(cmd, ((LinkURI *)action)->getURI()); break; // Named action case actionNamed: actionName = ((LinkNamed *)action)->getName(); if (!actionName->cmp("NextPage")) { gotoNextPage(1, gTrue); } else if (!actionName->cmp("PrevPage")) { gotoPrevPage(1, gTrue, gFalse); } else if (!actionName->cmp("FirstPage")) { if (page != 1) { displayPage(1, zoom, rotate, gTrue, gTrue); } } else if (!actionName->cmp("LastPage")) { if (page != doc->getNumPages()) { displayPage(doc->getNumPages(), zoom, rotate, gTrue, gTrue); } } else if (!actionName->cmp("GoBack")) { goBackward(); } else if (!actionName->cmp("GoForward")) { goForward(); } else if (!actionName->cmp("Quit")) { if (actionCbk) { (*actionCbk)(actionCbkData, "Quit"); } } else { error(-1, "Unknown named action: '%s'", actionName->getCString()); } break; // Movie action case actionMovie: if (!(cmd = globalParams->getMovieCommand())) { error(-1, "No movieCommand defined in config file"); break; } if (((LinkMovie *)action)->hasAnnotRef()) { doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num, ((LinkMovie *)action)->getAnnotRef()->gen, &movieAnnot); } else { doc->getCatalog()->getPage(page)->getAnnots(&obj1); if (obj1.isArray()) { for (i = 0; i < obj1.arrayGetLength(); ++i) { if (obj1.arrayGet(i, &movieAnnot)->isDict()) { if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie")) { obj2.free(); break; } obj2.free(); } movieAnnot.free(); } obj1.free(); } } if (movieAnnot.isDict()) { if (movieAnnot.dictLookup("Movie", &obj1)->isDict()) { if (obj1.dictLookup("F", &obj2)) { if ((fileName = LinkAction::getFileSpecName(&obj2))) { if (!isAbsolutePath(fileName->getCString())) { fileName2 = appendToPath( grabPath(doc->getFileName()->getCString()), fileName->getCString()); delete fileName; fileName = fileName2; } runCommand(cmd, fileName); delete fileName; } obj2.free(); } obj1.free(); } } movieAnnot.free(); break; // unknown action type case actionUnknown: error(-1, "Unknown link action type: '%s'", ((LinkUnknown *)action)->getAction()->getCString()); break; }}// Run a command, given a <cmdFmt> string with one '%s' in it, and an// <arg> string to insert in place of the '%s'.void XPDFCore::runCommand(GString *cmdFmt, GString *arg) { GString *cmd; char *s; int i; if ((s = strstr(cmdFmt->getCString(), "%s"))) { cmd = arg->copy(); // filter out any quote marks (' or ") to avoid a potential // security hole i = 0; while (i < cmd->getLength()) { if (cmd->getChar(i) == '"') { cmd->del(i); cmd->insert(i, "%22"); i += 3; } else if (cmd->getChar(i) == '\'') { cmd->del(i); cmd->insert(i, "%27"); i += 3; } else { ++i; } } cmd->insert(0, cmdFmt->getCString(), s - cmdFmt->getCString()); cmd->append(s + 2); } else { cmd = cmdFmt->copy(); }#ifdef VMS cmd->insert(0, "spawn/nowait ");#elif defined(__EMX__) cmd->insert(0, "start /min /n ");#else cmd->append(" &");#endif system(cmd->getCString()); delete cmd;}//------------------------------------------------------------------------// find//------------------------------------------------------------------------void XPDFCore::find(char *s) { Unicode *u; TextOutputDev *textOut; int xMin, yMin, xMax, yMax; double xMin1, yMin1, xMax1, yMax1; int pg; GBool top; int len, i; // check for zero-length string if (!s[0]) { XBell(display, 0); return; } // set cursor to watch setCursor(busyCursor); // convert to Unicode#if 1 //~ should do something more intelligent here len = strlen(s); u = (Unicode *)gmalloc(len * sizeof(Unicode)); for (i = 0; i < len; ++i) { u[i] = (Unicode)(s[i] & 0xff); }#endif // search current page starting at current selection or top of page xMin = yMin = xMax = yMax = 0; if (selectXMin < selectXMax && selectYMin < selectYMax) { xMin = selectXMax; yMin = (selectYMin + selectYMax) / 2; top = gFalse; } else { top = gTrue; } if (out->findText(u, len, top, gTrue, &xMin, &yMin, &xMax, &yMax)) { goto found; } // search following pages textOut = new TextOutputDev(NULL, gFalse, gFalse, gFalse); if (!textOut->isOk()) { delete textOut; goto done; } for (pg = page+1; pg <= doc->getNumPages(); ++pg) { doc->displayPage(textOut, pg, 72, 0, gFalse); if (textOut->findText(u, len, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; } } // search previous pages for (pg = 1; pg < page; ++pg) { doc->displayPage(textOut, pg, 72, 0, gFalse); if (textOut->findText(u, len, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1)) { goto foundPage; } } delete textOut; // search current page ending at current selection if (selectXMin < selectXMax && selectYMin < selectYMax) { xMax = selectXMin; yMax = (selectYMin + selectYMax) / 2; if (out->findText(u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax)) { goto found; } } // not found XBell(display, 0); goto done; // found on a different page foundPage: delete textOut; displayPage(pg, zoom, rotate, gTrue, gTrue); if (!out->findText(u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax)) { // this can happen if coalescing is bad goto done; } // found: change the selection found: setSelection(xMin, yMin, xMax, yMax);#ifndef NO_TEXT_SELECT copySelection();#endif done: gfree(u); // reset cursors to normal setCursor(None);}//------------------------------------------------------------------------// misc access//------------------------------------------------------------------------void XPDFCore::setBusyCursor(GBool busy) { setCursor(busy ? busyCursor : None);}void XPDFCore::takeFocus() { XmProcessTraversal(drawArea, XmTRAVERSE_CURRENT);}//------------------------------------------------------------------------// GUI code//------------------------------------------------------------------------void XPDFCore::initWindow() { Arg args[20]; int n; // create the cursors busyCursor = XCreateFontCursor(display, XC_watch); linkCursor = XCreateFontCursor(display, XC_hand2); selectCursor = XCreateFontCursor(display, XC_cross); currentCursor = 0; // create the scrolled window and scrollbars n = 0; XtSetArg(args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++n; XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n; scrolledWin = XmCreateScrolledWindow(parentWidget, "scroll", args, n); XtManageChild(scrolledWin); n = 0; XtSetArg(args[n], XmNorientation, XmHORIZONTAL); ++n; XtSetArg(args[n], XmNminimum, 0); ++n; XtSetArg(args[n], XmNmaximum, 1); ++n; XtSetArg(args[n], XmNsliderSize, 1); ++n; XtSetArg(args[n], XmNvalue, 0); ++n; XtSetArg(args[n], XmNincrement, 1); ++n; XtSetArg(args[n], XmNpageIncrement, 1); ++n; hScrollBar = XmCreateScrollBar(scrolledWin, "hScrollBar", args, n); XtManageChild(hScrollBar); XtAddCallback(hScrollBar, XmNvalueChangedCallback, &hScrollChangeCbk, (XtPointer)this);#ifndef DISABLE_SMOOTH_SCROLL XtAddCallback(hScrollBar, XmNdragCallback, &hScrollDragCbk, (XtPointer)this);#endif n = 0; XtSetArg(args[n], XmNorientation, XmVERTICAL); ++n; XtSetArg(args[n], XmNminimum, 0); ++n; XtSetArg(args[n], XmNmaximum, 1); ++n; XtSetArg(args[n], XmNsliderSize, 1); ++n; XtSetArg(args[n], XmNvalue, 0); ++n; XtSetArg(args[n], XmNincrement, 1); ++n; XtSetArg(args[n], XmNpageIncrement, 1); ++n; vScrollBar = XmCreateScrollBar(scrolledWin, "vScrollBar", args, n); XtManageChild(vScrollBar); XtAddCallback(vScrollBar, XmNvalueChangedCallback, &vScrollChangeCbk, (XtPointer)this);#ifndef DISABLE_SMOOTH_SCROLL XtAddCallback(vScrollBar, XmNdragCallback, &vScrollDragCbk, (XtPointer)this);#endif // create the drawing area n = 0; XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); ++n; XtSetArg(args[n], XmNmarginWidth, 0); ++n; XtSetArg(args[n], XmNmarginHeight, 0); ++n; if (fullScreen) { XtSetArg(args[n], XmNshadowThickness, 0); ++n; } drawAreaFrame = XmCreateFrame(scrolledWin, "drawAreaFrame", args, n); XtManageChild(drawAreaFrame); n = 0; XtSetArg(args[n], XmNresizePolicy, XmRESIZE_ANY); ++n; XtSetArg(args[n], XmNbackground, paperColor); ++n; XtSetArg(args[n], XmNwidth, 700); ++n; XtSetArg(args[n], XmNheight, 500); ++n; drawArea = XmCreateDrawingArea(drawAreaFrame, "drawArea", args, n); XtManageChild(drawArea); XtAddCallback(drawArea, XmNresizeCallback, &resizeCbk, (XtPointer)this); XtAddCallback(drawArea, XmNexposeCallback, &redrawCbk, (XtPointer)this); XtAddCallback(drawArea, XmNinputCallback, &inputCbk, (XtPointer)this); resizeCbk(drawArea, this, NULL); // set up mouse motion translations XtOverrideTranslations(drawArea, XtParseTranslationTable( "<Btn1Down>:DrawingAreaInput()\n" "<Btn1Up>:DrawingAreaInput()\n" "<Btn1Motion>:DrawingAreaInput()\n" "<Motion>:DrawingAreaInput()")); // can't create a GC until the window gets mapped drawAreaGC = NULL; selectGC = NULL; highlightGC = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -