From 2ae2fc5a16c8fa4fb533a68565578afc54289dfa Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Thu, 23 Nov 2023 19:44:25 +0100 Subject: [PATCH] update pdf-tools Signed-off-by: Andreas Gerler --- elpa/pdf-tools-20191031.642/README | 381 - .../build/server/m4/ax_check_compile_flag.m4 | 74 - .../build/server/poppler-hack.cc | 122 - .../build/server/synctex_parser.c | 4414 -------- .../build/server/synctex_parser.h | 363 - .../build/server/synctex_parser_version.txt | 1 - .../build/server/test/docker/lib/run-tests | 9 - .../test/docker/templates/Dockerfile.in | 4 - .../test/docker/templates/arch.Dockerfile.in | 6 - .../docker/templates/centos-7.Dockerfile.in | 3 - .../docker/templates/debian-8.Dockerfile.in | 4 - .../docker/templates/debian-9.Dockerfile.in | 4 - .../docker/templates/fedora-24.Dockerfile.in | 5 - .../docker/templates/fedora-25.Dockerfile.in | 5 - .../docker/templates/fedora-26.Dockerfile.in | 5 - .../docker/templates/gentoo.Dockerfile.in | 5 - .../docker/templates/ubuntu-14.Dockerfile.in | 4 - .../docker/templates/ubuntu-16.Dockerfile.in | 4 - .../docker/templates/ubuntu-17.Dockerfile.in | 4 - .../pdf-tools-autoloads.el | 387 - elpa/pdf-tools-20191031.642/pdf-tools-pkg.el | 13 - elpa/pdf-tools-20230611.239/README | 645 ++ .../build/Makefile | 26 +- .../build/server/.gitignore | 0 .../build/server/Makefile.am | 15 +- .../build/server/autobuild | 170 +- .../build/server/autogen.sh | 0 .../build/server/configure.ac | 19 +- .../build/server/epdfinfo.c | 425 +- .../build/server/epdfinfo.h | 6 - .../build/server/poppler-versions | 0 .../build/server/synctex_parser.c | 8924 +++++++++++++++++ .../build/server/synctex_parser.h | 429 + .../build/server/synctex_parser_advanced.h | 554 + .../build/server/synctex_parser_local.h | 3 + .../build/server/synctex_parser_readme.txt | 26 +- .../build/server/synctex_parser_utils.c | 170 +- .../build/server/synctex_parser_utils.h | 41 +- .../build/server/synctex_parser_version.txt | 1 + .../build/server/synctex_version.h} | 44 +- .../build/server/test/.gitignore | 1 + .../build/server/test/docker/.gitignore | 1 + .../build/server/test/docker/lib/run-tests | 24 + .../build/server/test/docker/lib/yes-or-enter | 0 .../docker/templates/Dockerfile.common.in | 4 + .../templates/arch.Dockerfile.in.FAILING | 4 + .../templates/centos.Dockerfile.in.FAILING | 6 + .../docker/templates/debian-10.Dockerfile.in | 6 + .../docker/templates/debian-11.Dockerfile.in | 6 + .../docker/templates/debian-9.Dockerfile.in | 6 + .../docker/templates/emacs-26.Dockerfile.in | 5 + .../docker/templates/emacs-27.Dockerfile.in | 5 + .../docker/templates/emacs-28.Dockerfile.in | 5 + .../docker/templates/emacs-29.Dockerfile.in | 5 + .../docker/templates/fedora-34.Dockerfile.in | 4 + .../docker/templates/fedora-35.Dockerfile.in | 4 + .../docker/templates/fedora-36.Dockerfile.in | 4 + .../templates/freebsd.Dockerfile.in.FAILING | 0 .../templates/gentoo.Dockerfile.in.FAILING | 6 + .../templates/macos.Dockerfile.in.FAILING | 0 .../templates/msys2.Dockerfile.in.FAILING | 0 .../templates/nixos.Dockerfile.in.FAILING | 0 .../templates/openbsd.Dockerfile.in.FAILING | 0 .../templates/opensuse.Dockerfile.in.FAILING | 0 .../docker/templates/ubuntu-18.Dockerfile.in | 5 + .../docker/templates/ubuntu-20.Dockerfile.in | 5 + .../docker/templates/ubuntu-22.Dockerfile.in | 5 + .../templates/void.Dockerfile.in.FAILING | 0 .../pdf-annot.el | 360 +- .../pdf-cache.el | 109 +- .../pdf-dev.el | 12 +- .../pdf-history.el | 16 +- .../pdf-info.el | 221 +- .../pdf-isearch.el | 9 +- .../pdf-links.el | 9 +- .../pdf-loader.el | 0 elpa/pdf-tools-20230611.239/pdf-macs.el | 51 + .../pdf-misc.el | 86 +- .../pdf-occur.el | 80 +- .../pdf-outline.el | 98 +- .../pdf-sync.el | 81 +- .../pdf-tools-autoloads.el | 637 ++ elpa/pdf-tools-20230611.239/pdf-tools-pkg.el | 16 + .../pdf-tools.el | 61 +- .../pdf-util.el | 366 +- .../pdf-view.el | 377 +- .../pdf-virtual.el | 19 +- 87 files changed, 13114 insertions(+), 6920 deletions(-) delete mode 100644 elpa/pdf-tools-20191031.642/README delete mode 100644 elpa/pdf-tools-20191031.642/build/server/m4/ax_check_compile_flag.m4 delete mode 100644 elpa/pdf-tools-20191031.642/build/server/poppler-hack.cc delete mode 100644 elpa/pdf-tools-20191031.642/build/server/synctex_parser.c delete mode 100644 elpa/pdf-tools-20191031.642/build/server/synctex_parser.h delete mode 100644 elpa/pdf-tools-20191031.642/build/server/synctex_parser_version.txt delete mode 100755 elpa/pdf-tools-20191031.642/build/server/test/docker/lib/run-tests delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/arch.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/centos-7.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-8.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-9.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-24.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-25.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-26.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/gentoo.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-14.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-16.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-17.Dockerfile.in delete mode 100644 elpa/pdf-tools-20191031.642/pdf-tools-autoloads.el delete mode 100644 elpa/pdf-tools-20191031.642/pdf-tools-pkg.el create mode 100644 elpa/pdf-tools-20230611.239/README rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/Makefile (81%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/.gitignore (100%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/Makefile.am (73%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/autobuild (77%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/autogen.sh (100%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/configure.ac (85%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/epdfinfo.c (89%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/epdfinfo.h (97%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/poppler-versions (100%) create mode 100644 elpa/pdf-tools-20230611.239/build/server/synctex_parser.c create mode 100644 elpa/pdf-tools-20230611.239/build/server/synctex_parser.h create mode 100644 elpa/pdf-tools-20230611.239/build/server/synctex_parser_advanced.h create mode 100644 elpa/pdf-tools-20230611.239/build/server/synctex_parser_local.h rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/synctex_parser_readme.txt (87%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/synctex_parser_utils.c (80%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/synctex_parser_utils.h (89%) create mode 100644 elpa/pdf-tools-20230611.239/build/server/synctex_parser_version.txt rename elpa/{pdf-tools-20191031.642/build/server/synctex_parser_local.h => pdf-tools-20230611.239/build/server/synctex_version.h} (58%) create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/.gitignore rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/test/docker/.gitignore (63%) create mode 100755 elpa/pdf-tools-20230611.239/build/server/test/docker/lib/run-tests rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/build/server/test/docker/lib/yes-or-enter (100%) create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/Dockerfile.common.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/arch.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/centos.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-10.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-11.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-9.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-26.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-27.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-28.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-29.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-34.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-35.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-36.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/freebsd.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/macos.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/msys2.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/nixos.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/openbsd.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/opensuse.Dockerfile.in.FAILING create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-18.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-20.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-22.Dockerfile.in create mode 100644 elpa/pdf-tools-20230611.239/build/server/test/docker/templates/void.Dockerfile.in.FAILING rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-annot.el (85%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-cache.el (80%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-dev.el (90%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-history.el (91%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-info.el (91%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-isearch.el (99%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-links.el (98%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-loader.el (100%) create mode 100644 elpa/pdf-tools-20230611.239/pdf-macs.el rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-misc.el (77%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-occur.el (93%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-outline.el (87%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-sync.el (92%) create mode 100644 elpa/pdf-tools-20230611.239/pdf-tools-autoloads.el create mode 100644 elpa/pdf-tools-20230611.239/pdf-tools-pkg.el rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-tools.el (89%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-util.el (83%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-view.el (84%) rename elpa/{pdf-tools-20191031.642 => pdf-tools-20230611.239}/pdf-virtual.el (98%) diff --git a/elpa/pdf-tools-20191031.642/README b/elpa/pdf-tools-20191031.642/README deleted file mode 100644 index 6738261d..00000000 --- a/elpa/pdf-tools-20191031.642/README +++ /dev/null @@ -1,381 +0,0 @@ -#+TITLE: PDF Tools README -#+AUTHOR: Andreas Politz -#+EMAIL: politza@fh-trier.de - -[[https://travis-ci.org/politza/pdf-tools.svg?branch%3Dmaster][https://travis-ci.org/politza/pdf-tools.svg?branch=master]] -[[http://stable.melpa.org/#/pdf-tools][http://stable.melpa.org/packages/pdf-tools-badge.svg]] -[[http://melpa.org/#/pdf-tools][http://melpa.org/packages/pdf-tools-badge.svg]] - - - -** About this package - PDF Tools is, among other things, a replacement of DocView for PDF - files. The key difference is that pages are not pre-rendered by - e.g. ghostscript and stored in the file-system, but rather created - on-demand and stored in memory. - - This rendering is performed by a special library named, for - whatever reason, poppler, running inside a server program. This - program is called ~epdfinfo~ and its job is to successively - read requests from Emacs and produce the proper results, i.e. the - PNG image of a PDF page. - - Actually, displaying PDF files is just one part of PDF Tools. - Since poppler can provide us with all kinds of information about a - document and is also able to modify it, there is a lot more we can - do with it. [[http://www.dailymotion.com/video/x2bc1is_pdf-tools-tourdeforce_tech?forcedQuality%3Dhd720][Watch]] - - Please read also about [[#known-problems][known problems.]] - -** Features - + View :: View PDF documents in a buffer with DocView-like - bindings. - + Isearch :: Interactively search PDF documents like any other - buffer, either for a string or a PCRE. - + Occur :: List lines matching a string or regexp in one or more - PDF documents. - + Follow :: - Click on highlighted links, moving to some part of a different - page, some external file, a website or any other URI. Links may - also be followed by keyboard commands. - + Annotations :: Display and list text and markup annotations (like - underline), edit their contents and attributes - (e.g. color), move them around, delete them or - create new ones and then save the modifications - back to the PDF file. - + Attachments :: Save files attached to the PDF-file or list them - in a dired buffer. - + Outline :: Use imenu or a special buffer to examine and navigate - the PDF's outline. - + SyncTeX :: Jump from a position on a page directly to the TeX - source and vice versa. - + Virtual :: - Use a collection of documents as if it were one, big single PDF. - - + Misc :: - - Display PDF's metadata. - - Mark a region and kill the text from the PDF. - - Keep track of visited pages via a history. - - Apply a color filter for reading in low light conditions. - -** Installation - The package may be installed via melpa and it will try to build the - server part when it is activated the first time. Though the next - section regarding build-prerequisites is still relevant, the rest - of the installation instructions assume a build from within a git - repository. (The melpa package has a different directory - structure.) - -*** Server Prerequisites - You'll need GNU Emacs \ge 24.3 and some form of a GNU/Linux OS. - Other operating systems are currently not supported (patches - welcome). The following instructions assume a Debian-based - system. (The prerequisites may be installed automatically on this - kind of systems, see [[#compilation][Compilation]] .) - - First make sure a suitable build-system is installed. We need at - least a C/C++ compiler (both ~gcc~ and ~g++~), ~make~, ~automake~ - and ~autoconf~. - - Next we need to install a few libraries PDF Tools depends on, some - of which are probably already on your system. -#+begin_src sh - $ sudo aptitude install libpng-dev zlib1g-dev - $ sudo aptitude install libpoppler-glib-dev - $ sudo aptitude install libpoppler-private-dev -#+end_src - On some older Ubuntu systems, the final command will possibly give - an error. This should be no problem, since in some versions this - package was contained in the main package ~libpoppler-dev~. Also - note, that ~zlib1g-dev~ was for a long time called ~libz-dev~, - which it still may be on your system. - - Debian wheezy comes with libpoppler version 0.18, which is pretty - old. The minimally required version is 0.16, but some features of - PDF Tools depend on a more recent version of this library. See - the following table for what they are and what version they - require. - - | You want to ... | Required version | - |-------------------------------------------+------------------| - | ... create and modify text annotations. | \ge 0.19.4 | - | ... search case-sensitive. | \ge 0.22 | - | ... create and modify markup annotations. | \ge 0.26 | - |-------------------------------------------+------------------| - - In case you decide to install libpoppler from source, make sure - to run its configure script with the ~--enable-xpdf-headers~ - option. - - Finally there is one feature (following links of a PDF document by - plain keystrokes) which requires imagemagick's convert utility. - This requirement is optional and you may install it like so: -#+begin_src sh - $ sudo aptitude install imagemagick -#+end_src -**** Compiling on OS X - Although OS X is not officially supported, it has been reported - to have been successfully compiled. You will need to install - poppler which you can get with homebrew via -#+BEGIN_SRC sh - $ brew install poppler automake -#+END_SRC - - You will also have to help ~pkg-config~ find some libraries by - setting ~PKG_CONFIG_PATH~, e.g. -#+BEGIN_SRC sh - $ export PKG_CONFIG_PATH=/usr/local/Cellar/zlib/1.2.8/lib/pkgconfig:/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig -#+END_SRC - or likewise within Emacs using `setenv`. - - After that, compilation should proceed as normal. -**** FreeBSD - Although not officially supported, it has been reported that - pdf-tools work well on FreeBSD. Instead of building pdf-tools, you - can install one of the OS packages with, e.g. -#+BEGIN_SRC sh - $ pkg install pdf-tools-emacs26 -#+END_SRC - To see the current list of pdf-tools packages for FreeBSD visit - [[https://repology.org/metapackages/?search=pdf-tools&inrepo=freebsd][the Repology list]]. - - To build pdf-tools from either melpa or directly from the source - repository, install the dependencies with -#+BEGIN_SRC sh - $ pkg install autotools gmake poppler-glib -#+END_SRC - - If you choose not to install from melpa, you must substitute - ~gmake~ for ~make~ in the instructions below. -**** Compiling on Centos - It is possible to compile pdf-tools on Centos. Install poppler the dependencies with: -#+BEGIN_SRC sh - $ yum install poppler-devel poppler-glib-devel -#+END_SRC - -**** Compiling on Fedora -#+BEGIN_SRC sh - $ sudo dnf install make automake autoconf gcc gcc-c++ ImageMagick libpng-devel zlib-devel poppler-glib-devel -#+END_SRC - -**** Compiling on Alpine Linux -#+BEGIN_SRC sh - $ apk add build-base g++ gcc automake autoconf libpng-dev glib-dev poppler-dev -#+END_SRC - -**** Compiling on Windows - PDF Tools can be built and used on Windows using the MSYS2 - compiler. This will work with native (not cygwin) Windows builds of - emacs. This includes the standard binaries provided by the GNU - project, those available as MSYS2 packages and numerous third-party - binaries. It has been tested with emacs 25.1. Instructions are - provided under [[#compilation-and-installation-on-windows][Compilation and installation on Windows]], below. - PDF Tools will successfully compile using Cygwin, but it will not be - able to open PDFs properly due to the way binaries compiled with Cygwin - handle file paths. - -*** Compilation - :PROPERTIES: - :CUSTOM_ID: compilation - :END: - Now it's time to compile the source. -#+begin_src sh - $ cd /path/to/pdf-tools - $ make install-server-deps # optional - $ make -s -#+end_src - The ~make install-server-deps~ command will try to install all - necessary programs and libraries to build the package, though - it'll only work, if ~sudo~ and ~apt-get~ are available. - - This should compile the source code and create a Emacs Lisp - Package in the root directory of the project. The configure script - also tells you at the very end, which features, depending on the - libpoppler version, will be available. These commands should give - no error, otherwise you are in trouble. -**** Compilation and installation on Windows - If using the GNU binaries for Windows, support for PNG and zlib - must first be installed by copying the appropriate dlls into - emacs' ~bin/~ directory. Most third-party binaries come with this - already done. - - First, install [[http://www.msys2.org/][install MSYS2]] and update - the package database and core packages using the instructions - provided. Then, to compile PDF tools itself: - - 1. Open msys2 shell - - 2. Update and install dependencies, skipping any you already have - #+BEGIN_SRC sh - $ pacman -Syu - $ pacman -S base-devel - $ pacman -S mingw-w64-x86_64-toolchain - $ pacman -S mingw-w64-x86_64-zlib - $ pacman -S mingw-w64-x86_64-libpng - $ pacman -S mingw-w64-x86_64-poppler - $ pacman -S mingw-w64-x86_64-imagemagick - #+END_SRC - - 3. Install PDF tools in Emacs, but do not try to compile the - server. Instead, get a separate copy of the source somewhere - else. - #+BEGIN_SRC sh - $ git clone https://github.com/politza/pdf-tools - #+END_SRC - - 4. Open mingw64 shell (*Note:* You must use mingw64.exe and not msys2.exe) - - 5. Compile pdf-tools - #+BEGIN_SRC sh - $ cd /path/to/pdf-tools - $ make -s - #+END_SRC - - 6. This should produce a file ~server/epdfinfo.exe~. Copy this file - into the ~pdf-tools/~ installation directory in your Emacs. - - 7. Start Emacs and activate the package. - #+BEGIN_SRC - M-x pdf-tools-install RET - #+END_SRC - - 8. Test. - #+BEGIN_SRC - M-x pdf-info-check-epdfinfo RET - #+END_SRC - - If this is successful, ~(pdf-tools-install)~ can be added to Emacs' - config. Note that libraries from other GNU utilities, such as Git - for Windows, may interfere with those needed by PDF Tools. - ~pdf-info-check-epdinfo~ will succeed, but errors occur when trying - to view a PDF file. This can be fixed by ensuring that the MSYS - libraries are always preferred in emacs: - - #+BEGIN_SRC emacs-lisp - (setenv "PATH" (concat "C:\\msys64\\mingw64\\bin;" (getenv "PATH"))) - #+END_SRC - -*** ELisp Prerequisites - This package depends on the following Elisp packages, which should - be installed before installing the Pdf Tools package. - - | Package | Required version | - |-----------+----------------------------------| - | [[https://elpa.gnu.org/packages/let-alist.html][let-alist]] | >= 1.0.4 (comes with Emacs 25.2) | - | [[http://melpa.org/#/tablist][tablist]] | >= 0.70 | - |-----------+----------------------------------| - -*** Installing - If ~make~ produced the ELP file ~pdf-tools-${VERSION}.tar~ you are - fine. This package contains all the necessary files for Emacs - and may be installed by either using -#+begin_src sh - $ make install-package -#+end_src - or executing the Emacs command -#+begin_src elisp - M-x package-install-file RET pdf-tools-${VERSION}.tar RET -#+end_src - - To complete the installation process, you need to activate the - package by putting -#+begin_src elisp - (pdf-tools-install) -#+end_src - somewhere in your ~.emacs~. Alternatively, and if you care about - start-up time, you may want to use -#+begin_src elisp - (pdf-loader-install) -#+end_src - instead. Next you probably want to take a look at the various - features of what you've just installed. The following two commands - might be of help for doing so. -#+begin_src elisp - M-x pdf-tools-help RET - M-x pdf-tools-customize RET -#+end_src - -*** Updating - Some day you might want to update this package via ~git pull~ and - then reinstall it. Sometimes this may fail, especially if - Lisp-Macros are involved and the version hasn't changed. To avoid - this kind of problems, you should delete the old package via - ~list-packages~, restart Emacs and then reinstall the package. - - This also applies when updating via package and melpa. - -** Known problems - :PROPERTIES: - :CUSTOM_ID: known-problems - :END: - -*** linum-mode - PDF Tools does not work well together with ~linum-mode~ and - activating it in a ~pdf-view-mode~, e.g. via ~global-linum-mode~, - might make Emacs choke. - -*** auto-revert - Autorevert works by polling the file-system every - ~auto-revert-interval~ seconds, optionally combined with some - event-based reverting via [[https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Notifications.html][file notification]]. But this currently - does not work reliably, such that Emacs may revert the PDF-buffer - while the corresponding file is still being written to (e.g. by - LaTeX), leading to a potential error. - - With a recent [[https://www.gnu.org/software/auctex/][auctex]] installation, you might want to put the - following somewhere in your dotemacs, which will revert the PDF-buffer - *after* the TeX compilation has finished. -#+BEGIN_SRC emacs-lisp - (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer) -#+END_SRC -** Some keybindings - -| Navigation | | -|--------------------------------------------+-----------------------| -| Scroll Up / Down by page-full | ~space~ / ~backspace~ | -| Scroll Up / Down by line | ~C-n~ / ~C-p~ | -| Scroll Right / Left | ~C-f~ / ~C-b~ | -| Top of Page / Bottom of Page | ~<~ / ~>~ | -| Next Page / Previous Page | ~n~ / ~p~ | -| First Page / Last Page | ~M-<~ / ~M->~ | -| Incremental Search Forward / Backward | ~C-s~ / ~C-r~ | -| Occur (list all lines containing a phrase) | ~M-s o~ | -| Jump to Occur Line | ~RETURN~ | -| Pick a Link and Jump | ~F~ | -| Incremental Search in Links | ~f~ | -| History Back / Forwards | ~B~ / ~N~ | -| Display Outline | ~o~ | -| Jump to Section from Outline | ~RETURN~ | -| Jump to Page | ~M-g g~ | - -| Display | | -|------------------------------------------+-----------------| -| Zoom in / Zoom out | ~+~ / ~-~ | -| Fit Height / Fit Width / Fit Page | ~H~ / ~W~ / ~P~ | -| Trim margins (set slice to bounding box) | ~s b~ | -| Reset margins | ~s r~ | -| Reset Zoom | 0 | - -| Annotations | | -|-------------------------------+-------------------------------------------------| -| List Annotations | ~C-c C-a l~ | -| Jump to Annotations from List | ~SPACE~ | -| Mark Annotation for Deletion | ~d~ | -| Delete Marked Annotations | ~x~ | -| Unmark Annotations | ~u~ | -| Close Annotation List | ~q~ | -| Add and edit annotations | via Mouse selection and left-click context menu | - -| Syncing with Auctex | | -|----------------------------------+-------------| -| jump to PDF location from source | ~C-c C-g~ | -| jump source location from PDF | ~C-mouse-1~ | - -| Miscellaneous | | -|-----------------------------------------------+-----------| -| Refresh File (e.g., after recompiling source) | ~g~ | -| Print File | ~C-c C-p~ | - -# Local Variables: -# mode: org -# End: diff --git a/elpa/pdf-tools-20191031.642/build/server/m4/ax_check_compile_flag.m4 b/elpa/pdf-tools-20191031.642/build/server/m4/ax_check_compile_flag.m4 deleted file mode 100644 index dcabb92a..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_COMPILE_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 5 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/elpa/pdf-tools-20191031.642/build/server/poppler-hack.cc b/elpa/pdf-tools-20191031.642/build/server/poppler-hack.cc deleted file mode 100644 index 24511018..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/poppler-hack.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2013, 2014 Andreas Politz - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include -#include -#include -#include -#include -#include - -extern "C" -{ - -GType poppler_annot_get_type (void) G_GNUC_CONST; -GType poppler_annot_markup_get_type (void) G_GNUC_CONST; - -#define POPPLER_TYPE_ANNOT (poppler_annot_get_type ()) -#define POPPLER_ANNOT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_ANNOT, PopplerAnnot)) -#define POPPLER_IS_ANNOT_MARKUP(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_ANNOT_MARKUP)) -#define POPPLER_TYPE_ANNOT_MARKUP (poppler_annot_markup_get_type ()) - -#if POPPLER_CHECK_VERSION(0,72,0) -#define GET_CSTR c_str -#else -#define GET_CSTR getCString -#endif - - struct PopplerAnnot - { - GObject parent_instance; - Annot *annot; - }; - - struct PopplerAnnotMarkup - { - GObject parent_instance; - }; - - struct PopplerRectangle - { - double x1; - double y1; - double x2; - double y2; - }; - - // This function does not modify its argument s, but for - // compatibility reasons (e.g. getLength in GooString.h before 2015) - // with older poppler code, it can't be declared as such. - char *_xpoppler_goo_string_to_utf8(/* const */ GooString *s) - { - char *result; - - if (! s) - return NULL; - - if (s->hasUnicodeMarker()) { - result = g_convert (s->GET_CSTR () + 2, - s->getLength () - 2, - "UTF-8", "UTF-16BE", NULL, NULL, NULL); - } else { - int len; - gunichar *ucs4_temp; - int i; - - len = s->getLength (); - ucs4_temp = g_new (gunichar, len + 1); - for (i = 0; i < len; ++i) { - ucs4_temp[i] = pdfDocEncoding[(unsigned char)s->getChar(i)]; - } - ucs4_temp[i] = 0; - - result = g_ucs4_to_utf8 (ucs4_temp, -1, NULL, NULL, NULL); - - g_free (ucs4_temp); - } - - return result; - } -#ifdef HAVE_POPPLER_ANNOT_WRITE - // Set the rectangle of an annotation. It was first added in v0.26. - void xpoppler_annot_set_rectangle (PopplerAnnot *a, PopplerRectangle *rectangle) - { - GooString *state = (GooString*) a->annot->getAppearState (); - char *ustate = _xpoppler_goo_string_to_utf8 (state); - - a->annot->setRect (rectangle->x1, rectangle->y1, - rectangle->x2, rectangle->y2); - a->annot->setAppearanceState (ustate); - g_free (ustate); - } -#endif - // This function is in the library, but the enforced date parsing is - // incomplete (at least in some versions), because it ignores the - // timezone. - gchar *xpoppler_annot_markup_get_created (PopplerAnnotMarkup *poppler_annot) - { - AnnotMarkup *annot; - GooString *text; - - g_return_val_if_fail (POPPLER_IS_ANNOT_MARKUP (poppler_annot), NULL); - - annot = static_cast(POPPLER_ANNOT (poppler_annot)->annot); - text = (GooString*) annot->getDate (); - - return text ? _xpoppler_goo_string_to_utf8 (text) : NULL; - } -} diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser.c b/elpa/pdf-tools-20191031.642/build/server/synctex_parser.c deleted file mode 100644 index 5b7e8c52..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser.c +++ /dev/null @@ -1,4414 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.18 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -Acknowledgments: ----------------- -The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, -and significant help from XeTeX developer Jonathan Kew - -Nota Bene: ----------- -If you include or use a significant part of the synctex package into a software, -I would appreciate to be listed as contributor and see "SyncTeX" highlighted. - -Version 1 -Thu Jun 19 09:39:21 UTC 2008 - -*/ - -/* We assume that high level application like pdf viewers will want - * to embed this code as is. We assume that they also have locale.h and setlocale. - * For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER, - * when building. You also have to create and customize synctex_parser_local.h to fit your system. - * In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined. - * With this design, you should not need to edit this file. */ - -# if defined(SYNCTEX_USE_LOCAL_HEADER) -# include "synctex_parser_local.h" -# else -# define HAVE_LOCALE_H 1 -# define HAVE_SETLOCALE 1 -# if defined(_MSC_VER) -# define SYNCTEX_INLINE __inline -# else -# define SYNCTEX_INLINE inline -# endif -# endif - -#include -#include -#include -#include -#include - -#if defined(HAVE_LOCALE_H) -#include -#endif - -/* The data is organized in a graph with multiple entries. - * The root object is a scanner, it is created with the contents on a synctex file. - * Each leaf of the tree is a synctex_node_t object. - * There are 3 subtrees, two of them sharing the same leaves. - * The first tree is the list of input records, where input file names are associated with tags. - * The second tree is the box tree as given by TeX when shipping pages out. - * First level objects are sheets, containing boxes, glues, kerns... - * The third tree allows to browse leaves according to tag and line. - */ - -#include "synctex_parser.h" -#include "synctex_parser_utils.h" - -#define printf(fmt, args...) (fprintf (stderr, (fmt), ## args)) - -/* These are the possible extensions of the synctex file */ -const char * synctex_suffix = ".synctex"; -const char * synctex_suffix_gz = ".gz"; - -/* each synctex node has a class */ -typedef struct __synctex_class_t _synctex_class_t; -typedef _synctex_class_t * synctex_class_t; - - -/* synctex_node_t is a pointer to a node - * _synctex_node is the target of the synctex_node_t pointer - * It is a pseudo object oriented program. - * class is a pointer to the class object the node belongs to. - * implementation is meant to contain the private data of the node - * basically, there are 2 kinds of information: navigation information and - * synctex information. Both will depend on the type of the node, - * thus different nodes will have different private data. - * There is no inheritancy overhead. - */ -typedef union _synctex_info_t { - int INT; - char * PTR; -} synctex_info_t; - -# if defined(SYNCTEX_USE_CHARINDEX) -# define SYNCTEX_DECLARE_CHARINDEX synctex_charindex_t char_index; -# define SYNCTEX_CHARINDEX(NODE) (NODE->char_index) -# define SYNCTEX_PRINT_CHARINDEX printf("#%i\n",SYNCTEX_CHARINDEX(node)) -# define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset -# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) NODE->char_index = (synctex_charindex_t)(scanner->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION)); -# else -# define SYNCTEX_DECLARE_CHARINDEX -# define SYNCTEX_CHARINDEX(NODE) 0 -# define SYNCTEX_PRINT_CHARINDEX printf("\n") -# define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset -# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) -# endif - -struct _synctex_node { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t * implementation; -}; - -/* Each node of the tree, except the scanner itself belongs to a class. - * The class object is just a struct declaring the owning scanner - * This is a pointer to the scanner as root of the tree. - * The type is used to identify the kind of node. - * The class declares pointers to a creator and a destructor method. - * The log and display fields are used to log and display the node. - * display will also display the child, sibling and parent sibling. - * parent, child and sibling are used to navigate the tree, - * from TeX box hierarchy point of view. - * The friend field points to a method which allows to navigate from friend to friend. - * A friend is a node with very close tag and line numbers. - * Finally, the info field point to a method giving the private node info offset. - */ - -typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t); -typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t); - -struct __synctex_class_t { - synctex_scanner_t scanner; - int type; - synctex_node_t (*new)(synctex_scanner_t scanner); - void (*free)(synctex_node_t); - void (*log)(synctex_node_t); - void (*display)(synctex_node_t); - _synctex_node_getter_t parent; - _synctex_node_getter_t child; - _synctex_node_getter_t sibling; - _synctex_node_getter_t friend; - _synctex_node_getter_t next_hbox; - _synctex_info_getter_t info; -}; - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Abstract OBJECTS and METHODS -# endif - -/* These macros are shortcuts - * This macro checks if a message can be sent. - */ -# define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\ - (NULL!=((((NODE)->class))->SELECTOR)) - -/* This macro is some kind of objc_msg_send. - * It takes care of sending the proper message if possible. - */ -# define SYNCTEX_MSG_SEND(NODE,SELECTOR) if (NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\ - (*((((NODE)->class))->SELECTOR))(NODE);\ - } - -/* read only safe getter - */ -# define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL)) - -/* read/write getter - */ -# define SYNCTEX_GETTER(NODE,SELECTOR)\ - ((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE))) - -# define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free); - -/* Parent getter and setter - */ -# define SYNCTEX_PARENT(NODE) SYNCTEX_GET(NODE,parent) -# define SYNCTEX_SET_PARENT(NODE,NEW_PARENT) if (NODE && NEW_PARENT && SYNCTEX_CAN_PERFORM(NODE,parent)){\ - SYNCTEX_GETTER(NODE,parent)[0]=NEW_PARENT;\ - } - -/* Child getter and setter - */ -# define SYNCTEX_CHILD(NODE) SYNCTEX_GET(NODE,child) -# define SYNCTEX_SET_CHILD(NODE,NEW_CHILD) if (NODE && NEW_CHILD){\ - SYNCTEX_GETTER(NODE,child)[0]=NEW_CHILD;\ - SYNCTEX_GETTER(NEW_CHILD,parent)[0]=NODE;\ - } - -/* Sibling getter and setter - */ -# define SYNCTEX_SIBLING(NODE) SYNCTEX_GET(NODE,sibling) -# define SYNCTEX_SET_SIBLING(NODE,NEW_SIBLING) if (NODE && NEW_SIBLING) {\ - SYNCTEX_GETTER(NODE,sibling)[0]=NEW_SIBLING;\ - if (SYNCTEX_CAN_PERFORM(NEW_SIBLING,parent) && SYNCTEX_CAN_PERFORM(NODE,parent)) {\ - SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\ - }\ - } -/* Friend getter and setter. A friend is a kern, math, glue or void box node which tag and line numbers are similar. - * This is a first filter on the nodes that avoids testing all of them. - * Friends are used mainly in forward synchronization aka from source to output. - */ -# define SYNCTEX_FRIEND(NODE) SYNCTEX_GET(NODE,friend) -# define SYNCTEX_SET_FRIEND(NODE,NEW_FRIEND) if (NODE && NEW_FRIEND){\ - SYNCTEX_GETTER(NODE,friend)[0]=NEW_FRIEND;\ - } - -/* Next box getter and setter. The box tree can be traversed from one horizontal box to the other. - * Navigation starts with the deeper boxes. - */ -# define SYNCTEX_NEXT_hbox(NODE) SYNCTEX_GET(NODE,next_hbox) -# define SYNCTEX_SET_NEXT_hbox(NODE,NEXT_HBOX) if (NODE && NEXT_HBOX){\ - SYNCTEX_GETTER(NODE,next_hbox)[0]=NEXT_HBOX;\ - } - -/* A node is meant to own its child and sibling. - * It is not owned by its parent, unless it is its first child. - * This destructor is for all nodes with children. - */ -static void _synctex_free_node(synctex_node_t node) { - if (node) { - (*((node->class)->sibling))(node); - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - SYNCTEX_FREE(SYNCTEX_CHILD(node)); - free(node); - } - return; -} - -/* A node is meant to own its child and sibling. - * It is not owned by its parent, unless it is its first child. - * This destructor is for nodes with no child. - * The first sheet is onwned by the scanner. - */ -static void _synctex_free_leaf(synctex_node_t node) { - if (node) { - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - free(node); - } - return; -} -# ifdef __SYNCTEX_WORK__ -# include "/usr/include/zlib.h" -# else -# include -# endif - -/* The synctex scanner is the root object. - * Is is initialized with the contents of a text file or a gzipped file. - * The buffer_? are first used to parse the text. - */ -struct __synctex_scanner_t { - gzFile file; /* The (possibly compressed) file */ - SYNCTEX_DECLARE_CHAR_OFFSET; - char * buffer_cur; /* current location in the buffer */ - char * buffer_start; /* start of the buffer */ - char * buffer_end; /* end of the buffer */ - char * output_fmt; /* dvi or pdf, not yet used */ - char * output; /* the output name used to create the scanner */ - char * synctex; /* the .synctex or .synctex.gz name used to create the scanner */ - int version; /* 1, not yet used */ - struct { - unsigned has_parsed:1; /* Whether the scanner has parsed its underlying synctex file. */ - unsigned reserved:sizeof(unsigned)-1; /* alignment */ - } flags; - int pre_magnification; /* magnification from the synctex preamble */ - int pre_unit; /* unit from the synctex preamble */ - int pre_x_offset; /* X offste from the synctex preamble */ - int pre_y_offset; /* Y offset from the synctex preamble */ - int count; /* Number of records, from the synctex postamble */ - float unit; /* real unit, from synctex preamble or post scriptum */ - float x_offset; /* X offset, from synctex preamble or post scriptum */ - float y_offset; /* Y Offset, from synctex preamble or post scriptum */ - synctex_node_t sheet; /* The first sheet node, its siblings are the other sheet nodes */ - synctex_node_t input; /* The first input node, its siblings are the other input nodes */ - int number_of_lists; /* The number of friend lists */ - synctex_node_t * lists_of_friends;/* The friend lists */ - _synctex_class_t class[synctex_node_number_of_types]; /* The classes of the nodes of the scanner */ -}; - -/* SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts - */ -# define SYNCTEX_CUR (scanner->buffer_cur) -# define SYNCTEX_START (scanner->buffer_start) -# define SYNCTEX_END (scanner->buffer_end) - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark OBJECTS, their creators and destructors. -# endif - -/* Here, we define the indices for the different informations. - * They are used to declare the size of the implementation. - * For example, if one object uses SYNCTEX_HORIZ_IDX is its size, - * then its info will contain a tag, line, column, horiz but no width nor height nor depth - */ - -/* The sheet is a first level node. - * It has no parent (the parent is the scanner itself) - * Its sibling points to another sheet. - * Its child points to its first child, in general a box. - * A sheet node contains only one synctex information: the page. - * This is the 1 based page index as given by TeX. - */ -/* The next macros are used to access the node info - * SYNCTEX_INFO(node) points to the first synctex integer or pointer data of node - * SYNCTEX_INFO(node)[index] is the information at index - * for example, the page of a sheet is stored in SYNCTEX_INFO(sheet)[SYNCTEX_PAGE_IDX] - */ -# define SYNCTEX_INFO(NODE) ((*((((NODE)->class))->info))(NODE)) -# define SYNCTEX_PAGE_IDX 0 -# define SYNCTEX_PAGE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_PAGE_IDX].INT - -/* This macro defines implementation offsets - * It is only used for pointer values - */ -# define SYNCTEX_MAKE_GET(SYNCTEX_GETTER,OFFSET)\ -static synctex_node_t * SYNCTEX_GETTER (synctex_node_t node) {\ - return node?(synctex_node_t *)((&((node)->implementation))+OFFSET):NULL;\ -} -SYNCTEX_MAKE_GET(_synctex_implementation_0,0) -SYNCTEX_MAKE_GET(_synctex_implementation_1,1) -SYNCTEX_MAKE_GET(_synctex_implementation_2,2) -SYNCTEX_MAKE_GET(_synctex_implementation_3,3) -SYNCTEX_MAKE_GET(_synctex_implementation_4,4) -SYNCTEX_MAKE_GET(_synctex_implementation_5,5) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/* child, sibling, next box, - * SYNCTEX_PAGE_IDX */ -} synctex_node_sheet_t; - -/* sheet node creator */ - -#define DEFINE_synctex_new_NODE(NAME)\ -static synctex_node_t _synctex_new_##NAME(synctex_scanner_t scanner) {\ - if (scanner) {\ - synctex_node_t node = _synctex_malloc(sizeof(synctex_node_##NAME##_t));\ - if (node) {\ - SYNCTEX_IMPLEMENT_CHARINDEX(node,0);\ - ++SYNCTEX_CUR;\ - node->class = scanner->class+synctex_node_type_##NAME;\ - }\ - return node;\ - }\ - return NULL;\ -} -DEFINE_synctex_new_NODE(sheet) - -static void _synctex_display_sheet(synctex_node_t node); -static void _synctex_log_sheet(synctex_node_t node); - -static _synctex_class_t synctex_class_sheet = { - NULL, /* No scanner yet */ - synctex_node_type_sheet, /* Node type */ - &_synctex_new_sheet, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_sheet, /* log */ - &_synctex_display_sheet, /* display */ - NULL, /* No parent */ - &_synctex_implementation_0, /* child */ - &_synctex_implementation_1, /* sibling */ - NULL, /* No friend */ - &_synctex_implementation_2, /* Next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 /* info */ -}; - -/* A box node contains navigation and synctex information - * There are different kind of boxes. - * Only horizontal boxes are treated differently because of their visible size. - */ -# define SYNCTEX_TAG_IDX 0 -# define SYNCTEX_LINE_IDX (SYNCTEX_TAG_IDX+1) -# define SYNCTEX_COLUMN_IDX (SYNCTEX_LINE_IDX+1) -# define SYNCTEX_HORIZ_IDX (SYNCTEX_COLUMN_IDX+1) -# define SYNCTEX_VERT_IDX (SYNCTEX_HORIZ_IDX+1) -# define SYNCTEX_WIDTH_IDX (SYNCTEX_VERT_IDX+1) -# define SYNCTEX_HEIGHT_IDX (SYNCTEX_WIDTH_IDX+1) -# define SYNCTEX_DEPTH_IDX (SYNCTEX_HEIGHT_IDX+1) -/* the corresponding info accessors */ -# define SYNCTEX_TAG(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_TAG_IDX].INT -# define SYNCTEX_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_LINE_IDX].INT -# define SYNCTEX_COLUMN(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_COLUMN_IDX].INT -# define SYNCTEX_HORIZ(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_IDX].INT -# define SYNCTEX_VERT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_IDX].INT -# define SYNCTEX_WIDTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_IDX].INT -# define SYNCTEX_HEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_IDX].INT -# define SYNCTEX_DEPTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_IDX].INT -# define SYNCTEX_ABS_WIDTH(NODE) ((SYNCTEX_WIDTH(NODE)>0?SYNCTEX_WIDTH(NODE):-SYNCTEX_WIDTH(NODE))) -# define SYNCTEX_ABS_HEIGHT(NODE) ((SYNCTEX_HEIGHT(NODE)>0?SYNCTEX_HEIGHT(NODE):-SYNCTEX_HEIGHT(NODE))) -# define SYNCTEX_ABS_DEPTH(NODE) ((SYNCTEX_DEPTH(NODE)>0?SYNCTEX_DEPTH(NODE):-SYNCTEX_DEPTH(NODE))) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[5+SYNCTEX_DEPTH_IDX+1]; /* parent,child,sibling,friend,next box, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH */ -} synctex_node_vbox_t; - -/* vertical box node creator */ -DEFINE_synctex_new_NODE(vbox) - -static void _synctex_log_vbox(synctex_node_t node); -static void _synctex_display_vbox(synctex_node_t node); - -/* These are static class objects, each scanner will make a copy of them and setup the scanner field. - */ -static _synctex_class_t synctex_class_vbox = { - NULL, /* No scanner yet */ - synctex_node_type_vbox, /* Node type */ - &_synctex_new_vbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_vbox, /* log */ - &_synctex_display_vbox, /* display */ - &_synctex_implementation_0, /* parent */ - &_synctex_implementation_1, /* child */ - &_synctex_implementation_2, /* sibling */ - &_synctex_implementation_3, /* friend */ - &_synctex_implementation_4, /* next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_5 -}; - -/* Horizontal boxes must contain visible size, because 0 width does not mean emptiness. - * They also contain an average of the line numbers of the containing nodes. */ -# define SYNCTEX_MEAN_LINE_IDX (SYNCTEX_DEPTH_IDX+1) -# define SYNCTEX_NODE_WEIGHT_IDX (SYNCTEX_MEAN_LINE_IDX+1) -# define SYNCTEX_HORIZ_V_IDX (SYNCTEX_NODE_WEIGHT_IDX+1) -# define SYNCTEX_VERT_V_IDX (SYNCTEX_HORIZ_V_IDX+1) -# define SYNCTEX_WIDTH_V_IDX (SYNCTEX_VERT_V_IDX+1) -# define SYNCTEX_HEIGHT_V_IDX (SYNCTEX_WIDTH_V_IDX+1) -# define SYNCTEX_DEPTH_V_IDX (SYNCTEX_HEIGHT_V_IDX+1) -/* the corresponding info accessors */ -# define SYNCTEX_MEAN_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_MEAN_LINE_IDX].INT -# define SYNCTEX_NODE_WEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NODE_WEIGHT_IDX].INT -# define SYNCTEX_HORIZ_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_V_IDX].INT -# define SYNCTEX_VERT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_V_IDX].INT -# define SYNCTEX_WIDTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_V_IDX].INT -# define SYNCTEX_HEIGHT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_V_IDX].INT -# define SYNCTEX_DEPTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_V_IDX].INT -# define SYNCTEX_ABS_WIDTH_V(NODE) ((SYNCTEX_WIDTH_V(NODE)>0?SYNCTEX_WIDTH_V(NODE):-SYNCTEX_WIDTH_V(NODE))) -# define SYNCTEX_ABS_HEIGHT_V(NODE) ((SYNCTEX_HEIGHT_V(NODE)>0?SYNCTEX_HEIGHT_V(NODE):-SYNCTEX_HEIGHT_V(NODE))) -# define SYNCTEX_ABS_DEPTH_V(NODE) ((SYNCTEX_DEPTH_V(NODE)>0?SYNCTEX_DEPTH_V(NODE):-SYNCTEX_DEPTH_V(NODE))) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[5+SYNCTEX_DEPTH_V_IDX+1]; /*parent,child,sibling,friend,next box, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH, - * SYNCTEX_MEAN_LINE,SYNCTEX_NODE_WEIGHT, - * SYNCTEX_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/ -} synctex_node_hbox_t; - -/* horizontal box node creator */ -DEFINE_synctex_new_NODE(hbox) - -static void _synctex_display_hbox(synctex_node_t node); -static void _synctex_log_hbox(synctex_node_t node); - - -static _synctex_class_t synctex_class_hbox = { - NULL, /* No scanner yet */ - synctex_node_type_hbox, /* Node type */ - &_synctex_new_hbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_hbox, /* log */ - &_synctex_display_hbox, /* display */ - &_synctex_implementation_0, /* parent */ - &_synctex_implementation_1, /* child */ - &_synctex_implementation_2, /* sibling */ - &_synctex_implementation_3, /* friend */ - &_synctex_implementation_4, /* next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_5 -}; - -/* This void box node implementation is either horizontal or vertical - * It does not contain a child field. - */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_DEPTH_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH*/ -} synctex_node_void_vbox_t; - -/* vertical void box node creator */ -DEFINE_synctex_new_NODE(void_vbox) - -static void _synctex_log_void_box(synctex_node_t node); -static void _synctex_display_void_vbox(synctex_node_t node); - -static _synctex_class_t synctex_class_void_vbox = { - NULL, /* No scanner yet */ - synctex_node_type_void_vbox,/* Node type */ - &_synctex_new_void_vbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_void_box, /* log */ - &_synctex_display_void_vbox,/* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -typedef synctex_node_void_vbox_t synctex_node_void_hbox_t; - -/* horizontal void box node creator */ -DEFINE_synctex_new_NODE(void_hbox) - -static void _synctex_display_void_hbox(synctex_node_t node); - -static _synctex_class_t synctex_class_void_hbox = { - NULL, /* No scanner yet */ - synctex_node_type_void_hbox,/* Node type */ - &_synctex_new_void_hbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_void_box, /* log */ - &_synctex_display_void_hbox,/* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* The medium nodes correspond to kern, glue, penalty and math nodes. - * In LuaTeX, the size of the nodes may have changed. */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_WIDTH_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH */ -} synctex_node_medium_t; - -#define SYNCTEX_IS_BOX(NODE)\ - ((NODE->class->type == synctex_node_type_vbox)\ - || (NODE->class->type == synctex_node_type_void_vbox)\ - || (NODE->class->type == synctex_node_type_hbox)\ - || (NODE->class->type == synctex_node_type_void_hbox)) - -#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && SYNCTEX_CHILD(NODE)) - -static void _synctex_log_medium_node(synctex_node_t node); - -typedef synctex_node_medium_t synctex_node_math_t; - -/* math node creator */ -DEFINE_synctex_new_NODE(math) - -static void _synctex_display_math(synctex_node_t node); - -static _synctex_class_t synctex_class_math = { - NULL, /* No scanner yet */ - synctex_node_type_math, /* Node type */ - &_synctex_new_math, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_math, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -typedef synctex_node_medium_t synctex_node_kern_t; - -/* kern node creator */ -DEFINE_synctex_new_NODE(kern) - -static void _synctex_display_kern(synctex_node_t node); - -static _synctex_class_t synctex_class_kern = { - NULL, /* No scanner yet */ - synctex_node_type_kern, /* Node type */ - &_synctex_new_kern, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_kern, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* The small nodes correspond to glue and boundary nodes. */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_VERT_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT */ -} synctex_node_small_t; - -static void _synctex_log_small_node(synctex_node_t node); - -/* glue node creator */ -typedef synctex_node_small_t synctex_node_glue_t; -DEFINE_synctex_new_NODE(glue) -static void _synctex_display_glue(synctex_node_t node); - -static _synctex_class_t synctex_class_glue = { - NULL, /* No scanner yet */ - synctex_node_type_glue, /* Node type */ - &_synctex_new_glue, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_glue, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* boundary node creator */ -typedef synctex_node_small_t synctex_node_boundary_t; -DEFINE_synctex_new_NODE(boundary) - -static void _synctex_display_boundary(synctex_node_t node); - -static _synctex_class_t synctex_class_boundary = { - NULL, /* No scanner yet */ - synctex_node_type_boundary, /* Node type */ - &_synctex_new_boundary, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_small_node, /* log */ - &_synctex_display_boundary, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -# define SYNCTEX_NAME_IDX (SYNCTEX_TAG_IDX+1) -# define SYNCTEX_NAME(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NAME_IDX].PTR - -/* Input nodes only know about their sibling, which is another input node. - * The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /* sibling, - * SYNCTEX_TAG,SYNCTEX_NAME */ -} synctex_input_t; - -# define SYNCTEX_INPUT_MARK "Input:" -static synctex_node_t _synctex_new_input(synctex_scanner_t scanner) { - if (scanner) { - synctex_node_t node = _synctex_malloc(sizeof(synctex_input_t)); - if (node) { - SYNCTEX_IMPLEMENT_CHARINDEX(node,strlen(SYNCTEX_INPUT_MARK)); - node->class = scanner->class+synctex_node_type_input; - } - return node; - } - return NULL; -} - -static void _synctex_free_input(synctex_node_t node){ - if (node) { - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - free(SYNCTEX_NAME(node)); - free(node); - } -} - -static void _synctex_display_input(synctex_node_t node); -static void _synctex_log_input(synctex_node_t node); - -static _synctex_class_t synctex_class_input = { - NULL, /* No scanner yet */ - synctex_node_type_input, /* Node type */ - &_synctex_new_input, /* creator */ - &_synctex_free_input, /* destructor */ - &_synctex_log_input, /* log */ - &_synctex_display_input, /* display */ - NULL, /* No parent */ - NULL, /* No child */ - &_synctex_implementation_0, /* sibling */ - NULL, /* No friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_1 -}; - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Navigation -# endif -synctex_node_t synctex_node_parent(synctex_node_t node) -{ - return SYNCTEX_PARENT(node); -} -synctex_node_t synctex_node_sheet(synctex_node_t node) -{ - while(node && node->class->type != synctex_node_type_sheet) { - node = SYNCTEX_PARENT(node); - } - /* exit the while loop either when node is NULL or node is a sheet */ - return node; -} -synctex_node_t synctex_node_child(synctex_node_t node) -{ - return SYNCTEX_CHILD(node); -} -synctex_node_t synctex_node_sibling(synctex_node_t node) -{ - return SYNCTEX_SIBLING(node); -} -synctex_node_t synctex_node_next(synctex_node_t node) { - if (SYNCTEX_CHILD(node)) { - return SYNCTEX_CHILD(node); - } -sibling: - if (SYNCTEX_SIBLING(node)) { - return SYNCTEX_SIBLING(node); - } - if ((node = SYNCTEX_PARENT(node))) { - if (node->class->type == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */ - return NULL; - } - goto sibling; - } - return NULL; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark CLASS -# endif - -/* Public node accessor: the type */ -synctex_node_type_t synctex_node_type(synctex_node_t node) { - if (node) { - return (((node)->class))->type; - } - return synctex_node_type_error; -} - -/* Public node accessor: the human readable type */ -const char * synctex_node_isa(synctex_node_t node) { -static const char * isa[synctex_node_number_of_types] = - {"Not a node","input","sheet","vbox","void vbox","hbox","void hbox","kern","glue","math","boundary"}; - return isa[synctex_node_type(node)]; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark SYNCTEX_LOG -# endif - -# define SYNCTEX_LOG(NODE) SYNCTEX_MSG_SEND(NODE,log) - -/* Public node logger */ -void synctex_node_log(synctex_node_t node) { - SYNCTEX_LOG(node); -} - -static void _synctex_log_input(synctex_node_t node) { - if (node) { - printf("%s:%i,%s",synctex_node_isa(node),SYNCTEX_TAG(node),SYNCTEX_NAME(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_log_sheet(synctex_node_t node) { - if (node) { - printf("%s:%i",synctex_node_isa(node),SYNCTEX_PAGE(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -static void _synctex_log_small_node(synctex_node_t node) { - if (node) { - printf("%s:%i,%i:%i,%i", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_medium_node(synctex_node_t node) { - if (node) { - printf("%s:%i,%i:%i,%i:%i", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_void_box(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i",SYNCTEX_LINE(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_vbox(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i",SYNCTEX_LINE(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -static void _synctex_log_hbox(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i~%i*%i",SYNCTEX_LINE(node),SYNCTEX_MEAN_LINE(node),SYNCTEX_NODE_WEIGHT(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - printf("/%i",SYNCTEX_HORIZ_V(node)); - printf(",%i",SYNCTEX_VERT_V(node)); - printf(":%i",SYNCTEX_WIDTH_V(node)); - printf(",%i",SYNCTEX_HEIGHT_V(node)); - printf(",%i",SYNCTEX_DEPTH_V(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -# define SYNCTEX_DISPLAY(NODE) SYNCTEX_MSG_SEND(NODE,display) - -void synctex_node_display(synctex_node_t node) { - SYNCTEX_DISPLAY(node); -} - -static void _synctex_display_input(synctex_node_t node) { - if (node) { - printf("....Input:%i:%s", - SYNCTEX_TAG(node), - SYNCTEX_NAME(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_sheet(synctex_node_t node) { - if (node) { - printf("....{%i",SYNCTEX_PAGE(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....}\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_vbox(synctex_node_t node) { - if (node) { - printf("....[%i,%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....]\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_hbox(synctex_node_t node) { - if (node) { - printf("....(%i,%i~%i*%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_MEAN_LINE(node), - SYNCTEX_NODE_WEIGHT(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....)\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_void_vbox(synctex_node_t node) { - if (node) { - printf("....v%i,%i;%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_void_hbox(synctex_node_t node) { - if (node) { - printf("....h%i,%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_glue(synctex_node_t node) { - if (node) { - printf("....glue:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_math(synctex_node_t node) { - if (node) { - printf("....math:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_kern(synctex_node_t node) { - if (node) { - printf("....kern:%i,%i:%i,%i:%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_boundary(synctex_node_t node) { - if (node) { - printf("....boundary:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark SCANNER -# endif - -/* Here are gathered all the possible status that the next scanning functions will return. - * All these functions return a status, and pass their result through pointers. - * Negative values correspond to errors. - * The management of the buffer is causing some significant overhead. - * Every function that may access the buffer returns a status related to the buffer and file state. - * status >= SYNCTEX_STATUS_OK means the function worked as expected - * status < SYNCTEX_STATUS_OK means the function did not work as expected - * status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse. - * status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material. - * statusfile) - -/* Actually, the minimum buffer size is driven by integer and float parsing. - * ±0.123456789e123 - */ -# define SYNCTEX_BUFFER_MIN_SIZE 16 -# define SYNCTEX_BUFFER_SIZE 32768 - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Prototypes -# endif -synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr); -synctex_status_t _synctex_next_line(synctex_scanner_t scanner); -synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string); -synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref); -synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref); -synctex_status_t _synctex_scan_input(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref); -synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_postamble(synctex_scanner_t scanner); -synctex_status_t _synctex_setup_visible_box(synctex_node_t box); -synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v); -synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t parent); -synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_content(synctex_scanner_t scanner); -int synctex_scanner_pre_x_offset(synctex_scanner_t scanner); -int synctex_scanner_pre_y_offset(synctex_scanner_t scanner); -const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner); -int _synctex_node_is_box(synctex_node_t node); - -/* Try to ensure that the buffer contains at least size bytes. - * Passing a huge size argument means the whole buffer length. - * Passing a null size argument means return the available buffer length, without reading the file. - * In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL, - * in which case, SYNCTEX_STATUS_BAD_ARGUMENT is returned. - * The value returned in size_ptr is the number of bytes now available in the buffer. - * This is a nonnegative integer, it may take the value 0. - * It is the responsibility of the caller to test whether this size is conforming to its needs. - * Negative values may return in case of error, actually - * when there was an error reading the synctex file. */ -synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr) { - size_t available = 0; - if (NULL == scanner || NULL == size_ptr) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -# define size (* size_ptr) - if (size>SYNCTEX_BUFFER_SIZE){ - size = SYNCTEX_BUFFER_SIZE; - } - available = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */ - if (size<=available) { - /* There are already sufficiently many characters in the buffer */ - size = available; - return SYNCTEX_STATUS_OK; - } - if (SYNCTEX_FILE) { - /* Copy the remaining part of the buffer to the beginning, - * then read the next part of the file */ - int already_read = 0; -# if defined(SYNCTEX_USE_CHARINDEX) - scanner->charindex_offset += SYNCTEX_CUR - SYNCTEX_START; -# endif - if (available) { - memmove(SYNCTEX_START, SYNCTEX_CUR, available); - } - SYNCTEX_CUR = SYNCTEX_START + available; /* the next character after the move, will change. */ - /* Fill the buffer up to its end */ - already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - available)); - if (already_read>0) { - /* We assume that 0already_read) { - /* There is a possible error in reading the file */ - int errnum = 0; - const char * error_string = gzerror(SYNCTEX_FILE, &errnum); - if (Z_ERRNO == errnum) { - /* There is an error in zlib caused by the file system */ - _synctex_error("gzread error from the file system (%i)",errno); - return SYNCTEX_STATUS_ERROR; - } else if (errnum) { - _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string); - return SYNCTEX_STATUS_ERROR; - } - } - /* Nothing was read, we are at the end of the file. */ - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - SYNCTEX_END = SYNCTEX_CUR; - SYNCTEX_CUR = SYNCTEX_START; - * SYNCTEX_END = '\0';/* Terminate the string properly.*/ - size = SYNCTEX_END - SYNCTEX_CUR; - return SYNCTEX_STATUS_EOF; /* there might be a bit of text left */ - } - /* We cannot enlarge the buffer because the end of the file was reached. */ - size = available; - return SYNCTEX_STATUS_EOF; -# undef size -} - -/* Used when parsing the synctex file. - * Advance to the next character starting a line. - * Actually, only '\n' is recognized as end of line marker. - * On normal completion, the returned value is the number of unparsed characters available in the buffer. - * In general, it is a positive value, 0 meaning that the end of file was reached. - * -1 is returned in case of error, actually because there was an error while feeding the buffer. - * When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any. - * J. Laurens: Sat May 10 07:52:31 UTC 2008 - */ -synctex_status_t _synctex_next_line(synctex_scanner_t scanner) { - synctex_status_t status = SYNCTEX_STATUS_OK; - size_t available = 0; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -infinite_loop: - while(SYNCTEX_CUR=remaining_len) { - /* The buffer is sufficiently big to hold the expected number of characters. */ - if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { - return SYNCTEX_STATUS_NOT_OK; - } -return_OK: - /* Advance SYNCTEX_CUR to the next character after the_string. */ - SYNCTEX_CUR += remaining_len; - return SYNCTEX_STATUS_OK; - } else if (strncmp((char *)SYNCTEX_CUR,the_string,available)) { - /* No need to go further, this is not the expected string in the buffer. */ - return SYNCTEX_STATUS_NOT_OK; - } else if (SYNCTEX_FILE) { - /* The buffer was too small to contain remaining_len characters. - * We have to cut the string into pieces. */ - z_off_t offset = 0L; - /* the first part of the string is found, advance the_string to the next untested character. */ - the_string += available; - /* update the remaining length and the parsed length. */ - remaining_len -= available; - tested_len += available; - SYNCTEX_CUR += available; /* We validate the tested characters. */ - if (0 == remaining_len) { - /* Nothing left to test, we have found the given string, we return the length. */ - return tested_len; - } - /* We also have to record the current state of the file cursor because - * if the_string does not match, all this should be a totally blank operation, - * for which the file and buffer states should not be modified at all. - * In fact, the states of the buffer before and after this function are in general different - * but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR - * can be safely discarded. */ - offset = gztell(SYNCTEX_FILE); - /* offset now corresponds to the first character of the file that was not buffered. */ - available = SYNCTEX_CUR - SYNCTEX_START; /* available can be used as temporary placeholder. */ - /* available now corresponds to the number of chars that where already buffered and - * that match the head of the_string. If in fine the_string does not match, all these chars must be recovered - * because the buffer contents is completely replaced by _synctex_buffer_get_available_size. - * They were buffered from offset-len location in the file. */ - offset -= available; -more_characters: - /* There is still some work to be done, so read another bunch of file. - * This is the second call to _synctex_buffer_get_available_size, - * which means that the actual contents of the buffer will be discarded. - * We will definitely have to recover the previous state in case we do not find the expected string. */ - available = remaining_len; - status = _synctex_buffer_get_available_size(scanner,&available); - if (statusptr) { - SYNCTEX_CUR = end; - if (value_ref) { - * value_ref = result; - } - return SYNCTEX_STATUS_OK;/* Successfully scanned an int */ - } - return SYNCTEX_STATUS_NOT_OK;/* Could not scan an int */ -} - -/* The purpose of this function is to read a string. - * A string is an array of characters from the current parser location - * and before the next '\n' character. - * If a string was properly decoded, it is returned in value_ref and - * the cursor points to the new line marker. - * The returned string was alloced on the heap, the caller is the owner and - * is responsible to free it in due time. - * If no string is parsed, * value_ref is undefined. - * The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX. - * If you just want to blindly parse the file up to the end of the current line, - * use _synctex_next_line instead. - * On return, the scanner cursor is unchanged if a string could not be scanned or - * points to the terminating '\n' character otherwise. As a consequence, - * _synctex_next_line is necessary after. - * If either scanner or value_ref is NULL, it is considered as an error and - * SYNCTEX_STATUS_BAD_ARGUMENT is returned. - */ -synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref) { - char * end = NULL; - size_t current_size = 0; - size_t new_size = 0; - size_t len = 0;/* The number of bytes to copy */ - size_t available = 0; - synctex_status_t status = 0; - if (NULL == scanner || NULL == value_ref) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* The buffer must at least contain one character: the '\n' end of line marker */ - if (SYNCTEX_CUR>=SYNCTEX_END) { - available = 1; - status = _synctex_buffer_get_available_size(scanner,&available); - if (status < 0) { - return status; - } - if (0 == available) { - return SYNCTEX_STATUS_EOF; - } - } - /* Now we are sure that there is at least one available character, either because - * SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */ - /* end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */ - end = SYNCTEX_CUR; - * value_ref = NULL;/* Initialize, it will be realloc'ed */ - /* We scan all the characters up to the next '\n' */ -next_character: - if (endUINT_MAX-len-1) { - /* But we have reached the limit: we do not have current_size+len+1>UINT_MAX. - * We return the missing amount of memory. - * This will never occur in practice. */ - return UINT_MAX-len-1 - current_size; - } - new_size = current_size+len; - /* We have current_size+len+1<=UINT_MAX - * or equivalently new_sizeUINT_MAX-len-1) { - /* We have reached the limit. */ - _synctex_error("limit reached (missing %i).",current_size-(UINT_MAX-len-1)); - return SYNCTEX_STATUS_ERROR; - } - new_size = current_size+len; - if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) { - if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) { - (* value_ref)[new_size]='\0'; /* Terminate the string */ - SYNCTEX_CUR = SYNCTEX_END;/* Advance the cursor to the end of the bufer */ - return SYNCTEX_STATUS_OK; - } - free(* value_ref); - * value_ref = NULL; - _synctex_error("could not copy memory (2)."); - return SYNCTEX_STATUS_ERROR; - } - /* Huge memory problem */ - _synctex_error("could not allocate memory (2)."); - return SYNCTEX_STATUS_ERROR; - } -} - -/* Used when parsing the synctex file. - * Read an Input record. - */ -synctex_status_t _synctex_scan_input(synctex_scanner_t scanner) { - synctex_status_t status = 0; - size_t available = 0; - synctex_node_t input = NULL; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - status = _synctex_match_string(scanner,SYNCTEX_INPUT_MARK); - if (statusinput); - scanner->input = input; -# if SYNCTEX_VERBOSE - synctex_node_log(input); -# endif - return _synctex_next_line(scanner);/* read the line termination character, if any */ - /* Now, set up the path */ -} - -typedef synctex_status_t (*synctex_decoder_t)(synctex_scanner_t,void *); - -synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder); - -/* Used when parsing the synctex file. - * Read one of the settings. - * On normal completion, returns SYNCTEX_STATUS_OK. - * On error, returns SYNCTEX_STATUS_ERROR. - * Both arguments must not be NULL. - * On return, the scanner points to the next character after the decoded object whatever it is. - * It is the responsibility of the caller to prepare the scanner for the next line. - */ -synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder) { - synctex_status_t status = 0; - if (NULL == scanner || NULL == name || NULL == value_ref || NULL == decoder) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -not_found: - status = _synctex_match_string(scanner,name); - if (statusversion),(synctex_decoder_t)&_synctex_decode_int); - if (statusoutput_fmt),(synctex_decoder_t)&_synctex_decode_string); - if (statuspre_magnification),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_unit),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_x_offset),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_y_offset),(synctex_decoder_t)&_synctex_decode_int); - if (status= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536; - } else if (status= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536/2.54f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536/25.4f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) { - f *= 65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) { - f *= 72.27f/72*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) { - f *= 12.0*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) { - f *= 1.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) { - f *= 1238.0f/1157*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) { - f *= 14856.0f/1157*65536; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) { - f *= 685.0f/642*65536; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) { - f *= 1370.0f/107*65536; - } else if (status<0) { - goto report_unit_error; - } - *value_ref = f; - return SYNCTEX_STATUS_OK; -} - -/* parse the post scriptum - * SYNCTEX_STATUS_OK is returned on completion - * a negative error is returned otherwise */ -synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner) { - synctex_status_t status = 0; - char * endptr = NULL; -#ifdef HAVE_SETLOCALE - char * loc = setlocale(LC_NUMERIC, NULL); -#endif - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* Scan the file until a post scriptum line is found */ -post_scriptum_not_found: - status = _synctex_match_string(scanner,"Post scriptum:"); - if (statusunit = strtod(SYNCTEX_CUR,&endptr); -#ifdef HAVE_SETLOCALE - setlocale(LC_NUMERIC, loc); -#endif - if (endptr == SYNCTEX_CUR) { - _synctex_error("bad magnification in the post scriptum, a float was expected."); - return SYNCTEX_STATUS_ERROR; - } - if (scanner->unit<=0) { - _synctex_error("bad magnification in the post scriptum, a positive float was expected."); - return SYNCTEX_STATUS_ERROR; - } - SYNCTEX_CUR = endptr; - goto next_line; - } - if (statusx_offset)); - if (statusy_offset)); - if (statuscount),(synctex_decoder_t)&_synctex_decode_int); - if (status < SYNCTEX_STATUS_EOF) { - return status; /* forward the error */ - } else if (status < SYNCTEX_STATUS_OK) { /* No Count record found */ - status = _synctex_next_line(scanner); /* Advance one more line */ - if (statusclass->type) { - case synctex_node_type_hbox: - if (SYNCTEX_INFO(box) != NULL) { - SYNCTEX_HORIZ_V(box) = SYNCTEX_HORIZ(box); - SYNCTEX_VERT_V(box) = SYNCTEX_VERT(box); - SYNCTEX_WIDTH_V(box) = SYNCTEX_WIDTH(box); - SYNCTEX_HEIGHT_V(box) = SYNCTEX_HEIGHT(box); - SYNCTEX_DEPTH_V(box) = SYNCTEX_DEPTH(box); - return SYNCTEX_STATUS_OK; - } - return SYNCTEX_STATUS_ERROR; - } - } - return SYNCTEX_STATUS_BAD_ARGUMENT; -} - -/* This method is sent to an horizontal box to setup the visible size - * Some box have 0 width but do contain text material. - * With this method, one can enlarge the box to contain the given point (h,v). - */ -synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v) { -# ifdef __DARWIN_UNIX03 -# pragma unused(v) -# endif - int itsBtm, itsTop; - if (NULL == node || node->class->type != synctex_node_type_hbox) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - if (SYNCTEX_WIDTH_V(node)<0) { - itsBtm = SYNCTEX_HORIZ_V(node); - itsTop = SYNCTEX_HORIZ_V(node)-SYNCTEX_WIDTH_V(node); - if (hitsTop) { - SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - h; - } - } else { - itsBtm = SYNCTEX_HORIZ_V(node); - itsTop = SYNCTEX_HORIZ_V(node)+SYNCTEX_WIDTH_V(node); - if (hitsTop) { - SYNCTEX_WIDTH_V(node) = h - SYNCTEX_HORIZ_V(node); - } - } - return SYNCTEX_STATUS_OK; -} - -/* Here are the control characters that strat each line of the synctex output file. - * Their values define the meaning of the line. - */ -# define SYNCTEX_CHAR_BEGIN_SHEET '{' -# define SYNCTEX_CHAR_END_SHEET '}' -# define SYNCTEX_CHAR_BEGIN_VBOX '[' -# define SYNCTEX_CHAR_END_VBOX ']' -# define SYNCTEX_CHAR_BEGIN_HBOX '(' -# define SYNCTEX_CHAR_END_HBOX ')' -# define SYNCTEX_CHAR_ANCHOR '!' -# define SYNCTEX_CHAR_VOID_VBOX 'v' -# define SYNCTEX_CHAR_VOID_HBOX 'h' -# define SYNCTEX_CHAR_KERN 'k' -# define SYNCTEX_CHAR_GLUE 'g' -# define SYNCTEX_CHAR_MATH '$' -# define SYNCTEX_CHAR_BOUNDARY 'x' - -# define SYNCTEX_RETURN(STATUS) return STATUS; - -/* Used when parsing the synctex file. A '{' character has just been parsed. - * The purpose is to gobble everything until the closing '}'. - * Actually only one nesting depth has been observed when using the clip option - * of \includegraphics option. Here we use arbitrary level of depth. - */ -synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner) { - unsigned int depth = 0; -deeper: - ++depth; - if (_synctex_next_line(scanner)0) { - goto scan_next_line; - } else { - SYNCTEX_RETURN(SYNCTEX_STATUS_OK); - } - } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) { - ++SYNCTEX_CUR; - goto deeper; - - } else if (_synctex_next_line(scanner)class->type != synctex_node_type_sheet - || _synctex_next_line(scanner)0){ - _synctex_error("Uncomplete sheet(0)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - goto prepare_loop; - } -/* The child loop means that we go down one level, when we just created a box node, - * the next node created is a child of this box. */ -child_loop: - if (SYNCTEX_CURclass->type == synctex_node_type_vbox) { - #define SYNCTEX_UPDATE_BOX_FRIEND(NODE)\ - friend_index = ((SYNCTEX_INFO(NODE))[SYNCTEX_TAG_IDX].INT+(SYNCTEX_INFO(NODE))[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\ - SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\ - (scanner->lists_of_friends)[friend_index] = NODE; - if (NULL == SYNCTEX_CHILD(parent)) { - /* only void boxes are friends */ - SYNCTEX_UPDATE_BOX_FRIEND(parent); - } - child = parent; - parent = SYNCTEX_PARENT(child); - } else { - _synctex_error("Unexpected end of vbox, ignored."); - } - if (_synctex_next_line(scanner)class->type == synctex_node_type_hbox) { - /* Update the mean line number */ - synctex_node_t node = SYNCTEX_CHILD(parent); - if (node) { - unsigned int node_weight = 0; - unsigned int cumulated_line_numbers = 0; - do { - if (synctex_node_type(node)==synctex_node_type_hbox) { - if (SYNCTEX_NODE_WEIGHT(node)) { - node_weight += SYNCTEX_NODE_WEIGHT(node); - cumulated_line_numbers += SYNCTEX_MEAN_LINE(node)*SYNCTEX_NODE_WEIGHT(node); - } else { - ++node_weight; - cumulated_line_numbers += SYNCTEX_MEAN_LINE(node); - } - } else { - ++node_weight; - cumulated_line_numbers += SYNCTEX_LINE(node); - } - } while ((node = SYNCTEX_SIBLING(node))); - SYNCTEX_MEAN_LINE(parent)=(cumulated_line_numbers + node_weight/2)/node_weight; - SYNCTEX_NODE_WEIGHT(parent)=node_weight; - } else { - SYNCTEX_MEAN_LINE(parent)=SYNCTEX_LINE(parent); - SYNCTEX_NODE_WEIGHT(parent)=1; - } - if (NULL == child) { - /* Only boxes with no children are friends, - * boxes with children are indirectly friends through one of their contained nodes. */ - SYNCTEX_UPDATE_BOX_FRIEND(parent); - } - /* setting the next horizontal box at the end ensures that a child is recorded before any of its ancestors. */ - SYNCTEX_SET_NEXT_hbox(box,parent); - box = parent; - child = parent; - parent = SYNCTEX_PARENT(child); - } else { - _synctex_error("Unexpected end of hbox, ignored."); - } - if (_synctex_next_line(scanner)number_of_lists);\ - SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\ - (scanner->lists_of_friends)[friend_index] = NODE; - SYNCTEX_UPDATE_FRIEND(child); -# if SYNCTEX_VERBOSE - synctex_node_log(child); -# endif - goto sibling_loop; - } else { - _synctex_error("Can't create vbox record."); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) { - if (NULL != (child = _synctex_new_void_hbox(scanner)) - && NULL != (info = SYNCTEX_INFO(child))) { - if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX) - || _synctex_next_line(scanner)0){ - _synctex_error("Uncomplete sheet(0)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } else { - goto child_loop; - } - } -/* The vertical loop means that we are on the same level, for example when we just ended a box. - * If a node is created now, it will be a sibling of the current node, sharing the same parent. */ -sibling_loop: - if (SYNCTEX_CUR0){ - goto sibling_loop; - } else { - _synctex_error("Uncomplete sheet(2)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - } -# undef SYNCTEX_DECODE_FAILED -} - -# define SYNCTEX_APPEND_SHEET(SCANNER,SHEET) if (SCANNER->sheet) {\ - synctex_node_t last_sheet = SCANNER->sheet;\ - synctex_node_t next_sheet = NULL;\ - while ((next_sheet = SYNCTEX_SIBLING(last_sheet))) {\ - last_sheet = next_sheet;\ - }\ - SYNCTEX_SET_SIBLING(last_sheet,SHEET);\ - } else {\ - SCANNER->sheet = SHEET;\ - } - -/* Used when parsing the synctex file - */ -synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) { - synctex_node_t sheet = NULL; - synctex_status_t status = 0; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* set up the lists of friends */ - if (NULL == scanner->lists_of_friends) { - scanner->number_of_lists = 1024; - scanner->lists_of_friends = (synctex_node_t *)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_t)); - if (NULL == scanner->lists_of_friends) { - _synctex_error("malloc:2"); - return SYNCTEX_STATUS_ERROR; - } - } - /* Find where this section starts */ -content_not_found: - status = _synctex_match_string(scanner,"Content:"); - if (status= SYNCTEX_STATUS_OK); - goto next_sheet; -} - -int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_modeRef); - -/* Where the synctex scanner is created. */ -synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) { - gzFile file = NULL; - char * synctex = NULL; - synctex_scanner_t scanner = NULL; - synctex_io_mode_t io_mode = 0; - /* Here we assume that int are smaller than void * */ - if (sizeof(int)>sizeof(void*)) { - _synctex_error("INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out."); - return NULL; - } - /* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */ - if (SYNCTEX_BUFFER_SIZE >= UINT_MAX) { - _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)"); - return NULL; - } - /* for integers: */ - if (SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) { - _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)"); - return NULL; - } - /* now open the synctex file */ - if (_synctex_open(output,build_directory,&synctex,&file,synctex_ADD_QUOTES,&io_mode) || !file) { - if (_synctex_open(output,build_directory,&synctex,&file,synctex_DONT_ADD_QUOTES,&io_mode) || !file) { - return NULL; - } - } - scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t)); - if (NULL == scanner) { - _synctex_error("malloc problem"); - free(synctex); - gzclose(file); - return NULL; - } - /* make a private copy of output for the scanner */ - if (NULL == (scanner->output = (char *)malloc(strlen(output)+1))){ - _synctex_error("! synctex_scanner_new_with_output_file: Memory problem (2), scanner's output is not reliable."); - } else if (scanner->output != strcpy(scanner->output,output)) { - _synctex_error("! synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable."); - } - scanner->synctex = synctex;/* Now the scanner owns synctex */ - SYNCTEX_FILE = file; - return parse? synctex_scanner_parse(scanner):scanner; -} - -/* This functions opens the file at the "output" given location. - * It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character. - * In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes. - * This function will remove them if possible. - * All the reference arguments will take a value on return. They must be non NULL. - * 0 on success, non 0 on error. */ -static int __synctex_open(const char * output, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) { - if (synctex_name_ref && file_ref && io_mode_ref) { - /* 1 local variables that uses dynamic memory */ - char * synctex_name = NULL; - gzFile the_file = NULL; - char * quoteless_synctex_name = NULL; - size_t size = 0; - synctex_io_mode_t io_mode = *io_mode_ref; - const char * mode = _synctex_get_io_mode_name(io_mode); - /* now create the synctex file name */ - size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1; - synctex_name = (char *)malloc(size); - if (NULL == synctex_name) { - _synctex_error("! __synctex_open: Memory problem (1)\n"); - return 1; - } - /* we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices, - * including the terminating character. size is free now. */ - if (synctex_name != strcpy(synctex_name,output)) { - _synctex_error("! __synctex_open: Copy problem\n"); -return_on_error: - free(synctex_name); - free(quoteless_synctex_name); - return 2; - } - /* remove the last path extension if any */ - _synctex_strip_last_path_extension(synctex_name); - if (!strlen(synctex_name)) { - goto return_on_error; - } - /* now insert quotes. */ - if (add_quotes) { - char * quoted = NULL; - if (_synctex_copy_with_quoting_last_path_component(synctex_name,"ed,size) || (NULL == quoted)) { - /* There was an error or quoting does not make sense: */ - goto return_on_error; - } - quoteless_synctex_name = synctex_name; - synctex_name = quoted; - } - /* Now add to synctex_name the first path extension. */ - if (synctex_name != strcat(synctex_name,synctex_suffix)){ - _synctex_error("! __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix); - goto return_on_error; - } - /* Add to quoteless_synctex_name as well, if relevant. */ - if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){ - free(quoteless_synctex_name); - quoteless_synctex_name = NULL; - } - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("could not open %s, error %i\n",synctex_name,errno); - goto return_on_error; - } - /* Apparently, there is no uncompressed synctex file. Try the compressed version */ - if (synctex_name != strcat(synctex_name,synctex_suffix_gz)){ - _synctex_error("! __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz); - goto return_on_error; - } - io_mode |= synctex_io_gz_mask; - mode = _synctex_get_io_mode_name(io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */ - /* Add the suffix to the quoteless_synctex_name as well. */ - if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){ - free(quoteless_synctex_name); - quoteless_synctex_name = NULL; - } - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("Could not open %s, error %i\n",synctex_name,errno); - } - goto return_on_error; - } - } - /* At this point, the file is properly open. - * If we are in the add_quotes mode, we change the file name by removing the quotes. */ - if (quoteless_synctex_name) { - gzclose(the_file); - if (rename(synctex_name,quoteless_synctex_name)) { - _synctex_error("Could not rename %s to %s, error %i\n",synctex_name,quoteless_synctex_name,errno); - /* We could not rename, reopen the file with the quoted name. */ - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* No luck, could not re open this file, something has happened meanwhile */ - if (errno != ENOENT) { - /* The file does not exist any more, it has certainly be removed somehow - * this is a lower level error, I can't do anything. */ - _synctex_error("Could not open again %s, error %i\n",synctex_name,errno); - } - goto return_on_error; - } - } else { - /* The file has been successfully renamed */ - if (NULL == (the_file = gzopen(quoteless_synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno); - } - goto return_on_error; - } - /* The quote free file name should replace the old one:*/ - free(synctex_name); - synctex_name = quoteless_synctex_name; - quoteless_synctex_name = NULL; - } - } - /* The operation is successfull, return the arguments by value. */ - * file_ref = the_file; - * io_mode_ref = io_mode; - * synctex_name_ref = synctex_name; - return 0; - } - return 3; /* Bad parameter. */ -} - -/* Opens the ouput file, taking into account the eventual build_directory. - * 0 on success, non 0 on error. */ -int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) { -# define synctex_name (*synctex_name_ref) -# define the_file (*file_ref) - int result = __synctex_open(output,synctex_name_ref,file_ref,add_quotes,io_mode_ref); - if ((result || !*file_ref) && build_directory && strlen(build_directory)) { - char * build_output; - const char *lpc; - size_t size; - synctex_bool_t is_absolute; - build_output = NULL; - lpc = _synctex_last_path_component(output); - size = strlen(build_directory)+strlen(lpc)+2; /* One for the '/' and one for the '\0'. */ - is_absolute = _synctex_path_is_absolute(build_directory); - if (!is_absolute) { - size += strlen(output); - } - if ((build_output = (char *)malloc(size))) { - if (is_absolute) { - build_output[0] = '\0'; - } else { - if (build_output != strcpy(build_output,output)) { - free(build_output); - return -4; - } - build_output[lpc-output]='\0'; - } - if (build_output == strcat(build_output,build_directory)) { - /* Append a path separator if necessary. */ - if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) { - if (build_output != strcat(build_output,"/")) { - free(build_output); - return -2; - } - } - /* Append the last path component of the output. */ - if (build_output != strcat(build_output,lpc)) { - free(build_output); - return -3; - } - result = __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_mode_ref); - free(build_output); - return result; - } - free(build_output); - } - return -1; - } - return result; -# undef synctex_name -# undef the_file -} - -/* The scanner destructor - */ -void synctex_scanner_free(synctex_scanner_t scanner) { - if (NULL == scanner) { - return; - } - if (SYNCTEX_FILE) { - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - } - SYNCTEX_FREE(scanner->sheet); - SYNCTEX_FREE(scanner->input); - free(SYNCTEX_START); - free(scanner->output_fmt); - free(scanner->output); - free(scanner->synctex); - free(scanner->lists_of_friends); - free(scanner); -} - -/* Where the synctex scanner parses the contents of the file. */ -synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner) { - synctex_status_t status = 0; - if (!scanner || scanner->flags.has_parsed) { - return scanner; - } - scanner->flags.has_parsed=1; - scanner->pre_magnification = 1000; - scanner->pre_unit = 8192; - scanner->pre_x_offset = scanner->pre_y_offset = 578; - /* initialize the offset with a fake unprobable value, - * If there is a post scriptum section, this value will be overriden by the real life value */ - scanner->x_offset = scanner->y_offset = 6.027e23f; -# define DEFINE_synctex_scanner_class(NAME)\ - scanner->class[synctex_node_type_##NAME] = synctex_class_##NAME;\ - (scanner->class[synctex_node_type_##NAME]).scanner = scanner - DEFINE_synctex_scanner_class(sheet); - DEFINE_synctex_scanner_class(input); - DEFINE_synctex_scanner_class(hbox); - DEFINE_synctex_scanner_class(void_hbox); - DEFINE_synctex_scanner_class(vbox); - DEFINE_synctex_scanner_class(void_vbox); - DEFINE_synctex_scanner_class(kern); - DEFINE_synctex_scanner_class(glue); - DEFINE_synctex_scanner_class(math); - DEFINE_synctex_scanner_class(boundary); - SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */ - if (NULL == SYNCTEX_START) { - _synctex_error("malloc error"); - synctex_scanner_free(scanner); - return NULL; - } - SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE; - /* SYNCTEX_END always points to a null terminating character. - * Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1. - * At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */ - *SYNCTEX_END = '\0'; - SYNCTEX_CUR = SYNCTEX_END; -# if defined(SYNCTEX_USE_CHARINDEX) - scanner->charindex_offset = -SYNCTEX_BUFFER_SIZE; -# endif - status = _synctex_scan_preamble(scanner); - if (statuspre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp - * 1 pt = 65536 sp */ - if (scanner->pre_unit<=0) { - scanner->pre_unit = 8192; - } - if (scanner->pre_magnification<=0) { - scanner->pre_magnification = 1000; - } - if (scanner->unit <= 0) { - /* no post magnification */ - scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/ - } else { - /* post magnification */ - scanner->unit *= scanner->pre_unit / 65781.76; - } - scanner->unit *= scanner->pre_magnification / 1000.0; - if (scanner->x_offset > 6e23) { - /* no post offset */ - scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76); - scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76); - } else { - /* post offset */ - scanner->x_offset /= 65781.76f; - scanner->y_offset /= 65781.76f; - } - return scanner; - #undef SYNCTEX_FILE -} - -/* Scanner accessors. - */ -int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){ - return scanner?scanner->pre_x_offset:0; -} -int synctex_scanner_pre_y_offset(synctex_scanner_t scanner){ - return scanner?scanner->pre_y_offset:0; -} -int synctex_scanner_x_offset(synctex_scanner_t scanner){ - return scanner?scanner->x_offset:0; -} -int synctex_scanner_y_offset(synctex_scanner_t scanner){ - return scanner?scanner->y_offset:0; -} -float synctex_scanner_magnification(synctex_scanner_t scanner){ - return scanner?scanner->unit:1; -} -void synctex_scanner_display(synctex_scanner_t scanner) { - if (NULL == scanner) { - return; - } - printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->output,scanner->output_fmt,scanner->version); - printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset); - printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", - scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset); - printf("The input:\n"); - SYNCTEX_DISPLAY(scanner->input); - if (scanner->count<1000) { - printf("The sheets:\n"); - SYNCTEX_DISPLAY(scanner->sheet); - printf("The friends:\n"); - if (scanner->lists_of_friends) { - int i = scanner->number_of_lists; - synctex_node_t node; - while(i--) { - printf("Friend index:%i\n",i); - node = (scanner->lists_of_friends)[i]; - while(node) { - printf("%s:%i,%i\n", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node) - ); - node = SYNCTEX_FRIEND(node); - } - } - } - } else { - printf("SyncTeX Warning: Too many objects\n"); - } -} -/* Public*/ -const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) { - synctex_node_t input = NULL; - if (NULL == scanner) { - return NULL; - } - input = scanner->input; - do { - if (tag == SYNCTEX_TAG(input)) { - return (SYNCTEX_NAME(input)); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - return NULL; -} - -int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name); -int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) { - synctex_node_t input = NULL; - if (NULL == scanner) { - return 0; - } - input = scanner->input; - do { - if (_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) { - return SYNCTEX_TAG(input); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - // 2011 version - name = _synctex_base_name(name); - input = scanner->input; - do { - if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(input)))) { - synctex_node_t other_input = input; - while((other_input = SYNCTEX_SIBLING(other_input)) != NULL) { - if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(other_input))) - && (strlen(SYNCTEX_NAME(input))!=strlen(SYNCTEX_NAME(other_input)) - || strncmp(SYNCTEX_NAME(other_input),SYNCTEX_NAME(input),strlen(SYNCTEX_NAME(input))))) { - // There is a second possible candidate - return 0; - } - } - return SYNCTEX_TAG(input); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - return 0; -} - -int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) { - size_t char_index = strlen(name); - if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) { - /* the name is not void */ - char_index -= 1; - if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) { - /* the last character of name is not a path separator */ - int result = _synctex_scanner_get_tag(scanner,name); - if (result) { - return result; - } else { - /* the given name was not the one known by TeX - * try a name relative to the enclosing directory of the scanner->output file */ - const char * relative = name; - const char * ptr = scanner->output; - while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) - { - relative += 1; - ptr += 1; - } - /* Find the last path separator before relative */ - while(relative > name) { - if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) { - break; - } - relative -= 1; - } - if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) { - return result; - } - if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) { - /* No tag found for the given absolute name, - * Try each relative path starting from the shortest one */ - while(0input:NULL; -} -const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner) { - return NULL != scanner && scanner->output_fmt?scanner->output_fmt:""; -} -const char * synctex_scanner_get_output(synctex_scanner_t scanner) { - return NULL != scanner && scanner->output?scanner->output:""; -} -const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) { - return NULL != scanner && scanner->synctex?scanner->synctex:""; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Public node attributes -# endif -int synctex_node_h(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_HORIZ(node); -} -int synctex_node_v(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_VERT(node); -} -int synctex_node_width(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_WIDTH(node); -} -int synctex_node_box_h(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_HORIZ(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_v(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_VERT(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_width(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_WIDTH(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_height(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_HEIGHT(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_depth(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_DEPTH(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Public node visible attributes -# endif -float synctex_node_visible_h(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset; -} -float synctex_node_visible_v(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset; -} -float synctex_node_visible_width(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_WIDTH(node)*node->class->scanner->unit; -} -float synctex_node_box_visible_h(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset; - case synctex_node_type_hbox: -result: - return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_v(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset; - case synctex_node_type_hbox: -result: - return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->y_offset; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_width(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_WIDTH(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_height(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_HEIGHT(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_depth(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_DEPTH(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Other public node attributes -# endif - -int synctex_node_page(synctex_node_t node){ - synctex_node_t parent = NULL; - if (!node) { - return -1; - } - parent = SYNCTEX_PARENT(node); - while(parent) { - node = parent; - parent = SYNCTEX_PARENT(node); - } - if (node->class->type == synctex_node_type_sheet) { - return SYNCTEX_PAGE(node); - } - return -1; -} -synctex_charindex_t synctex_node_charindex(synctex_node_t node) { - return node?SYNCTEX_CHARINDEX(node):0; -} -int synctex_node_tag(synctex_node_t node) { - return node?SYNCTEX_TAG(node):-1; -} -int synctex_node_line(synctex_node_t node) { - return node?SYNCTEX_LINE(node):-1; -} -int synctex_node_mean_line(synctex_node_t node) { - return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_MEAN_LINE(node):SYNCTEX_LINE(node)):-1; -} -int synctex_node_child_count(synctex_node_t node) { - return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_NODE_WEIGHT(node):0):-1; -} -int synctex_node_column(synctex_node_t node) { -# ifdef __DARWIN_UNIX03 -# pragma unused(node) -# endif - return -1; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Sheet -# endif - -synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page) { - if (scanner) { - synctex_node_t sheet = scanner->sheet; - while(sheet) { - if (page == SYNCTEX_PAGE(sheet)) { - return sheet; - } - sheet = SYNCTEX_SIBLING(sheet); - } - } - return NULL; -} - -synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) { - if (scanner) { - return SYNCTEX_CHILD(synctex_sheet(scanner,page)); - } - return NULL; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Query -# endif - -synctex_status_t synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column) { -# ifdef __DARWIN_UNIX03 -# pragma unused(column) -# endif - int tag = synctex_scanner_get_tag(scanner,name); - size_t size = 0; - int friend_index = 0; - int max_line = 0; - synctex_node_t node = NULL; - if (tag == 0) { - printf("SyncTeX Warning: No tag for %s\n",name); - return -1; - } - free(SYNCTEX_START); - SYNCTEX_CUR = SYNCTEX_END = SYNCTEX_START = NULL; - max_line = line < INT_MAX-scanner->number_of_lists ? line+scanner->number_of_lists:INT_MAX; - while(linenumber_of_lists); - if ((node = (scanner->lists_of_friends)[friend_index])) { - do { - if ((synctex_node_type(node)>=synctex_node_type_boundary) - && (tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while ((node = SYNCTEX_FRIEND(node))); - if (SYNCTEX_START == NULL) { - /* We did not find any matching boundary, retry with glue or kern */ - node = (scanner->lists_of_friends)[friend_index];/* no need to test it again, already done */ - do { - if ((synctex_node_type(node)>=synctex_node_type_kern) - && (tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while ((node = SYNCTEX_FRIEND(node))); - if (SYNCTEX_START == NULL) { - /* We did not find any matching glue or kern, retry with boxes */ - node = (scanner->lists_of_friends)[friend_index];/* no need to test it again, already done */ - do { - if ((tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while((node = SYNCTEX_FRIEND(node))); - } - } - SYNCTEX_END = SYNCTEX_CUR; - /* Now reverse the order to have nodes in display order, and then keep just a few nodes. - * Order first the best node. */ - if ((SYNCTEX_START) && (SYNCTEX_END)) { - unsigned int best_match = -1; - unsigned int next_match = -1; - unsigned int best_weight = 0; - synctex_node_t * best_ref = NULL; - synctex_node_t * start_ref = (synctex_node_t *)SYNCTEX_START; - synctex_node_t * end_ref = (synctex_node_t *)SYNCTEX_END; - --end_ref; - while (start_ref < end_ref) { - node = *start_ref; - *start_ref = *end_ref; - *end_ref = node; - ++start_ref; - --end_ref; - } - /* Now reorder the nodes to put first the one which fits best. - * The idea is to walk along the list of nodes and pick up the first one - * which line info is exactly the mean line of its parent, or at least very close. - * Then we choose among all such node the one with the maximum number of child nodes. - * Then we switch with the first node. - */ - best_ref = start_ref = (synctex_node_t *)SYNCTEX_START; - node = *start_ref; - best_match = abs(SYNCTEX_LINE(node)-SYNCTEX_MEAN_LINE(SYNCTEX_PARENT(node))); - end_ref = (synctex_node_t *)SYNCTEX_END; - while (++start_refbest_weight)) { - best_match = next_match; - best_ref = start_ref; - best_weight = SYNCTEX_NODE_WEIGHT(parent); - } - } - node = *best_ref; - *best_ref = *(synctex_node_t *)SYNCTEX_START; - *(synctex_node_t *)SYNCTEX_START = node; - /* Basically, we keep the first node for each parent. - * More precisely, we keep only nodes that are not children of - * their predecessor's parent. */ - start_ref = (synctex_node_t *)SYNCTEX_START; - end_ref = (synctex_node_t *)SYNCTEX_START; -next_end: - end_ref += 1; /* we allways have start_ref<= end_ref*/ - if (end_ref < (synctex_node_t *)SYNCTEX_END) { - node = *end_ref; - while ((node = SYNCTEX_PARENT(node))) { - if (SYNCTEX_PARENT(*start_ref) == node) { - goto next_end; - } - } - start_ref += 1; - *start_ref = *end_ref; - goto next_end; - } - start_ref += 1; - SYNCTEX_END = (char *)start_ref; - SYNCTEX_CUR = NULL;// added on behalf of Jose Alliste - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);// added on behalf Jan Sundermeyer - } - SYNCTEX_CUR = NULL; - // return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer - } -# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__) - break; -# else - ++line; -# endif - } - return 0; -} - -synctex_node_t synctex_next_result(synctex_scanner_t scanner) { - if (NULL == SYNCTEX_CUR) { - SYNCTEX_CUR = SYNCTEX_START; - } else { - SYNCTEX_CUR+=sizeof(synctex_node_t); - } - if (SYNCTEX_CUR= scanner->unit) {/* scanner->unit must be >0 */ - return 0; - } - /* Convert the given point to scanner integer coordinates */ - hitPoint.h = (h-scanner->x_offset)/scanner->unit; - hitPoint.v = (v-scanner->y_offset)/scanner->unit; - /* We will store in the scanner's buffer the result of the query. */ - free(SYNCTEX_START); - SYNCTEX_START = SYNCTEX_END = SYNCTEX_CUR = NULL; - /* Find the proper sheet */ - sheet = scanner->sheet; - while((sheet) && SYNCTEX_PAGE(sheet) != page) { - sheet = SYNCTEX_SIBLING(sheet); - } - if (NULL == sheet) { - return -1; - } - /* Now sheet points to the sheet node with proper page number */ - /* Here is how we work: - * At first we do not consider the visible box dimensions. This will cover the most frequent cases. - * Then we try with the visible box dimensions. - * We try to find a non void box containing the hit point. - * We browse all the horizontal boxes until we find one containing the hit point. */ - if ((node = SYNCTEX_NEXT_hbox(sheet))) { - do { - if (_synctex_point_in_box(hitPoint,node,synctex_YES)) { - /* Maybe the hitPoint belongs to a contained vertical box. */ -end: - /* This trick is for catching overlapping boxes */ - if ((other_node = SYNCTEX_NEXT_hbox(node))) { - do { - if (_synctex_point_in_box(hitPoint,other_node,synctex_YES)) { - node = _synctex_smallest_container(other_node,node); - } - } while((other_node = SYNCTEX_NEXT_hbox(other_node))); - } - /* node is the smallest horizontal box that contains hitPoint. */ - if ((bestContainer = _synctex_eq_deepest_container(hitPoint,node,synctex_YES))) { - node = bestContainer; - } - _synctex_eq_get_closest_children_in_box(hitPoint,node,&bestNodes,&bestDistances,synctex_YES); - if (bestNodes.right && bestNodes.left) { - if ((SYNCTEX_TAG(bestNodes.right)!=SYNCTEX_TAG(bestNodes.left)) - || (SYNCTEX_LINE(bestNodes.right)!=SYNCTEX_LINE(bestNodes.left)) - || (SYNCTEX_COLUMN(bestNodes.right)!=SYNCTEX_COLUMN(bestNodes.left))) { - if ((SYNCTEX_START = malloc(2*sizeof(synctex_node_t)))) { - if (bestDistances.left>bestDistances.right) { - ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.right; - ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.left; - } else { - ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.left; - ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.right; - } - SYNCTEX_END = SYNCTEX_START + 2*sizeof(synctex_node_t); - SYNCTEX_CUR = NULL; - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); - } - return SYNCTEX_STATUS_ERROR; - } - /* both nodes have the same input coordinates - * We choose the one closest to the hit point */ - if (bestDistances.left>bestDistances.right) { - bestNodes.left = bestNodes.right; - } - bestNodes.right = NULL; - } else if (bestNodes.right) { - bestNodes.left = bestNodes.right; - } else if (!bestNodes.left){ - bestNodes.left = node; - } - if ((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) { - * (synctex_node_t *)SYNCTEX_START = bestNodes.left; - SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t); - SYNCTEX_CUR = NULL; - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); - } - return SYNCTEX_STATUS_ERROR; - } - } while ((node = SYNCTEX_NEXT_hbox(node))); - /* All the horizontal boxes have been tested, - * None of them contains the hit point. - */ - } - /* We are not lucky */ - if ((node = SYNCTEX_CHILD(sheet))) { - goto end; - } - return 0; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Utilities -# endif - -/* Rougly speaking, this is: - * node's h coordinate - hitPoint's h coordinate. - * If node is to the right of the hit point, then this distance is positive, - * if node is to the left of the hit point, this distance is negative.*/ -int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible); -int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { - if (node) { - int min,med,max; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - */ - case synctex_node_type_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = visible?SYNCTEX_HORIZ_V(node):SYNCTEX_HORIZ(node); - max = min + (visible?SYNCTEX_ABS_WIDTH_V(node):SYNCTEX_ABS_WIDTH(node)); - /* We allways have min <= max */ - if (hitPoint.h 0 */ - } else if (hitPoint.h>max) { - return max - hitPoint.h; /* regions 3+6+9, result is < 0 */ - } else { - return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ - } - break; - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative width, height and depth. - * For these boxes, no visible dimension available */ - min = SYNCTEX_HORIZ(node); - max = min + SYNCTEX_ABS_WIDTH(node); - /* We allways have min <= max */ - if (hitPoint.h 0 */ - } else if (hitPoint.h>max) { - return max - hitPoint.h; /* regions 3+6+9, result is < 0 */ - } else { - return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ - } - break; - case synctex_node_type_kern: - /* IMPORTANT NOTICE: the location of the kern is recorded AFTER the move. - * The distance to the kern is very special, - * in general, there is no text material in the kern, - * this is why we compute the offset relative to the closest edge of the kern.*/ - max = SYNCTEX_WIDTH(node); - if (max<0) { - min = SYNCTEX_HORIZ(node); - max = min - max; - } else { - min = -max; - max = SYNCTEX_HORIZ(node); - min += max; - } - med = (min+max)/2; - /* positive kern: '.' means text, '>' means kern offset - * ............. - * min>>>>med>>>>max - * ............... - * negative kern: '.' means text, '<' means kern offset - * ............................ - * min<<<max) { - return max - hitPoint.h - 1; /* same kind of penalty */ - } else if (hitPoint.h>med) { - /* do things like if the node had 0 width and was placed at the max edge + 1*/ - return max - hitPoint.h + 1; /* positive, the kern is to the right of the hitPoint */ - } else { - return min - hitPoint.h - 1; /* negative, the kern is to the left of the hitPoint */ - } - case synctex_node_type_glue: - case synctex_node_type_math: - return SYNCTEX_HORIZ(node) - hitPoint.h; - } - } - return INT_MAX;/* We always assume that the node is faraway to the right*/ -} -/* Rougly speaking, this is: - * node's v coordinate - hitPoint's v coordinate. - * If node is at the top of the hit point, then this distance is positive, - * if node is at the bottom of the hit point, this distance is negative.*/ -int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible); -int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible) { -# ifdef __DARWIN_UNIX03 -# pragma unused(visible) -# endif - if (node) { - int min,max; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - */ - case synctex_node_type_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = SYNCTEX_VERT_V(node); - max = min + SYNCTEX_ABS_DEPTH_V(node); - min -= SYNCTEX_ABS_HEIGHT_V(node); - /* We allways have min <= max */ - if (hitPoint.v 0 */ - } else if (hitPoint.v>max) { - return max - hitPoint.v; /* regions 7+8+9, result is < 0 */ - } else { - return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ - } - break; - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = SYNCTEX_VERT(node); - max = min + SYNCTEX_ABS_DEPTH(node); - min -= SYNCTEX_ABS_HEIGHT(node); - /* We allways have min <= max */ - if (hitPoint.v 0 */ - } else if (hitPoint.v>max) { - return max - hitPoint.v; /* regions 7+8+9, result is < 0 */ - } else { - return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ - } - break; - case synctex_node_type_kern: - case synctex_node_type_glue: - case synctex_node_type_math: - return SYNCTEX_VERT(node) - hitPoint.v; - } - } - return INT_MAX;/* We always assume that the node is faraway to the top*/ -} - -SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node) { - float height, other_height; - if (SYNCTEX_ABS_WIDTH(node)SYNCTEX_ABS_WIDTH(other_node)) { - return other_node; - } - height = SYNCTEX_ABS_DEPTH(node) + SYNCTEX_ABS_HEIGHT(node); - other_height = SYNCTEX_ABS_DEPTH(other_node) + SYNCTEX_ABS_HEIGHT(other_node); - if (heightother_height) { - return other_node; - } - return node; -} - -synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { - if (node) { - if (0 == _synctex_point_h_distance(hitPoint,node,visible) - && 0 == _synctex_point_v_distance(hitPoint,node,visible)) { - return synctex_YES; - } - } - return synctex_NO; -} - -int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { -# ifdef __DARWIN_UNIX03 -# pragma unused(visible) -# endif - int result = INT_MAX; /* when the distance is meaning less (sheet, input...) */ - if (node) { - int minH,maxH,minV,maxV; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - * In each region, there is a different formula. - * In the end we have a continuous distance which may not be a mathematical distance but who cares. */ - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_hbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative widths. */ - minH = SYNCTEX_HORIZ(node); - maxH = minH + SYNCTEX_ABS_WIDTH(node); - minV = SYNCTEX_VERT(node); - maxV = minV + SYNCTEX_ABS_DEPTH(node); - minV -= SYNCTEX_ABS_HEIGHT(node); - /* In what region is the point hitPoint=(H,V) ? */ - if (hitPoint.vminV) { - result = hitPoint.v - minV + minH - hitPoint.h; - } else { - result = minV - hitPoint.v + minH - hitPoint.h; - } - } else if (hitPoint.h>maxH) { - if (hitPoint.v>minV) { - result = hitPoint.v - minV + hitPoint.h - maxH; - } else { - result = minV - hitPoint.v + hitPoint.h - maxH; - } - } else if (hitPoint.v>minV) { - result = hitPoint.v - minV; - } else { - result = minV - hitPoint.v; - } - break; - case synctex_node_type_glue: - case synctex_node_type_math: - minH = SYNCTEX_HORIZ(node); - minV = SYNCTEX_VERT(node); - if (hitPoint.hminV) { - result = hitPoint.v - minV + minH - hitPoint.h; - } else { - result = minV - hitPoint.v + minH - hitPoint.h; - } - } else if (hitPoint.v>minV) { - result = hitPoint.v - minV + hitPoint.h - minH; - } else { - result = minV - hitPoint.v + hitPoint.h - minH; - } - break; - } - } - return result; -} - -static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) { - if (node) { - synctex_node_t result = NULL; - synctex_node_t child = NULL; - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - /* test the deep nodes first */ - if ((child = SYNCTEX_CHILD(node))) { - do { - if ((result = _synctex_eq_deepest_container(hitPoint,child,visible))) { - return result; - } - } while((child = SYNCTEX_SIBLING(child))); - } - /* is the hit point inside the box? */ - if (_synctex_point_in_box(hitPoint,node,visible)) { - /* for vboxes we try to use some node inside. - * Walk through the list of siblings until we find the closest one. - * Only consider siblings with children. */ - if ((node->class->type == synctex_node_type_vbox) && (child = SYNCTEX_CHILD(node))) { - int bestDistance = INT_MAX; - do { - if (SYNCTEX_CHILD(child)) { - int distance = _synctex_node_distance_to_point(hitPoint,child,visible); - if (distance < bestDistance) { - bestDistance = distance; - node = child; - } - } - } while((child = SYNCTEX_SIBLING(child))); - } - return node; - } - } - } - return NULL; -} - -/* Compares the locations of the hitPoint with the locations of the various nodes contained in the box. - * As it is an horizontal box, we only compare horizontal coordinates. */ -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef, synctex_bool_t visible); -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef, synctex_bool_t visible) { - int result = 0; - if ((node = SYNCTEX_CHILD(node))) { - do { - int off7 = _synctex_point_h_distance(hitPoint,node,visible); - if (off7 > 0) { - /* node is to the right of the hit point. - * We compare node and the previously recorded one, through the recorded distance. - * If the nodes have the same tag, prefer the one with the smallest line number, - * if the nodes also have the same line number, prefer the one with the smallest column. */ - if (bestDistancesRef->right > off7) { - bestDistancesRef->right = off7; - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } else if (bestDistancesRef->right == off7 && bestNodesRef->right) { - if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } - } - } else if (off7 == 0) { - /* hitPoint is inside node. */ - bestDistancesRef->left = bestDistancesRef->right = 0; - bestNodesRef->left = node; - bestNodesRef->right = NULL; - result |= SYNCTEX_MASK_LEFT; - } else { /* here off7 < 0, hitPoint is to the right of node */ - off7 = -off7; - if (bestDistancesRef->left > off7) { - bestDistancesRef->left = off7; - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } else if (bestDistancesRef->left == off7 && bestNodesRef->left) { - if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } - } - } - } while((node = SYNCTEX_SIBLING(node))); - if (result & SYNCTEX_MASK_LEFT) { - /* the left node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - } - if (result & SYNCTEX_MASK_RIGHT) { - /* the right node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - } - } - return result; -} -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible); -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible) { - int result = 0; - if ((node = SYNCTEX_CHILD(node))) { - do { - int off7 = _synctex_point_v_distance(hitPoint,node,visible);/* this is what makes the difference with the h version above */ - if (off7 > 0) { - /* node is to the top of the hit point (below because TeX is oriented from top to bottom. - * We compare node and the previously recorded one, through the recorded distance. - * If the nodes have the same tag, prefer the one with the smallest line number, - * if the nodes also have the same line number, prefer the one with the smallest column. */ - if (bestDistancesRef->right > off7) { - bestDistancesRef->right = off7; - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } else if (bestDistancesRef->right == off7 && bestNodesRef->right) { - if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } - } - } else if (off7 == 0) { - bestDistancesRef->left = bestDistancesRef->right = 0; - bestNodesRef->left = node; - bestNodesRef->right = NULL; - result |= SYNCTEX_MASK_LEFT; - } else { /* here off7 < 0 */ - off7 = -off7; - if (bestDistancesRef->left > off7) { - bestDistancesRef->left = off7; - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } else if (bestDistancesRef->left == off7 && bestNodesRef->left) { - if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } - } - } - } while((node = SYNCTEX_SIBLING(node))); - if (result & SYNCTEX_MASK_LEFT) { - /* the left node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - } - if (result & SYNCTEX_MASK_RIGHT) { - /* the right node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - } - } - return result; -} -SYNCTEX_INLINE static int _synctex_eq_get_closest_children_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible) { - if (node) { - switch(node->class->type) { - case synctex_node_type_hbox: - return __synctex_eq_get_closest_children_in_hbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible); - case synctex_node_type_vbox: - return __synctex_eq_get_closest_children_in_vbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible); - } - } - return 0; -} - -SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int* distanceRef, synctex_bool_t visible); -SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int* distanceRef, synctex_bool_t visible) { - synctex_node_t best_node = NULL; - if ((node = SYNCTEX_CHILD(node))) { - do { - int distance = _synctex_node_distance_to_point(hitPoint,node,visible); - synctex_node_t candidate = NULL; - if (distance<=*distanceRef) { - *distanceRef = distance; - best_node = node; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - if ((candidate = __synctex_eq_closest_child(hitPoint,node,distanceRef,visible))) { - best_node = candidate; - } - } - } while((node = SYNCTEX_SIBLING(node))); - } - return best_node; -} -SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) { - if (node) { - switch(node->class->type) { - case synctex_node_type_hbox: - case synctex_node_type_vbox: - { - int best_distance = INT_MAX; - synctex_node_t best_node = __synctex_eq_closest_child(hitPoint,node,&best_distance,visible); - if ((best_node)) { - synctex_node_t child = NULL; - switch(best_node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - if ((child = SYNCTEX_CHILD(best_node))) { - best_distance = _synctex_node_distance_to_point(hitPoint,child,visible); - while((child = SYNCTEX_SIBLING(child))) { - int distance = _synctex_node_distance_to_point(hitPoint,child,visible); - if (distance<=best_distance) { - best_distance = distance; - best_node = child; - } - } - } - } - } - return best_node; - } - } - } - return NULL; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Updater -# endif - -typedef int (*synctex_fprintf_t)(void *, const char * , ...); /* print formatted to either FILE * or gzFile */ - -# define SYNCTEX_BITS_PER_BYTE 8 - -struct __synctex_updater_t { - gzFile file; /* the foo.synctex or foo.synctex.gz I/O identifier */ - synctex_fprintf_t fprintf; /* either fprintf or gzprintf */ - int length; /* the number of chars appended */ - struct _flags { - unsigned int no_gz:1; /* Whether zlib is used or not */ - unsigned int reserved:SYNCTEX_BITS_PER_BYTE*sizeof(int)-1; /* Align */ - } flags; -}; -# define SYNCTEX_FILE updater->file -# define SYNCTEX_NO_GZ ((updater->flags).no_gz) -# define SYNCTEX_fprintf (*(updater->fprintf)) - -synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * build_directory) { - synctex_updater_t updater = NULL; - char * synctex = NULL; - synctex_io_mode_t io_mode = 0; - const char * mode = NULL; - /* prepare the updater, the memory is the only one dynamically allocated */ - updater = (synctex_updater_t)_synctex_malloc(sizeof(synctex_updater_t)); - if (NULL == updater) { - _synctex_error("! synctex_updater_new_with_file: malloc problem"); - return NULL; - } - if (_synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_ADD_QUOTES,&io_mode) - && _synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_DONT_ADD_QUOTES,&io_mode)) { -return_on_error: - free(updater); - updater = NULL; - return NULL; - } - /* OK, the file exists, we close it and reopen it with the correct mode. - * The receiver is now the owner of the "synctex" variable. */ - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - SYNCTEX_NO_GZ = (io_mode&synctex_io_gz_mask)?synctex_NO:synctex_YES; - mode = _synctex_get_io_mode_name(io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */ - if (SYNCTEX_NO_GZ) { - if (NULL == (SYNCTEX_FILE = (void *)fopen(synctex,mode))) { -no_write_error: - _synctex_error("! synctex_updater_new_with_file: Can't append to %s",synctex); - free(synctex); - goto return_on_error; - } - updater->fprintf = (synctex_fprintf_t)(&fprintf); - } else { - if (NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) { - goto no_write_error; - } - updater->fprintf = (synctex_fprintf_t)(&gzprintf); - } - printf("SyncTeX: updating %s...",synctex); - free(synctex); - return updater; -} - - -void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){ - if (NULL==updater) { - return; - } - if (magnification && strlen(magnification)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Magnification:%s\n",magnification); - } -} - -void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset){ - if (NULL==updater) { - return; - } - if (x_offset && strlen(x_offset)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"X Offset:%s\n",x_offset); - } -} - -void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset){ - if (NULL==updater) { - return; - } - if (y_offset && strlen(y_offset)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Y Offset:%s\n",y_offset); - } -} - -void synctex_updater_free(synctex_updater_t updater){ - if (NULL==updater) { - return; - } - if (updater->length>0) { - SYNCTEX_fprintf(SYNCTEX_FILE,"!%i\n",updater->length); - } - if (SYNCTEX_NO_GZ) { - fclose((FILE *)SYNCTEX_FILE); - } else { - gzclose((gzFile)SYNCTEX_FILE); - } - free(updater); - printf("... done.\n"); - return; -} diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser.h b/elpa/pdf-tools-20191031.642/build/server/synctex_parser.h deleted file mode 100644 index 2c1911e0..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser.h +++ /dev/null @@ -1,363 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.18 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -Acknowledgments: ----------------- -The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, -and significant help from XeTeX developer Jonathan Kew - -Nota Bene: ----------- -If you include or use a significant part of the synctex package into a software, -I would appreciate to be listed as contributor and see "SyncTeX" highlighted. - -Version 1 -Thu Jun 19 09:39:21 UTC 2008 - -*/ - -#ifndef __SYNCTEX_PARSER__ -# define __SYNCTEX_PARSER__ - -#ifdef __cplusplus -extern "C" { -#endif - -# define SYNCTEX_VERSION_STRING "1.18" - -/* synctex_node_t is the type for all synctex nodes. - * The synctex file is parsed into a tree of nodes, either sheet, boxes, math nodes... */ -typedef struct _synctex_node * synctex_node_t; - -/* The main synctex object is a scanner - * Its implementation is considered private. - * The basic workflow is - * - create a "synctex scanner" with the contents of a file - * - perform actions on that scanner like display or edit queries - * - free the scanner when the work is done - */ -typedef struct __synctex_scanner_t _synctex_scanner_t; -typedef _synctex_scanner_t * synctex_scanner_t; - -/* This is the designated method to create a new synctex scanner object. - * output is the pdf/dvi/xdv file associated to the synctex file. - * If necessary, it can be the tex file that originated the synctex file - * but this might cause problems if the \jobname has a custom value. - * Despite this method can accept a relative path in practice, - * you should only pass a full path name. - * The path should be encoded by the underlying file system, - * assuming that it is based on 8 bits characters, including UTF8, - * not 16 bits nor 32 bits. - * The last file extension is removed and replaced by the proper extension. - * Then the private method _synctex_scanner_new_with_contents_of_file is called. - * NULL is returned in case of an error or non existent file. - * Once you have a scanner, use the synctex_display_query and synctex_edit_query below. - * The new "build_directory" argument is available since version 1.5. - * It is the directory where all the auxiliary stuff is created. - * Sometimes, the synctex output file and the pdf, dvi or xdv files are not created in the same directory. - * This is the case in MikTeX (I will include this into TeX Live). - * This directory path can be nil, it will be ignored then. - * It can be either absolute or relative to the directory of the output pdf (dvi or xdv) file. - * If no synctex file is found in the same directory as the output file, then we try to find one in the build directory. - * Please note that this new "build_directory" is provided as a convenient argument but should not be used. - * In fact, this is implempented as a work around of a bug in MikTeX where the synctex file does not follow the pdf file. - * The new "parse" argument is available since version 1.5. In general, use 1. - * Use 0 only if you do not want to parse the content but just check the existence. - */ -synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse); - -/* This is the designated method to delete a synctex scanner object. - * Frees all the memory, you must call it when you are finished with the scanner. - */ -void synctex_scanner_free(synctex_scanner_t scanner); - -/* Send this message to force the scanner to parse the contents of the synctex output file. - * Nothing is performed if the file was already parsed. - * In each query below, this message is sent, but if you need to access information more directly, - * you must be sure that the parsing did occur. - * Usage: - * if((my_scanner = synctex_scanner_parse(my_scanner))) { - * continue with my_scanner... - * } else { - * there was a problem - * } - */ -synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner); - -/* The main entry points. - * Given the file name, a line and a column number, synctex_display_query returns the number of nodes - * satisfying the contrain. Use code like - * - * if(synctex_display_query(scanner,name,line,column)>0) { - * synctex_node_t node; - * while((node = synctex_next_result(scanner))) { - * // do something with node - * ... - * } - * } - * - * For example, one can - * - highlight each resulting node in the output, using synctex_node_h and synctex_node_v - * - highlight all the rectangles enclosing those nodes, using synctex_box_... functions - * - highlight just the character using that information - * - * Given the page and the position in the page, synctex_edit_query returns the number of nodes - * satisfying the contrain. Use code like - * - * if(synctex_edit_query(scanner,page,h,v)>0) { - * synctex_node_t node; - * while(node = synctex_next_result(scanner)) { - * // do something with node - * ... - * } - * } - * - * For example, one can - * - highlight each resulting line in the input, - * - highlight just the character using that information - * - * page is 1 based - * h and v are coordinates in 72 dpi unit, relative to the top left corner of the page. - * If you make a new query, the result of the previous one is discarded. - * If one of this function returns a non positive integer, - * it means that an error occurred. - * - * Both methods are conservative, in the sense that matching is weak. - * If the exact column number is not found, there will be an answer with the whole line. - * - * Sumatra-PDF, Skim, iTeXMac2 and Texworks are examples of open source software that use this library. - * You can browse their code for a concrete implementation. - */ -typedef long synctex_status_t; -synctex_status_t synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column); -synctex_status_t synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v); -synctex_node_t synctex_next_result(synctex_scanner_t scanner); - -/* Display all the information contained in the scanner object. - * If the records are too numerous, only the first ones are displayed. - * This is mainly for informatinal purpose to help developers. - */ -void synctex_scanner_display(synctex_scanner_t scanner); - -/* The x and y offset of the origin in TeX coordinates. The magnification - These are used by pdf viewers that want to display the real box size. - For example, getting the horizontal coordinates of a node would require - synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner) - Getting its TeX width would simply require - synctex_node_box_width(node)*synctex_scanner_magnification(scanner) - but direct methods are available for that below. - */ -int synctex_scanner_x_offset(synctex_scanner_t scanner); -int synctex_scanner_y_offset(synctex_scanner_t scanner); -float synctex_scanner_magnification(synctex_scanner_t scanner); - -/* Managing the input file names. - * Given a tag, synctex_scanner_get_name will return the corresponding file name. - * Conversely, given a file name, synctex_scanner_get_tag will retur, the corresponding tag. - * The file name must be the very same as understood by TeX. - * For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex. - * No automatic path expansion is performed. - * Finally, synctex_scanner_input is the first input node of the scanner. - * To browse all the input node, use a loop like - * - * if((input_node = synctex_scanner_input(scanner))){ - * do { - * blah - * } while((input_node=synctex_node_sibling(input_node))); - * } - * - * The output is the name that was used to create the scanner. - * The synctex is the real name of the synctex file, - * it was obtained from output by setting the proper file extension. - */ -const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag); -int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name); -synctex_node_t synctex_scanner_input(synctex_scanner_t scanner); -const char * synctex_scanner_get_output(synctex_scanner_t scanner); -const char * synctex_scanner_get_synctex(synctex_scanner_t scanner); - -/* Browsing the nodes - * parent, child and sibling are standard names for tree nodes. - * The parent is one level higher, the child is one level deeper, - * and the sibling is at the same level. - * The sheet of a node is the first ancestor, it is of type sheet. - * A node and its sibling have the same parent. - * A node is the parent of its child. - * A node is either the child of its parent, - * or belongs to the sibling chain of its parent's child. - * The next node is either the child, the sibling or the parent's sibling, - * unless the parent is a sheet. - * This allows to navigate through all the nodes of a given sheet node: - * - * synctex_node_t node = sheet; - * while((node = synctex_node_next(node))) { - * // do something with node - * } - * - * With synctex_sheet_content, you can retrieve the sheet node given the page. - * The page is 1 based, according to TeX standards. - * Conversely synctex_node_sheet allows to retrieve the sheet containing a given node. - */ -synctex_node_t synctex_node_parent(synctex_node_t node); -synctex_node_t synctex_node_sheet(synctex_node_t node); -synctex_node_t synctex_node_child(synctex_node_t node); -synctex_node_t synctex_node_sibling(synctex_node_t node); -synctex_node_t synctex_node_next(synctex_node_t node); -synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page); -synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page); - -/* These are the types of the synctex nodes */ -typedef enum { - synctex_node_type_error = 0, - synctex_node_type_input, - synctex_node_type_sheet, - synctex_node_type_vbox, - synctex_node_type_void_vbox, - synctex_node_type_hbox, - synctex_node_type_void_hbox, - synctex_node_type_kern, - synctex_node_type_glue, - synctex_node_type_math, - synctex_node_type_boundary, - synctex_node_number_of_types -} synctex_node_type_t; - -/* synctex_node_type gives the type of a given node, - * synctex_node_isa gives the same information as a human readable text. */ -synctex_node_type_t synctex_node_type(synctex_node_t node); -const char * synctex_node_isa(synctex_node_t node); - -/* This is primarily used for debugging purpose. - * The second one logs information for the node and recursively displays information for its next node */ -void synctex_node_log(synctex_node_t node); -void synctex_node_display(synctex_node_t node); - -/* Given a node, access to the location in the synctex file where it is defined. - */ -typedef unsigned int synctex_charindex_t; -synctex_charindex_t synctex_node_charindex(synctex_node_t node); - -/* Given a node, access to its tag, line and column. - * The line and column numbers are 1 based. - * The latter is not yet fully supported in TeX, the default implementation returns 0 which means the whole line. - * When the tag is known, the scanner of the node will give the corresponding file name. - * When the tag is known, the scanner of the node will give the name. - */ -int synctex_node_tag(synctex_node_t node); -int synctex_node_line(synctex_node_t node); -int synctex_node_column(synctex_node_t node); - -/* In order to enhance forward synchronization, - * non void horizontal boxes have supplemental cached information. - * The mean line is the average of the line numbers of the included nodes. - * The child count is the number of chidren. - */ -int synctex_node_mean_line(synctex_node_t node); -int synctex_node_child_count(synctex_node_t node); - -/* This is the page where the node appears. - * This is a 1 based index as given by TeX. - */ -int synctex_node_page(synctex_node_t node); - -/* For quite all nodes, horizontal, vertical coordinates, and width. - * These are expressed in TeX small points coordinates, with origin at the top left corner. - */ -int synctex_node_h(synctex_node_t node); -int synctex_node_v(synctex_node_t node); -int synctex_node_width(synctex_node_t node); - -/* For all nodes, dimensions of the enclosing box. - * These are expressed in TeX small points coordinates, with origin at the top left corner. - * A box is enclosing itself. - */ -int synctex_node_box_h(synctex_node_t node); -int synctex_node_box_v(synctex_node_t node); -int synctex_node_box_width(synctex_node_t node); -int synctex_node_box_height(synctex_node_t node); -int synctex_node_box_depth(synctex_node_t node); - -/* For quite all nodes, horizontal, vertical coordinates, and width. - * The visible dimensions are bigger than real ones to compensate 0 width boxes - * that do contain nodes. - * These are expressed in page coordinates, with origin at the top left corner. - * A box is enclosing itself. - */ -float synctex_node_visible_h(synctex_node_t node); -float synctex_node_visible_v(synctex_node_t node); -float synctex_node_visible_width(synctex_node_t node); -/* For all nodes, visible dimensions of the enclosing box. - * A box is enclosing itself. - * The visible dimensions are bigger than real ones to compensate 0 width boxes - * that do contain nodes. - */ -float synctex_node_box_visible_h(synctex_node_t node); -float synctex_node_box_visible_v(synctex_node_t node); -float synctex_node_box_visible_width(synctex_node_t node); -float synctex_node_box_visible_height(synctex_node_t node); -float synctex_node_box_visible_depth(synctex_node_t node); - -/* The main synctex updater object. - * This object is used to append information to the synctex file. - * Its implementation is considered private. - * It is used by the synctex command line tool to take into account modifications - * that could occur while postprocessing files by dvipdf like filters. - */ -typedef struct __synctex_updater_t _synctex_updater_t; -typedef _synctex_updater_t * synctex_updater_t; - -/* Designated initializer. - * Once you are done with your whole job, - * free the updater */ -synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * directory); - -/* Use the next functions to append records to the synctex file, - * no consistency tests made on the arguments */ -void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification); -void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset); -void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset); - -/* You MUST free the updater, once everything is properly appended */ -void synctex_updater_free(synctex_updater_t updater); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_version.txt b/elpa/pdf-tools-20191031.642/build/server/synctex_parser_version.txt deleted file mode 100644 index d907c153..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_version.txt +++ /dev/null @@ -1 +0,0 @@ -1.18 \ No newline at end of file diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/lib/run-tests b/elpa/pdf-tools-20191031.642/build/server/test/docker/lib/run-tests deleted file mode 100755 index 43fe5e5c..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/lib/run-tests +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -PATH="$(dirname "$0")":$PATH - -set -e - -yes-or-enter | ./autobuild -i /bin -yes-or-enter | ./autobuild -i /usr/bin | \ - grep -q "Skipping package installation (already installed)" diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/Dockerfile.in deleted file mode 100644 index 083b19a5..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -ADD . /epdfinfo -WORKDIR /epdfinfo -RUN make -s distclean || true -CMD ["sh", "./test/docker/lib/run-tests"] diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/arch.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/arch.Dockerfile.in deleted file mode 100644 index 50e66585..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/arch.Dockerfile.in +++ /dev/null @@ -1,6 +0,0 @@ -# -*- dockerfile -*- -FROM base/archlinux -RUN pacman -Syu --noconfirm --noprogressbar && \ - pacman -S --noconfirm --noprogressbar poppler-glib base-devel - - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/centos-7.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/centos-7.Dockerfile.in deleted file mode 100644 index 62f2eb42..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/centos-7.Dockerfile.in +++ /dev/null @@ -1,3 +0,0 @@ -# -*- dockerfile -*- -FROM centos:7 -RUN yum update -y && yum install -y gcc gcc-c++ poppler-glib-devel diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-8.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-8.Dockerfile.in deleted file mode 100644 index adcc6d37..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-8.Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -# -*- dockerfile -*- -FROM debian:8 -RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-9.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-9.Dockerfile.in deleted file mode 100644 index 1f4ece7b..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/debian-9.Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -# -*- dockerfile -*- -FROM debian:9 -RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-24.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-24.Dockerfile.in deleted file mode 100644 index a2490ad6..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-24.Dockerfile.in +++ /dev/null @@ -1,5 +0,0 @@ -# -*- dockerfile -*- -FROM fedora:24 -RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel - - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-25.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-25.Dockerfile.in deleted file mode 100644 index 6f5f8c22..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-25.Dockerfile.in +++ /dev/null @@ -1,5 +0,0 @@ -# -*- dockerfile -*- -FROM fedora:25 -RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel - - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-26.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-26.Dockerfile.in deleted file mode 100644 index 8c43d1d4..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/fedora-26.Dockerfile.in +++ /dev/null @@ -1,5 +0,0 @@ -# -*- dockerfile -*- -FROM fedora:26 -RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel - - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/gentoo.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/gentoo.Dockerfile.in deleted file mode 100644 index 00ef03f8..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/gentoo.Dockerfile.in +++ /dev/null @@ -1,5 +0,0 @@ -# -*- dockerfile -*- -FROM gentoo/stage3-amd64 -RUN emerge --sync && emerge sys-devel/gcc app-text/poppler - - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-14.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-14.Dockerfile.in deleted file mode 100644 index 1c9aaa70..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-14.Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -# -*- dockerfile -*- -FROM ubuntu:trusty -RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-16.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-16.Dockerfile.in deleted file mode 100644 index e7d477ed..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-16.Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -# -*- dockerfile -*- -FROM ubuntu:xenial -RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev - diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-17.Dockerfile.in b/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-17.Dockerfile.in deleted file mode 100644 index bf2dc3dd..00000000 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/templates/ubuntu-17.Dockerfile.in +++ /dev/null @@ -1,4 +0,0 @@ -# -*- dockerfile -*- -FROM ubuntu:artful -RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev - diff --git a/elpa/pdf-tools-20191031.642/pdf-tools-autoloads.el b/elpa/pdf-tools-20191031.642/pdf-tools-autoloads.el deleted file mode 100644 index dda8580b..00000000 --- a/elpa/pdf-tools-20191031.642/pdf-tools-autoloads.el +++ /dev/null @@ -1,387 +0,0 @@ -;;; pdf-tools-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) - -;;;### (autoloads nil "pdf-annot" "pdf-annot.el" (23994 46397 260173 -;;;;;; 770000)) -;;; Generated autoloads from pdf-annot.el - -(autoload 'pdf-annot-minor-mode "pdf-annot" "\ -Support for PDF Annotations. - -\\{pdf-annot-minor-mode-map} - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-history" "pdf-history.el" (23994 46397 -;;;;;; 259193 628000)) -;;; Generated autoloads from pdf-history.el - -(autoload 'pdf-history-minor-mode "pdf-history" "\ -Keep a history of previously visited pages. - -This is a simple stack-based history. Turning the page or -following a link pushes the left-behind page on the stack, which -may be navigated with the following keys. - -\\{pdf-history-minor-mode-map} - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-isearch" "pdf-isearch.el" (23994 46397 -;;;;;; 249007 18000)) -;;; Generated autoloads from pdf-isearch.el - -(autoload 'pdf-isearch-minor-mode "pdf-isearch" "\ -Isearch mode for PDF buffer. - -When this mode is enabled \\[isearch-forward], among other keys, -starts an incremental search in this PDF document. Since this mode -uses external programs to highlight found matches via -image-processing, proceeding to the next match may be slow. - -Therefore two isearch behaviours have been defined: Normal isearch and -batch mode. The later one is a minor mode -\(`pdf-isearch-batch-mode'), which when activated inhibits isearch -from stopping at and highlighting every single match, but rather -display them batch-wise. Here a batch means a number of matches -currently visible in the selected window. - -The kind of highlighting is determined by three faces -`pdf-isearch-match' (for the current match), `pdf-isearch-lazy' -\(for all other matches) and `pdf-isearch-batch' (when in batch -mode), which see. - -Colors may also be influenced by the minor-mode -`pdf-view-dark-minor-mode'. If this is minor mode enabled, each face's -dark colors, are used (see e.g. `frame-background-mode'), instead -of the light ones. - -\\{pdf-isearch-minor-mode-map} -While in `isearch-mode' the following keys are available. Note -that not every isearch command work as expected. - -\\{pdf-isearch-active-mode-map} - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-links" "pdf-links.el" (23994 46397 251008 -;;;;;; 846000)) -;;; Generated autoloads from pdf-links.el - -(autoload 'pdf-links-minor-mode "pdf-links" "\ -Handle links in PDF documents.\\ - -If this mode is enabled, most links in the document may be -activated by clicking on them or by pressing \\[pdf-links-action-perform] and selecting -one of the displayed keys, or by using isearch limited to -links via \\[pdf-links-isearch-link]. - -\\{pdf-links-minor-mode-map} - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-links-action-perform "pdf-links" "\ -Follow LINK, depending on its type. - -This may turn to another page, switch to another PDF buffer or -invoke `pdf-links-browse-uri-function'. - -Interactively, link is read via `pdf-links-read-link-action'. -This function displays characters around the links in the current -page and starts reading characters (ignoring case). After a -sufficient number of characters have been read, the corresponding -link's link is invoked. Additionally, SPC may be used to -scroll the current page. - -\(fn LINK)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-loader" "pdf-loader.el" (23994 46397 258169 -;;;;;; 584000)) -;;; Generated autoloads from pdf-loader.el - -(autoload 'pdf-loader-install "pdf-loader" "\ -Prepare Emacs for using PDF Tools. - -This function acts as a replacement for `pdf-tools-install' and -makes Emacs load and use PDF Tools as soon as a PDF file is -opened, but not sooner. - -The arguments are passed verbatim to `pdf-tools-install', which -see. - -\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" nil nil) - -;;;*** - -;;;### (autoloads nil "pdf-misc" "pdf-misc.el" (23994 46397 253136 -;;;;;; 199000)) -;;; Generated autoloads from pdf-misc.el - -(autoload 'pdf-misc-minor-mode "pdf-misc" "\ -FIXME: Not documented. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-misc-size-indication-minor-mode "pdf-misc" "\ -Provide a working size indication in the mode-line. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-misc-menu-bar-minor-mode "pdf-misc" "\ -Display a PDF Tools menu in the menu-bar. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-misc-context-menu-minor-mode "pdf-misc" "\ -Provide a right-click context menu in PDF buffers. - -\\{pdf-misc-context-menu-minor-mode-map} - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-occur" "pdf-occur.el" (23994 46397 248001 -;;;;;; 265000)) -;;; Generated autoloads from pdf-occur.el - -(autoload 'pdf-occur "pdf-occur" "\ -List lines matching STRING or PCRE. - -Interactively search for a regexp. Unless a prefix arg was given, -in which case this functions performs a string search. - -If `pdf-occur-prefer-string-search' is non-nil, the meaning of -the prefix-arg is inverted. - -\(fn STRING &optional REGEXP-P)" t nil) - -(autoload 'pdf-occur-multi-command "pdf-occur" "\ -Perform `pdf-occur' on multiple buffer. - -For a programmatic search of multiple documents see -`pdf-occur-search'. - -\(fn)" t nil) - -(defvar pdf-occur-global-minor-mode nil "\ -Non-nil if Pdf-Occur-Global minor mode is enabled. -See the `pdf-occur-global-minor-mode' command -for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `pdf-occur-global-minor-mode'.") - -(custom-autoload 'pdf-occur-global-minor-mode "pdf-occur" nil) - -(autoload 'pdf-occur-global-minor-mode "pdf-occur" "\ -Enable integration of Pdf Occur with other modes. - -This global minor mode enables (or disables) -`pdf-occur-ibuffer-minor-mode' and `pdf-occur-dired-minor-mode' -in all current and future ibuffer/dired buffer. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-occur-ibuffer-minor-mode "pdf-occur" "\ -Hack into ibuffer's do-occur binding. - -This mode remaps `ibuffer-do-occur' to -`pdf-occur-ibuffer-do-occur', which will start the PDF Tools -version of `occur', if all marked buffer's are in `pdf-view-mode' -and otherwise fallback to `ibuffer-do-occur'. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-occur-dired-minor-mode "pdf-occur" "\ -Hack into dired's `dired-do-search' binding. - -This mode remaps `dired-do-search' to -`pdf-occur-dired-do-search', which will start the PDF Tools -version of `occur', if all marked buffer's are in `pdf-view-mode' -and otherwise fallback to `dired-do-search'. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-outline" "pdf-outline.el" (23994 46397 -;;;;;; 261141 728000)) -;;; Generated autoloads from pdf-outline.el - -(autoload 'pdf-outline-minor-mode "pdf-outline" "\ -Display an outline of a PDF document. - -This provides a PDF's outline on the menu bar via imenu. -Additionally the same outline may be viewed in a designated -buffer. - -\\{pdf-outline-minor-mode-map} - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-outline "pdf-outline" "\ -Display an PDF outline of BUFFER. - -BUFFER defaults to the current buffer. Select the outline -buffer, unless NO-SELECT-WINDOW-P is non-nil. - -\(fn &optional BUFFER NO-SELECT-WINDOW-P)" t nil) - -(autoload 'pdf-outline-imenu-enable "pdf-outline" "\ -Enable imenu in the current PDF buffer. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-sync" "pdf-sync.el" (23994 46397 262109 -;;;;;; 503000)) -;;; Generated autoloads from pdf-sync.el - -(autoload 'pdf-sync-minor-mode "pdf-sync" "\ -Correlate a PDF position with the TeX file. -\\ -This works via SyncTeX, which means the TeX sources need to have -been compiled with `--synctex=1'. In AUCTeX this can be done by -setting `TeX-source-correlate-method' to 'synctex (before AUCTeX -is loaded) and enabling `TeX-source-correlate-mode'. - -Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will open the -corresponding TeX location. - -If AUCTeX is your preferred tex-mode, this library arranges to -bind `pdf-sync-forward-display-pdf-key' (the default is `C-c C-g') -to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This -function displays the PDF page corresponding to the current -position in the TeX buffer. This function only works together -with AUCTeX. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-tools" "pdf-tools.el" (23994 46397 247044 -;;;;;; 318000)) -;;; Generated autoloads from pdf-tools.el - -(defvar pdf-tools-handle-upgrades t "\ -Whether PDF Tools should handle upgrading itself.") - -(custom-autoload 'pdf-tools-handle-upgrades "pdf-tools" t) - -(autoload 'pdf-tools-install "pdf-tools" "\ -Install PDF-Tools in all current and future PDF buffers. - -If the `pdf-info-epdfinfo-program' is not running or does not -appear to be working, attempt to rebuild it. If this build -succeeded, continue with the activation of the package. -Otherwise fail silently, i.e. no error is signaled. - -Build the program (if necessary) without asking first, if -NO-QUERY-P is non-nil. - -Don't attempt to install system packages, if SKIP-DEPENDENCIES-P -is non-nil. - -Do not signal an error in case the build failed, if NO-ERROR-P is -non-nil. - -Attempt to install system packages (even if it is deemed -unnecessary), if FORCE-DEPENDENCIES-P is non-nil. - -Note that SKIP-DEPENDENCIES-P and FORCE-DEPENDENCIES-P are -mutually exclusive. - -Note further, that you can influence the installation directory -by setting `pdf-info-epdfinfo-program' to an appropriate -value (e.g. ~/bin/epdfinfo) before calling this function. - -See `pdf-view-mode' and `pdf-tools-enabled-modes'. - -\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" t nil) - -(autoload 'pdf-tools-enable-minor-modes "pdf-tools" "\ -Enable MODES in the current buffer. - -MODES defaults to `pdf-tools-enabled-modes'. - -\(fn &optional MODES)" t nil) - -(autoload 'pdf-tools-help "pdf-tools" "\ - - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "pdf-view" "pdf-view.el" (23994 46397 250000 -;;;;;; 807000)) -;;; Generated autoloads from pdf-view.el - -(autoload 'pdf-view-bookmark-jump-handler "pdf-view" "\ -The bookmark handler-function interface for bookmark BMK. - -See also `pdf-view-bookmark-make-record'. - -\(fn BMK)" nil nil) - -;;;*** - -;;;### (autoloads nil "pdf-virtual" "pdf-virtual.el" (23994 46397 -;;;;;; 256216 424000)) -;;; Generated autoloads from pdf-virtual.el - -(autoload 'pdf-virtual-edit-mode "pdf-virtual" "\ -Major mode when editing a virtual PDF buffer. - -\(fn)" t nil) - -(autoload 'pdf-virtual-view-mode "pdf-virtual" "\ -Major mode in virtual PDF buffers. - -\(fn)" t nil) - -(defvar pdf-virtual-global-minor-mode nil "\ -Non-nil if Pdf-Virtual-Global minor mode is enabled. -See the `pdf-virtual-global-minor-mode' command -for a description of this minor mode. -Setting this variable directly does not take effect; -either customize it (see the info node `Easy Customization') -or call the function `pdf-virtual-global-minor-mode'.") - -(custom-autoload 'pdf-virtual-global-minor-mode "pdf-virtual" nil) - -(autoload 'pdf-virtual-global-minor-mode "pdf-virtual" "\ -Enable recognition and handling of VPDF files. - -\(fn &optional ARG)" t nil) - -(autoload 'pdf-virtual-buffer-create "pdf-virtual" "\ - - -\(fn &optional FILENAMES BUFFER-NAME DISPLAY-P)" t nil) - -;;;*** - -;;;### (autoloads nil nil ("pdf-cache.el" "pdf-dev.el" "pdf-info.el" -;;;;;; "pdf-tools-pkg.el" "pdf-util.el") (23994 46397 257150 14000)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; pdf-tools-autoloads.el ends here diff --git a/elpa/pdf-tools-20191031.642/pdf-tools-pkg.el b/elpa/pdf-tools-20191031.642/pdf-tools-pkg.el deleted file mode 100644 index 45dcf931..00000000 --- a/elpa/pdf-tools-20191031.642/pdf-tools-pkg.el +++ /dev/null @@ -1,13 +0,0 @@ -(define-package "pdf-tools" "20191031.642" "Support library for PDF documents." - '((emacs "24.3") - (tablist "1.0") - (let-alist "1.0.4")) - :keywords - '("files" "multimedia") - :authors - '(("Andreas Politz" . "politza@fh-trier.de")) - :maintainer - '("Andreas Politz" . "politza@fh-trier.de")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/pdf-tools-20230611.239/README b/elpa/pdf-tools-20230611.239/README new file mode 100644 index 00000000..61e394da --- /dev/null +++ b/elpa/pdf-tools-20230611.239/README @@ -0,0 +1,645 @@ +#+TITLE: PDF Tools README +#+AUTHOR: Andreas Politz +#+EMAIL: mail@andreas-politz.de +#+Maintainer: Vedang Manerikar +#+Maintainer_Email: vedang.manerikar@gmail.com + +[[https://app.circleci.com/pipelines/github/vedang/pdf-tools][https://circleci.com/gh/vedang/pdf-tools.svg?style=svg]] +[[https://elpa.nongnu.org/nongnu/pdf-tools.html][http://elpa.nongnu.org/nongnu/pdf-tools.svg]] +[[https://stable.melpa.org/#/pdf-tools][http://stable.melpa.org/packages/pdf-tools-badge.svg]] +[[https://melpa.org/#/pdf-tools][http://melpa.org/packages/pdf-tools-badge.svg]] [[https://ci.appveyor.com/project/vedang/pdf-tools][https://ci.appveyor.com/api/projects/status/yqic2san0wi7o5v8/branch/master?svg=true]] + +The ~pdf-tools~ Wiki is maintained at https://pdftools.wiki. Head to the site if you find it easier to navigate a website for reading a manual. All the topics on the site are listed at https://pdftools.wiki/impulse. + +* Table of Contents :noexport:TOC_3_gh: +- [[#about-pdf-tools][About PDF Tools]] +- [[#installing-pdf-tools][Installing pdf-tools]] + - [[#installing-the-epdfinfo-server][Installing the epdfinfo server]] + - [[#installing-the-epdfinfo-server-from-package-managers][Installing the epdfinfo server from package managers]] + - [[#installing-the-epdfinfo-server-from-source-on-windows--gotchas][Installing the epdfinfo server from source on Windows (+ Gotchas)]] + - [[#installing-the-epdfinfo-server-from-source-on-macos--gotchas][Installing the epdfinfo server from source on macOS (+ Gotchas)]] + - [[#common-installation-gotchas][Common installation gotchas]] + - [[#installing-optional-features][Installing optional features]] + - [[#installing-pdf-tools-elisp-code][Installing pdf-tools elisp code]] + - [[#updating-pdf-tools][Updating pdf-tools]] +- [[#features][Features]] + - [[#view-and-navigate-pdfs][View and Navigate PDFs]] + - [[#keybindings-for-navigating-pdf-documents][Keybindings for navigating PDF documents]] + - [[#keybindings-for-manipulating-display-of-pdf][Keybindings for manipulating display of PDF]] + - [[#annotations][Annotations]] + - [[#keybindings-for-working-with-annotations][Keybindings for working with Annotations]] + - [[#working-with-auctex][Working with AUCTeX]] + - [[#keybindings-for-working-with-auctex][Keybindings for working with AUCTeX]] + - [[#miscellaneous-features][Miscellaneous features]] + - [[#keybindings-for-miscellaneous-features-in-pdf-tools][Keybindings for miscellaneous features in PDF tools]] + - [[#easy-help-for-pdf-tools-features][Easy Help for PDF Tools features]] + - [[#configuring-pdf-tools-features][Configuring PDF Tools features]] +- [[#known-problems][Known problems]] + - [[#linum-mode][linum-mode]] + - [[#display-line-numbers-mode][display-line-numbers-mode]] + - [[#auto-revert][auto-revert]] + - [[#sublimity][sublimity]] + - [[#text-selection-is-not-transparent-in-pdfs-ocred-with-tesseract][Text selection is not transparent in PDFs OCRed with Tesseract]] +- [[#key-bindings-in-pdf-tools][Key-bindings in PDF Tools]] +- [[#tips-and-tricks-for-developers][Tips and Tricks for Developers]] + - [[#turn-on-debug-mode][Turn on debug mode]] + - [[#run-emacs-lisp-tests-locally][Run Emacs lisp tests locally]] + - [[#run-server-compilation-tests-locally][Run server compilation tests locally]] + - [[#add-a-dockerfile-to-automate-server-compilation-testing][Add a Dockerfile to automate server compilation testing]] + - [[#issue-template-for-bug-reports][Issue Template for Bug Reports]] + - [[#describe-the-bug][Describe the bug]] + - [[#steps-to-reproduce-the-behaviour][Steps To Reproduce the behaviour:]] + - [[#what-is-the-expected-behaviour][What is the expected behaviour?]] + - [[#desktop][Desktop]] + - [[#your-pdf-tools-install][Your pdf-tools install]] + - [[#additional-context][Additional context]] +- [[#faqs][FAQs]] + - [[#pdfs-are-not-rendering-well][PDFs are not rendering well!]] + - [[#what-emacs-versions-does-pdf-tools-support][What Emacs versions does pdf-tools support?]] + - [[#i-want-to-add-support-for-pdf-tools-on-my-fav-os-how-do-i-do-that][I want to add support for pdf-tools on "My Fav OS". How do I do that?]] + - [[#i-am-on-a-macbook-m1-and-pdf-tools-installation-fails-with-a-stack-trace][I am on a Macbook M1 and pdf-tools installation fails with a stack-trace]] + - [[#i-am-a-developer-making-changes-to-the-pdf-tools-source-code][I am a developer, making changes to the pdf-tools source code]] + +* About PDF Tools +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 5a884389-6aec-498a-90d5-f37168809b4f +:EXPORT_FILE_NAME: index +:END: +PDF Tools is, among other things, a replacement of DocView for PDF files. The key difference is that pages are not pre-rendered by, say, ~ghostscript~ and stored in the file-system, but rather created on-demand and stored in memory. + +This rendering is performed by a special library named, for whatever reason, ~poppler~, running inside a server program. This program is called ~epdfinfo~ and its job is to successively read requests from Emacs and produce the proper results, i.e. the PNG image of a PDF page. + +Actually, displaying PDF files is just one part of ~pdf-tools~. Since ~poppler~ can provide us with all kinds of information about a document and is also able to modify it, there is a lot more we can do with it. [[https://www.dailymotion.com/video/x2bc1is][Watch this video for a detailed demo!]] + +* Installing pdf-tools +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 6ceea50c-cbaa-4d8a-b450-8067c5e8c9da +:NEURON_DIRTREE_DISPLAY: false +:END: +Installing this package via NonGNU ELPA or MELPA or any of the other package managers is straightforward and should just work! You should not require any manual changes. The documentation below is *only if you are installing from source*, or for troubleshooting / debugging purposes. + +~pdf-tools~ requires a server ~epdfinfo~ to run against, which it will try to compile and build when it is activated for the first time. The following steps need to be followed *in this order*, to install ~pdf-tools~ and ~epdfinfo~ correctly: + +- [[brain-child:e305cd0a-e798-4c2b-af27-21bcd936c1c9][Installing the epdfinfo server]] +- [[brain-child:32c4fc3b-b4ea-43bd-b92c-bdf2d3831fcf][Installing pdf-tools elisp code]] + +** Installing the epdfinfo server +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: e305cd0a-e798-4c2b-af27-21bcd936c1c9 +:END: +If you install ~pdf-tools~ via NonGNU ELPA or MELPA, *you don't need to worry about this separate server installation at all*. + +Note: You'll need GNU Emacs \ge 26.3 and some form of a GNU/Linux OS. Other operating systems are not officially supported, but ~pdf-tools~ is known to work on many of them. + +The ~epdfinfo~ install script takes care of installing all the necessary pre-requisites on supported operating systems (see list below). See the section on [[id:A34704B9-1B51-4614-8806-C4059F7B42D5][I want to add support for ~pdf-tools~ on =My Fav OS=. How do I do that?]] to learn how to add your favorite Operating System to this list. + +Similarly, package-managers are not officially supported, but ~pdf-tools~ is known to be available on some of them. See the section on [[id:fb5cef15-fed4-4dec-a443-52f7c00c7831][Installing the ~epdfinfo~ server from package managers]] to avoid manual installation of server / server prerequisites. + +Installation Instructions for ~epdfinfo~: +#+begin_src sh + $ git clone https://github.com/vedang/pdf-tools + $ cd /path/to/pdf-tools + $ make -s # If you don't have make installed, run ./server/autobuild and it will install make +#+end_src + +This should give you no error and should compile the ~epdfinfo~ server. If you face a problem, please report on the issue tracker! + +The following Operating Systems / package managers are supported. *Note*: The package manager used to install pre-requisites should be installed on your OS for the script to work: + +- Debian-based systems (~debian~, ~ubuntu~): ~apt-get~ +- Fedora: ~dnf~ +- macOS: ~brew~ +- Windows (MSYS2/ MingW): ~pacman~ +- NixOS: ~nix-shell~ +- openSUSE (Tumbleweed and Leap): ~zypper~ +- Void Linux: ~xbps-install~ +- Apline Linux: ~apk~ +- FreeBSD: ~pkg~ +- OpenBSD: ~pkg_add~ +- NetBSD: ~pkgin~ +- Arch Linux: ~pacman~ +- Gentoo: ~emerge~ +- CentOS: ~yum~ + +*** Installing the epdfinfo server from package managers +:PROPERTIES: +:CREATED: [2022-02-13 Sun 23:10] +:ID: fb5cef15-fed4-4dec-a443-52f7c00c7831 +:END: +~pdf-tools~ can be directly installed from the package manager on some operating systems. Note that the packages available on these package managers are not maintained by the author and might be outdated. + +- Debian: https://packages.debian.org/buster/elpa-pdf-tools-server +- Ubuntu: https://packages.ubuntu.com/impish/elpa-pdf-tools-server +- MSYS2 / MINGW (Windows): https://packages.msys2.org/package/mingw-w64-x86_64-emacs-pdf-tools-server?repo=mingw64 +- FreeBSD: https://repology.org/metapackages/?search=pdf-tools&inrepo=freebsd + +*** Installing the epdfinfo server from source on Windows (+ Gotchas) +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: d14e01ff-9bd5-47ee-86fc-859b4499d5d7 +:END: +If using the GNU binaries for Windows, support for PNG and ~zlib~ must first be installed by copying the appropriate dlls into emacs' ~bin/~ directory. Most third-party binaries come with this already done. + +1. [[https://www.msys2.org/][install MSYS2]] and update the package database and core packages using the instructions provided. +2. Open ~mingw64~ shell (*Note:* You must use ~mingw64.exe~ and not ~msys2.exe~) +3. Compile the ~epdfinfo~ server using Installation steps described in [[id:e305cd0a-e798-4c2b-af27-21bcd936c1c9][Installing the ~epdfinfo~ server]] +4. This should produce a file ~server/epdfinfo.exe~. Copy this file into the ~pdf-tools/~ installation directory in your Emacs. +5. Make sure Emacs can find ~epdfinfo.exe~. Either add the MINGW install location (e.g. ~C:/msys2/mingw64/bin~) to the system path with ~setx PATH "C:\msys2\mingw64\bin;%PATH%"~ or set Emacs's path with ~(setenv "PATH" (concat "C:\\msys64\\mingw64\\bin;" (getenv "PATH")))~. Note that libraries from other GNU utilities, such as Git for Windows, may interfere with those needed by ~pdf-tools~. ~pdf-info-check-epdinfo~ will succeed, but errors occur when trying to view a PDF file. This can be fixed by ensuring that the MSYS libraries are always preferred. +6. ~pdf-tools~ will successfully compile using Cygwin, but it will not be able to open PDFs properly due to the way binaries compiled with Cygwin handle file paths. Please use MSYS2. + +*** Installing the epdfinfo server from source on macOS (+ Gotchas) +:PROPERTIES: +:CREATED: [2022-10-11 Tue 11:42] +:ID: 60CBCD65-5654-400A-913F-8B31901D071C +:END: +On macOS, ~autobuild~ adjusts ~PKG_CONFIG_PATH~ so that ~pdf-tools~ can find some of the keg-only packages installed by ~brew~. It is recommended that you review the output logs printed by ~brew~ during the installation process to also export the relevant paths to the appropriate ENV variables. + +*** Common installation gotchas +:PROPERTIES: +:CREATED: [2022-10-11 Tue 11:04] +:ID: 3F4C0FDF-6AC0-4845-BA2D-ED7C2F40D894 +:END: +In case you decide to install ~libpoppler~ from source, make sure to run its configure script with the ~--enable-xpdf-headers~ option. + +*** Installing optional features +:PROPERTIES: +:CREATED: [2022-10-11 Tue 11:15] +:ID: 97FC4447-B567-457F-A498-7CCA74DD5657 +:END: +One feature -- following links of a PDF document by plain keystrokes -- requires ~imagemagick~'s convert utility. This requirement is optional, the installation process will detect if you have ~imagemagick~ installed or not. +** Installing pdf-tools elisp code +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 32c4fc3b-b4ea-43bd-b92c-bdf2d3831fcf +:END: +~pdf-tools~ requires ~tablist~ package (>= version 0.70) to be installed, for it to work correctly. Please make sure that the latest version of ~tablist~ is installed. + +We have already run the steps necessary to install ~pdf-tools~ as part of [[id:e305cd0a-e798-4c2b-af27-21bcd936c1c9][the server installation]]! These are: +#+BEGIN_SRC sh + $ git clone https://github.com/vedang/pdf-tools + $ cd /path/to/pdf-tools + $ make -s +#+END_SRC + +If the ~make~ command produced the ELP file ~pdf-tools-${VERSION}.tar~ you are fine! This package contains all the necessary files for Emacs and may be installed by either using +#+begin_src sh + $ make install-package +#+end_src +or executing the Emacs command +#+begin_src elisp + M-x package-install-file RET pdf-tools-${VERSION}.tar RET +#+end_src + +You can test if the package has been installed correctly, by running +#+begin_src elisp + M-x pdf-info-check-epdfinfo RET +#+end_src + +To complete the installation process, you need to activate the package by putting the code below somewhere in your ~.emacs~. Alternatively, and if you care about startup time, you may want to use the loader version instead. +#+begin_src elisp + (pdf-tools-install) ; Standard activation command + (pdf-loader-install) ; On demand loading, leads to faster startup time +#+end_src + +Once the Installation process is complete, check out [[id:19a3daea-6fa6-4ac3-9201-d2034c46ad8c][Easy Help for PDF Tools features]] and [[id:8dccd685-18b8-4c98-977a-0fe2d66b724c][Configuring PDF Tools features]] to get started! +** Updating pdf-tools +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 9dd62314-f5ad-4bd4-83fa-8e28343e3d9c +:END: +Some day you might want to update this package via ~git pull~ and then reinstall it. Sometimes this may fail, especially if Lisp-Macros are involved and the version hasn't changed. To avoid this kind of problems, you should delete the old package via ~list-packages~, restart Emacs, run ~make distclean~ and then reinstall the package. Follow the steps described in [[id:32c4fc3b-b4ea-43bd-b92c-bdf2d3831fcf][Installing pdf-tools elisp code]]. + +This also applies when updating via MELPA / NonGNU ELPA (except for running the ~make distclean~ step). + +* Features +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 555b4a2a-7881-49ac-a066-7e3f10034ca4 +:END: ++ View :: View PDF documents in a buffer with DocView-like bindings. [[id:18d362e1-a1a3-4c51-9d45-04e2c53d8c0c][More information here]]. ++ Isearch :: Interactively search PDF documents like any other buffer, either for a string or a PCRE. ++ Occur :: List lines matching a string or regexp in one or more PDF documents. ++ Follow :: Click on highlighted links, moving to some part of a different page, some external file, a website or any other URI. Links may also be followed by keyboard commands. ++ Annotations :: Display and list text and markup annotations (like underline), edit their contents and attributes (e.g. color), move them around, delete them or create new ones and then save the modifications back to the PDF file. [[id:5fff6471-a933-46d7-8ae9-b2fa4a9de952][More information here]]. ++ Attachments :: Save files attached to the PDF-file or list them in a dired buffer. ++ Outline :: Use ~imenu~ or a special buffer (=M-x pdf-outline=) to examine and navigate the PDF's outline. ++ SyncTeX :: Jump from a position on a page directly to the TeX source and vice versa. ++ Virtual :: Use a collection of documents as if it were one, big single PDF. ++ Misc :: + - Display PDF's metadata. + - Mark a region and kill the text from the PDF. + - Keep track of visited pages via a history. + - Apply a color filter for reading in low light conditions. +** View and Navigate PDFs +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:25] +:ID: 18d362e1-a1a3-4c51-9d45-04e2c53d8c0c +:END: +PDFView Mode is an Emacs PDF viewer. It displays PDF files as PNG images in Emacs buffers. PDFs are navigable using DocView-like bindings. Once you have installed ~pdf-tools~, opening a PDF in Emacs will automatically trigger this mode. +*** Keybindings for navigating PDF documents +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:25] +:ID: 01864499-2286-4e64-91f5-f8133f53ec61 +:END: +| Navigation | | +|-----------------------------------------------+-------------------------| +| Scroll Up / Down by Page-full | ~space~ / ~backspace~ | +| Scroll Up / Down by Line | ~C-n~ / ~C-p~ | +| Scroll Right / Left | ~C-f~ / ~C-b~ | +| First Page / Last Page | ~<~, ~M-<~ / ~>~, ~M->~ | +| Next Page / Previous Page | ~n~ / ~p~ | +| Incremental Search Forward / Backward | ~C-s~ / ~C-r~ | +| Occur (list all lines containing a phrase) | ~M-s o~ | +| Jump to Occur Line | ~RETURN~ | +| Pick a Link and Jump | ~F~ | +| Incremental Search in Links | ~f~ | +| History Back / Forwards | ~l~ / ~r~ | +| Display Outline | ~o~ | +| Jump to Section from Outline | ~RETURN~ | +| Jump to Page | ~M-g g~ | +| Store position / Jump to position in register | ~m~ / ~'~ | +|-----------------------------------------------+-------------------------| +| | | +Note that ~pdf-tools~ renders the PDF as images inside Emacs. This means that all the keybindings of ~image-mode~ work on individual PDF pages as well. +| Image Mode | | +|------------------------+---------------------------------------------| +| image-scroll-right | ~C-x >~ / ~ ~ | +| image-scroll-left | ~C-x <~ / ~ ~ | +| image-scroll-up | ~C-v~ / ~ ~ | +| image-scroll-down | ~M-v~ / ~ ~ | +| image-forward-hscroll | ~C-f~ / ~right~ / ~ ~ | +| image-backward-hscroll | ~C-b~ / ~left~ / ~ ~ | +| image-bob | ~ ~ | +| image-eob | ~ ~ | +| image-bol | ~ ~ | +| image-eol | ~ ~ | +| image-scroll-down | ~ ~ | +| image-scroll-up | ~ ~ | +| image-scroll-left | ~ ~ | +| image-scroll-right | ~ ~ | +|------------------------+---------------------------------------------| +| | | + +*** Keybindings for manipulating display of PDF +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:33] +:ID: 73a18ea8-aa21-48d4-9d8b-dc64e3601000 +:END: +| Display | | +|------------------------------------------+-----------------| +| Zoom in / Zoom out | ~+~ / ~-~ | +| Fit Height / Fit Width / Fit Page | ~H~ / ~W~ / ~P~ | +| Trim Margins (set slice to bounding box) | ~s b~ | +| Reset Margins | ~s r~ | +| Reset Zoom | ~0~ | +| Rotate Page | ~R~ | +|------------------------------------------+-----------------| + +** Annotations +:PROPERTIES: +:CREATED: [2021-12-30 Thu 16:58] +:ID: 5fff6471-a933-46d7-8ae9-b2fa4a9de952 +:END: +~pdf-tools~ supports working with PDF Annotations. You can display and list text and markup annotations (like squiggly, highlight), edit their contents and attributes (e.g. color), move them around, delete them or create new ones and then save the modifications back to the PDF file. +*** Keybindings for working with Annotations +:PROPERTIES: +:CREATED: [2021-12-30 Thu 17:08] +:ID: 243b3843-b912-430b-884a-641304755b92 +:END: +| Annotations | | +|--------------------------------------+----------------------------------------------------| +| List Annotations | ~C-c C-a l~ | +| Jump to Annotations from List | ~SPACE~ | +| Mark Annotation for Deletion | ~d~ | +| Delete Marked Annotations | ~x~ | +| Unmark Annotations | ~u~ | +| Close Annotation List | ~q~ | +| Enable/Disable Following Annotations | ~C-c C-f~ | +|--------------------------------------+----------------------------------------------------| +| Add and Edit Annotations | Select region via Mouse selection. | +| | Then left-click context menu OR keybindings below | +|--------------------------------------+----------------------------------------------------| +| Add a Markup Annotation | ~C-c C-a m~ | +| Add a Highlight Markup Annotation | ~C-c C-a h~ | +| Add a Strikeout Markup Annotation | ~C-c C-a o~ | +| Add a Squiggly Markup Annotation | ~C-c C-a s~ | +| Add an Underline Markup Annotation | ~C-c C-a u~ | +| Add a Text Annotation | ~C-c C-a t~ | +|--------------------------------------+----------------------------------------------------| +| Highlight an arbitrary region | Section region with Mouse Drag (Hold down Meta and | +| | drag). Then ~C-c C-a h~ to highlight that region. | +|--------------------------------------+----------------------------------------------------| +| | | + +** Working with AUCTeX +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:37] +:ID: 698bdbad-e5f1-4958-b61e-9ed12d4b1234 +:END: +*** Keybindings for working with AUCTeX +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:37] +:ID: ab7872c1-edd6-465d-9d1d-b621db6364a3 +:END: +| Syncing with AUCTeX | | +|-----------------------------------------------+-------------| +| Refresh File (e.g., after recompiling source) | ~g~ | +| Jump to PDF Location from Source | ~C-c C-g~ | +| Jump Source Location from PDF | ~C-mouse-1~ | + +** Miscellaneous features +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:37] +:ID: bbefb49d-fca8-4d4f-9d16-4a4ad1946d89 +:END: +*** Keybindings for miscellaneous features in PDF tools +:PROPERTIES: +:CREATED: [2021-12-30 Thu 18:35] +:ID: 9148deff-dd5a-46be-a48f-cd2f96b7ce19 +:END: +| Miscellaneous | | +|-----------------------------------------------+-----------| +| Print File | ~C-c C-p~ | + +** Easy Help for PDF Tools features +:PROPERTIES: +:CREATED: [2021-12-29 Wed 13:49] +:ID: 19a3daea-6fa6-4ac3-9201-d2034c46ad8c +:END: +#+begin_src elisp + M-x pdf-tools-help RET +#+end_src + +Run =M-x pdf-tools-help= inside Emacs, as shown above. It will list all the features provided by ~pdf-tools~ as well as the key-bindings for these features. + +** Configuring PDF Tools features +:PROPERTIES: +:CREATED: [2021-12-29 Wed 13:51] +:ID: 8dccd685-18b8-4c98-977a-0fe2d66b724c +:END: +Once you have read through the features provided by ~pdf-tools~, you probably want to customize the behavior of the features as per your requirements. Full customization of features is available by running the following: +#+begin_src elisp + M-x pdf-tools-customize RET +#+end_src + +* Known problems +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:29] +:ID: 4baf936a-2454-41c9-99db-177133ee9568 +:END: + +** linum-mode +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 73625d02-d472-4e7d-9805-db6d3b60e0ff +:END: +~pdf-tools~ does not work well together with ~linum-mode~ and activating it in a ~pdf-view-mode~, e.g. via ~global-linum-mode~, might make Emacs choke. + +** display-line-numbers-mode +:PROPERTIES: +:CREATED: [2022-01-03 Mon 08:31] +:ID: f178ba41-0f5a-4d22-b4a8-889af1af566e +:END: +This mode is an alternative to ~linum-mode~ and is available since Emacs 26. ~pdf-tools~ does not work well with it. For example, it makes horizontal navigation (such as ~C-f~, ~C-b~, ~C-x <~ or ~C-x >~ ) in a document impossible. + +** auto-revert +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 24b671c6-c242-4983-9d11-38421d2752e9 +:END: +Autorevert works by polling the file-system every ~auto-revert-interval~ seconds, optionally combined with some event-based reverting via [[https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Notifications.html][file notification]]. But this currently does not work reliably, such that Emacs may revert the PDF-buffer while the corresponding file is still being written to (e.g. by LaTeX), leading to a potential error. + +With a recent [[https://www.gnu.org/software/auctex/][AUCTeX]] installation, you might want to put the following somewhere in your dotemacs, which will revert the PDF-buffer *after* the TeX compilation has finished. +#+BEGIN_SRC emacs-lisp + (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer) +#+END_SRC + +** sublimity +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 4766d18a-c02a-456d-8398-701bbea3ee80 +:END: +L/R scrolling breaks while zoomed into a pdf, with usage of sublimity smooth scrolling features + +** Text selection is not transparent in PDFs OCRed with Tesseract +:PROPERTIES: +:CREATED: [2022-09-19 Mon 18:50] +:ID: C3A4A7C0-6BBB-4923-AD39-3707C8482A76 +:END: + +In such PDFs the selected text becomes hidden behind the selection; see [[https://github.com/vedang/pdf-tools/issues/149][this issue]], which also describes the workaround in detail. The following function, which depends on the [[https://github.com/orgtre/qpdf.el][qpdf.el]] package, can be used to convert such a PDF file into one where text selection is transparent: +#+begin_src elisp + (defun my-fix-pdf-selection () + "Replace pdf with one where selection shows transparently." + (interactive) + (unless (equal (file-name-extension (buffer-file-name)) "pdf") + (error "Buffer should visit a pdf file.")) + (unless (equal major-mode 'pdf-view-mode) + (pdf-view-mode)) + ;; save file in QDF-mode + (qpdf-run (list + (concat "--infile=" + (buffer-file-name)) + "--qdf --object-streams=disable" + "--replace-input")) + ;; do replacements + (text-mode) + (read-only-mode -1) + (while (re-search-forward "3 Tr" nil t) + (replace-match "7 Tr" nil nil)) + (save-buffer) + (pdf-view-mode)) +#+end_src +Note that this overwrites the PDF file visited in the buffer from which it is run! To avoid this replace the ~--replace-input~ with ~(concat "--outfile=" (file-truename (read-file-name "Outfile: ")))~. + +* Key-bindings in PDF Tools +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: fa99285a-437e-4be4-9a65-426db019019f +:END: +- [[brain-child:01864499-2286-4e64-91f5-f8133f53ec61][Keybindings for navigating PDF documents]] +- [[brain-child:243b3843-b912-430b-884a-641304755b92][Keybindings for working with Annotations]] +- [[brain-child:73a18ea8-aa21-48d4-9d8b-dc64e3601000][Keybindings for manipulating display of PDF]] +- [[brain-child:ab7872c1-edd6-465d-9d1d-b621db6364a3][Keybindings for working with AUCTeX]] +- [[brain-child:9148deff-dd5a-46be-a48f-cd2f96b7ce19][Keybindings for miscellaneous features in PDF tools]] + +* Tips and Tricks for Developers +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: fd64c10c-4ea5-4ece-8d95-b723098dd4f6 +:END: +** Turn on debug mode +:PROPERTIES: +:CREATED: [2021-12-29 Wed 18:34] +:ID: 100fc888-7064-4dd3-9db4-c84a7e8f4af0 +:END: +#+begin_src elisp + M-x pdf-tools-toggle-debug RET +#+end_src +Toggling debug mode prints information about various operations in the ~*Messages*~ buffer, and this is useful to see what is happening behind the scenes + +** Run Emacs lisp tests locally +:PROPERTIES: +:CREATED: [2022-05-09 Mon 21:27] +:ID: 1CBE7325-A5A1-479B-9A98-BEEFBAC9D8FF +:END: +You can go to the ~pdf-tools~ folder and run ~make test~ to run the ERT tests and check if the changes you have made to the code break any of the tests. + +The tests are written in ERT, which is the built-in testing system in Emacs. However, they are run using ~Cask~ which you will have to install first, if you don't have it already. You can install ~Cask~ by following the instructions on their site at https://github.com/cask/cask +** Run server compilation tests locally +:PROPERTIES: +:CREATED: [2022-07-20 Wed 16:42] +:ID: 5327945D-9D92-4462-8172-7237DEF4C359 +:END: +You can go to the ~pdf-tools~ folder and run ~make server-test~ to check if the changes you have made to the server code break compilation on any of the supported operating systems. + +The tests build ~Podman~ images for all supported operating systems, so you will have to install ~Podman~ first, if you don't have already. You can install ~Podman~ by following the instructions on their site at https://podman.io/getting-started/installation + +Podman is compatible with Docker, so if you already have ~docker~ installed, you should be able to ~alias podman=docker~ on your shell and run the tests, without having to install Docker. (Note: I have not tested this) + +** Add a Dockerfile to automate server compilation testing +:PROPERTIES: +:CREATED: [2022-07-20 Wed 16:52] +:ID: A401543C-308B-4175-8212-5B78CD6C8389 +:END: +The ~server/test/docker~ folder contains Dockerfile templates used for testing that the ~epdfinfo~ server compiles correctly on various operating systems ([[id:5327945D-9D92-4462-8172-7237DEF4C359][more details here]]). + +To see the list of operating systems where compilation testing is supported, run ~make server-test-supported~. To see the list of operating systems where testing is unsupported, run ~make server-test-unsupported~. To add support, look into the ~server/test/docker/templates~ folder (~ubuntu~ files are a good example to refer to) + +** Issue Template for Bug Reports +:PROPERTIES: +:CREATED: [2022-12-02 Fri 13:30] +:ID: F563A2A4-FCF8-4F04-94CA-19E80E4841A6 +:END: +Please use the 'Bug Report' issue template when reporting bugs. The template is as follows: + +*** Describe the bug +A clear and concise description of what the bug is. + +*** Steps To Reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +*** What is the expected behaviour? +A clear and concise description of what you expected to happen. + +*** Desktop +Please complete the following information: + +- OS: [eg: MacOS Catalina] +- Emacs Version: [This should be the output of =M-x emacs-version= ] +- Poppler Version: [eg: output of ~brew info poppler~ and similarly for other OSs] + +*** Your pdf-tools install +Please complete the following information: +- ~pdf-tools~ Version: [ =M-x package-list-packages= -> Search for ~pdf-tools~ -> Hit Enter and copy all the details that pop up in the Help buffer] +- ~pdf-tools~ customization / configuration that you use: + +*** Additional context +- If you are reporting a crash, please try and add the Backtrace / Stacktrace of the crash. +- If you are reporting a bug, please try and attach an example PDF file where I can reproduce the bug. +- If you can attach screenshots or recordings, that is a great help +- Please try reproducing the bug yourself on Vanilla Emacs before reporting the problem. + +* FAQs +:PROPERTIES: +:CREATED: [2021-12-30 Thu 22:04] +:ID: 3be6abe7-163e-4c3e-a7df-28e8470fe37f +:END: +** Epdfinfo has stopped working! +:PROPERTIES: +:CREATED: [2023-06-10 Sat 23:25] +:ID: 9B5F797F-9BB3-45D9-B364-D4E5F13222BF +:END: +Have you upgraded ~poppler~ recently? This can cause ~epdfinfo~ to stop working, since it was compiled with the previous version of ~poppler~. Just run =M-x pdf-tools-install= and this should be fixed. + +** PDFs are not rendering well! +:PROPERTIES: +:CREATED: [2021-12-30 Thu 22:04] +:ID: 20ef86be-7c92-4cda-97ec-70a22484e689 +:END: +~pdf-tools~ version ~1.1.0~ release changed the default value of ~pdf-view-use-scaling~ to ~t~ (previously, it was ~nil~). This has been done keeping in mind that most modern monitors are HiDPI screens, so the default configuration should cater to this user. If you are not using a HiDPI screen, you might have to change this value to ~nil~ in your configuration + +#+begin_src elisp + (setq pdf-view-use-scaling nil) +#+end_src + +to scale the images correctly when rendering them. + +** What Emacs versions does pdf-tools support? +:PROPERTIES: +:CREATED: [2022-01-02 Sun 10:12] +:ID: f44c66e6-402d-4154-b806-6bb4180a0a5b +:END: +~pdf-tools~ supports the 3 latest versions of Emacs major releases. At the moment of this writing, this means that the minimum supported Emacs version is ~26.3~. + +** I want to add support for pdf-tools on "My Fav OS". How do I do that? +:PROPERTIES: +:CREATED: [2022-04-25 Mon 21:50] +:ID: A34704B9-1B51-4614-8806-C4059F7B42D5 +:END: +I'm working on automating ~pdf-tools~ installation as much as possible, in order to improve the installation experience. If you want to add support for a new / currently unsupported Operating System, please modify the ~server/autobuild~ script. Say you want to support a new Operating System called MyFavOS. You need to do the following work: + +1. Search for the ~Figure out where we are~ section. Here, add a call to ~os_myfavos~ right below ~handle_options~ at the end of the existing call chain. Here we try and pick up the correct Operating System and install the relevant dependencies. +2. Add handling for the ~--os~ argument in ~os_argument~ for ~myfavos~, so that the appropriate function can be called to install pre-requisites. ~--os~ is the argument that we pass to the script from the command-line to indicate which OS we are on. +3. Create a ~os_myfavos~ function. This function checks if we are running on MyFavOS. If we are running on MyFavOS, it sets up ~PKGCMD~, ~PKGARGS~ and ~PACKAGES~ variables so that the appropriate package manager can install the dependencies as part of the rest of the ~autobuild~ script. +4. If you are adding support for your favorite operating system, consider adding automated testing support as well, to help me ensure that ~epdfinfo~ continues to compile correctly. See [[id:A401543C-308B-4175-8212-5B78CD6C8389][Add a Dockerfile to automate server compilation testing]] for more details. + +The idea here is to make the ~server/autobuild~ file the single place from which installation can happen on any Operating System. This makes building ~pdf-tools~ dead simple via the ~Makefile~. + +This seems like a lot of work, but it is not. If you need a reference, search for ~os_gentoo~ or ~os_debian~ in the ~server/autobuild~ file and see how these are setup and used. The functions are used to install dependencies on Gentoo and Debian respectively, and are simple to copy / change. + +When you make your changes, please be sure to test [[id:1CBE7325-A5A1-479B-9A98-BEEFBAC9D8FF][the elisp changes]] as well as [[id:5327945D-9D92-4462-8172-7237DEF4C359][the server code changes]] as described in the linked articles. + +** I am on a Macbook M1 and pdf-tools installation fails with a stack-trace +:PROPERTIES: +:CREATED: [2022-05-09 Mon 20:29] +:ID: 96D389D8-DD23-4FB0-996C-2D6F70A76BB2 +:END: +There have been a number of issues around ~pdf-tools~ installation problems on M1. =M-x pdf-tools-install= throws the following stack trace: +#+begin_example + 1 warning generated. + ld: warning: ignoring file /opt/homebrew/opt/gettext/lib/libintl.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/glib/2.72.1/lib/libglib-2.0.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/poppler/22.02.0/lib/libpoppler-glib.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/glib/2.72.1/lib/libgobject-2.0.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/poppler/22.02.0/lib/libpoppler.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/cairo/1.16.0_5/lib/libcairo.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/libpng/1.6.37/lib/libpng16.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + ld: warning: ignoring file /opt/homebrew/Cellar/zlib/1.2.11/lib/libz.dylib, building for macOS-x86_64 but attempting to link with file built for macOS-arm64 + Undefined symbols for architecture x86_64: +#+end_example + +This happens because M1 architecture is =ARM64=, whereas the Emacs App you are using has been compiled for the =x86_64= architecture. The way to solve this problem is to install a version of Emacs which has been compiled for the M1. As of today, [2022-05-09 Mon], the latest version of Emacs available on https://emacsformacosx.com/ is natively compiled and you will not face these issues on it. Please remove your current Emacs App and install it from https://emacsformacosx.com/. + +Thank you. + +PS: How do I know if the Emacs I'm running has been compiled correctly? + +You can see this by opening the =Activity Monitor=, selecting =Emacs=, clicking on the =Info= key, and then clicking on =Sample=. The =Code Type= field in the Sample output will show you how your Application has been compiled. Here is the output for EmacsForMacOSX (you can see that it's =ARM64=): +#+begin_example + Sampling process 61824 for 3 seconds with 1 millisecond of run time between samples + Sampling completed, processing symbols... + Analysis of sampling Emacs-arm64-11 (pid 61824) every 1 millisecond + Process: Emacs-arm64-11 [61824] + Path: /Applications/Emacs.app/Contents/MacOS/Emacs-arm64-11 + Load Address: 0x1007f0000 + Identifier: org.gnu.Emacs + Version: Version 28.1 (9.0) + Code Type: ARM64 + Platform: macOS +#+end_example + +If your Emacs is compiled for x86, the =Code Type= will be =x86_64=. + +** I am a developer, making changes to the pdf-tools source code +:PROPERTIES: +:CREATED: [2022-05-09 Mon 21:31] +:ID: 2D173424-C211-4474-B0D0-83F4381CAFFA +:END: +Thank you for taking the time to contribute back to the code. You may find some useful notes in the [[id:fd64c10c-4ea5-4ece-8d95-b723098dd4f6][Tips and Tricks for Developers]] section. Please be sure to check it out! diff --git a/elpa/pdf-tools-20191031.642/build/Makefile b/elpa/pdf-tools-20230611.239/build/Makefile similarity index 81% rename from elpa/pdf-tools-20191031.642/build/Makefile rename to elpa/pdf-tools-20230611.239/build/Makefile index 1b50fee9..e2bdc29c 100644 --- a/elpa/pdf-tools-20191031.642/build/Makefile +++ b/elpa/pdf-tools-20230611.239/build/Makefile @@ -1,4 +1,4 @@ - +CASK = cask EMACS ?= emacs # Handle the mess when inside Emacs. unexport INSIDE_EMACS #cask not like this. @@ -15,21 +15,26 @@ version=$(shell sed -ne 's/^;\+ *Version: *\([0-9.]\)/\1/p' lisp/pdf-tools.el) pkgname=pdf-tools-$(version) pkgfile=$(pkgname).tar -.PHONY: all clean distclean bytecompile test check melpa cask-install +.PHONY: all clean distclean bytecompile test check melpa all: $(pkgfile) # Create a elpa package including the server $(pkgfile): .cask/$(emacs_version) server/epdfinfo lisp/*.el - cask package . + $(CASK) package . # Compile the Lisp sources bytecompile: .cask/$(emacs_version) - cask exec $(emacs) --batch -L lisp -f batch-byte-compile lisp/*.el + $(CASK) exec $(emacs) --batch -L lisp -f batch-byte-compile lisp/*.el + +# Clean bytecompiled sources +byteclean: + rm -f -- lisp/*.elc + rm -f -- lisp/*.eln # Run ERT tests test: all - PACKAGE_TAR=$(pkgfile) cask exec ert-runner + PACKAGE_TAR=$(pkgfile) $(CASK) exec ert-runner check: test @@ -41,7 +46,7 @@ test-all: test test-autobuild # Init cask .cask/$(emacs_version): - cask install + $(CASK) install # Run the autobuild script (installing depends and compiling) autobuild: @@ -68,9 +73,8 @@ melpa-package: $(pkgfile) -f $(pkgname)-melpa.tar # Various clean targets -clean: server-clean +clean: server-clean byteclean rm -f -- $(pkgfile) - rm -f -- lisp/*.elc rm -f -- pdf-tools-readme.txt rm -f -- pdf-tools-$(version).entry @@ -95,3 +99,9 @@ server-clean: server-distclean: ! [ -f server/Makefile ] || $(MAKE) -C server distclean + +server-test-supported: server/test/Makefile + $(MAKE) -C server/test print + +server-test-unsupported: server/test/Makefile + $(MAKE) -C server/test print-failing diff --git a/elpa/pdf-tools-20191031.642/build/server/.gitignore b/elpa/pdf-tools-20230611.239/build/server/.gitignore similarity index 100% rename from elpa/pdf-tools-20191031.642/build/server/.gitignore rename to elpa/pdf-tools-20230611.239/build/server/.gitignore diff --git a/elpa/pdf-tools-20191031.642/build/server/Makefile.am b/elpa/pdf-tools-20230611.239/build/server/Makefile.am similarity index 73% rename from elpa/pdf-tools-20191031.642/build/server/Makefile.am rename to elpa/pdf-tools-20230611.239/build/server/Makefile.am index 5a5a7a65..b39e8051 100644 --- a/elpa/pdf-tools-20191031.642/build/server/Makefile.am +++ b/elpa/pdf-tools-20230611.239/build/server/Makefile.am @@ -1,28 +1,29 @@ bin_PROGRAMS = epdfinfo epdfinfo_CFLAGS = -Wall $(glib_CFLAGS) $(poppler_glib_CFLAGS) $(poppler_CFLAGS) \ $(png_CFLAGS) -epdfinfo_CXXFLAGS = -Wall $(epdfinfo_CFLAGS) +# Need -lm to link libm.so.6 epdfinfo_LDADD = $(glib_LIBS) $(poppler_glib_LIBS) $(poppler_LIBS) \ - $(png_LIBS) libsynctex.a $(zlib_LIBS) -epdfinfo_SOURCES = epdfinfo.c epdfinfo.h poppler-hack.cc + $(png_LIBS) libsynctex.a $(zlib_LIBS) -lm +epdfinfo_SOURCES = epdfinfo.c epdfinfo.h noinst_LIBRARIES = libsynctex.a libsynctex_a_SOURCES = synctex_parser.c synctex_parser_utils.c synctex_parser.h \ synctex_parser_local.h synctex_parser_utils.h -libsynctex_a_CFLAGS = -w $(zlib_CFLAGS) +libsynctex_a_CFLAGS = -w $(zlib_CFLAGS) -DSYNCTEX_USE_LOCAL_HEADER if HAVE_W32 epdfinfo_LDADD += -lshlwapi endif -SYNCTEX_UPSTREAM = svn://tug.org/texlive/tags/texlive-2017.1/Build/source/texk/web2c/synctexdir +SYNCTEX_UPSTREAM = svn://tug.org/texlive/trunk/Build/source/texk/web2c/synctexdir SYNCTEX_FILES = synctex_parser.c \ synctex_parser.h \ - synctex_parser_local.h \ synctex_parser_readme.txt \ synctex_parser_utils.c \ synctex_parser_utils.h \ - synctex_parser_version.txt + synctex_parser_version.txt \ + synctex_version.h \ + synctex_parser_advanced.h check-local: diff --git a/elpa/pdf-tools-20191031.642/build/server/autobuild b/elpa/pdf-tools-20230611.239/build/server/autobuild similarity index 77% rename from elpa/pdf-tools-20191031.642/build/server/autobuild rename to elpa/pdf-tools-20230611.239/build/server/autobuild index aa6b54c0..d5a594d2 100755 --- a/elpa/pdf-tools-20191031.642/build/server/autobuild +++ b/elpa/pdf-tools-20230611.239/build/server/autobuild @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env sh ## ## Installs package dependencies and builds the application. @@ -6,7 +6,7 @@ # Don't exit if some command fails. set +e -# Disalbe file globbing. +# Disable file globbing. set -f # Boolean variables are true if non-empty and false otherwise. @@ -64,16 +64,7 @@ which() if [ -z "$1" ]; then return 1 fi - IFS=: - for dir in $PATH; do - if [ -x "$dir/$1" ]; then - printf "%s" "$dir/$1" - unset IFS - return 0 - fi - done - unset IFS - return 1 + command -v "$1" } # Quote $@ for the shell. @@ -166,10 +157,6 @@ have_packages_installed() done which make || return 1 which gcc || which cc || return 1 - which g++ || which c++ || return 1 - cc $(pkg-config --cflags poppler) -o /dev/null -E - 2>/dev/null < -EOF [ $? -eq 0 ] || return 1 return 0 } >/dev/null 2>&1 @@ -232,7 +219,6 @@ os_centos() { PACKAGES="autoconf automake gcc - gcc-c++ libpng-devel make pkgconfig @@ -253,6 +239,17 @@ os_freebsd() { return 0 } +# NetBSD +os_netbsd() { + if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "NetBSD" ]; then + return 1 + fi + PKGCMD=pkgin + PKGARGS=install + PACKAGES="autoconf automake poppler-glib png pkgconf" + return 0 +} + # OpenBSD os_openbsd() { if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "OpenBSD" ]; then @@ -260,18 +257,9 @@ os_openbsd() { fi PKGCMD=pkg_add PKGARGS="-uU" - PACKAGES="autoconf-2.69p2 automake-1.15.1 poppler poppler-utils png" + PACKAGES="autoconf%2.69 automake%1.15 poppler poppler-utils png" export AUTOCONF_VERSION=2.69 export AUTOMAKE_VERSION=1.15 - if whereis clang++ ;then - export CXX=clang++ - elif whereis eg++ ;then - export CXX=eg++ - else - export CXX=eg++ - PACKAGES="${PACKAGES} g++" - fi - export CXXFLAGS="-std=c++11 -I/usr/local/include/poppler -I/usr/local/include" return 0 } @@ -285,7 +273,6 @@ os_fedora() { PACKAGES="autoconf automake gcc - gcc-c++ libpng-devel make poppler-devel @@ -307,17 +294,15 @@ os_debian() { fi PACKAGES="autoconf automake - g++ gcc libpng-dev libpoppler-dev libpoppler-glib-dev - libpoppler-private-dev libz-dev make pkg-config" PKGCMD=apt-get - PKGARGS=install + PKGARGS="install -y" return 0 } @@ -329,15 +314,23 @@ os_msys2() { case $MSYSTEM in MINGW64) PACKAGES="base-devel + autoconf + automake mingw-w64-x86_64-libpng mingw-w64-x86_64-poppler + mingw-w64-x86_64-imagemagick mingw-w64-x86_64-toolchain + mingw-w64-x86_64-openssl mingw-w64-x86_64-zlib" ;; MINGW32) PACKAGES="base-devel + autoconf + automake mingw-w64-i686-libpng mingw-w64-i686-poppler + mingw-w64-i686-imagemagick mingw-w64-i686-toolchain + mingw-w64-i686-openssl mingw-w64-i686-zlib" ;; MSYS) case $(uname -m) in @@ -367,15 +360,15 @@ os_macos() { elif which brew >/dev/null 2>&1; then PKGCMD=brew PKGARGS=install - PACKAGES="pkg-config poppler automake" + PACKAGES="pkg-config poppler autoconf automake" PKG_INSTALL_AS_ROOT= - # homebrew install libffi as keg-only, meaning we need to set + # brew installs libffi as keg-only, meaning we need to set # PKG_CONFIG_PATH manually so configure can find it - export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig/" + export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:$(brew --prefix libffi)/lib/pkgconfig/:$(brew --prefix zlib)/lib/pkgconfig/" elif which port >/dev/null 2>&1; then PKGCMD=port PKGARGS=install - PACKAGES="pkgconfig poppler automake libpng" + PACKAGES="pkgconfig poppler autoconf automake libpng" else return 1 fi @@ -394,11 +387,15 @@ os_nixos() { if [ -n "$DRY_RUN" ]; then return 0 fi + if ! nix-instantiate --eval -E "" &>/dev/null; then + echo "File 'nixpkgs' was not found in the Nix path. Using NixOS/nixpkgs" + NIX_PATH="nixpkgs=https://github.com/nixos/nixpkgs/archive/master.tar.gz:$NIX_PATH" + fi command="AUTOBUILD_NIX_SHELL=true" command="$command;export AUTOBUILD_NIX_SHELL" command="$command;$(quote "$0" "$@")" - exec nix-shell --pure --command "$command" \ - -p gcc gnumake automake autoconf pkgconfig libpng zlib poppler + exec nix-shell --pure --run "$command" \ + -p automake autoconf pkg-config libpng zlib poppler } # Gentoo @@ -409,16 +406,90 @@ os_gentoo() { PKGCMD=emerge PKGARGS=--noreplace PACKAGES="app-text/poppler - dev-util/pkgconfig + dev-util/pkgconf media-libs/libpng sys-devel/autoconf sys-devel/automake sys-devel/gcc sys-devel/make + sys-libs/glibc sys-libs/zlib" return 0 } +# Void +os_void() { + if [ -f "/etc/os-release" ]; then + . /etc/os-release + if [ "$ID" != "void" ]; then + return 1 + fi + else + return 1 + fi + PACKAGES="autoconf + automake + libpng-devel + poppler-devel + poppler-glib-devel + zlib-devel + make + pkgconf + cairo-devel" + PKGCMD=xbps-install + PKGARGS="-Sy" + export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/lib/pkgconfig" + return 0 +} + +# openSUSE (TODO: add support for micro versions) +os_opensuse() { + if [ -f "/etc/os-release" ]; then + . /etc/os-release + if [ "$ID" != "opensuse-leap" ] && [ "$ID" != "opensuse-tumbleweed" ]; then + return 1 + fi + else + return 1 + fi + PACKAGES="make + automake + autoconf + gcc + libpng16-devel + libpng16-compat-devel + zlib-devel + libpoppler-devel + libpoppler-glib-devel + glib2-devel + pkgconf" + PKGCMD=zypper + PKGARGS="install" + return 0 +} + +# Alpine Linux +os_alpine() { + if [ -f "/etc/os-release" ]; then + . /etc/os-release + if [ "$ID" != "alpine" ]; then + return 1 + fi + else + return 1 + fi + PACKAGES="autoconf + automake + libpng-dev + poppler-dev + glib-dev + gcc + build-base" + PKGCMD=apk + PKGARGS="add" + return 0 +} + # By Parameter --os os_argument() { [ -z "$OS" ] && return 1 @@ -427,12 +498,16 @@ os_argument() { freebsd) os_freebsd "$@";; arch) os_arch "$@";; centos) os_centos "$@";; + netbsd) os_netbsd "$@";; openbsd) os_openbsd "$@";; fedora) os_fedora "$@";; debian) os_debian "$@";; gentoo) os_gentoo "$@";; msys2) os_msys2 "$@";; nixos) os_nixos "$@";; + void) os_void "$@";; + opensuse) os_opensuse "$@";; + alpine) os_alpine "$@";; *) echo "Invalid --os argument: $OS" exit 1 esac || { @@ -442,7 +517,8 @@ os_argument() { } ## +-----------------------------------------------------------+ -## * Figure out were we are, install deps and build the program +## * Figure out where we are +## ** install deps and build the program ## +-----------------------------------------------------------+ handle_options "$@" @@ -452,12 +528,16 @@ os_macos "$@" || \ os_freebsd "$@" || \ os_arch "$@" || \ os_centos "$@" || \ +os_netbsd "$@" || \ os_openbsd "$@" || \ os_fedora "$@" || \ os_debian "$@" || \ os_gentoo "$@" || \ os_msys2 "$@" || \ os_nixos "$@" || \ +os_void "$@" || \ +os_opensuse "$@" || \ +os_alpine "$@" || \ { OS_IS_HANDLED= if [ -z "$DRY_RUN" ]; then @@ -490,10 +570,6 @@ if [ -n "$PKGCMD" ];then echo fi -echo "---------------------------" -echo " Configuring and compiling " -echo "---------------------------" - # Try to be in the correct directory. if which dirname >/dev/null 2>&1; then cd "$(dirname "$0")" || { @@ -502,6 +578,10 @@ if which dirname >/dev/null 2>&1; then } fi +echo "---------------------------" +echo " Configuring and compiling " +echo "---------------------------" + # Create the configure script. if ! [ -f ./configure ]; then assert_program autoreconf @@ -515,8 +595,8 @@ if [ -n "$INSTALL_DIR" ]; then prefix=--bindir=$INSTALL_DIR fi -echo "./configure -q $prefix && make -s" -eval "./configure -q $(quote "$prefix") && make -s || exit_fail" +echo "./configure -q $prefix && make clean && make -s" +eval "./configure -q $(quote "$prefix") && make clean && make -s || exit_fail" echo if [ -n "$INSTALL_DIR" ]; then echo "---------------------------" diff --git a/elpa/pdf-tools-20191031.642/build/server/autogen.sh b/elpa/pdf-tools-20230611.239/build/server/autogen.sh similarity index 100% rename from elpa/pdf-tools-20191031.642/build/server/autogen.sh rename to elpa/pdf-tools-20230611.239/build/server/autogen.sh diff --git a/elpa/pdf-tools-20191031.642/build/server/configure.ac b/elpa/pdf-tools-20230611.239/build/server/configure.ac similarity index 85% rename from elpa/pdf-tools-20191031.642/build/server/configure.ac rename to elpa/pdf-tools-20230611.239/build/server/configure.ac index ae1255f1..9a8c46db 100644 --- a/elpa/pdf-tools-20191031.642/build/server/configure.ac +++ b/elpa/pdf-tools-20230611.239/build/server/configure.ac @@ -10,7 +10,6 @@ AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O -AC_PROG_CXX AC_PROG_RANLIB AM_PROG_AR @@ -43,22 +42,6 @@ if test "$have_w32" = true; then fi fi -SAVED_CPPFLAGS=$CPPFLAGS -CPPFLAGS=$poppler_CFLAGS -AC_LANG_PUSH([C++]) -# Check if we can use the -std=c++11 option. -m4_include([m4/ax_check_compile_flag.m4]) -AX_CHECK_COMPILE_FLAG([-std=c++11], [HAVE_STD_CXX11=yes]) - -if test "$HAVE_STD_CXX11" = yes; then - CXXFLAGS="-std=c++11 $CXXFLAGS" -fi -# Check for private poppler header. -AC_CHECK_HEADERS([Annot.h PDFDocEncoding.h], [], - AC_MSG_ERROR([cannot find necessary poppler-private header (see README.org)])) -AC_LANG_POP([C++]) -CPPFLAGS=$SAVED_CPPFLAGS - # Setup compile time features. if test "$HAVE_POPPLER_FIND_OPTS" = yes; then AC_DEFINE([HAVE_POPPLER_FIND_OPTS],1, @@ -86,7 +69,7 @@ AC_LANG_PUSH([C]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ #include ],[error (0, 0, "");])], - [AC_DEFINE([HAVE_ERROR_H],1, [Define to 1 if error.h is useable.]) + [AC_DEFINE([HAVE_ERROR_H],1, [Define to 1 if error.h is usable.]) AC_MSG_RESULT([yes])], AC_MSG_RESULT([no])) AC_LANG_POP([C]) diff --git a/elpa/pdf-tools-20191031.642/build/server/epdfinfo.c b/elpa/pdf-tools-20230611.239/build/server/epdfinfo.c similarity index 89% rename from elpa/pdf-tools-20191031.642/build/server/epdfinfo.c rename to elpa/pdf-tools-20230611.239/build/server/epdfinfo.c index 86d92009..b3925d0e 100644 --- a/elpa/pdf-tools-20191031.642/build/server/epdfinfo.c +++ b/elpa/pdf-tools-20230611.239/build/server/epdfinfo.c @@ -339,7 +339,7 @@ strchomp (char *str) } /** - * Create a new, temporary file and returns it's name. + * Create a new, temporary file and returns its name. * * @return The filename. */ @@ -354,7 +354,7 @@ mktempfile() filename = tempnam(NULL, "epdfinfo"); if (filename) { - int fd = open(filename, O_CREAT | O_EXCL | O_RDONLY, S_IRWXU); + int fd = open(filename, O_CREAT | O_EXCL | O_RDONLY, S_IRUSR | S_IWUSR); if (fd > 0) close (fd); else @@ -370,17 +370,122 @@ mktempfile() return filename; } +/* Holds RGB, HSL, HSV, Lab, or Lch... but note that the order in memory for HSL + * and HSV are actually VSH and LSH. */ +struct color +{ + union + { + double r, v, l; + }; + union + { + double g, s, a; + }; + union + { + double b, h; + }; +}; + +#define struct_color(x) (*((struct color *) x)) +#define vec_color(x) ((double *) &x) + +// Using values reported at https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab +// instead of going through xyz. This ensures any whitepoint is ignored +static struct color +rgb2oklab(struct color rgb) +{ + struct color srgb; + + for (int i = 0; i < 3; i++) + { + double val = vec_color(rgb)[i]; + vec_color(srgb)[i] = ((val > 0.04045) + ? pow((val + 0.055) / 1.055, 2.4) + : (val / 12.92)); + } + + double l = 0.4121656120 * srgb.r + 0.5362752080 * srgb.g + 0.0514575653 * srgb.b; + double m = 0.2118591070 * srgb.r + 0.6807189584 * srgb.g + 0.1074065790 * srgb.b; + double s = 0.0883097947 * srgb.r + 0.2818474174 * srgb.g + 0.6302613616 * srgb.b; + + l = cbrt(l); + m = cbrt(m); + s = cbrt(s); + + return (struct color) { + .l = 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s, + .a = 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s, + .b = 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s + }; +} + +static double clamp(double x, double low, double high) +{ + return ((x < low) + ? low + : ((x > high) ? high : x)); +} + +static struct color +oklab2rgb(struct color lab) +{ + double l = lab.l + 0.3963377774 * lab.a + 0.2158037573 * lab.b; + double m = lab.l - 0.1055613458 * lab.a - 0.0638541728 * lab.b; + double s = lab.l - 0.0894841775 * lab.a - 1.2914855480 * lab.b; + + l = l * l * l; + m = m * m * m; + s = s * s * s; + + struct color srgb = { + .r = 4.0767245293 * l - 3.3072168827 * m + 0.2307590544 * s, + .g = -1.2681437731 * l + 2.6093323231 * m - 0.3411344290 * s, + .b = -0.0041119885 * l - 0.7034763098 * m + 1.7068625689 * s + }; + + struct color rgb; + for (int i = 0; i < 3; i++) + { + double val = vec_color(srgb)[i]; + val = ((val > 0.0031308) + ? (1.055 * pow(val, 1 / 2.4) - 0.055) + : (12.92 * val)); + + vec_color(rgb)[i] = clamp(val, 0.0, 1.0); + } + + return rgb; +} + +#undef struct_color +#undef vec_color + +static inline gboolean color_equal(struct color a, struct color b) +{ + return (a.r == b.r && a.g == b.g && a.b == b.b); +} + static void image_recolor (cairo_surface_t * surface, const PopplerColor * fg, - const PopplerColor * bg) + const PopplerColor * bg, int usecolors) { - /* uses a representation of a rgb color as follows: - - a lightness scalar (between 0,1), which is a weighted average of r, g, b, - - a hue vector, which indicates a radian direction from the grey axis, - inside the equal lightness plane. - - a saturation scalar between 0,1. It is 0 when grey, 1 when the color is - in the boundary of the rgb cube. - */ + /* Performs one of two kinds of image recoloring depending on the value of usecolors: + + 1 -> Bg-Fg Interpolation: maps source document colors to colors + interpolated between the background and foreground values in + pdf-view-midnight-colors via the lightness of the source color. This + discards hue information but allows you to fit your color theme + perfectly. + + 2 -> Hue-Preserving interpolation: same as above, similar to above, but + attempts to preserve hue while still respecting the background and + foreground colors. This is done by matching source document white and + black to the specified background and foreground as above, but mixes + hue/saturation with the background color. This preserves hue but is + more expensive. + */ const unsigned int page_width = cairo_image_surface_get_width (surface); const unsigned int page_height = cairo_image_surface_get_height (surface); @@ -391,46 +496,131 @@ image_recolor (cairo_surface_t * surface, const PopplerColor * fg, static const double a[] = { 0.30, 0.59, 0.11 }; const double f = 65535.; - const double rgb_fg[] = { - fg->red / f, fg->green / f, fg->blue / f + const struct color rgb_fg = { + .r = fg->red / f, + .g = fg->green / f, + .b = fg->blue / f }; - const double rgb_bg[] = { - bg->red / f, bg->green / f, bg->blue / f + const struct color rgb_bg = { + .r = bg->red / f, + .g = bg->green / f, + .b = bg->blue / f }; - const double rgb_diff[] = { - rgb_bg[0] - rgb_fg[0], - rgb_bg[1] - rgb_fg[1], - rgb_bg[2] - rgb_fg[2] + const struct color rgb_diff = { + .r = rgb_bg.r - rgb_fg.r, + .g = rgb_bg.g - rgb_fg.g, + .b = rgb_bg.b - rgb_fg.b }; - unsigned int y; - for (y = 0; y < page_height * rowstride; y += rowstride) + switch (usecolors) { - unsigned char *data = image + y; + case 0: + break; + case 1: + { + unsigned int y; + for (y = 0; y < page_height * rowstride; y += rowstride) + { + unsigned char *data = image + y; - unsigned int x; - for (x = 0; x < page_width; x++, data += 4) - { - /* Careful. data color components blue, green, red. */ - const double rgb[3] = { - (double) data[2] / 256., - (double) data[1] / 256., - (double) data[0] / 256. - }; + unsigned int x; + for (x = 0; x < page_width; x++, data += 4) + { + /* Careful. data color components blue, green, red. */ + struct color rgb = { + .r = (double) data[2] / 256., + .g = (double) data[1] / 256., + .b = (double) data[0] / 256. + }; + + /* Linear interpolation between bg and fg based on the + perceptual lightness measure l */ + /* compute h, s, l data */ + double l = a[0] * rgb.r + a[1] * rgb.g + a[2] * rgb.b; + + /* linear interpolation between dark and light with color + lightness as a parameter */ + data[2] = + (unsigned char) round (255. * (l * rgb_diff.r + rgb_fg.r)); + data[1] = + (unsigned char) round (255. * (l * rgb_diff.g + rgb_fg.g)); + data[0] = + (unsigned char) round (255. * (l * rgb_diff.b + rgb_fg.b)); + } + } + } + break; + case 2: + { + /* If using the Oklab transform, it is relatively expensive. Precompute + white->background and black->foreground and have a single entry cache to + speed up computation */ + const struct color white = {.r = 1.0, .g = 1.0, .b = 1.0}; + struct color precomputed_rgb = white; + struct color precomputed_inv_rgb = rgb_bg; - /* compute h, s, l data */ - double l = a[0] * rgb[0] + a[1] * rgb[1] + a[2] * rgb[2]; + /* Must match the transformation of colors below. */ + struct color oklab_fg = rgb2oklab(rgb_fg); + struct color oklab_bg = rgb2oklab(rgb_bg); - /* linear interpolation between dark and light with color ligtness as - * a parameter */ - data[2] = - (unsigned char) round (255. * (l * rgb_diff[0] + rgb_fg[0])); - data[1] = - (unsigned char) round (255. * (l * rgb_diff[1] + rgb_fg[1])); - data[0] = - (unsigned char) round (255. * (l * rgb_diff[2] + rgb_fg[2])); - } + const double oklab_diff_l = oklab_fg.l - oklab_bg.l; + + unsigned int y; + for (y = 0; y < page_height * rowstride; y += rowstride) + { + unsigned char *data = image + y; + + unsigned int x; + for (x = 0; x < page_width; x++, data += 4) + { + /* Careful. data color components blue, green, red. */ + struct color rgb = { + .r = (double) data[2] / 256., + .g = (double) data[1] / 256., + .b = (double) data[0] / 256. + }; + + /* Convert to Oklab coordinates, invert perceived lightness, + convert back to RGB. */ + if (color_equal(white, rgb)) + { + rgb = rgb_bg; + } + else if (color_equal(precomputed_rgb, rgb)) + { + rgb = precomputed_inv_rgb; + } + else + { + struct color oklab = rgb2oklab(rgb); + precomputed_rgb = rgb; + + /* Invert the perceived lightness, and scales it */ + double l = oklab.l; + double inv_l = 1.0 - l; + oklab.l = oklab_bg.l + oklab_diff_l * inv_l; + + /* Have a and b parameters (which encode hue and saturation) + start at the background value and interpolate up to + foreground */ + oklab.a = (oklab.a + oklab_bg.a * l + oklab_fg.a * inv_l); + oklab.b = (oklab.b + oklab_bg.b * l + oklab_fg.b * inv_l); + + rgb = oklab2rgb(oklab); + + precomputed_inv_rgb = rgb; + } + + data[2] = (unsigned char) round(255. * rgb.r); + data[1] = (unsigned char) round(255. * rgb.g); + data[0] = (unsigned char) round(255. * rgb.b); + } + } + } + break; + default: + internal_error ("image_recolor switch fell through"); } } @@ -501,8 +691,8 @@ image_render_page(PopplerDocument *pdf, PopplerPage *page, cairo_paint (cr); - if (options && options->usecolors) - image_recolor (surface, &options->fg, &options->bg); + if (options && (options->usecolors)) + image_recolor (surface, &options->fg, &options->bg, options->usecolors); cairo_destroy (cr); @@ -672,7 +862,7 @@ region_print (cairo_region_t *region, double width, double height) * * @param type The PopplerActionType. * - * @return It's string representation. + * @return Its string representation. */ static const char * xpoppler_action_type_string(PopplerActionType type) @@ -699,7 +889,7 @@ xpoppler_action_type_string(PopplerActionType type) * * @param type The PopplerAnnotType. * - * @return It's string representation. + * @return Its string representation. */ static const char * xpoppler_annot_type_string (PopplerAnnotType type) @@ -741,7 +931,7 @@ xpoppler_annot_type_string (PopplerAnnotType type) * * @param type The PopplerAnnotTextState. * - * @return It's string representation. + * @return Its string representation. */ static const char * xpoppler_annot_text_state_string (PopplerAnnotTextState state) @@ -760,6 +950,26 @@ xpoppler_annot_text_state_string (PopplerAnnotTextState state) } }; +/** + * Validate a PopplerSelectionStyle by replacing invalid styles + * with a default of POPPLER_SELECTION_GLYPH. + * + * @param selection_style The selection style. + * + * @return selection_style for valid styles, otherwise POPPLER_SELECTION_GLYPH. + */ +static PopplerSelectionStyle +xpoppler_validate_selection_style (int selection_style) +{ + switch (selection_style) { + case POPPLER_SELECTION_GLYPH: + case POPPLER_SELECTION_WORD: + case POPPLER_SELECTION_LINE: + return selection_style; + } + return POPPLER_SELECTION_GLYPH; +} + static document_t* document_open (const epdfinfo_t *ctx, const char *filename, const char *passwd, GError **gerror) @@ -1309,25 +1519,6 @@ annotation_get_by_key (document_t *doc, const gchar *key) } #ifdef HAVE_POPPLER_ANNOT_MARKUP -void -annotation_translate_quadrilateral (PopplerPage *page, PopplerQuadrilateral *q, gboolean inverse) -{ - PopplerRectangle cbox; - gdouble xs, ys; - - poppler_page_get_crop_box (page, &cbox); - xs = MIN (cbox.x1, cbox.x2); - ys = MIN (cbox.y1, cbox.y2); - - if (inverse) - { - xs = -xs; ys = -ys; - } - - q->p1.x -= xs, q->p2.x -= xs; q->p3.x -= xs; q->p4.x -= xs; - q->p1.y -= ys, q->p2.y -= ys; q->p3.y -= ys; q->p4.y -= ys; -} - static cairo_region_t* annotation_markup_get_text_regions (PopplerPage *page, PopplerAnnotTextMarkup *a) { @@ -1343,7 +1534,6 @@ annotation_markup_get_text_regions (PopplerPage *page, PopplerAnnotTextMarkup *a PopplerQuadrilateral *q = &g_array_index (quads, PopplerQuadrilateral, i); cairo_rectangle_int_t r; - annotation_translate_quadrilateral (page, q, FALSE); q->p1.y = height - q->p1.y; q->p2.y = height - q->p2.y; q->p3.y = height - q->p3.y; @@ -1367,12 +1557,15 @@ annotation_markup_get_text_regions (PopplerPage *page, PopplerAnnotTextMarkup *a * * @param page The page of the annotation. This is used to get the * text regions and pagesize. + * @param selection_style The selection style. * @param region The region to add. * @param garray[in,out] An array of PopplerQuadrilateral, where the * new quadrilaterals will be appended. */ static void -annotation_markup_append_text_region (PopplerPage *page, PopplerRectangle *region, +annotation_markup_append_text_region (PopplerPage *page, + PopplerSelectionStyle selection_style, + PopplerRectangle *region, GArray *garray) { gdouble height; @@ -1380,7 +1573,7 @@ annotation_markup_append_text_region (PopplerPage *page, PopplerRectangle *regio replacement. (poppler_page_get_selected_region returns a union of rectangles.) */ GList *regions = - poppler_page_get_selection_region (page, 1.0, POPPLER_SELECTION_GLYPH, region); + poppler_page_get_selection_region (page, 1.0, selection_style, region); GList *item; poppler_page_get_size (page, NULL, &height); @@ -1398,7 +1591,6 @@ annotation_markup_append_text_region (PopplerPage *page, PopplerRectangle *regio q.p3.x = r->x1; q.p3.y = height - r->y2; - annotation_translate_quadrilateral (page, &q, TRUE); g_array_append_val (garray, q); } g_list_free (regions); @@ -1410,6 +1602,7 @@ annotation_markup_append_text_region (PopplerPage *page, PopplerRectangle *regio * * @param doc The document for which to create it. * @param type The type of the annotation. + * @param selection_style The selection style. * @param r The rectangle where annotation will end up on the page. * * @return The new annotation, or NULL, if the annotation type is @@ -1417,8 +1610,9 @@ annotation_markup_append_text_region (PopplerPage *page, PopplerRectangle *regio */ static PopplerAnnot* annotation_new (const epdfinfo_t *ctx, document_t *doc, PopplerPage *page, - const char *type, PopplerRectangle *r, - const command_arg_t *rest, char **error_msg) + const char *type, PopplerSelectionStyle selection_style, + PopplerRectangle *r, const command_arg_t *rest, + char **error_msg) { PopplerAnnot *a = NULL; @@ -1441,6 +1635,21 @@ annotation_new (const epdfinfo_t *ctx, document_t *doc, PopplerPage *page, #ifdef HAVE_POPPLER_ANNOT_MARKUP garray = g_array_new (FALSE, FALSE, sizeof (PopplerQuadrilateral)); poppler_page_get_size (page, &width, &height); + if (nargs == 0) + { + PopplerQuadrilateral q; + + q.p1.x = r->x1; + q.p1.y = r->y1; + q.p2.x = r->x2; + q.p2.y = r->y1; + q.p4.x = r->x2; + q.p4.y = r->y2; + q.p3.x = r->x1; + q.p3.y = r->y2; + + g_array_append_val (garray, q); + } for (i = 0; i < nargs; ++i) { PopplerRectangle *rr = &carg.value.rectangle; @@ -1449,7 +1658,7 @@ annotation_new (const epdfinfo_t *ctx, document_t *doc, PopplerPage *page, ARG_EDGES, error_msg)); rr->x1 *= width; rr->x2 *= width; rr->y1 *= height; rr->y2 *= height; - annotation_markup_append_text_region (page, rr, garray); + annotation_markup_append_text_region (page, selection_style, rr, garray); } cerror_if_not (garray->len > 0, error_msg, "%s", "Unable to create empty markup annotation"); @@ -1567,6 +1776,7 @@ annotation_print (const annotation_t *annot, /* const */ PopplerPage *page) gchar *text; gdouble opacity; cairo_region_t *region = NULL; + GDate *date; if (! annot || ! page) return; @@ -1668,11 +1878,13 @@ annotation_print (const annotation_t *annot, /* const */ PopplerPage *page) printf ("::"); /* Creation Date */ - text = xpoppler_annot_markup_get_created (ma); - if (text) + date = poppler_annot_markup_get_date (ma); + if (date != NULL && g_date_valid(date)) { - print_response_string (text, NONE); - g_free (text); + gchar datebuf[128]; + g_date_strftime (datebuf, 127, "%x", date); + print_response_string (datebuf, NONE); + g_date_free (date); } /* <<< Markup Annotation <<< */ @@ -2337,14 +2549,7 @@ cmd_gettext(const epdfinfo_t *ctx, const command_arg_t *args) double width, height; gchar *text = NULL; - switch (selection_style) - { - case POPPLER_SELECTION_GLYPH: break; - case POPPLER_SELECTION_LINE: break; - case POPPLER_SELECTION_WORD: break; - default: selection_style = POPPLER_SELECTION_GLYPH; - } - + selection_style = xpoppler_validate_selection_style (selection_style); page = poppler_document_get_page (doc, pn - 1); perror_if_not (page, "No such page %d", pn); poppler_page_get_size (page, &width, &height); @@ -2386,7 +2591,7 @@ const command_arg_type_t cmd_getselection_spec[] = { ARG_DOC, ARG_NATNUM, /* page number */ - ARG_EDGES, /* selection */ + ARG_EDGES, /* selection */ ARG_NATNUM /* selection-style */ }; @@ -2402,14 +2607,7 @@ cmd_getselection (const epdfinfo_t *ctx, const command_arg_t *args) PopplerPage *page = NULL; int i; - switch (selection_style) - { - case POPPLER_SELECTION_GLYPH: break; - case POPPLER_SELECTION_LINE: break; - case POPPLER_SELECTION_WORD: break; - default: selection_style = POPPLER_SELECTION_GLYPH; - } - + selection_style = xpoppler_validate_selection_style (selection_style); page = poppler_document_get_page (doc, pn - 1); perror_if_not (page, "No such page %d", pn); poppler_page_get_size (page, &width, &height); @@ -2662,6 +2860,7 @@ const command_arg_type_t cmd_addannot_spec[] = ARG_DOC, ARG_NATNUM, /* page number */ ARG_STRING, /* type */ + ARG_NATNUM, /* selection-style */ ARG_EDGES_OR_POSITION, /* edges or position (uses default size) */ ARG_REST, /* markup regions */ }; @@ -2673,7 +2872,8 @@ cmd_addannot (const epdfinfo_t *ctx, const command_arg_t *args) document_t *doc = args->value.doc; gint pn = args[1].value.natnum; const char *type_string = args[2].value.string; - PopplerRectangle r = args[3].value.rectangle; + int selection_style = args[3].value.natnum; + PopplerRectangle r = args[4].value.rectangle; int i; PopplerPage *page = NULL; double width, height; @@ -2685,6 +2885,7 @@ cmd_addannot (const epdfinfo_t *ctx, const command_arg_t *args) gdouble y2; char *error_msg = NULL; + selection_style = xpoppler_validate_selection_style (selection_style); page = poppler_document_get_page (doc->pdf, pn - 1); perror_if_not (page, "Unable to get page %d", pn); poppler_page_get_size (page, &width, &height); @@ -2698,7 +2899,8 @@ cmd_addannot (const epdfinfo_t *ctx, const command_arg_t *args) r.y2 = height - r.y1; r.y1 = height - y2; - pa = annotation_new (ctx, doc, page, type_string, &r, &args[4], &error_msg); + pa = annotation_new (ctx, doc, page, type_string, selection_style, &r, &args[5], + &error_msg); perror_if_not (pa, "Creating annotation failed: %s", error_msg ? error_msg : "Reason unknown"); amap = poppler_annot_mapping_new (); @@ -2848,7 +3050,7 @@ cmd_editannot (const epdfinfo_t *ctx, const command_arg_t *args) area->x1 = r.x1 * width; area->y2 = height - (r.y1 * height); - xpoppler_annot_set_rectangle (pa, area); + poppler_annot_set_rectangle (pa, area); } else if (! strcmp (key, "label")) { @@ -2971,8 +3173,8 @@ cmd_synctex_forward_search (const epdfinfo_t *ctx, const command_arg_t *args) const char *source = args[1].value.string; int line = args[2].value.natnum; int column = args[3].value.natnum; - synctex_scanner_t scanner = NULL; - synctex_node_t node; + synctex_scanner_p scanner = NULL; + synctex_node_p node; float x1, y1, x2, y2; PopplerPage *page = NULL; double width, height; @@ -2982,8 +3184,8 @@ cmd_synctex_forward_search (const epdfinfo_t *ctx, const command_arg_t *args) perror_if_not (scanner, "Unable to create synctex scanner,\ did you run latex with `--synctex=1' ?"); - perror_if_not (synctex_display_query (scanner, source, line, column) - && (node = synctex_next_result (scanner)), + perror_if_not (synctex_display_query (scanner, source, line, column, 0) + && (node = synctex_scanner_next_result (scanner)), "Destination not found"); pn = synctex_node_page (node); @@ -3026,10 +3228,10 @@ cmd_synctex_backward_search (const epdfinfo_t *ctx, const command_arg_t *args) int pn = args[1].value.natnum; double x = args[2].value.edge; double y = args[3].value.edge; - synctex_scanner_t scanner = NULL; + synctex_scanner_p scanner = NULL; const char *filename; PopplerPage *page = NULL; - synctex_node_t node; + synctex_node_p node; double width, height; int line, column; @@ -3044,7 +3246,7 @@ cmd_synctex_backward_search (const epdfinfo_t *ctx, const command_arg_t *args) y = y * height; if (! synctex_edit_query (scanner, pn, x, y) - || ! (node = synctex_next_result (scanner)) + || ! (node = synctex_scanner_next_result (scanner)) || ! (filename = synctex_scanner_get_name (scanner, synctex_node_tag (node)))) { @@ -3092,6 +3294,7 @@ cmd_renderpage (const epdfinfo_t *ctx, const command_arg_t *args) PopplerColor bg = { 65535, 0, 0 }; double alpha = 1.0; double line_width = 1.5; + PopplerSelectionStyle selection_style = POPPLER_SELECTION_GLYPH; PopplerRectangle cb = {0.0, 0.0, 1.0, 1.0}; int i = 0; @@ -3220,10 +3423,18 @@ cmd_renderpage (const epdfinfo_t *ctx, const command_arg_t *args) } poppler_page_render_selection (page, cr, r, NULL, - POPPLER_SELECTION_GLYPH, &fg, &bg); + selection_style, &fg, &bg); } } } + else if (! strcmp (keyword, ":selection-style")) + { + perror_if_not (command_arg_parse_arg (ctx, rest_args[i], &rest_arg, + ARG_NATNUM, &error_msg), + "%s", error_msg); + ++i; + selection_style = xpoppler_validate_selection_style (rest_arg.value.natnum); + } else perror_if_not (0, "Unknown render command: %s", keyword); } @@ -3438,7 +3649,7 @@ cmd_charlayout(const epdfinfo_t *ctx, const command_arg_t *args) const document_option_t document_options [] = { - DEC_DOPT (":render/usecolors", ARG_BOOL, render.usecolors), + DEC_DOPT (":render/usecolors", ARG_NATNUM, render.usecolors), DEC_DOPT (":render/printed", ARG_BOOL, render.printed), DEC_DOPT (":render/foreground", ARG_COLOR, render.fg), DEC_DOPT (":render/background", ARG_COLOR, render.bg), @@ -3581,7 +3792,7 @@ static const command_t commands [] = DEC_CMD2 (search_regexp, "search-regexp"), DEC_CMD2 (regexp_flags, "regexp-flags"), - /* General Informations */ + /* General Information */ DEC_CMD (metadata), DEC_CMD (outline), DEC_CMD2 (number_of_pages, "number-of-pages"), @@ -3592,7 +3803,7 @@ static const command_t commands [] = DEC_CMD (boundingbox), DEC_CMD (charlayout), - /* General Informations */ + /* General Information */ DEC_CMD (metadata), DEC_CMD (outline), DEC_CMD2 (number_of_pages, "number-of-pages"), diff --git a/elpa/pdf-tools-20191031.642/build/server/epdfinfo.h b/elpa/pdf-tools-20230611.239/build/server/epdfinfo.h similarity index 97% rename from elpa/pdf-tools-20191031.642/build/server/epdfinfo.h rename to elpa/pdf-tools-20230611.239/build/server/epdfinfo.h index 9f80cfd2..542b5776 100644 --- a/elpa/pdf-tools-20191031.642/build/server/epdfinfo.h +++ b/elpa/pdf-tools-20230611.239/build/server/epdfinfo.h @@ -243,10 +243,4 @@ typedef struct const command_arg_type_t *args_spec; int nargs; } command_t; - -/* Defined in poppler-hack.cc */ -#ifdef HAVE_POPPLER_ANNOT_WRITE -extern void xpoppler_annot_set_rectangle (PopplerAnnot*, PopplerRectangle*); -#endif -extern gchar *xpoppler_annot_markup_get_created (PopplerAnnotMarkup*); #endif /* _EPDF_H_ */ diff --git a/elpa/pdf-tools-20191031.642/build/server/poppler-versions b/elpa/pdf-tools-20230611.239/build/server/poppler-versions similarity index 100% rename from elpa/pdf-tools-20191031.642/build/server/poppler-versions rename to elpa/pdf-tools-20230611.239/build/server/poppler-versions diff --git a/elpa/pdf-tools-20230611.239/build/server/synctex_parser.c b/elpa/pdf-tools-20230611.239/build/server/synctex_parser.c new file mode 100644 index 00000000..27be6089 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser.c @@ -0,0 +1,8924 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + + Acknowledgments: + ---------------- + The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, + and significant help from XeTeX developer Jonathan Kew + + Nota Bene: + ---------- + If you include or use a significant part of the synctex package into a software, + I would appreciate to be listed as contributor and see "SyncTeX" highlighted. + + */ + +/* We assume that high level application like pdf viewers will want + * to embed this code as is. We assume that they also have locale.h and setlocale. + * For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER, + * when building. You also have to create and customize synctex_parser_local.h to fit your system. + * In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined. + * With this design, you should not need to edit this file. */ + +/** + * \file synctex_parser.c + * \brief SyncTeX file parser and controller. + * - author: Jérôme LAURENS + * \version 1.21 + * \date Sun Oct 15 15:09:55 UTC 2017 + * + * Reads and parse *.synctex[.gz] files, + * performs edit and display queries. + * + * See + * - synctex_scanner_new_with_output_file + * - synctex_scanner_parse + * - synctex_scanner_free + * - synctex_display_query + * - synctex_edit_query + * - synctex_scanner_next_result + * - synctex_scanner_reset_result + * + * The data is organized in a graph with multiple entries. + * The root object is a scanner, it is created with the contents on a synctex file. + * Each node of the tree is a synctex_node_t object. + * There are 3 subtrees, two of them sharing the same leaves. + * The first tree is the list of input records, where input file names are associated with tags. + * The second tree is the box tree as given by TeX when shipping pages out. + * First level objects are sheets and forms, containing boxes, glues, kerns... + * The third tree allows to browse leaves according to tag and line. + */ +# if defined(SYNCTEX_USE_LOCAL_HEADER) +# include "synctex_parser_local.h" +# else +# define HAVE_LOCALE_H 1 +# define HAVE_SETLOCALE 1 +# if defined(_MSC_VER) +# define SYNCTEX_INLINE __inline +# else +# define SYNCTEX_INLINE inline +# endif +# endif + +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_LOCALE_H) +#include +#endif + +/* Mark unused parameters, so that there will be no compile warnings. */ +#ifdef __DARWIN_UNIX03 +# define SYNCTEX_UNUSED(x) SYNCTEX_PRAGMA(unused(x)) +# define SYNCTEX_PRAGMA(x) _Pragma ( #x ) +#else +# define SYNCTEX_UNUSED(x) (void)(x); +#endif + +#include "synctex_parser_advanced.h" + +SYNCTEX_INLINE static int _synctex_abs(int x) { + return x>0? x: -x; +} +/* These are the possible extensions of the synctex file */ +const char * synctex_suffix = ".synctex"; +const char * synctex_suffix_gz = ".gz"; + +typedef synctex_node_p(*synctex_node_new_f)(synctex_scanner_p); +typedef void(*synctex_node_fld_f)(synctex_node_p); +typedef char *(*synctex_node_str_f)(synctex_node_p); + +/** + * Pseudo class. + * - author: J. Laurens + * + * Each nodes has a class, it is therefore called an object. + * Each class has a unique scanner. + * Each class has a type which is a unique identifier. + * The class points to various methods, + * each of them vary amongst objects. + * Each class has a data model which stores node's attributes. + * Each class has an tree model which stores children and parent. + * Inspectors give access to data and tree elements. + */ + +/* 8 fields + size: spcflnat */ +typedef struct synctex_tree_model_t { + int sibling; + int parent; + int child; + int friend; + int last; + int next_hbox; + int arg_sibling; + int target; + int size; +} synctex_tree_model_s; +typedef const synctex_tree_model_s * synctex_tree_model_p; + +typedef struct synctex_data_model_t { + int tag; + int line; + int column; + int h; + int v; + int width; + int height; + int depth; + int mean_line; + int weight; + int h_V; + int v_V; + int width_V; + int height_V; + int depth_V; + int name; + int page; + int size; +} synctex_data_model_s; + +typedef const synctex_data_model_s * synctex_data_model_p; + +typedef int (*synctex_int_getter_f)(synctex_node_p); +typedef struct synctex_tlcpector_t { + synctex_int_getter_f tag; + synctex_int_getter_f line; + synctex_int_getter_f column; +} synctex_tlcpector_s; +typedef const synctex_tlcpector_s * synctex_tlcpector_p; +static int _synctex_int_none(synctex_node_p node) { + SYNCTEX_UNUSED(node) + return 0; +} +static const synctex_tlcpector_s synctex_tlcpector_none = { + &_synctex_int_none, /* tag */ + &_synctex_int_none, /* line */ + &_synctex_int_none, /* column */ +}; + +typedef struct synctex_inspector_t { + synctex_int_getter_f h; + synctex_int_getter_f v; + synctex_int_getter_f width; + synctex_int_getter_f height; + synctex_int_getter_f depth; +} synctex_inspector_s; +typedef const synctex_inspector_s * synctex_inspector_p; +static const synctex_inspector_s synctex_inspector_none = { + &_synctex_int_none, /* h */ + &_synctex_int_none, /* v */ + &_synctex_int_none, /* width */ + &_synctex_int_none, /* height */ + &_synctex_int_none, /* depth */ +}; + +typedef float (*synctex_float_getter_f)(synctex_node_p); +typedef struct synctex_vispector_t { + synctex_float_getter_f h; + synctex_float_getter_f v; + synctex_float_getter_f width; + synctex_float_getter_f height; + synctex_float_getter_f depth; +} synctex_vispector_s; +static float _synctex_float_none(synctex_node_p node) { + SYNCTEX_UNUSED(node) + return 0; +} +static const synctex_vispector_s synctex_vispector_none = { + &_synctex_float_none, /* h */ + &_synctex_float_none, /* v */ + &_synctex_float_none, /* width */ + &_synctex_float_none, /* height */ + &_synctex_float_none, /* depth */ +}; +typedef const synctex_vispector_s * synctex_vispector_p; + +struct synctex_class_t { + synctex_scanner_p scanner; + synctex_node_type_t type; + synctex_node_new_f new; + synctex_node_fld_f free; + synctex_node_fld_f log; + synctex_node_fld_f display; + synctex_node_str_f abstract; + synctex_tree_model_p navigator; + synctex_data_model_p modelator; + synctex_tlcpector_p tlcpector; + synctex_inspector_p inspector; + synctex_vispector_p vispector; +}; + +/** + * Nota bene: naming convention. + * For static API, when the name contains "proxy", it applies to proxies. + * When the name contains "noxy", it applies to non proxies only. + * When the name contains "node", well it depends... + */ + +typedef synctex_node_p synctex_proxy_p; +typedef synctex_node_p synctex_noxy_p; + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Abstract OBJECTS and METHODS +# endif + +/** + * \def SYNCTEX_MSG_SEND + * \brief Takes care of sending the given message if possible. + * - parameter NODE: of type synctex_node_p + * - parameter SELECTOR: one of the class_ pointer properties + */ +# define SYNCTEX_MSG_SEND(NODE,SELECTOR) do {\ + synctex_node_p N__ = NODE;\ + if (N__ && N__->class_->SELECTOR) {\ + (*(N__->class_->SELECTOR))(N__);\ + }\ +} while (synctex_NO) + +/** + * Free the given node by sending the free message. + * - parameter NODE: of type synctex_node_p + */ +void synctex_node_free(synctex_node_p node) { + SYNCTEX_MSG_SEND(node,free); +} +# if defined(SYNCTEX_TESTING) +# if !defined(SYNCTEX_USE_HANDLE) +# define SYNCTEX_USE_HANDLE 1 +# endif +# if !defined(SYNCTEX_USE_CHARINDEX) +# define SYNCTEX_USE_CHARINDEX 1 +# endif +# endif +SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target); +# if defined(SYNCTEX_USE_HANDLE) +# define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) \ +__synctex_scanner_free_handle(SCANR) +# define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) \ +__synctex_scanner_remove_handle_to(WHAT) +# define SYNCTEX_REGISTER_HANDLE_TO(NODE) \ +__synctex_scanner_register_handle_to(NODE) +# else +# define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) +# define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) +# define SYNCTEX_REGISTER_HANDLE_TO(NODE) +# endif + +# if defined(SYNCTEX_USE_CHARINDEX) +# define SYNCTEX_CHARINDEX(NODE) (NODE->char_index) +# define SYNCTEX_LINEINDEX(NODE) (NODE->line_index) +# define SYNCTEX_PRINT_CHARINDEX_FMT "#%i" +# define SYNCTEX_PRINT_CHARINDEX_WHAT ,SYNCTEX_CHARINDEX(node) +# define SYNCTEX_PRINT_CHARINDEX \ + printf(SYNCTEX_PRINT_CHARINDEX_FMT SYNCTEX_PRINT_CHARINDEX_WHAT) +# define SYNCTEX_PRINT_LINEINDEX_FMT "L#%i" +# define SYNCTEX_PRINT_LINEINDEX_WHAT ,SYNCTEX_LINEINDEX(node) +# define SYNCTEX_PRINT_LINEINDEX \ + printf(SYNCTEX_PRINT_LINEINDEX_FMT SYNCTEX_PRINT_LINEINDEX_WHAT) +# define SYNCTEX_PRINT_CHARINDEX_NL \ + printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n" SYNCTEX_PRINT_CHARINDEX_WHAT) +# define SYNCTEX_PRINT_LINEINDEX_NL \ + printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n"SYNCTEX_PRINT_LINEINDEX_WHAT) +# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION)\ + NODE->char_index = (synctex_charindex_t)(scanner->reader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION)); \ + NODE->line_index = scanner->reader->line_number; +# else +# define SYNCTEX_CHARINDEX(NODE) 0 +# define SYNCTEX_LINEINDEX(NODE) 0 +# define SYNCTEX_PRINT_CHARINDEX_FMT +# define SYNCTEX_PRINT_CHARINDEX_WHAT +# define SYNCTEX_PRINT_CHARINDEX +# define SYNCTEX_PRINT_CHARINDEX +# define SYNCTEX_PRINT_LINEINDEX_FMT +# define SYNCTEX_PRINT_LINEINDEX_WHAT +# define SYNCTEX_PRINT_LINEINDEX +# define SYNCTEX_PRINT_CHARINDEX_NL printf("\n") +# define SYNCTEX_PRINT_LINEINDEX_NL printf("\n") +# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) +# endif + +/** + * The next macros are used to access the node tree info + * SYNCTEX_DATA(node) points to the first synctex integer or pointer data of node + * SYNCTEX_DATA(node)[index] is the information at index + * for example, the page of a sheet is stored in SYNCTEX_DATA(sheet)[_synctex_data_page_idx] + * - parameter NODE: of type synctex_node_p + * If the name starts with "__", the argument is nonullable + */ +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Tree SETGET +# endif + +#if SYNCTEX_DEBUG > 1000 +#define SYNCTEX_PARAMETER_ASSERT(WHAT) \ + do { \ + if (!(WHAT)) { \ + printf("! Parameter failure: %s\n",#WHAT); \ + } \ + } while (synctex_NO) +#define DEFINE_SYNCTEX_TREE_HAS(WHAT)\ +static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\ + if (node) {\ + if (node->class_->navigator->WHAT>=0) {\ + return synctex_YES; \ + } else {\ + printf("WARNING: NO tree %s for %s\n", #WHAT, synctex_node_isa(node));\ + }\ + }\ + return synctex_NO;\ +} +#else +#define SYNCTEX_PARAMETER_ASSERT(WHAT) +#define DEFINE_SYNCTEX_TREE_HAS(WHAT) \ +static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\ + return (node && (node->class_->navigator->WHAT>=0));\ +} +#endif + +# define DEFINE_SYNCTEX_TREE__GET(WHAT) \ +SYNCTEX_INLINE static synctex_node_p __synctex_tree_##WHAT(synctex_non_null_node_p node) {\ + return node->data[node->class_->navigator->WHAT].as_node;\ +} +# define DEFINE_SYNCTEX_TREE_GET(WHAT) \ +DEFINE_SYNCTEX_TREE__GET(WHAT) \ +static synctex_node_p _synctex_tree_##WHAT(synctex_node_p node) {\ + if (_synctex_tree_has_##WHAT(node)) {\ + return __synctex_tree_##WHAT(node);\ + }\ + return 0;\ +} +# define DEFINE_SYNCTEX_TREE__RESET(WHAT) \ +SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_##WHAT(synctex_non_null_node_p node) {\ + synctex_node_p old = node->data[node->class_->navigator->WHAT].as_node;\ + node->data[node->class_->navigator->WHAT].as_node=NULL;\ + return old;\ +} +# define DEFINE_SYNCTEX_TREE_RESET(WHAT) \ +DEFINE_SYNCTEX_TREE__RESET(WHAT) \ +SYNCTEX_INLINE static synctex_node_p _synctex_tree_reset_##WHAT(synctex_node_p node) {\ + return _synctex_tree_has_##WHAT(node)? \ + __synctex_tree_reset_##WHAT(node): NULL; \ +} +# define DEFINE_SYNCTEX_TREE__SET(WHAT) \ +SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_##WHAT(synctex_non_null_node_p node, synctex_node_p new_value) {\ + synctex_node_p old = __synctex_tree_##WHAT(node);\ + node->data[node->class_->navigator->WHAT].as_node=new_value;\ + return old;\ +} +# define DEFINE_SYNCTEX_TREE_SET(WHAT) \ +DEFINE_SYNCTEX_TREE__SET(WHAT) \ +SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_##WHAT(synctex_node_p node, synctex_node_p new_value) {\ + return _synctex_tree_has_##WHAT(node)?\ + __synctex_tree_set_##WHAT(node,new_value):NULL;\ +} +# define DEFINE_SYNCTEX_TREE__GETSETRESET(WHAT) \ +DEFINE_SYNCTEX_TREE__GET(WHAT) \ +DEFINE_SYNCTEX_TREE__SET(WHAT) \ +DEFINE_SYNCTEX_TREE__RESET(WHAT) + +# define DEFINE_SYNCTEX_TREE_GETSET(WHAT) \ +DEFINE_SYNCTEX_TREE_HAS(WHAT) \ +DEFINE_SYNCTEX_TREE_GET(WHAT) \ +DEFINE_SYNCTEX_TREE_SET(WHAT) + +# define DEFINE_SYNCTEX_TREE_GETRESET(WHAT) \ +DEFINE_SYNCTEX_TREE_HAS(WHAT) \ +DEFINE_SYNCTEX_TREE_GET(WHAT) \ +DEFINE_SYNCTEX_TREE_RESET(WHAT) + +# define DEFINE_SYNCTEX_TREE_GETSETRESET(WHAT) \ +DEFINE_SYNCTEX_TREE_HAS(WHAT) \ +DEFINE_SYNCTEX_TREE_GET(WHAT) \ +DEFINE_SYNCTEX_TREE_SET(WHAT) \ +DEFINE_SYNCTEX_TREE_RESET(WHAT) + +/* + * _synctex_tree_set_... methods return the old value. + * The return value of _synctex_tree_set_child and + * _synctex_tree_set_sibling must be released somehown. + */ +DEFINE_SYNCTEX_TREE__GETSETRESET(sibling) +DEFINE_SYNCTEX_TREE_GETSETRESET(parent) +DEFINE_SYNCTEX_TREE_GETSETRESET(child) +DEFINE_SYNCTEX_TREE_GETSETRESET(friend) +DEFINE_SYNCTEX_TREE_GETSET(last) +DEFINE_SYNCTEX_TREE_GETSET(next_hbox) +DEFINE_SYNCTEX_TREE_GETSET(arg_sibling) +DEFINE_SYNCTEX_TREE_GETSETRESET(target) + +#if SYNCTEX_DEBUG>1000 +# undef SYNCTEX_USE_NODE_COUNT +# define SYNCTEX_USE_NODE_COUNT 1 +#endif +#if SYNCTEX_USE_NODE_COUNT>0 +# define SYNCTEX_DECLARE_NODE_COUNT int node_count; +# define SYNCTEX_INIT_NODE_COUNT \ + do { node_count = 0; } while(synctex_NO) +#else +# define SYNCTEX_DECLARE_NODE_COUNT +# define SYNCTEX_INIT_NODE_COUNT +#endif + +#if SYNCTEX_USE_NODE_COUNT>10 +# define SYNCTEX_DID_NEW(N) _synctex_did_new(N) +# define SYNCTEX_WILL_FREE(N) _synctex_will_free(N) +#else +# define SYNCTEX_DID_NEW(N) +# define SYNCTEX_WILL_FREE(N) +#endif + +#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && _synctex_tree_child(NODE)) +# ifdef __SYNCTEX_WORK__ +# include "/usr/include/zlib.h" +# else +# include +# endif + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark STATUS +# endif +/* When the end of the synctex file has been reached: */ +# define SYNCTEX_STATUS_EOF 0 +/* When the function could not return the value it was asked for: */ +# define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF+1) +/* When the function returns the value it was asked for: + It must be the biggest one */ +# define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK+1) +/* Generic error: */ +# define SYNCTEX_STATUS_ERROR (SYNCTEX_STATUS_EOF-1) +/* Parameter error: */ +# define SYNCTEX_STATUS_BAD_ARGUMENT (SYNCTEX_STATUS_ERROR-1) + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark File reader +# endif + +/* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */ +/* Actually, the minimum buffer size is driven by integer and float parsing, including the unit. + * ±0.123456789e123?? + */ +# define SYNCTEX_BUFFER_MIN_SIZE 32 +# define SYNCTEX_BUFFER_SIZE 32768 + +#if SYNCTEX_BUFFER_SIZE >= UINT_MAX +# error BAD BUFFER SIZE(1) +#endif +#if SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE +# error BAD BUFFER SIZE(2) +#endif + +typedef struct synctex_reader_t { + gzFile file; /* The (possibly compressed) file */ + char * output; + char * synctex; + char * current; /* current location in the buffer */ + char * start; /* start of the buffer */ + char * end; /* end of the buffer */ + size_t min_size; + size_t size; + int lastv; + int line_number; + SYNCTEX_DECLARE_CHAR_OFFSET +} synctex_reader_s; + +typedef synctex_reader_s * synctex_reader_p; + +typedef struct { + synctex_status_t status; + char * synctex; + gzFile file; + synctex_io_mode_t io_mode; +} synctex_open_s; + +/* This functions opens the file at the "output" given location. + * It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character. + * In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes. + * This function will remove them if possible. + * All the reference arguments will take a value on return. They must be non NULL. + * - returns: an open structure which status is + * SYNCTEX_STATUS_OK on success, + * SYNCTEX_STATUS_ERROR on failure. + * - note: on success, the caller is the owner + * of the fields of the returned open structure. + */ +static synctex_open_s __synctex_open_v2(const char * output, synctex_io_mode_t io_mode, synctex_bool_t add_quotes) { + synctex_open_s open = {SYNCTEX_STATUS_ERROR, NULL, NULL, io_mode}; + char * quoteless_synctex_name = NULL; + const char * mode = _synctex_get_io_mode_name(open.io_mode); + size_t size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1; + if (NULL == (open.synctex = (char *)malloc(size))) { + _synctex_error("! __synctex_open_v2: Memory problem (1)\n"); + return open; + } + /* we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices, + * including the terminating character. size is free now. */ + if (open.synctex != strcpy(open.synctex,output)) { + _synctex_error("! __synctex_open_v2: Copy problem\n"); + return_on_error: + free(open.synctex); + open.synctex = NULL; + free(quoteless_synctex_name);/* We MUST have quoteless_synctex_name<>synctex_name */ + return open; + } + /* remove the last path extension if any */ + _synctex_strip_last_path_extension(open.synctex); + if (!strlen(open.synctex)) { + goto return_on_error; + } + /* now insert quotes. */ + if (add_quotes) { + char * quoted = NULL; + if (_synctex_copy_with_quoting_last_path_component(open.synctex,"ed,size) || quoted == NULL) { + /* There was an error or quoting does not make sense: */ + goto return_on_error; + } + quoteless_synctex_name = open.synctex; + open.synctex = quoted; + } + /* Now add to open.synctex the first path extension. */ + if (open.synctex != strcat(open.synctex,synctex_suffix)){ + _synctex_error("! __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix); + goto return_on_error; + } + /* Add to quoteless_synctex_name as well, if relevant. */ + if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){ + free(quoteless_synctex_name); + quoteless_synctex_name = NULL; + } + if (NULL == (open.file = gzopen(open.synctex,mode))) { + /* Could not open this file */ + if (errno != ENOENT) { + /* The file does exist, this is a lower level error, I can't do anything. */ + _synctex_error("could not open %s, error %i\n",open.synctex,errno); + goto return_on_error; + } + /* Apparently, there is no uncompressed synctex file. Try the compressed version */ + if (open.synctex != strcat(open.synctex,synctex_suffix_gz)){ + _synctex_error("! __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz); + goto return_on_error; + } + open.io_mode |= synctex_io_gz_mask; + mode = _synctex_get_io_mode_name(open.io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */ + /* Add the suffix to the quoteless_synctex_name as well. */ + if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){ + free(quoteless_synctex_name); + quoteless_synctex_name = NULL; + } + if (NULL == (open.file = gzopen(open.synctex,mode))) { + /* Could not open this file */ + if (errno != ENOENT) { + /* The file does exist, this is a lower level error, I can't do anything. */ + _synctex_error("Could not open %s, error %i\n",open.synctex,errno); + } + goto return_on_error; + } + } + /* At this point, the file is properly open. + * If we are in the add_quotes mode, we change the file name by removing the quotes. */ + if (quoteless_synctex_name) { + gzclose(open.file); + if (rename(open.synctex,quoteless_synctex_name)) { + _synctex_error("Could not rename %s to %s, error %i\n",open.synctex,quoteless_synctex_name,errno); + /* We could not rename, reopen the file with the quoted name. */ + if (NULL == (open.file = gzopen(open.synctex,mode))) { + /* No luck, could not re open this file, something has happened meanwhile */ + if (errno != ENOENT) { + /* The file does not exist any more, it has certainly be removed somehow + * this is a lower level error, I can't do anything. */ + _synctex_error("Could not open again %s, error %i\n",open.synctex,errno); + } + goto return_on_error; + } + } else { + /* The file has been successfully renamed */ + if (NULL == (open.file = gzopen(quoteless_synctex_name,mode))) { + /* Could not open this file */ + if (errno != ENOENT) { + /* The file does exist, this is a lower level error, I can't do anything. */ + _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno); + } + goto return_on_error; + } + /* The quote free file name should replace the old one:*/ + free(open.synctex); + open.synctex = quoteless_synctex_name; + quoteless_synctex_name = NULL; + } + } + /* The operation is successful, return the arguments by value. */ + open.status = SYNCTEX_STATUS_OK; + return open; +} + +/* Opens the output file, taking into account the eventual build_directory. + * - returns: an open structure which status is + * SYNCTEX_STATUS_OK on success, + * SYNCTEX_STATUS_ERROR on failure. + * - note: on success, the caller is the owner + * of the fields of the returned open structure. + */ +static synctex_open_s _synctex_open_v2(const char * output, const char * build_directory, synctex_io_mode_t io_mode, synctex_bool_t add_quotes) { + synctex_open_s open = __synctex_open_v2(output,io_mode,add_quotes); + if (open.status == SYNCTEX_STATUS_OK) { + return open; + } + if (build_directory && strlen(build_directory)) { + char * build_output; + const char *lpc; + size_t size; + synctex_bool_t is_absolute; + build_output = NULL; + lpc = _synctex_last_path_component(output); + size = strlen(build_directory)+strlen(lpc)+2; /* One for the '/' and one for the '\0'. */ + is_absolute = _synctex_path_is_absolute(build_directory); + if (!is_absolute) { + size += strlen(output); + } + if ((build_output = (char *)_synctex_malloc(size))) { + if (is_absolute) { + build_output[0] = '\0'; + } else { + if (build_output != strcpy(build_output,output)) { + _synctex_free(build_output); + return open; + } + build_output[lpc-output]='\0'; + } + if (build_output == strcat(build_output,build_directory)) { + /* Append a path separator if necessary. */ + if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) { + if (build_output != strcat(build_output,"/")) { + _synctex_free(build_output); + return open; + } + } + /* Append the last path component of the output. */ + if (build_output != strcat(build_output,lpc)) { + _synctex_free(build_output); + return open; + } + open = __synctex_open_v2(build_output,io_mode,add_quotes); + } + _synctex_free(build_output); + } /* if ((build_output... */ + } /* if (build_directory...) */ + return open; +} +void synctex_reader_free(synctex_reader_p reader) { + if (reader) { + _synctex_free(reader->output); + _synctex_free(reader->synctex); + _synctex_free(reader->start); + gzclose(reader->file); + _synctex_free(reader); + } +} +/* + * Return reader on success. + * Deallocate reader and return NULL on failure. + */ +synctex_reader_p synctex_reader_init_with_output_file(synctex_reader_p reader, const char * output, const char * build_directory) { + if (reader) { + /* now open the synctex file */ + synctex_open_s open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES); + if (open.statussynctex = open.synctex; + reader->file = open.file; + /* make a private copy of output */ + if (NULL == (reader->output = (char *)_synctex_malloc(strlen(output)+1))){ + _synctex_error("! synctex_scanner_new_with_output_file: Memory problem (2), reader's output is not reliable."); + } else if (reader->output != strcpy(reader->output,output)) { + _synctex_free(reader->output); + reader->output = NULL; + _synctex_error("! synctex_scanner_new_with_output_file: Copy problem, reader's output is not reliable."); + } + reader->start = reader->end = reader->current = NULL; + reader->min_size = SYNCTEX_BUFFER_MIN_SIZE; + reader->size = SYNCTEX_BUFFER_SIZE; + reader->start = reader->current = + (char *)_synctex_malloc(reader->size+1); /* one more character for null termination */ + if (NULL == reader->start) { + _synctex_error("! malloc error in synctex_reader_init_with_output_file."); + bailey: +#ifdef SYNCTEX_DEBUG + return reader; +#else + synctex_reader_free(reader); + return NULL; +#endif + } + reader->end = reader->start+reader->size; + /* reader->end always points to a null terminating character. + * Maybe there is another null terminating character between reader->current and reader->end-1. + * At least, we are sure that reader->current points to a string covering a valid part of the memory. */ +# if defined(SYNCTEX_USE_CHARINDEX) + reader->charindex_offset = -reader->size; +# endif + } + return reader; +} + +# if defined(SYNCTEX_USE_HANDLE) +# define SYNCTEX_DECLARE_HANDLE synctex_node_p handle; +# else +# define SYNCTEX_DECLARE_HANDLE +# endif + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SCANNER +# endif +/** + * The synctex scanner is the root object. + * Is is initialized with the contents of a text file or a gzipped file. + * The buffer_.* are first used to parse the text. + */ +struct synctex_scanner_t { + synctex_reader_p reader; + SYNCTEX_DECLARE_NODE_COUNT + SYNCTEX_DECLARE_HANDLE + char * output_fmt; /* dvi or pdf, not yet used */ + synctex_iterator_p iterator;/* result iterator */ + int version; /* 1, not yet used */ + struct { + unsigned has_parsed:1; /* Whether the scanner has parsed its underlying synctex file. */ + unsigned postamble:1; /* Whether the scanner has parsed its underlying synctex file. */ + unsigned reserved:sizeof(unsigned)-2; /* alignment */ + } flags; + int pre_magnification; /* magnification from the synctex preamble */ + int pre_unit; /* unit from the synctex preamble */ + int pre_x_offset; /* X offset from the synctex preamble */ + int pre_y_offset; /* Y offset from the synctex preamble */ + int count; /* Number of records, from the synctex postamble */ + float unit; /* real unit, from synctex preamble or post scriptum */ + float x_offset; /* X offset, from synctex preamble or post scriptum */ + float y_offset; /* Y Offset, from synctex preamble or post scriptum */ + synctex_node_p input; /* The first input node, its siblings are the other input nodes */ + synctex_node_p sheet; /* The first sheet node, its siblings are the other sheet nodes */ + synctex_node_p form; /* The first form, its siblings are the other forms */ + synctex_node_p ref_in_sheet; /* The first form ref node in sheet, its friends are the other form ref nodes */ + synctex_node_p ref_in_form; /* The first form ref node, its friends are the other form ref nodes in sheet */ + int number_of_lists; /* The number of friend lists */ + synctex_node_r lists_of_friends;/* The friend lists */ + synctex_class_s class_[synctex_node_number_of_types]; /* The classes of the nodes of the scanner */ + int display_switcher; + char * display_prompt; +}; + +/** + * Create a new node of the given type. + * - parameter scanner: of type synctex_node_p + * - parameter type: a type, the client is responsible + * to ask for an acceptable type. + */ +synctex_node_p synctex_node_new(synctex_scanner_p scanner, synctex_node_type_t type) { + return scanner? scanner->class_[type].new(scanner):NULL; +} +# if defined(SYNCTEX_USE_HANDLE) +SYNCTEX_INLINE static void __synctex_scanner_free_handle(synctex_scanner_p scanner) { + synctex_node_free(scanner->handle); +} +SYNCTEX_INLINE static void __synctex_scanner_remove_handle_to(synctex_node_p node) { + synctex_node_p arg_sibling = NULL; + synctex_node_p handle = node->class_->scanner->handle; + while (handle) { + synctex_node_p sibling; + if (node == _synctex_tree_target(handle)) { + sibling = __synctex_tree_reset_sibling(handle); + if (arg_sibling) { + __synctex_tree_set_sibling(arg_sibling, sibling); + } else { + node->class_->scanner->handle = sibling; + } + synctex_node_free(handle); + break; + } else { + sibling = __synctex_tree_sibling(handle); + } + arg_sibling = handle; + handle = sibling; + } +} +SYNCTEX_INLINE static void __synctex_scanner_register_handle_to(synctex_node_p node) { + synctex_node_p NNN = _synctex_new_handle_with_target(node); + __synctex_tree_set_sibling(NNN,node->class_->scanner->handle); + node->class_->scanner->handle = NNN; +} +#endif +#if SYNCTEX_USE_NODE_COUNT>10 +SYNCTEX_INLINE static void _synctex_did_new(synctex_node_p node) { + printf("NODE CREATED # %i, %s, %p\n", + (node->class_->scanner->node_count)++, + synctex_node_isa(node), + node); +} +SYNCTEX_INLINE static void _synctex_will_free(synctex_node_p node) { + printf("NODE DELETED # %i, %s, %p\n", + --(node->class_->scanner->node_count), + synctex_node_isa(node), + node); +} +#endif + +/** + * Free the given node. + * - parameter node: of type synctex_node_p + * - note: a node is meant to own its child and sibling. + * It is not owned by its parent, unless it is its first child. + * This destructor is for all nodes with children. + */ +static void _synctex_free_node(synctex_node_p node) { + if (node) { + SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); + SYNCTEX_WILL_FREE(node); + synctex_node_free(__synctex_tree_sibling(node)); + synctex_node_free(_synctex_tree_child(node)); + _synctex_free(node); + } + return; +} +/** + * Free the given handle. + * - parameter node: of type synctex_node_p + * - note: a node is meant to own its child and sibling. + * It is not owned by its parent, unless it is its first child. + * This destructor is for all handles. + */ +static void _synctex_free_handle(synctex_node_p handle) { + if (handle) { + _synctex_free_handle(__synctex_tree_sibling(handle)); + _synctex_free_handle(_synctex_tree_child(handle)); + _synctex_free(handle); + } + return; +} + +/** + * Free the given leaf node. + * - parameter node: of type synctex_node_p, with no child nor sibling. + * - note: a node is meant to own its child and sibling. + * It is not owned by its parent, unless it is its first child. + * This destructor is for all nodes with no children. + */ +static void _synctex_free_leaf(synctex_node_p node) { + if (node) { + SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); + SYNCTEX_WILL_FREE(node); + synctex_node_free(__synctex_tree_sibling(node)); + _synctex_free(node); + } + return; +} + +/** + SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts + */ +# define SYNCTEX_CUR (scanner->reader->current) +# define SYNCTEX_START (scanner->reader->start) +# define SYNCTEX_END (scanner->reader->end) + +/* Here are gathered all the possible status that the next scanning functions will return. + * All these functions return a status, and pass their result through pointers. + * Negative values correspond to errors. + * The management of the buffer is causing some significant overhead. + * Every function that may access the buffer returns a status related to the buffer and file state. + * status >= SYNCTEX_STATUS_OK means the function worked as expected + * status < SYNCTEX_STATUS_OK means the function did not work as expected + * status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse. + * status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material. + * statushandle:NULL; +} +#endif + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Decoding prototypes +# endif + +typedef struct { + int integer; + synctex_status_t status; +} synctex_is_s; + +static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner); +static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value); +static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner); + +typedef struct { + char * string; + synctex_status_t status; +} synctex_ss_s; + +static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner); + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Data SETGET +# endif + +/** + * The next macros are used to access the node data info + * through the class modelator integer fields. + * - parameter NODE: of type synctex_node_p + */ +# define SYNCTEX_DATA(NODE) ((*((((NODE)->class_))->info))(NODE)) +#if defined SYNCTEX_DEBUG > 1000 +# define DEFINE_SYNCTEX_DATA_HAS(WHAT) \ +SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\ + return (node && (node->class_->modelator->WHAT>=0));\ +}\ +SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\ + if (node && (node->class_->modelator->WHAT<0)) {\ + printf("WARNING: NO %s for %s\n", #WHAT, synctex_node_isa(node));\ + }\ + return __synctex_data_has_##WHAT(node);\ +} +#else +# define DEFINE_SYNCTEX_DATA_HAS(WHAT) \ +SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\ + return (node && (node->class_->modelator->WHAT>=0));\ +}\ +SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\ + return __synctex_data_has_##WHAT(node);\ +} +#endif + +SYNCTEX_INLINE static synctex_data_p __synctex_data(synctex_node_p node) { + return node->data+node->class_->navigator->size; +} +# define DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ +DEFINE_SYNCTEX_DATA_HAS(WHAT)\ +static int _synctex_data_##WHAT(synctex_node_p node) {\ + if (_synctex_data_has_##WHAT(node)) {\ + return __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\ + }\ + return 0;\ +}\ +static int _synctex_data_set_##WHAT(synctex_node_p node, int new_value) {\ + int old = 0;\ + if (_synctex_data_has_##WHAT(node)) {\ + old = __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\ + __synctex_data(node)[node->class_->modelator->WHAT].as_integer=new_value;\ + }\ + return old;\ +} +#define DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT) \ +static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\ + if (_synctex_data_has_##WHAT(node)) {\ + synctex_is_s is = _synctex_decode_int(node->class_->scanner);\ + if (is.status == SYNCTEX_STATUS_OK) {\ + _synctex_data_set_##WHAT(node,is.integer);\ + } \ + return is.status;\ + }\ + return SYNCTEX_STATUS_BAD_ARGUMENT;\ +} +# define DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT) \ +static synctex_status_t _synctex_data_decode_##WHAT##_v(synctex_node_p node) {\ + if (_synctex_data_has_##WHAT(node)) {\ + synctex_is_s is = _synctex_decode_int_v(node->class_->scanner);\ + if (is.status == SYNCTEX_STATUS_OK) {\ + _synctex_data_set_##WHAT(node,is.integer);\ + } \ + return is.status;\ + }\ + return SYNCTEX_STATUS_BAD_ARGUMENT;\ +} +#define DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \ +DEFINE_SYNCTEX_DATA_HAS(WHAT)\ +static char * _synctex_data_##WHAT(synctex_node_p node) {\ + if (_synctex_data_has_##WHAT(node)) {\ + return node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\ + }\ + return NULL;\ +}\ +static char * _synctex_data_set_##WHAT(synctex_node_p node, char * new_value) {\ + char * old = "";\ + if (_synctex_data_has_##WHAT(node)) {\ + old = node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\ + node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string =new_value;\ + }\ + return old;\ +} +#define DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT) \ +static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\ + if (_synctex_data_has_##WHAT(node)) {\ + synctex_ss_s ss = _synctex_decode_string(node->class_->scanner);\ + if (ss.status == SYNCTEX_STATUS_OK) {\ + _synctex_data_set_##WHAT(node,ss.string);\ + } \ + return ss.status;\ + }\ + return SYNCTEX_STATUS_BAD_ARGUMENT;\ +} +#define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(WHAT) \ +DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ +DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT) +#define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(WHAT) \ +DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ +DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT) +#define DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(WHAT) \ +DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \ +DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT) + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark OBJECTS, their creators and destructors. +# endif + +# ifdef SYNCTEX_NOTHING +# pragma mark input. +# endif + +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(tag) +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(line) +DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(name) + +/* Input nodes only know about their sibling, which is another input node. + * The synctex information is the _synctex_data_tag and _synctex_data_name + * note: the input owns its name. */ + +# define SYNCTEX_INPUT_MARK "Input:" + +static const synctex_tree_model_s synctex_tree_model_input = { + synctex_tree_sibling_idx, /* sibling */ + -1, /* parent */ + -1, /* child */ + -1, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + -1, /* target */ + synctex_tree_s_input_max +}; +static const synctex_data_model_s synctex_data_model_input = { + synctex_data_input_tag_idx, /* tag */ + synctex_data_input_line_idx,/* line */ + -1, /* column */ + -1, /* h */ + -1, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + synctex_data_input_name_idx, /* name */ + -1, /* page */ + synctex_data_input_tln_max +}; + +#define SYNCTEX_INSPECTOR_GETTER_F(WHAT)\ +&_synctex_data_##WHAT, &_synctex_data_set_##WHAT + +static synctex_node_p _synctex_new_input(synctex_scanner_p scanner); +static void _synctex_free_input(synctex_node_p node); +static void _synctex_log_input(synctex_node_p node); +static char * _synctex_abstract_input(synctex_node_p node); +static void _synctex_display_input(synctex_node_p node); + +static const synctex_tlcpector_s synctex_tlcpector_input = { + &_synctex_data_tag, /* tag */ + &_synctex_int_none, /* line */ + &_synctex_int_none, /* column */ +}; + +static synctex_class_s synctex_class_input = { + NULL, /* No scanner yet */ + synctex_node_type_input, /* Node type */ + &_synctex_new_input, /* creator */ + &_synctex_free_input, /* destructor */ + &_synctex_log_input, /* log */ + &_synctex_display_input, /* display */ + &_synctex_abstract_input, /* abstract */ + &synctex_tree_model_input, /* tree model */ + &synctex_data_model_input, /* data model */ + &synctex_tlcpector_input, /* inspector */ + &synctex_inspector_none, /* inspector */ + &synctex_vispector_none, /* vispector */ +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_s_input_max+synctex_data_input_tln_max]; +} synctex_input_s; + +static synctex_node_p _synctex_new_input(synctex_scanner_p scanner) { + if (scanner) { + synctex_node_p node = _synctex_malloc(sizeof(synctex_input_s)); + if (node) { + node->class_ = scanner->class_+synctex_node_type_input; + SYNCTEX_DID_NEW(node); + SYNCTEX_IMPLEMENT_CHARINDEX(node,0); + SYNCTEX_REGISTER_HANDLE_TO(node); + } + return node; + } + return NULL; +} + +static void _synctex_free_input(synctex_node_p node){ + if (node) { + SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); + SYNCTEX_WILL_FREE(node); + synctex_node_free(__synctex_tree_sibling(node)); + _synctex_free(_synctex_data_name(node)); + _synctex_free(node); + } +} + +/* The sheet is a first level node. + * It has no parent (the owner is the scanner itself) + * Its sibling points to another sheet. + * Its child points to its first child, in general a box. + * A sheet node contains only one synctex information: the page. + * This is the 1 based page index as given by TeX. + */ + +# ifdef SYNCTEX_NOTHING +# pragma mark sheet. +# endif +/** + * Every node has the same structure, but not the same size. + */ + +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(page) + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_scn_sheet_max+synctex_data_p_sheet_max]; +} synctex_node_sheet_s; + +/* sheet node creator */ + +#define DEFINE_synctex_new_scanned_NODE(NAME)\ +static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\ + if (scanner) {\ + ++SYNCTEX_CUR;\ + synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\ + if (node) {\ + node->class_ = scanner->class_+synctex_node_type_##NAME;\ + SYNCTEX_DID_NEW(node); \ + SYNCTEX_IMPLEMENT_CHARINDEX(node,-1);\ + SYNCTEX_REGISTER_HANDLE_TO(node); \ + }\ + return node;\ + }\ + return NULL;\ +} +/* NB: -1 in SYNCTEX_IMPLEMENT_CHARINDEX above because + * the first char of the line has been scanned + */ +DEFINE_synctex_new_scanned_NODE(sheet) +static void _synctex_log_sheet(synctex_node_p node); +static char * _synctex_abstract_sheet(synctex_node_p node); +static void _synctex_display_sheet(synctex_node_p node); + +static const synctex_tree_model_s synctex_tree_model_sheet = { + synctex_tree_sibling_idx, /* sibling */ + -1, /* parent */ + synctex_tree_s_child_idx, /* child */ + -1, /* friend */ + -1, /* last */ + synctex_tree_sc_next_hbox_idx, /* next_hbox */ + -1, /* arg_sibling */ + -1, /* target */ + synctex_tree_scn_sheet_max +}; +static const synctex_data_model_s synctex_data_model_sheet = { + -1, /* tag */ + -1, /* line */ + -1, /* column */ + -1, /* h */ + -1, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + synctex_data_sheet_page_idx, /* page */ + synctex_data_p_sheet_max +}; +static synctex_class_s synctex_class_sheet = { + NULL, /* No scanner yet */ + synctex_node_type_sheet, /* Node type */ + &_synctex_new_sheet, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_sheet, /* log */ + &_synctex_display_sheet, /* display */ + &_synctex_abstract_sheet, /* abstract */ + &synctex_tree_model_sheet, /* tree model */ + &synctex_data_model_sheet, /* data model */ + &synctex_tlcpector_none, /* tlcpector */ + &synctex_inspector_none, /* inspector */ + &synctex_vispector_none, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark form. +# endif +/** + * Every node has the same structure, but not the same size. + */ +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_sct_form_max+synctex_data_t_form_max]; +} synctex_node_form_s; + +DEFINE_synctex_new_scanned_NODE(form) + +static char * _synctex_abstract_form(synctex_node_p node); +static void _synctex_display_form(synctex_node_p node); +static void _synctex_log_form(synctex_node_p node); + +static const synctex_tree_model_s synctex_tree_model_form = { + synctex_tree_sibling_idx, /* sibling */ + -1, /* parent */ + synctex_tree_s_child_idx, /* child */ + -1, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + synctex_tree_sc_target_idx, /* target */ + synctex_tree_sct_form_max +}; +static const synctex_data_model_s synctex_data_model_form = { + synctex_data_form_tag_idx, /* tag */ + -1, /* line */ + -1, /* column */ + -1, /* h */ + -1, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_t_form_max +}; +static synctex_class_s synctex_class_form = { + NULL, /* No scanner yet */ + synctex_node_type_form, /* Node type */ + &_synctex_new_form, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_form, /* log */ + &_synctex_display_form, /* display */ + &_synctex_abstract_form, /* abstract */ + &synctex_tree_model_form, /* tree model */ + &synctex_data_model_form, /* data model */ + &synctex_tlcpector_none, /* tlcpector */ + &synctex_inspector_none, /* inspector */ + &synctex_vispector_none, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark vbox. +# endif + +/* A box node contains navigation and synctex information + * There are different kinds of boxes. + * Only horizontal boxes are treated differently because of their visible size. + */ +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spcfl_vbox_max+synctex_data_box_max]; +} synctex_node_vbox_s; + +/* vertical box node creator */ +DEFINE_synctex_new_scanned_NODE(vbox) + +static char * _synctex_abstract_vbox(synctex_node_p node); +static void _synctex_display_vbox(synctex_node_p node); +static void _synctex_log_vbox(synctex_node_p node); + +static const synctex_tree_model_s synctex_tree_model_vbox = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + synctex_tree_sp_child_idx, /* child */ + synctex_tree_spc_friend_idx, /* friend */ + synctex_tree_spcf_last_idx, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + -1, /* target */ + synctex_tree_spcfl_vbox_max +}; + +#define SYNCTEX_DFLT_COLUMN -1 + +DEFINE_SYNCTEX_DATA_INT_GETSET(column) +static synctex_status_t _synctex_data_decode_column(synctex_node_p node) { + if (_synctex_data_has_column(node)) { + synctex_is_s is = _synctex_decode_int_opt(node->class_->scanner, + SYNCTEX_DFLT_COLUMN); + if (is.status == SYNCTEX_STATUS_OK) { + _synctex_data_set_column(node,is.integer); + } + return is.status; + } + return SYNCTEX_STATUS_BAD_ARGUMENT; +} +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(h) +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(v) +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(width) +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(height) +DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(depth) + +SYNCTEX_INLINE static void _synctex_data_set_tlc(synctex_node_p node, synctex_node_p model) { + _synctex_data_set_tag(node, _synctex_data_tag(model)); + _synctex_data_set_line(node, _synctex_data_line(model)); + _synctex_data_set_column(node, _synctex_data_column(model)); +} +SYNCTEX_INLINE static void _synctex_data_set_tlchv(synctex_node_p node, synctex_node_p model) { + _synctex_data_set_tlc(node,model); + _synctex_data_set_h(node, _synctex_data_h(model)); + _synctex_data_set_v(node, _synctex_data_v(model)); +} + +static const synctex_data_model_s synctex_data_model_box = { + synctex_data_tag_idx, /* tag */ + synctex_data_line_idx, /* line */ + synctex_data_column_idx,/* column */ + synctex_data_h_idx, /* h */ + synctex_data_v_idx, /* v */ + synctex_data_width_idx, /* width */ + synctex_data_height_idx,/* height */ + synctex_data_depth_idx, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_box_max +}; +static const synctex_tlcpector_s synctex_tlcpector_default = { + &_synctex_data_tag, /* tag */ + &_synctex_data_line, /* line */ + &_synctex_data_column, /* column */ +}; +static const synctex_inspector_s synctex_inspector_box = { + &_synctex_data_h, + &_synctex_data_v, + &_synctex_data_width, + &_synctex_data_height, + &_synctex_data_depth, +}; +static float __synctex_node_visible_h(synctex_node_p node); +static float __synctex_node_visible_v(synctex_node_p node); +static float __synctex_node_visible_width(synctex_node_p node); +static float __synctex_node_visible_height(synctex_node_p node); +static float __synctex_node_visible_depth(synctex_node_p node); +static synctex_vispector_s synctex_vispector_box = { + &__synctex_node_visible_h, + &__synctex_node_visible_v, + &__synctex_node_visible_width, + &__synctex_node_visible_height, + &__synctex_node_visible_depth, +}; +/* These are static class objects, each scanner will make a copy of them and setup the scanner field. + */ +static synctex_class_s synctex_class_vbox = { + NULL, /* No scanner yet */ + synctex_node_type_vbox, /* Node type */ + &_synctex_new_vbox, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_vbox, /* log */ + &_synctex_display_vbox, /* display */ + &_synctex_abstract_vbox, /* abstract */ + &synctex_tree_model_vbox, /* tree model */ + &synctex_data_model_box, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_box, /* inspector */ + &synctex_vispector_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark hbox. +# endif + +/* Horizontal boxes must contain visible size, because 0 width does not mean emptiness. + * They also contain an average of the line numbers of the containing nodes. */ + +static const synctex_tree_model_s synctex_tree_model_hbox = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + synctex_tree_sp_child_idx, /* child */ + synctex_tree_spc_friend_idx, /* friend */ + synctex_tree_spcf_last_idx, /* last */ + synctex_tree_spcfl_next_hbox_idx, /* next_hbox */ + -1, /* arg_sibling */ + -1, /* target */ + synctex_tree_spcfln_hbox_max +}; + +DEFINE_SYNCTEX_DATA_INT_GETSET(mean_line) +DEFINE_SYNCTEX_DATA_INT_GETSET(weight) +DEFINE_SYNCTEX_DATA_INT_GETSET(h_V) +DEFINE_SYNCTEX_DATA_INT_GETSET(v_V) +DEFINE_SYNCTEX_DATA_INT_GETSET(width_V) +DEFINE_SYNCTEX_DATA_INT_GETSET(height_V) +DEFINE_SYNCTEX_DATA_INT_GETSET(depth_V) + +/** + * The hbox model. + * It contains V variants of geometrical information. + * It happens that hboxes contain material that is not used to compute + * the bounding box. Some letters may appear out of the box given by TeX. + * In such a situation, the visible bounding box is bigger ence the V variant. + * Only hboxes have such variant. It does not make sense for void boxes + * and it is not used here for vboxes. + * - author: JL + */ + +static const synctex_data_model_s synctex_data_model_hbox = { + synctex_data_tag_idx, /* tag */ + synctex_data_line_idx, /* line */ + synctex_data_column_idx,/* column */ + synctex_data_h_idx, /* h */ + synctex_data_v_idx, /* v */ + synctex_data_width_idx, /* width */ + synctex_data_height_idx,/* height */ + synctex_data_depth_idx, /* depth */ + synctex_data_mean_line_idx, /* mean_line */ + synctex_data_weight_idx, /* weight */ + synctex_data_h_V_idx, /* h_V */ + synctex_data_v_V_idx, /* v_V */ + synctex_data_width_V_idx, /* width_V */ + synctex_data_height_V_idx, /* height_V */ + synctex_data_depth_V_idx, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_hbox_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spcfln_hbox_max+synctex_data_hbox_max]; +} synctex_node_hbox_s; + +/* horizontal box node creator */ +DEFINE_synctex_new_scanned_NODE(hbox) + +static void _synctex_log_hbox(synctex_node_p node); +static char * _synctex_abstract_hbox(synctex_node_p node); +static void _synctex_display_hbox(synctex_node_p node); + +static synctex_class_s synctex_class_hbox = { + NULL, /* No scanner yet */ + synctex_node_type_hbox, /* Node type */ + &_synctex_new_hbox, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_hbox, /* log */ + &_synctex_display_hbox, /* display */ + &_synctex_abstract_hbox, /* abstract */ + &synctex_tree_model_hbox, /* tree model */ + &synctex_data_model_hbox, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_box, /* inspector */ + &synctex_vispector_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark void vbox. +# endif + +/* This void box node implementation is either horizontal or vertical + * It does not contain a child field. + */ +static const synctex_tree_model_s synctex_tree_model_spf = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + -1, /* child */ + synctex_tree_sp_friend_idx, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + -1, /* target */ + synctex_tree_spf_max +}; +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max]; +} synctex_node_void_vbox_s; + +/* vertical void box node creator */ +DEFINE_synctex_new_scanned_NODE(void_vbox) + +static void _synctex_log_void_box(synctex_node_p node); +static char * _synctex_abstract_void_vbox(synctex_node_p node); +static void _synctex_display_void_vbox(synctex_node_p node); + +static synctex_class_s synctex_class_void_vbox = { + NULL, /* No scanner yet */ + synctex_node_type_void_vbox,/* Node type */ + &_synctex_new_void_vbox, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_void_box, /* log */ + &_synctex_display_void_vbox,/* display */ + &_synctex_abstract_void_vbox,/* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_box, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_box, /* inspector */ + &synctex_vispector_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark void hbox. +# endif + +typedef synctex_node_void_vbox_s synctex_node_void_hbox_s; + +/* horizontal void box node creator */ +DEFINE_synctex_new_scanned_NODE(void_hbox) + +static char * _synctex_abstract_void_hbox(synctex_node_p node); +static void _synctex_display_void_hbox(synctex_node_p node); + +static synctex_class_s synctex_class_void_hbox = { + NULL, /* No scanner yet */ + synctex_node_type_void_hbox,/* Node type */ + &_synctex_new_void_hbox, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_void_box, /* log */ + &_synctex_display_void_hbox,/* display */ + &_synctex_abstract_void_hbox,/* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_box, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_box, /* inspector */ + &synctex_vispector_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark form ref. +# endif + +/* The form ref node. */ +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spfa_max+synctex_data_ref_thv_max]; +} synctex_node_ref_s; + +/* form ref node creator */ +DEFINE_synctex_new_scanned_NODE(ref) + +static void _synctex_log_ref(synctex_node_p node); +static char * _synctex_abstract_ref(synctex_node_p node); +static void _synctex_display_ref(synctex_node_p node); + +static const synctex_tree_model_s synctex_tree_model_spfa = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + -1, /* child */ + synctex_tree_sp_friend_idx, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + synctex_tree_spf_arg_sibling_idx, /* arg_sibling */ + -1, /* target */ + synctex_tree_spfa_max +}; +static const synctex_data_model_s synctex_data_model_ref = { + synctex_data_tag_idx, /* tag */ + -1, /* line */ + -1, /* column */ + synctex_data_ref_h_idx, /* h */ + synctex_data_ref_v_idx, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_ref_thv_max /* size */ +}; +static synctex_class_s synctex_class_ref = { + NULL, /* No scanner yet */ + synctex_node_type_ref, /* Node type */ + &_synctex_new_ref, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_ref, /* log */ + &_synctex_display_ref, /* display */ + &_synctex_abstract_ref, /* abstract */ + &synctex_tree_model_spfa, /* navigator */ + &synctex_data_model_ref, /* data model */ + &synctex_tlcpector_none, /* tlcpector */ + &synctex_inspector_none, /* inspector */ + &synctex_vispector_none, /* vispector */ +}; +# ifdef SYNCTEX_NOTHING +# pragma mark small node. +# endif + +/* The small nodes correspond to glue, penalty, math and boundary nodes. */ +static const synctex_data_model_s synctex_data_model_tlchv = { + synctex_data_tag_idx, /* tag */ + synctex_data_line_idx, /* line */ + synctex_data_column_idx, /* column */ + synctex_data_h_idx, /* h */ + synctex_data_v_idx, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_tlchv_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchv_max]; +} synctex_node_tlchv_s; + +static void _synctex_log_tlchv_node(synctex_node_p node); + +# ifdef SYNCTEX_NOTHING +# pragma mark math. +# endif + +typedef synctex_node_tlchv_s synctex_node_math_s; + +/* math node creator */ +DEFINE_synctex_new_scanned_NODE(math) + +static char * _synctex_abstract_math(synctex_node_p node); +static void _synctex_display_math(synctex_node_p node); +static synctex_inspector_s synctex_inspector_hv = { + &_synctex_data_h, + &_synctex_data_v, + &_synctex_int_none, + &_synctex_int_none, + &_synctex_int_none, +}; +static synctex_vispector_s synctex_vispector_hv = { + &__synctex_node_visible_h, + &__synctex_node_visible_v, + &_synctex_float_none, + &_synctex_float_none, + &_synctex_float_none, +}; + +static synctex_class_s synctex_class_math = { + NULL, /* No scanner yet */ + synctex_node_type_math, /* Node type */ + &_synctex_new_math, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_tlchv_node, /* log */ + &_synctex_display_math, /* display */ + &_synctex_abstract_math, /* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_tlchv, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_hv, /* inspector */ + &synctex_vispector_hv, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark kern node. +# endif + +static const synctex_data_model_s synctex_data_model_tlchvw = { + synctex_data_tag_idx, /* tag */ + synctex_data_line_idx, /* line */ + synctex_data_column_idx,/* column */ + synctex_data_h_idx, /* h */ + synctex_data_v_idx, /* v */ + synctex_data_width_idx, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_tlchvw_max +}; +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchvw_max]; +} synctex_node_kern_s; + +/* kern node creator */ +DEFINE_synctex_new_scanned_NODE(kern) + +static void _synctex_log_kern_node(synctex_node_p node); +static char * _synctex_abstract_kern(synctex_node_p node); +static void _synctex_display_kern(synctex_node_p node); + +static synctex_inspector_s synctex_inspector_kern = { + &_synctex_data_h, + &_synctex_data_v, + &_synctex_data_width, + &_synctex_int_none, + &_synctex_int_none, +}; +static float __synctex_kern_visible_h(synctex_node_p node); +static float __synctex_kern_visible_width(synctex_node_p node); +static synctex_vispector_s synctex_vispector_kern = { + &__synctex_kern_visible_h, + &__synctex_node_visible_v, + &__synctex_kern_visible_width, + &_synctex_float_none, + &_synctex_float_none, +}; + +static synctex_class_s synctex_class_kern = { + NULL, /* No scanner yet */ + synctex_node_type_kern, /* Node type */ + &_synctex_new_kern, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_kern_node, /* log */ + &_synctex_display_kern, /* display */ + &_synctex_abstract_kern, /* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_tlchvw, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_kern, /* inspector */ + &synctex_vispector_kern, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark glue. +# endif + +/* glue node creator */ +typedef synctex_node_tlchv_s synctex_node_glue_s; +DEFINE_synctex_new_scanned_NODE(glue) + +static char * _synctex_abstract_glue(synctex_node_p node); +static void _synctex_display_glue(synctex_node_p node); + +static synctex_class_s synctex_class_glue = { + NULL, /* No scanner yet */ + synctex_node_type_glue, /* Node type */ + &_synctex_new_glue, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_tlchv_node, /* log */ + &_synctex_display_glue, /* display */ + &_synctex_abstract_glue, /* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_tlchv, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_hv, /* inspector */ + &synctex_vispector_hv, /* vispector */ +}; + +/* The small nodes correspond to glue and boundary nodes. */ + +# ifdef SYNCTEX_NOTHING +# pragma mark rule. +# endif + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max]; +} synctex_node_rule_s; + +DEFINE_synctex_new_scanned_NODE(rule) + +static void _synctex_log_rule(synctex_node_p node); +static char * _synctex_abstract_rule(synctex_node_p node); +static void _synctex_display_rule(synctex_node_p node); + +static float __synctex_rule_visible_h(synctex_node_p node); +static float __synctex_rule_visible_v(synctex_node_p node); +static float __synctex_rule_visible_width(synctex_node_p node); +static float __synctex_rule_visible_height(synctex_node_p node); +static float __synctex_rule_visible_depth(synctex_node_p node); +static synctex_vispector_s synctex_vispector_rule = { + &__synctex_rule_visible_h, + &__synctex_rule_visible_v, + &__synctex_rule_visible_width, + &__synctex_rule_visible_height, + &__synctex_rule_visible_depth, +}; + +static synctex_class_s synctex_class_rule = { + NULL, /* No scanner yet */ + synctex_node_type_rule, /* Node type */ + &_synctex_new_rule, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_rule, /* log */ + &_synctex_display_rule, /* display */ + &_synctex_abstract_rule, /* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_box, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_box, /* inspector */ + &synctex_vispector_rule, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark boundary. +# endif + +/* boundary node creator */ +typedef synctex_node_tlchv_s synctex_node_boundary_s; +DEFINE_synctex_new_scanned_NODE(boundary) + +static char * _synctex_abstract_boundary(synctex_node_p node); +static void _synctex_display_boundary(synctex_node_p node); + +static synctex_class_s synctex_class_boundary = { + NULL, /* No scanner yet */ + synctex_node_type_boundary, /* Node type */ + &_synctex_new_boundary, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_tlchv_node, /* log */ + &_synctex_display_boundary, /* display */ + &_synctex_abstract_boundary,/* abstract */ + &synctex_tree_model_spf, /* tree model */ + &synctex_data_model_tlchv, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_hv, /* inspector */ + &synctex_vispector_hv, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark box boundary. +# endif + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spfa_max+synctex_data_tlchv_max]; +} synctex_node_box_bdry_s; + +#define DEFINE_synctex_new_unscanned_NODE(NAME)\ +SYNCTEX_INLINE static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\ + if (scanner) {\ + synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\ + if (node) {\ + node->class_ = scanner->class_+synctex_node_type_##NAME;\ + SYNCTEX_DID_NEW(node); \ + }\ + return node;\ + }\ + return NULL;\ +} +DEFINE_synctex_new_unscanned_NODE(box_bdry) + +static char * _synctex_abstract_box_bdry(synctex_node_p node); +static void _synctex_display_box_bdry(synctex_node_p node); + +static synctex_class_s synctex_class_box_bdry = { + NULL, /* No scanner yet */ + synctex_node_type_box_bdry, /* Node type */ + &_synctex_new_box_bdry, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_tlchv_node, /* log */ + &_synctex_display_box_bdry, /* display */ + &_synctex_abstract_box_bdry,/* display */ + &synctex_tree_model_spfa, /* tree model */ + &synctex_data_model_tlchv, /* data model */ + &synctex_tlcpector_default, /* tlcpector */ + &synctex_inspector_hv, /* inspector */ + &synctex_vispector_hv, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark hbox proxy. +# endif + +/** + * Standard nodes refer to TeX nodes: math, kern, boxes... + * Proxy nodes are used to support forms. + * A form is parsed as a tree of standard nodes starting + * at the top left position. + * When a reference is used, the form is duplicated + * to the location specified by the reference. + * As the same form can be duplicated at different locations, + * the geometrical information is relative to its own top left point. + * As we need absolute locations, we use proxy nodes. + * A proxy node records an offset and the target node. + * The target partly acts as a delegate. + * The h and v position of the proxy node is the h and v + * position of the target shifted by the proxy's offset. + * The width, height and depth are not sensitive to offsets. + * When are proxies created ? + * 1) when the synctex file has been parsed, all the form refs + * are replaced by proxies to the content of a form. + * This content is a node with siblings (actually none). + * Those root proxies have the parent of the ref they replace, + * so their parents exist and are no proxy. + * Moreover, if they have no sibling, it means that their target have no + * sibling as well. + * Such nodes are called root proxies. + * 2) On the fly, when a proxy is asked for its child + * (or sibling) and has none, a proxy to its target's child + * (or sibling) is created if any. There are only 2 possible situations: + * either the newly created proxy is the child of a proxy, + * or it is the sibling of a proxy created on the fly. + * In both cases, the parent is a proxy with children. + * Such nodes are called child proxies. + * How to compute the offset of a proxy ? + * The offset of root proxy objects is exactly + * the offset of the ref they replace. + * The offset of other proxies is their owner's, + * except when pointing to a root proxy. + * What happens for cascading forms ? + * Here is an example diagram + * + * At parse time, the arrow means "owns": + * sheet0 -> ref_to1 + * + * target1 -> ref_to2 + * + * target2 -> child22 + * + * After replacing the refs: + * sheet0 -> proxy00 -> proxy01 -> proxy02 + * | | | + * target1 -> proxy11 -> proxy12 + * | | + * target2 -> proxy22 + * + * proxy00, proxy11 and proxy22 are root proxies. + * Their offset is the one of the ref they replace + * proxy01, proxy02 and proxy12 are child proxies. + * Their proxy is the one of their parent. + * Optimization. + * After all the refs are replaced, there are only root nodes + * targeting standard node. We make sure that each child proxy + * also targets a standard node. + * It is possible for a proxy to have a standard sibling + * whereas its target has no sibling at all. Root proxies + * are such nodes, and are the only ones. + * The consequence is that proxies created on the fly + * must take into account this situation. + */ + +/* A proxy to a hbox. + * A proxy do have a target, which can be a proxy + */ + +static const synctex_tree_model_s synctex_tree_model_proxy_hbox = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + synctex_tree_sp_child_idx, /* child */ + synctex_tree_spc_friend_idx, /* friend */ + synctex_tree_spcf_last_idx, /* last */ + synctex_tree_spcfl_next_hbox_idx, /* next_hbox */ + -1, /* arg_sibling */ + synctex_tree_spcfln_target_idx, /* target */ + synctex_tree_spcflnt_proxy_hbox_max +}; +static const synctex_data_model_s synctex_data_model_proxy = { + -1, /* tag */ + -1, /* line */ + -1, /* column */ + synctex_data_proxy_h_idx, /* h */ + synctex_data_proxy_v_idx, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + -1, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_proxy_hv_max +}; +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spcflnt_proxy_hbox_max+synctex_data_proxy_hv_max]; +} synctex_node_proxy_hbox_s; + +/* box proxy node creator */ +DEFINE_synctex_new_unscanned_NODE(proxy_hbox) + +static void _synctex_log_proxy(synctex_node_p node); +static char * _synctex_abstract_proxy_hbox(synctex_node_p node); +static void _synctex_display_proxy_hbox(synctex_node_p node); + +static int _synctex_proxy_tag(synctex_node_p); +static int _synctex_proxy_line(synctex_node_p); +static int _synctex_proxy_column(synctex_node_p); + +static synctex_tlcpector_s synctex_tlcpector_proxy = { + &_synctex_proxy_tag, + &_synctex_proxy_line, + &_synctex_proxy_column, +}; +static int _synctex_proxy_h(synctex_node_p); +static int _synctex_proxy_v(synctex_node_p); +static int _synctex_proxy_width(synctex_node_p); +static int _synctex_proxy_height(synctex_node_p); +static int _synctex_proxy_depth(synctex_node_p); +static synctex_inspector_s synctex_inspector_proxy_box = { + &_synctex_proxy_h, + &_synctex_proxy_v, + &_synctex_proxy_width, + &_synctex_proxy_height, + &_synctex_proxy_depth, +}; + +static float __synctex_proxy_visible_h(synctex_node_p); +static float __synctex_proxy_visible_v(synctex_node_p); +static float __synctex_proxy_visible_width(synctex_node_p); +static float __synctex_proxy_visible_height(synctex_node_p); +static float __synctex_proxy_visible_depth(synctex_node_p); + +static synctex_vispector_s synctex_vispector_proxy_box = { + &__synctex_proxy_visible_h, + &__synctex_proxy_visible_v, + &__synctex_proxy_visible_width, + &__synctex_proxy_visible_height, + &__synctex_proxy_visible_depth, +}; + +static synctex_class_s synctex_class_proxy_hbox = { + NULL, /* No scanner yet */ + synctex_node_type_proxy_hbox, /* Node type */ + &_synctex_new_proxy_hbox, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_proxy, /* log */ + &_synctex_display_proxy_hbox, /* display */ + &_synctex_abstract_proxy_hbox, /* abstract */ + &synctex_tree_model_proxy_hbox, /* tree model */ + &synctex_data_model_proxy, /* data model */ + &synctex_tlcpector_proxy, /* tlcpector */ + &synctex_inspector_proxy_box, /* inspector */ + &synctex_vispector_proxy_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark vbox proxy. +# endif + +/* A proxy to a vbox. */ + +static const synctex_tree_model_s synctex_tree_model_proxy_vbox = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + synctex_tree_sp_child_idx, /* child */ + synctex_tree_spc_friend_idx, /* friend */ + synctex_tree_spcf_last_idx, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + synctex_tree_spcfl_target_idx, /* target */ + synctex_tree_spcflt_proxy_vbox_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spcflt_proxy_vbox_max+synctex_data_proxy_hv_max]; +} synctex_node_proxy_vbox_s; + +/* box proxy node creator */ +DEFINE_synctex_new_unscanned_NODE(proxy_vbox) + +static void _synctex_log_proxy(synctex_node_p node); +static char * _synctex_abstract_proxy_vbox(synctex_node_p node); +static void _synctex_display_proxy_vbox(synctex_node_p node); + +static synctex_class_s synctex_class_proxy_vbox = { + NULL, /* No scanner yet */ + synctex_node_type_proxy_vbox, /* Node type */ + &_synctex_new_proxy_vbox, /* creator */ + &_synctex_free_node, /* destructor */ + &_synctex_log_proxy, /* log */ + &_synctex_display_proxy_vbox, /* display */ + &_synctex_abstract_proxy_vbox, /* abstract */ + &synctex_tree_model_proxy_vbox, /* tree model */ + &synctex_data_model_proxy, /* data model */ + &synctex_tlcpector_proxy, /* tlcpector */ + &synctex_inspector_proxy_box, /* inspector */ + &synctex_vispector_proxy_box, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark proxy. +# endif + +/** + * A proxy to a node but a box. + */ + +static const synctex_tree_model_s synctex_tree_model_proxy = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + -1, /* child */ + synctex_tree_sp_friend_idx, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + synctex_tree_spf_target_idx,/* target */ + synctex_tree_spft_proxy_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spft_proxy_max+synctex_data_proxy_hv_max]; +} synctex_node_proxy_s; + +/* proxy node creator */ +DEFINE_synctex_new_unscanned_NODE(proxy) + +static void _synctex_log_proxy(synctex_node_p node); +static char * _synctex_abstract_proxy(synctex_node_p node); +static void _synctex_display_proxy(synctex_node_p node); + +static synctex_vispector_s synctex_vispector_proxy = { + &__synctex_proxy_visible_h, + &__synctex_proxy_visible_v, + &__synctex_proxy_visible_width, + &_synctex_float_none, + &_synctex_float_none, +}; + +static synctex_class_s synctex_class_proxy = { + NULL, /* No scanner yet */ + synctex_node_type_proxy, /* Node type */ + &_synctex_new_proxy, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_proxy, /* log */ + &_synctex_display_proxy, /* display */ + &_synctex_abstract_proxy, /* abstract */ + &synctex_tree_model_proxy, /* tree model */ + &synctex_data_model_proxy, /* data model */ + &synctex_tlcpector_proxy, /* tlcpector */ + &synctex_inspector_proxy_box, /* inspector */ + &synctex_vispector_proxy, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark last proxy. +# endif + +/** + * A proxy to the last proxy/box boundary. + */ + +static const synctex_tree_model_s synctex_tree_model_proxy_last = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + -1, /* child */ + synctex_tree_sp_friend_idx, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + synctex_tree_spf_arg_sibling_idx, /* arg_sibling */ + synctex_tree_spfa_target_idx, /* target */ + synctex_tree_spfat_proxy_last_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spfat_proxy_last_max+synctex_data_proxy_hv_max]; +} synctex_node_proxy_last_s; + +/* proxy node creator */ +DEFINE_synctex_new_unscanned_NODE(proxy_last) + +static void _synctex_log_proxy(synctex_node_p node); +static char * _synctex_abstract_proxy(synctex_node_p node); +static void _synctex_display_proxy(synctex_node_p node); + +static synctex_class_s synctex_class_proxy_last = { + NULL, /* No scanner yet */ + synctex_node_type_proxy_last, /* Node type */ + &_synctex_new_proxy, /* creator */ + &_synctex_free_leaf, /* destructor */ + &_synctex_log_proxy, /* log */ + &_synctex_display_proxy, /* display */ + &_synctex_abstract_proxy, /* abstract */ + &synctex_tree_model_proxy_last, /* tree model */ + &synctex_data_model_proxy, /* data model */ + &synctex_tlcpector_proxy, /* tlcpector */ + &synctex_inspector_proxy_box, /* inspector */ + &synctex_vispector_proxy, /* vispector */ +}; + +# ifdef SYNCTEX_NOTHING +# pragma mark handle. +# endif + +/** + * A handle node. + * A handle is never the target of a proxy + * or another handle. + * The child of a handle is always a handle if any. + * The sibling of a handle is always a handle if any. + * The parent of a handle is always a handle if any. + */ + +static const synctex_tree_model_s synctex_tree_model_handle = { + synctex_tree_sibling_idx, /* sibling */ + synctex_tree_s_parent_idx, /* parent */ + synctex_tree_sp_child_idx, /* child */ + -1, /* friend */ + -1, /* last */ + -1, /* next_hbox */ + -1, /* arg_sibling */ + synctex_tree_spc_target_idx,/* target */ + synctex_tree_spct_handle_max +}; + +static const synctex_data_model_s synctex_data_model_handle = { + -1, /* tag */ + -1, /* line */ + -1, /* column */ + -1, /* h */ + -1, /* v */ + -1, /* width */ + -1, /* height */ + -1, /* depth */ + -1, /* mean_line */ + synctex_data_handle_w_idx, /* weight */ + -1, /* h_V */ + -1, /* v_V */ + -1, /* width_V */ + -1, /* height_V */ + -1, /* depth_V */ + -1, /* name */ + -1, /* page */ + synctex_data_handle_w_max +}; + +typedef struct { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; + synctex_data_u data[synctex_tree_spct_handle_max+synctex_data_handle_w_max]; +} synctex_node_handle_s; + +/* handle node creator */ +DEFINE_synctex_new_unscanned_NODE(handle) + +static void _synctex_log_handle(synctex_node_p node); +static char * _synctex_abstract_handle(synctex_node_p node); +static void _synctex_display_handle(synctex_node_p node); + +static synctex_class_s synctex_class_handle = { + NULL, /* No scanner yet */ + synctex_node_type_handle, /* Node type */ + &_synctex_new_handle, /* creator */ + &_synctex_free_handle, /* destructor */ + &_synctex_log_handle, /* log */ + &_synctex_display_handle, /* display */ + &_synctex_abstract_handle, /* abstract */ + &synctex_tree_model_handle, /* tree model */ + &synctex_data_model_handle, /* data model */ + &synctex_tlcpector_proxy, /* tlcpector */ + &synctex_inspector_proxy_box, /* inspector */ + &synctex_vispector_proxy_box, /* vispector */ +}; + +SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target) { + if (target) { + synctex_node_p result = _synctex_new_handle(target->class_->scanner); + if (result) { + _synctex_tree_set_target(result,target); + return result; + } + } + return NULL; +} +SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_child(synctex_node_p child) { + if (child) { + synctex_node_p result = _synctex_new_handle(child->class_->scanner); + if (result) { + _synctex_tree_set_child(result,child); + return result; + } + } + return NULL; +} + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Navigation +# endif +synctex_node_p synctex_node_parent(synctex_node_p node) +{ + return _synctex_tree_parent(node); +} +synctex_node_p synctex_node_parent_sheet(synctex_node_p node) +{ + while(node && synctex_node_type(node) != synctex_node_type_sheet) { + node = _synctex_tree_parent(node); + } + /* exit the while loop either when node is NULL or node is a sheet */ + return node; +} +synctex_node_p synctex_node_parent_form(synctex_node_p node) +{ + while(node && synctex_node_type(node) != synctex_node_type_form) { + node = _synctex_tree_parent(node); + } + /* exit the while loop either when node is NULL or node is a form */ + return node; +} + +/** + * The returned proxy will be the child or a sibling of source. + * The returned proxy has no parent, child nor sibling. + * Used only by __synctex_replace_ref. + * argument to_node: a box, not a proxy nor anything else. + */ +SYNCTEX_INLINE static synctex_node_p __synctex_new_proxy_from_ref_to(synctex_node_p ref, synctex_node_p to_node) { + synctex_node_p proxy = NULL; + if (!ref || !to_node) { + return NULL; + } + switch(synctex_node_type(to_node)) { + case synctex_node_type_vbox: + proxy = _synctex_new_proxy_vbox(ref->class_->scanner); + break; + case synctex_node_type_hbox: + proxy = _synctex_new_proxy_hbox(ref->class_->scanner); + break; + default: + _synctex_error("! __synctex_new_proxy_from_ref_to. Unexpected form child (%s). Please report.", synctex_node_isa(to_node)); + return NULL; + } + if (!proxy) { + _synctex_error("! __synctex_new_proxy_from_ref_to. Internal error. Please report."); + return NULL; + } + _synctex_data_set_h(proxy, _synctex_data_h(ref)); + _synctex_data_set_v(proxy, _synctex_data_v(ref)-_synctex_data_height(to_node)); + _synctex_tree_set_target(proxy,to_node); +# if defined(SYNCTEX_USE_CHARINDEX) + proxy->line_index=to_node?to_node->line_index:0; + proxy->char_index=to_node?to_node->char_index:0; +# endif + return proxy; +} +/** + * The returned proxy will be the child or a sibling of owning_proxy. + * The returned proxy has no parent, nor child. + * Used only by synctex_node_child and synctex_node_sibling + * to create proxies on the fly. + * If the to_node has an already computed sibling, + * then the returned proxy has itself a sibling + * pointing to that already computed sibling. + */ +SYNCTEX_INLINE static synctex_node_p __synctex_new_child_proxy_to(synctex_node_p owner, synctex_node_p to_node) { + synctex_node_p proxy = NULL; + synctex_node_p target = to_node; + if (!owner) { + return NULL; + } + switch(synctex_node_type(target)) { + case synctex_node_type_vbox: + if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) { + exit_standard: + _synctex_data_set_h(proxy, _synctex_data_h(owner)); + _synctex_data_set_v(proxy, _synctex_data_v(owner)); + exit0: + _synctex_tree_set_target(proxy,target); +# if defined(SYNCTEX_USE_CHARINDEX) + proxy->line_index=to_node?to_node->line_index:0; + proxy->char_index=to_node?to_node->char_index:0; +# endif + return proxy; + }; + break; + case synctex_node_type_proxy_vbox: + if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) { + exit_proxy: + target = _synctex_tree_target(to_node); + _synctex_data_set_h(proxy, _synctex_data_h(owner)+_synctex_data_h(to_node)); + _synctex_data_set_v(proxy, _synctex_data_v(owner)+_synctex_data_v(to_node)); + goto exit0; + }; + break; + case synctex_node_type_hbox: + if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) { + goto exit_standard; + }; + break; + case synctex_node_type_proxy_hbox: + if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) { + goto exit_proxy; + }; + break; + case synctex_node_type_proxy: + case synctex_node_type_proxy_last: + if ((proxy = _synctex_new_proxy(owner->class_->scanner))) { + goto exit_proxy; + }; + break; + default: + if ((proxy = _synctex_new_proxy(owner->class_->scanner))) { + goto exit_standard; + }; + break; + } + _synctex_error("! __synctex_new_child_proxy_to. " + "Internal error. " + "Please report."); + return NULL; +} +SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling); +typedef struct synctex_nns_t { + synctex_node_p first; + synctex_node_p last; + synctex_status_t status; +} synctex_nns_s; +/** + * Given a target node, create a list of proxies. + * The first proxy points to the target node, + * its sibling points to the target's sibling and so on. + * Returns the first created proxy, the last one and + * an error status. + */ +SYNCTEX_INLINE static synctex_nns_s _synctex_new_child_proxies_to(synctex_node_p owner, synctex_node_p to_node) { + synctex_nns_s nns = {NULL,NULL,SYNCTEX_STATUS_OK}; + if ((nns.first = nns.last = __synctex_new_child_proxy_to(owner,to_node))) { + synctex_node_p to_next_sibling = __synctex_tree_sibling(to_node); + synctex_node_p to_sibling; + while ((to_sibling = to_next_sibling)) { + synctex_node_p sibling; + if ((to_next_sibling = __synctex_tree_sibling(to_sibling))) { + /* This is not the last sibling */ + if((sibling = __synctex_new_child_proxy_to(owner,to_sibling))) { + _synctex_tree_set_sibling(nns.last,sibling); + nns.last = sibling; + continue; + } else { + _synctex_error("! _synctex_new_child_proxy_to. " + "Internal error (1). " + "Please report."); + nns.status = SYNCTEX_STATUS_ERROR; + } + } else if((sibling = _synctex_new_proxy_last(owner->class_->scanner))) { + _synctex_tree_set_sibling(nns.last,sibling); + nns.last = sibling; + _synctex_data_set_h(nns.last, _synctex_data_h(nns.first)); + _synctex_data_set_v(nns.last, _synctex_data_v(nns.first)); + _synctex_tree_set_target(nns.last,to_sibling); +# if defined(SYNCTEX_USE_CHARINDEX) + nns.last->line_index=to_sibling->line_index; + nns.last->char_index=to_sibling->char_index; +# endif + } else { + _synctex_error("! _synctex_new_child_proxy_to. " + "Internal error (2). " + "Please report."); + nns.status = SYNCTEX_STATUS_ERROR; + } + break; + } + } + return nns; +} +static char * _synctex_node_abstract(synctex_node_p node); +SYNCTEX_INLINE static synctex_node_p synctex_tree_set_friend(synctex_node_p node,synctex_node_p new_friend) { +#if SYNCTEX_DEBUG + synctex_node_p F = new_friend; + while (F) { + if (node == F) { + printf("THIS IS AN ERROR\n"); + F = new_friend; + while (F) { + printf("%s\n",_synctex_node_abstract(F)); + if (node == F) { + return NULL; + } + F = _synctex_tree_friend(F); + } + return NULL; + } + F = _synctex_tree_friend(F); + } +#endif + return new_friend?_synctex_tree_set_friend(node,new_friend):_synctex_tree_reset_friend(node); +} +/** + * + */ +SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend(synctex_node_p node, int i) { + synctex_node_p old = NULL; + if (i>=0) { + i = i%(node->class_->scanner->number_of_lists); + old = synctex_tree_set_friend(node,(node->class_->scanner->lists_of_friends)[i]); + (node->class_->scanner->lists_of_friends)[i] = node; +#if SYNCTEX_DEBUG>500 + printf("tl(%i)=>",i); + synctex_node_log(node); + if (synctex_node_parent_form(node)) { + printf("! ERROR. No registration expected!\n"); + } +#endif + } + return old; +} +/** + * All proxies have tlc attributes, on behalf of their target. + * The purpose is to register all af them. + * - argument node: is the proxy, must not be NULL + */ +SYNCTEX_INLINE static synctex_node_p __synctex_proxy_make_friend_and_next_hbox(synctex_node_p node) { + synctex_node_p old = NULL; + synctex_node_p target = _synctex_tree_target(node); + if (target) { + int i = _synctex_data_tag(target)+_synctex_data_line(target); + old = __synctex_node_make_friend(node,i); + } else { + old = __synctex_tree_reset_friend(node); + } + if (synctex_node_type(node) == synctex_node_type_proxy_hbox) { + synctex_node_p sheet = synctex_node_parent_sheet(node); + if (sheet) { + _synctex_tree_set_next_hbox(node,_synctex_tree_next_hbox(sheet)); + _synctex_tree_set_next_hbox(sheet,node); + } + } + return old; +} +/** + * Register a node which have tag, line and column. + * - argument node: the node + */ +SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node) { + int i = synctex_node_tag(node)+synctex_node_line(node); + return __synctex_node_make_friend(node,i); +} +/** + * Register a node which have tag, line and column. + * Does nothing if the argument is NULL. + * Calls __synctex_node_make_friend_tlc. + * - argument node: the node + */ +SYNCTEX_INLINE static void _synctex_node_make_friend_tlc(synctex_node_p node) { + if (node) { + __synctex_node_make_friend_tlc(node); + } +} +static synctex_node_p _synctex_node_set_child(synctex_node_p node, synctex_node_p new_child); +/** + * The (first) child of the node, if any, NULL otherwise. + * At parse time, non void box nodes have children. + * All other nodes have no children. + * In order to support pdf forms, proxies are created + * to place form nodes at real locations. + * Ref nodes are replaced by root proxies targeting + * form contents. If root proxies have no children, + * they are created on the fly as proxies to the + * children of the targeted box. + * As such, proxies created here are targeting a + * node that belongs to a form. + * This is the only place where child proxies are created. + */ +synctex_node_p synctex_node_child(synctex_node_p node) { + synctex_node_p child = NULL; + synctex_node_p target = NULL; + if ((child = _synctex_tree_child(node))) { + return child; + } else if ((target = _synctex_tree_target(node))) { + if ((child = synctex_node_child(target))) { + /* This is a proxy with no child + * which target does have a child. */ + synctex_nns_s nns = _synctex_new_child_proxies_to(node, child); + if (nns.first) { + _synctex_node_set_child(node,nns.first); + return nns.first; + } else { + _synctex_error("! synctex_node_child. Internal inconsistency. Please report."); + } + } + } + return NULL; +} +/* + * Set the parent/child bound. + * Things get complicated when new_child has siblings. + * The caller is responsible for releasing the returned value. + */ +static synctex_node_p _synctex_node_set_child(synctex_node_p parent, synctex_node_p new_child) { + if (parent) { + synctex_node_p old = _synctex_tree_set_child(parent,new_child); + synctex_node_p last_child = NULL; + synctex_node_p child; + if ((child = old)) { + do { + _synctex_tree_reset_parent(child); + } while ((child = __synctex_tree_sibling(child))); + } + if ((child = new_child)) { + do { + _synctex_tree_set_parent(child,parent); + last_child = child; + } while ((child = __synctex_tree_sibling(child))); + } + _synctex_tree_set_last(parent,last_child); + return old; + } + return NULL; +} + +/* The last child of the given node, or NULL. + */ +synctex_node_p synctex_node_last_child(synctex_node_p node) { + return _synctex_tree_last(node); +} +/** + * All nodes siblings are properly set up at parse time + * except for non root proxies. + */ +synctex_node_p synctex_node_sibling(synctex_node_p node) { + return node? __synctex_tree_sibling(node): NULL; +} +/** + * All the _synctex_tree_... methods refer to the tree model. + * __synctex_tree_... methods are low level. + */ +/** + * Replace the sibling. + * Connect to the arg_sibling of the new_sibling if relevant. + * - returns the old sibling. + * The caller is responsible for releasing the old sibling. + * The bound to the parent is managed below. + */ +SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling) { + if (node == new_sibling) { + printf("BOF\n"); + } + synctex_node_p old = node? __synctex_tree_set_sibling(node,new_sibling): NULL; + _synctex_tree_set_arg_sibling(new_sibling,node); + return old; +} +/** + * Replace the sibling. + * Set the parent of the new sibling (and further siblings) + * to the parent of the receiver. + * Also set the last sibling of parent. + * - argument new_sibling: must not be NULL. + * - returns the old sibling. + * The caller is responsible for releasing the old sibling. + */ +static synctex_node_p _synctex_node_set_sibling(synctex_node_p node, synctex_node_p new_sibling) { + if (node && new_sibling) { + synctex_node_p old = _synctex_tree_set_sibling(node,new_sibling); + if (_synctex_tree_has_parent(node)) { + synctex_node_p parent = __synctex_tree_parent(node); + if (parent) { + synctex_node_p N = new_sibling; + while (synctex_YES) { + if (_synctex_tree_has_parent(N)) { + __synctex_tree_set_parent(N,parent); + _synctex_tree_set_last(parent,N); + N = __synctex_tree_sibling(N); + continue; + } else if (N) { + _synctex_error("! synctex_node_sibling. " + "Internal inconsistency. " + "Please report."); + } + break; + } + } + } + return old; + } + return NULL; +} +/** + * The last sibling of the given node, or NULL with node. + */ +synctex_node_p synctex_node_last_sibling(synctex_node_p node) { + synctex_node_p sibling; + do { + sibling = node; + } while((node = synctex_node_sibling(node))); + return sibling; +} +/** + * The next nodes corresponds to a deep first tree traversal. + * Does not create child proxies as side effect contrary to + * the synctex_node_next method above. + * May loop infinitely many times if the tree + * is not properly built (contains loops). + */ +SYNCTEX_INLINE static synctex_node_p _synctex_node_sibling_or_parents(synctex_node_p node) { + while (node) { + synctex_node_p N; + if ((N = __synctex_tree_sibling(node))) { + return N; + } else if ((node = _synctex_tree_parent(node))) { + if (synctex_node_type(node) == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */ + return NULL; + } else if (synctex_node_type(node) == synctex_node_type_form) { + return NULL; + } + } else { + return NULL; + } + } + return NULL; +} +/** + * The next nodes corresponds to a deep first tree traversal. + * Creates child proxies as side effect. + * May loop infinitely many times if the tree + * is not properly built (contains loops). + */ +synctex_node_p synctex_node_next(synctex_node_p node) { + synctex_node_p N = synctex_node_child(node); + if (N) { + return N; + } + return _synctex_node_sibling_or_parents(node); +} +/** + * The next nodes corresponds to a deep first tree traversal. + * Does not create child proxies as side effect contrary to + * the synctex_node_next method above. + * May loop infinitely many times if the tree + * is not properly built (contains loops). + */ +synctex_node_p _synctex_node_next(synctex_node_p node) { + synctex_node_p N = _synctex_tree_child(node); + if (N) { + return N; + } + return _synctex_node_sibling_or_parents(node); +} +/** + * The node which argument is the sibling. + * - return: NULL if the argument has no parent or + * is the first child of its parent. + * - Input nodes have no arg siblings + */ +synctex_node_p synctex_node_arg_sibling(synctex_node_p node) { +#if 1 + return _synctex_tree_arg_sibling(node); +#else + synctex_node_p N = _synctex_tree_parent(node); + if ((N = _synctex_tree_child(N))) { + do { + synctex_node_p NN = __synctex_tree_sibling(N); + if (NN == node) { + return N; + } + N = NN; + } while (N); + } + return N; +#endif +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark CLASS +# endif + +/* Public node accessor: the type */ +synctex_node_type_t synctex_node_type(synctex_node_p node) { + return node? node->class_->type: synctex_node_type_none; +} + +/* Public node accessor: the type */ +synctex_node_type_t synctex_node_target_type(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + return (((target)->class_))->type; + } else if (node) { + return (((node)->class_))->type; + } + return synctex_node_type_none; +} + +/* Public node accessor: the human readable type */ +const char * synctex_node_isa(synctex_node_p node) { + static const char * isa[synctex_node_number_of_types] = + {"Not a node", + "input", + "sheet", + "form", + "ref", + "vbox", + "void vbox", + "hbox", + "void hbox", + "kern", + "glue", + "rule", + "math", + "boundary", + "box_bdry", + "proxy", + "last proxy", + "vbox proxy", + "hbox proxy", + "handle"}; + return isa[synctex_node_type(node)]; +} + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark LOG +# endif + +/* Public node logger */ +void synctex_node_log(synctex_node_p node) { + SYNCTEX_MSG_SEND(node,log); +} + +static void _synctex_log_input(synctex_node_p node) { + if (node) { + printf("%s:%i,%s(%i)\n",synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_name(node), + _synctex_data_line(node)); + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n", + (void *)__synctex_tree_sibling(node)); + } +} + +static void _synctex_log_sheet(synctex_node_p node) { + if (node) { + printf("%s:%i",synctex_node_isa(node),_synctex_data_page(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); + } +} + +static void _synctex_log_form(synctex_node_p node) { + if (node) { + printf("%s:%i",synctex_node_isa(node),_synctex_data_tag(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + } +} + +static void _synctex_log_ref(synctex_node_p node) { + if (node) { + printf("%s:%i:%i,%i", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + } +} + +static void _synctex_log_tlchv_node(synctex_node_p node) { + if (node) { + printf("%s:%i,%i,%i:%i,%i", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_column(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + } +} + +static void _synctex_log_kern_node(synctex_node_p node) { + if (node) { + printf("%s:%i,%i,%i:%i,%i:%i", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_column(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + } +} + +static void _synctex_log_rule(synctex_node_p node) { + if (node) { + printf("%s:%i,%i,%i:%i,%i", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_column(node), + _synctex_data_h(node), + _synctex_data_v(node)); + printf(":%i",_synctex_data_width(node)); + printf(",%i",_synctex_data_height(node)); + printf(",%i",_synctex_data_depth(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + } +} + +static void _synctex_log_void_box(synctex_node_p node) { + if (node) { + printf("%s",synctex_node_isa(node)); + printf(":%i",_synctex_data_tag(node)); + printf(",%i",_synctex_data_line(node)); + printf(",%i",_synctex_data_column(node)); + printf(":%i",_synctex_data_h(node)); + printf(",%i",_synctex_data_v(node)); + printf(":%i",_synctex_data_width(node)); + printf(",%i",_synctex_data_height(node)); + printf(",%i",_synctex_data_depth(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + } +} + +static void _synctex_log_vbox(synctex_node_p node) { + if (node) { + printf("%s",synctex_node_isa(node)); + printf(":%i",_synctex_data_tag(node)); + printf(",%i",_synctex_data_line(node)); + printf(",%i",_synctex_data_column(node)); + printf(":%i",_synctex_data_h(node)); + printf(",%i",_synctex_data_v(node)); + printf(":%i",_synctex_data_width(node)); + printf(",%i",_synctex_data_height(node)); + printf(",%i",_synctex_data_depth(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); + } +} + +static void _synctex_log_hbox(synctex_node_p node) { + if (node) { + printf("%s",synctex_node_isa(node)); + printf(":%i",_synctex_data_tag(node)); + printf(",%i~%i*%i",_synctex_data_line(node),_synctex_data_mean_line(node),_synctex_data_weight(node)); + printf(",%i",_synctex_data_column(node)); + printf(":%i",_synctex_data_h(node)); + printf(",%i",_synctex_data_v(node)); + printf(":%i",_synctex_data_width(node)); + printf(",%i",_synctex_data_height(node)); + printf(",%i",_synctex_data_depth(node)); + printf("/%i",_synctex_data_h_V(node)); + printf(",%i",_synctex_data_v_V(node)); + printf(":%i",_synctex_data_width_V(node)); + printf(",%i",_synctex_data_height_V(node)); + printf(",%i",_synctex_data_depth_V(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); + printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); + } +} +static void _synctex_log_proxy(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s",synctex_node_isa(node)); + printf(":%i",_synctex_data_h(node)); + printf(",%i",_synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); + printf(" ->%s\n",_synctex_node_abstract(N)); + } +} +static void _synctex_log_handle(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s",synctex_node_isa(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + printf("SELF:%p\n",(void *)node); + printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); + printf(" ->%s\n",_synctex_node_abstract(N)); + } +} + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SYNCTEX_DISPLAY +# endif + +int synctex_scanner_display_switcher(synctex_scanner_p scanR) { + return scanR->display_switcher; +} +void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher) { + scanR->display_switcher = switcher; +} +static const char * const _synctex_display_prompt = "................................"; + +static char * _synctex_scanner_display_prompt_down(synctex_scanner_p scanR) { + if (scanR->display_prompt>_synctex_display_prompt) { + --scanR->display_prompt; + } + return scanR->display_prompt; +} +static char * _synctex_scanner_display_prompt_up(synctex_scanner_p scanR) { + if (scanR->display_prompt+1<_synctex_display_prompt+strlen(_synctex_display_prompt)) { + ++scanR->display_prompt; + } + return scanR->display_prompt; +} + +void synctex_node_display(synctex_node_p node) { + if (node) { + synctex_scanner_p scanR = node->class_->scanner; + if (scanR) { + if (scanR->display_switcher<0) { + SYNCTEX_MSG_SEND(node, display); + } else if (scanR->display_switcher>0 && --scanR->display_switcher>0) { + SYNCTEX_MSG_SEND(node, display); + } else if (scanR->display_switcher-->=0) { + printf("%s Next display skipped. Reset display switcher.\n",node->class_->scanner->display_prompt); + } + } else { + SYNCTEX_MSG_SEND(node, display); + } + } +} +static char * _synctex_node_abstract(synctex_node_p node) { + SYNCTEX_PARAMETER_ASSERT(node || node->class_); + return (node && node->class_->abstract)? node->class_->abstract(node):"none"; +} + +SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node) { + synctex_node_p N = _synctex_tree_child(node); + if (N) { + _synctex_scanner_display_prompt_down(N->class_->scanner); + synctex_node_display(N); + _synctex_scanner_display_prompt_up(N->class_->scanner); + } +} + +SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node) { + synctex_node_display(__synctex_tree_sibling(node)); +} +#define SYNCTEX_ABSTRACT_MAX 128 +static char * _synctex_abstract_input(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_name(node), + _synctex_data_line(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_input(synctex_node_p node) { + if (node) { + printf("Input:%i:%s(%i)" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + _synctex_data_tag(node), + _synctex_data_name(node), + _synctex_data_line(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + synctex_node_display(__synctex_tree_sibling(node)); + } +} + +static char * _synctex_abstract_sheet(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_page(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_sheet(synctex_node_p node) { + if (node) { + printf("%s{%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_page(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s}\n",node->class_->scanner->display_prompt); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_form(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"<%i...>" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + SYNCTEX_PRINT_CHARINDEX; + } + return abstract; +} + +static void _synctex_display_form(synctex_node_p node) { + if (node) { + printf("%s<%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s>\n",node->class_->scanner->display_prompt); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"[%i,%i:%i,%i:%i,%i,%i...]" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_vbox(synctex_node_p node) { + if (node) { + printf("%s[%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s]\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(%i,%i~%i*%i:%i,%i:%i,%i,%i...)" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_mean_line(node), + _synctex_data_weight(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_hbox(synctex_node_p node) { + if (node) { + printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_mean_line(node), + _synctex_data_weight(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s)\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_void_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"v%i,%i;%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_void_vbox(synctex_node_p node) { + if (node) { + printf("%sv%i,%i;%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_void_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"h%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_void_hbox(synctex_node_p node) { + if (node) { + printf("%sh%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_glue(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"glue:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_glue(synctex_node_p node) { + if (node) { + printf("%sglue:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_rule(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"rule:%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_rule(synctex_node_p node) { + if (node) { + printf("%srule:%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_math(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"math:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_math(synctex_node_p node) { + if (node) { + printf("%smath:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_kern(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"kern:%i,%i:%i,%i:%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_kern(synctex_node_p node) { + if (node) { + printf("%skern:%i,%i:%i,%i:%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_boundary(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"boundary:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_boundary(synctex_node_p node) { + if (node) { + printf("%sboundary:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_box_bdry(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"box bdry:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_box_bdry(synctex_node_p node) { + if (node) { + printf("%sbox bdry:%i,%i:%i,%i", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_ref(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"form ref:%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_ref(synctex_node_p node) { + if (node) { + printf("%sform ref:%i:%i,%i", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + _synctex_display_sibling(node); + } +} +static char * _synctex_abstract_proxy(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + synctex_node_p N = _synctex_tree_target(node); + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%i,%i:%i,%i/%p%s", + synctex_node_isa(node), + synctex_node_tag(node), + synctex_node_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + node, + _synctex_node_abstract(N)); + } + return abstract; +} +static void _synctex_display_proxy(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s%s:%i,%i:%i,%i", + node->class_->scanner->display_prompt, + synctex_node_isa(node), + synctex_node_tag(node), + synctex_node_line(node), + _synctex_data_h(node), + _synctex_data_v(node)); + if (N) { + printf("=%i,%i:%i,%i,%i->%s", + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node), + _synctex_node_abstract(N)); + } + printf("\n"); + _synctex_display_child(node); + _synctex_display_sibling(node); + } +} +static char * _synctex_abstract_proxy_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX, + "[*%i,%i:%i,%i:%i,%i,%i...*]" + SYNCTEX_PRINT_CHARINDEX_FMT, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_proxy_vbox(synctex_node_p node) { + if (node) { + printf("%s[*%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s*]\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_proxy_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(*%i,%i~%i*%i:%i,%i:%i,%i,%i...*)/%p" + SYNCTEX_PRINT_CHARINDEX_FMT, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_mean_line(node), + synctex_node_weight(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node), + node + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_proxy_hbox(synctex_node_p node) { + if (node) { + printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_mean_line(node), + synctex_node_weight(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s*)\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_handle(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + synctex_node_p N = _synctex_tree_target(node); + if (N && !N->class_) { + exit(1); + } + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%s", + synctex_node_isa(node), + (N?_synctex_node_abstract(N):"")); + } + return abstract; +} +static void _synctex_display_handle(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s%s(%i):->%s\n", + node->class_->scanner->display_prompt, + synctex_node_isa(node), + _synctex_data_weight(N), + _synctex_node_abstract(N)); + _synctex_display_child(node); + _synctex_display_sibling(node); + } +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark STATUS +# endif + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Prototypes +# endif +typedef struct { + size_t size; + synctex_status_t status; +} synctex_zs_s; +static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t size); +static synctex_status_t _synctex_next_line(synctex_scanner_p scanner); +static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string); + +typedef struct synctex_ns_t { + synctex_node_p node; + synctex_status_t status; +} synctex_ns_s; +static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner); +typedef struct { + float value; + synctex_status_t status; +} synctex_fs_s; +static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner); +static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box); +static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner); +int synctex_scanner_pre_x_offset(synctex_scanner_p scanner); +int synctex_scanner_pre_y_offset(synctex_scanner_p scanner); +const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner); + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SCANNER UTILITIES +# endif + +# define SYNCTEX_FILE (scanner->reader->file) + +/** + * Try to ensure that the buffer contains at least size bytes. + * Passing a huge size argument means the whole buffer length. + * Passing a 0 size argument means return the available buffer length, without reading the file. + * In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL. + * The size_t value returned is the number of bytes now available in the buffer. This is a nonnegative integer, it may take the value 0. + * It is the responsibility of the caller to test whether this size is conforming to its needs. + * Negative values may return in case of error, actually + * when there was an error reading the synctex file. + * - parameter scanner: The owning scanner. When NULL, returns SYNCTEX_STATUS_BAD_ARGUMENT. + * - parameter expected: expected number of bytes. + * - returns: a size and a status. + */ +static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected) { + size_t size = 0; + if (NULL == scanner) { + return (synctex_zs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + if (expected>scanner->reader->size){ + expected = scanner->reader->size; + } + size = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */ + if (expected<=size) { + /* There are already sufficiently many characters in the buffer */ + return (synctex_zs_s){size,SYNCTEX_STATUS_OK}; + } + if (SYNCTEX_FILE) { + /* Copy the remaining part of the buffer to the beginning, + * then read the next part of the file */ + int already_read = 0; +# if defined(SYNCTEX_USE_CHARINDEX) + scanner->reader->charindex_offset += SYNCTEX_CUR - SYNCTEX_START; +# endif + if (size) { + memmove(SYNCTEX_START, SYNCTEX_CUR, size); + } + SYNCTEX_CUR = SYNCTEX_START + size; /* the next character after the move, will change. */ + /* Fill the buffer up to its end */ + already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - size)); + if (already_read>0) { + /* We assume that 0already_read) { + /* There is a possible error in reading the file */ + int errnum = 0; + const char * error_string = gzerror(SYNCTEX_FILE, &errnum); + if (Z_ERRNO == errnum) { + /* There is an error in zlib caused by the file system */ + _synctex_error("gzread error from the file system (%i)",errno); + return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; + } else if (errnum) { + _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string); + return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; + } + } + /* Nothing was read, we are at the end of the file. */ + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + SYNCTEX_END = SYNCTEX_CUR; + SYNCTEX_CUR = SYNCTEX_START; + * SYNCTEX_END = '\0';/* Terminate the string properly.*/ + /* there might be a bit of text left */ + return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_EOF}; + } + /* We cannot enlarge the buffer because the end of the file was reached. */ + return (synctex_zs_s){size,SYNCTEX_STATUS_EOF}; +} + +/* Used when parsing the synctex file. + * Advance to the next character starting a line. + * Actually, only '\n' is recognized as end of line marker. + * On normal completion, the returned value is the number of unparsed characters available in the buffer. + * In general, it is a positive value, 0 meaning that the end of file was reached. + * -1 is returned in case of error, actually because there was an error while feeding the buffer. + * When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any. + * J. Laurens: Sat May 10 07:52:31 UTC 2008 + */ +static synctex_status_t _synctex_next_line(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + if (NULL == scanner) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } +infinite_loop: + while(SYNCTEX_CURreader->line_number; + return _synctex_buffer_get_available_size(scanner, 1).status; + } + ++SYNCTEX_CUR; + } + /* Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size + * will read another bunch of synctex file. Little by little, we advance to the end of the file. */ + status = _synctex_buffer_get_available_size(scanner, 1).status; + if (status<=SYNCTEX_STATUS_EOF) { + return status; + } + goto infinite_loop; +} + +/* Scan the given string. + * Both scanner and the_string must not be NULL, and the_string must not be 0 length. + * SYNCTEX_STATUS_OK is returned if the string is found, + * SYNCTEX_STATUS_EOF is returned when the EOF is reached, + * SYNCTEX_STATUS_NOT_OK is returned is the string is not found, + * an error status is returned otherwise. + * This is a critical method because buffering renders things more difficult. + * The given string might be as long as the maximum size_t value. + * As side effect, the buffer state may have changed if the given argument string can't fit into the buffer. + */ +static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string) { + size_t tested_len = 0; /* the number of characters at the beginning of the_string that match */ + size_t remaining_len = 0; /* the number of remaining characters of the_string that should match */ + size_t available = 0; + synctex_zs_s zs = {0,0}; + if (NULL == scanner || NULL == the_string) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + remaining_len = strlen(the_string); /* All the_string should match */ + if (0 == remaining_len) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + /* How many characters available in the buffer? */ + zs = _synctex_buffer_get_available_size(scanner,remaining_len); + if (zs.status=remaining_len) { + /* The buffer is sufficiently big to hold the expected number of characters. */ + if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { + return SYNCTEX_STATUS_NOT_OK; + } + return_OK: + /* Advance SYNCTEX_CUR to the next character after the_string. */ + SYNCTEX_CUR += remaining_len; + return SYNCTEX_STATUS_OK; + } else if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) { + /* No need to go further, this is not the expected string in the buffer. */ + return SYNCTEX_STATUS_NOT_OK; + } else if (SYNCTEX_FILE) { + /* The buffer was too small to contain remaining_len characters. + * We have to cut the string into pieces. */ + z_off_t offset = 0L; + /* the first part of the string is found, advance the_string to the next untested character. */ + the_string += zs.size; + /* update the remaining length and the parsed length. */ + remaining_len -= zs.size; + tested_len += zs.size; + SYNCTEX_CUR += zs.size; /* We validate the tested characters. */ + if (0 == remaining_len) { + /* Nothing left to test, we have found the given string. */ + return SYNCTEX_STATUS_OK; + } + /* We also have to record the current state of the file cursor because + * if the_string does not match, all this should be a totally blank operation, + * for which the file and buffer states should not be modified at all. + * In fact, the states of the buffer before and after this function are in general different + * but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR + * can be safely discarded. */ + offset = gztell(SYNCTEX_FILE); + /* offset now corresponds to the first character of the file that was not buffered. */ + /* SYNCTEX_CUR - SYNCTEX_START is the number of chars that where already buffered and + * that match the head of the_string. If in fine the_string does not match, all these chars must be recovered + * because the whole buffer contents is replaced in _synctex_buffer_get_available_size. + * They were buffered from offset-len location in the file. */ + offset -= SYNCTEX_CUR - SYNCTEX_START; + more_characters: + /* There is still some work to be done, so read another bunch of file. + * This is the second call to _synctex_buffer_get_available_size, + * which means that the actual contents of the buffer will be discarded. + * We will definitely have to recover the previous state in case we do not find the expected string. */ + zs = _synctex_buffer_get_available_size(scanner,remaining_len); + if (zs.statusptr) { + SYNCTEX_CUR = end; + return (synctex_is_s){result,SYNCTEX_STATUS_OK}; + } + return (synctex_is_s){result,SYNCTEX_STATUS_NOT_OK}; +} +static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value) { + char * ptr = NULL; + char * end = NULL; + synctex_zs_s zs = {0, 0}; + if (NULL == scanner) { + return (synctex_is_s){default_value, SYNCTEX_STATUS_BAD_ARGUMENT}; + } + zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); + if (zs.statusptr) { + SYNCTEX_CUR = end; + return (synctex_is_s){result,SYNCTEX_STATUS_OK}; + } + return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK}; + } + return (synctex_is_s){default_value,SYNCTEX_STATUS_OK}; +} +/* Used when parsing the synctex file. + * Decode an integer for a v field. + * Try the _synctex_decode_int version and set the last v field scanned. + * If it does not succeed, tries to match an '=' sign, + * which is a shortcut for the last v field scanned. + */ +# define SYNCTEX_INPUT_COMEQUALS ",=" +static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner) { + synctex_is_s is = _synctex_decode_int(scanner); + if (SYNCTEX_STATUS_OK == is.status) { + scanner->reader->lastv = is.integer; + return is; + } + is.status = _synctex_match_string(scanner,SYNCTEX_INPUT_COMEQUALS); + if (is.statusreader->lastv; + return is; +} + +/* The purpose of this function is to read a string. + * A string is an array of characters from the current parser location + * and before the next '\n' character. + * If a string was properly decoded, it is returned in value_ref and + * the cursor points to the new line marker. + * The returned string was allocated on the heap, the caller is the owner and + * is responsible to free it in due time, + * unless it transfers the ownership to another object. + * If no string is parsed, * value_ref is undefined. + * The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX. + * If you just want to blindly parse the file up to the end of the current line, + * use _synctex_next_line instead. + * On return, the scanner cursor is unchanged if a string could not be scanned or + * points to the terminating '\n' character otherwise. As a consequence, + * _synctex_next_line is necessary after. + * If either scanner or value_ref is NULL, it is considered as an error and + * SYNCTEX_STATUS_BAD_ARGUMENT is returned. + */ +static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner) { + char * end = NULL; + size_t len = 0;/* The number of bytes to copy */ + size_t already_len = 0; + synctex_zs_s zs = {0,0}; + char * string = NULL; + if (NULL == scanner) { + return (synctex_ss_s){NULL,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + /* The buffer must at least contain one character: the '\n' end of line marker */ + if (SYNCTEX_CUR>=SYNCTEX_END) { +more_characters: + zs = _synctex_buffer_get_available_size(scanner,1); + if (zs.status < SYNCTEX_STATUS_EOF) { + return (synctex_ss_s){NULL,zs.status}; + } else if (0 == zs.size) { + return (synctex_ss_s){NULL,SYNCTEX_STATUS_EOF}; + } + } + /* Now we are sure that there is at least one available character, either because + * SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */ + /* end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */ + end = SYNCTEX_CUR; + /* We scan all the characters up to the next '\n' */ + while (end0) { + already_len = len--; + if (string[len]!=' ') { + break; + } + } + string[already_len] = '\0'; + return (synctex_ss_s){string,SYNCTEX_STATUS_OK}; + } + free(string); + _synctex_error("could not copy memory (1)."); + return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; + } + } + _synctex_error("could not (re)allocate memory (1)."); + return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; +} + +/* Used when parsing the synctex file. + * Read an Input record. + * - parameter scanner: non NULL scanner + * - returns SYNCTEX_STATUS_OK on successful completions, others values otherwise. + */ +static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner) { + synctex_node_p input = NULL; + synctex_status_t status = SYNCTEX_STATUS_BAD_ARGUMENT; + synctex_zs_s zs = {0,0}; + if (NULL == scanner) { + return (synctex_ns_s){NULL,status}; + } + if ((status=_synctex_match_string(scanner,SYNCTEX_INPUT_MARK))input);/* input has no parent */ + scanner->input = input; +# if SYNCTEX_VERBOSE + synctex_node_log(input); +# endif + return (synctex_ns_s){input,_synctex_next_line(scanner)};/* read the line termination character, if any */ +} + +typedef synctex_is_s (*synctex_decoder_t)(synctex_scanner_p); + +/* Used when parsing the synctex file. + * Read one of the settings. + * On normal completion, returns SYNCTEX_STATUS_OK. + * On error, returns SYNCTEX_STATUS_ERROR. + * Both arguments must not be NULL. + * On return, the scanner points to the next character after the decoded object whatever it is. + * It is the responsibility of the caller to prepare the scanner for the next line. + */ +static synctex_status_t _synctex_scan_named(synctex_scanner_p scanner,const char * name) { + synctex_status_t status = 0; + if (NULL == scanner || NULL == name) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } +not_found: + status = _synctex_match_string(scanner,name); + if (statusversion = is.integer; + /* Read all the input records */ + do { + status = __synctex_parse_new_input(scanner).status; + if (statusoutput_fmt = ss.string; + if ((status=_synctex_scan_named(scanner,"Magnification:"))pre_magnification = is.integer; + if ((status=_synctex_scan_named(scanner,"Unit:"))pre_unit = is.integer; + if ((status=_synctex_scan_named(scanner,"X Offset:"))pre_x_offset = is.integer; + if ((status=_synctex_scan_named(scanner,"Y Offset:"))pre_y_offset = is.integer; + return SYNCTEX_STATUS_OK; +} + +/* parse a float with a dimension */ +static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner) { + synctex_fs_s fs = {0,0}; + synctex_zs_s zs = {0,0}; + char * endptr = NULL; +#ifdef HAVE_SETLOCALE + char * loc = setlocale(LC_NUMERIC, NULL); +#endif + if (NULL == scanner) { + return (synctex_fs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); + if (zs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536/2.54f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536/25.4f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f/72*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 12.0*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1238.0f/1157*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 14856.0f/1157*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 685.0f/642*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1370.0f/107*65536; + } else if (fs.statusunit = strtod(SYNCTEX_CUR,&endptr); +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, loc); +#endif + if (endptr == SYNCTEX_CUR) { + _synctex_error("bad magnification in the post scriptum, a float was expected."); + return SYNCTEX_STATUS_ERROR; + } + if (scanner->unit<=0) { + _synctex_error("bad magnification in the post scriptum, a positive float was expected."); + return SYNCTEX_STATUS_ERROR; + } + SYNCTEX_CUR = endptr; + goto next_line; + } + if (statusx_offset = fs.value; + goto next_line; + } else if (statusx_offset = fs.value; + goto next_line; + } else if (statusflags.postamble && (status=_synctex_match_string(scanner,"Postamble:"))count = is.integer; + /* Now we scan the last part of the SyncTeX file: the Post Scriptum section. */ + return _synctex_scan_post_scriptum(scanner); +} + +/* Horizontal boxes also have visible size. + * Visible size are bigger than real size. + * For example 0 width boxes may contain text. + * At creation time, the visible size is set to the values of the real size. + */ +static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box) { + if (box) { + switch(synctex_node_type(box)) { + case synctex_node_type_hbox: + _synctex_data_set_h_V(box,_synctex_data_h(box)); + _synctex_data_set_v_V(box,_synctex_data_v(box)); + _synctex_data_set_width_V(box,_synctex_data_width(box)); + _synctex_data_set_height_V(box,_synctex_data_height(box)); + _synctex_data_set_depth_V(box,_synctex_data_depth(box)); + return SYNCTEX_STATUS_OK; + default: + break; + } + } + return SYNCTEX_STATUS_BAD_ARGUMENT; +} + +/* This method is sent to an horizontal box to setup the visible size + * Some box have 0 width but do contain text material. + * With this method, one can enlarge the box to contain the given point (h,v). + */ +static synctex_status_t _synctex_make_hbox_contain_point(synctex_node_p node,synctex_point_s point) { + int min, max, n; + if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + if ((n = _synctex_data_width_V(node))<0) { + max = _synctex_data_h_V(node); + min = max+n; + if (point.hmax) { + _synctex_data_set_h_V(node,point.h); + _synctex_data_set_width_V(node,min-point.h); + } + } else { + min = _synctex_data_h_V(node); + max = min+n; + if (point.hmax) { + _synctex_data_set_width_V(node,point.h - min); + } + } + n = _synctex_data_v_V(node); + min = n - _synctex_data_height_V(node); + max = n + _synctex_data_depth_V(node); + if (point.vmax) { + _synctex_data_set_depth_V(node,point.v-n); + } + return SYNCTEX_STATUS_OK; +} +static synctex_status_t _synctex_make_hbox_contain_box(synctex_node_p node,synctex_box_s box) { + int min, max, n; + if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + if ((n = _synctex_data_width_V(node))<0) { + max = _synctex_data_h_V(node); + min = max+n; + if (box.min.h max) { + _synctex_data_set_h_V(node,box.max.h); + _synctex_data_set_width_V(node,min-box.max.h); + } + } else { + min = _synctex_data_h_V(node); + max = min+n; + if (box.min.hmax) { + _synctex_data_set_width_V(node,box.max.h - min); + } + } + n = _synctex_data_v_V(node); + min = n - _synctex_data_height_V(node); + max = n + _synctex_data_depth_V(node); + if (box.min.vmax) { + _synctex_data_set_depth_V(node,box.max.v-n); + } + return SYNCTEX_STATUS_OK; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SPECIAL CHARACTERS +# endif + + +/* Here are the control characters that start each line of the synctex output file. + * Their values define the meaning of the line. + */ +# define SYNCTEX_CHAR_BEGIN_SHEET '{' +# define SYNCTEX_CHAR_END_SHEET '}' +# define SYNCTEX_CHAR_BEGIN_FORM '<' +# define SYNCTEX_CHAR_END_FORM '>' +# define SYNCTEX_CHAR_BEGIN_VBOX '[' +# define SYNCTEX_CHAR_END_VBOX ']' +# define SYNCTEX_CHAR_BEGIN_HBOX '(' +# define SYNCTEX_CHAR_END_HBOX ')' +# define SYNCTEX_CHAR_ANCHOR '!' +# define SYNCTEX_CHAR_VOID_VBOX 'v' +# define SYNCTEX_CHAR_VOID_HBOX 'h' +# define SYNCTEX_CHAR_KERN 'k' +# define SYNCTEX_CHAR_GLUE 'g' +# define SYNCTEX_CHAR_RULE 'r' +# define SYNCTEX_CHAR_MATH '$' +# define SYNCTEX_CHAR_FORM_REF 'f' +# define SYNCTEX_CHAR_BOUNDARY 'x' +# define SYNCTEX_CHAR_CHARACTER 'c' +# define SYNCTEX_CHAR_COMMENT '%' + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SCANNERS & PARSERS +# endif + +# define SYNCTEX_DECODE_FAILED(NODE,WHAT) \ +(_synctex_data_decode_##WHAT(NODE)sheet) { + synctex_node_p last_sheet = scanner->sheet; + synctex_node_p next_sheet = NULL; + while ((next_sheet = __synctex_tree_sibling(last_sheet))) { + last_sheet = next_sheet; + } + /* sheets have no parent */ + __synctex_tree_set_sibling(last_sheet,node); + } else { + scanner->sheet = node; + } + return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; + } + _synctex_free_node(node); + } + return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; +} +/** + * - requirement: scanner != NULL + */ +static synctex_ns_s _synctex_parse_new_form(synctex_scanner_p scanner) { + synctex_node_p node; + if ((node = _synctex_new_form(scanner))) { + if ( + SYNCTEX_DECODE_FAILED(node,tag)) { + _synctex_error("Bad sheet record."); + } else if (_synctex_next_line(scanner)form) { + synctex_node_p last_form = scanner->form; + synctex_node_p next_form = NULL; + while ((next_form = __synctex_tree_sibling(last_form))) { + last_form = next_form; + } + __synctex_tree_set_sibling(last_form,node); + } else { + scanner->form = node; + } + return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; + } + _synctex_free_node(node); + } + return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; +} +# define SYNCTEX_SHOULD_DECODE_FAILED(NODE,WHAT) \ +(_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT(NODE)class_->scanner,_synctex_data_tag(node)); + } + if (_synctex_data_line(node)>_synctex_data_line(input)) { + _synctex_data_set_line(input,_synctex_data_line(node)); + } + return input; +} +/** + * Free node and its siblings and return its detached child. + */ +SYNCTEX_INLINE static synctex_node_p _synctex_handle_pop_child(synctex_node_p handle) { + synctex_node_p child = _synctex_tree_reset_child(handle); + synctex_node_free(handle); + return child; +} +/** + * Set the tlc of all the x nodes that are targets of + * x_handle and its sibling. + * Reset the target of x_handle and deletes its siblings. + * child is a node that has just been parsed and is not a boundary node. + */ +SYNCTEX_INLINE static void _synctex_handle_set_tlc(synctex_node_p x_handle, synctex_node_p child, synctex_bool_t make_friend) { + if (x_handle) { + synctex_node_p sibling = x_handle; + if (child) { + synctex_node_p target; + while ((target = synctex_node_target(sibling))) { + _synctex_data_set_tlc(target,child); + if (make_friend) { + _synctex_node_make_friend_tlc(target); + } + if ((sibling = __synctex_tree_sibling(sibling))) { + continue; + } else { + break; + } + } + } + _synctex_tree_reset_target(x_handle); + sibling = __synctex_tree_reset_sibling(x_handle); + synctex_node_free(sibling); + } +} +/** + * When we have parsed a box, we must register + * all the contained heading boundary nodes + * that have not yet been registered. + * Those handles will be deleted when popping. + */ +SYNCTEX_INLINE static void _synctex_handle_make_friend_tlc(synctex_node_p node) { + while (node) { + synctex_node_p target = _synctex_tree_reset_target(node); + _synctex_node_make_friend_tlc(target); + node = __synctex_tree_sibling(node); + } +} +/** + * Scan sheets, forms and input records. + * - parameter scanner: owning scanner + * - returns: status + */ +static synctex_status_t __synctex_parse_sfi(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + synctex_zs_s zs = {0,0}; + synctex_ns_s input = SYNCTEX_NS_NULL; + synctex_node_p sheet = NULL; + synctex_node_p form = NULL; + synctex_node_p parent = NULL; + synctex_node_p child = NULL; + /* + * Experimentations lead to the forthcoming conclusion: + * Sometimes, the first nodes of a box have the wrong line number. + * These are only boundary (x) nodes. + * We observed that boundary nodes do have the proper line number + * if they follow a node with a different type. + * We keep track of these leading x nodes in a handle tree. + */ + synctex_node_p x_handle = NULL; +# define SYNCTEX_RETURN(STATUS) \ + synctex_node_free(x_handle);\ + return STATUS + synctex_node_p last_k = NULL; + synctex_node_p last_g = NULL; + synctex_ns_s ns = SYNCTEX_NS_NULL; + int form_depth = 0; + int ignored_form_depth = 0; + synctex_bool_t try_input = synctex_YES; + if (!(x_handle = _synctex_new_handle(scanner))) { + SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); + } +# ifdef SYNCTEX_NOTHING +# pragma mark MAIN LOOP +# endif +main_loop: + status = SYNCTEX_STATUS_OK; + sheet = form = parent = child = NULL; +# define SYNCTEX_START_SCAN(WHAT)\ +(*SYNCTEX_CUR == SYNCTEX_CHAR_##WHAT) + if (SYNCTEX_CURflags.postamble = 1; + SYNCTEX_RETURN(status); + } + status = _synctex_next_line(scanner); + if (status" at top level. + * - in a box, the unique possibility is '<', '[', '(' or ">". + * We still keep the '(' for a sheet, because that dos not cost too much. + * We must also consider void boxes as children. + */ + /* forms are everywhere */ + ns = SYNCTEX_NS_NULL; +#if SYNCTEX_VERBOSE + synctex_scanner_set_display_switcher(scanner,-1); + printf("NEW CONTENT LOOP\n"); +#if SYNCTEX_DEBUG>500 + synctex_node_display(sheet); +#endif +#endif + if (SYNCTEX_CURreader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START); + synctex_lineindex_t line_index = scanner->reader->line_number; +# endif + ns = _synctex_parse_new_hbox(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + x_handle = _synctex_new_handle_with_child(x_handle); + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + parent = ns.node; + /* add a box boundary node at the start */ + if ((child = _synctex_new_box_bdry(scanner))) { +# if defined(SYNCTEX_USE_CHARINDEX) + child->line_index=line_index; + child->char_index=char_index; +# endif + _synctex_node_set_child(parent,child); + _synctex_data_set_tlchv(child,parent); + if (!form) { + __synctex_node_make_friend_tlc(child); + } + } else { + _synctex_error("Can't create box bdry record."); + } +# if SYNCTEX_VERBOSE + synctex_node_log(parent); +# endif + input.node = _synctex_input_register_line(input.node,parent); + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(END_HBOX)) { + if (synctex_node_type(parent) == synctex_node_type_hbox) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN XOBH +# endif + ++SYNCTEX_CUR; + /* setting the next horizontal box at the end ensures + * that a child is recorded before any of its ancestors. + */ + if (form == NULL /* && sheet != NULL*/ ) { + _synctex_tree_set_next_hbox(parent,_synctex_tree_next_hbox(sheet)); + _synctex_tree_set_next_hbox(sheet,parent); + } + { + /* Update the mean line number */ + synctex_node_p node = _synctex_tree_child(parent); + synctex_node_p sibling = NULL; + /* Ignore the first node (a box_bdry) */ + if (node && (sibling = __synctex_tree_sibling(node))) { + unsigned int node_weight = 0; + unsigned int cumulated_line_numbers = 0; + _synctex_data_set_line(node, _synctex_data_line(sibling)); + node = sibling; + do { + if (synctex_node_type(node)==synctex_node_type_hbox) { + if (_synctex_data_weight(node)) { + node_weight += _synctex_data_weight(node); + cumulated_line_numbers += _synctex_data_mean_line(node)*_synctex_data_weight(node); + } else { + ++node_weight; + cumulated_line_numbers += _synctex_data_mean_line(node); + } + } else { + ++node_weight; + cumulated_line_numbers += synctex_node_line(node); + } + } while ((node = __synctex_tree_sibling(node))); + _synctex_data_set_mean_line(parent,(cumulated_line_numbers + node_weight/2)/node_weight); + _synctex_data_set_weight(parent,node_weight); + } else { + _synctex_data_set_mean_line(parent,_synctex_data_line(parent)); + _synctex_data_set_weight(parent,1); + } + if ((sibling = _synctex_new_box_bdry(scanner))) { +# if defined(SYNCTEX_USE_CHARINDEX) + sibling->line_index=child->line_index; + sibling->char_index=child->char_index; +# endif + _synctex_node_set_sibling(child,sibling); + { + synctex_node_p N = child; + while (synctex_node_type(N) == synctex_node_type_ref) { + N = _synctex_tree_arg_sibling(N); + } + _synctex_data_set_tlc(sibling,N); + } + _synctex_data_set_h(sibling,_synctex_data_h_V(parent)+_synctex_data_width_V(parent)); + _synctex_data_set_v(sibling,_synctex_data_v_V(parent)); + child = sibling; + } else { + _synctex_error("Can't create box bdry record."); + } + sibling = _synctex_tree_child(parent); + _synctex_data_set_point(sibling,_synctex_data_point_V(parent)); + if (last_k && last_g && (child = synctex_node_child(parent))) { + /* Find the node preceding last_k */ + synctex_node_p next; + while ((next = __synctex_tree_sibling(child))) { + if (next == last_k) { + _synctex_data_set_tlc(last_k,child); + _synctex_data_set_tlc(last_g,child); + break; + } + child = next; + } + } + child = parent; + parent = _synctex_tree_parent(child); + if (!form) { + _synctex_handle_make_friend_tlc(x_handle); + } + x_handle = _synctex_handle_pop_child(x_handle); + _synctex_handle_set_tlc(x_handle,child,!form); + _synctex_make_hbox_contain_box(parent, _synctex_data_box_V(child)); +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + } + if (_synctex_next_line(scanner)500 + synctex_node_display(parent); + synctex_node_display(child); +#endif + ns = _synctex_parse_new_ref(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + child = ns.node; + if (form) { + if (scanner->ref_in_form) { + synctex_tree_set_friend(child,scanner->ref_in_form); + } + scanner->ref_in_form = child; + } else { + if (scanner->ref_in_sheet) { + synctex_tree_set_friend(child,scanner->ref_in_sheet); + } + scanner->ref_in_sheet = child; + } +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(BOUNDARY)) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN BOUNDARY +# endif + ns = _synctex_parse_new_boundary(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + if (synctex_node_type(child)==synctex_node_type_box_bdry + || _synctex_tree_target(x_handle)) { + child = _synctex_tree_reset_child(x_handle); + child = _synctex_new_handle_with_child(child); + __synctex_tree_set_sibling(child, x_handle); + x_handle = child; + _synctex_tree_set_target(x_handle,ns.node); + } else if (!form) { + __synctex_node_make_friend_tlc(ns.node); + } + child = ns.node; + _synctex_make_hbox_contain_point(parent,_synctex_data_point(child)); +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + input.node = _synctex_input_register_line(input.node,child); + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(CHARACTER)) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN CHARACTER +# endif + ++SYNCTEX_CUR; + if (_synctex_next_line(scanner) 0) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN MROF +# endif + ++SYNCTEX_CUR; + --form_depth; + if (_synctex_next_line(scanner)(line %i)\n",SYNCTEX_CUR, scanner->reader->line_number+1); + if (_synctex_next_line(scanner)class_->scanner, _synctex_data_tag(ref)); + /* The target is a single node (box) + * with children and no siblings. */ + if ((ns.node = __synctex_new_proxy_from_ref_to(ref, target))) { + /* Insert this proxy instead of ref. */ + _synctex_node_set_sibling(arg_sibling,ns.node); + /* Then append the original sibling of ref. */ + _synctex_node_set_sibling(ns.node,sibling); +# if defined(SYNCTEX_USE_CHARINDEX) + if (synctex_node_type(sibling) == synctex_node_type_box_bdry) { + /* The sibling is the last box boundary + * which may have a less accurate information */ + sibling->char_index = arg_sibling->char_index; + sibling->line_index = arg_sibling->line_index; + } +#endif +#if SYNCTEX_DEBUG>500 + printf("! Ref replacement:\n"); + synctex_node_log(ref); + synctex_node_display(synctex_node_sibling(ref)); +#endif + } else /* simply remove ref */ { + _synctex_tree_set_sibling(arg_sibling,sibling); + } + __synctex_tree_reset_parent(ref); + } else { + _synctex_error("! Missing parent in __synctex_replace_ref. " + "Please report."); + ns.status = SYNCTEX_STATUS_BAD_ARGUMENT; + } + return ns; +} +/** + * - argument ref: is the starting point of a linked list + * of refs. The link is made through the friend field. + * - returns: the status and the list of all the proxies + * created. The link is made through the friend field. + * - note: All refs are freed + */ +SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref) { + synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK}; + while (ref) { + synctex_node_p next_ref = _synctex_tree_reset_friend(ref); + synctex_ns_s sub_ns = __synctex_replace_ref(ref); + if (sub_ns.status < ns.status) { + ns.status = sub_ns.status; + } else { + /* Insert all the created proxies in the list + * sub_ns.node is the last friend, + */ + synctex_tree_set_friend(sub_ns.node,ns.node); + ns.node = sub_ns.node; + } + synctex_node_free(ref); + ref = next_ref; + } + return ns; +} +typedef synctex_node_p (* synctex_processor_f)(synctex_node_p node); +/** + * Apply the processor f to the tree hierarchy rooted at proxy. + * proxy has replaced a form ref, no children yet. + * As a side effect all the hierarchy of nodes will be created. + */ +SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f) { + while(proxy) { + synctex_node_p next_proxy = _synctex_tree_friend(proxy); + synctex_node_p halt = __synctex_tree_sibling(proxy); + /* if proxy is the last sibling, halt is NULL. + * Find what should be a next node, + * without creating new nodes. */ + if (!halt) { + synctex_node_p parent = _synctex_tree_parent(proxy); + halt = __synctex_tree_sibling(parent); + while (!halt && parent) { + parent = _synctex_tree_parent(parent); + halt = __synctex_tree_sibling(parent); + } + } + do { +#if SYNCTEX_DEBUG>500 + printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy)); + { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\nBeforehand %i match\n",j); + } + } +#endif + f(proxy); +#if SYNCTEX_DEBUG>500 + { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\n%i match\n",j); + } + } +#endif + /* Side effect: create the hierarchy on the fly */ + proxy = synctex_node_next(proxy); /* Change is here */ +#if SYNCTEX_DEBUG>500 + if (proxy) { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\nnext %i match\n",j); + } + } +#endif + } while (proxy && proxy != halt); + proxy = next_proxy; + } + return SYNCTEX_STATUS_OK; +} +/** + * Replace all the form refs by root box proxies. + * Create the node hierarchy and update the friends. + * On entry, the refs are collected as a friend list + * in either a form or a sheet + * - parameter: the owning scanner + */ +SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + synctex_ns_s ns = {NULL,SYNCTEX_STATUS_NOT_OK}; +#if SYNCTEX_DEBUG>500 + printf("! entering _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + /* replace form refs inside forms by box proxies */ + ns = _synctex_post_process_ref(scanner->ref_in_form); + scanner->ref_in_form = NULL;/* it was just released */ + if (ns.status500 + printf("! ref replaced in form _synctex_post_process.\n"); + synctex_node_display(scanner->form); +#endif + /* Create all the form proxy nodes on the fly. + * ns.node is the root of the list of + * newly created proxies. + * There might be a problem with cascading proxies. + * In order to be properly managed, the data must + * be organized in the right way. + * The inserted form must be defined before + * the inserting one. *TeX will take care of that. */ + ns.status = _synctex_post_process_proxy(ns.node,&_synctex_tree_reset_friend); + if (ns.statusref_in_sheet); + if (ns.statusref_in_sheet = NULL; +#if SYNCTEX_DEBUG>500 + printf("! ref replaced in sheet _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); +#endif +#if 0 + { + int i; + for (i=0;inumber_of_lists;++i) { + synctex_node_p P = ns.node; + do { + synctex_node_p N = scanner->lists_of_friends[i]; + do { + if (P == N) { + printf("Already registered.\n"); + synctex_node_display(N); + break; + } + } while ((N = _synctex_tree_friend(N))); + } while((P = _synctex_tree_friend(P))); + } + } +#endif +#if SYNCTEX_DEBUG>10000 + { + int i; + for (i=0;inumber_of_lists;++i) { + synctex_node_p P = scanner->lists_of_friends[i]; + int j = 0; + while (P) { + ++j; + synctex_node_log(P); + P = _synctex_tree_friend(P); + } + if (j) { + printf("friends %i -> # %i\n",i,j); + } + } + } +#endif + ns.status = _synctex_post_process_proxy(ns.node,&__synctex_proxy_make_friend_and_next_hbox); + if (ns.status500 + printf("! exiting _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); + printf("! display all.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + return status; +} +/* Used when parsing the synctex file + */ +static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner) { + scanner->reader->lastv = -1; + synctex_status_t status = 0; + if (NULL == scanner) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + /* Find where this section starts */ +content_not_found: + status = _synctex_match_string(scanner,"Content:"); + if (statusreader = _synctex_malloc(sizeof(synctex_reader_s)))) { + _synctex_free(scanner); + return NULL; + } +# ifdef SYNCTEX_NOTHING +# pragma mark - +# endif +# define DEFINE_synctex_scanner_class(NAME)\ + scanner->class_[synctex_node_type_##NAME] = synctex_class_##NAME;\ +(scanner->class_[synctex_node_type_##NAME]).scanner = scanner + DEFINE_synctex_scanner_class(input); + DEFINE_synctex_scanner_class(sheet); + DEFINE_synctex_scanner_class(form); + DEFINE_synctex_scanner_class(hbox); + DEFINE_synctex_scanner_class(void_hbox); + DEFINE_synctex_scanner_class(vbox); + DEFINE_synctex_scanner_class(void_vbox); + DEFINE_synctex_scanner_class(kern); + DEFINE_synctex_scanner_class(glue); + DEFINE_synctex_scanner_class(rule); + DEFINE_synctex_scanner_class(math); + DEFINE_synctex_scanner_class(boundary); + DEFINE_synctex_scanner_class(box_bdry); + DEFINE_synctex_scanner_class(ref); + DEFINE_synctex_scanner_class(proxy_hbox); + DEFINE_synctex_scanner_class(proxy_vbox); + DEFINE_synctex_scanner_class(proxy); + DEFINE_synctex_scanner_class(proxy_last); + DEFINE_synctex_scanner_class(handle); + /* set up the lists of friends */ + scanner->number_of_lists = 1024; + scanner->lists_of_friends = (synctex_node_r)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_p)); + if (NULL == scanner->lists_of_friends) { + synctex_scanner_free(scanner); + _synctex_error("malloc:2"); + return NULL; + } + scanner->display_switcher = 100; + scanner->display_prompt = (char *)_synctex_display_prompt+strlen(_synctex_display_prompt)-1; + } + return scanner; +} +/* Where the synctex scanner is created. */ +synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) { + synctex_scanner_p scanner = synctex_scanner_new(); + if (NULL == scanner) { + _synctex_error("malloc problem"); + return NULL; + } + if ((scanner->reader = synctex_reader_init_with_output_file(scanner->reader, output, build_directory))) { + return parse? synctex_scanner_parse(scanner):scanner; + } + _synctex_error("No file?"); + return NULL; +} + +/* The scanner destructor + */ +int synctex_scanner_free(synctex_scanner_p scanner) { + int node_count = 0; + if (scanner) { + if (SYNCTEX_FILE) { + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + } + synctex_node_free(scanner->sheet); + synctex_node_free(scanner->form); + synctex_node_free(scanner->input); + synctex_reader_free(scanner->reader); + SYNCTEX_SCANNER_FREE_HANDLE(scanner); + synctex_iterator_free(scanner->iterator); + free(scanner->output_fmt); + free(scanner->lists_of_friends); +#if SYNCTEX_USE_NODE_COUNT>0 + node_count = scanner->node_count; +#endif + free(scanner); + } + return node_count; +} + +/* Where the synctex scanner parses the contents of the file. */ +synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner) { + synctex_status_t status = 0; + if (!scanner || scanner->flags.has_parsed) { + return scanner; + } + scanner->flags.has_parsed=1; + scanner->pre_magnification = 1000; + scanner->pre_unit = 8192; + scanner->pre_x_offset = scanner->pre_y_offset = 578; + /* initialize the offset with a fake unprobable value, + * If there is a post scriptum section, this value will be overridden by the real life value */ + scanner->x_offset = scanner->y_offset = 6.027e23f; + scanner->reader->line_number = 1; + + SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */ + if (NULL == SYNCTEX_START) { + _synctex_error("! malloc error in synctex_scanner_parse."); + bailey: +#ifdef SYNCTEX_DEBUG + return scanner; +#else + synctex_scanner_free(scanner); + return NULL; +#endif + } + synctex_scanner_set_display_switcher(scanner, 1000); + SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE; + /* SYNCTEX_END always points to a null terminating character. + * Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1. + * At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */ + *SYNCTEX_END = '\0'; + SYNCTEX_CUR = SYNCTEX_END; +# if defined(SYNCTEX_USE_CHARINDEX) + scanner->reader->charindex_offset = -SYNCTEX_BUFFER_SIZE; +# endif + status = _synctex_scan_preamble(scanner); + if (status500 + synctex_scanner_set_display_switcher(scanner, 100); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + synctex_scanner_set_display_switcher(scanner, 1000); + /* Everything is finished, free the buffer, close the file */ + free((void *)SYNCTEX_START); + SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL; + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + /* Final tuning: set the default values for various parameters */ + /* 1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp + * 1 pt = 65536 sp */ + if (scanner->pre_unit<=0) { + scanner->pre_unit = 8192; + } + if (scanner->pre_magnification<=0) { + scanner->pre_magnification = 1000; + } + if (scanner->unit <= 0) { + /* no post magnification */ + scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/ + } else { + /* post magnification */ + scanner->unit *= scanner->pre_unit / 65781.76; + } + scanner->unit *= scanner->pre_magnification / 1000.0; + if (scanner->x_offset > 6e23) { + /* no post offset */ + scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76); + scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76); + } else { + /* post offset */ + scanner->x_offset /= 65781.76f; + scanner->y_offset /= 65781.76f; + } + return scanner; +#undef SYNCTEX_FILE +} + +/* Scanner accessors. + */ +int synctex_scanner_pre_x_offset(synctex_scanner_p scanner){ + return scanner?scanner->pre_x_offset:0; +} +int synctex_scanner_pre_y_offset(synctex_scanner_p scanner){ + return scanner?scanner->pre_y_offset:0; +} +int synctex_scanner_x_offset(synctex_scanner_p scanner){ + return scanner?scanner->x_offset:0; +} +int synctex_scanner_y_offset(synctex_scanner_p scanner){ + return scanner?scanner->y_offset:0; +} +float synctex_scanner_magnification(synctex_scanner_p scanner){ + return scanner?scanner->unit:1; +} +void synctex_scanner_display(synctex_scanner_p scanner) { + if (NULL == scanner) { + return; + } + printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->reader->output,scanner->output_fmt,scanner->version); + printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset); + printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", + scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset); + printf("The input:\n"); + synctex_node_display(scanner->input); + if (scanner->count<1000) { + printf("The sheets:\n"); + synctex_node_display(scanner->sheet); + printf("The friends:\n"); + if (scanner->lists_of_friends) { + int i = scanner->number_of_lists; + synctex_node_p node; + while(i--) { + printf("Friend index:%i\n",i); + node = (scanner->lists_of_friends)[i]; + while(node) { + printf("%s:%i,%i\n", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_line(node) + ); + node = _synctex_tree_friend(node); + } + } + } + } else { + printf("SyncTeX Warning: Too many objects\n"); + } +} +/* Public */ +const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag) { + synctex_node_p input = NULL; + if (NULL == scanner) { + return NULL; + } + if ((input = scanner->input)) {; + do { + if (tag == _synctex_data_tag(input)) { + return (_synctex_data_name(input)); + } + } while((input = __synctex_tree_sibling(input))); + } + return NULL; +} +const char * synctex_node_get_name(synctex_node_p node) { + if (node) { + return synctex_scanner_get_name(node->class_->scanner,_synctex_data_tag(node)); + } + return NULL; +} + +static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name); +static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { + synctex_node_p input = NULL; + if (NULL == scanner) { + return 0; + } + if ((input = scanner->input)) { + do { + if (_synctex_is_equivalent_file_name(name,(_synctex_data_name(input)))) { + return _synctex_data_tag(input); + } + } while((input = __synctex_tree_sibling(input))); + } + // 2011 version + name = _synctex_base_name(name); + if ((input = scanner->input)) { + do { + if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(input)))) { + synctex_node_p other_input = input; + while((other_input = __synctex_tree_sibling(other_input))) { + if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(other_input))) + && (strlen(_synctex_data_name(input))!=strlen(_synctex_data_name(other_input)) + || strncmp(_synctex_data_name(other_input),_synctex_data_name(input),strlen(_synctex_data_name(input))))) { + // There is a second possible candidate + return 0; + } + } + return _synctex_data_tag(input); + } + } while((input = __synctex_tree_sibling(input))); + } + return 0; +} + +int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { + size_t char_index = strlen(name); + if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) { + /* the name is not void */ + char_index -= 1; + if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) { + /* the last character of name is not a path separator */ + int result = _synctex_scanner_get_tag(scanner,name); + if (result) { + return result; + } else { + /* the given name was not the one known by TeX + * try a name relative to the enclosing directory of the scanner->output file */ + const char * relative = name; + const char * ptr = scanner->reader->output; + while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) + { + relative += 1; + ptr += 1; + } + /* Find the last path separator before relative */ + while(relative > name) { + if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) { + break; + } + relative -= 1; + } + if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) { + return result; + } + if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) { + /* No tag found for the given absolute name, + * Try each relative path starting from the shortest one */ + while(0input:NULL; +} +synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag) { + synctex_node_p input = scanner?scanner->input:NULL; + while (_synctex_data_tag(input)!=tag) { + if ((input = __synctex_tree_sibling(input))) { + continue; + } + break; + } + return input; +} +const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner) { + return NULL != scanner && scanner->output_fmt?scanner->output_fmt:""; +} +const char * synctex_scanner_get_output(synctex_scanner_p scanner) { + return NULL != scanner && scanner->reader->output?scanner->reader->output:""; +} +const char * synctex_scanner_get_synctex(synctex_scanner_p scanner) { + return NULL != scanner && scanner->reader->synctex?scanner->reader->synctex:""; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Public node attributes +# endif + +# define SYNCTEX_DEFINE_NODE_HVWHD(WHAT) \ +int synctex_node_##WHAT(synctex_node_p node) { \ + return (node && node->class_->inspector->WHAT)? \ + node->class_->inspector->WHAT(node): 0; \ +} +# define SYNCTEX_DEFINE_PROXY_HV(WHAT) \ +static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ + synctex_node_p target = _synctex_tree_target(proxy); \ + if (target) { \ + return _synctex_data_##WHAT(proxy)+synctex_node_##WHAT(target); \ + } else { \ + return proxy? _synctex_data_##WHAT(proxy): 0; \ + } \ +} +#define SYNCTEX_DEFINE_PROXY_TLCWVD(WHAT) \ +static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ + synctex_node_p target = _synctex_tree_target(proxy); \ + return target? synctex_node_##WHAT(target): 0; \ +} + +/** + * The horizontal location of the node. + * Idem for v, width, height and depth. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - requires: every proxy node has a target. + * - note: recursive call if the parameter has a proxy. + * - author: JL + */ +SYNCTEX_DEFINE_NODE_HVWHD(h) +SYNCTEX_DEFINE_NODE_HVWHD(v) +SYNCTEX_DEFINE_NODE_HVWHD(width) +SYNCTEX_DEFINE_NODE_HVWHD(height) +SYNCTEX_DEFINE_NODE_HVWHD(depth) +SYNCTEX_DEFINE_PROXY_TLCWVD(tag) +SYNCTEX_DEFINE_PROXY_TLCWVD(line) +SYNCTEX_DEFINE_PROXY_TLCWVD(column) +SYNCTEX_DEFINE_PROXY_HV(h) +SYNCTEX_DEFINE_PROXY_HV(v) +SYNCTEX_DEFINE_PROXY_TLCWVD(width) +SYNCTEX_DEFINE_PROXY_TLCWVD(height) +SYNCTEX_DEFINE_PROXY_TLCWVD(depth) + +/** + * Whether the argument is a box, + * either vertical or horizontal, + * either void or not, + * or a proxy to such a box. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_hbox + || node->class_->type == synctex_node_type_void_hbox + || node->class_->type == synctex_node_type_vbox + || node->class_->type == synctex_node_type_void_vbox + || _synctex_node_is_box(_synctex_tree_target(node))); +} + +/** + * Whether the argument is a handle. + * Handles are similar to proxies because they have a target. + * They are used for query results. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_handle); +} + +/** + * Resolves handle indirection. + * - parameter node: of type synctex_node_p + * - returns: node if it is not a handle, + * its target otherwise. + */ + +SYNCTEX_INLINE static synctex_node_p _synctex_node_or_handle_target(synctex_node_p node) { + return _synctex_node_is_handle(node)? + _synctex_tree_target(node):node; +} + +/** + * Whether the argument is an hbox. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_hbox + || node->class_->type == synctex_node_type_void_hbox + || _synctex_node_is_hbox(_synctex_tree_target(node))); +} + +/** + * The horizontal location of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_h(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_h(node); + } + return 0; +} +/** + * The vertical location of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_v(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_v(node); + } + return 0; +} +/** + * The width of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_width(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_width(node); + } + return 0; +} +/** + * The height of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_height(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_height(node); + } + return 0; +} +/** + * The depth of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_depth(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_depth(node); + } + return 0; +} +/** + * The horizontal location of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_h(synctex_node_p node) { + switch(synctex_node_type(node)) { + case synctex_node_type_hbox: + return _synctex_data_h_V(node); + case synctex_node_type_proxy_hbox: + return _synctex_data_h(node)+synctex_node_hbox_h(_synctex_tree_target(node)); + default: + return 0; + } +} +/** + * The vertical location of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_v(synctex_node_p node) { + switch(synctex_node_type(node)) { + case synctex_node_type_hbox: + return _synctex_data_v_V(node); + case synctex_node_type_proxy_hbox: + return _synctex_data_v(node)+synctex_node_hbox_v(_synctex_tree_target(node)); + default: + return 0; + } +} +/** + * The width of an hbox, corrected with contents. + * - parameter node: an hbox node, 0 if node is not an hbox or an hbox proxy. + * - returns: an integer. + * - author: JL + */ +int synctex_node_hbox_width(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_width_V(node): 0; +} +/** + * The height of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_height(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_height_V(node): 0; +} +/** + * The depth of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_depth(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_depth_V(node): 0; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Public node visible attributes +# endif + +#define SYNCTEX_VISIBLE_SIZE(node,s) \ +(s)*node->class_->scanner->unit +#define SYNCTEX_VISIBLE_DISTANCE_h(node,d) \ +((d)*node->class_->scanner->unit+node->class_->scanner->x_offset) +#define SYNCTEX_VISIBLE_DISTANCE_v(node,d) \ +((d)*node->class_->scanner->unit+node->class_->scanner->y_offset) +static float __synctex_node_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); +} +static float __synctex_node_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); +} +static float __synctex_node_visible_width(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_width(node)); +} +static float __synctex_node_visible_height(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_height(node)); +} +static float __synctex_node_visible_depth(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_depth(node)); +} +static float __synctex_proxy_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); +} +static float __synctex_proxy_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); +} +static float __synctex_proxy_visible_width(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_width(target); +} +static float __synctex_proxy_visible_height(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_height(target); +} +static float __synctex_proxy_visible_depth(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_depth(target); +} +static float __synctex_kern_visible_h(synctex_noxy_p noxy) { + int h = _synctex_data_h(noxy); + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h-width:h); +} +static float __synctex_kern_visible_width(synctex_noxy_p noxy) { + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); +} +static float __synctex_rule_visible_h(synctex_noxy_p noxy) { + int h = _synctex_data_h(noxy); + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h:h-width); +} +static float __synctex_rule_visible_width(synctex_noxy_p noxy) { + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); +} +static float __synctex_rule_visible_v(synctex_noxy_p noxy) { + return __synctex_node_visible_v(noxy); +} +static float __synctex_rule_visible_height(synctex_noxy_p noxy) { + return __synctex_node_visible_height(noxy); +} +static float __synctex_rule_visible_depth(synctex_noxy_p noxy) { + return __synctex_node_visible_depth(noxy); +} + +/** + * The horizontal location of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_h(synctex_node_p node){ + return node? node->class_->vispector->h(node): 0; +} +/** + * The vertical location of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_v(synctex_node_p node){ + return node? node->class_->vispector->v(node): 0; +} +/** + * The width of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_width(synctex_node_p node){ + return node? node->class_->vispector->width(node): 0; +} +/** + * The height of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_height(synctex_node_p node){ + return node? node->class_->vispector->height(node): 0; +} +/** + * The depth of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_depth(synctex_node_p node){ + return node? node->class_->vispector->depth(node): 0; +} + +/** + * The V variant of geometrical information. + * - parameter node: a node. + * - returns: an integer. + * - author: JL + */ +#define SYNCTEX_DEFINE_V(WHAT)\ +SYNCTEX_INLINE static int _synctex_node_##WHAT##_V(synctex_node_p node) { \ + synctex_node_p target = _synctex_tree_target(node); \ + if (target) { \ + return _synctex_data_##WHAT(node)+_synctex_node_##WHAT##_V(target); \ + } else if (_synctex_data_has_##WHAT##_V(node)) { \ + return _synctex_data_##WHAT##_V(node); \ + } else { \ + return _synctex_data_##WHAT(node); \ + } \ +} +SYNCTEX_DEFINE_V(h) +SYNCTEX_DEFINE_V(v) +SYNCTEX_DEFINE_V(width) +SYNCTEX_DEFINE_V(height) +SYNCTEX_DEFINE_V(depth) + +SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node) { + return (synctex_point_s){synctex_node_h(node),synctex_node_v(node)}; +} +SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node) { + return (synctex_point_s){_synctex_node_h_V(node),_synctex_node_v_V(node)}; +} +SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point) { + synctex_point_s old = _synctex_data_point(node); + _synctex_data_set_h(node,point.h); + _synctex_data_set_v(node,point.v); + return old; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = synctex_node_width(node); + if (n<0) { + box.max.h = synctex_node_h(node); + box.min.h = box.max.h + n; + } else { + box.min.h = synctex_node_h(node); + box.max.h = box.min.h + n; + } + n = synctex_node_v(node); + box.min.v = n - synctex_node_height(node); + box.max.v = n + synctex_node_depth(node); + return box; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = synctex_node_width(node); + if (n>0) { + box.max.h = synctex_node_h(node); + box.min.h = box.max.h - n; + } else { + box.min.h = synctex_node_h(node); + box.max.h = box.min.h - n; + } + n = synctex_node_v(node); + box.min.v = n - synctex_node_height(node); + box.max.v = n + synctex_node_depth(node); + return box; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = _synctex_node_width_V(node); + if (n<0) { + box.max.h = _synctex_node_h_V(node); + box.min.h = box.max.h + n; + } else { + box.min.h = _synctex_node_h_V(node); + box.max.h = box.min.h + n; + } + n = _synctex_node_v_V(node); + box.min.v = n - _synctex_node_height_V(node); + box.max.v = n + _synctex_node_depth_V(node); + return box; +} + +/** + * The higher box node in the parent hierarchy which + * mean line number is the one of node ±1. + * This enclosing box is computed as follows + * 1) get the first hbox in the parent linked list + * starting at node. + * If there is none, simply return the parent of node. + * 2) compute the mean line number + * 3) scans up the tree for the higher hbox with + * the same mean line number, ±1 eventually +* - parameter node: a node. + * - returns: a (proxy to a) box node. + * - author: JL + */ +static synctex_node_p _synctex_node_box_visible(synctex_node_p node) { + if ((node = _synctex_node_or_handle_target(node))) { + int mean = 0; + int bound = 1500000/(node->class_->scanner->pre_magnification/1000.0); + synctex_node_p parent = NULL; + /* get the first enclosing parent + * then get the highest enclosing parent with the same mean line ±1 */ + node = _synctex_node_or_handle_target(node); + if (!_synctex_node_is_box(node)) { + if ((parent = _synctex_tree_parent(node))) { + node = parent; + } else if ((node = _synctex_tree_target(node))) { + if (!_synctex_node_is_box(node)) { + if ((parent = _synctex_tree_parent(node))) { + node = parent; + } else { + return NULL; + } + } + } + } + parent = node; + mean = synctex_node_mean_line(node); + while ((parent = _synctex_tree_parent(parent))) { + if (_synctex_node_is_hbox(parent)) { + if (_synctex_abs(mean-synctex_node_mean_line(parent))>1) { + return node; + } else if (synctex_node_width(parent)>bound) { + return parent; + } else if (synctex_node_height(parent)+synctex_node_depth(parent)>bound) { + return parent; + } + node = parent; + } + } + } + return node; +} +/** + * The horizontal location of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,_synctex_node_h_V(_synctex_node_box_visible(node))); +} +/** + * The vertical location of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,_synctex_node_v_V(_synctex_node_box_visible(node))); +} +/** + * The width of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_width(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_width_V(_synctex_node_box_visible(node))); +} +/** + * The height of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_height(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_height_V(_synctex_node_box_visible(node))); +} +/** + * The depth of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_depth(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_depth_V(_synctex_node_box_visible(node))); +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Other public node attributes +# endif + +/** + * The page number of the sheet enclosing node. + * - parameter node: a node. + * - returns: the page number or -1 if node does not belong to a sheet tree. + * - note: a proxy target does not belong to a sheet + * but a form, its page number is always -1. + * - note: a handles does not belong to a sheet not a form. + * its page number is -1. + * - author: JL + */ +int synctex_node_page(synctex_node_p node){ + synctex_node_p parent = NULL; + while((parent = _synctex_tree_parent(node))) { + node = parent; + } + if (synctex_node_type(node) == synctex_node_type_sheet) { + return _synctex_data_page(node); + } + return -1; +} +/** + * The page number of the target. + * - author: JL + */ +SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node){ + return synctex_node_page(_synctex_tree_target(node)); +} + +#if defined (SYNCTEX_USE_CHARINDEX) +synctex_charindex_t synctex_node_charindex(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return target? SYNCTEX_CHARINDEX(target):(node?SYNCTEX_CHARINDEX(node):0); +} +#endif + +/** + * The tag of the node. + * - parameter node: a node. + * - returns: the tag or -1 if node is NULL. + * - author: JL + */ +int synctex_node_tag(synctex_node_p node) { + return node? node->class_->tlcpector->tag(node): -1; +} +/** + * The line of the node. + * - parameter node: a node. + * - returns: the line or -1 if node is NULL. + * - author: JL + */ +int synctex_node_line(synctex_node_p node) { + return node? node->class_->tlcpector->line(node): -1; +} +/** + * The column of the node. + * - parameter node: a node. + * - returns: the column or -1 if node is NULL. + * - author: JL + */ +int synctex_node_column(synctex_node_p node) { + return node? node->class_->tlcpector->column(node): -1; +} +/** + * The mean line number of the node. + * - parameter node: a node. + * - returns: the mean line or -1 if node is NULL. + * - author: JL + */ +int synctex_node_mean_line(synctex_node_p node) { + synctex_node_p other = _synctex_tree_target(node); + if (other) { + node = other; + } + if (_synctex_data_has_mean_line(node)) { + return _synctex_data_mean_line(node); + } + if ((other = synctex_node_parent(node))) { + if (_synctex_data_has_mean_line(other)) { + return _synctex_data_mean_line(other); + } + } + return synctex_node_line(node); +} +/** + * The weight of the node. + * - parameter node: a node. + * - returns: the weight or -1 if node is NULL. + * - author: JL + */ +int synctex_node_weight(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; +} +/** + * The number of children of the node. + * - parameter node: a node. + * - returns: the count or -1 if node is NULL. + * - author: JL + */ +int synctex_node_child_count(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Sheet & Form +# endif + +/** + * The sheet of the scanner with a given page number. + * - parameter scanner: a scanner. + * - parameter page: a 1 based page number. + * If page == 0, returns the first sheet. + * - returns: a sheet or NULL. + * - author: JL + */ +synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page) { + if (scanner) { + synctex_node_p sheet = scanner->sheet; + while(sheet) { + if (page == _synctex_data_page(sheet)) { + return sheet; + } + sheet = __synctex_tree_sibling(sheet); + } + if (page == 0) { + return scanner->sheet; + } + } + return NULL; +} +/** + * The form of the scanner with a given tag. + * - parameter scanner: a scanner. + * - parameter tag: an integer identifier. + * If tag == 0, returns the first form. + * - returns: a form. + * - author: JL + */ +synctex_node_p synctex_form(synctex_scanner_p scanner,int tag) { + if (scanner) { + synctex_node_p form = scanner->form; + while(form) { + if (tag == _synctex_data_tag(form)) { + return form; + } + form = __synctex_tree_sibling(form); + } + if (tag == 0) { + return scanner->form; + } + } + return NULL; +} + +/** + * The content of the sheet with given page number. + * - parameter scanner: a scanner. + * - parameter page: a 1 based page number. + * - returns: a (vertical) box node. + * - author: JL + */ +synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page) { + if (scanner) { + return _synctex_tree_child(synctex_sheet(scanner,page)); + } + return NULL; +} + +/** + * The content of the sheet with given page number. + * - parameter scanner: a scanner. + * - parameter tag: an integer identifier. + * - returns: a box node. + * - author: JL + */ +synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag) { + if (scanner) { + return _synctex_tree_child(synctex_form(scanner,tag)); + } + return NULL; +} + +SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner,int i) { + if (i>=0) { + i = _synctex_abs(i)%(scanner->number_of_lists); + return (scanner->lists_of_friends)[i]; + } + return NULL; +} +SYNCTEX_INLINE static synctex_bool_t _synctex_nodes_are_friend(synctex_node_p left, synctex_node_p right) { + return synctex_node_tag(left) == synctex_node_tag(right) && synctex_node_line(left) == synctex_node_line(right); +} +/** + * The sibling argument is a parent/child list of nodes of the same page. + */ +typedef struct { + int count; + synctex_node_p node; +} synctex_counted_node_s; + +SYNCTEX_INLINE static synctex_counted_node_s _synctex_vertically_sorted_v2(synctex_node_p sibling) { + /* Clean the weights of the parents */ + synctex_counted_node_s result = {0, NULL}; + synctex_node_p h = NULL; + synctex_node_p next_h = NULL; + synctex_node_p parent = NULL; + int weight = 0; + synctex_node_p N = NULL; + h = sibling; + do { + N = _synctex_tree_target(h); + parent = _synctex_tree_parent(N); + _synctex_data_set_weight(parent, 0); + } while((h = _synctex_tree_child(h))); + /* Compute the weights of the nodes */ + h = sibling; + do { + N = _synctex_tree_target(h); + parent = _synctex_tree_parent(N); + weight = _synctex_data_weight(parent); + if (weight==0) { + N = _synctex_tree_child(parent); + do { + if (_synctex_nodes_are_friend(N,sibling)) { + ++ weight; + } + } while ((N = __synctex_tree_sibling(N))); + _synctex_data_set_weight(h,weight); + _synctex_data_set_weight(parent,weight); + } + } while((h = _synctex_tree_child(h))); + /* Order handle nodes according to the weight */ + h = _synctex_tree_reset_child(sibling); + result.node = sibling; + weight = 0; + while((h)) { + N = result.node; + if (_synctex_data_weight(h)>_synctex_data_weight(N)) { + next_h = _synctex_tree_set_child(h,N); + result.node = h; + } else if (_synctex_data_weight(h) == 0) { + ++ weight; + next_h = _synctex_tree_reset_child(h); + synctex_node_free(h); + } else { + synctex_node_p next_N = NULL; + while((next_N = _synctex_tree_child(N))) { + N = next_N; + if (_synctex_data_weight(h)<_synctex_data_weight(next_N)) { + continue; + } + break; + } + next_h = _synctex_tree_set_child(h,_synctex_tree_set_child(N,h)); + } + h = next_h; + }; + h = result.node; + weight = 0; + do { + ++weight; + } while((h = _synctex_tree_child(h))); + result.count = 1; + h = result.node; + while((next_h = _synctex_tree_child(h))) { + if (_synctex_data_weight(next_h)==0) { + _synctex_tree_reset_child(h); + weight = 1; + h = next_h; + while((h = _synctex_tree_child(h))) { + ++weight; + } + synctex_node_free(next_h); + break; + } + ++result.count; + h = next_h; + } + return result; +} + +SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node); + +/* This struct records distances, the left one is non negative and the right one is non positive. + * When comparing the locations of 2 different graphical objects on the page, we will have to also record the + * horizontal distance as signed to keep track of the typesetting order.*/ + +typedef struct { + synctex_node_p node; + int distance; +} synctex_nd_s; + +#define SYNCTEX_ND_0 (synctex_nd_s){NULL,INT_MAX} + +typedef synctex_nd_s * synctex_nd_p; + +typedef struct { + synctex_nd_s l; + synctex_nd_s r; +} synctex_nd_lr_s; + +/* The best container is the deeper box that contains the hit point (H,V). + * _synctex_eq_deepest_container_v2 starts with node whereas + * _synctex_box_child_deepest starts with node's children, if any + * if node is not a box, or a void box, NULL is returned. + * We traverse the node tree in a deep first manner and stop as soon as a result is found. */ +static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hitP, synctex_node_p node); + +SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node); + +/* Closest child, recursive. */ +static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node); + +/* The smallest container between two has the smallest width or height. + * This comparison is used when there are 2 overlapping boxes that contain the hit point. + * For ConTeXt, the problem appears at each page. + * The chosen box is the one with the smallest height, then the smallest width. */ +SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node); + +/* Returns the distance between the hit point hit point=(H,V) and the given node. */ + +static int _synctex_point_node_distance_v2(synctex_point_p hitP, synctex_node_p node); + +/* The closest container is the box that is the one closest to the given point. + * The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */ +static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node); + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Queries +# endif + +/** + * iterator for a deep first tree traversal. + */ +struct synctex_iterator_t { + synctex_node_p seed; + synctex_node_p top; + synctex_node_p next; + int count0; + int count; +}; + +SYNCTEX_INLINE static synctex_iterator_p _synctex_iterator_new(synctex_node_p result, int count) { + synctex_iterator_p iterator; + if ((iterator = _synctex_malloc(sizeof(synctex_iterator_s)))) { + iterator->seed = iterator->top = iterator->next = result; + iterator->count0 = iterator->count = count; + } + return iterator; +}; + +void synctex_iterator_free(synctex_iterator_p iterator) { + if (iterator) { + synctex_node_free(iterator->seed); + _synctex_free(iterator); + } +} +synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator) { + return iterator?iterator->count>0:0; +} +int synctex_iterator_count(synctex_iterator_p iterator) { + return iterator? iterator->count: 0; +} + +/** + * The next result of the iterator. + * Internally, the iterator stores handles to nodes. + * Externally, it returns the targets, + * such that the caller only sees nodes. + */ +synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator) { + if (iterator && iterator->count>0) { + synctex_node_p N = iterator->next; + if(!(iterator->next = _synctex_tree_child(N))) { + iterator->next = iterator->top = __synctex_tree_sibling(iterator->top); + } + --iterator->count; + return _synctex_tree_target(N); + } + return NULL; +} +int synctex_iterator_reset(synctex_iterator_p iterator) { + if (iterator) { + iterator->next = iterator->top = iterator->seed; + return iterator->count = iterator->count0; + } + return 0; +} + +synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v){ + if (scanner) { + synctex_node_p sheet = NULL; + synctex_point_s hit; + synctex_node_p node = NULL; + synctex_nd_lr_s nds = {{NULL,0},{NULL,0}}; + if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/* scanner->unit must be >0 */ + return NULL; + } + /* Find the proper sheet */ + sheet = synctex_sheet(scanner,page); + if (NULL == sheet) { + return NULL; + } + /* Now sheet points to the sheet node with proper page number. */ + /* Now that scanner has been initialized, we can convert + * the given point to scanner integer coordinates */ + hit = (synctex_point_s) + {(h-scanner->x_offset)/scanner->unit, + (v-scanner->y_offset)/scanner->unit}; + /* At first, we browse all the horizontal boxes of the sheet + * until we find one containing the hit point. */ + if ((node = _synctex_tree_next_hbox(sheet))) { + do { + if (_synctex_point_in_box_v2(&hit,node)) { + /* Maybe the hit point belongs to a contained vertical box. + * This is the most likely situation. + */ + synctex_node_p next = node; +#if defined(SYNCTEX_DEBUG) + printf("--- We are lucky\n"); +#endif + /* This trick is for catching overlapping boxes */ + while ((next = _synctex_tree_next_hbox(next))) { + if (_synctex_point_in_box_v2(&hit,next)) { + node = _synctex_smallest_container_v2(next,node); + } + } + /* node is the smallest horizontal box that contains hit, + * unless there is no hbox at all. + */ + node = _synctex_eq_deepest_container_v2(&hit, node); + nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node); + end: + if (nds.r.node && nds.l.node) { + if ((_synctex_data_tag(nds.r.node)!=_synctex_data_tag(nds.l.node)) + || (_synctex_data_line(nds.r.node)!=_synctex_data_line(nds.l.node)) + || (_synctex_data_column(nds.r.node)!=_synctex_data_column(nds.l.node))) { + if (_synctex_data_line(nds.r.node)<_synctex_data_line(nds.l.node)) { + node = nds.r.node; + nds.r.node = nds.l.node; + nds.l.node = node; + } else if (_synctex_data_line(nds.r.node)==_synctex_data_line(nds.l.node)) { + if (nds.l.distance>nds.r.distance) { + node = nds.r.node; + nds.r.node = nds.l.node; + nds.l.node = node; + } + } + if((node = _synctex_new_handle_with_target(nds.l.node))) { + synctex_node_p other_handle; + if((other_handle = _synctex_new_handle_with_target(nds.r.node))) { + _synctex_tree_set_sibling(node,other_handle); + return _synctex_iterator_new(node,2); + } + return _synctex_iterator_new(node,1); + } + return NULL; + } + /* both nodes have the same input coordinates + * We choose the one closest to the hit point */ + if (nds.l.distance>nds.r.distance) { + nds.l.node = nds.r.node; + } + nds.r.node = NULL; + } else if (nds.r.node) { + nds.l = nds.r; + } else if (!nds.l.node) { + nds.l.node = node; + } + if((node = _synctex_new_handle_with_target(nds.l.node))) { + return _synctex_iterator_new(node,1); + } + return 0; + } + } while ((node = _synctex_tree_next_hbox(node))); + /* All the horizontal boxes have been tested, + * None of them contains the hit point. + */ + } + /* We are not lucky, + * we test absolutely all the node + * to find the closest... */ + if ((node = _synctex_tree_child(sheet))) { +#if defined(SYNCTEX_DEBUG) + printf("--- We are not lucky\n"); +#endif + nds.l = __synctex_closest_deep_child_v2(&hit, node); +#if defined(SYNCTEX_DEBUG) + printf("Edit query best: %i\n", nds.l.distance); +#endif + goto end; + } + } + return NULL; +} + +/** + * Loop the candidate friendly list to find the ones with the proper + * tag and line. + * Returns a tree of results targeting the found candidates. + * At the top level each sibling has its own page number. + * All the results with the same page number are linked by child/parent entry. + * - parameter candidate: a friendly list of candidates + */ +static synctex_node_p _synctex_display_query_v2(synctex_node_p target, int tag, int line, synctex_bool_t exclude_box) { + synctex_node_p first_handle = NULL; + /* Search the first match */ + if (target == NULL) { + return first_handle; + } + do { + int page; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* We found a first match, create + * a result handle targeting that candidate. */ + first_handle = _synctex_new_handle_with_target(target); + if (first_handle == NULL) { + return first_handle; + } + /* target is either a node, + * or a proxy to some node, in which case, + * the target's target belongs to a form, + * not a sheet. */ + page = synctex_node_page(target); + /* Now create all the other results */ + while ((target = _synctex_tree_friend(target))) { + synctex_node_p result = NULL; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* Another match, same page number ? */ + result = _synctex_new_handle_with_target(target); + if (NULL == result ) { + return first_handle; + } + /* is it the same page number ? */ + if (synctex_node_page(target) == page) { + __synctex_tree_set_child(result, first_handle); + first_handle = result; + } else { + /* We have 2 page numbers involved */ + __synctex_tree_set_sibling(first_handle, result); + while ((target = _synctex_tree_friend(target))) { + synctex_node_p same_page_node; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* New match found, which page? */ + result = _synctex_new_handle_with_target(target); + if (NULL == result) { + return first_handle; + } + same_page_node = first_handle; + page = synctex_node_page(target); + /* Find a result with the same page number */; + do { + if (_synctex_node_target_page(same_page_node) == page) { + /* Insert result between same_page_node and its child */ + _synctex_tree_set_child(result,_synctex_tree_set_child(same_page_node,result)); + } else if ((same_page_node = __synctex_tree_sibling(same_page_node))) { + continue; + } else { + /* This is a new page number */ + __synctex_tree_set_sibling(result,first_handle); + first_handle = result; + } + break; + } while (synctex_YES); + } + return first_handle; + } + } + } while ((target = _synctex_tree_friend(target))); + return first_handle; +} +synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { + SYNCTEX_UNUSED(column) + if (scanner) { + int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */ + int max_line = 0; + int line_offset = 1; + int try_count = 100; + synctex_node_p node = NULL; + synctex_node_p result = NULL; + if (tag == 0) { + printf("SyncTeX Warning: No tag for %s\n",name); + return NULL; + } + node = synctex_scanner_input_with_tag(scanner, tag); + max_line = _synctex_data_line(node); + /* node = NULL; */ + if (line>max_line) { + line = max_line; + } + while(try_count--) { + if (line<=max_line) { + /* This loop will only be performed once for advanced viewers */ + synctex_node_p friend = _synctex_scanner_friend(scanner,tag+line); + if ((node = friend)) { + result = _synctex_display_query_v2(node,tag,line,synctex_YES); + if (!result) { + /* We did not find any matching boundary, retry including boxes */ + node = friend;/* no need to test it again, already done */ + result = _synctex_display_query_v2(node,tag,line,synctex_NO); + } + /* Now reverse the order to have nodes in display order, and then keep just a few nodes. + * Order first the best node. */ + /* The result is a tree. At the root level, all nodes + * correspond to different page numbers. + * Each node has a child which corresponds to the same + * page number if relevant. + * Then reorder the nodes to put first the one which fits best. + * The idea is to count the number of nodes + * with the same tag and line number in the parents + * and choose the ones with the biggest count. + */ + if (result) { + /* navigate through siblings, then children */ + synctex_node_p next_sibling = __synctex_tree_reset_sibling(result); + int best_match = abs(page_hint-_synctex_node_target_page(result)); + synctex_node_p sibling; + int match; + synctex_counted_node_s cn = _synctex_vertically_sorted_v2(result); + int count = cn.count; + result = cn.node; + while((sibling = next_sibling)) { + /* What is next? Do not miss that step! */ + next_sibling = __synctex_tree_reset_sibling(sibling); + cn = _synctex_vertically_sorted_v2(sibling); + count += cn.count; + sibling = cn.node; + match = abs(page_hint-_synctex_node_target_page(sibling)); + if (match=best_match)*/ { + __synctex_tree_set_sibling(sibling,__synctex_tree_sibling(result)); + __synctex_tree_set_sibling(result,sibling); + } + } + return _synctex_iterator_new(result,count); + } + } +# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__) + break; +# else + line += line_offset; + line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); + if (line <= 0) { + line += line_offset; + line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); + } +# endif + } + } + } + return NULL; +} +synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { + if (scanner) { + synctex_iterator_free(scanner->iterator); + scanner->iterator = synctex_iterator_new_display(scanner, name,line,column, page_hint); + return synctex_iterator_count(scanner->iterator); + } + return SYNCTEX_STATUS_ERROR; +} +synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v) { + if (scanner) { + synctex_iterator_free(scanner->iterator); + scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v); + return synctex_iterator_count(scanner->iterator); + } + return SYNCTEX_STATUS_ERROR; +} +/** + * The next result of a query. + */ +synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner) { + return scanner? synctex_iterator_next_result(scanner->iterator): NULL; +} +synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner) { + return scanner? synctex_iterator_reset(scanner->iterator): SYNCTEX_STATUS_ERROR; +} + +synctex_node_p synctex_node_target(synctex_node_p node) { + return _synctex_tree_target(node); +} + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Geometric utilities +# endif + +/** Roughly speaking, this is: + * node's h coordinate - hit point's h coordinate. + * If node is to the right of the hit point, then this distance is positive, + * if node is to the left of the hit point, this distance is negative. + * If the argument is a pdf form reference, then the child is used and returned instead. + * Last Revision: Mon Apr 24 07:05:27 UTC 2017 + */ +static synctex_nd_s _synctex_point_h_ordered_distance_v2 +(synctex_point_p hit, synctex_node_p node) { + synctex_nd_s nd = {node,INT_MAX}; + if (node) { + int min,med,max,width; + switch(synctex_node_type(node)) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + */ + case synctex_node_type_vbox: + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = _synctex_data_width(node); + min = _synctex_data_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_proxy_vbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = synctex_node_width(node); + min = synctex_node_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = synctex_node_hbox_width(node); + min = synctex_node_hbox_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_kern: + /* IMPORTANT NOTICE: the location of the kern is recorded AFTER the move. + * The distance to the kern is very special, + * in general, there is no text material in the kern, + * this is why we compute the offset relative to the closest edge of the kern.*/ + max = _synctex_data_width(node); + if (max<0) { + min = _synctex_data_h(node); + max = min - max; + } else { + min = -max; + max = _synctex_data_h(node); + min += max; + } + med = (min+max)/2; + /* positive kern: '.' means text, '>' means kern offset + * ............. + * min>>>>med>>>>max + * ............... + * negative kern: '.' means text, '<' means kern offset + * ............................ + * min<<<hh + 1; /* penalty to ensure other nodes are chosen first in case of overlapping ones */ + } else if (hit->h>max) { + nd.distance = max - hit->h - 1; /* same kind of penalty */ + } else if (hit->h>med) { + /* do things like if the node had 0 width and was placed at the max edge + 1*/ + nd.distance = max - hit->h + 1; /* positive, the kern is to the right of the hit point */ + } else { + nd.distance = min - hit->h - 1; /* negative, the kern is to the left of the hit point */ + } + break; + case synctex_node_type_rule:/* to do: special management */ + case synctex_node_type_glue: + case synctex_node_type_math: + case synctex_node_type_boundary: + case synctex_node_type_box_bdry: + nd.distance = _synctex_data_h(node) - hit->h; + break; + case synctex_node_type_ref: + nd.node = synctex_node_child(node); + nd = _synctex_point_h_ordered_distance_v2(hit,nd.node); + break; + case synctex_node_type_proxy: + case synctex_node_type_proxy_last: + { + /* shift the hit point to be relative to the proxy origin, + * then compute the distance to the target + */ + synctex_point_s otherHit = *hit; + otherHit.h -= _synctex_data_h(node); + otherHit.v -= _synctex_data_v(node); + nd.node = _synctex_tree_target(node); + nd = _synctex_point_h_ordered_distance_v2(&otherHit,nd.node); + nd.node = node; + } + default: + break; + } + } + return nd; +} +/** Roughly speaking, this is: + * node's v coordinate - hit point's v coordinate. + * If node is at the top of the hit point, then this distance is positive, + * if node is at the bottom of the hit point, this distance is negative. + */ +static synctex_nd_s _synctex_point_v_ordered_distance_v2 +(synctex_point_p hit, synctex_node_p node) { + synctex_nd_s nd = {node, INT_MAX}; + int min,max,depth,height; + switch(synctex_node_type(node)) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + */ + case synctex_node_type_vbox: + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + min = synctex_node_v(node); + max = min + _synctex_abs(_synctex_data_depth(node)); + min -= _synctex_abs(_synctex_data_height(node)); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_proxy_vbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + min = synctex_node_v(node); + max = min + _synctex_abs(synctex_node_depth(node)); + min -= _synctex_abs(synctex_node_height(node)); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + /* getting the box bounds, taking into account negative height and depth. */ + min = synctex_node_hbox_v(node); + depth = synctex_node_hbox_depth(node); + max = min + (depth>0?depth:-depth); + height = synctex_node_hbox_height(node); + min -= (height>0?height:-height); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_rule:/* to do: special management */ + case synctex_node_type_kern: + case synctex_node_type_glue: + case synctex_node_type_math: + min = _synctex_data_v(node); + max = min + _synctex_abs(_synctex_data_depth(_synctex_tree_parent(node))); + min -= _synctex_abs(_synctex_data_height(_synctex_tree_parent(node))); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_ref: + nd.node = synctex_node_child(node); + nd = _synctex_point_v_ordered_distance_v2(hit,nd.node); + break; + case synctex_node_type_proxy: + case synctex_node_type_proxy_last: + { + synctex_point_s otherHit = *hit; + otherHit.h -= _synctex_data_h(node); + otherHit.v -= _synctex_data_v(node); + nd.node = _synctex_tree_target(node); + nd = _synctex_point_v_ordered_distance_v2(&otherHit,nd.node); + nd.node = node; + } + default: break; + } + return nd; +} +/** + * The best is the one with the smallest area. + * The area is width*height where width and height may be big. + * So there is a real risk of overflow if we stick with ints. + */ +SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node) { + long total_height, other_total_height; + unsigned long area, other_area; + long width = synctex_node_hbox_width(node); + long other_width = synctex_node_hbox_width(other_node); + if (width<0) { + width = -width; + } + if (other_width<0) { + other_width = -other_width; + } + total_height = _synctex_abs(synctex_node_hbox_depth(node)) + _synctex_abs(synctex_node_hbox_height(node)); + other_total_height = _synctex_abs(synctex_node_hbox_depth(other_node)) + _synctex_abs(synctex_node_hbox_height(other_node)); + area = total_height*width; + other_area = other_total_height*other_width; + if (areaother_area) { + return other_node; + } + if (_synctex_abs(_synctex_data_width(node))>_synctex_abs(_synctex_data_width(other_node))) { + return node; + } + if (_synctex_abs(_synctex_data_width(node))<_synctex_abs(_synctex_data_width(other_node))) { + return other_node; + } + if (total_heightother_total_height) { + return other_node; + } + return node; +} + +SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node) { + if (node) { + if (0 == _synctex_point_h_ordered_distance_v2(hit,node).distance + && 0 == _synctex_point_v_ordered_distance_v2(hit,node).distance) { + return synctex_YES; + } + } + return synctex_NO; +} + +static int _synctex_distance_to_box_v2(synctex_point_p hit,synctex_box_p box) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + * In each region, there is a different formula. + * In the end we have a continuous distance which may not be a mathematical distance but who cares. */ + if (hit->vmin.v) { + /* Regions 1, 2 or 3 */ + if (hit->hmin.h) { + /* This is region 1. The distance to the box is the L1 distance PA. */ + return box->min.v - hit->v + box->min.h - hit->h;/* Integer overflow? probability epsilon */ + } else if (hit->h<=box->max.h) { + /* This is region 2. The distance to the box is the geometrical distance to the top edge. */ + return box->min.v - hit->v; + } else { + /* This is region 3. The distance to the box is the L1 distance PB. */ + return box->min.v - hit->v + hit->h - box->max.h; + } + } else if (hit->v<=box->max.v) { + /* Regions 4, 5 or 6 */ + if (hit->hmin.h) { + /* This is region 4. The distance to the box is the geometrical distance to the left edge. */ + return box->min.h - hit->h; + } else if (hit->h<=box->max.h) { + /* This is region 5. We are inside the box. */ + return 0; + } else { + /* This is region 6. The distance to the box is the geometrical distance to the right edge. */ + return hit->h - box->max.h; + } + } else { + /* Regions 7, 8 or 9 */ + if (hit->hmin.h) { + /* This is region 7. The distance to the box is the L1 distance PC. */ + return hit->v - box->max.v + box->min.h - hit->h; + } else if (hit->h<=box->max.h) { + /* This is region 8. The distance to the box is the geometrical distance to the top edge. */ + return hit->v - box->max.v; + } else { + /* This is region 9. The distance to the box is the L1 distance PD. */ + return hit->v - box->max.v + hit->h - box->max.h; + } + } +} + +/** + * The distance from the hit point to the node. + */ +static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node) { + int d = INT_MAX; + if (node) { + synctex_box_s box = {{0,0},{0,0}}; + int dd = INT_MAX; + switch(synctex_node_type(node)) { + case synctex_node_type_vbox: + box.min.h = _synctex_data_h(node); + box.max.h = box.min.h + _synctex_abs(_synctex_data_width(node)); + box.min.v = synctex_node_v(node); + box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); + box.min.v -= _synctex_abs(_synctex_data_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_proxy_vbox: + box.min.h = synctex_node_h(node); + box.max.h = box.min.h + _synctex_abs(synctex_node_width(node)); + box.min.v = synctex_node_v(node); + box.max.v = box.min.v + _synctex_abs(synctex_node_depth(node)); + box.min.v -= _synctex_abs(synctex_node_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + box.min.h = synctex_node_hbox_h(node); + box.max.h = box.min.h + _synctex_abs(synctex_node_hbox_width(node)); + box.min.v = synctex_node_hbox_v(node); + box.max.v = box.min.v + _synctex_abs(synctex_node_hbox_depth(node)); + box.min.v -= _synctex_abs(synctex_node_hbox_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* best of distances from the left edge and right edge*/ + box.min.h = _synctex_data_h(node); + box.max.h = box.min.h; + box.min.v = _synctex_data_v(node); + box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); + box.min.v -= _synctex_abs(_synctex_data_height(node)); + d = _synctex_distance_to_box_v2(hit,&box); + box.min.h = box.min.h + _synctex_abs(_synctex_data_width(node)); + box.max.h = box.min.h; + dd = _synctex_distance_to_box_v2(hit,&box); + return d
*/ + return deep; + } + } while((child = synctex_node_sibling(child))); + /* For vboxes we try to use some node inside. + * Walk through the list of siblings until we find the closest one. + * Only consider siblings with children inside. */ + if (synctex_node_type(node) == synctex_node_type_vbox + || synctex_node_type(node) == synctex_node_type_proxy_vbox) { + if ((child = synctex_node_child(node))) { + synctex_nd_s best = SYNCTEX_ND_0; + do { + if (synctex_node_child(child)) { + int d = _synctex_point_node_distance_v2(hit,child); + if (d < best.distance) { + best = (synctex_nd_s){child,d}; + } + } + } while((child = synctex_node_sibling(child))); + if (best.node) { + return best; + } + } + } + /* is the hit point inside the box? */ + if (_synctex_point_in_box_v2(hit,node)) { + return (synctex_nd_s){node, 0}; + } + } + } + return SYNCTEX_ND_0; +} + +/* Compares the locations of the hit point with the locations of + * the various nodes contained in the box. + * As it is an horizontal box, we only compare horizontal coordinates. + */ +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s childd = SYNCTEX_ND_0; + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if ((childd.node = synctex_node_child(node))) { + synctex_nd_s nd = SYNCTEX_ND_0; + do { + childd = _synctex_point_h_ordered_distance_v2(hitP,childd.node); + if (childd.distance > 0) { + /* node is to the right of the hit point. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > childd.distance) { + nds.r = childd; + } else if (nds.r.distance == childd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(childd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(childd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(childd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(childd.node)))) { + nds.r = childd; + } + } + } else if (childd.distance == 0) { + /* hit point is inside node. */ + if (_synctex_tree_child(childd.node)) { + return _synctex_eq_get_closest_children_in_box_v2(hitP, childd.node); + } + nds.l = childd; + } else { /* here childd.distance < 0, the hit point is to the right of node */ + childd.distance = -childd.distance; + if (nds.l.distance > childd.distance) { + nds.l = childd; + } else if (nds.l.distance == childd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(childd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(childd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(childd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(childd.node)))) { + nds.l = childd; + } + } + } + } while((childd.node = synctex_node_sibling(childd.node))); + if (nds.l.node) { + /* the left node is new, try to narrow the result */ + if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.l.node)).node) { + nds.l = nd; + } + if((nd = __synctex_closest_deep_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + /* the right node is new, try to narrow the result */ + if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.r.node)).node) { + nds.r = nd; + } + if((nd = __synctex_closest_deep_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} + +#if 0 +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v3(synctex_point_p hitP, synctex_node_p nodeP) { + synctex_nd_s nd = SYNCTEX_ND_0; + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if ((nd.node = _synctex_tree_child(nodeP))) { + do { + nd = _synctex_point_h_ordered_distance_v2(hitP,nd.node); + if (nd.distance > 0) { + /* node is to the right of the hit point. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > nd.distance) { + nds.r = nd; + } else if (nds.r.distance == nd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { + nds.r = nd; + } + } + } else if (nd.distance == 0) { + /* hit point is inside node. */ + nds.l = nd; + } else { /* here nd.d < 0, the hit point is to the right of node */ + nd.distance = -nd.distance; + if (nds.l.distance > nd.distance) { + nds.l = nd; + } else if (nds.l.distance == nd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { + nds.l = nd; + } + } + } + } while((nd.node = __synctex_tree_sibling(nd.node))); + if (nds.l.node) { + /* the left node is new, try to narrow the result */ + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { + nds.l.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + /* the right node is new, try to narrow the result */ + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { + nds.r.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} +#endif +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP) { + SYNCTEX_UNUSED(nodeP) + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + synctex_nd_s nd = SYNCTEX_ND_0; + if ((nd.node = synctex_node_child(nd.node))) { + do { + nd = _synctex_point_v_ordered_distance_v2(hitP,nd.node); + /* this is what makes the difference with the h version above */ + if (nd.distance > 0) { + /* node is to the top of the hit point (below because TeX is oriented from top to bottom. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > nd.distance) { + nds.r = nd; + } else if (nds.r.distance == nd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { + nds.r = nd; + } + } + } else if (nd.distance == 0) { + nds.l = nd; + } else { /* here nd < 0 */ + nd.distance = -nd.distance; + if (nds.l.distance > nd.distance) { + nds.l = nd; + } else if (nds.l.distance == nd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { + nds.l = nd; + } + } + } + } while((nd.node = synctex_node_sibling(nd.node))); + if (nds.l.node) { + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { + nds.l.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { + nds.r.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} + +/** + * Get the child closest to the hit point. + * - parameter: hit point + * - parameter: containing node + * - returns: the child and the distance to the hit point. + * SYNCTEX_ND_0 if the parameter node has no children. + * - note: recursive call. + */ +static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s best = SYNCTEX_ND_0; + synctex_node_p child = NULL; + if ((child = synctex_node_child(node))) { +#if defined(SYNCTEX_DEBUG) + printf("Closest deep child on box at line %i\n", + SYNCTEX_LINEINDEX(node)); +#endif + do { +#if SYNCTEX_DEBUG>500 + synctex_node_display(child); +#endif + synctex_nd_s nd = SYNCTEX_ND_0; + if (_synctex_node_is_box(child)) { + nd = __synctex_closest_deep_child_v2(hitP,child); + } else { + nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP,child)}; + } + if (nd.distance < best.distance ||(nd.distance == best.distance + && synctex_node_type(nd.node) != synctex_node_type_kern)) { +#if defined(SYNCTEX_DEBUG) + if(nd.node) { + printf("New best %i<=%i line %i\n",nd.distance, + best.distance,SYNCTEX_LINEINDEX(nd.node)); + } +#endif + best = nd; + } + } while((child = synctex_node_sibling(child))); +#if defined(SYNCTEX_DEBUG) + if(best.node) { + printf("Found new best %i line %i\n",best.distance,SYNCTEX_LINEINDEX(best.node)); + } +#endif + } + return best; +} + +/** + * Return the closest child. + * - parameter: a pointer to the hit point, + * - parameter: the container + * - return: SYNCTEX_ND_0 if node has no child, + * the __synctex_closest_deep_child_v2 otherwise. + */ +static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s nd = SYNCTEX_ND_0; + if (_synctex_node_is_box(node)) { + nd = __synctex_closest_deep_child_v2(hitP, node); + if (_synctex_node_is_box(nd.node)) { + synctex_node_p child = NULL; + if ((child = synctex_node_child(nd.node))) { + synctex_nd_s best = {child,_synctex_point_node_distance_v2(hitP,child)}; + while((child = synctex_node_sibling(child))) { + int d = _synctex_point_node_distance_v2(hitP,child); + if (d < best.distance) { + best = (synctex_nd_s){child,d}; + } else if (d == best.distance && synctex_node_type(child) != synctex_node_type_kern) { + best.node = child; + } + } + return best; + } + } + return nd; + } + return SYNCTEX_ND_0; +} +SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if(_synctex_tree_has_child(node)) { /* node != NULL */ + if (node->class_->type==synctex_node_type_hbox || + node->class_->type==synctex_node_type_proxy_hbox) { + return __synctex_eq_get_closest_children_in_hbox_v2(hitP,node); + } else { + return __synctex_eq_get_closest_children_in_vbox_v2(hitP,node); + } + } + return nds; +} + +#ifndef SYNCTEX_NO_UPDATER + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Updater +# endif + +typedef int (*synctex_print_f)(synctex_updater_p, const char * , ...); /* print formatted to either FILE * or gzFile */ +typedef void (*synctex_close_f)(synctex_updater_p); /* close FILE * or gzFile */ + +# define SYNCTEX_BITS_PER_BYTE 8 + +typedef union { + gzFile as_gzFile; + FILE * as_FILE_p; + void * as_ptr; +} syncex_file_u; + +struct synctex_updater_t { + syncex_file_u file; + synctex_print_f print; + synctex_close_f close; + int length; /* the number of chars appended */ +}; + +static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) { + int result = 0; + if (updater) { + va_list va; + va_start(va, format); + result = vfprintf(updater->file.as_FILE_p, + format, + va); + va_end(va); + } + return result; +} +#if defined(_MSC_VER) +#include +#include +#include + +static int vasprintf(char **ret, + const char *format, + va_list ap) +{ + int len; + len = _vsnprintf(NULL, 0, format, ap); + if (len < 0) return -1; + *ret = malloc(len + 1); + if (!*ret) return -1; + _vsnprintf(*ret, len+1, format, ap); + (*ret)[len] = '\0'; + return len; +} + +#endif + +/** + * gzvprintf is not available until OSX 10.10 + */ +static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) { + int result = 0; + if (updater) { + char * buffer; + va_list va; + va_start(va, format); + if (vasprintf(&buffer, format, va) < 0) { + _synctex_error("Out of memory..."); + } else if ((result = (int)strlen(buffer))) { + result = gzwrite(updater->file.as_gzFile, buffer, (unsigned)result); + } + va_end(va); + free(buffer); + } + return result; +} + +static void _synctex_updater_close(synctex_updater_p updater) { + if (updater) { + fclose(updater->file.as_FILE_p); + } +} + +static void _synctex_updater_close_gz(synctex_updater_p updater) { + if (updater) { + gzclose(updater->file.as_gzFile); + } +} + +synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * build_directory) { + synctex_updater_p updater = NULL; + const char * mode = NULL; + synctex_open_s open; + /* prepare the updater, the memory is the only one dynamically allocated */ + updater = (synctex_updater_p)_synctex_malloc(sizeof(synctex_updater_s)); + if (NULL == updater) { + _synctex_error("! synctex_updater_new_with_file: malloc problem"); + return NULL; + } + open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES); + if (open.status < SYNCTEX_STATUS_OK) { + open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES); + if (open.status < SYNCTEX_STATUS_OK) { + return_on_error: + _synctex_free(updater); + return updater = NULL; + } + } + /* OK, the file exists, we close it and reopen it with the correct mode. + * The receiver is now the owner of the "synctex" variable. */ + gzclose(open.file); + updater->file.as_ptr = NULL; + mode = _synctex_get_io_mode_name(open.io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */ + if (open.io_mode&synctex_io_gz_mask) { + if (NULL == (updater->file.as_FILE_p = fopen(open.synctex,mode))) { + no_write_error: + _synctex_error("! synctex_updater_new_with_file: Can't append to %s",open.synctex); + free(open.synctex); + goto return_on_error; + } + updater->print = &_synctex_updater_print; + updater->close = &_synctex_updater_close; + } else { + if (NULL == (updater->file.as_gzFile = gzopen(open.synctex,mode))) { + goto no_write_error; + } + updater->print = &_synctex_updater_print_gz; + updater->close = &_synctex_updater_close_gz; + } + printf("SyncTeX: updating %s...",open.synctex); + _synctex_free(open.synctex); + return updater; +} + +void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification){ + if (NULL==updater) { + return; + } + if (magnification && strlen(magnification)) { + updater->length += + updater->print(updater,"Magnification:%s\n",magnification); + } +} + +void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset){ + if (NULL==updater) { + return; + } + if (x_offset && strlen(x_offset)) { + updater->length += updater->print(updater,"X Offset:%s\n",x_offset); + } +} + +void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset){ + if (NULL==updater) { + return; + } + if (y_offset && strlen(y_offset)) { + updater->length += updater->print(updater,"Y Offset:%s\n",y_offset); + } +} + +void synctex_updater_free(synctex_updater_p updater){ + if (NULL==updater) { + return; + } + if (updater->length>0) { + updater->print(updater,"!%i\n",updater->length); + } + updater->close(updater); + _synctex_free(updater); + printf("... done.\n"); + return; +} +#endif + +#if defined(SYNCTEX_TESTING) +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Testers +# endif +static int _synctex_input_copy_name(synctex_node_p input, char * name) { + char * copy = _synctex_malloc(strlen(name)+1); + memcpy(copy,name,strlen(name)+1); + _synctex_data_set_name(input,copy); + return 0; +} +int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,4); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==4,""); + synctex_node_free(scanner->sheet); + scanner->sheet = sheet; + sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,2); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==2,""); + __synctex_tree_set_sibling(sheet, scanner->sheet); + scanner->sheet = sheet; + sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,1); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==1,""); + __synctex_tree_set_sibling(sheet, scanner->sheet); + scanner->sheet = sheet; + return TC; +} +int synctex_test_input(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); + _synctex_data_set_tag(input,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==421,""); + _synctex_data_set_tag(input,124); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==124,""); + _synctex_data_set_line(input,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); + _synctex_data_set_line(input,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); + _synctex_data_set_line(input,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); + _synctex_input_copy_name(input,"214"); + SYNCTEX_TEST_BODY(TC, 0==memcmp(_synctex_data_name(input),"214",4),""); + _synctex_input_copy_name(input,"421421"); + + SYNCTEX_TEST_BODY(TC, + 0==memcmp(_synctex_data_name(input), + "421421", + 4), + ""); + synctex_node_free(input); + return TC; +} +int synctex_test_proxy(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p proxy = synctex_node_new(scanner,synctex_node_type_proxy); + synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_tree_set_target(proxy,target); + _synctex_data_set_tag(target,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(proxy)==421,""); + synctex_node_free(proxy); + synctex_node_free(target); + return TC; +} +int synctex_test_handle(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p handle = synctex_node_new(scanner,synctex_node_type_handle); + synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy); + synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_tree_set_target(handle,target); + _synctex_data_set_tag(target,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==421,""); + _synctex_data_set_line(target,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==214,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==214,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==214,""); + _synctex_data_set_column(target,142); + SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==142,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==142,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==142,""); + _synctex_tree_set_target(proxy,target); + _synctex_tree_set_target(handle,proxy); + _synctex_data_set_tag(target,412); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==412,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==412,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==412,""); + _synctex_data_set_line(target,124); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==124,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==124,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==124,""); + _synctex_data_set_column(target,241); + SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==241,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==241,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==241,""); + synctex_node_free(handle); + synctex_node_free(proxy); + synctex_node_free(target); + return TC; +} +int synctex_test_setup_scanner_input(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); + _synctex_data_set_tag(input,4); + _synctex_input_copy_name(input,"21"); + _synctex_data_set_line(input,421); + synctex_node_free(scanner->input); + scanner->input = input; + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==4,""); + SYNCTEX_TEST_BODY(TC, strcmp(_synctex_data_name(input),"21")==0,""); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); + return TC; +} +int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes) { + int TC = 0; + int n; + for (n=0;nsheet; + synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, synctex_node_page(node)==synctex_node_page(sheet),""); + return TC; +} +int synctex_test_display_query(synctex_scanner_p scanner) { + int TC = synctex_test_setup_scanner_sheets_421(scanner); + synctex_node_p sheet = scanner->sheet; + synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); + sheet = __synctex_tree_sibling(sheet); + node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); + sheet = __synctex_tree_sibling(sheet); + node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, (_synctex_scanner_friend(scanner, 25)==node),""); + synctex_test_setup_scanner_input(scanner); + scanner->flags.has_parsed = synctex_YES; +#if 1 + SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner,"21",21,4,-1)==3),""); +#endif + return TC; +} +typedef struct { + int s; /* status */ + char n[25]; /* name */ +} synctex_test_sn_s; + +synctex_test_sn_s synctex_test_tmp_sn(char * content) { + synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"}; + FILE *sfp; + int fd = mkstemps(sn.n,8); + if (fd < 0) { + fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); + sn.s = -1; + return sn; + } + if ((sfp = fdopen(fd, "w+")) == NULL) { + unlink(sn.n); + close(fd); + fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); + sn.s = -2; + return sn; + } + sn.s = fputs(content,sfp); + printf("temp:%s\n%i\n",sn.n,sn.s); + fclose(sfp); + if (sn.s==0) { + sn.s = -2; + unlink(sn.n); + } + return sn; +} +int synctex_test_sheet_1() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "] \n" /*90-99*/ + "} \n" /*00-09*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = synctex_node_next(node); + } + synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_sheet_2() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "(1,10:20,350:330,330,0 \n" /*60-89*/ + ") \n" /*90-99*/ + "} \n" /*00-09*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = _synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_charindex() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "(1,58:20,100:250,10,5 \n" /*90-119*/ + "f1000:50,100 \n" /*20-39*/ + ") \n" /*40-49*/ + "] \n" /*50-59*/ + "} \n" /*60-69*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_form() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "(1,58:20,100:250,10,5 \n" /*90-119*/ + "f1000:50,100 \n" /*20-39*/ + ") \n" /*40-49*/ + "] \n" /*50-59*/ + "} \n" /*60-69*/ + "<1000 \n" /*70-79*/ + "(1,63:0,0:100,8,3 \n" /*80-99*/ + ") \n" /*00-09*/ + "> \n" /*10-19*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = _synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +#endif diff --git a/elpa/pdf-tools-20230611.239/build/server/synctex_parser.h b/elpa/pdf-tools-20230611.239/build/server/synctex_parser.h new file mode 100644 index 00000000..9e0a00e9 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser.h @@ -0,0 +1,429 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + + ## Acknowledgments: + + The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh, + and significant help from __XeTeX__ developer Jonathan Kew. + + ## Nota Bene: + + If you include or use a significant part of the __SyncTeX__ package into a software, + I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted. +*/ + +#ifndef __SYNCTEX_PARSER__ +# define __SYNCTEX_PARSER__ + +#include "synctex_version.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* The main synctex object is a scanner. + * Its implementation is considered private. + * The basic workflow is + * - create a "synctex scanner" with the contents of a file + * - perform actions on that scanner like + synctex_display_query or synctex_edit_query below. + * - perform actions on nodes returned by the scanner + * - free the scanner when the work is done + */ + typedef struct synctex_scanner_t synctex_scanner_s; + typedef synctex_scanner_s * synctex_scanner_p; + + /** + * This is the designated method to create + * a new synctex scanner object. + * - argument output: the pdf/dvi/xdv file associated + * to the synctex file. + * If necessary, it can be the tex file that + * originated the synctex file but this might cause + * problems if the \jobname has a custom value. + * Despite this method can accept a relative path + * in practice, you should only pass full paths. + * The path should be encoded by the underlying + * file system, assuming that it is based on + * 8 bits characters, including UTF8, + * not 16 bits nor 32 bits. + * The last file extension is removed and + * replaced by the proper extension, + * either synctex or synctex.gz. + * - argument build_directory: It is the directory where + * all the auxiliary stuff is created. + * If no synctex file is found in the same directory + * as the output file, then we try to find one in + * this build directory. + * It is the directory where all the auxiliary + * stuff is created. Sometimes, the synctex output + * file and the pdf, dvi or xdv files are not + * created in the same location. See MikTeX. + * This directory path can be NULL, + * it will be ignored then. + * It can be either absolute or relative to the + * directory of the output pdf (dvi or xdv) file. + * Please note that this new argument is provided + * as a convenience but should not be used. + * Available since version 1.5. + * - argument parse: In general, use 1. + * Use 0 only if you do not want to parse the + * content but just check for existence. + * Available since version 1.5 + * - return: a scanner. NULL is returned in case + * of an error or non existent file. + */ + synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse); + + /** + * Designated method to delete a synctex scanner object, + * including all its internal resources. + * Frees all the memory, you must call it when you are finished with the scanner. + * - argument scanner: a scanner. + * - returns: an integer used for testing purposes. + */ + int synctex_scanner_free(synctex_scanner_p scanner); + + /** + * Send this message to force the scanner to + * parse the contents of the synctex output file. + * Nothing is performed if the file was already parsed. + * In each query below, this message is sent, + * but if you need to access information more directly, + * you must ensure that the parsing did occur. + * Usage: + * if((my_scanner = synctex_scanner_parse(my_scanner))) { + * continue with my_scanner... + * } else { + * there was a problem + * } + * - returns: the argument on success. + * On failure, frees scanner and returns NULL. + */ + synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner); + + /* synctex_node_p is the type for all synctex nodes. + * Its implementation is considered private. + * The synctex file is parsed into a tree of nodes, either sheet, form, boxes, math nodes... */ + + typedef struct synctex_node_t synctex_node_s; + typedef synctex_node_s * synctex_node_p; + + /* The main entry points. + * Given the file name, a line and a column number, synctex_display_query returns the number of nodes + * satisfying the contrain. Use code like + * + * if(synctex_display_query(scanner,name,line,column,page_hint)>0) { + * synctex_node_p node; + * while((node = synctex_scanner_next_result(scanner))) { + * // do something with node + * ... + * } + * } + * + * Please notice that since version 1.19, + * there is a new argument page_hint. + * The results in pages closer to page_hint are given first. + * For example, one can + * - highlight each resulting node in the output, using synctex_node_visible_h and synctex_node_visible_v + * - highlight all the rectangles enclosing those nodes, using synctex_node_box_visible_... functions + * - highlight just the character using that information + * + * Given the page and the position in the page, synctex_edit_query returns the number of nodes + * satisfying the contrain. Use code like + * + * if(synctex_edit_query(scanner,page,h,v)>0) { + * synctex_node_p node; + * while(node = synctex_scanner_next_result(scanner)) { + * // do something with node + * ... + * } + * } + * + * For example, one can + * - highlight each resulting line in the input, + * - highlight just the character using that information + * + * page is 1 based + * h and v are coordinates in 72 dpi unit, relative to the top left corner of the page. + * If you make a new query, the result of the previous one is discarded. If you need to make more than one query + * in parallel, use the iterator API exposed in + * the synctex_parser_private.h header. + * If one of this function returns a negative integer, + * it means that an error occurred. + * + * Both methods are conservative, in the sense that matching is weak. + * If the exact column number is not found, there will be an answer with the whole line. + * + * Sumatra-PDF, Skim, iTeXMac2, TeXShop and Texworks are examples of open source software that use this library. + * You can browse their code for a concrete implementation. + */ + typedef long synctex_status_t; + /* The page_hint argument is used to resolve ambiguities. + * Whenever, different matches occur, the ones closest + * to the page will be given first. Pass a negative number + * when in doubt. Using pdf forms may lead to ambiguities. + */ + synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint); + synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v); + synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner); + synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner); + + /** + * The horizontal and vertical location, + * the width, height and depth of a box enclosing node. + * All dimensions are given in page coordinates + * as opposite to TeX coordinates. + * The origin is at the top left corner of the page. + * Code example for Qt5: + * (from TeXworks source TWSynchronize.cpp) + * QRectF nodeRect(synctex_node_box_visible_h(node), + * synctex_node_box_visible_v(node) - + * synctex_node_box_visible_height(node), + * synctex_node_box_visible_width(node), + * synctex_node_box_visible_height(node) + + * synctex_node_box_visible_depth(node)); + * Code example for Cocoa: + * NSRect bounds = [pdfPage + * boundsForBox:kPDFDisplayBoxMediaBox]; + * NSRect nodeRect = NSMakeRect( + * synctex_node_box_visible_h(node), + * NSMaxY(bounds)-synctex_node_box_visible_v(node) + + * synctex_node_box_visible_height(node), + * synctex_node_box_visible_width(node), + * synctex_node_box_visible_height(node) + + * synctex_node_box_visible_depth(node) + * ); + * The visible dimensions are bigger than real ones + * to compensate 0 width boxes or nodes intentionnaly + * put outside the box (using \kern for example). + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ + float synctex_node_box_visible_h(synctex_node_p node); + float synctex_node_box_visible_v(synctex_node_p node); + float synctex_node_box_visible_width(synctex_node_p node); + float synctex_node_box_visible_height(synctex_node_p node); + float synctex_node_box_visible_depth(synctex_node_p node); + + /** + * For quite all nodes, horizontal and vertical coordinates, and width. + * All dimensions are given in page coordinates + * as opposite to TeX coordinates. + * The origin is at the top left corner of the page. + * The visible dimensions are bigger than real ones + * to compensate 0 width boxes or nodes intentionnaly + * put outside the box (using \kern for example). + * All nodes have coordinates, but all nodes don't + * have non null size. For example, math nodes + * have no width according to TeX, and in that case + * synctex_node_visible_width simply returns 0. + * The same holds for kern nodes that do not have + * height nor depth, etc... + */ + float synctex_node_visible_h(synctex_node_p node); + float synctex_node_visible_v(synctex_node_p node); + float synctex_node_visible_width(synctex_node_p node); + float synctex_node_visible_height(synctex_node_p node); + float synctex_node_visible_depth(synctex_node_p node); + + /** + * Given a node, access to its tag, line and column. + * The line and column numbers are 1 based. + * The latter is not yet fully supported in TeX, + * the default implementation returns 0 + * which means the whole line. + * synctex_node_get_name returns the path of the + * TeX source file that was used to create the node. + * When the tag is known, the scanner of the node + * will also give that same file name, see + * synctex_scanner_get_name below. + * For an hbox node, the mean line is the mean + * of all the lines of the child nodes. + * Sometimes, when synchronization form pdf to source + * fails with the line, one should try with the + * mean line. + */ + int synctex_node_tag(synctex_node_p node); + int synctex_node_line(synctex_node_p node); + int synctex_node_mean_line(synctex_node_p node); + int synctex_node_column(synctex_node_p node); + const char * synctex_node_get_name(synctex_node_p node); + + /** + This is the page where the node appears. + * This is a 1 based index as given by TeX. + */ + int synctex_node_page(synctex_node_p node); + + /** + * Display all the information contained in the scanner. + * If the records are too numerous, only the first ones are displayed. + * This is mainly for informational purpose to help developers. + */ + void synctex_scanner_display(synctex_scanner_p scanner); + + /* Managing the input file names. + * Given a tag, synctex_scanner_get_name will return the corresponding file name. + * Conversely, given a file name, synctex_scanner_get_tag will return, the corresponding tag. + * The file name must be the very same as understood by TeX. + * For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex. + * No automatic path expansion is performed. + * Finally, synctex_scanner_input is the first input node of the scanner. + * To browse all the input node, use a loop like + * ... + * synctex_node_p = input_node; + * ... + * if((input_node = synctex_scanner_input(scanner))) { + * do { + * blah + * } while((input_node=synctex_node_sibling(input_node))); + * } + * + * The output is the name that was used to create the scanner. + * The synctex is the real name of the synctex file, + * it was obtained from output by setting the proper file extension. + */ + const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag); + + int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name); + + synctex_node_p synctex_scanner_input(synctex_scanner_p scanner); + synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner,int tag); + const char * synctex_scanner_get_output(synctex_scanner_p scanner); + const char * synctex_scanner_get_synctex(synctex_scanner_p scanner); + + /* The x and y offset of the origin in TeX coordinates. The magnification + These are used by pdf viewers that want to display the real box size. + For example, getting the horizontal coordinates of a node would require + synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner) + Getting its TeX width would simply require + synctex_node_box_width(node)*synctex_scanner_magnification(scanner) + but direct methods are available for that below. + */ + int synctex_scanner_x_offset(synctex_scanner_p scanner); + int synctex_scanner_y_offset(synctex_scanner_p scanner); + float synctex_scanner_magnification(synctex_scanner_p scanner); + + /** + * ## Browsing the nodes + * parent, child and sibling are standard names for tree nodes. + * The parent is one level higher, + * the child is one level deeper, + * and the sibling is at the same level. + * A node and its sibling have the same parent. + * A node is the parent of its children. + * A node is either the child of its parent, + * or belongs to the sibling chain of its parent's child. + * The sheet or form of a node is the topmost ancestor, + * it is of type sheet or form. + * The next node is either the child, the sibling or the parent's sibling, + * unless the parent is a sheet, a form or NULL. + * This allows to navigate through all the nodes of a given sheet node: + * + * synctex_node_p node = sheet; + * while((node = synctex_node_next(node))) { + * // do something with node + * } + * + * With synctex_sheet_content and synctex_form_content, + * you can retrieve the sheet node given the page + * or form tag. + * The page is 1 based, according to TeX standards. + * Conversely synctex_node_parent_sheet or + * synctex_node_parent_form allows to retrieve + * the sheet or the form containing a given node. + * Notice that a node is not contained in a sheet + * and a form at the same time. + * Some nodes are not contained in either (handles). + */ + + synctex_node_p synctex_node_parent(synctex_node_p node); + synctex_node_p synctex_node_parent_sheet(synctex_node_p node); + synctex_node_p synctex_node_parent_form(synctex_node_p node); + synctex_node_p synctex_node_child(synctex_node_p node); + synctex_node_p synctex_node_last_child(synctex_node_p node); + synctex_node_p synctex_node_sibling(synctex_node_p node); + synctex_node_p synctex_node_last_sibling(synctex_node_p node); + synctex_node_p synctex_node_arg_sibling(synctex_node_p node); + synctex_node_p synctex_node_next(synctex_node_p node); + + /** + * Top level entry points. + * The scanner owns a list of sheet siblings and + * a list of form siblings. + * Sheets or forms have one child which is a box: + * theie contents. + * - argument page: 1 based sheet page number. + * - argument tag: 1 based form tag number. + */ + synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page); + synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page); + synctex_node_p synctex_form(synctex_scanner_p scanner,int tag); + synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag); + + /* This is primarily used for debugging purpose. + * The second one logs information for the node and recursively displays information for its next node */ + void synctex_node_log(synctex_node_p node); + void synctex_node_display(synctex_node_p node); + + /* For quite all nodes, horizontal, vertical coordinates, and width. + * These are expressed in TeX small points coordinates, with origin at the top left corner. + */ + int synctex_node_h(synctex_node_p node); + int synctex_node_v(synctex_node_p node); + int synctex_node_width(synctex_node_p node); + int synctex_node_height(synctex_node_p node); + int synctex_node_depth(synctex_node_p node); + + /* For all nodes, dimensions of the enclosing box. + * These are expressed in TeX small points coordinates, with origin at the top left corner. + * A box is enclosing itself. + */ + int synctex_node_box_h(synctex_node_p node); + int synctex_node_box_v(synctex_node_p node); + int synctex_node_box_width(synctex_node_p node); + int synctex_node_box_height(synctex_node_p node); + int synctex_node_box_depth(synctex_node_p node); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elpa/pdf-tools-20230611.239/build/server/synctex_parser_advanced.h b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_advanced.h new file mode 100644 index 00000000..95c2ac19 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_advanced.h @@ -0,0 +1,554 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + */ + +#include "synctex_parser.h" +#include "synctex_parser_utils.h" + +#ifndef __SYNCTEX_PARSER_PRIVATE__ +# define __SYNCTEX_PARSER_PRIVATE__ + +#ifdef __cplusplus +extern "C" { +#endif + /* Reminder that the argument must not be NULL */ + typedef synctex_node_p synctex_non_null_node_p; + + /* Each node of the tree, except the scanner itself belongs to a class. + * The class object is just a struct declaring the owning scanner + * This is a pointer to the scanner as root of the tree. + * The type is used to identify the kind of node. + * The class declares pointers to a creator and a destructor method. + * The log and display fields are used to log and display the node. + * display will also display the child, sibling and parent sibling. + * parent, child and sibling are used to navigate the tree, + * from TeX box hierarchy point of view. + * The friend field points to a method which allows to navigate from friend to friend. + * A friend is a node with very close tag and line numbers. + * Finally, the info field point to a method giving the private node info offset. + */ + + /** + * These are the masks for the synctex node types. + * int's are 32 bits at least. + */ + enum { + synctex_shift_root, + synctex_shift_no_root, + synctex_shift_void, + synctex_shift_no_void, + synctex_shift_box, + synctex_shift_no_box, + synctex_shift_proxy, + synctex_shift_no_proxy, + synctex_shift_h, + synctex_shift_v + }; + enum { + synctex_mask_root = 1, + synctex_mask_no_root = synctex_mask_root<<1, + synctex_mask_void = synctex_mask_no_root<<1, + synctex_mask_no_void = synctex_mask_void<<1, + synctex_mask_box = synctex_mask_no_void<<1, + synctex_mask_no_box = synctex_mask_box<<1, + synctex_mask_proxy = synctex_mask_no_box<<1, + synctex_mask_no_proxy = synctex_mask_proxy<<1, + synctex_mask_h = synctex_mask_no_proxy<<1, + synctex_mask_v = synctex_mask_h<<1, + }; + enum { + synctex_mask_non_void_hbox = synctex_mask_no_void + | synctex_mask_box + | synctex_mask_h, + synctex_mask_non_void_vbox = synctex_mask_no_void + | synctex_mask_box + | synctex_mask_v + }; + typedef enum { + synctex_node_mask_sf = + synctex_mask_root + |synctex_mask_no_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_vbox = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_v, + synctex_node_mask_hbox = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_h, + synctex_node_mask_void_vbox = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_v, + synctex_node_mask_void_hbox = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_h, + synctex_node_mask_vbox_proxy = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_proxy + |synctex_mask_v, + synctex_node_mask_hbox_proxy = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_proxy + |synctex_mask_h, + synctex_node_mask_nvnn = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_input = + synctex_mask_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_proxy = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_proxy + } synctex_node_mask_t; + + enum { + /* input */ + synctex_tree_sibling_idx = 0, + synctex_tree_s_input_max = 1, + /* All */ + synctex_tree_s_parent_idx = 1, + synctex_tree_sp_child_idx = 2, + synctex_tree_spc_friend_idx = 3, + synctex_tree_spcf_last_idx = 4, + synctex_tree_spcfl_vbox_max = 5, + /* hbox supplement */ + synctex_tree_spcfl_next_hbox_idx = 5, + synctex_tree_spcfln_hbox_max = 6, + /* hbox proxy supplement */ + synctex_tree_spcfln_target_idx = 6, + synctex_tree_spcflnt_proxy_hbox_max = 7, + /* vbox proxy supplement */ + synctex_tree_spcfl_target_idx = 5, + synctex_tree_spcflt_proxy_vbox_max = 6, + /* spf supplement*/ + synctex_tree_sp_friend_idx = 2, + synctex_tree_spf_max = 3, + /* box boundary supplement */ + synctex_tree_spf_arg_sibling_idx = 3, + synctex_tree_spfa_max = 4, + /* proxy supplement */ + synctex_tree_spf_target_idx = 3, + synctex_tree_spft_proxy_max = 4, + /* last proxy supplement */ + synctex_tree_spfa_target_idx = 4, + synctex_tree_spfat_proxy_last_max = 5, + /* sheet supplement */ + synctex_tree_s_child_idx = 1, + synctex_tree_sc_next_hbox_idx = 2, + synctex_tree_scn_sheet_max = 3, + /* form supplement */ + synctex_tree_sc_target_idx = 2, + synctex_tree_sct_form_max = 3, + /* spct */ + synctex_tree_spc_target_idx = 3, + synctex_tree_spct_handle_max = 4, + }; + + enum { + /* input */ + synctex_data_input_tag_idx = 0, + synctex_data_input_line_idx = 1, + synctex_data_input_name_idx = 2, + synctex_data_input_tln_max = 3, + /* sheet */ + synctex_data_sheet_page_idx = 0, + synctex_data_p_sheet_max = 1, + /* form */ + synctex_data_form_tag_idx = 0, + synctex_data_t_form_max = 1, + /* tlchv */ + synctex_data_tag_idx = 0, + synctex_data_line_idx = 1, + synctex_data_column_idx = 2, + synctex_data_h_idx = 3, + synctex_data_v_idx = 4, + synctex_data_tlchv_max = 5, + /* tlchvw */ + synctex_data_width_idx = 5, + synctex_data_tlchvw_max = 6, + /* box */ + synctex_data_height_idx = 6, + synctex_data_depth_idx = 7, + synctex_data_box_max = 8, + /* hbox supplement */ + synctex_data_mean_line_idx = 8, + synctex_data_weight_idx = 9, + synctex_data_h_V_idx = 10, + synctex_data_v_V_idx = 11, + synctex_data_width_V_idx = 12, + synctex_data_height_V_idx = 13, + synctex_data_depth_V_idx = 14, + synctex_data_hbox_max = 15, + /* ref */ + synctex_data_ref_tag_idx = 0, + synctex_data_ref_h_idx = 1, + synctex_data_ref_v_idx = 2, + synctex_data_ref_thv_max = 3, + /* proxy */ + synctex_data_proxy_h_idx = 0, + synctex_data_proxy_v_idx = 1, + synctex_data_proxy_hv_max = 2, + /* handle */ + synctex_data_handle_w_idx = 0, + synctex_data_handle_w_max = 1, + }; + + /* each synctex node has a class */ + typedef struct synctex_class_t synctex_class_s; + typedef synctex_class_s * synctex_class_p; + + + /* synctex_node_p is a pointer to a node + * synctex_node_s is the target of the synctex_node_p pointer + * It is a pseudo object oriented program. + * class is a pointer to the class object the node belongs to. + * implementation is meant to contain the private data of the node + * basically, there are 2 kinds of information: navigation information and + * synctex information. Both will depend on the type of the node, + * thus different nodes will have different private data. + * There is no inheritancy overhead. + */ + typedef union { + synctex_node_p as_node; + int as_integer; + char * as_string; + void * as_pointer; + } synctex_data_u; + typedef synctex_data_u * synctex_data_p; + +# if defined(SYNCTEX_USE_CHARINDEX) + typedef unsigned int synctex_charindex_t; + synctex_charindex_t synctex_node_charindex(synctex_node_p node); + typedef synctex_charindex_t synctex_lineindex_t; + synctex_lineindex_t synctex_node_lineindex(synctex_node_p node); + synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner); +# define SYNCTEX_DECLARE_CHARINDEX \ + synctex_charindex_t char_index;\ + synctex_lineindex_t line_index; +# define SYNCTEX_DECLARE_CHAR_OFFSET \ + synctex_charindex_t charindex_offset; +# else +# define SYNCTEX_DECLARE_CHARINDEX +# define SYNCTEX_DECLARE_CHAR_OFFSET +# endif + struct synctex_node_t { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; +#ifdef DEBUG + synctex_data_u data[22]; +#else + synctex_data_u data[1]; +#endif + }; + + typedef synctex_node_p * synctex_node_r; + + typedef struct { + int h; + int v; + } synctex_point_s; + + typedef synctex_point_s * synctex_point_p; + + typedef struct { + synctex_point_s min; /* top left */ + synctex_point_s max; /* bottom right */ + } synctex_box_s; + + typedef synctex_box_s * synctex_box_p; + /** + * These are the types of the synctex nodes. + * No need to use them but the compiler needs them here. + * There are 3 kinds of nodes. + * - primary nodes + * - proxies + * - handles + * Primary nodes are created at parse time + * of the synctex file. + * Proxies are used to support pdf forms. + * The ref primary nodes are replaced by a tree + * of proxy nodes which duplicate the tree of primary + * nodes available in the referred form. + * Roughly speaking, the primary nodes of the form + * know what to display, the proxy nodes know where. + * Handles are used in queries. They point to either + * primary nodes or proxies. + */ + typedef enum { + synctex_node_type_none = 0, + synctex_node_type_input, + synctex_node_type_sheet, + synctex_node_type_form, + synctex_node_type_ref, + synctex_node_type_vbox, + synctex_node_type_void_vbox, + synctex_node_type_hbox, + synctex_node_type_void_hbox, + synctex_node_type_kern, + synctex_node_type_glue, + synctex_node_type_rule, + synctex_node_type_math, + synctex_node_type_boundary, + synctex_node_type_box_bdry, + synctex_node_type_proxy, + synctex_node_type_proxy_last, + synctex_node_type_proxy_vbox, + synctex_node_type_proxy_hbox, + synctex_node_type_handle, + synctex_node_number_of_types + } synctex_node_type_t; + /* synctex_node_type gives the type of a given node, + * synctex_node_isa gives the same information as a human readable text. */ + synctex_node_type_t synctex_node_type(synctex_node_p node); + const char * synctex_node_isa(synctex_node_p node); + + synctex_node_type_t synctex_node_target_type(synctex_node_p node); + + synctex_node_type_t synctex_node_type(synctex_node_p node); + const char * synctex_node_isa(synctex_node_p node); + + void synctex_node_log(synctex_node_p node); + void synctex_node_display(synctex_node_p node); + + /* Given a node, access to the location in the synctex file where it is defined. + */ + + int synctex_node_form_tag(synctex_node_p node); + + int synctex_node_weight(synctex_node_p node); + int synctex_node_child_count(synctex_node_p node); + + int synctex_node_h(synctex_node_p node); + int synctex_node_v(synctex_node_p node); + int synctex_node_width(synctex_node_p node); + + int synctex_node_box_h(synctex_node_p node); + int synctex_node_box_v(synctex_node_p node); + int synctex_node_box_width(synctex_node_p node); + int synctex_node_box_height(synctex_node_p node); + int synctex_node_box_depth(synctex_node_p node); + + int synctex_node_hbox_h(synctex_node_p node); + int synctex_node_hbox_v(synctex_node_p node); + int synctex_node_hbox_width(synctex_node_p node); + int synctex_node_hbox_height(synctex_node_p node); + int synctex_node_hbox_depth(synctex_node_p node); + + synctex_scanner_p synctex_scanner_new(void); + synctex_node_p synctex_node_new(synctex_scanner_p scanner,synctex_node_type_t type); + + /** + * Scanner display switcher getter. + * If the switcher is 0, synctex_node_display is disabled. + * If the switcher is <0, synctex_node_display has no limit. + * If the switcher is >0, only the first switcher (as number) nodes are displayed. + * - parameter: a scanner + * - returns: an integer + */ + int synctex_scanner_display_switcher(synctex_scanner_p scanR); + void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher); + + /** + * Iterator is the structure used to traverse + * the answer to client queries. + * First answers are the best matches, according + * to criteria explained below. + * Next answers are not ordered. + * Objects are handles to nodes in the synctex node tree starting at scanner. + */ + typedef struct synctex_iterator_t synctex_iterator_s; + typedef synctex_iterator_s * synctex_iterator_p; + + /** + * Designated creator for a display query, id est, + * forward navigation from source to output. + * Returns NULL if the query has no answer. + * Code example: + * synctex_iterator_p iterator = NULL; + * if ((iterator = synctex_iterator_new_display(...)) { + * synctex_node_p node = NULL; + * while((node = synctex_iterator_next_result(iterator))) { + * do something with node... + * } + */ + synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint); + /** + * Designated creator for an edit query, id est, + * backward navigation from output to source. + * Code example: + * synctex_iterator_p iterator = NULL; + * if ((iterator = synctex_iterator_new_edit(...)) { + * synctex_node_p node = NULL; + * while((node = synctex_iterator_next_result(iterator))) { + * do something with node... + * } + */ + synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v); + /** + * Free all the resources. + * - argument iterator: the object to free... + * You should free the iterator before the scanner + * owning the nodes it iterates with. + */ + void synctex_iterator_free(synctex_iterator_p iterator); + /** + * Whether the iterator actually points to an object. + * - argument iterator: the object to iterate on... + */ + synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator); + /** + * Returns the pointed object and advance the cursor + * to the next object. Returns NULL and does nothing + * if the end has already been reached. + * - argument iterator: the object to iterate on... + */ + synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator); + /** + * Reset the cursor position to the first result. + * - argument iterator: the object to iterate on... + */ + int synctex_iterator_reset(synctex_iterator_p iterator); + /** + * The number of objects left for traversal. + * - argument iterator: the object to iterate on... + */ + int synctex_iterator_count(synctex_iterator_p iterator); + + /** + * The target of the node, either a handle or a proxy. + */ + synctex_node_p synctex_node_target(synctex_node_p node); + +#ifndef SYNCTEX_NO_UPDATER + /* The main synctex updater object. + * This object is used to append information to the synctex file. + * Its implementation is considered private. + * It is used by the synctex command line tool to take into account modifications + * that could occur while postprocessing files by dvipdf like filters. + */ + typedef struct synctex_updater_t synctex_updater_s; + typedef synctex_updater_s * synctex_updater_p; + + /* Designated initializer. + * Once you are done with your whole job, + * free the updater */ + synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * directory); + + /* Use the next functions to append records to the synctex file, + * no consistency tests made on the arguments */ + void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification); + void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset); + void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset); + + /* You MUST free the updater, once everything is properly appended */ + void synctex_updater_free(synctex_updater_p updater); +#endif + +#if defined(SYNCTEX_DEBUG) +# include "assert.h" +# define SYNCTEX_ASSERT assert +#else +# define SYNCTEX_ASSERT(UNUSED) +#endif + +#if defined(SYNCTEX_TESTING) +#warning TESTING IS PROHIBITED +#if __clang__ +#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wformat-extra-args\"") + +#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic pop") +#else +#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS +#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS +#endif + +# define SYNCTEX_TEST_BODY(counter, condition, desc, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (!(condition)) { \ + ++counter; \ + printf("**** Test failed: %s\nfile %s\nfunction %s\nline %i\n",#condition,__FILE__,__FUNCTION__,__LINE__); \ + printf((desc), ##__VA_ARGS__); \ + } \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } while(0) + +# define SYNCTEX_TEST_PARAMETER(counter, condition) SYNCTEX_TEST_BODY(counter, (condition), "Invalid parameter not satisfying: %s", #condition) + + int synctex_test_input(synctex_scanner_p scanner); + int synctex_test_proxy(synctex_scanner_p scanner); + int synctex_test_tree(synctex_scanner_p scanner); + int synctex_test_page(synctex_scanner_p scanner); + int synctex_test_handle(synctex_scanner_p scanner); + int synctex_test_display_query(synctex_scanner_p scanner); + int synctex_test_charindex(); + int synctex_test_sheet_1(); + int synctex_test_sheet_2(); + int synctex_test_sheet_3(); + int synctex_test_form(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/elpa/pdf-tools-20230611.239/build/server/synctex_parser_local.h b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_local.h new file mode 100644 index 00000000..b53439f4 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_local.h @@ -0,0 +1,3 @@ +#include +#define printf(fmt, args...) (fprintf (stderr, (fmt), ## args)) +#define SYNCTEX_INLINE diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_readme.txt b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_readme.txt similarity index 87% rename from elpa/pdf-tools-20191031.642/build/server/synctex_parser_readme.txt rename to elpa/pdf-tools-20230611.239/build/server/synctex_parser_readme.txt index 0243f535..4a25b58f 100644 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_readme.txt +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_readme.txt @@ -1,10 +1,12 @@ This file is part of the SyncTeX package. +Please refer to synctex_parser_readme.md + The Synchronization TeXnology named SyncTeX is a new feature of recent TeX engines designed by Jerome Laurens. It allows to synchronize between input and output, which means to navigate from the source document to the typeset material and vice versa. -More informations on http://itexmac2.sourceforge.net/SyncTeX.html +More information on http://itexmac2.sourceforge.net/SyncTeX.html This package is mainly for developers, it mainly contains the following files: @@ -13,10 +15,11 @@ synctex_parser_version.txt synctex_parser_utils.c synctex_parser_utils.h synctex_parser_local.h +synctex_parser_private.h synctex_parser.h synctex_parser.c -The file you are reading contains more informations about the SyncTeX parser history. +The file you are reading contains more information about the SyncTeX parser history. In order to support SyncTeX in a viewer, it is sufficient to include in the source the files synctex_parser.h and synctex_parser.c. @@ -167,6 +170,25 @@ TeX and friends are not concerned by these changes. - cosmetic changes: uniform indentation - suppression of warnings, mainly long/int ones. In short, zlib likes ints when size_t likes longs. - CLI synctex tool can build out of TeXLive (modulo appropriate options passed to the compiler) +1.19: Thu Mar 9 21:26:27 UTC 2017 +- the nested sheets patch was not a good solution. + It has been moved from the parser to the engine. + See the synctex.c source file for detailed explanations. +- there is a new synctex format specification. + We can see that a .synctex file can contain many times + the same vertical position because many objects belong + to the same line. When the options read -synctex=±2 or more, + a very basic compression algorithm is used: + if synctex is about write the same number then it writes + an = sign instead. This saves approximately 10% of the + synctex output file, either compressed or not. + The new synctex parser has been updated accordingly. + Actual tex frontend won't see any difference with the + TeX engines that include this new feature. + Frontends with the new parser won't see any difference + with the older TeX engines. + Frontends with the new parser will only see a difference + with new TeX engines if -synctex=±2 or more is used. Acknowledgments: ---------------- diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.c b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.c similarity index 80% rename from elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.c rename to elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.c index 0e9fd0e5..5be3d099 100644 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.c +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.c @@ -1,41 +1,40 @@ /* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.18 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. */ @@ -61,7 +60,7 @@ authorization from the copyright holder. #define SYNCTEX_OS2 1 #endif -#ifdef _WIN32_WINNT_WINXP +#if defined(_WIN32) #define SYNCTEX_RECENT_WINDOWS 1 #endif @@ -71,18 +70,25 @@ authorization from the copyright holder. #endif void *_synctex_malloc(size_t size) { - void * ptr = malloc(size); - if(ptr) { -/* There used to be a switch to use bzero because it is more secure. JL */ - memset(ptr,0, size); - } - return (void *)ptr; + void * ptr = malloc(size); + if(ptr) { + memset(ptr,0, size);/* ensures null termination of strings */ + } + return (void *)ptr; } -int _synctex_error(const char * reason,...) { - va_list arg; +void _synctex_free(void * ptr) { + if (ptr) { + free(ptr); + } +} + +#if !defined(_WIN32) +# include +#endif + +int _synctex_log(int level, const char * prompt, const char * reason,va_list arg) { int result; - va_start (arg, reason); # ifdef SYNCTEX_RECENT_WINDOWS {/* This code is contributed by William Blum. As it does not work on some older computers, @@ -94,23 +100,65 @@ int _synctex_error(const char * reason,...) { JL.*/ char *buff; size_t len; - OutputDebugStringA("SyncTeX ERROR: "); + OutputDebugStringA(prompt); len = _vscprintf(reason, arg) + 1; buff = (char*)malloc( len * sizeof(char) ); - result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: "); + result = vsprintf(buff, reason, arg) +strlen(prompt); OutputDebugStringA(buff); OutputDebugStringA("\n"); free(buff); } +# elif SYNCTEX_USE_SYSLOG + char * buffer1 = NULL; + char * buffer2 = NULL; + openlog ("SyncTeX", LOG_CONS | LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_LOCAL0); + if (vasprintf(&buffer1,reason,arg)>=0 + && asprintf(&buffer2,"%s%s",prompt, buffer1)>=0) { + syslog (level, "%s", buffer2); + result = (int)strlen(buffer2); + } else { + syslog (level, "%s",prompt); + vsyslog(level,reason,arg); + result = (int)strlen(prompt); + } + free(buffer1); + free(buffer2); + closelog(); # else - result = fprintf(stderr,"SyncTeX ERROR: "); - result += vfprintf(stderr, reason, arg); - result += fprintf(stderr,"\n"); + FILE * where = level == LOG_ERR? stderr: stdout; + result = fputs(prompt,where); + result += vfprintf(where, reason, arg); + result += fprintf(where,"\n"); # endif - va_end (arg); return result; } +int _synctex_error(const char * reason,...) { + va_list arg; + int result; + va_start (arg, reason); +#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_ERR is not used */ + result = _synctex_log(0, "! SyncTeX Error : ", reason, arg); +#else + result = _synctex_log(LOG_ERR, "! SyncTeX Error : ", reason, arg); +#endif + va_end (arg); + return result; +} + +int _synctex_debug(const char * reason,...) { + va_list arg; + int result; + va_start (arg, reason); +#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_DEBUG is not used */ + result = _synctex_log(0, "! SyncTeX Error : ", reason, arg); +#else + result = _synctex_log(LOG_DEBUG, "! SyncTeX Error : ", reason, arg); +#endif + va_end (arg); + return result; +} + /* strip the last extension of the given string, this string is modified! */ void _synctex_strip_last_path_extension(char * string) { if(NULL != string){ @@ -250,10 +298,10 @@ const char * _synctex_last_path_component(const char * name) { } int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) { - const char * lpc; if(src && dest_ref) { + const char * lpc; # define dest (*dest_ref) - dest = NULL; /* Default behavior: no change and sucess. */ + dest = NULL; /* Default behavior: no change and success. */ lpc = _synctex_last_path_component(src); if(strlen(lpc)) { if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') { @@ -396,7 +444,6 @@ int _synctex_get_name(const char * output, const char * build_directory, char ** if(NULL == (dir_name = (char *)malloc(size+1))) { _synctex_error("! _synctex_get_name: Memory problem"); free(core_name); - dir_name = NULL; return -1; } if(dir_name != strncpy(dir_name,output,size)) { @@ -497,6 +544,17 @@ int _synctex_get_name(const char * output, const char * build_directory, char ** # undef CLEAN_AND_REMOVE /* set up the returned values */ * synctex_name_ref = synctex_name; + /* synctex_name won't always end in .gz, even when compressed. */ + FILE * F = fopen(synctex_name, "r"); + if (F != NULL) { + if (!feof(F) + && 31 == fgetc(F) + && !feof(F) + && 139 == fgetc(F)) { + io_mode = synctex_compress_mode_gz; + } + fclose(F); + } * io_mode_ref = io_mode; return 0; } diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.h b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.h similarity index 89% rename from elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.h rename to elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.h index 9c76ac52..4dd4e17e 100644 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_utils.h +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_utils.h @@ -1,16 +1,15 @@ /* -Copyright (c) 2008, 2009, 2010, 2011 jerome DOT laurens AT u-bourgogne DOT fr + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.18 - -See synctex_parser_readme.txt for more details - -License: --------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without @@ -39,16 +38,22 @@ authorization from the copyright holder. */ +#ifndef SYNCTEX_PARSER_UTILS_H +#define SYNCTEX_PARSER_UTILS_H + /* The utilities declared here are subject to conditional implementation. * All the operating system special stuff goes here. * The problem mainly comes from file name management: path separator, encoding... */ -# define synctex_bool_t int -# define synctex_YES -1 +#include "synctex_version.h" + +typedef int synctex_bool_t; +# define synctex_YES (0==0) +# define synctex_NO (0==1) + # define synctex_ADD_QUOTES -1 # define synctex_COMPRESS -1 -# define synctex_NO 0 # define synctex_DONT_ADD_QUOTES 0 # define synctex_DONT_COMPRESS 0 @@ -85,10 +90,15 @@ extern "C" { * There is no bzero function on windows. */ void *_synctex_malloc(size_t size); +/* To balance _synctex_malloc. + * ptr might be NULL. */ +void _synctex_free(void * ptr); + /* This is used to log some informational message to the standard error stream. * On Windows, the stderr stream is not exposed and another method is used. * The return value is the number of characters printed. */ -int _synctex_error(const char * reason,...); + int _synctex_error(const char * reason,...); + int _synctex_debug(const char * reason,...); /* strip the last extension of the given string, this string is modified! * This function depends on the OS because the path separator may differ. @@ -150,3 +160,4 @@ synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name); #endif #endif +#endif /* SYNCTEX_PARSER_UTILS_H */ diff --git a/elpa/pdf-tools-20230611.239/build/server/synctex_parser_version.txt b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_version.txt new file mode 100644 index 00000000..d2ab029d --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_parser_version.txt @@ -0,0 +1 @@ +1.21 diff --git a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_local.h b/elpa/pdf-tools-20230611.239/build/server/synctex_version.h similarity index 58% rename from elpa/pdf-tools-20191031.642/build/server/synctex_parser_local.h rename to elpa/pdf-tools-20230611.239/build/server/synctex_version.h index 89fd1369..5665ccb9 100644 --- a/elpa/pdf-tools-20191031.642/build/server/synctex_parser_local.h +++ b/elpa/pdf-tools-20230611.239/build/server/synctex_version.h @@ -1,16 +1,15 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr +/* +Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr -This file is part of the SyncTeX package. +This file is part of the __SyncTeX__ package. -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 +[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) +[//]: # (Version: 1.21) -Version: 1.18 +See `synctex_parser_readme.md` for more details -See synctex_parser_readme.txt for more details +## License -License: --------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without @@ -32,14 +31,29 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written +Except as contained in this notice, the name of the copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Software without prior written authorization from the copyright holder. +## Acknowledgments: + +The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh, +and significant help from __XeTeX__ developer Jonathan Kew. + +## Nota Bene: + +If you include or use a significant part of the __SyncTeX__ package into a software, +I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted. */ -/* This local header file is for TEXLIVE, use your own header to fit your system */ -# include /* for inline && HAVE_xxx */ -/* No inlining for synctex tool in texlive. */ -# define SYNCTEX_INLINE +#ifndef __SYNCTEX_VERSION__ +# define __SYNCTEX_VERSION__ + +# define SYNCTEX_VERSION_MAJOR 1 + +# define SYNCTEX_VERSION_STRING "1.21" + +# define SYNCTEX_CLI_VERSION_STRING "1.5" + +#endif diff --git a/elpa/pdf-tools-20230611.239/build/server/test/.gitignore b/elpa/pdf-tools-20230611.239/build/server/test/.gitignore new file mode 100644 index 00000000..aaedb1f2 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/.gitignore @@ -0,0 +1 @@ +.start-vm diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/.gitignore b/elpa/pdf-tools-20230611.239/build/server/test/docker/.gitignore similarity index 63% rename from elpa/pdf-tools-20191031.642/build/server/test/docker/.gitignore rename to elpa/pdf-tools-20230611.239/build/server/test/docker/.gitignore index a6d94610..d7dc3184 100644 --- a/elpa/pdf-tools-20191031.642/build/server/test/docker/.gitignore +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/.gitignore @@ -1,2 +1,3 @@ *.Dockerfile *.build +*.container diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/lib/run-tests b/elpa/pdf-tools-20230611.239/build/server/test/docker/lib/run-tests new file mode 100755 index 00000000..31887bf2 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/lib/run-tests @@ -0,0 +1,24 @@ +#!/bin/sh + +PATH="$(dirname "$0")":$PATH + +run_tests_exit_success() +{ + echo "===============================" + echo " Elisp Tests succeeded. :O) " + echo "===============================" + exit 0 +} + +set -e +# Check that install completes successfully +yes-or-enter | ./server/autobuild -i /bin +# Check that re-install skips package installation +yes-or-enter | ./server/autobuild -i /usr/bin | \ + grep -q "Skipping package installation (already installed)" +# Check that lisp tests run correctly, if emacs is installed and available on PATH +echo +if which emacs > /dev/null 2> /dev/null; then + echo "Emacs found installed! Running elisp tests" + make test && run_tests_exit_success +fi diff --git a/elpa/pdf-tools-20191031.642/build/server/test/docker/lib/yes-or-enter b/elpa/pdf-tools-20230611.239/build/server/test/docker/lib/yes-or-enter similarity index 100% rename from elpa/pdf-tools-20191031.642/build/server/test/docker/lib/yes-or-enter rename to elpa/pdf-tools-20230611.239/build/server/test/docker/lib/yes-or-enter diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/Dockerfile.common.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/Dockerfile.common.in new file mode 100644 index 00000000..142f0620 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/Dockerfile.common.in @@ -0,0 +1,4 @@ +COPY . /pdf-tools +WORKDIR /pdf-tools +RUN make -s distclean || true +CMD ["sh", "./server/test/docker/lib/run-tests"] diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/arch.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/arch.Dockerfile.in.FAILING new file mode 100644 index 00000000..a85762b5 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/arch.Dockerfile.in.FAILING @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM archlinux:latest +RUN pacman -Syu --noconfirm --noprogressbar +# @TODO: The official Archlinux image does not seem to have any form of shell. Marking this as FAILING. diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/centos.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/centos.Dockerfile.in.FAILING new file mode 100644 index 00000000..1da2ab83 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/centos.Dockerfile.in.FAILING @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +FROM centos:centos7 +RUN sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-* +RUN sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-* +RUN yum update -y +# @TODO: Since CentOS is no more, do I even want to try and fix this? diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-10.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-10.Dockerfile.in new file mode 100644 index 00000000..a2ad6bb2 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-10.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 10 is known as buster +FROM debian:10 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-11.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-11.Dockerfile.in new file mode 100644 index 00000000..dae6b6c2 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-11.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 11 is known as bullseye +FROM debian:11 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-9.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-9.Dockerfile.in new file mode 100644 index 00000000..b558ade5 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/debian-9.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 9 is known as stretch +FROM debian:9 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-26.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-26.Dockerfile.in new file mode 100644 index 00000000..088a991f --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-26.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:26-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-27.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-27.Dockerfile.in new file mode 100644 index 00000000..50cd8209 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-27.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:27-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-28.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-28.Dockerfile.in new file mode 100644 index 00000000..c6895ac2 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-28.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:28-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-29.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-29.Dockerfile.in new file mode 100644 index 00000000..edbf7647 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/emacs-29.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:master-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-34.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-34.Dockerfile.in new file mode 100644 index 00000000..dbb736e1 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-34.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:34 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-35.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-35.Dockerfile.in new file mode 100644 index 00000000..915cac41 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-35.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:35 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-36.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-36.Dockerfile.in new file mode 100644 index 00000000..c36a716d --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/fedora-36.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:36 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/freebsd.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/freebsd.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING new file mode 100644 index 00000000..7e1d5208 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +FROM gentoo/stage3 +RUN emerge --sync +# IF you see this error, just ignore it: !!! It seems /run is not mounted. Process management may malfunction. +# Note that gentoo takes a **long** time to build and run, that's okay. +# @TODO: Currently, running this errors out because it cannot find glib-2.0, needs fixing. diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/macos.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/macos.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/msys2.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/msys2.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/nixos.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/nixos.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/openbsd.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/openbsd.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/opensuse.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/opensuse.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-18.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-18.Dockerfile.in new file mode 100644 index 00000000..b139c84d --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-18.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:bionic +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-20.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-20.Dockerfile.in new file mode 100644 index 00000000..f650856c --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-20.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:focal +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-22.Dockerfile.in b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-22.Dockerfile.in new file mode 100644 index 00000000..2ac71271 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/ubuntu-22.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:jammy +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/void.Dockerfile.in.FAILING b/elpa/pdf-tools-20230611.239/build/server/test/docker/templates/void.Dockerfile.in.FAILING new file mode 100644 index 00000000..e69de29b diff --git a/elpa/pdf-tools-20191031.642/pdf-annot.el b/elpa/pdf-tools-20230611.239/pdf-annot.el similarity index 85% rename from elpa/pdf-tools-20191031.642/pdf-annot.el rename to elpa/pdf-tools-20230611.239/pdf-annot.el index efde0ecc..344a5c0d 100644 --- a/elpa/pdf-tools-20191031.642/pdf-annot.el +++ b/elpa/pdf-tools-20230611.239/pdf-annot.el @@ -37,6 +37,8 @@ ;; * Customizations ;; * ================================================================== * +;;; Code: + (defgroup pdf-annot nil "Annotation support for PDF documents." :group 'pdf-tools) @@ -48,22 +50,19 @@ The functions on this hook will be called when some annotation is activated, usually by a mouse-click. Each one is called with the annotation as a single argument and it should return a non-nil value if it has `handled' it. If no such function exists, the -default handler `pdf-annot-default-handler' will be +default handler `pdf-annot-default-activate-handler' will be called. This hook is meant to allow for custom annotations. FIXME: Implement and describe basic org example." - :group 'pdf-annot :type 'hook) (defcustom pdf-annot-default-text-annotation-properties nil "Alist of initial properties for new text annotations." - :group 'pdf-annot :type '(alist :key-type symbol :value-type sexp)) (defcustom pdf-annot-default-markup-annotation-properties nil "Alist of initial properties for new markup annotations." - :group 'pdf-annot :type '(alist :key-type symbol :value-type sexp)) (make-obsolete-variable 'pdf-annot-default-text-annotation-properties @@ -107,7 +106,6 @@ would use a green color for highlight and a red one for other annotations. Additionally the label for all annotations is set to \"Joe\"." - :group 'pdf-annot :type (let* ((label '(cons :tag "Label" (const label) string)) (contents '(cons :tag "Contents" (const contents) string)) (color '(cons :tag "Color" (const color) color)) @@ -147,7 +145,6 @@ will be used. If all of them return nil, the default function `pdf-annot-print-annotation-default' is used." - :group 'pdf-annot :type 'hook) (defcustom pdf-annot-latex-string-predicate @@ -157,17 +154,14 @@ If all of them return nil, the default function It receives a string and should return non-nil, if string is a LaTeX fragment." - :group 'pdf-annot :type 'function) (defcustom pdf-annot-latex-header (concat org-format-latex-header "\n\\setlength{\\textwidth}{12cm}") "Header used when latex compiling annotations. - -The default value is `org-format-latex-header' + \ +The default value is `org-format-latex-header' + \"\\n\\\\setlength{\\\\textwidth}{12cm}\"." - :group 'pdf-annot :type 'string) (defcustom pdf-annot-tweak-tooltips t @@ -180,17 +174,14 @@ order to display text properties; `tooltip-hide-delay' is set to infinity, in order to not being annoyed while reading the annotations." - :group 'pdf-annot :type 'boolean) (defcustom pdf-annot-activate-created-annotations nil "Whether to activate (i.e. edit) created annotations." - :group 'pdf-annot :type 'boolean) (defcustom pdf-annot-attachment-display-buffer-action nil "The display action used when displaying attachments." - :group 'pdf-annot :type display-buffer--action-custom-type) (defconst pdf-annot-annotation-types @@ -205,7 +196,6 @@ annoyed while reading the annotations." (list 'text 'file 'squiggly 'highlight 'underline 'strike-out) (list 'text 'file)) "A list of annotation types displayed in the list buffer." - :group 'pdf-annot :type `(set ,@(mapcar (lambda (type) (list 'const type)) pdf-annot-annotation-types))) @@ -224,7 +214,7 @@ annoyed while reading the annotations." A function on this hook should accept one argument: A CLOSURE containing inserted, changed and deleted annotations. -It may access theses annotations by calling CLOSURE with one of +It may access these annotations by calling CLOSURE with one of these arguments: `:inserted' The list of recently added annotations. @@ -233,9 +223,9 @@ these arguments: `:changed' The list of recently changed annotations. -`t' The union of recently added, deleted or changed annotations. +t The union of recently added, deleted or changed annotations. -`nil' Just returns nil. +nil Just returns nil. Any other argument signals an error.") @@ -258,8 +248,10 @@ no effect on the rendering.") "A list of standard icon properties for text annotations.") (defvar pdf-annot-inhibit-modification-hooks nil - "Non-nil, if running `pdf-annot-modified-functions' should be - inhibited after some annotation has changed.") + "Controls the behavior of `pdf-annot-modified-functions'. + +If non-nil, `pdf-annot-modified-functions' are not run on any +annotation change.") (defvar-local pdf-annot-delayed-modified-annotations nil "A plist of not yet propagated modifications. @@ -294,25 +286,23 @@ current buffer, because that won't run the hooks properly." "The prefix to use for `pdf-annot-minor-mode-map'. Setting this after the package was loaded has no effect." - :group 'pdf-annot :type 'key-sequence) (defvar pdf-annot-minor-mode-map (let ((kmap (make-sparse-keymap)) (smap (make-sparse-keymap))) (define-key kmap pdf-annot-minor-mode-map-prefix smap) - (define-key smap "l" 'pdf-annot-list-annotations) - ;; (define-key smap "d" 'pdf-annot-toggle-display-annotations) - (define-key smap "a" 'pdf-annot-attachment-dired) + (define-key smap "l" #'pdf-annot-list-annotations) + (define-key smap "a" #'pdf-annot-attachment-dired) (when (pdf-info-writable-annotations-p) - (define-key smap "D" 'pdf-annot-delete) - (define-key smap "t" 'pdf-annot-add-text-annotation) + (define-key smap "D" #'pdf-annot-delete) + (define-key smap "t" #'pdf-annot-add-text-annotation) (when (pdf-info-markup-annotations-p) - (define-key smap "m" 'pdf-annot-add-markup-annotation) - (define-key smap "s" 'pdf-annot-add-squiggly-markup-annotation) - (define-key smap "u" 'pdf-annot-add-underline-markup-annotation) - (define-key smap "o" 'pdf-annot-add-strikeout-markup-annotation) - (define-key smap "h" 'pdf-annot-add-highlight-markup-annotation))) + (define-key smap "m" #'pdf-annot-add-markup-annotation) + (define-key smap "s" #'pdf-annot-add-squiggly-markup-annotation) + (define-key smap "u" #'pdf-annot-add-underline-markup-annotation) + (define-key smap "o" #'pdf-annot-add-strikeout-markup-annotation) + (define-key smap "h" #'pdf-annot-add-highlight-markup-annotation))) kmap) "Keymap used for `pdf-annot-minor-mode'.") @@ -323,7 +313,7 @@ Setting this after the package was loaded has no effect." "Support for PDF Annotations. \\{pdf-annot-minor-mode-map}" - nil nil nil + :group 'pdf-annot (cond (pdf-annot-minor-mode (when pdf-annot-tweak-tooltips @@ -332,14 +322,14 @@ Setting this after the package was loaded has no effect." (setq tooltip-hide-delay 3600)) (pdf-view-add-hotspot-function 'pdf-annot-hotspot-function 9) (add-hook 'pdf-info-close-document-hook - 'pdf-annot-attachment-delete-base-directory nil t) + #'pdf-annot-attachment-delete-base-directory nil t) (when (featurep 'savehist) (add-to-list 'savehist-minibuffer-history-variables 'pdf-annot-color-history))) (t (pdf-view-remove-hotspot-function 'pdf-annot-hotspot-function) (remove-hook 'pdf-info-close-document-hook - 'pdf-annot-attachment-delete-base-directory t))) + #'pdf-annot-attachment-delete-base-directory t))) (pdf-view-redisplay t)) (defun pdf-annot-create-context-menu (a) @@ -386,41 +376,43 @@ Setting this after the package was loaded has no effect." menu)) (defun pdf-annot-create-color-submenu (a) + "Show the user a color menu for their annotation A." (let ((menu (make-sparse-keymap))) (define-key menu [color-chooser] - `(menu-item "Choose ..." - ,(lambda () - (interactive) - (list-colors-display - nil "*Choose annotation color*" - ;; list-colors-print does not like closures. - (let ((callback (make-symbol "xcallback"))) - (fset callback - (lambda (color) - (pdf-annot-put a 'color color) - (setq pdf-annot-color-history - (cons color - (remove color pdf-annot-color-history))) - (quit-window t))) - (list 'function callback)))))) + `(menu-item "Choose ..." + ,(lambda () + (interactive) + (list-colors-display + nil "*Choose annotation color*" + ;; list-colors-print does not like closures. + (let ((callback (make-symbol "xcallback"))) + (fset callback + (lambda (color) + (pdf-annot-put a 'color color) + (setq pdf-annot-color-history + (cons color + (remove color pdf-annot-color-history))) + (quit-window t))) + (list 'function callback)))))) (dolist (color (butlast (reverse pdf-annot-color-history) (max 0 (- (length pdf-annot-color-history) 12)))) (define-key menu (vector (intern (format "color-%s" color))) - `(menu-item ,color - ,(lambda nil - (interactive) - (pdf-annot-put a 'color color))))) + `(menu-item ,color + ,(lambda nil + (interactive) + (pdf-annot-put a 'color color))))) menu)) (defun pdf-annot-create-icon-submenu (a) + "Show the user an icon menu for the annotation A." (let ((menu (make-sparse-keymap))) (dolist (icon (reverse pdf-annot-standard-text-icons)) (define-key menu (vector (intern (format "icon-%s" icon))) - `(menu-item ,icon - ,(lambda nil - (interactive) - (pdf-annot-put a 'icon icon))))) + `(menu-item ,icon + ,(lambda nil + (interactive) + (pdf-annot-put a 'icon icon))))) menu)) ;; * ================================================================== * @@ -460,6 +452,10 @@ current buffer." result))) (defun pdf-annot-getannot (id &optional buffer) + "Return the annotation object for annotation ID. + +Optionally take the BUFFER name of the PDF buffer. When none is +provided, the `current-buffer' is picked up." (pdf-annot-create (pdf-info-getannot id buffer) buffer)) @@ -528,19 +524,19 @@ the variable is nil and this function is called again." (union (cl-union (cl-union changed inserted :test 'pdf-annot-equal) deleted :test 'pdf-annot-equal)) (closure (lambda (arg) - (cl-ecase arg - (:inserted (copy-sequence inserted)) - (:changed (copy-sequence changed)) - (:deleted (copy-sequence deleted)) - (t (copy-sequence union)) - (nil nil)))) + (when arg + (cl-case arg + (:inserted (copy-sequence inserted)) + (:changed (copy-sequence changed)) + (:deleted (copy-sequence deleted)) + (t (copy-sequence union)))))) (pages (mapcar (lambda (a) (pdf-annot-get a 'page)) union))) (when union (unwind-protect (run-hook-with-args 'pdf-annot-modified-functions closure) (setq pdf-annot-delayed-modified-annotations nil) - (apply 'pdf-view-redisplay-pages pages)))))) + (apply #'pdf-view-redisplay-pages pages)))))) (defun pdf-annot-equal (a1 a2) "Return non-nil, if annotations A1 and A2 are equal. @@ -593,14 +589,19 @@ This function always returns nil." nil) (defun pdf-annot-text-annotation-p (a) + "Return non-nil if annotation A is of type text." (eq 'text (pdf-annot-get a 'type))) (defun pdf-annot-markup-annotation-p (a) + "Return non-nil if annotation A is a known markup type. + +Annotation types are defined in `pdf-annot-markup-annotation-types'." (not (null (memq (pdf-annot-get a 'type) pdf-annot-markup-annotation-types)))) (defun pdf-annot-property-modifiable-p (a property) + "Return non-nil if PROPERTY for annotation A is editable." (or (memq property '(edges color flags contents)) (and (pdf-annot-markup-annotation-p a) (memq property '(label opacity popup popup-is-open))) @@ -608,12 +609,18 @@ This function always returns nil." (memq property '(icon is-open))))) (defun pdf-annot-activate-annotation (a) + "Run handler functions on A to activate the annotation. + +Activation functions are defined in `pdf-annot-activate-handler-functions'." (or (run-hook-with-args-until-success 'pdf-annot-activate-handler-functions a) (pdf-annot-default-activate-handler a))) (defun pdf-annot-default-activate-handler (a) + "The default activation function to run on annotation A. + +Activation functions are defined in `pdf-annot-activate-handler-functions'." (cond ((pdf-annot-has-attachment-p a) (pdf-annot-pop-to-attachment a)) @@ -678,7 +685,7 @@ The DO-SAVE argument is given to (defun pdf-annot-attachment-save (attachment &optional regenerate-p) - "Save ATTACHMENT's data to a unique filename and return it's name. + "Save ATTACHMENT's data to a unique filename and return its name. If REGENERATE-P is non-nil, copy attachment's file even if the copy already exists. @@ -712,13 +719,13 @@ Signals an error, if A has no data attached." (delete-file tmpfile)))))) (defun pdf-annot-attachment-dired (&optional regenerate-p) - "List all attachments in a dired buffer. + "List all attachments in a Dired buffer. If REGENERATE-P is non-nil, create attachment's files even if they already exist. Interactively REGENERATE-P is non-nil if a prefix argument was given. -Return the dired buffer." +Return the Dired buffer." (interactive (list current-prefix-arg)) (let ((attachments (pdf-info-getattachments t))) (unwind-protect @@ -850,7 +857,7 @@ Return nil, if no annotation was found." (setq window (posn-window pos) pos (posn-object-x-y pos))) (save-selected-window - (when window (select-window window)) + (when window (select-window window 'norecord)) (let* ((annots (pdf-annot-getannots (pdf-view-current-page))) (size (pdf-view-image-size)) (rx (/ (car pos) (float (car size)))) @@ -906,14 +913,16 @@ i.e. a non mouse-movement event is read." (defun pdf-annot-hotspot-function (page size) "Create image hotspots for page PAGE of size SIZE." - (apply 'nconc (mapcar (lambda (a) - (unless (eq (pdf-annot-get a 'type) - 'link) - (pdf-annot-create-hotspots a size))) - (pdf-annot-getannots page)))) + (apply #'nconc (mapcar (lambda (a) + (unless (eq (pdf-annot-get a 'type) + 'link) + (pdf-annot-create-hotspots a size))) + (pdf-annot-getannots page)))) (defun pdf-annot-create-hotspots (a size) - "Return a list of image hotspots for annotation A." + "Return a list of image hotspots for annotation A. + +SIZE is a cons (SX . SY), by which edges are scaled." (let ((id (pdf-annot-get-id a)) (edges (pdf-util-scale (pdf-annot-get-display-edges a) @@ -935,6 +944,11 @@ i.e. a non mouse-movement event is read." ;; FIXME: Define a keymap as a template for this. Much cleaner. (defun pdf-annot-create-hotspot-binding (id moveable-p annotation) + "Create a local keymap for interacting with ANNOTATION using the mouse. + +ID is the identifier for the ANNOTATION, as returned +`pdf-annot-get-id'. MOVEABLE-P indicates whether the annotation +is moveable." ;; Activating (local-set-key (vector id 'mouse-1) @@ -968,7 +982,7 @@ If HIGHLIGHT-P is non-nil, visually distinguish annotation A from other annotations." (save-selected-window - (when window (select-window window)) + (when window (select-window window 'norecord)) (pdf-util-assert-pdf-window) (let ((page (pdf-annot-get a 'page)) (size (pdf-view-image-size))) @@ -982,7 +996,8 @@ other annotations." page (car size) `("white" "steel blue" 0.35 ,@edges)) :map (pdf-view-apply-hotspot-functions - window page size)))) + window page size) + :width (car size)))) (pdf-util-scroll-to-edges (pdf-util-scale-relative-to-pixel (car edges))))))) @@ -998,7 +1013,7 @@ other annotations." ;; * ================================================================== * (defun pdf-annot-add-annotation (type edges &optional property-alist page) - "Creates and adds a new annotation of type TYPE to the document. + "Create and add a new annotation of type TYPE to the document. TYPE determines the kind of annotation to add and maybe one of `text', `squiggly', `underline', `strike-out' or `highlight'. @@ -1037,19 +1052,24 @@ Return the new annotation." (when (and (eq type 'text) (> (length edges) 1)) (error "Edges argument should be a single edge-list for text annotations")) - (let* ((a (apply 'pdf-info-addannot + (let* ((selection-style pdf-view-selection-style) + (non-markup (pcase type + ('text t) + ('highlight pdf-view--have-rectangle-region))) + (a (apply #'pdf-info-addannot page - (if (eq type 'text) + (if non-markup (car edges) (apply #'pdf-util-edges-union (apply #'append (mapcar (lambda (e) - (pdf-info-getselection page e)) + (pdf-info-getselection page e selection-style)) edges)))) type + selection-style nil - (if (not (eq type 'text)) edges))) + (unless non-markup edges))) (id (pdf-annot-get-id a))) (when property-alist (condition-case err @@ -1121,6 +1141,9 @@ Return the new annotation." `((color . ,(car pdf-annot-color-history)))))))) (defun pdf-annot-mouse-add-text-annotation (ev) + "Add a text annotation using the mouse. + +EV describes the captured mouse event." (interactive "@e") (pdf-annot-add-text-annotation (if (eq (car-safe ev) @@ -1174,7 +1197,9 @@ Return the new annotation." &optional color property-alist) "Add a new squiggly annotation in the selected window. -See also `pdf-annot-add-markup-annotation'." +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." (interactive (list (pdf-view-active-region t))) (pdf-annot-add-markup-annotation list-of-edges 'squiggly color property-alist)) @@ -1182,7 +1207,9 @@ See also `pdf-annot-add-markup-annotation'." &optional color property-alist) "Add a new underline annotation in the selected window. -See also `pdf-annot-add-markup-annotation'." +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." (interactive (list (pdf-view-active-region t))) (pdf-annot-add-markup-annotation list-of-edges 'underline color property-alist)) @@ -1190,7 +1217,9 @@ See also `pdf-annot-add-markup-annotation'." &optional color property-alist) "Add a new strike-out annotation in the selected window. -See also `pdf-annot-add-markup-annotation'." +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." (interactive (list (pdf-view-active-region t))) (pdf-annot-add-markup-annotation list-of-edges 'strike-out color property-alist)) @@ -1198,7 +1227,9 @@ See also `pdf-annot-add-markup-annotation'." &optional color property-alist) "Add a new highlight annotation in the selected window. -See also `pdf-annot-add-markup-annotation'." +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." (interactive (list (pdf-view-active-region t))) (pdf-annot-add-markup-annotation list-of-edges 'highlight color property-alist)) @@ -1236,7 +1267,7 @@ Suppresses successive duplicate entries of keys after the first occurrence in ALISTS." (let (merged) - (dolist (elt (apply 'append alists)) + (dolist (elt (apply #'append alists)) (unless (assq (car elt) merged) (push elt merged))) (nreverse merged))) @@ -1300,7 +1331,7 @@ property." (t (format "%s" (mapconcat - 'identity + #'identity (mapcar (lambda (property) (pdf-annot-print-property @@ -1340,8 +1371,12 @@ by a header." "pdf-annot-print-annotation-latex%s%s%s" page header contents))) (data (pdf-cache-lookup-image page 0 nil hash)) - (org-format-latex-header - pdf-annot-latex-header) + ;; pdf-tools can only work with png files, so this + ;; binding ensures that pdf-tools can print the + ;; latex-preview regardless of the user + ;; configuration. + (org-preview-latex-default-process 'dvipng) + (org-format-latex-header pdf-annot-latex-header) (temporary-file-directory (pdf-util-expand-file-name "pdf-annot-print-annotation-latex"))) (unless (file-directory-p temporary-file-directory) @@ -1389,7 +1424,7 @@ by a header." (let ((mode (if (funcall pdf-annot-latex-string-predicate (pdf-annot-get a 'contents)) 'latex-mode - 'text-mode))) + 'org-mode))) (unless (derived-mode-p mode) (funcall mode)))) "A function for setting up, e.g. the major-mode, of the edit buffer. @@ -1399,8 +1434,7 @@ is about to be edited in this buffer. The default value turns on `latex-mode' if `pdf-annot-latex-string-predicate' returns non-nil on the -annotation's contents and otherwise `text-mode'. " - :group 'pdf-annot +annotation's contents and otherwise `org-mode'." :type 'function) (defcustom pdf-annot-edit-contents-display-buffer-action @@ -1409,28 +1443,35 @@ annotation's contents and otherwise `text-mode'. " (inhibit-same-window . t) (window-height . 0.25)) "Display action when showing the edit buffer." - :group 'pdf-annot :type display-buffer--action-custom-type) (defvar pdf-annot-edit-contents-minor-mode-map (let ((kmap (make-sparse-keymap))) (set-keymap-parent kmap text-mode-map) - (define-key kmap (kbd "C-c C-c") 'pdf-annot-edit-contents-commit) - (define-key kmap (kbd "C-c C-q") 'pdf-annot-edit-contents-abort) + (define-key kmap (kbd "C-c C-c") #'pdf-annot-edit-contents-commit) + (define-key kmap (kbd "C-c C-q") #'pdf-annot-edit-contents-abort) + (define-key kmap (kbd "C-c C-k") #'pdf-annot-edit-contents-abort) kmap)) (define-minor-mode pdf-annot-edit-contents-minor-mode "Active when editing the contents of annotations." - nil nil nil + :group 'pdf-annot (when pdf-annot-edit-contents-minor-mode - (message "%s" - (substitute-command-keys - "Press \\[pdf-annot-edit-contents-commit] to commit your changes, \\[pdf-annot-edit-contents-abort] to abandon them.")))) + (setq-local header-line-format + (substitute-command-keys "\ +Press \\[pdf-annot-edit-contents-commit] to commit your changes, \\[pdf-annot-edit-contents-abort] to abandon them.")))) (put 'pdf-annot-edit-contents-minor-mode 'permanent-local t) -;; FIXME: Document pdf-annot-edit-* functions below. (defun pdf-annot-edit-contents-finalize (do-save &optional do-kill) + "Finalize edit-operations on an Annotation. + +If DO-SAVE is t, save the changes to annotation content without +asking. If DO-SAVE is `ask', check with the user if contents +should be saved. + +If DO-KILL is t, kill all windows displaying the annotation +contents. Else just bury the buffers." (when (buffer-modified-p) (cond ((eq do-save 'ask) @@ -1445,6 +1486,7 @@ annotation's contents and otherwise `text-mode'. " (quit-window do-kill win))) (defun pdf-annot-edit-contents-save-annotation () + "Internal function to save the contents of the annotation under editing." (when pdf-annot-edit-contents--annotation (pdf-annot-put pdf-annot-edit-contents--annotation 'contents @@ -1452,14 +1494,19 @@ annotation's contents and otherwise `text-mode'. " (set-buffer-modified-p nil))) (defun pdf-annot-edit-contents-commit () + "Save the change made to the current annotation." (interactive) (pdf-annot-edit-contents-finalize t)) (defun pdf-annot-edit-contents-abort () + "Abort the change made to the current annotation." (interactive) (pdf-annot-edit-contents-finalize nil t)) (defun pdf-annot-edit-contents-noselect (a) + "Internal function to setup all prerequisites for editing annotation A. + +At any given point of time, only one annotation can be in edit mode." (with-current-buffer (pdf-annot-get-buffer a) (when (and (buffer-live-p pdf-annot-edit-contents--buffer) (not (eq a pdf-annot-edit-contents--annotation))) @@ -1467,11 +1514,8 @@ annotation's contents and otherwise `text-mode'. " (pdf-annot-edit-contents-finalize 'ask))) (unless (buffer-live-p pdf-annot-edit-contents--buffer) (setq pdf-annot-edit-contents--buffer - (with-current-buffer (get-buffer-create - (format "*Edit Annotation %s*" - (buffer-name))) - (pdf-annot-edit-contents-minor-mode 1) - (current-buffer)))) + (get-buffer-create + (format "*Edit Annotation %s*" (buffer-name))))) (with-current-buffer pdf-annot-edit-contents--buffer (let ((inhibit-read-only t)) (erase-buffer) @@ -1479,15 +1523,18 @@ annotation's contents and otherwise `text-mode'. " (set-buffer-modified-p nil)) (setq pdf-annot-edit-contents--annotation a) (funcall pdf-annot-edit-contents-setup-function a) + (pdf-annot-edit-contents-minor-mode 1) (current-buffer)))) (defun pdf-annot-edit-contents (a) + "Edit the contents of annotation A." (select-window (display-buffer (pdf-annot-edit-contents-noselect a) pdf-annot-edit-contents-display-buffer-action))) (defun pdf-annot-edit-contents-mouse (ev) + "Edit the contents of the annotation described by mouse event EV." (interactive "@e") (let* ((pos (posn-object-x-y (event-start ev))) (a (and pos (pdf-annot-at-position pos)))) @@ -1506,7 +1553,6 @@ annotation's contents and otherwise `text-mode'. " display-buffer-pop-up-window) (inhibit-same-window . t)) "Display action used when displaying the list buffer." - :group 'pdf-annot :type display-buffer--action-custom-type) (defcustom pdf-annot-list-format @@ -1526,12 +1572,10 @@ Currently supported properties are page, type, label, date and contents." (type (integer :value 10 :tag "Column Width" )) (label (integer :value 24 :tag "Column Width")) (date (integer :value 24 :tag "Column Width")) - (contents (integer :value 56 :tag "Column Width"))) - :group 'pdf-annot) + (contents (integer :value 56 :tag "Column Width")))) -(defcustom pdf-annot-list-highlight-type nil +(defcustom pdf-annot-list-highlight-type t "Whether to highlight \"Type\" column annotation list with annotation color." - :group 'pdf-annot :type 'boolean) (defvar-local pdf-annot-list-buffer nil) @@ -1540,8 +1584,8 @@ Currently supported properties are page, type, label, date and contents." (defvar pdf-annot-list-mode-map (let ((km (make-sparse-keymap))) - (define-key km (kbd "C-c C-f") 'pdf-annot-list-follow-minor-mode) - (define-key km (kbd "SPC") 'pdf-annot-list-display-annotation-from-id) + (define-key km (kbd "C-c C-f") #'pdf-annot-list-follow-minor-mode) + (define-key km (kbd "SPC") #'pdf-annot-list-display-annotation-from-id) km)) (defun pdf-annot-property-completions (property) @@ -1573,14 +1617,19 @@ belong to the same page and A1 is displayed above/left of A2." (<= e1-left e2-left))))))))) (defun pdf-annot-list-entries () + "Return all the annotations of this PDF buffer as a `tabulated-list'." (unless (buffer-live-p pdf-annot-list-document-buffer) (error "No PDF document associated with this buffer")) - (mapcar 'pdf-annot-list-create-entry + (mapcar #'pdf-annot-list-create-entry (sort (pdf-annot-getannots nil pdf-annot-list-listed-types pdf-annot-list-document-buffer) - 'pdf-annot-compare-annotations))) + #'pdf-annot-compare-annotations))) (defun pdf-annot--make-entry-formatter (a) + "Return a formatter function for annotation A. + +A formatter function takes a format cons-cell and returns +pretty-printed output." (lambda (fmt) (let ((entry-type (car fmt)) (entry-width (cdr fmt)) @@ -1593,7 +1642,9 @@ belong to the same page and A1 is displayed above/left of A2." (lambda (str) (replace-regexp-in-string "\n" " " str t t)))) (cl-ecase entry-type - (date (pdf-annot-print-property a 'modified)) + (date (propertize (pdf-annot-print-property a 'modified) + 'date + (pdf-annot-get a 'modified))) (page (pdf-annot-print-property a 'page)) (label (funcall prune-newlines (pdf-annot-print-property a 'label))) @@ -1605,11 +1656,11 @@ belong to the same page and A1 is displayed above/left of A2." (type (let ((color (pdf-annot-get a 'color)) (type (pdf-annot-print-property a 'type))) - (if pdf-annot-list-highlight-type + (if (and pdf-annot-list-highlight-type color) (propertize type 'face `(:background ,color - :foreground ,(funcall contrasty-color color))) + :foreground ,(funcall contrasty-color color))) type))))))) (defun pdf-annot-list-create-entry (a) @@ -1620,19 +1671,38 @@ belong to the same page and A1 is displayed above/left of A2." pdf-annot-list-format)))) (define-derived-mode pdf-annot-list-mode tablist-mode "Annots" + ;; @TODO: Remove the hard-coded index values here, and figure out a + ;; way to properly link this to the index values of + ;; `pdf-annot-list-format'. + + ;; @TODO: Add tests for annotation formatting and display (let* ((page-sorter (lambda (a b) (< (string-to-number (aref (cadr a) 0)) (string-to-number (aref (cadr b) 0))))) + (date-sorter + (lambda (a b) + (time-less-p (get-text-property 0 'date (aref (cadr a) 3)) + (get-text-property 0 'date (aref (cadr b) 3))))) (format-generator (lambda (format) (let ((field (car format)) (width (cdr format))) (cl-case field - (page `("Pg." 3 ,page-sorter :read-only t :right-alight t)) + (page `("Pg." + ,width + ,page-sorter + :read-only t + :right-align t)) + (date `("Date" + ,width + ,date-sorter + :read-only t)) (t (list (capitalize (symbol-name field)) - width t :read-only t))))))) + width + t + :read-only t))))))) (setq tabulated-list-entries 'pdf-annot-list-entries tabulated-list-format (vconcat (mapcar @@ -1647,24 +1717,27 @@ belong to the same page and A1 is displayed above/left of A2." (tabulated-list-init-header)) (defun pdf-annot-list-annotations () - "List annotations in a dired like buffer. + "List annotations in a Dired like buffer. \\{pdf-annot-list-mode-map}" (interactive) (pdf-util-assert-pdf-buffer) - (let ((buffer (current-buffer))) - (with-current-buffer (get-buffer-create - (format "*%s's annots*" - (file-name-sans-extension - (buffer-name)))) + (let* ((buffer (current-buffer)) + (name (format "*%s's annots*" + (file-name-sans-extension + (buffer-name)))) + (annots-existed (and (get-buffer name) + pdf-annot-list-buffer))) + (with-current-buffer (get-buffer-create name) (delay-mode-hooks (unless (derived-mode-p 'pdf-annot-list-mode) (pdf-annot-list-mode)) (setq pdf-annot-list-document-buffer buffer) - (tabulated-list-print) + (unless annots-existed + (tabulated-list-print)) (setq tablist-context-window-function (lambda (id) (pdf-annot-list-context-function id buffer)) - tablist-operations-function 'pdf-annot-list-operation-function) + tablist-operations-function #'pdf-annot-list-operation-function) (let ((list-buffer (current-buffer))) (with-current-buffer buffer (setq pdf-annot-list-buffer list-buffer)))) @@ -1675,11 +1748,14 @@ belong to the same page and A1 is displayed above/left of A2." (tablist-move-to-major-column) (tablist-display-context-window)) (add-hook 'pdf-info-close-document-hook - 'pdf-annot-list-update nil t) + #'pdf-annot-list-update nil t) (add-hook 'pdf-annot-modified-functions - 'pdf-annot-list-update nil t))) + #'pdf-annot-list-update nil t))) (defun pdf-annot-list-goto-annotation (a) + "List all the annotations in the current buffer. + +Goto the annotation A in the list." (with-current-buffer (pdf-annot-get-buffer a) (unless (and (buffer-live-p pdf-annot-list-buffer) (get-buffer-window pdf-annot-list-buffer)) @@ -1698,6 +1774,9 @@ belong to the same page and A1 is displayed above/left of A2." (defun pdf-annot-list-update (&optional _fn) + "Update the list of annotations on any change. + +This is an internal function which runs as a hook in various situations." (when (buffer-live-p pdf-annot-list-buffer) (with-current-buffer pdf-annot-list-buffer (unless tablist-edit-column-minor-mode @@ -1705,6 +1784,10 @@ belong to the same page and A1 is displayed above/left of A2." (tablist-context-window-update)))) (defun pdf-annot-list-context-function (id buffer) + "Show the contents of an Annotation. + +For an annotation identified by ID, belonging to PDF in BUFFER, +get the contents and display them on demand." (with-current-buffer (get-buffer-create "*Contents*") (set-window-buffer nil (current-buffer)) (let ((inhibit-read-only t)) @@ -1717,6 +1800,12 @@ belong to the same page and A1 is displayed above/left of A2." (read-only-mode 1)))) (defun pdf-annot-list-operation-function (op &rest args) + "Define bulk operations in Annotation list buffer. + +OP is the operation that the user wants to execute. Supported +operations are `delete' and `find-entry'. + +ARGS contain the annotation-ids to operate on." (cl-ecase op (supported-operations '(delete find-entry)) (delete @@ -1725,7 +1814,7 @@ belong to the same page and A1 is displayed above/left of A2." (when (buffer-live-p pdf-annot-list-document-buffer) (with-current-buffer pdf-annot-list-document-buffer (pdf-annot-with-atomic-modifications - (dolist (a (mapcar 'pdf-annot-getannot ids)) + (dolist (a (mapcar #'pdf-annot-getannot ids)) (pdf-annot-delete a))))))) (find-entry (cl-destructuring-bind (id) @@ -1752,6 +1841,10 @@ belong to the same page and A1 is displayed above/left of A2." (defvar pdf-annot-list-display-annotation--timer nil) (defun pdf-annot-list-display-annotation-from-id (id) + "Display the Annotation ID in the PDF file. + +This allows us to follow the tabulated-list of annotations and +have the PDF buffer automatically move along with us." (interactive (list (tabulated-list-get-id))) (when id (unless (buffer-live-p pdf-annot-list-document-buffer) @@ -1772,19 +1865,20 @@ belong to the same page and A1 is displayed above/left of A2." (pdf-annot-getannot id pdf-annot-list-document-buffer))))) (define-minor-mode pdf-annot-list-follow-minor-mode - "" nil nil nil + "Make the PDF follow the annotations in the list buffer." + :group 'pdf-annot (unless (derived-mode-p 'pdf-annot-list-mode) - (error "No in pdf-annot-list-mode.")) + (error "Not in pdf-annot-list-mode")) (cond (pdf-annot-list-follow-minor-mode (add-hook 'tablist-selection-changed-functions - 'pdf-annot-list-display-annotation-from-id nil t) + #'pdf-annot-list-display-annotation-from-id nil t) (let ((id (tabulated-list-get-id))) (when id (pdf-annot-list-display-annotation-from-id id)))) (t (remove-hook 'tablist-selection-changed-functions - 'pdf-annot-list-display-annotation-from-id t)))) + #'pdf-annot-list-display-annotation-from-id t)))) (provide 'pdf-annot) ;;; pdf-annot.el ends here diff --git a/elpa/pdf-tools-20191031.642/pdf-cache.el b/elpa/pdf-tools-20230611.239/pdf-cache.el similarity index 80% rename from elpa/pdf-tools-20191031.642/pdf-cache.el rename to elpa/pdf-tools-20230611.239/pdf-cache.el index 9ed72414..9c25e07d 100644 --- a/elpa/pdf-tools-20191031.642/pdf-cache.el +++ b/elpa/pdf-tools-20230611.239/pdf-cache.el @@ -23,6 +23,7 @@ ;;; Code: ;; +(require 'pdf-macs) (require 'pdf-info) (require 'pdf-util) @@ -62,15 +63,25 @@ be prefetched and their order." (defvar pdf-annot-modified-functions) (defun pdf-cache--initialize () + "Initialize the cache to store document data. + +Note: The cache is only initialized once. After that it needs to +be cleared before this function makes any changes to it. This is +an internal function and not meant to be directly used." (unless pdf-cache--data (setq pdf-cache--data (make-hash-table)) - (add-hook 'pdf-info-close-document-hook 'pdf-cache-clear-data nil t) + (add-hook 'pdf-info-close-document-hook #'pdf-cache-clear-data nil t) (add-hook 'pdf-annot-modified-functions - 'pdf-cache--clear-data-of-annotations + #'pdf-cache--clear-data-of-annotations nil t))) (defun pdf-cache--clear-data-of-annotations (fn) - (apply 'pdf-cache-clear-data-of-pages + "Clear the data cache when annotations are modified. + +FN is a closure as described in `pdf-annot-modified-functions'. + +Note: This is an internal function and not meant to be directly used." + (apply #'pdf-cache-clear-data-of-pages (mapcar (lambda (a) (cdr (assq 'page a))) (funcall fn t)))) @@ -89,7 +100,7 @@ be prefetched and their order." "Get value of KEY in the cache of PAGE. Returns a cons \(HIT . VALUE\), where HIT is non-nil if KEY was -stored previously for PAGE and VALUE it's value. Otherwise HIT +stored previously for PAGE and VALUE its value. Otherwise HIT is nil and VALUE undefined." (pdf-cache--initialize) (let ((elt (assq key (gethash page pdf-cache--data)))) @@ -98,6 +109,7 @@ is nil and VALUE undefined." (cons nil nil)))) (defun pdf-cache--data-clear (key &optional page) + "Remove KEY from the cache of PAGE." (pdf-cache--initialize) (puthash page (assq-delete-all key (gethash page pdf-cache--data)) @@ -105,11 +117,13 @@ is nil and VALUE undefined." nil) (defun pdf-cache-clear-data-of-pages (&rest pages) + "Remove all PAGES from the cache." (when pdf-cache--data (dolist (page pages) (remhash page pdf-cache--data)))) (defun pdf-cache-clear-data () + "Remove the entire cache." (interactive) (when pdf-cache--data (clrhash pdf-cache--data))) @@ -130,7 +144,7 @@ Both args are unevaluated." (ifn (intern (format "pdf-info-%s" command))) (doc (format "Cached version of `pdf-info-%s', which see. -Make sure, not to modify it's return value." command))) +Make sure, not to modify its return value." command))) `(defun ,fn ,args ,doc (let ((hit-value (pdf-cache--data-get ',command ,(if page-arg-p 'page)))) @@ -161,19 +175,30 @@ Make sure, not to modify it's return value." command))) (defvar-local pdf-cache--image-cache nil) (defmacro pdf-cache--make-image (page width data hash) + "Make the image that we store in the image cache. + +An image is a tuple of PAGE WIDTH DATA HASH." `(list ,page ,width ,data ,hash)) -(defmacro pdf-cache--image/page (img) `(nth 0 ,img)) -(defmacro pdf-cache--image/width (img) `(nth 1 ,img)) -(defmacro pdf-cache--image/data (img) `(nth 2 ,img)) -(defmacro pdf-cache--image/hash (img) `(nth 3 ,img)) +(defmacro pdf-cache--image/page (img) + "Return the page value for IMG." + `(nth 0 ,img)) +(defmacro pdf-cache--image/width (img) + "Return the width value for IMG." + `(nth 1 ,img)) +(defmacro pdf-cache--image/data (img) + "Return the data value for IMG." + `(nth 2 ,img)) +(defmacro pdf-cache--image/hash (img) + "Return the hash value for IMG." + `(nth 3 ,img)) (defun pdf-cache--image-match (image page min-width &optional max-width hash) "Match IMAGE with specs. IMAGE should be a list as created by `pdf-cache--make-image'. -Return non-nil, if IMAGE's page is the same as PAGE, it's width -is at least MIN-WIDTH and at most MAX-WIDTH and it's stored +Return non-nil, if IMAGE's page is the same as PAGE, its width +is at least MIN-WIDTH and at most MAX-WIDTH and its stored hash-value is `eql' to HASH." (and (= (pdf-cache--image/page image) page) @@ -189,12 +214,15 @@ hash-value is `eql' to HASH." (defun pdf-cache-lookup-image (page min-width &optional max-width hash) "Return PAGE's cached PNG data as a string or nil. +Return an image of at least MIN-WIDTH and, if non-nil, maximum +width MAX-WIDTH and `eql' HASH value. + Does not modify the cache. See also `pdf-cache-get-image'." (let ((image (car (cl-member (list page min-width max-width hash) pdf-cache--image-cache :test (lambda (spec image) - (apply 'pdf-cache--image-match image spec)))))) + (apply #'pdf-cache--image-match image spec)))))) (and image (pdf-cache--image/data image)))) @@ -202,7 +230,7 @@ Does not modify the cache. See also `pdf-cache-get-image'." "Return PAGE's PNG data as a string. Return an image of at least MIN-WIDTH and, if non-nil, maximum -width MAX-WIDTH and `eql' hash value. +width MAX-WIDTH and `eql' HASH value. Remember that image was recently used. @@ -228,9 +256,9 @@ the HASH argument. This function always returns nil." (unless pdf-cache--image-cache - (add-hook 'pdf-info-close-document-hook 'pdf-cache-clear-images nil t) + (add-hook 'pdf-info-close-document-hook #'pdf-cache-clear-images nil t) (add-hook 'pdf-annot-modified-functions - 'pdf-cache--clear-images-of-annotations nil t)) + #'pdf-cache--clear-images-of-annotations nil t)) (push (pdf-cache--make-image page width data hash) pdf-cache--image-cache) ;; Forget old image(s). @@ -266,19 +294,25 @@ from the cache." (defun pdf-cache--clear-images-of-annotations (fn) - (apply 'pdf-cache-clear-images-of-pages + "Clear the images cache when annotations are modified. + +FN is a closure as described in `pdf-annot-modified-functions'. + +Note: This is an internal function and not meant to be directly used." + (apply #'pdf-cache-clear-images-of-pages (mapcar (lambda (a) (cdr (assq 'page a))) (funcall fn t)))) (defun pdf-cache-clear-images-of-pages (&rest pages) + "Remove all images of PAGES from the image cache." (pdf-cache-clear-images-if (lambda (page &rest _) (memq page pages)))) (defun pdf-cache-renderpage (page min-width &optional max-width) "Render PAGE according to MIN-WIDTH and MAX-WIDTH. -Return the PNG data of an image as a string, such that it's width +Return the PNG data of an image as a string, such that its width is at least MIN-WIDTH and, if non-nil, at most MAX-WIDTH. If such an image is not available in the cache, call @@ -297,14 +331,14 @@ If such an image is not available in the cache, call See also `pdf-info-renderpage-text-regions' and `pdf-cache-renderpage'." (if pdf-cache-image-inihibit - (apply 'pdf-info-renderpage-text-regions - page width single-line-p nil selection) + (apply #'pdf-info-renderpage-text-regions + page width single-line-p nil nil selection) (let ((hash (sxhash (format "%S" (cons 'renderpage-text-regions (cons single-line-p selection)))))) (or (pdf-cache-get-image page width width hash) - (let ((data (apply 'pdf-info-renderpage-text-regions - page width single-line-p nil selection))) + (let ((data (apply #'pdf-info-renderpage-text-regions + page width single-line-p nil nil selection))) (pdf-cache-put-image page width data hash) data))))) @@ -314,13 +348,13 @@ See also `pdf-info-renderpage-text-regions' and See also `pdf-info-renderpage-highlight' and `pdf-cache-renderpage'." (if pdf-cache-image-inihibit - (apply 'pdf-info-renderpage-highlight + (apply #'pdf-info-renderpage-highlight page width nil regions) (let ((hash (sxhash (format "%S" (cons 'renderpage-highlight regions))))) (or (pdf-cache-get-image page width width hash) - (let ((data (apply 'pdf-info-renderpage-highlight + (let ((data (apply #'pdf-info-renderpage-highlight page width nil regions))) (pdf-cache-put-image page width data hash) data))))) @@ -338,21 +372,25 @@ See also `pdf-info-renderpage-highlight' and (define-minor-mode pdf-cache-prefetch-minor-mode "Try to load images which will probably be needed in a while." - nil nil nil + :group 'pdf-cache (pdf-cache--prefetch-cancel) (cond (pdf-cache-prefetch-minor-mode (pdf-util-assert-pdf-buffer) - (add-hook 'pre-command-hook 'pdf-cache--prefetch-stop nil t) - ;; FIXME: Disable the time when the buffer is killed or it's + (add-hook 'pre-command-hook #'pdf-cache--prefetch-stop nil t) + ;; FIXME: Disable the time when the buffer is killed or its ;; major-mode changes. (setq pdf-cache--prefetch-timer - (run-with-idle-timer (or pdf-cache-prefetch-delay 1) - t 'pdf-cache--prefetch-start (current-buffer)))) + (run-with-idle-timer (or pdf-cache-prefetch-delay 1) t + #'pdf-cache--prefetch-start (current-buffer)))) (t - (remove-hook 'pre-command-hook 'pdf-cache--prefetch-stop t)))) + (remove-hook 'pre-command-hook #'pdf-cache--prefetch-stop t)))) (defun pdf-cache-prefetch-pages-function-default () + "The default function to prefetch pages. + +See `pdf-cache-prefetch-pages-function' for an explanation of +what this function does." (let ((page (pdf-view-current-page))) (pdf-util-remove-duplicates (cl-remove-if-not @@ -379,7 +417,11 @@ See also `pdf-info-renderpage-highlight' and (pdf-cache-pagelinks (pdf-view-current-page))))))))) +(defvar pdf-view-use-scaling) (defun pdf-cache--prefetch-pages (window image-width) + "Internal function to prefetch pages and store them in the cache. + +WINDOW and IMAGE-WIDTH decide the page and scale of the final image." (when (and (eq window (selected-window)) (pdf-util-pdf-buffer-p)) (let ((page (pop pdf-cache--prefetch-pages))) @@ -387,9 +429,9 @@ See also `pdf-info-renderpage-highlight' and (pdf-cache-lookup-image page image-width - (if (not (pdf-view-use-scaling-p)) - image-width - (* 2 image-width)))) + (if pdf-view-use-scaling + (* 2 image-width) + image-width))) (setq page (pop pdf-cache--prefetch-pages))) (pdf-util-debug (when (null page) @@ -411,7 +453,8 @@ See also `pdf-info-renderpage-highlight' and (message "Prefetched page %s." page)) ;; Avoid max-lisp-eval-depth (run-with-timer - 0.001 nil 'pdf-cache--prefetch-pages window image-width))))))) + 0.001 nil + #'pdf-cache--prefetch-pages window image-width))))))) (condition-case err (pdf-info-renderpage page image-width) (error diff --git a/elpa/pdf-tools-20191031.642/pdf-dev.el b/elpa/pdf-tools-20230611.239/pdf-dev.el similarity index 90% rename from elpa/pdf-tools-20191031.642/pdf-dev.el rename to elpa/pdf-tools-20230611.239/pdf-dev.el index 6273b3ec..6ea5d8ca 100644 --- a/elpa/pdf-tools-20191031.642/pdf-dev.el +++ b/elpa/pdf-tools-20230611.239/pdf-dev.el @@ -20,7 +20,7 @@ ;;; Commentary: ;; -;; This file is only ment for developers. The entry point is +;; This file is only meant for developers. The entry point is ;; pdf-dev-minor-mode, which see. ;;; Code: @@ -31,7 +31,7 @@ (file-name-directory load-file-name)))) (defun pdf-dev-reload () - "Reload lisp files from source." + "Reload Lisp files from source." (interactive) (let ((default-directory (expand-file-name "lisp" @@ -53,8 +53,8 @@ Quits the server and sets `pdf-info-epdfinfo-program' to Installs a `compilation-finish-functions' which will restart epdfinfo after a successful recompilation. -Sets up `load-path' and reloads all PDF Tools lisp files." - nil nil nil +Sets up `load-path' and reloads all PDF Tools Lisp files." + :group 'pdf-dev (let ((lisp-dir (expand-file-name "lisp" pdf-dev-root-directory))) (setq load-path (remove lisp-dir load-path)) (cond @@ -71,6 +71,10 @@ Sets up `load-path' and reloads all PDF Tools lisp files." (remove-hook 'compilation-finish-functions 'pdf-dev-compilation-finished))))) (defun pdf-dev-compilation-finished (buffer status) + "Restart the epdfinfo server. + +BUFFER is the PDF buffer and STATUS is the compilation status of +building epdfinfo." (with-current-buffer buffer (when (and (equal status "finished\n") (file-equal-p diff --git a/elpa/pdf-tools-20191031.642/pdf-history.el b/elpa/pdf-tools-20230611.239/pdf-history.el similarity index 91% rename from elpa/pdf-tools-20191031.642/pdf-history.el rename to elpa/pdf-tools-20230611.239/pdf-history.el index 433d7e3f..e380cf55 100644 --- a/elpa/pdf-tools-20191031.642/pdf-history.el +++ b/elpa/pdf-tools-20230611.239/pdf-history.el @@ -38,8 +38,10 @@ (defvar pdf-history-minor-mode-map (let ((kmap (make-sparse-keymap))) - (define-key kmap (kbd "B") 'pdf-history-backward) - (define-key kmap (kbd "N") 'pdf-history-forward) + (define-key kmap (kbd "B") #'pdf-history-backward) + (define-key kmap (kbd "N") #'pdf-history-forward) + (define-key kmap (kbd "l") #'pdf-history-backward) + (define-key kmap (kbd "r") #'pdf-history-forward) kmap) "Keymap used in `pdf-history-minor-mode'.") @@ -52,17 +54,17 @@ following a link pushes the left-behind page on the stack, which may be navigated with the following keys. \\{pdf-history-minor-mode-map}" - nil nil nil + :group 'pdf-history (pdf-util-assert-pdf-buffer) (pdf-history-clear) (cond (pdf-history-minor-mode (pdf-history-push) (add-hook 'pdf-view-after-change-page-hook - 'pdf-history-before-change-page-hook nil t)) + #'pdf-history-before-change-page-hook nil t)) (t (remove-hook 'pdf-view-after-change-page-hook - 'pdf-history-before-change-page-hook t)))) + #'pdf-history-before-change-page-hook t)))) (defun pdf-history-before-change-page-hook () "Push a history item, before leaving this page." @@ -110,7 +112,7 @@ represents the current page." (1- (length pdf-history-stack)))) (defun pdf-history-backward (n) - "Go N-times backward in the history." + "Go N times backward in the history." (interactive "p") (cond ((and (> n 0) @@ -128,7 +130,7 @@ represents the current page." (t 0))) (defun pdf-history-forward (n) - "Go N-times forward in the history." + "Go N times forward in the history." (interactive "p") (pdf-history-backward (- n))) diff --git a/elpa/pdf-tools-20191031.642/pdf-info.el b/elpa/pdf-tools-20230611.239/pdf-info.el similarity index 91% rename from elpa/pdf-tools-20191031.642/pdf-info.el rename to elpa/pdf-tools-20230611.239/pdf-info.el index 6dd7ff65..db1dc7e9 100644 --- a/elpa/pdf-tools-20191031.642/pdf-info.el +++ b/elpa/pdf-tools-20230611.239/pdf-info.el @@ -75,7 +75,7 @@ (or (executable-find executable) ;; This works if epdfinfo is in the same place as emacs and ;; the editor was started with an absolute path, i.e. it is - ;; ment for Windows/Msys2. + ;; meant for Windows/Msys2. (and (stringp (car-safe command-line-args)) (file-name-directory (car command-line-args)) (try-directory @@ -85,14 +85,12 @@ ;; Fall back to epdfinfo in the directory of this file. (expand-file-name executable)))) "Filename of the epdfinfo executable." - :group 'pdf-info :type 'file) (defcustom pdf-info-epdfinfo-error-filename nil "Filename for error output of the epdfinfo executable. If nil, discard any error messages. Useful for debugging." - :group 'pdf-info :type `(choice (const :tag "None" nil) ,@(when (file-directory-p "/tmp/") '((const "/tmp/epdfinfo.log"))) @@ -103,14 +101,12 @@ If nil, discard any error messages. Useful for debugging." If this is non-nil, all communication with the epdfinfo program will be logged to the buffer \"*pdf-info-log*\"." - :group 'pdf-info :type 'boolean) (defcustom pdf-info-log-entry-max 512 "Maximum number of characters in a single log entry. This variable has no effect if `pdf-info-log' is nil." - :group 'pdf-info :type 'integer) (defcustom pdf-info-restart-process-p 'ask @@ -123,7 +119,6 @@ ask -- ask whether to restart or not. If it is `ask', the server quits and you answer no, this variable is set to nil." - :group 'pdf-info :type '(choice (const :tag "Do nothing" nil) (const :tag "Restart silently" t) (const :tag "Always ask" ask))) @@ -133,7 +128,6 @@ is set to nil." The hook is run in the documents buffer, if it exists. Otherwise in a `with-temp-buffer' form." - :group 'pdf-info :type 'hook) @@ -194,7 +188,7 @@ This variable should only be let-bound.") (defvar pdf-info--queue t "Internally used transmission-queue for the server. -This variable is initially `t', telling the code starting the +This variable is initially t, telling the code starting the server, that it never ran.") @@ -311,41 +305,46 @@ error." (setq pdf-info--queue (tq-create proc)))) pdf-info--queue) -(defadvice tq-process-buffer (around bugfix activate) - "Fix a bug in trunk where the wrong callback gets called." +(when (< emacs-major-version 27) + (advice-add 'tq-process-buffer :around #'pdf-info--tq-workaround)) + +(defun pdf-info--tq-workaround (orig-fun tq &rest args) + "Fix a bug in trunk where the wrong callback gets called. + +ORIG-FUN is the callback that should be called. TQ and ARGS are +the transmission-queue and arguments to the callback." ;; FIXME: Make me iterative. - (let ((tq (ad-get-arg 0))) - (if (not (equal (car (process-command (tq-process tq))) - pdf-info-epdfinfo-program)) - ad-do-it - (let ((buffer (tq-buffer tq)) - done) - (when (buffer-live-p buffer) - (set-buffer buffer) - (while (and (not done) - (> (buffer-size) 0)) - (setq done t) - (if (tq-queue-empty tq) - (let ((buf (generate-new-buffer "*spurious*"))) - (copy-to-buffer buf (point-min) (point-max)) - (delete-region (point-min) (point)) - (pop-to-buffer buf nil) - (error "Spurious communication from process %s, see buffer %s" - (process-name (tq-process tq)) - (buffer-name buf))) - (goto-char (point-min)) - (when (re-search-forward (tq-queue-head-regexp tq) nil t) - (setq done nil) - (let ((answer (buffer-substring (point-min) (point))) - (fn (tq-queue-head-fn tq)) - (closure (tq-queue-head-closure tq))) - (delete-region (point-min) (point)) - (tq-queue-pop tq) - (condition-case-unless-debug err - (funcall fn closure answer) - (error - (message "Error while processing tq callback: %s" - (error-message-string err))))))))))))) + (if (not (equal (car (process-command (tq-process tq))) + pdf-info-epdfinfo-program)) + (apply orig-fun tq args) + (let ((buffer (tq-buffer tq)) + done) + (when (buffer-live-p buffer) + (set-buffer buffer) + (while (and (not done) + (> (buffer-size) 0)) + (setq done t) + (if (tq-queue-empty tq) + (let ((buf (generate-new-buffer "*spurious*"))) + (copy-to-buffer buf (point-min) (point-max)) + (delete-region (point-min) (point)) + (pop-to-buffer buf nil) + (error "Spurious communication from process %s, see buffer %s" + (process-name (tq-process tq)) + (buffer-name buf))) + (goto-char (point-min)) + (when (re-search-forward (tq-queue-head-regexp tq) nil t) + (setq done nil) + (let ((answer (buffer-substring (point-min) (point))) + (fn (tq-queue-head-fn tq)) + (closure (tq-queue-head-closure tq))) + (delete-region (point-min) (point)) + (tq-queue-pop tq) + (condition-case-unless-debug err + (funcall fn closure answer) + (error + (message "Error while processing tq callback: %s" + (error-message-string err)))))))))))) ;; * ================================================================== * @@ -357,8 +356,9 @@ error." (pdf-info-process-assert-running) (unless (symbolp cmd) (setq cmd (intern cmd))) - (let* ((query (concat (mapconcat 'pdf-info-query--escape - (cons cmd args) ":") "\n")) + (let* ((query (concat (mapconcat #'pdf-info-query--escape + (cons cmd args) ":") + "\n")) (callback (lambda (closure response) (cl-destructuring-bind (status &rest result) @@ -384,7 +384,7 @@ error." (not (eq (process-status (pdf-info-process)) 'run)) (not (eq cmd 'quit))) - (error "The epdfinfo server quit unexpectedly.")) + (error "The epdfinfo server quit unexpectedly")) (cond ((null status) response) ((eq status 'error) @@ -392,7 +392,7 @@ error." ((eq status 'interrupted) (error "epdfinfo: Command was interrupted")) (t - (error "internal error: invalid response status")))))) + (error "Internal error: invalid response status")))))) (defun pdf-info-interrupt () "FIXME: This command does currently nothing." @@ -483,7 +483,7 @@ interrupted." (mapcar (lambda (elt) (cl-assert (= 1 (length (cadr elt))) t) `(,(aref (cadr elt) 0) - ,(mapcar 'string-to-number + ,(mapcar #'string-to-number (split-string (car elt) " " t)))) response)) (regexp-flags @@ -499,7 +499,7 @@ interrupted." (pdf-util-highlight-regexp-in-string (regexp-quote (nth 1 r)) (nth 2 r)))) (edges . ,(mapcar (lambda (m) - (mapcar 'string-to-number + (mapcar #'string-to-number (split-string m " " t))) (cddr (cdr r)))))) response)) @@ -511,7 +511,7 @@ interrupted." (pagelinks (mapcar (lambda (r) `((edges . - ,(mapcar 'string-to-number ;area + ,(mapcar #'string-to-number ;area (split-string (pop r) " " t))) ,@(pdf-info-query--transform-action r))) response)) @@ -534,10 +534,10 @@ interrupted." (or (caar response) "")) (getselection (mapcar (lambda (line) - (mapcar 'string-to-number + (mapcar #'string-to-number (split-string (car line) " " t))) response)) - (features (mapcar 'intern (car response))) + (features (mapcar #'intern (car response))) (pagesize (setq response (car response)) (cons (round (string-to-number (car response))) @@ -545,15 +545,15 @@ interrupted." ((getannot editannot addannot) (pdf-info-query--transform-annotation (car response))) (getannots - (mapcar 'pdf-info-query--transform-annotation response)) + (mapcar #'pdf-info-query--transform-annotation response)) (getattachments - (mapcar 'pdf-info-query--transform-attachment response)) + (mapcar #'pdf-info-query--transform-attachment response)) ((getattachment-from-annot) (pdf-info-query--transform-attachment (car response))) (boundingbox - (mapcar 'string-to-number (car response))) + (mapcar #'string-to-number (car response))) (synctex-forward-search - (let ((list (mapcar 'string-to-number (car response)))) + (let ((list (mapcar #'string-to-number (car response)))) `((page . ,(car list)) (edges . ,(cdr list))))) (synctex-backward-search @@ -570,12 +570,18 @@ interrupted." (let ((key (intern (car key-value))) (value (cadr key-value))) (cl-case key - ((:render/printed :render/usecolors) - (setq value (equal value "1")))) + ((:render/printed) + (setq value (equal value "1"))) + ((:render/usecolors) + (setq value (ignore-errors + (let ((int-val (cl-parse-integer value))) + (if (> 3 int-val 0) + int-val + 0)))))) (push value options) (push key options))) options)) - (pagelabels (mapcar 'car response)) + (pagelabels (mapcar #'car response)) (ping (caar response)) (t response))) @@ -604,7 +610,7 @@ interrupted." (cl-destructuring-bind (page edges type id flags color contents modified &rest rest) a (setq a1 `((page . ,(string-to-number page)) - (edges . ,(mapcar 'string-to-number + (edges . ,(mapcar #'string-to-number (split-string edges " " t))) (type . ,(intern type)) (id . ,(intern id)) @@ -623,7 +629,7 @@ interrupted." (and o (string-to-number o)))) (popup-edges . ,(let ((p (not-empty popup-edges))) (when p - (mapcar 'string-to-number + (mapcar #'string-to-number (split-string p " " t))))) (popup-is-open . ,(equal popup-is-open "1")) (created . ,(pdf-info-parse-pdf-date (not-empty created))))) @@ -639,7 +645,7 @@ interrupted." '(squiggly highlight underline strike-out)) (setq a3 `((markup-edges . ,(mapcar (lambda (r) - (mapcar 'string-to-number + (mapcar #'string-to-number (split-string r " " t))) rest))))))))) (append a1 a2 a3)))) @@ -851,9 +857,8 @@ i.e. `pdf-info-asynchronous' is non-nil, transparently. ;; Let-bind responses corresponding to their variables, ;; i.e. keys in alist RESULTS. (let (,@(mapcar (lambda (var) - (list var (list 'cdr (list 'assq (list 'quote var) - results)))) - (mapcar 'car let-forms))) + `(,var (cdr (assq ',var ,results)))) + (mapcar #'car let-forms))) (setq ,status (not (not ,first-error)) ,response (or ,first-error (with-current-buffer ,buffer @@ -888,7 +893,7 @@ i.e. `pdf-info-asynchronous' is non-nil, transparently. (when (and (not ,done) (not (eq (process-status (pdf-info-process)) 'run))) - (error "The epdfinfo server quit unexpectedly.")) + (error "The epdfinfo server quit unexpectedly")) (when ,status (error "epdfinfo: %s" ,response)) ,response)))) @@ -920,7 +925,7 @@ restart it." (tq-close pdf-info--queue)) (set (make-local-variable 'pdf-info--queue) nil) (pdf-info-process-assert-running t) - (add-hook 'kill-buffer-hook 'pdf-info-kill-local-server nil t) + (add-hook 'kill-buffer-hook #'pdf-info-kill-local-server nil t) pdf-info--queue))) (defun pdf-info-kill-local-server (&optional buffer) @@ -1034,7 +1039,11 @@ Manually opened documents are never closed automatically." Returns t, if the document was actually open, otherwise nil. This command is rarely needed, see also `pdf-info-open'." (let* ((pdf (pdf-info--normalize-file-or-buffer file-or-buffer)) - (buffer (find-buffer-visiting pdf))) + (buffer (cond + ((not file-or-buffer) (current-buffer)) + ((bufferp file-or-buffer) file-or-buffer) + ((stringp file-or-buffer) + (find-buffer-visiting file-or-buffer))))) (prog1 (pdf-info-query 'close pdf) (if (buffer-live-p buffer) @@ -1244,6 +1253,17 @@ of this element in the tree." 'outline (pdf-info--normalize-file-or-buffer file-or-buffer))) +(defun pdf-info--selection-style (selection-style) + "SELECTION-STYLE is the smallest unit of the selected region. + +It must be one of glyph, word or line. If it is none of these, we +fallback to glyph." + (cl-case selection-style + (glyph 0) + (word 1) + (line 2) + (t 0))) + (defun pdf-info-gettext (page edges &optional selection-style file-or-buffer) "Get text on PAGE according to EDGES. @@ -1259,31 +1279,22 @@ Return the text contained in the selection." 'gettext (pdf-info--normalize-file-or-buffer file-or-buffer) page - (mapconcat 'number-to-string edges " ") - (cl-case selection-style - (glyph 0) - (word 1) - (line 2) - (t 0)))) - -(defun pdf-info-getselection (page edges &optional selection-style - file-or-buffer) + (mapconcat #'number-to-string edges " ") + (pdf-info--selection-style selection-style))) + +(defun pdf-info-getselection (page edges + &optional selection-style file-or-buffer) "Return the edges of the selection EDGES on PAGE. Arguments are the same as for `pdf-info-gettext'. Return a list of edges corresponding to the text that would be returned by the aforementioned function, when called with the same arguments." - (pdf-info-query 'getselection (pdf-info--normalize-file-or-buffer file-or-buffer) page - (mapconcat 'number-to-string edges " ") - (cl-case selection-style - (glyph 0) - (word 1) - (line 2) - (t 0)))) + (mapconcat #'number-to-string edges " ") + (pdf-info--selection-style selection-style))) (defun pdf-info-textregions (page &optional file-or-buffer) "Return a list of edges describing PAGE's text-layout." @@ -1314,7 +1325,7 @@ contains at most one element." 'charlayout (pdf-info--normalize-file-or-buffer file-or-buffer) page - (mapconcat 'number-to-string edges-or-pos " "))) + (mapconcat #'number-to-string edges-or-pos " "))) (defun pdf-info-pagesize (page &optional file-or-buffer) "Return the size of PAGE as a cons \(WIDTH . HEIGHT\) @@ -1416,7 +1427,9 @@ function." (pdf-info--normalize-file-or-buffer file-or-buffer) id)) -(defun pdf-info-addannot (page edges type &optional file-or-buffer &rest markup-edges) +(defun pdf-info-addannot (page edges type + &optional selection-style file-or-buffer + &rest markup-edges) "Add a new annotation to PAGE with EDGES of TYPE. FIXME: TYPE may be one of `text', `markup-highlight', ... . @@ -1428,11 +1441,12 @@ returns." (push file-or-buffer markup-edges) (setq file-or-buffer nil)) (apply - 'pdf-info-query + #'pdf-info-query 'addannot (pdf-info--normalize-file-or-buffer file-or-buffer) page type + (pdf-info--selection-style selection-style) (mapconcat 'number-to-string edges " ") (mapcar (lambda (me) (mapconcat 'number-to-string me " ")) @@ -1488,11 +1502,11 @@ The server must support modifying annotations for this to work." (t (list (car elt) (cdr elt))))) modifications))) - (apply 'pdf-info-query + (apply #'pdf-info-query 'editannot (pdf-info--normalize-file-or-buffer file-or-buffer) id - (apply 'append edits)))) + (apply #'append edits)))) (defun pdf-info-save (&optional file-or-buffer) "Save FILE-OR-BUFFER. @@ -1590,7 +1604,7 @@ Return the data of the corresponding PNG image." (when (keywordp file-or-buffer) (push file-or-buffer commands) (setq file-or-buffer nil)) - (apply 'pdf-info-query + (apply #'pdf-info-query 'renderpage (pdf-info--normalize-file-or-buffer file-or-buffer) page @@ -1602,11 +1616,13 @@ Return the data of the corresponding PNG image." (setq value (cl-case kw ((:crop-to :highlight-line :highlight-region :highlight-text) - (mapconcat 'number-to-string value " ")) + (mapconcat #'number-to-string value " ")) ((:foreground :background) (pdf-util-hexcolor value)) (:alpha (number-to-string value)) + (:selection-style + (number-to-string (pdf-info--selection-style value))) (otherwise value))) (push kw transformed) (push value transformed))) @@ -1615,14 +1631,14 @@ Return the data of the corresponding PNG image." (nreverse transformed)))) (defun pdf-info-renderpage-text-regions (page width single-line-p - &optional file-or-buffer + &optional selection-style file-or-buffer &rest regions) "Highlight text on PAGE with width WIDTH using REGIONS. REGIONS is a list determining foreground and background color and the regions to render. So each element should look like \(FG BG \(LEFT TOP RIGHT BOT\) \(LEFT TOP RIGHT BOT\) ... \) . The -rendering is text-aware. +rendering is text-aware and is controlled by SELECTION-STYLE. If SINGLE-LINE-P is non-nil, the edges in REGIONS are each supposed to be limited to a single line in the document. Setting @@ -1636,9 +1652,10 @@ Return the data of the corresponding PNG image." (push file-or-buffer regions) (setq file-or-buffer nil)) - (apply 'pdf-info-renderpage + (apply #'pdf-info-renderpage page width file-or-buffer - (apply 'append + (apply #'append + `(:selection-style ,selection-style) (mapcar (lambda (elt) `(:foreground ,(pop elt) :background ,(pop elt) @@ -1668,9 +1685,9 @@ Return the data of the corresponding PNG image." (push file-or-buffer regions) (setq file-or-buffer nil)) - (apply 'pdf-info-renderpage + (apply #'pdf-info-renderpage page width file-or-buffer - (apply 'append + (apply #'append (mapcar (lambda (elt) `(:background ,(pop elt) :foreground ,(pop elt) @@ -1701,7 +1718,7 @@ Returns a list \(LEFT TOP RIGHT BOT\)." (setq file-or-buffer nil)) (unless (= (% (length options) 2) 0) (error "Missing a option value")) - (apply 'pdf-info-query + (apply #'pdf-info-query 'setoptions (pdf-info--normalize-file-or-buffer file-or-buffer) (let (soptions) @@ -1715,8 +1732,16 @@ Returns a list \(LEFT TOP RIGHT BOT\)." ((:render/foreground :render/background) (push (pdf-util-hexcolor value) soptions)) - ((:render/usecolors :render/printed) + ((:render/printed) (push (if value 1 0) soptions)) + ((:render/usecolors) + ;; 0 -> original color + ;; 1 -> recolor document to grayscale mapping black to + ;; :render/foreground and white to :render/background + ;; 2 -> recolor document by inverting the perceived lightness + ;; preserving hue + (push (if (and (integerp value) (> 3 value 0)) value 0) + soptions)) (t (push value soptions))) (push key soptions))) soptions))) diff --git a/elpa/pdf-tools-20191031.642/pdf-isearch.el b/elpa/pdf-tools-20230611.239/pdf-isearch.el similarity index 99% rename from elpa/pdf-tools-20191031.642/pdf-isearch.el rename to elpa/pdf-tools-20230611.239/pdf-isearch.el index 563e721c..f5468eb5 100644 --- a/elpa/pdf-tools-20191031.642/pdf-isearch.el +++ b/elpa/pdf-tools-20230611.239/pdf-isearch.el @@ -127,7 +127,9 @@ keymap is `isearch-mode-map'.") (put 'image-scroll-up 'isearch-scroll t) (put 'image-scroll-down 'isearch-scroll t) -(define-minor-mode pdf-isearch-active-mode "" nil nil nil +(define-minor-mode pdf-isearch-active-mode + "This mode is enabled when isearch is active in a PDF file." + :group 'pdf-isearch (cond (pdf-isearch-active-mode (set (make-local-variable 'isearch-mode-map) @@ -218,7 +220,6 @@ If this mode is enabled, isearching does not stop at every match, but rather moves to the next one not currently visible. This behaviour is much faster than ordinary isearch, since far less different images have to be displayed." - nil nil nil :group 'pdf-isearch (when isearch-mode (pdf-isearch-redisplay) @@ -742,9 +743,9 @@ MATCH-BG LAZY-FG LAZY-BG\)." occur-hack-p) (eq page (pdf-view-current-page))) (pdf-view-display-image - (pdf-view-create-image data)))))))) + (pdf-view-create-image data :width width)))))))) (pdf-info-renderpage-text-regions - page width t nil + page width t nil nil `(,fg1 ,bg1 ,@(pdf-util-scale-pixel-to-relative current)) `(,fg2 ,bg2 ,@(pdf-util-scale-pixel-to-relative diff --git a/elpa/pdf-tools-20191031.642/pdf-links.el b/elpa/pdf-tools-20230611.239/pdf-links.el similarity index 98% rename from elpa/pdf-tools-20191031.642/pdf-links.el rename to elpa/pdf-tools-20230611.239/pdf-links.el index 24baa3c2..d54981e0 100644 --- a/elpa/pdf-tools-20191031.642/pdf-links.el +++ b/elpa/pdf-tools-20230611.239/pdf-links.el @@ -111,8 +111,6 @@ one of the displayed keys, or by using isearch limited to links via \\[pdf-links-isearch-link]. \\{pdf-links-minor-mode-map}" - - nil nil nil :group 'pdf-links (pdf-util-assert-pdf-buffer) (cond @@ -369,7 +367,12 @@ Wraps the URI in \[\[ ... \]\] and calls `org-open-link-from-string' on the resulting string." (cl-check-type uri string) (message "Opening `%s' with Org" uri) - (org-open-link-from-string (format "[[%s]]" uri))) + (cond + ((fboundp 'org-link-open-from-string) + (org-link-open-from-string (format "[[%s]]" uri))) + ;; For Org 9.2 and older + ((fboundp 'org-open-link-from-string) + (org-open-link-from-string (format "[[%s]]" uri))))) (provide 'pdf-links) diff --git a/elpa/pdf-tools-20191031.642/pdf-loader.el b/elpa/pdf-tools-20230611.239/pdf-loader.el similarity index 100% rename from elpa/pdf-tools-20191031.642/pdf-loader.el rename to elpa/pdf-tools-20230611.239/pdf-loader.el diff --git a/elpa/pdf-tools-20230611.239/pdf-macs.el b/elpa/pdf-tools-20230611.239/pdf-macs.el new file mode 100644 index 00000000..e4ac6ea0 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/pdf-macs.el @@ -0,0 +1,51 @@ +;;; pdf-macs.el --- Macros for pdf-tools. -*- lexical-binding:t -*- + +;; Copyright (C) 2013 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, doc-view, pdf + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;;; Code: +;; + +(defmacro pdf-view-current-page (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'page ,window)) + +(defmacro pdf-view-current-overlay (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'overlay ,window)) + +(defmacro pdf-view-current-image (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'image ,window)) + +(defmacro pdf-view-current-slice (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'slice ,window)) + +(defmacro pdf-view-current-window-size (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'window-size ,window)) + +(defmacro pdf-view-window-needs-redisplay (&optional window) + `(image-mode-window-get 'needs-redisplay ,window)) + +(provide 'pdf-macs) + +;;; pdf-macs.el ends here diff --git a/elpa/pdf-tools-20191031.642/pdf-misc.el b/elpa/pdf-tools-20230611.239/pdf-misc.el similarity index 77% rename from elpa/pdf-tools-20191031.642/pdf-misc.el rename to elpa/pdf-tools-20230611.239/pdf-misc.el index 6b46d999..bcba8aea 100644 --- a/elpa/pdf-tools-20191031.642/pdf-misc.el +++ b/elpa/pdf-tools-20230611.239/pdf-misc.el @@ -1,4 +1,4 @@ -;;; pdf-misc.el --- Miscellaneous commands for PDF buffer. +;;; pdf-misc.el --- Miscellaneous commands for PDF buffer. -*- lexical-binding: t; -*- ;; Copyright (C) 2013, 2014 Andreas Politz @@ -28,6 +28,8 @@ +;;; Code: + (defvar pdf-misc-minor-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "I") 'pdf-misc-display-metadata) @@ -38,12 +40,12 @@ ;;;###autoload (define-minor-mode pdf-misc-minor-mode "FIXME: Not documented." - nil nil nil) + :group 'pdf-misc) ;;;###autoload (define-minor-mode pdf-misc-size-indication-minor-mode "Provide a working size indication in the mode-line." - nil nil nil + :group 'pdf-misc (pdf-util-assert-pdf-buffer) (cond (pdf-misc-size-indication-minor-mode @@ -141,6 +143,19 @@ ["Copy region" pdf-view-kill-ring-save :keys "\\[kill-ring-save]" :active (pdf-view-active-region-p)] + ("Selection style" + ["Glyph" (pdf-view-set-selection-style 'glyph) + :style radio + :selected (eq pdf-view-selection-style 'glyph) + :help "When dragging the mouse, select individual characters."] + ["Word" (pdf-view-set-selection-style 'word) + :style radio + :selected (eq pdf-view-selection-style 'word) + :help "When dragging the mouse, select entire words."] + ["Line" (pdf-view-set-selection-style 'line) + :style radio + :selected (eq pdf-view-selection-style 'line) + :help "When dragging the mouse, select entire lines."]) "--" ["Isearch document" isearch-forward :visible (bound-and-true-p pdf-isearch-minor-mode)] @@ -171,7 +186,7 @@ ;;;###autoload (define-minor-mode pdf-misc-menu-bar-minor-mode "Display a PDF Tools menu in the menu-bar." - nil nil nil + :group 'pdf-misc (pdf-util-assert-pdf-buffer)) (defvar pdf-misc-context-menu-minor-mode-map @@ -184,16 +199,18 @@ "Provide a right-click context menu in PDF buffers. \\{pdf-misc-context-menu-minor-mode-map}" - nil nil nil + :group 'pdf-misc (pdf-util-assert-pdf-buffer)) -(defun pdf-misc-popup-context-menu (event) - "Popup a context menu at position determined by EVENT." +(defun pdf-misc-popup-context-menu (_event) + "Popup a context menu at position." (interactive "@e") (popup-menu (cons 'keymap - (cddr (lookup-key pdf-misc-menu-bar-minor-mode-map - [menu-bar PDF\ Tools]))))) + (cddr (or (lookup-key pdf-misc-menu-bar-minor-mode-map + [menu-bar PDF\ Tools]) + (lookup-key pdf-misc-menu-bar-minor-mode-map + [menu-bar pdf\ tools])))))) (defun pdf-misc-display-metadata () "Display all available metadata in a separate buffer." @@ -206,8 +223,7 @@ (pad (apply' max (mapcar (lambda (d) (length (symbol-name (car d)))) md))) - (fmt (format "%%%ds:%%s\n" pad)) - window) + (fmt (format "%%%ds:%%s\n" pad))) (erase-buffer) (setq header-line-format (buffer-name buffer) buffer-read-only t) @@ -234,48 +250,62 @@ "Miscellaneous options for PDF documents." :group 'pdf-tools) -(defcustom pdf-misc-print-programm nil +(define-obsolete-variable-alias 'pdf-misc-print-programm + 'pdf-misc-print-program-executable "1.0") +(defcustom pdf-misc-print-program-executable nil "The program used for printing. It is called with one argument, the PDF file." :group 'pdf-misc :type 'file) -(defcustom pdf-misc-print-programm-args nil +(define-obsolete-variable-alias 'pdf-misc-print-programm-args + 'pdf-misc-print-program-args "1.0") +(defcustom pdf-misc-print-program-args nil "List of additional arguments passed to `pdf-misc-print-program'." :group 'pdf-misc :type '(repeat string)) -(defun pdf-misc-print-programm (&optional interactive-p) - (or (and pdf-misc-print-programm - (executable-find pdf-misc-print-programm)) +(define-obsolete-function-alias 'pdf-misc-print-programm + 'pdf-misc-print-program "1.0") +(defun pdf-misc-print-program (&optional interactive-p) + "Return the program used to print PDFs (if the executable is installed). + +If INTERACTIVE-P is non-nil, ask the user for which program to +use when printing the PDF. Optionally, save the choice" + (or (and pdf-misc-print-program-executable + (executable-find pdf-misc-print-program-executable)) (when interactive-p (let* ((default (car (delq nil (mapcar 'executable-find '("gtklp" "xpp" "gpr"))))) buffer-file-name - (programm + (program (expand-file-name (read-file-name "Print with: " default nil t nil 'file-executable-p)))) - (when (and programm - (executable-find programm)) - (when (y-or-n-p "Save choice using customize ?") + (when (and program + (executable-find program)) + (when (y-or-n-p "Save choice using customize? ") (customize-save-variable - 'pdf-misc-print-programm programm)) - (setq pdf-misc-print-programm programm)))))) + 'pdf-misc-print-program-executable program)) + (setq pdf-misc-print-program-executable program)))))) (defun pdf-misc-print-document (filename &optional interactive-p) + "Print the PDF doc FILENAME. + +`pdf-misc-print-program' handles the print program, which see for +definition of INTERACTIVE-P." (interactive (list (pdf-view-buffer-file-name) t)) - (cl-check-type filename (and string file-readable)) - (let ((programm (pdf-misc-print-programm interactive-p)) - (args (append pdf-misc-print-programm-args (list filename)))) - (unless programm + (cl-check-type filename (and string (satisfies file-readable-p))) + (let ((program (pdf-misc-print-program interactive-p)) + (args (append pdf-misc-print-program-args (list filename)))) + (unless program (error "No print program available")) - (apply #'start-process "printing" nil programm args) + (apply #'start-process "printing" nil program args) (message "Print job started: %s %s" - programm (mapconcat #'identity args " ")))) + program (mapconcat #'identity args " ")))) (provide 'pdf-misc) diff --git a/elpa/pdf-tools-20191031.642/pdf-occur.el b/elpa/pdf-tools-20230611.239/pdf-occur.el similarity index 93% rename from elpa/pdf-tools-20191031.642/pdf-occur.el rename to elpa/pdf-tools-20230611.239/pdf-occur.el index f2572e96..47bf2d29 100644 --- a/elpa/pdf-tools-20191031.642/pdf-occur.el +++ b/elpa/pdf-tools-20230611.239/pdf-occur.el @@ -46,25 +46,21 @@ (defface pdf-occur-document-face '((default (:inherit font-lock-string-face))) - "Face used to highlight documents in the list buffer." - :group 'pdf-occur) + "Face used to highlight documents in the list buffer.") (defface pdf-occur-page-face '((default (:inherit font-lock-type-face))) - "Face used to highlight page numbers in the list buffer." - :group 'pdf-occur) + "Face used to highlight page numbers in the list buffer.") (defcustom pdf-occur-search-batch-size 16 "Maximum number of pages searched in one query. Lower numbers will make Emacs more responsive when searching at the cost of slightly increased search time." - :group 'pdf-occur :type 'integer) (defcustom pdf-occur-prefer-string-search nil "If non-nil, reverse the meaning of the regexp-p prefix-arg." - :group 'pdf-occur :type 'boolean) (defvar pdf-occur-history nil @@ -78,7 +74,7 @@ the cost of slightly increased search time." Each element should be either the filename of a PDF document or a cons \(FILENAME . PAGES\), where PAGES is the list of pages to -search. See `pdf-info-normalize-page-range' for it's format.") +search. See `pdf-info-normalize-page-range' for its format.") (defvar pdf-occur-number-of-matches 0 "The number of matches in all searched documents.") @@ -92,15 +88,15 @@ search. See `pdf-info-normalize-page-range' for it's format.") (defvar pdf-occur-buffer-mode-map (let ((kmap (make-sparse-keymap))) (set-keymap-parent kmap tablist-mode-map) - (define-key kmap (kbd "RET") 'pdf-occur-goto-occurrence) - (define-key kmap (kbd "C-o") 'pdf-occur-view-occurrence) - (define-key kmap (kbd "SPC") 'pdf-occur-view-occurrence) - (define-key kmap (kbd "C-c C-f") 'next-error-follow-minor-mode) - (define-key kmap (kbd "g") 'pdf-occur-revert-buffer-with-args) - (define-key kmap (kbd "K") 'pdf-occur-abort-search) - (define-key kmap (kbd "D") 'pdf-occur-tablist-do-delete) - (define-key kmap (kbd "x") 'pdf-occur-tablist-do-flagged-delete) - (define-key kmap (kbd "A") 'pdf-occur-tablist-gather-documents) + (define-key kmap (kbd "RET") #'pdf-occur-goto-occurrence) + (define-key kmap (kbd "C-o") #'pdf-occur-view-occurrence) + (define-key kmap (kbd "SPC") #'pdf-occur-view-occurrence) + (define-key kmap (kbd "C-c C-f") #'next-error-follow-minor-mode) + (define-key kmap (kbd "g") #'pdf-occur-revert-buffer-with-args) + (define-key kmap (kbd "K") #'pdf-occur-abort-search) + (define-key kmap (kbd "D") #'pdf-occur-tablist-do-delete) + (define-key kmap (kbd "x") #'pdf-occur-tablist-do-flagged-delete) + (define-key kmap (kbd "A") #'pdf-occur-tablist-gather-documents) kmap) "The keymap used for `pdf-occur-buffer-mode'.") @@ -127,9 +123,10 @@ Some useful keys are: `pdf-view-mode' buffers in the search. \\{pdf-occur-buffer-mode-map}" - (setq-local next-error-function 'pdf-occur-next-error) + (setq-local case-fold-search case-fold-search) + (setq-local next-error-function #'pdf-occur-next-error) (setq-local revert-buffer-function - 'pdf-occur-revert-buffer) + #'pdf-occur-revert-buffer) (setq next-error-last-buffer (current-buffer)) (setq-local tabulated-list-sort-key nil) (setq-local tabulated-list-use-header-line t) @@ -191,10 +188,10 @@ For a programmatic search of multiple documents see (let* ((2-columns-p (= 1 (length pdf-occur-search-documents))) (filename-width (min 24 - (apply 'max - (mapcar 'length - (mapcar 'pdf-occur-abbrev-document - (mapcar 'car pdf-occur-search-documents)))))) + (apply #'max + (mapcar #'length + (mapcar #'pdf-occur-abbrev-document + (mapcar #'car pdf-occur-search-documents)))))) (page-sorter (tablist-generate-sorter (if 2-columns-p 0 1) '< @@ -352,8 +349,8 @@ Compatibility function for \\[next-error] invocations." This global minor mode enables (or disables) `pdf-occur-ibuffer-minor-mode' and `pdf-occur-dired-minor-mode' -in all current and future ibuffer/dired buffer." nil nil nil -:global t +in all current and future ibuffer/dired buffer." + :global t (let ((arg (if pdf-occur-global-minor-mode 1 -1))) (dolist (buf (buffer-list)) (with-current-buffer buf @@ -364,15 +361,15 @@ in all current and future ibuffer/dired buffer." nil nil nil (pdf-occur-ibuffer-minor-mode arg))))) (cond (pdf-occur-global-minor-mode - (add-hook 'dired-mode-hook 'pdf-occur-dired-minor-mode) - (add-hook 'ibuffer-mode-hook 'pdf-occur-ibuffer-minor-mode)) + (add-hook 'dired-mode-hook #'pdf-occur-dired-minor-mode) + (add-hook 'ibuffer-mode-hook #'pdf-occur-ibuffer-minor-mode)) (t - (remove-hook 'dired-mode-hook 'pdf-occur-dired-minor-mode) - (remove-hook 'ibuffer-mode-hook 'pdf-occur-ibuffer-minor-mode))))) + (remove-hook 'dired-mode-hook #'pdf-occur-dired-minor-mode) + (remove-hook 'ibuffer-mode-hook #'pdf-occur-ibuffer-minor-mode))))) (defvar pdf-occur-ibuffer-minor-mode-map (let ((map (make-sparse-keymap))) - (define-key map [remap ibuffer-do-occur] 'pdf-occur-ibuffer-do-occur) + (define-key map [remap ibuffer-do-occur] #'pdf-occur-ibuffer-do-occur) map) "Keymap used in `pdf-occur-ibuffer-minor-mode'.") @@ -383,9 +380,7 @@ in all current and future ibuffer/dired buffer." nil nil nil This mode remaps `ibuffer-do-occur' to `pdf-occur-ibuffer-do-occur', which will start the PDF Tools version of `occur', if all marked buffer's are in `pdf-view-mode' -and otherwise fallback to `ibuffer-do-occur'." - - nil nil nil) +and otherwise fallback to `ibuffer-do-occur'.") (defun pdf-occur-ibuffer-do-occur (&optional regexp-p) "Uses `pdf-occur-search', if appropriate. @@ -408,7 +403,7 @@ I.e. all marked buffers are in PDFView mode." (defvar pdf-occur-dired-minor-mode-map (let ((map (make-sparse-keymap))) - (define-key map [remap dired-do-search] 'pdf-occur-dired-do-search) + (define-key map [remap dired-do-search] #'pdf-occur-dired-do-search) map) "Keymap used in `pdf-occur-dired-minor-mode'.") @@ -419,9 +414,7 @@ I.e. all marked buffers are in PDFView mode." This mode remaps `dired-do-search' to `pdf-occur-dired-do-search', which will start the PDF Tools version of `occur', if all marked buffer's are in `pdf-view-mode' -and otherwise fallback to `dired-do-search'." - - nil nil nil) +and otherwise fallback to `dired-do-search'.") (defun pdf-occur-dired-do-search () "Uses `pdf-occur-search', if appropriate. @@ -452,7 +445,7 @@ I.e. all marked files look like PDF documents." DOCUMENTS should be a list of buffers (objects, not names), filenames or conses \(BUFFER-OR-FILENAME . PAGES\), where PAGES determines the scope of the search of the respective document. -See `pdf-info-normalize-page-range' for it's format. +See `pdf-info-normalize-page-range' for its format. STRING is either the string to search for or, if REGEXP-P is non-nil, a Perl compatible regular expression (PCRE). @@ -477,7 +470,8 @@ Returns the window where the buffer is displayed." (display-buffer (current-buffer)))) -(defadvice tabulated-list-init-header (after update-header activate) +(advice-add 'tabulated-list-init-header :after #'pdf-occur--update-header) +(defun pdf-occur--update-header (&rest _) "We want our own headers, thank you." (when (derived-mode-p 'pdf-occur-buffer-mode) (save-current-buffer @@ -554,7 +548,7 @@ matches linked with PAGE." (mapcar (lambda (doc) (pdf-occur-create-entry doc 1)) (cl-set-difference - (mapcar 'car + (mapcar #'car pdf-occur-search-documents) (mapcar (lambda (elt) (plist-get (car elt) :document)) @@ -634,7 +628,7 @@ matches linked with PAGE." batches) (setq pdf-occur-number-of-matches 0) (setq pdf-occur-search-pages-left - (apply '+ (mapcar (lambda (elt) + (apply #'+ (mapcar (lambda (elt) (1+ (- (cdr (nth 1 elt)) (car (nth 1 elt))))) batches))))) @@ -695,7 +689,7 @@ matches linked with PAGE." Examine all dired/ibuffer windows and offer to put marked files in the search list." (interactive) - (let ((searched (mapcar 'car pdf-occur-search-documents)) + (let ((searched (mapcar #'car pdf-occur-search-documents)) files) (dolist (win (window-list)) (with-selected-window win @@ -708,7 +702,7 @@ in the search list." (setq files (append files marked nil))))) ((derived-mode-p 'ibuffer-mode) - (dolist (fname (mapcar 'buffer-file-name + (dolist (fname (mapcar #'buffer-file-name (ibuffer-get-marked-buffers))) (when fname (push fname files)))) @@ -734,7 +728,7 @@ in the search list." (when (tablist-yes-or-no-p 'add nil (mapcar (lambda (file) (cons nil (vector file))) - (cl-sort files 'string-lessp))) + (cl-sort files #'string-lessp))) (setq pdf-occur-search-documents (append pdf-occur-search-documents (pdf-occur-normalize-documents files))) diff --git a/elpa/pdf-tools-20191031.642/pdf-outline.el b/elpa/pdf-tools-20230611.239/pdf-outline.el similarity index 87% rename from elpa/pdf-tools-20191031.642/pdf-outline.el rename to elpa/pdf-tools-20230611.239/pdf-outline.el index e141ca8c..fc75b027 100644 --- a/elpa/pdf-tools-20191031.642/pdf-outline.el +++ b/elpa/pdf-tools-20230611.239/pdf-outline.el @@ -41,73 +41,73 @@ (defcustom pdf-outline-buffer-indent 2 "The level of indent in the Outline buffer." - :type 'integer - :group 'pdf-outline) + :type 'integer) (defcustom pdf-outline-enable-imenu t "Whether `imenu' should be enabled in PDF documents." - :group 'pdf-outline :type '(choice (const :tag "Yes" t) (const :tag "No" nil))) (defcustom pdf-outline-imenu-keep-order t "Whether `imenu' should be advised not to reorder the outline." - :group 'pdf-outline :type '(choice (const :tag "Yes" t) (const :tag "No" nil))) (defcustom pdf-outline-imenu-use-flat-menus nil "Whether the constructed Imenu should be a list, rather than a tree." - :group 'pdf-outline :type '(choice (const :tag "Yes" t) (const :tag "No" nil))) (defcustom pdf-outline-display-buffer-action '(nil . nil) "The display action used, when displaying the outline buffer." - :group 'pdf-outline :type display-buffer--action-custom-type) (defcustom pdf-outline-display-labels nil "Whether the outline should display labels instead of page numbers. -Usually a page's label is it's displayed page number." - :group 'pdf-outline +Usually a page's label is its displayed page number." :type 'boolean) +(defcustom pdf-outline-fill-column fill-column + "The value of `fill-column' in pdf outline buffers. + +Set to nil to disable line wrapping." + :type 'integer) + (defvar pdf-outline-minor-mode-map (let ((km (make-sparse-keymap))) - (define-key km (kbd "o") 'pdf-outline) + (define-key km (kbd "o") #'pdf-outline) km) "Keymap used for `pdf-outline-minor-mode'.") (defvar pdf-outline-buffer-mode-map (let ((kmap (make-sparse-keymap))) (dotimes (i 10) - (define-key kmap (vector (+ i ?0)) 'digit-argument)) - (define-key kmap "-" 'negative-argument) - (define-key kmap (kbd "p") 'previous-line) - (define-key kmap (kbd "n") 'next-line) - (define-key kmap (kbd "b") 'outline-backward-same-level) - (define-key kmap (kbd "d") 'hide-subtree) - (define-key kmap (kbd "a") 'show-all) - (define-key kmap (kbd "s") 'show-subtree) - (define-key kmap (kbd "f") 'outline-forward-same-level) - (define-key kmap (kbd "u") 'pdf-outline-up-heading) - (define-key kmap (kbd "Q") 'hide-sublevels) - (define-key kmap (kbd "<") 'beginning-of-buffer) - (define-key kmap (kbd ">") 'pdf-outline-end-of-buffer) - (define-key kmap (kbd "TAB") 'outline-toggle-children) - (define-key kmap (kbd "RET") 'pdf-outline-follow-link) - (define-key kmap (kbd "C-o") 'pdf-outline-display-link) - (define-key kmap (kbd "SPC") 'pdf-outline-display-link) - (define-key kmap [mouse-1] 'pdf-outline-mouse-display-link) - (define-key kmap (kbd "o") 'pdf-outline-select-pdf-window) - (define-key kmap (kbd ".") 'pdf-outline-move-to-current-page) - ;; (define-key kmap (kbd "Q") 'pdf-outline-quit) - (define-key kmap (kbd "C-c C-q") 'pdf-outline-quit-and-kill) - (define-key kmap (kbd "q") 'quit-window) - (define-key kmap (kbd "M-RET") 'pdf-outline-follow-link-and-quit) - (define-key kmap (kbd "C-c C-f") 'pdf-outline-follow-mode) + (define-key kmap (vector (+ i ?0)) #'digit-argument)) + (define-key kmap "-" #'negative-argument) + (define-key kmap (kbd "p") #'previous-line) + (define-key kmap (kbd "n") #'next-line) + (define-key kmap (kbd "b") #'outline-backward-same-level) + (define-key kmap (kbd "d") #'hide-subtree) + (define-key kmap (kbd "a") #'show-all) + (define-key kmap (kbd "s") #'show-subtree) + (define-key kmap (kbd "f") #'outline-forward-same-level) + (define-key kmap (kbd "u") #'pdf-outline-up-heading) + (define-key kmap (kbd "Q") #'hide-sublevels) + (define-key kmap (kbd "<") #'beginning-of-buffer) + (define-key kmap (kbd ">") #'pdf-outline-end-of-buffer) + (define-key kmap (kbd "TAB") #'outline-toggle-children) + (define-key kmap (kbd "RET") #'pdf-outline-follow-link) + (define-key kmap (kbd "C-o") #'pdf-outline-display-link) + (define-key kmap (kbd "SPC") #'pdf-outline-display-link) + (define-key kmap [mouse-1] #'pdf-outline-mouse-display-link) + (define-key kmap (kbd "o") #'pdf-outline-select-pdf-window) + (define-key kmap (kbd ".") #'pdf-outline-move-to-current-page) + ;; (define-key kmap (kbd "Q") #'pdf-outline-quit) + (define-key kmap (kbd "C-c C-q") #'pdf-outline-quit-and-kill) + (define-key kmap (kbd "q") #'quit-window) + (define-key kmap (kbd "M-RET") #'pdf-outline-follow-link-and-quit) + (define-key kmap (kbd "C-c C-f") #'pdf-outline-follow-mode) kmap) "Keymap used in `pdf-outline-buffer-mode'.") @@ -141,7 +141,7 @@ Additionally the same outline may be viewed in a designated buffer. \\{pdf-outline-minor-mode-map}" - nil nil nil + :group 'pdf-outline (pdf-util-assert-pdf-buffer) (cond (pdf-outline-minor-mode @@ -155,7 +155,7 @@ buffer. "View and traverse the outline of a PDF file. Press \\[pdf-outline-display-link] to display the PDF document, -\\[pdf-outline-select-pdf-window] to select it's window, +\\[pdf-outline-select-pdf-window] to select its window, \\[pdf-outline-move-to-current-page] to move to the outline item of the current page, \\[pdf-outline-follow-link] to goto the corresponding page or \\[pdf-outline-follow-link-and-quit] to @@ -186,13 +186,13 @@ rebound to their respective last character. (define-minor-mode pdf-outline-follow-mode "Display links as point moves." - nil nil nil + :group 'pdf-outline (setq pdf-outline-follow-mode-last-link nil) (cond (pdf-outline-follow-mode - (add-hook 'post-command-hook 'pdf-outline-follow-mode-pch nil t)) + (add-hook 'post-command-hook #'pdf-outline-follow-mode-pch nil t)) (t - (remove-hook 'post-command-hook 'pdf-outline-follow-mode-pch t)))) + (remove-hook 'post-command-hook #'pdf-outline-follow-mode-pch t)))) (defun pdf-outline-follow-mode-pch () (let ((link (pdf-outline-link-at-pos (point)))) @@ -229,6 +229,7 @@ buffer, unless NO-SELECT-WINDOW-P is non-nil." (buffer-exists-p (get-buffer bname)) (buffer (get-buffer-create bname))) (with-current-buffer buffer + (setq-local fill-column pdf-outline-fill-column) (unless buffer-exists-p (when (= 0 (save-excursion (pdf-outline-insert-outline pdf-buffer))) @@ -313,7 +314,7 @@ Open nodes as necessary." (pdf-outline-move-to-page page))) (defun pdf-outline-quit-and-kill () - "Quit browsing the outline and kill it's buffer." + "Quit browsing the outline and kill its buffer." (interactive) (pdf-outline-quit t)) @@ -571,23 +572,6 @@ not call `imenu-sort-function'." (cons title (nconc (nreverse keep-at-top) menulist)))) -;; bugfix for imenu in Emacs 24.3 and below. -(when (condition-case nil - (progn (imenu--truncate-items '(("" 0))) nil) - (error t)) - (eval-after-load "imenu" - '(defun imenu--truncate-items (menulist) - "Truncate all strings in MENULIST to `imenu-max-item-length'." - (mapc (lambda (item) - ;; Truncate if necessary. - (when (and (numberp imenu-max-item-length) - (> (length (car item)) imenu-max-item-length)) - (setcar item (substring (car item) 0 imenu-max-item-length))) - (when (imenu--subalist-p item) - (imenu--truncate-items (cdr item)))) - menulist)))) - - (provide 'pdf-outline) diff --git a/elpa/pdf-tools-20191031.642/pdf-sync.el b/elpa/pdf-tools-20230611.239/pdf-sync.el similarity index 92% rename from elpa/pdf-tools-20191031.642/pdf-sync.el rename to elpa/pdf-tools-20230611.239/pdf-sync.el index bf40cdce..cfbc2a3b 100644 --- a/elpa/pdf-tools-20191031.642/pdf-sync.el +++ b/elpa/pdf-tools-20230611.239/pdf-sync.el @@ -21,8 +21,8 @@ ;; ;; The backward search uses a heuristic, which is pretty simple, but ;; effective: It extracts the text around the click-position in the -;; PDF, normalizes it's whitespace, deletes certain notorious -;; character and translates certain other character into their latex +;; PDF, normalizes its whitespace, deletes certain notorious +;; characters and translates certain other characters into their latex ;; equivalents. This transformed text is split into a series of ;; token. A similar operation is performed on the source code around ;; the position synctex points at. These two sequences of token are @@ -43,11 +43,10 @@ :group 'pdf-tools) (defcustom pdf-sync-forward-display-pdf-key "C-c C-g" - "Key to jump from a TeX buffer to it's PDF file. + "Key to jump from a TeX buffer to its PDF file. This key is added to `TeX-source-correlate-method', when command `pdf-sync-minor-mode' is activated and this map is defined." - :group 'pdf-sync :type 'key-sequence) (make-obsolete-variable @@ -58,7 +57,6 @@ command `pdf-sync-minor-mode' is activated and this map is defined." "Hook ran after going to a source location. The hook is run in the TeX buffer." - :group 'pdf-sync :type 'hook :options '(pdf-sync-backward-beginning-of-word)) @@ -66,17 +64,14 @@ The hook is run in the TeX buffer." "Hook ran after displaying the PDF buffer. The hook is run in the PDF's buffer." - :group 'pdf-sync :type 'hook) (defcustom pdf-sync-forward-display-action nil "Display action used when displaying PDF buffers." - :group 'pdf-sync :type 'display-buffer--action-custom-type) (defcustom pdf-sync-backward-display-action nil "Display action used when displaying TeX buffers." - :group 'pdf-sync :type 'display-buffer--action-custom-type) (defcustom pdf-sync-locate-synctex-file-functions nil @@ -86,13 +81,12 @@ Each function on this hook should accept a single argument: The absolute path of a PDF file. It should return the absolute path of the corresponding synctex database or nil, if it was unable to locate it." - :group 'pdf-sync :type 'hook) (defvar pdf-sync-minor-mode-map (let ((kmap (make-sparse-keymap))) - (define-key kmap [double-mouse-1] 'pdf-sync-backward-search-mouse) - (define-key kmap [C-mouse-1] 'pdf-sync-backward-search-mouse) + (define-key kmap [double-mouse-1] #'pdf-sync-backward-search-mouse) + (define-key kmap [C-mouse-1] #'pdf-sync-backward-search-mouse) kmap)) (defcustom pdf-sync-backward-redirect-functions nil @@ -110,7 +104,6 @@ none) values modified. AUCTeX installs a function here which changes the backward search location for synthetic `TeX-region' files back to the equivalent position in the original tex file." - :group 'pdf-sync :type '(repeat function)) @@ -120,20 +113,19 @@ position in the original tex file." \\ This works via SyncTeX, which means the TeX sources need to have been compiled with `--synctex=1'. In AUCTeX this can be done by -setting `TeX-source-correlate-method' to 'synctex \(before AUCTeX -is loaded\) and enabling `TeX-source-correlate-mode'. +setting `TeX-source-correlate-method' to `synctex' (before AUCTeX +is loaded) and enabling `TeX-source-correlate-mode'. -Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will open the -corresponding TeX location. +Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will +open the corresponding TeX location. If AUCTeX is your preferred tex-mode, this library arranges to -bind `pdf-sync-forward-display-pdf-key' \(the default is `C-c C-g'\) +bind `pdf-sync-forward-display-pdf-key' (the default is `C-c C-g') to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This function displays the PDF page corresponding to the current position in the TeX buffer. This function only works together with AUCTeX." - - nil nil nil + :group 'pdf-sync (pdf-util-assert-pdf-buffer)) @@ -146,7 +138,6 @@ with AUCTeX." If nil, just go where Synctex tells us. Otherwise try to find the exact location of the clicked-upon text in the PDF." - :group 'pdf-sync :type 'boolean) (defcustom pdf-sync-backward-text-translations @@ -258,13 +249,12 @@ the exact location of the clicked-upon text in the PDF." (9830 "diamondsuit")) "Alist mapping PDF character to a list of LaTeX macro names. -Adding a character here with it's LaTeX equivalent names allows -the heuristic backward search to find it's location in the source +Adding a character here with its LaTeX equivalent names allows +the heuristic backward search to find its location in the source file. These strings should not match `pdf-sync-backward-source-flush-regexp'. Has no effect if `pdf-sync-backward-use-heuristic' is nil." - :group 'pdf-sync :type '(alist :key-type character :value-type (repeat string))) @@ -321,7 +311,7 @@ point to the correct position." .line .column))) (cl-destructuring-bind (source line column) (or (save-selected-window - (apply 'run-hook-with-args-until-success + (apply #'run-hook-with-args-until-success 'pdf-sync-backward-redirect-functions data)) data) (list source @@ -430,8 +420,8 @@ point to the correct position." (need-suffix-space-p (memq char '(?\s ?\n))) ;; Figure out whether we missed a space by matching the ;; prefix's suffix with the line's prefix. Due to the text - ;; extraction in poppler, spaces are only inserted - ;; inbetween words. This test may fail, if prefix and line + ;; extraction in poppler, spaces are only inserted in + ;; between words. This test may fail, if prefix and line ;; do not overlap, which may happen in various cases, but ;; we don't care. (need-prefix-space-p @@ -539,23 +529,20 @@ word-level searching is desired." (define-minor-mode pdf-sync-backward-debug-minor-mode "Aid in debugging the backward search." - nil nil nil - (if (and (fboundp 'advice-add) - (fboundp 'advice-remove)) - (let ((functions - '(pdf-sync-backward-search - pdf-sync-backward--tokenize - pdf-util-seq-alignment))) - (cond - (pdf-sync-backward-debug-minor-mode - (dolist (fn functions) - (advice-add fn :around (apply-partially 'pdf-sync-backward-debug-wrapper - fn) - `((name . ,(format "%s-debug" fn)))))) - (t - (dolist (fn functions) - (advice-remove fn (format "%s-debug" fn)))))) - (error "Need Emacs version >= 24.4"))) + :group 'pdf-sync + (let ((functions + '(pdf-sync-backward-search + pdf-sync-backward--tokenize + pdf-util-seq-alignment))) + (cond + (pdf-sync-backward-debug-minor-mode + (dolist (fn functions) + (advice-add fn :around + (apply-partially #'pdf-sync-backward-debug-wrapper fn) + `((name . ,(format "%s-debug" fn)))))) + (t + (dolist (fn functions) + (advice-remove fn (format "%s-debug" fn))))))) (defun pdf-sync-backward-debug-explain () "Explain the last backward search. @@ -592,7 +579,7 @@ Needs to have `pdf-sync-backward-debug-minor-mode' enabled." (insert (mapconcat (lambda (elt) (if (consp elt) - (mapconcat 'identity elt or-sep) + (mapconcat #'identity elt or-sep) elt)) (nth 2 (cdr text)) " ")) (point))) @@ -605,7 +592,7 @@ Needs to have `pdf-sync-backward-debug-minor-mode' enabled." (insert (propertize "Source Token:" 'face 'font-lock-keyword-face)) (insert sep) (fill-region (point) - (progn (insert (mapconcat 'identity (nth 2 (cdr source)) " ")) + (progn (insert (mapconcat #'identity (nth 2 (cdr source)) " ")) (point))) (insert sep) @@ -618,7 +605,7 @@ Needs to have `pdf-sync-backward-debug-minor-mode' enabled." (dolist (a (cdr (cdr alignment))) (let* ((source (cdr a)) (text (if (consp (car a)) - (mapconcat 'identity (car a) or-sep) + (mapconcat #'identity (car a) or-sep) (car a))) (extend (max (length text) (length source)))) @@ -771,7 +758,7 @@ The first such filename is returned, or nil if none was found." (let ((syncname (match-string-no-properties 1))) (when (and (file-exists-p syncname) (file-equal-p filename syncname)) - (goto-char (point-at-bol)) + (goto-char (line-beginning-position)) (throw 'found syncname)))) (setq end beg beg (point-min)) diff --git a/elpa/pdf-tools-20230611.239/pdf-tools-autoloads.el b/elpa/pdf-tools-20230611.239/pdf-tools-autoloads.el new file mode 100644 index 00000000..a5cc8c12 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/pdf-tools-autoloads.el @@ -0,0 +1,637 @@ +;;; pdf-tools-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "pdf-annot" "pdf-annot.el" (0 0 0 0)) +;;; Generated autoloads from pdf-annot.el + +(autoload 'pdf-annot-minor-mode "pdf-annot" "\ +Support for PDF Annotations. + +This is a minor mode. If called interactively, toggle the +`Pdf-Annot minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-annot-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\\{pdf-annot-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-annot" '("pdf-annot-")) + +;;;*** + +;;;### (autoloads nil "pdf-cache" "pdf-cache.el" (0 0 0 0)) +;;; Generated autoloads from pdf-cache.el + +(register-definition-prefixes "pdf-cache" '("boundingbox" "define-pdf-cache-function" "page" "pdf-cache-" "textregions")) + +;;;*** + +;;;### (autoloads nil "pdf-dev" "pdf-dev.el" (0 0 0 0)) +;;; Generated autoloads from pdf-dev.el + +(register-definition-prefixes "pdf-dev" '("pdf-dev-")) + +;;;*** + +;;;### (autoloads nil "pdf-history" "pdf-history.el" (0 0 0 0)) +;;; Generated autoloads from pdf-history.el + +(autoload 'pdf-history-minor-mode "pdf-history" "\ +Keep a history of previously visited pages. + +This is a minor mode. If called interactively, toggle the +`Pdf-History minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-history-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This is a simple stack-based history. Turning the page or +following a link pushes the left-behind page on the stack, which +may be navigated with the following keys. + +\\{pdf-history-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-history" '("pdf-history-")) + +;;;*** + +;;;### (autoloads nil "pdf-info" "pdf-info.el" (0 0 0 0)) +;;; Generated autoloads from pdf-info.el + +(register-definition-prefixes "pdf-info" '("pdf-info-")) + +;;;*** + +;;;### (autoloads nil "pdf-isearch" "pdf-isearch.el" (0 0 0 0)) +;;; Generated autoloads from pdf-isearch.el + +(autoload 'pdf-isearch-minor-mode "pdf-isearch" "\ +Isearch mode for PDF buffer. + +This is a minor mode. If called interactively, toggle the +`Pdf-Isearch minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-isearch-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +When this mode is enabled \\[isearch-forward], among other keys, +starts an incremental search in this PDF document. Since this mode +uses external programs to highlight found matches via +image-processing, proceeding to the next match may be slow. + +Therefore two isearch behaviours have been defined: Normal isearch and +batch mode. The later one is a minor mode +\(`pdf-isearch-batch-mode'), which when activated inhibits isearch +from stopping at and highlighting every single match, but rather +display them batch-wise. Here a batch means a number of matches +currently visible in the selected window. + +The kind of highlighting is determined by three faces +`pdf-isearch-match' (for the current match), `pdf-isearch-lazy' +\(for all other matches) and `pdf-isearch-batch' (when in batch +mode), which see. + +Colors may also be influenced by the minor-mode +`pdf-view-dark-minor-mode'. If this is minor mode enabled, each face's +dark colors, are used (see e.g. `frame-background-mode'), instead +of the light ones. + +\\{pdf-isearch-minor-mode-map} +While in `isearch-mode' the following keys are available. Note +that not every isearch command work as expected. + +\\{pdf-isearch-active-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-isearch" '("pdf-isearch-")) + +;;;*** + +;;;### (autoloads nil "pdf-links" "pdf-links.el" (0 0 0 0)) +;;; Generated autoloads from pdf-links.el + +(autoload 'pdf-links-minor-mode "pdf-links" "\ +Handle links in PDF documents.\\ + +This is a minor mode. If called interactively, toggle the +`Pdf-Links minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-links-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +If this mode is enabled, most links in the document may be +activated by clicking on them or by pressing \\[pdf-links-action-perform] and selecting +one of the displayed keys, or by using isearch limited to +links via \\[pdf-links-isearch-link]. + +\\{pdf-links-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-links-action-perform "pdf-links" "\ +Follow LINK, depending on its type. + +This may turn to another page, switch to another PDF buffer or +invoke `pdf-links-browse-uri-function'. + +Interactively, link is read via `pdf-links-read-link-action'. +This function displays characters around the links in the current +page and starts reading characters (ignoring case). After a +sufficient number of characters have been read, the corresponding +link's link is invoked. Additionally, SPC may be used to +scroll the current page. + +\(fn LINK)" t nil) + +(register-definition-prefixes "pdf-links" '("pdf-links-")) + +;;;*** + +;;;### (autoloads nil "pdf-loader" "pdf-loader.el" (0 0 0 0)) +;;; Generated autoloads from pdf-loader.el + +(autoload 'pdf-loader-install "pdf-loader" "\ +Prepare Emacs for using PDF Tools. + +This function acts as a replacement for `pdf-tools-install' and +makes Emacs load and use PDF Tools as soon as a PDF file is +opened, but not sooner. + +The arguments are passed verbatim to `pdf-tools-install', which +see. + +\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" nil nil) + +(register-definition-prefixes "pdf-loader" '("pdf-loader--")) + +;;;*** + +;;;### (autoloads nil "pdf-macs" "pdf-macs.el" (0 0 0 0)) +;;; Generated autoloads from pdf-macs.el + +(register-definition-prefixes "pdf-macs" '("pdf-view-")) + +;;;*** + +;;;### (autoloads nil "pdf-misc" "pdf-misc.el" (0 0 0 0)) +;;; Generated autoloads from pdf-misc.el + +(autoload 'pdf-misc-minor-mode "pdf-misc" "\ +FIXME: Not documented. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-size-indication-minor-mode "pdf-misc" "\ +Provide a working size indication in the mode-line. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Size-Indication minor mode' mode. If the prefix +argument is positive, enable the mode, and if it is zero or +negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-size-indication-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-menu-bar-minor-mode "pdf-misc" "\ +Display a PDF Tools menu in the menu-bar. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Menu-Bar minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-menu-bar-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-context-menu-minor-mode "pdf-misc" "\ +Provide a right-click context menu in PDF buffers. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Context-Menu minor mode' mode. If the prefix argument +is positive, enable the mode, and if it is zero or negative, +disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-context-menu-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\\{pdf-misc-context-menu-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-misc" '("pdf-misc-")) + +;;;*** + +;;;### (autoloads nil "pdf-occur" "pdf-occur.el" (0 0 0 0)) +;;; Generated autoloads from pdf-occur.el + +(autoload 'pdf-occur "pdf-occur" "\ +List lines matching STRING or PCRE. + +Interactively search for a regexp. Unless a prefix arg was given, +in which case this functions performs a string search. + +If `pdf-occur-prefer-string-search' is non-nil, the meaning of +the prefix-arg is inverted. + +\(fn STRING &optional REGEXP-P)" t nil) + +(autoload 'pdf-occur-multi-command "pdf-occur" "\ +Perform `pdf-occur' on multiple buffer. + +For a programmatic search of multiple documents see +`pdf-occur-search'." t nil) + +(defvar pdf-occur-global-minor-mode nil "\ +Non-nil if Pdf-Occur-Global minor mode is enabled. +See the `pdf-occur-global-minor-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pdf-occur-global-minor-mode'.") + +(custom-autoload 'pdf-occur-global-minor-mode "pdf-occur" nil) + +(autoload 'pdf-occur-global-minor-mode "pdf-occur" "\ +Enable integration of Pdf Occur with other modes. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Global minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='pdf-occur-global-minor-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This global minor mode enables (or disables) +`pdf-occur-ibuffer-minor-mode' and `pdf-occur-dired-minor-mode' +in all current and future ibuffer/dired buffer. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-occur-ibuffer-minor-mode "pdf-occur" "\ +Hack into ibuffer's do-occur binding. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Ibuffer minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-occur-ibuffer-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This mode remaps `ibuffer-do-occur' to +`pdf-occur-ibuffer-do-occur', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `ibuffer-do-occur'. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-occur-dired-minor-mode "pdf-occur" "\ +Hack into dired's `dired-do-search' binding. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Dired minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-occur-dired-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This mode remaps `dired-do-search' to +`pdf-occur-dired-do-search', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `dired-do-search'. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-occur" '("pdf-occur-")) + +;;;*** + +;;;### (autoloads nil "pdf-outline" "pdf-outline.el" (0 0 0 0)) +;;; Generated autoloads from pdf-outline.el + +(autoload 'pdf-outline-minor-mode "pdf-outline" "\ +Display an outline of a PDF document. + +This is a minor mode. If called interactively, toggle the +`Pdf-Outline minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-outline-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This provides a PDF's outline on the menu bar via imenu. +Additionally the same outline may be viewed in a designated +buffer. + +\\{pdf-outline-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-outline "pdf-outline" "\ +Display an PDF outline of BUFFER. + +BUFFER defaults to the current buffer. Select the outline +buffer, unless NO-SELECT-WINDOW-P is non-nil. + +\(fn &optional BUFFER NO-SELECT-WINDOW-P)" t nil) + +(autoload 'pdf-outline-imenu-enable "pdf-outline" "\ +Enable imenu in the current PDF buffer." t nil) + +(register-definition-prefixes "pdf-outline" '("pdf-outline")) + +;;;*** + +;;;### (autoloads nil "pdf-sync" "pdf-sync.el" (0 0 0 0)) +;;; Generated autoloads from pdf-sync.el + +(autoload 'pdf-sync-minor-mode "pdf-sync" "\ +Correlate a PDF position with the TeX file. +\\ +This works via SyncTeX, which means the TeX sources need to have +been compiled with `--synctex=1'. In AUCTeX this can be done by +setting `TeX-source-correlate-method' to `synctex' (before AUCTeX +is loaded) and enabling `TeX-source-correlate-mode'. + +This is a minor mode. If called interactively, toggle the +`Pdf-Sync minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-sync-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will +open the corresponding TeX location. + +If AUCTeX is your preferred tex-mode, this library arranges to +bind `pdf-sync-forward-display-pdf-key' (the default is `C-c C-g') +to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This +function displays the PDF page corresponding to the current +position in the TeX buffer. This function only works together +with AUCTeX. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-sync" '("pdf-sync-")) + +;;;*** + +;;;### (autoloads nil "pdf-tools" "pdf-tools.el" (0 0 0 0)) +;;; Generated autoloads from pdf-tools.el + +(defvar pdf-tools-handle-upgrades t "\ +Whether PDF Tools should handle upgrading itself.") + +(custom-autoload 'pdf-tools-handle-upgrades "pdf-tools" t) + +(autoload 'pdf-tools-install "pdf-tools" "\ +Install PDF-Tools in all current and future PDF buffers. + +If the `pdf-info-epdfinfo-program' is not running or does not +appear to be working, attempt to rebuild it. If this build +succeeded, continue with the activation of the package. +Otherwise fail silently, i.e. no error is signaled. + +Build the program (if necessary) without asking first, if +NO-QUERY-P is non-nil. + +Don't attempt to install system packages, if SKIP-DEPENDENCIES-P +is non-nil. + +Do not signal an error in case the build failed, if NO-ERROR-P is +non-nil. + +Attempt to install system packages (even if it is deemed +unnecessary), if FORCE-DEPENDENCIES-P is non-nil. + +Note that SKIP-DEPENDENCIES-P and FORCE-DEPENDENCIES-P are +mutually exclusive. + +Note further, that you can influence the installation directory +by setting `pdf-info-epdfinfo-program' to an appropriate +value (e.g. ~/bin/epdfinfo) before calling this function. + +See `pdf-view-mode' and `pdf-tools-enabled-modes'. + +\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" t nil) + +(autoload 'pdf-tools-enable-minor-modes "pdf-tools" "\ +Enable MODES in the current buffer. + +MODES defaults to `pdf-tools-enabled-modes'. + +\(fn &optional MODES)" t nil) + +(autoload 'pdf-tools-help "pdf-tools" "\ +Show a Help buffer for `pdf-tools'." t nil) + +(register-definition-prefixes "pdf-tools" '("pdf-tools-")) + +;;;*** + +;;;### (autoloads nil "pdf-util" "pdf-util.el" (0 0 0 0)) +;;; Generated autoloads from pdf-util.el + +(register-definition-prefixes "pdf-util" '("display-buffer-split-below-and-attach" "pdf-util-")) + +;;;*** + +;;;### (autoloads nil "pdf-view" "pdf-view.el" (0 0 0 0)) +;;; Generated autoloads from pdf-view.el + +(autoload 'pdf-view-bookmark-jump-handler "pdf-view" "\ +The bookmark handler-function interface for bookmark BMK. + +See also `pdf-view-bookmark-make-record'. + +\(fn BMK)" nil nil) + +(register-definition-prefixes "pdf-view" '("cua-copy-region--pdf-view-advice" "pdf-view-")) + +;;;*** + +;;;### (autoloads nil "pdf-virtual" "pdf-virtual.el" (0 0 0 0)) +;;; Generated autoloads from pdf-virtual.el + +(autoload 'pdf-virtual-edit-mode "pdf-virtual" "\ +Major mode when editing a virtual PDF buffer. + +\(fn)" t nil) + +(autoload 'pdf-virtual-view-mode "pdf-virtual" "\ +Major mode in virtual PDF buffers. + +\(fn)" t nil) + +(defvar pdf-virtual-global-minor-mode nil "\ +Non-nil if Pdf-Virtual-Global minor mode is enabled. +See the `pdf-virtual-global-minor-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pdf-virtual-global-minor-mode'.") + +(custom-autoload 'pdf-virtual-global-minor-mode "pdf-virtual" nil) + +(autoload 'pdf-virtual-global-minor-mode "pdf-virtual" "\ +Enable recognition and handling of VPDF files. + +This is a minor mode. If called interactively, toggle the +`Pdf-Virtual-Global minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='pdf-virtual-global-minor-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-virtual-buffer-create "pdf-virtual" "\ + + +\(fn &optional FILENAMES BUFFER-NAME DISPLAY-P)" t nil) + +(register-definition-prefixes "pdf-virtual" '("pdf-virtual-")) + +;;;*** + +;;;### (autoloads nil nil ("pdf-tools-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; pdf-tools-autoloads.el ends here diff --git a/elpa/pdf-tools-20230611.239/pdf-tools-pkg.el b/elpa/pdf-tools-20230611.239/pdf-tools-pkg.el new file mode 100644 index 00000000..80486a76 --- /dev/null +++ b/elpa/pdf-tools-20230611.239/pdf-tools-pkg.el @@ -0,0 +1,16 @@ +(define-package "pdf-tools" "20230611.239" "Support library for PDF documents" + '((emacs "26.3") + (tablist "1.0") + (let-alist "1.0.4")) + :commit "c69e7656a4678fe25afbd29f3503dd19ee7f9896" :authors + '(("Andreas Politz" . "mail@andreas-politz.de")) + :maintainers + '(("Vedang Manerikar" . "vedang.manerikar@gmail.com")) + :maintainer + '("Vedang Manerikar" . "vedang.manerikar@gmail.com") + :keywords + '("files" "multimedia") + :url "http://github.com/vedang/pdf-tools/") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/pdf-tools-20191031.642/pdf-tools.el b/elpa/pdf-tools-20230611.239/pdf-tools.el similarity index 89% rename from elpa/pdf-tools-20191031.642/pdf-tools.el rename to elpa/pdf-tools-20230611.239/pdf-tools.el index e512fd1d..62113697 100644 --- a/elpa/pdf-tools-20191031.642/pdf-tools.el +++ b/elpa/pdf-tools-20230611.239/pdf-tools.el @@ -1,12 +1,14 @@ -;;; pdf-tools.el --- Support library for PDF documents. -*- lexical-binding:t -*- +;;; pdf-tools.el --- Support library for PDF documents -*- lexical-binding:t -*- ;; Copyright (C) 2013, 2014 Andreas Politz -;; Author: Andreas Politz +;; Author: Andreas Politz +;; Maintainer: Vedang Manerikar +;; URL: http://github.com/vedang/pdf-tools/ ;; Keywords: files, multimedia ;; Package: pdf-tools -;; Version: 1.0 -;; Package-Requires: ((emacs "24.3") (tablist "1.0") (let-alist "1.0.4")) +;; Version: 1.1.0 +;; Package-Requires: ((emacs "26.3") (tablist "1.0") (let-alist "1.0.4")) ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -28,8 +30,11 @@ ;; e.g. ghostscript and stored in the file-system, but rather created ;; on-demand and stored in memory. ;; -;; Note: This package requires external libraries and works currently -;; only on GNU/Linux systems. +;; Note: This package is built and tested on GNU/Linux systems. It +;; works on macOS and Windows, but is officially supported only on +;; GNU/Linux systems. This package will not make macOS or Windows +;; specific functionality changes, behaviour on these systems is +;; provided as-is. ;; ;; Note: If you ever update it, you need to restart Emacs afterwards. ;; @@ -68,7 +73,7 @@ ;; back to the PDF file. ;; ;; * Attachments -;; Save files attached to the PDF-file or list them in a dired buffer. +;; Save files attached to the PDF-file or list them in a Dired buffer. ;; ;; * Outline ;; Use imenu or a special buffer to examine and navigate the PDF's @@ -140,9 +145,7 @@ In order to customize dark and light colors use pdf-sync-minor-mode pdf-misc-context-menu-minor-mode pdf-cache-prefetch-minor-mode - pdf-occur-global-minor-mode - ;; pdf-virtual-global-minor-mode - ) + pdf-occur-global-minor-mode) "A list of automatically enabled minor-modes. PDF Tools is build as a series of minor-modes. This variable and @@ -234,6 +237,7 @@ Returns a appropriate directory or nil. See also (list default-directory (expand-file-name "build/server" pdf-tools-directory) (expand-file-name "server") + (expand-file-name "server" pdf-tools-directory) (expand-file-name "../server" pdf-tools-directory)))) (defun pdf-tools-msys2-directory (&optional noninteractive-p) @@ -290,7 +294,7 @@ Install into TARGET-DIRECTORY, which should be a directory. If CALLBACK is non-nil, it should be a function. It is called with the compiled executable as the single argument or nil, if -the build falied. +the build failed. Expect sources to be in BUILD-DIRECTORY. If nil, search for it using `pdf-tools-locate-build-directory'. @@ -303,10 +307,11 @@ Returns the buffer of the compilation process." (unless callback (setq callback #'ignore)) (unless build-directory (setq build-directory (pdf-tools-locate-build-directory))) - (cl-check-type target-directory file-directory) + (cl-check-type target-directory (satisfies file-directory-p)) (setq target-directory (file-name-as-directory (expand-file-name target-directory))) - (cl-check-type build-directory (and (not null) file-directory)) + (cl-check-type build-directory (and (not null) + (satisfies file-directory-p))) (when (and skip-dependencies-p force-dependencies-p) (error "Can't simultaneously skip and force dependencies")) (let* ((compilation-auto-jump-to-first-error nil) @@ -424,13 +429,17 @@ See `pdf-view-mode' and `pdf-tools-enabled-modes'." (when (memq 'pdf-virtual-global-minor-mode pdf-tools-enabled-modes) (pdf-virtual-global-minor-mode 1)) - (add-hook 'pdf-view-mode-hook 'pdf-tools-enable-minor-modes) + (add-hook 'pdf-view-mode-hook #'pdf-tools-enable-minor-modes) (dolist (buf (buffer-list)) - (with-current-buffer buf - (when (and (not (derived-mode-p 'pdf-view-mode)) - (pdf-tools-pdf-buffer-p) - (buffer-file-name)) - (pdf-view-mode))))) + ;; This when check should not be necessary, but somehow dead + ;; buffers are showing up here. See + ;; https://github.com/vedang/pdf-tools/pull/93 + (when (buffer-live-p buf) + (with-current-buffer buf + (when (and (not (derived-mode-p 'pdf-view-mode)) + (pdf-tools-pdf-buffer-p) + (buffer-file-name)) + (pdf-view-mode)))))) (defun pdf-tools-uninstall () "Uninstall PDF-Tools in all current and future PDF buffers." @@ -442,7 +451,7 @@ See `pdf-view-mode' and `pdf-tools-enabled-modes'." (remove pdf-tools-magic-mode-alist-entry magic-mode-alist)) (pdf-occur-global-minor-mode -1) (pdf-virtual-global-minor-mode -1) - (remove-hook 'pdf-view-mode-hook 'pdf-tools-enable-minor-modes) + (remove-hook 'pdf-view-mode-hook #'pdf-tools-enable-minor-modes) (dolist (buf (buffer-list)) (with-current-buffer buf (when (pdf-util-pdf-buffer-p buf) @@ -450,7 +459,9 @@ See `pdf-view-mode' and `pdf-tools-enabled-modes'." (normal-mode))))) (defun pdf-tools-pdf-buffer-p (&optional buffer) - "Return non-nil if BUFFER contains a PDF document." + "Check if the current buffer is a PDF document. + +Optionally, take BUFFER as an argument and check if it is a PDF document." (save-current-buffer (when buffer (set-buffer buffer)) (save-excursion @@ -460,10 +471,14 @@ See `pdf-view-mode' and `pdf-tools-enabled-modes'." (looking-at "%PDF"))))) (defun pdf-tools-assert-pdf-buffer (&optional buffer) + "Throw an error if the current BUFFER does not contain a PDF document." (unless (pdf-tools-pdf-buffer-p buffer) (error "Buffer does not contain a PDF document"))) (defun pdf-tools-set-modes-enabled (enable &optional modes) + "Enable/Disable all the pdf-tools modes on the current buffer based on ENABLE. + +Accepts MODES as a optional argument to enable/disable specific modes." (dolist (m (or modes pdf-tools-enabled-modes)) (let ((enabled-p (and (boundp m) (symbol-value m)))) @@ -493,6 +508,7 @@ MODES defaults to `pdf-tools-enabled-modes'." ;;;###autoload (defun pdf-tools-help () + "Show a Help buffer for `pdf-tools'." (interactive) (help-setup-xref (list #'pdf-tools-help) (called-interactively-p 'interactive)) @@ -500,7 +516,7 @@ MODES defaults to `pdf-tools-enabled-modes'." (princ "PDF Tools Help\n\n") (princ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n") (dolist (m (cons 'pdf-view-mode - (sort (copy-sequence pdf-tools-modes) 'string<))) + (sort (copy-sequence pdf-tools-modes) #'string<))) (princ (format "`%s' is " m)) (describe-function-1 m) (terpri) (terpri) @@ -515,6 +531,7 @@ MODES defaults to `pdf-tools-enabled-modes'." "Non-nil, if debugging PDF Tools.") (defun pdf-tools-toggle-debug () + "Turn debugging on/off for pdf-tools." (interactive) (setq pdf-tools-debug (not pdf-tools-debug)) (when (called-interactively-p 'any) diff --git a/elpa/pdf-tools-20191031.642/pdf-util.el b/elpa/pdf-tools-20230611.239/pdf-util.el similarity index 83% rename from elpa/pdf-tools-20191031.642/pdf-util.el rename to elpa/pdf-tools-20230611.239/pdf-util.el index b5f3f556..1e3b7be5 100644 --- a/elpa/pdf-tools-20191031.642/pdf-util.el +++ b/elpa/pdf-tools-20230611.239/pdf-util.el @@ -25,6 +25,7 @@ ;;; Code: +(require 'pdf-macs) (require 'cl-lib) (require 'format-spec) (require 'faces) @@ -33,100 +34,10 @@ ;; which won't succeed, if pdf-view.el isn't loaded. (declare-function pdf-view-image-size "pdf-view") (declare-function pdf-view-image-offset "pdf-view") -(declare-function pdf-view-current-image "pdf-view") -(declare-function pdf-view-current-overlay "pdf-view") (declare-function pdf-cache-pagesize "pdf-cache") - (declare-function pdf-view-image-type "pdf-view") - -;; * ================================================================== * -;; * Compatibility with older Emacssen (< 25.1) -;; * ================================================================== * - -;; The with-file-modes macro is only available in recent Emacs -;; versions. -(eval-when-compile - (unless (fboundp 'with-file-modes) - (defmacro with-file-modes (modes &rest body) - "Execute BODY with default file permissions temporarily set to MODES. -MODES is as for `set-default-file-modes'." - (declare (indent 1) (debug t)) - (let ((umask (make-symbol "umask"))) - `(let ((,umask (default-file-modes))) - (unwind-protect - (progn - (set-default-file-modes ,modes) - ,@body) - (set-default-file-modes ,umask))))))) - -(unless (fboundp 'alist-get) ;;25.1 - (defun alist-get (key alist &optional default remove) - "Get the value associated to KEY in ALIST. -DEFAULT is the value to return if KEY is not found in ALIST. -REMOVE, if non-nil, means that when setting this element, we should -remove the entry if the new value is `eql' to DEFAULT." - (ignore remove) ;;Silence byte-compiler. - (let ((x (assq key alist))) - (if x (cdr x) default)))) - -(require 'register) -(unless (fboundp 'register-read-with-preview) - (defalias 'register-read-with-preview 'read-char - "Compatibility alias for pdf-tools.")) - -;; In Emacs 24.3 window-width does not have a PIXELWISE argument. -(defmacro pdf-util-window-pixel-width (&optional window) - "Return the width of WINDOW in pixel." - (if (< (cdr (subr-arity (symbol-function 'window-body-width))) 2) - (let ((window* (make-symbol "window"))) - `(let ((,window* ,window)) - (* (window-body-width ,window*) - (frame-char-width (window-frame ,window*))))) - `(window-body-width ,window t))) - -;; In Emacs 24.3 image-mode-winprops leads to infinite recursion. -(unless (or (> emacs-major-version 24) - (and (= emacs-major-version 24) - (>= emacs-minor-version 4))) - (require 'image-mode) - (defvar image-mode-winprops-original-function - (symbol-function 'image-mode-winprops)) - (eval-after-load "image-mode" - '(defun image-mode-winprops (&optional window cleanup) - (if (not (eq major-mode 'pdf-view-mode)) - (funcall image-mode-winprops-original-function - window cleanup) - (cond ((null window) - (setq window - (if (eq (current-buffer) (window-buffer)) (selected-window) t))) - ((eq window t)) - ((not (windowp window)) - (error "Not a window: %s" window))) - (when cleanup - (setq image-mode-winprops-alist - (delq nil (mapcar (lambda (winprop) - (let ((w (car-safe winprop))) - (if (or (not (windowp w)) (window-live-p w)) - winprop))) - image-mode-winprops-alist)))) - (let ((winprops (assq window image-mode-winprops-alist))) - ;; For new windows, set defaults from the latest. - (if winprops - ;; Move window to front. - (setq image-mode-winprops-alist - (cons winprops (delq winprops image-mode-winprops-alist))) - (setq winprops (cons window - (copy-alist (cdar image-mode-winprops-alist)))) - ;; Add winprops before running the hook, to avoid inf-loops if the hook - ;; triggers window-configuration-change-hook. - (setq image-mode-winprops-alist - (cons winprops image-mode-winprops-alist)) - (run-hook-with-args 'image-mode-new-window-functions winprops)) - winprops))))) - - ;; * ================================================================== * ;; * Transforming coordinates @@ -180,7 +91,7 @@ else return the scaled singleton." (defun pdf-util-scale-to (list-of-edges from to &optional rounding-fn) "Scale LIST-OF-EDGES in FROM basis to TO. -FROM and TO should both be a cons \(WIDTH . HEIGTH\). See also +FROM and TO should both be a cons \(WIDTH . HEIGHT\). See also `pdf-util-scale'." (pdf-util-scale list-of-edges @@ -304,6 +215,42 @@ See `pdf-util-scale' for the LIST-OF-EDGES-OR-POS argument." result (car result))))) +(defmacro pdf-util-with-edges (list-of-edges &rest body) + "Provide some convenient macros for the edges in LIST-OF-EDGES. + +LIST-OF-EDGES should be a list of variables \(X ...\), each one +holding a list of edges. Inside BODY the symbols X-left, X-top, +X-right, X-bot, X-width and X-height expand to their respective +values." + + (declare (indent 1) (debug (sexp &rest form))) + (unless (cl-every 'symbolp list-of-edges) + (error "Argument should be a list of symbols")) + (let ((list-of-syms + (mapcar (lambda (edge) + (cons edge (mapcar + (lambda (kind) + (intern (format "%s-%s" edge kind))) + '(left top right bot width height)))) + list-of-edges))) + (macroexpand-all + `(cl-symbol-macrolet + ,(apply #'nconc + (mapcar + (lambda (edge-syms) + (let ((edge (nth 0 edge-syms)) + (syms (cdr edge-syms))) + `((,(pop syms) (nth 0 ,edge)) + (,(pop syms) (nth 1 ,edge)) + (,(pop syms) (nth 2 ,edge)) + (,(pop syms) (nth 3 ,edge)) + (,(pop syms) (- (nth 2 ,edge) + (nth 0 ,edge))) + (,(pop syms) (- (nth 3 ,edge) + (nth 1 ,edge)))))) + list-of-syms)) + ,@body)))) + (defun pdf-util-edges-transform (region elts &optional to-region-p) "Translate ELTS according to REGION. @@ -356,43 +303,6 @@ depending on the input." result (car result)))))) -(defmacro pdf-util-with-edges (list-of-edges &rest body) - "Provide some convenient macros for the edges in LIST-OF-EDGES. - -LIST-OF-EDGES should be a list of variables \(X ...\), each one -holding a list of edges. Inside BODY the symbols X-left, X-top, -X-right, X-bot, X-width and X-height expand to their respective -values." - - (declare (indent 1) (debug (sexp &rest form))) - (unless (cl-every 'symbolp list-of-edges) - (error "Argument should be a list of symbols")) - (let ((list-of-syms - (mapcar (lambda (edge) - (cons edge (mapcar - (lambda (kind) - (intern (format "%s-%s" edge kind))) - '(left top right bot width height)))) - list-of-edges))) - (macroexpand-all - `(cl-symbol-macrolet - ,(apply 'nconc - (mapcar - (lambda (edge-syms) - (let ((edge (nth 0 edge-syms)) - (syms (cdr edge-syms))) - `((,(pop syms) (nth 0 ,edge)) - (,(pop syms) (nth 1 ,edge)) - (,(pop syms) (nth 2 ,edge)) - (,(pop syms) (nth 3 ,edge)) - (,(pop syms) (- (nth 2 ,edge) - (nth 0 ,edge))) - (,(pop syms) (- (nth 3 ,edge) - (nth 1 ,edge)))))) - list-of-syms)) - ,@body)))) - - ;; * ================================================================== * ;; * Scrolling ;; * ================================================================== * @@ -416,10 +326,10 @@ Returns a list of pixel edges." (+ x0 (- (nth 2 edges) (nth 0 edges))))) (y1 (min (cdr isize) (+ y0 (- (nth 3 edges) (nth 1 edges)))))) - (mapcar 'round (list x0 y0 x1 y1)))) + (mapcar #'round (list x0 y0 x1 y1)))) (defun pdf-util-required-hscroll (edges &optional eager-p context-pixel) - "Return the amount of scrolling nescessary, to make image EDGES visible. + "Return the amount of scrolling necessary, to make image EDGES visible. Scroll as little as necessary. Unless EAGER-P is non-nil, in which case scroll as much as possible. @@ -458,7 +368,7 @@ needed." (frame-char-width))))))))) (defun pdf-util-required-vscroll (edges &optional eager-p context-pixel) - "Return the amount of scrolling nescessary, to make image EDGES visible. + "Return the amount of scrolling necessary, to make image EDGES visible. Scroll as little as necessary. Unless EAGER-P is non-nil, in which case scroll as much as possible. @@ -467,9 +377,11 @@ Keep CONTEXT-PIXEL pixel of the image visible at the bottom and top of the window. CONTEXT-PIXEL defaults to an equivalent pixel value of `next-screen-context-lines'. -Return the required vscroll in lines or nil, if scrolling is not -needed." +Return the required vscroll in pixels or nil, if scrolling is not +needed. +Note: For versions of emacs before 27 this will return lines instead of +pixels. This is because of a change that occurred to `image-mode' in 27." (pdf-util-assert-pdf-window) (let* ((win (window-inside-pixel-edges)) (image-height (cdr (pdf-view-image-size t))) @@ -483,20 +395,28 @@ needed." (frame-char-height)))) ;;Be careful not to modify edges. (edges-top (- edges-top context-pixel)) - (edges-bot (+ edges-bot context-pixel))) - (if (< edges-top image-top) - (round (/ (max 0 (if eager-p - (- edges-bot win-height) - edges-top)) - (float (frame-char-height)))) - (if (> (min image-height - edges-bot) - (+ image-top win-height)) - (round (/ (min (- image-height win-height) - (if eager-p - edges-top - (- edges-bot win-height))) - (float (frame-char-height)))))))))) + (edges-bot (+ edges-bot context-pixel)) + (vscroll + (cond ((< edges-top image-top) + (max 0 (if eager-p + (- edges-bot win-height) + edges-top))) + ((> (min image-height + edges-bot) + (+ image-top win-height)) + (min (- image-height win-height) + (if eager-p + edges-top + (- edges-bot win-height))))))) + + + (when vscroll + (round + ;; `image-set-window-vscroll' changed in version 27 to using + ;; pixels, not lines. + (if (version< emacs-version "27") + (/ vscroll (float (frame-char-height))) + vscroll))))))) (defun pdf-util-scroll-to-edges (edges &optional eager-p) "Scroll window such that image EDGES are visible. @@ -549,14 +469,9 @@ killed." (let ((temporary-file-directory pdf-util--base-directory)) (setq pdf-util--dedicated-directory - (make-temp-file (convert-standard-filename - (concat (if buffer-file-name - (file-name-nondirectory - buffer-file-name) - (buffer-name)) - "-")) + (make-temp-file (convert-standard-filename (pdf-util-temp-prefix)) t)) - (add-hook 'kill-buffer-hook 'pdf-util-delete-dedicated-directory + (add-hook 'kill-buffer-hook #'pdf-util-delete-dedicated-directory nil t))) pdf-util--dedicated-directory)) @@ -568,13 +483,21 @@ killed." "Expand filename against current buffer's dedicated directory." (expand-file-name name (pdf-util-dedicated-directory))) -(defun pdf-util-make-temp-file (prefix &optional dir-flag suffix) +(defun pdf-util-temp-prefix () + "Create a temp-file prefix for the current buffer" + (concat (if buffer-file-name + (file-name-nondirectory buffer-file-name) + (replace-regexp-in-string "[^[:alnum:]]+" "-" (buffer-name))) + "-")) + +(defun pdf-util-make-temp-file (&optional prefix dir-flag suffix) "Create a temporary file in current buffer's dedicated directory. See `make-temp-file' for the arguments." - (let ((temporary-file-directory - (pdf-util-dedicated-directory))) - (make-temp-file (convert-standard-filename prefix) dir-flag suffix))) + (let ((temporary-file-directory (pdf-util-dedicated-directory))) + (make-temp-file (convert-standard-filename + (or prefix (pdf-util-temp-prefix))) + dir-flag suffix))) ;; * ================================================================== * @@ -630,14 +553,14 @@ is non-nil." (defun pdf-util-hexcolor (color) "Return COLOR in hex-format. -Singal an error, if color is invalid." +Signal an error, if color is invalid." (if (string-match "\\`#[[:xdigit:]]\\{6\\}\\'" color) color (let ((values (color-values color))) (unless values (signal 'wrong-type-argument (list 'color-defined-p color))) - (apply 'format "#%02x%02x%02x" - (mapcar (lambda (c) (lsh c -8)) + (apply #'format "#%02x%02x%02x" + (mapcar (lambda (c) (ash c -8)) values))))) (defun pdf-util-highlight-regexp-in-string (regexp string &optional face) @@ -658,6 +581,8 @@ string." 'face (or face 'match)))) (buffer-string))) +(autoload 'list-colors-duplicates "facemenu") + (defun pdf-util-color-completions () "Return a fontified list of defined colors." (let ((color-list (list-colors-duplicates)) @@ -678,6 +603,10 @@ string." ,@tooltip-frame-parameters))) (tooltip-show text))) +;; FIXME: Defined in `pdf-view' but we can't require it here because it +;; requires us :-( +(defvar pdf-view-midnight-colors) + (defun pdf-util-tooltip-arrow (image-top &optional timeout) (pdf-util-assert-pdf-window) (when (floatp image-top) @@ -713,14 +642,18 @@ string." 'face `(:foreground "orange red" :background - ,(if (bound-and-true-p pdf-view-midnight-minor-mode) - (cdr pdf-view-midnight-colors) - "white")))) + ,(cond + ((bound-and-true-p pdf-view-midnight-minor-mode) + (cdr pdf-view-midnight-colors)) + ((bound-and-true-p pdf-view-themed-minor-mode) + (face-background 'default nil)) + (t "white"))))) dx dy))) (defvar pdf-util--face-colors-cache (make-hash-table)) -(defadvice enable-theme (after pdf-util-clear-faces-cache activate) +(advice-add 'enable-theme :after #'pdf-util--clear-faces-cache) +(defun pdf-util--clear-faces-cache (&rest _) (clrhash pdf-util--face-colors-cache)) (defun pdf-util-face-colors (face &optional dark-p) @@ -747,7 +680,7 @@ colors, otherwise light." (let ((colors (cons (face-attribute face :foreground nil 'default) (face-attribute face :background nil 'default)))) - (puthash face `(,(mapcar 'copy-sequence spec) + (puthash face `(,(mapcar #'copy-sequence spec) ((,bg . ,colors) ,@color-alist)) pdf-util--face-colors-cache) colors) @@ -837,22 +770,21 @@ trailing 2 is ignored. The other possible values have similar effects. The default is nil, which means to match the whole sequences. -Return a cons \(VALUE . ALINGMENT\), where VALUE says how similar -the sequences are and ALINGMENT is a list of \(E1 . E2\), where +Return a cons \(VALUE . ALIGNMENT\), where VALUE says how similar +the sequences are and ALIGNMENT is a list of \(E1 . E2\), where E1 is an element from SEQ1 or nil, likewise for E2. If one of them is nil, it means there is gap at this position in the respective sequence." (cl-macrolet ((make-matrix (rows columns) - (list 'apply (list 'quote 'vector) - (list 'cl-loop 'for 'i 'from 1 'to rows - 'collect (list 'make-vector columns nil)))) + `(apply #'vector + (cl-loop for i from 1 to ,rows + collect (make-vector ,columns nil)))) (mset (matrix row column newelt) - (list 'aset (list 'aref matrix row) column newelt)) + `(aset (aref ,matrix ,row) ,column ,newelt)) (mref (matrix row column) - (list 'aref (list 'aref matrix row) column))) - (let* ((nil-value nil) - (len1 (length seq1)) + `(aref (aref ,matrix ,row) ,column))) + (let* ((len1 (length seq1)) (len2 (length seq2)) (d (make-matrix (1+ len1) (1+ len2))) (prefix-p (memq alignment-type '(prefix infix))) @@ -888,7 +820,7 @@ respective sequence." (= (mref d i j) (1- (mref d (1- i) j)))) (cl-decf i) - (push (cons (elt seq1 i) nil-value) alignment)) + (push (cons (elt seq1 i) nil) alignment)) ((and (> j 0) (= (mref d i j) (+ (mref d i (1- j)) @@ -896,13 +828,14 @@ respective sequence." (and (= i len1) prefix-p)) 0 -1)))) (cl-decf j) - (push (cons nil-value (elt seq2 j)) alignment)) + (push (cons nil (elt seq2 j)) alignment)) (t (cl-assert (and (> i 0) (> j 0)) t) (cl-decf i) (cl-decf j) (push (cons (elt seq1 i) - (elt seq2 j)) alignment)))) + (elt seq2 j)) + alignment)))) (cons (mref d len1 len2) alignment))))) @@ -919,32 +852,39 @@ See also `regexp-quote'." (when (memq ch to-escape) (push ?\\ escaped)) (push ch escaped)) - (apply 'string (nreverse escaped)))) + (apply #'string (nreverse escaped)))) (defun pdf-util-frame-ppi () "Return the PPI of the current frame." - (let* ((props (frame-monitor-attributes)) - (px (nthcdr 2 (alist-get 'geometry props))) - (mm (alist-get 'mm-size props)) - (dp (sqrt (+ (expt (nth 0 px) 2) - (expt (nth 1 px) 2)))) - (di (sqrt (+ (expt (/ (nth 0 mm) 25.4) 2) - (expt (/ (nth 1 mm) 25.4) 2))))) - (/ dp di))) + (condition-case nil + (let* ((props (frame-monitor-attributes)) + (px (nthcdr 2 (alist-get 'geometry props))) + (mm (alist-get 'mm-size props)) + (dp (sqrt (+ (expt (nth 0 px) 2) + (expt (nth 1 px) 2)))) + (di (sqrt (+ (expt (/ (nth 0 mm) 25.4) 2) + (expt (/ (nth 1 mm) 25.4) 2))))) + (/ dp di)) + ;; Calculating frame-ppi failed, return 0 to indicate unknown. + ;; This can happen when (frame-monitor-attributes) does not have + ;; the right properties (Emacs 26, 27). It leads to the + ;; wrong-type-argument error, which is the only one we are + ;; catching here. We will catch more errors only if we see them + ;; happening. + (wrong-type-argument 0))) (defvar pdf-view-use-scaling) (defun pdf-util-frame-scale-factor () "Return the frame scale factor depending on the image type used for display. -When `pdf-view-use-scaling' is non-nil and imagemagick or -image-io are used as the image type for display, return the -backing-scale-factor of the frame if available. If a -backing-scale-factor attribute isn't available, return 2 if the +When `pdf-view-use-scaling' is non-nil, return the scale factor of the frame +if available. If the scale factor isn't available, return 2 if the frame's PPI is larger than 180. Otherwise, return 1." - (if (and pdf-view-use-scaling - (memq (pdf-view-image-type) '(imagemagick image-io)) - (fboundp 'frame-monitor-attributes)) - (or (cdr (assq 'backing-scale-factor (frame-monitor-attributes))) + (if pdf-view-use-scaling + (or (and (fboundp 'frame-scale-factor) + (truncate (frame-scale-factor))) + (and (fboundp 'frame-monitor-attributes) + (cdr (assq 'backing-scale-factor (frame-monitor-attributes)))) (if (>= (pdf-util-frame-ppi) 180) 2 1)) @@ -1000,10 +940,10 @@ Returns a cons \(WIDTH . HEIGHT\)." "Convert image IN-FILE to OUT-FILE according to SPEC. IN-FILE should be the name of a file containing an image. Write -the result to OUT-FILE. The extension of this filename ususally +the result to OUT-FILE. The extension of this filename usually determines the resulting image-type. -SPEC is a property list, specifying what the convert programm +SPEC is a property list, specifying what the convert program should do with the image. All manipulations operate on a rectangle, see below. @@ -1032,7 +972,7 @@ as a single argument. `:formats' An alist of additional %-escapes. Every element should be a cons \(CHAR . STRING\) or \(CHAR . FUNCTION\). In -the first case, all occurences of %-CHAR in the above commands +the first case, all occurrences of %-CHAR in the above commands will be replaced by STRING. In the second case FUNCTION is called with the current rectangle and it should return the replacement string. @@ -1041,14 +981,14 @@ replacement string. IN-FILE coordinates. Each such rectangle triggers one execution of the last commands given earlier in SPEC. E.g. a call like -\(pdf-util-convert - image-file out-file - :foreground \"black\" - :background \"white\" - :commands '\(\"-fill\" \"%f\" \"-draw\" \"rectangle %x,%y,%X,%Y\"\) - :apply '\(\(0 0 10 10\) \(10 10 20 20\)\) - :commands '\(\"-fill\" \"%b\" \"-draw\" \"rectangle %x,%y,%X,%Y\"\) - :apply '\(\(10 0 20 10\) \(0 10 10 20\)\)\) + (pdf-util-convert + image-file out-file + :foreground \"black\" + :background \"white\" + :commands \\='(\"-fill\" \"%f\" \"-draw\" \"rectangle %x,%y,%X,%Y\") + :apply \\='((0 0 10 10) (10 10 20 20)) + :commands \\='(\"-fill\" \"%b\" \"-draw\" \"rectangle %x,%y,%X,%Y\") + :apply \\='((10 0 20 10) (0 10 10 20))) would draw a 4x4 checkerboard pattern in the left corner of the image, while leaving the rest of it as it was. @@ -1058,7 +998,7 @@ Returns OUT-FILE. See url `http://www.imagemagick.org/script/convert.php'." (pdf-util-assert-convert-program) (let* ((cmds (pdf-util-convert--create-commands spec)) - (status (apply 'call-process + (status (apply #'call-process pdf-util-convert-program nil (get-buffer-create "*pdf-util-convert-output*") nil @@ -1083,7 +1023,7 @@ Returns the convert process." callback nil)) (let* ((cmds (pdf-util-convert--create-commands spec)) (proc - (apply 'start-process "pdf-util-convert" + (apply #'start-process "pdf-util-convert" (get-buffer-create "*pdf-util-convert-output*") pdf-util-convert-program `(,in-file ,@cmds ,out-file)))) @@ -1108,7 +1048,7 @@ Return the converted PNG image as a string. See also (set-buffer-file-coding-system 'binary) (insert image-data)) (pdf-util-munch-file - (apply 'pdf-util-convert + (apply #'pdf-util-convert in-file out-file specs))) (when (file-exists-p in-file) (delete-file in-file)) @@ -1210,10 +1150,10 @@ If RELATIVE-P is non-nil, also check that all values <= 1." (defun pdf-util-edges-union (&rest edges) (if (null (cdr edges)) (car edges) - (list (apply 'min (mapcar 'car edges)) - (apply 'min (mapcar 'cadr edges)) - (apply 'max (mapcar 'cl-caddr edges)) - (apply 'max (mapcar 'cl-cadddr edges))))) + (list (apply #'min (mapcar #'car edges)) + (apply #'min (mapcar #'cadr edges)) + (apply #'max (mapcar #'cl-caddr edges)) + (apply #'max (mapcar #'cl-cadddr edges))))) (defun pdf-util-edges-intersection-area (e1 e2) (let ((inters (pdf-util-edges-intersection e1 e2))) diff --git a/elpa/pdf-tools-20191031.642/pdf-view.el b/elpa/pdf-tools-20230611.239/pdf-view.el similarity index 84% rename from elpa/pdf-tools-20191031.642/pdf-view.el rename to elpa/pdf-tools-20230611.239/pdf-view.el index 7de18886..f2b89227 100644 --- a/elpa/pdf-tools-20191031.642/pdf-view.el +++ b/elpa/pdf-tools-20230611.239/pdf-view.el @@ -25,6 +25,7 @@ ;;; Code: (require 'image-mode) +(require 'pdf-macs) (require 'pdf-util) (require 'pdf-info) (require 'pdf-cache) @@ -33,7 +34,7 @@ (require 'password-cache) (declare-function cua-copy-region "cua-base") - +(declare-function pdf-tools-pdf-buffer-p "pdf-tools") ;; * ================================================================== * ;; * Customizations @@ -85,16 +86,13 @@ FIXME: Explain dis-/advantages of imagemagick and png." :group 'pdf-view :type 'boolean) -(defcustom pdf-view-use-scaling nil +(defcustom pdf-view-use-scaling t "Whether images should be allowed to be scaled for rendering. This variable affects both the reuse of higher-resolution images as lower-resolution ones by down-scaling the image. As well as the rendering of higher-resolution for high-resolution displays, -if available. - -It has no effect, unless either the imagemagick or image-io -image-format is available." +if available." :group 'pdf-view :type 'boolean) @@ -113,13 +111,27 @@ image-format is available." :group 'pdf-tools-faces) (defcustom pdf-view-midnight-colors '("#839496" . "#002b36" ) - "Colors used when `pdf-view-midnight-minor-mode' is activated. + "Colors used when command `pdf-view-midnight-minor-mode' is activated. This should be a cons \(FOREGROUND . BACKGROUND\) of colors." :group 'pdf-view :type '(cons (color :tag "Foreground") (color :tag "Background"))) +(defcustom pdf-view-midnight-invert t + "In midnight mode invert the image color lightness maintaining hue. + +This is particularly useful if you are viewing documents with +color coded data in plots. This will maintain the colors such +that blue and red will remain these colors in the inverted +rendering. This inversion is non-trivial. This makes use of the +OKLab color space which is well calibrated to have equal +perceptual brightness across hue, but not all colors are within +the RGB gamut after inversion, causing some colors to saturate. +Nevertheless, this seems to work well in most cases." + :group 'pdf-view + :type 'boolean) + (defcustom pdf-view-change-page-hook nil "Hook run after changing to another page, but before displaying it. @@ -169,7 +181,7 @@ See :relief property in Info node `(elisp) Image Descriptors'." :type '(integer :tag "Pixel")) (defcustom pdf-view-use-unicode-ligther t - "Whether to use unicode symbols in the mode-line + "Decide whether to use unicode symbols in the mode-line. On some systems finding a font which supports those symbols can take some time. If you don't want to spend that time waiting and @@ -183,13 +195,23 @@ loaded." (defcustom pdf-view-incompatible-modes '(linum-mode linum-relative-mode helm-linum-relative-mode - nlinum-mode nlinum-hl-mode nlinum-relative-mode yalinum-mode) + nlinum-mode nlinum-hl-mode nlinum-relative-mode yalinum-mode + display-line-numbers-mode) "A list of modes incompatible with `pdf-view-mode'. Issue a warning, if one of them is active in a PDF buffer." :group 'pdf-view :type '(repeat symbol)) +(defcustom pdf-view-selection-style 'word + "The current default selection style. + +Must be one of `glyph', `word', or `line'." + :group 'pdf-view + :type '(choice (const glyph) + (const word) + (const line))) + ;; * ================================================================== * ;; * Internal variables and macros @@ -219,32 +241,12 @@ regarding display of the region in the later function.") (defvar-local pdf-view--hotspot-functions nil "Alist of hotspot functions.") +(defvar-local pdf-view--current-rotation nil + "Current rotation of the page.") + (defvar-local pdf-view-register-alist nil "Local, dedicated register for PDF positions.") -(defmacro pdf-view-current-page (&optional window) - ;;TODO: write documentation! - `(image-mode-window-get 'page ,window)) - -(defmacro pdf-view-current-overlay (&optional window) - ;;TODO: write documentation! - `(image-mode-window-get 'overlay ,window)) - -(defmacro pdf-view-current-image (&optional window) - ;;TODO: write documentation! - `(image-mode-window-get 'image ,window)) - -(defmacro pdf-view-current-slice (&optional window) - ;;TODO: write documentation! - `(image-mode-window-get 'slice ,window)) - -(defmacro pdf-view-current-window-size (&optional window) - ;;TODO: write documentation! - `(image-mode-window-get 'window-size ,window)) - -(defmacro pdf-view-window-needs-redisplay (&optional window) - `(image-mode-window-get 'needs-redisplay ,window)) - (defun pdf-view-current-pagelabel (&optional window) (nth (1- (pdf-view-current-page window)) (pdf-info-pagelabels))) @@ -259,7 +261,7 @@ regarding display of the region in the later function.") (defconst pdf-view-have-image-mode-pixel-vscroll (>= emacs-major-version 27) - "Whether image-mode scrolls vertically by pixels.") + "Whether `image-mode' scrolls vertically by pixels.") ;; * ================================================================== * @@ -282,10 +284,14 @@ regarding display of the region in the later function.") (define-key map (kbd "DEL") 'pdf-view-scroll-down-or-previous-page) (define-key map (kbd "C-n") 'pdf-view-next-line-or-next-page) (define-key map (kbd "") 'pdf-view-next-line-or-next-page) - (define-key map (kbd "C-p") 'pdf-view-previous-line-or-previous-page) - (define-key map (kbd "") 'pdf-view-previous-line-or-previous-page) - (define-key map (kbd "M-<") 'pdf-view-first-page) - (define-key map (kbd "M->") 'pdf-view-last-page) + (define-key map [remap next-line] 'pdf-view-next-line-or-next-page) + (define-key map (kbd "C-p") 'pdf-view-previous-line-or-previous-page) + (define-key map (kbd "") 'pdf-view-previous-line-or-previous-page) + (define-key map [remap previous-line] 'pdf-view-previous-line-or-previous-page) + (define-key map (kbd "M-<") 'pdf-view-first-page) + (define-key map [remap beginning-of-buffer] 'pdf-view-first-page) + (define-key map (kbd "M->") 'pdf-view-last-page) + (define-key map [remap end-of-buffer] 'pdf-view-last-page) (define-key map [remap goto-line] 'pdf-view-goto-page) (define-key map (kbd "M-g l") 'pdf-view-goto-label) (define-key map (kbd "RET") 'image-next-line) @@ -302,10 +308,11 @@ regarding display of the region in the later function.") (define-key map (kbd "s m") 'pdf-view-set-slice-using-mouse) (define-key map (kbd "s b") 'pdf-view-set-slice-from-bounding-box) (define-key map (kbd "s r") 'pdf-view-reset-slice) + ;; Rotation. + (define-key map (kbd "R") #'pdf-view-rotate) ;; Reconvert (define-key map (kbd "C-c C-c") 'doc-view-mode) (define-key map (kbd "g") 'revert-buffer) - (define-key map (kbd "r") 'revert-buffer) ;; Region (define-key map [down-mouse-1] 'pdf-view-mouse-set-region) (define-key map [M-down-mouse-1] 'pdf-view-mouse-set-region-rectangle) @@ -321,10 +328,12 @@ regarding display of the region in the later function.") (define-key map (kbd "C-c C-i") 'pdf-view-extract-region-image) ;; Rendering (define-key map (kbd "C-c C-r m") 'pdf-view-midnight-minor-mode) + (define-key map (kbd "C-c C-r t") 'pdf-view-themed-minor-mode) (define-key map (kbd "C-c C-r p") 'pdf-view-printer-minor-mode) map) "Keymap used by `pdf-view-mode' when displaying a doc as a set of images.") +(defvar pdf-tools-enabled-modes) (define-derived-mode pdf-view-mode special-mode "PDFView" "Major mode in PDF buffers. @@ -339,12 +348,7 @@ PNG images in Emacs buffers." (not (and buffer-file-name (file-readable-p buffer-file-name))))) (pdf-tools-pdf-buffer-p)) - (let ((tempfile (pdf-util-make-temp-file - (concat (if buffer-file-name - (file-name-nondirectory - buffer-file-name) - (buffer-name)) - "-")))) + (let ((tempfile (pdf-util-make-temp-file))) (write-region nil nil tempfile nil 'no-message) (setq-local pdf-view--buffer-file-name tempfile))) ;; Decryption needs to be done before any other function calls into @@ -360,6 +364,21 @@ PNG images in Emacs buffers." (setq-local mwheel-scroll-down-function #'pdf-view-scroll-down-or-previous-page)) + ;; Disable pixel-scroll-precision-mode locally if enabled + (if (bound-and-true-p pixel-scroll-precision-mode) + (set (make-local-variable 'pixel-scroll-precision-mode) nil)) + (if (boundp 'mwheel-coalesce-scroll-events) + (setq-local mwheel-coalesce-scroll-events t)) + + ;; If the Emacs theme is dark, add `pdf-view-dark-minor-mode' to the + ;; list of `pdf-tools-enabled-modes'. See an interesting discussion + ;; at: https://github.com/vedang/pdf-tools/issues/166 about how this + ;; avoids a segfault crash in MacOS Ventura. IF you know why this + ;; happens, please get in touch via the linked issue. + + (when (eq 'dark (frame-parameter nil 'background-mode)) + (add-to-list 'pdf-tools-enabled-modes 'pdf-view-dark-minor-mode)) + ;; Clearing overlays (add-hook 'change-major-mode-hook (lambda () @@ -396,14 +415,6 @@ PNG images in Emacs buffers." ;; Enable transient-mark-mode, so region deactivation when quitting ;; will work. (setq-local transient-mark-mode t) - ;; In Emacs >= 24.4, `cua-copy-region' should have been advised when - ;; loading pdf-view.el so as to make it work with - ;; pdf-view-mode. Disable cua-mode if that is not the case. - ;; FIXME: cua-mode is a global minor-mode, but setting cua-mode to - ;; nil seems to do the trick. - (when (and (bound-and-true-p cua-mode) - (version< emacs-version "24.4")) - (setq-local cua-mode nil)) (add-hook 'window-configuration-change-hook 'pdf-view-redisplay-some-windows nil t) @@ -425,17 +436,15 @@ PNG images in Emacs buffers." (pdf-view-check-incompatible-modes buffer))) (current-buffer))) -(unless (version< emacs-version "24.4") - (defun cua-copy-region--pdf-view-advice (&rest _) - "If the current buffer is in `pdf-view' mode, call -`pdf-view-kill-ring-save'." - (when (eq major-mode 'pdf-view-mode) - (pdf-view-kill-ring-save) - t)) +(advice-add 'cua-copy-region + :before-until + #'cua-copy-region--pdf-view-advice) - (advice-add 'cua-copy-region - :before-until - #'cua-copy-region--pdf-view-advice)) +(defun cua-copy-region--pdf-view-advice (&rest _) + "If the current buffer is in `pdf-view' mode, call `pdf-view-kill-ring-save'." + (when (eq major-mode 'pdf-view-mode) + (pdf-view-kill-ring-save) + t)) (defun pdf-view-check-incompatible-modes (&optional buffer) "Check BUFFER for incompatible modes, maybe issue a warning." @@ -493,7 +502,10 @@ operating on a local copy of a remote file." ;; in the process), it may be immediately reopened due to ;; redisplay happening inside the pdf-info-close function ;; (while waiting for a response from the process.). - (copy-file tempfile (buffer-file-name) t) + (copy-file tempfile (or (buffer-file-name) + (read-file-name + "File name to save PDF to: ")) + t) (pdf-info-close pdf-view--server-file-name) (when pdf-view--buffer-file-name @@ -506,8 +518,14 @@ operating on a local copy of a remote file." (when (file-exists-p tempfile) (delete-file tempfile)))))) +(defun pdf-view--after-revert () + "Reload the local copy in case of a remote file, and close the document." + (when pdf-view--buffer-file-name + (write-region nil nil pdf-view--buffer-file-name nil 'no-message)) + (pdf-info-close)) + (defun pdf-view-revert-buffer (&optional ignore-auto noconfirm) - "Revert buffer while preseving current modes. + "Revert buffer while preserving current modes. Optional parameters IGNORE-AUTO and NOCONFIRM are defined as in `revert-buffer'." @@ -519,7 +537,7 @@ Optional parameters IGNORE-AUTO and NOCONFIRM are defined as in (let ((revert-buffer-function (when (fboundp #'revert-buffer--default) #'revert-buffer--default)) (after-revert-hook - (cons #'pdf-info-close + (cons #'pdf-view--after-revert after-revert-hook))) (prog1 (revert-buffer ignore-auto noconfirm 'preserve-modes) @@ -528,7 +546,7 @@ Optional parameters IGNORE-AUTO and NOCONFIRM are defined as in (defun pdf-view-close-document () "Return immediately after closing document. -This function always suceeds. See also `pdf-info-close', which +This function always succeeds. See also `pdf-info-close', which does not return immediately." (when (pdf-info-running-p) (let ((pdf-info-asynchronous 'ignore)) @@ -600,12 +618,30 @@ For example, (pdf-view-shrink 1.25) decreases size by 20%." (setq pdf-view-display-size 1.0) (pdf-view-redisplay t)) + +;; * ================================================================== * +;; * Rotation +;; * ================================================================== * +(defun pdf-view-rotate (angle) + "Rotate the current page by ANGLE degrees clockwise. +When called interactively, angle defaults to 90. Moreover, if +called interactively with a prefix argument, then rotate +anti-clockwise." + (interactive (list (if current-prefix-arg -90 90))) + (setq-local pdf-view--current-rotation + (mod (+ (or pdf-view--current-rotation 0) + angle) + 360)) + (pdf-view-redisplay t)) ;; * ================================================================== * ;; * Moving by pages and scrolling ;; * ================================================================== * +(defvar pdf-view-inhibit-redisplay nil) +(defvar pdf-view-inhibit-hotspots nil) + (defun pdf-view-goto-page (page &optional window) "Go to PAGE in PDF. @@ -626,7 +662,7 @@ windows." (save-selected-window ;; Select the window for the hooks below. (when (window-live-p window) - (select-window window)) + (select-window window 'norecord)) (let ((changing-p (not (eq page (pdf-view-current-page window))))) (when changing-p @@ -719,17 +755,20 @@ next page only on typing SPC (ARG is nil)." (interactive "P") (if (or pdf-view-continuous (null arg)) (let ((hscroll (window-hscroll)) - (cur-page (pdf-view-current-page))) - (when (or (= (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll) - (image-scroll-up arg)) - ;; Workaround rounding/off-by-one issues. - (memq pdf-view-display-size - '(fit-height fit-page))) + (cur-page (pdf-view-current-page)) + (win-scroll (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll)) + (img-scroll (image-scroll-up arg))) + (when (or + ;; There is no next line for the image to scroll to + (and img-scroll (= win-scroll img-scroll)) + ;; Workaround rounding/off-by-one issues. + (memq pdf-view-display-size + '(fit-height fit-page))) (pdf-view-next-page) (when (/= cur-page (pdf-view-current-page)) (image-bob) (image-bol 1)) - (set-window-hscroll (selected-window) hscroll))) + (image-set-window-hscroll hscroll))) (image-scroll-up arg))) (defun pdf-view-scroll-down-or-previous-page (&optional arg) @@ -741,17 +780,20 @@ to previous page only on typing DEL (ARG is nil)." (interactive "P") (if (or pdf-view-continuous (null arg)) (let ((hscroll (window-hscroll)) - (cur-page (pdf-view-current-page))) - (when (or (= (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll) - (image-scroll-down arg)) - ;; Workaround rounding/off-by-one issues. - (memq pdf-view-display-size - '(fit-height fit-page))) + (cur-page (pdf-view-current-page)) + (win-scroll (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll)) + (img-scroll (image-scroll-down arg))) + (when (or + ;; There is no previous line for the image to scroll to + (and img-scroll (= win-scroll img-scroll)) + ;; Workaround rounding/off-by-one issues. + (memq pdf-view-display-size + '(fit-height fit-page))) (pdf-view-previous-page) (when (/= cur-page (pdf-view-current-page)) (image-eob) (image-bol 1)) - (set-window-hscroll (selected-window) hscroll))) + (image-set-window-hscroll hscroll))) (image-scroll-down arg))) (defun pdf-view-next-line-or-next-page (&optional arg) @@ -769,7 +811,7 @@ at the bottom edge of the page moves to the next page." (when (/= cur-page (pdf-view-current-page)) (image-bob) (image-bol 1)) - (set-window-hscroll (selected-window) hscroll))) + (image-set-window-hscroll hscroll))) (image-next-line 1))) (defun pdf-view-previous-line-or-previous-page (&optional arg) @@ -787,7 +829,7 @@ at the top edge of the page moves to the previous page." (when (/= cur-page (pdf-view-current-page)) (image-eob) (image-bol 1)) - (set-window-hscroll (selected-window) hscroll))) + (image-set-window-hscroll hscroll))) (image-previous-line arg))) (defun pdf-view-goto-label (label) @@ -803,15 +845,41 @@ displayed page number." (error "No such label: %s" label)) (pdf-view-goto-page (1+ index)))) +(defun pdf-view-center-in-window () + "Center PDF in window horizontally." + (interactive) + (image-set-window-hscroll + (/ (* (- (car (pdf-view-image-size)) + (window-pixel-width)) + (window-width)) + 2 (window-pixel-width))) ; convert from pixel to character width + (pdf-view-redisplay t)) + +(defun pdf-view-align-left () + "Align left edge of pdf with left edge of window." + (interactive) + (image-set-window-hscroll 0) + (pdf-view-redisplay t)) + +(defun pdf-view-align-right () + "Align right edge of pdf with right edge of window." + (interactive) + (image-set-window-hscroll + (/ (* (- (car (pdf-view-image-size)) + (window-pixel-width)) + (window-width)) + (window-pixel-width))) ; convert from pixel to character width + (pdf-view-redisplay t)) + ;; * ================================================================== * ;; * Slicing ;; * ================================================================== * (defun pdf-view-set-slice (x y width height &optional window) - ;; TODO: add WINDOW to docstring. - "Set the slice of the pages that should be displayed. + "Set the slice of the pages that should be displayed in WINDOW. +WINDOW defaults to `selected-window' if not provided. X, Y, WIDTH and HEIGHT should be relative coordinates, i.e. in \[0;1\]. To reset the slice use `pdf-view-reset-slice'." (unless (equal (pdf-view-current-slice window) @@ -848,9 +916,10 @@ dragging it to its bottom-right corner. See also (/ 1.0 (float (cdr size)))))))) (defun pdf-view-set-slice-from-bounding-box (&optional window) - ;; TODO: add WINDOW to docstring. "Set the slice from the page's bounding-box. +WINDOW defaults to `selected-window' if not provided. + The result is that the margins are almost completely cropped, much more accurate than could be done manually using `pdf-view-set-slice-using-mouse'. @@ -871,8 +940,9 @@ See also `pdf-view-bounding-box-margin'." (append slice (and window (list window)))))) (defun pdf-view-reset-slice (&optional window) - ;; TODO: add WINDOW to doctring. - "Reset the current slice. + "Reset the current slice and redisplay WINDOW. + +WINDOW defaults to `selected-window' if not provided. After calling this function the whole page will be visible again." @@ -886,7 +956,7 @@ again." "Automatically slice pages according to their bounding boxes. See also `pdf-view-set-slice-from-bounding-box'." - nil nil nil + :group 'pdf-view (pdf-util-assert-pdf-buffer) (cond (pdf-view-auto-slice-minor-mode @@ -896,17 +966,15 @@ See also `pdf-view-set-slice-from-bounding-box'." (add-hook 'pdf-view-change-page-hook 'pdf-view-set-slice-from-bounding-box nil t)) (t - (remove-hook 'pdf-view-change-page-hook - 'pdf-view-set-slice-from-bounding-box t)))) + (progn (remove-hook 'pdf-view-change-page-hook + 'pdf-view-set-slice-from-bounding-box t) + (pdf-view-reset-slice))))) ;; * ================================================================== * ;; * Display ;; * ================================================================== * -(defvar pdf-view-inhibit-redisplay nil) -(defvar pdf-view-inhibit-hotspots nil) - (defun pdf-view-image-type () "Return the image type that should be used. @@ -928,12 +996,6 @@ See also `pdf-view-use-imagemagick'." (t (error "PNG image supported not compiled into Emacs")))) -(defun pdf-view-use-scaling-p () - "Return t if scaling should be used." - (and (memq (pdf-view-image-type) - '(imagemagick image-io)) - pdf-view-use-scaling)) - (defmacro pdf-view-create-image (data &rest props) ;; TODO: add DATA and PROPS to docstring. "Like `create-image', but with set DATA-P and TYPE arguments." @@ -952,13 +1014,14 @@ See also `pdf-view-use-imagemagick'." (let* ((size (pdf-view-desired-image-size page window)) (data (pdf-cache-renderpage page (car size) - (if (not (pdf-view-use-scaling-p)) - (car size) - (* 2 (car size))))) + (if pdf-view-use-scaling + (* 2 (car size)) + (car size)))) (hotspots (pdf-view-apply-hotspot-functions window page size))) (pdf-view-create-image data :width (car size) + :rotation (or pdf-view--current-rotation 0) :map hotspots :pointer 'arrow))) @@ -1123,7 +1186,7 @@ If WINDOW is t, redisplay pages in all windows." (let* ((pagesize (pdf-cache-pagesize (or page (pdf-view-current-page window)))) (slice (pdf-view-current-slice window)) - (width-scale (/ (/ (float (pdf-util-window-pixel-width window)) + (width-scale (/ (/ (float (window-body-width window t)) (or (nth 2 slice) 1.0)) (float (car pagesize)))) (height (- (nth 3 (window-inside-pixel-edges window)) @@ -1167,7 +1230,7 @@ This will display a text cursor, when hovering over them." "Mode for PDF documents with dark background. This tells the various modes to use their face's dark colors." - nil nil nil + :group 'pdf-view (pdf-util-assert-pdf-buffer) ;; FIXME: This should really be run in a hook. (when (bound-and-true-p pdf-isearch-active-mode) @@ -1178,7 +1241,8 @@ This tells the various modes to use their face's dark colors." (define-minor-mode pdf-view-printer-minor-mode "Display the PDF as it would be printed." - nil " Prn" nil + :group 'pdf-view + :lighter " Prn" (pdf-util-assert-pdf-buffer) (let ((enable (lambda () (pdf-info-setoptions :render/printed t)))) @@ -1198,15 +1262,24 @@ This tells the various modes to use their face's dark colors." The colors are determined by the variable `pdf-view-midnight-colors', which see. " - - nil " Mid" nil + :group 'pdf-view + :lighter " Mid" (pdf-util-assert-pdf-buffer) ;; FIXME: Maybe these options should be passed stateless to pdf-info-renderpage ? (let ((enable (lambda () (pdf-info-setoptions :render/foreground (or (car pdf-view-midnight-colors) "black") :render/background (or (cdr pdf-view-midnight-colors) "white") - :render/usecolors t)))) + :render/usecolors + (if pdf-view-midnight-invert + ;; If midnight invert is enabled, pass "2" indicating + ;; that :render/foreground and :render/background should + ;; be ignored and to instead invert the PDF (preserving + ;; hue) + 2 + ;; If invert is not enabled, pass "1" indictating that + ;; :render/foreground and :render/background should be used + 1))))) (cond (pdf-view-midnight-minor-mode (add-hook 'after-save-hook enable nil t) @@ -1215,10 +1288,49 @@ The colors are determined by the variable (t (remove-hook 'after-save-hook enable t) (remove-hook 'after-revert-hook enable t) - (pdf-info-setoptions :render/usecolors nil)))) + (pdf-info-setoptions + ;; Value "0" indicates that colors should remain unchanged + :render/usecolors 0)))) (pdf-cache-clear-images) (pdf-view-redisplay t)) +(defun pdf-view-set-theme-background () + "Set the buffer's color filter to correspond to the current Emacs theme." + (pdf-util-assert-pdf-buffer) + (pdf-info-setoptions + :render/foreground (face-foreground 'default nil) + :render/background (face-background 'default nil) + :render/usecolors 1)) + +(defun pdf-view-refresh-themed-buffer (&optional get-theme) + "Refresh the current buffer to activate applied colors. + +When GET-THEME is non-nil, also reset the applied colors to the +current theme's colors." + (pdf-util-assert-pdf-buffer) + (pdf-cache-clear-images) + (when get-theme + (pdf-view-set-theme-background)) + (pdf-view-redisplay t)) + +(define-minor-mode pdf-view-themed-minor-mode + "Synchronize color filter with the present Emacs theme. + +The colors are determined by the `face-foreground' and +`face-background' of the currently active theme." + :group 'pdf-view + :lighter " Thm" + (pdf-util-assert-pdf-buffer) + (cond + (pdf-view-themed-minor-mode + (add-hook 'after-save-hook #'pdf-view-set-theme-background nil t) + (add-hook 'after-revert-hook #'pdf-view-set-theme-background nil t)) + (t + (remove-hook 'after-save-hook #'pdf-view-set-theme-background t) + (remove-hook 'after-revert-hook #'pdf-view-set-theme-background t) + (pdf-info-setoptions :render/usecolors 0))) + (pdf-view-refresh-themed-buffer pdf-view-themed-minor-mode)) + (when pdf-view-use-unicode-ligther ;; This check uses an implementation detail, which hopefully gets the ;; right answer. @@ -1242,7 +1354,7 @@ image size \(WIDTH . HEIGHT\) as arguments. It should return a list of hotspots applicable to the the :map image-property. LAYER determines the order: Functions in a higher LAYER will -supercede hotspots in lower ones." +supersede hotspots in lower ones." (push (cons (or layer 0) fn) pdf-view--hotspot-functions)) @@ -1261,7 +1373,7 @@ supercede hotspots in lower ones." ;; TODO: write documentation! (unless pdf-view-inhibit-hotspots (save-selected-window - (when window (select-window window)) + (when window (select-window window 'norecord)) (apply 'nconc (mapcar (lambda (fn) (funcall fn page image-size)) @@ -1297,13 +1409,17 @@ Deactivate the region if DEACTIVATE-P is non-nil." (pdf-view-redisplay t))) (defun pdf-view-mouse-set-region (event &optional allow-extend-p - rectangle-p) + rectangle-p + selection-style) "Select a region of text using the mouse with mouse event EVENT. Allow for stacking of regions, if ALLOW-EXTEND-P is non-nil. Create a rectangular region, if RECTANGLE-P is non-nil. +Overwrite `pdf-view-selection-style' with SELECTION-STYLE, +which is one of `glyph', `word', or `line'. + Stores the region in `pdf-view-active-region'." (interactive "@e") (setq pdf-view--have-rectangle-region rectangle-p) @@ -1325,6 +1441,7 @@ Stores the region in `pdf-view-active-region'." (setq begin-inside-image-p nil) (posn-x-y pos))) (abs-begin (posn-x-y pos)) + (selection-style (or selection-style pdf-view-selection-style)) pdf-view-continuous region) (when (pdf-util-track-mouse-dragging (event 0.05) @@ -1338,7 +1455,7 @@ Stores the region in `pdf-view-active-region'." (cond ((and end-inside-image-p (not begin-inside-image-p)) - ;; Started selection ouside the image, setup begin. + ;; Started selection outside the image, setup begin. (let* ((xy (posn-x-y pos)) (dxy (cons (- (car xy) (car begin)) (- (cdr xy) (cdr begin)))) @@ -1377,7 +1494,8 @@ Stores the region in `pdf-view-active-region'." (pdf-util-scale-pixel-to-relative iregion)) (pdf-view-display-region (cons region pdf-view-active-region) - rectangle-p) + rectangle-p + selection-style) (pdf-util-scroll-to-edges iregion))))) (setq pdf-view-active-region (append pdf-view-active-region @@ -1400,7 +1518,7 @@ This is more useful for commands like (interactive "@e") (pdf-view-mouse-set-region event nil t)) -(defun pdf-view-display-region (&optional region rectangle-p) +(defun pdf-view-display-region (&optional region rectangle-p selection-style) ;; TODO: write documentation! (unless region (pdf-view-assert-active-region) @@ -1417,8 +1535,9 @@ This is more useful for commands like page width nil `(,(car colors) ,(cdr colors) 0.35 ,@region)) (pdf-info-renderpage-text-regions - page width nil nil - `(,(car colors) ,(cdr colors) ,@region))))))) + page width nil selection-style nil + `(,(car colors) ,(cdr colors) ,@region))) + :width width)))) (defun pdf-view-kill-ring-save () "Copy the region to the `kill-ring'." @@ -1441,7 +1560,11 @@ This is more useful for commands like "Return the text of the active region as a list of strings." (pdf-view-assert-active-region) (mapcar - (apply-partially 'pdf-info-gettext (pdf-view-current-page)) + (lambda (edges) + (pdf-info-gettext + (pdf-view-current-page) + edges + pdf-view-selection-style)) pdf-view-active-region)) (defun pdf-view-extract-region-image (regions &optional page size @@ -1459,7 +1582,7 @@ image*\" and display it, unless NO-DISPLAY-P is non-nil. In case of multiple regions, the resulting image is constructed by joining them horizontally. For this operation (and this only) -the `convert' programm is used." +the `convert' program is used." (interactive (list (if (pdf-view-active-region-p) @@ -1512,6 +1635,20 @@ the `convert' programm is used." (dolist (f (cons result images)) (when (file-exists-p f) (delete-file f)))))) + +(defun pdf-view-set-selection-style (&optional style) + "Set `pdf-view-selection-style' to STYLE in the current buffer. + +When called interactively or without an argument, cycle between +the selection styles." + (interactive) + (unless style + (setq style (or (cadr (memq pdf-view-selection-style '(glyph word line))) + 'glyph)) + (message "Setting selection style to `%s'." style)) + (pdf-view-deactivate-region) + (setq-local pdf-view-selection-style style)) + ;; * ================================================================== * ;; * Bookmark + Register Integration diff --git a/elpa/pdf-tools-20191031.642/pdf-virtual.el b/elpa/pdf-tools-20230611.239/pdf-virtual.el similarity index 98% rename from elpa/pdf-tools-20191031.642/pdf-virtual.el rename to elpa/pdf-tools-20230611.239/pdf-virtual.el index 5d6458fc..f8ecf970 100644 --- a/elpa/pdf-tools-20191031.642/pdf-virtual.el +++ b/elpa/pdf-tools-20230611.239/pdf-virtual.el @@ -26,21 +26,16 @@ ;; order to transparently make this collection appear as one single ;; document. ;; -;; The trickiest part is to make theses intermediate functions behave +;; The trickiest part is to make these intermediate functions behave ;; like the pdf-info-* equivalents in both the synchronous and ;; asynchronous case. ;;; Code: -(eval-when-compile - (unless (or (> emacs-major-version 24) - (and (= emacs-major-version 24) - (>= emacs-minor-version 4))) - (error "pdf-virtual.el only works with Emacs >= 24.4"))) - (require 'let-alist) (require 'pdf-info) (require 'pdf-util) +(declare-function pdf-view-mode "pdf-view.el") ;; * ================================================================== * ;; * Variables @@ -477,8 +472,8 @@ PAGE should be a page-number." ;;;###autoload (define-minor-mode pdf-virtual-global-minor-mode "Enable recognition and handling of VPDF files." - nil nil nil :global t + :group 'pdf-tools (let ((elt `(,pdf-virtual-magic-mode-regexp . pdf-virtual-view-mode))) (cond (pdf-virtual-global-minor-mode @@ -518,7 +513,7 @@ PAGE should be a page-number." (concat " " f)) unreadable "\n")))) (if (= (pdf-virtual-document-number-of-pages) 0) - (error "Docüment is empty.") + (error "Document is empty.") (unless pdf-virtual-global-minor-mode (pdf-virtual-global-minor-mode 1)) (funcall fn)))) @@ -567,7 +562,7 @@ PAGE should be a page-number." (defun pdf-virtual-view-window-p (&optional window) (save-selected-window - (when window (select-window window)) + (when window (select-window window 'norecord)) (derived-mode-p 'pdf-virtual-view-mode))) (defun pdf-virtual-filename-p (filename) @@ -734,8 +729,8 @@ PAGE should be a page-number." (defun ,fn ,(cons base-fn-arg arglist) ,(format "%sPDF virtual adapter to `%s'. -This function delegates to `%s', unless the FILE-OR-BUFFER -argument denotes a VPDF document." +This function delegates to `%s', +unless the FILE-OR-BUFFER argument denotes a VPDF document." (if doc (concat doc "\n\n") "") base-fn base-fn) -- 2.47.3