diff options
Diffstat (limited to 'Build/source/utils/xpdfopen/xpdfopen-0.86')
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/ChangeLog | 136 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/Makefile.am | 18 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/README | 115 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/configure.ac | 25 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/externs.h | 24 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/pdfclose.c | 75 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.1 | 166 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.c | 681 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.c | 424 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.h | 19 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/utils.c | 45 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/utils.h | 13 | ||||
-rw-r--r-- | Build/source/utils/xpdfopen/xpdfopen-0.86/xpdfopen.h | 41 |
13 files changed, 1782 insertions, 0 deletions
diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/ChangeLog b/Build/source/utils/xpdfopen/xpdfopen-0.86/ChangeLog new file mode 100644 index 00000000000..5e22620685f --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/ChangeLog @@ -0,0 +1,136 @@ +2014-05-24 Jim Diamond <jim.diamond@acadiau.ca> + * pdfopen.c: fixed -g (goto named destination) option for AR9. + * README: update for V 0.86. + + +2014-05-22 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: add -g (goto named destination) option. + NOTE: notwithstanding the man page for AR 9.5.5 on + Linux, I can't get -g <named-dest> to work with AR9. + Allow use of '--file', '-V', '-?', '--page' and + '--goto' options for compatibility with (various and + sundry versions of) ms-windows pdfopen programs. + For consistency, add a '--viewer' form of that option, + but keep the '-viewer' form for backward compatibility. + Redo help text for all this. + * pdfclose.c allow use of '--file' option for compatibility + with ms-windows pdfclose program. + * pdfopen.1: update man page accordingly. + * README: updates for V 0.85. + + +2014-05-16 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: add -p option, update for externs.h + * pdfclose.c: update for externs.h + * utils.c: update for externs.h + * externs.h: add this for cleanliness + * pdfopen.1: update man page accordingly. + * xpdfopen.tex: remove from distribution, since it is now redundant + * configure.ac: update for V 0.84. + * README: update for V 0.84. + * Makefile.am update for externs.h, remove archaic pdfopen-AR-7-and-8.c + + +2012-01-28 Jim Diamond <jim.diamond@acadiau.ca> + + * sendx.c: fix (kludgily?) reset_focus() so that it actually works. + * pdfopen.c: add -r and -reset_focus options. + * pdfopen.1: update man page accordingly. + * xpdfopen.tex: update (ConTeXt) document accordingly. + * configure.ac: update for V 0.83. + * README: update for V 0.83. + + +2011-05-28 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: add -v and --version options. + * pdfopen.1: create man page: thanks to Karl Berry for numerous + suggestions and improvements. + * pdfclose.1: add version number to usage information. + * configure.ac: update for V 0.82. + + +2011-05-17 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: add -h and --help options. + Reformat usage information. + Add support for evince. + Replace '-openInNewWindow' with '-openInNewInstance' + since AR9 claims the former is deprecated. + * xpdfopen.h: add support for evince. + * pdfclose.c: add support for evince. + * configure.ac: update for V 0.81. + + +2010-05-03 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfclose.c: make it work with all of AR{5,7,8,9} and xpdf. + * pdfopen.c: add ability to parse and send function-keys. + Add code (commented out) in an attempt to + support okular (see code comments). + * sendx.c: add code (commented out) in an attempt to + support okular (see code comments). + * configure.ac: add changes suggested by Peter Breitenlohner. + + +2010-04-24 Jim Diamond <jim.diamond@acadiau.ca> + + * utils.[ch]: put a function to create window titles there + * xpdfopen.h: put constants related to the titles of various + PDF viewers there + * pdfclose.c: modify to use utils.c and xpdfopen.h + * pdfopen.c: major modifications so it works with AR7, AR8, AR9 + xpdf and maybe AR5, and so that it might be + relatively straightforward to add other PDF viewers. + The default viewer is AR9, this can be overridden + by an environment variable and a command-line + argument. + * sendx.c: Reset the error status in open_channel() so that an + error return doesn't become permanent. + Fixed mask param in XSendEvent(). + + +2010-04-21 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: Fold in some changes submitted by + Peter Breitenlohner <tex-live@tug.org> + * pdfopen.c: Fold in some changes submitted by + Peter Breitenlohner <tex-live@tug.org> + and reformat the code. + + +2010-04-11 Jim Diamond <jim.diamond@acadiau.ca> + + * pdfopen.c: Update (in a non-backward-compatible way) to + work with AR 9. Save old version in pdfopen-AR-7-and-8.c. + + +2009-08-22 Peter Breitenlohner <peb@mppmu.mpg.de> + + Avoid maximal compiler warnings. + * pdfopen.c: Use strdup'ed literal string (malloc+strcpy) to + initialize non-constant string. + * sendx.[ch]: Constify string args of all functions. + Consistently use wname for window name string param. + (close_channel): ANSI C function definition. + + +2009-08-19 Peter Breitenlohner <peb@mppmu.mpg.de> + + * Makefile.am (AM_CFLAGS), configure.ac: Enable compiler warnings. + * pdfopen.c (usage), pdfclose.c (usage): Declare as static. + + * sendx.h (new): Declare prototypes for functions in sendx.c. + * Makefile.am (pdfopen_SOURCES, pdfclose_SOURCES): Add sendx.h. + * pdfopen.c, pdfclose.c, sendx.c: #include "sendx.h". + + * sendx.c (GetRootWindow): Slightly reformulate to avoid compiler + warning (strict-aliasing rules). + + +2009-05-06 Peter Breitenlohner <peb@mppmu.mpg.de> + + Adapt to TL2009 build system. + diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/Makefile.am b/Build/source/utils/xpdfopen/xpdfopen-0.86/Makefile.am new file mode 100644 index 00000000000..b41b46db6b7 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/Makefile.am @@ -0,0 +1,18 @@ + +AM_CFLAGS = $(X_CFLAGS) +## Add warnings for gcc-3.4 +AM_CFLAGS += -Wall -Wunused -Wimplicit -Wreturn-type +AM_CFLAGS += -Wdeclaration-after-statement -Wno-unknown-pragmas +AM_CFLAGS += -Wmissing-prototypes -Wmissing-declarations -Wparentheses +AM_CFLAGS += -Wswitch -Wtrigraphs -Wpointer-arith -Wcast-qual +AM_CFLAGS += -Wcast-align -Wwrite-strings -Wold-style-definition + +LDADD = $(X_LIBS) -lX11 -lXmu $(X_EXTRA_LIBS) + +bin_PROGRAMS = pdfopen pdfclose + +pdfopen_SOURCES = externs.h pdfopen.c sendx.c utils.c sendx.h xpdfopen.h utils.h + +pdfclose_SOURCES = externs.h pdfclose.c sendx.c utils.c sendx.h xpdfopen.h utils.h + + diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/README b/Build/source/utils/xpdfopen/xpdfopen-0.86/README new file mode 100644 index 00000000000..3c7d6ba0c58 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/README @@ -0,0 +1,115 @@ +--------------------------------------------------------------------------- +xpdfopen 0.86 - Send open/close commands to Acrobat Reader, xpdf and evince +--------------------------------------------------------------------------- + +This is a Linux (X11) implementation of Fabrice Popineau's pdfclose/ +pdfopen commands to control Acrobat Reader, xpdf and evince. + +The libX code was borrowed from Reinhard Fobbe's Sendx library for +Tcl/Tk, and the programs use the same license, copied below. + +Version 0.3 adds support for Adobe Reader 7.0 for Linux. + (different window titles and key shortcuts) + +Version 0.4 uses autoconf + +Version 0.5 fixes an incorrect autoconf variable, supports building + under X11R5, handles pathnames on the command-line, and + fixes a bug where pdfopen did not exit correctly after + (automatically) starting acroread. + +Version 0.51 uses the strrchr() function instead of rindex() + to allow compilation on non-BSD derived unix platforms. + +Version 0.61 attempts to do something useful with Adobe Reader 8, + even though it is impossible to restore the viewport. + +Version 0.80 adds an implementation for AR 9 and xpdf. + +Version 0.81 adds an implementation for evince. + +Version 0.82 adds a man page and -v/--version options for pdfopen. + +Version 0.83 adds the -r/-reset_focus option for pdfopen. + +Version 0.84 adds 'load at given page' support (-p option) for Adobe + Reader 9, evince (at least 3.12, maybe earlier) and xpdf. + +Version 0.85 adds 'load at named destination' support (-g/--goto option) + for xpdf, evince and (supposedly) AR9. The AR9 man page + claims it should work, but it doesn't for me. I left + the allegedly-correct code there anyway, in case it works + for other people in other places. + Also add aliases for option names to make ms-windows + users feel at home. + +Version 0.86 fixes 'load at named destination' for AR9. + + +The AR command lines do not behave precisely the same as under Windows, +because the Linux Reader behaves somewhat differently: it is not +scriptable, but it is possible to 'fake' key-presses. + + +pdfopen has the following call sequence: + pdfopen [-r|-reset_focus] \ + [-viewer/--viewer <ar9|ar9-tab|ar8|ar7|ar5|xpdf|evince>] \ + [-p/--page <page number>] \ + [-g/--goto <named destination>] \ + [--file] <pdf file name> + +The "ar9" version uses AR9's "-openInNewInstance" option, the "ar9-tab" +version does not (so if there is already an AR9 window open, a new tab +will be opened in that window). + + +pdfclose has the following call sequence: + pdfclose [--file] <pdf file name> +This program closes an existing AR5, AR7, AR8, AR9, xpdf or evince window +displaying the given PDF file. + + +Version 0.85 compiles on Linux (Slackware64 14.1, anyway) with +the following command: + gcc -Wall pdfopen.c sendx.c utils.c -o pdfopen -lX11 -s + gcc -Wall pdfclose.c sendx.c utils.c -o pdfclose -lX11 -s +should you not want to go through the process of creating and running +a configure program. + + +Taco Hoekwater <taco@metatex.org> (Version(s) up to 0.61) +Dordrecht, The Netherlands, December 2008. + +Jim Diamond <jim.diamond@acadiau.ca> (Version 0.80 through 0.84) +Acadia University, Wolfville, Nova Scotia, Canada; May 2014. + + + + +License terms: +-------------- +The following terms apply to all files associated with the software +unless explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/configure.ac b/Build/source/utils/xpdfopen/xpdfopen-0.86/configure.ac new file mode 100644 index 00000000000..42f7b9a31bc --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/configure.ac @@ -0,0 +1,25 @@ +dnl Process this file with autoconf to produce a configure script. +dnl this is for autoconf 2.5x + +AC_INIT(pdfopen, 0.86, jim.diamond@acadiau.ca) + +AC_CONFIG_AUX_DIR(config) + +AM_INIT_AUTOMAKE() + +AC_CONFIG_FILES(Makefile) + +AC_PROG_CC + +dnl AC_PROG_INSTALL + +dnl Checks for header files. + +dnl Checks for typedefs, structures, and compiler characteristics. + +dnl Checks for library functions. + +dnl Find Xlibs. +AC_PATH_XTRA + +AC_OUTPUT diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/externs.h b/Build/source/utils/xpdfopen/xpdfopen-0.86/externs.h new file mode 100644 index 00000000000..2aff4f858ef --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/externs.h @@ -0,0 +1,24 @@ +/* + * externs.h: This file defines or declares (depending on whether + * DEFINE_EXTERNS is defined) all of the global variables + * and constants used by pdfopen and pdfclose. + * + * Copyright (C) 2014 Jim Diamond <jim.diamond@acadiau.ca> + * You may freely use, modify and/or distribute this file. + * + * This file new in Version 0.84 of pdfopen (2014/05/16). + */ + + +#ifndef EXTERNS_H +#define EXTERNS_H + +#ifdef DEFINE_EXTERNS +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN char * progname; + +#endif diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfclose.c b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfclose.c new file mode 100644 index 00000000000..95de13e79cc --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfclose.c @@ -0,0 +1,75 @@ +/* + * pdfclose.c: (attempt to) close a PDF viewer displaying argv[1]. + * + * Modified by Peter Breitenlohner <tex-live@tug.org> (2009) + * and Jim Diamond (jim.diamond@acadiau.ca) 2010--2014 (V 0.80 -- 0.86). + * + * This program does not take a viewer argument, and just tries to close + * any known viewer displaying the given file. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "sendx.h" +#include "xpdfopen.h" +#include "utils.h" + +#define DEFINE_EXTERNS +#include "externs.h" + +static void +usage(void) +{ + fprintf(stderr, "%s version %s\n", progname, VERSION); + fprintf(stderr, "Usage: %s [--file] <file.pdf>\n", progname); +} + + + +static int +try_name(const char * filename, const char * title_format) +{ + char * winname; + int ret ; + + winname = make_window_name(title_format, filename); + if (winname == NULL) + return 99; + + ret = sendx_control_token("W", winname); + free(winname); + + return ret; +} + + + +int +main (int argc, char * argv[]) +{ + + progname = argv[0]; + + if (argc < 2 || argc > 3 || (argc == 3 && strcmp("--file", argv[1]))) + { + usage(); + return EXIT_FAILURE; + } + if (argc == 3) + { + argv++; + argc--; + } + + if (try_name(argv[1], AR9_WIN_NAME_FMT)) /* This gets both AR8 & AR9 */ + if (try_name(argv[1], XPDF_WIN_NAME_FMT)) + if (try_name(argv[1], AR7_WIN_NAME_FMT)) + if (try_name(argv[1], AR5_WIN_NAME_FMT)) + if (try_name(argv[1], EVINCE_WIN_NAME_FMT)) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.1 b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.1 new file mode 100644 index 00000000000..23b8f84f61b --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.1 @@ -0,0 +1,166 @@ +.\" This manpage is licensed under the GNU Public License +.TH PDFOPEN 1 2014-05-24 "pdfopen 0.86" "" +. +.SH NAME +pdfopen, pdfclose \- open or close a PDF file viewer +. +.SH SYNOPSIS +.B pdfopen +[ \fIoptions\fP ]\ +[ +.B --file +]\ +\fIfile.pdf\fP +.br +.B pdfclose +[ +.B --file +]\ +\fIfile.pdf\fP +. +.SH OPTIONS +.TP 8 +.B -h, --help, -? +output help and exit. +.TP +.B -v, --version, -V +output the version number and exit. +.TP +.B -p <n>, --page <n> +when starting the viewer, display page <n> of the document (notes: not +all viewers support this feature, and even in those cases this option +only has effect when the document is initially loaded). This option +is over-ridden by \fB-g\fP. +.TP +.B -g <named destination>, --goto <named destination> +when starting the viewer, display the page of the document containing +the named destination (notes: not all viewers support this feature, +and even in those cases this option only has effect when the document +is initially loaded). +.TP +.B -r, --reset_focus +after sending commands to the PDF viewer, attempt to reset the input focus to +the window which had focus before the commands were sent. +.TP +.B -viewer, --viewer <\fIar9\fP|\fIar9-tab\fP|\fIar8\fP|\fIar7\fP|\fIar5\fP|\fIxpdf\fP|\fIevince\fP> +use (respectively) Adobe Reader 9 (in a new window), Adobe Reader 9 +(in a new tab of a running AR9, if any), +Adobe Reader 8, Adobe Reader 7, Adobe Reader 5, xpdf or evince as the +PDF viewer program. +Adobe Reader 9 (in a new window) is the default. +. +.SH RATIONALE +At certain points of TeX document preparation, many people repeat a +"edit-compile-view" cycle. Since PDF viewers such as Adobe's Acrobat +Reader ("\fBacroread\fP") do not automatically refresh the display when the +PDF file changes, this cycle can be more cumbersome than desired. +The +.B pdfopen +program provides the ability to automate the reloading of the PDF +document when it is changed. + +Note: there seems to be little need for +.B pdfclose +under GNU/Linux, since (unlike the situation for MS windows) +.B acroread +does not lock the PDF file, which would prevent +.B pdftex +(or a DVI to PDF converter) from creating a new version of the PDF +output file. However, +.B pdfclose +is provided in case someone finds it useful. +. +.SH DESCRIPTION +.B pdfopen +searches for an instance of the specified (or default) PDF viewer +displaying the specified PDF file. +If there is already an instance of the given viewer displaying the +given file, the viewer is instructed to reload the file. If no such +instance is found, \fBpdfopen\fP attempts to run the specified viewer +on the specified document. + +The default viewer is "\fBacroread\fP", which could start any one +of a number of versions of Acrobat Reader, depending on what is +installed on your system. However, the commands to reload the current +document vary from one version of \fBacroread\fP to another; +consequently, if you are using a version of \fBacroread\fP other than +AR9, you should explicitly specify the viewer program. + +This version of \fBpdfopen\fP accepts the following viewer options: +.br +\fIar9\fP, \fIar9-tab\fP, \fIar8\fP, \fIar7\fP, \fIar5\fP, \fIxpdf\fP, +and \fIevince\fP. +.br +The difference between \fIar9\fP and \fIar9-tab\fP is significant +when there is no instance of AR9 already displaying the requested +document. In this situation, while \fIar9\fP will +request \fBacroread\fP to create a new instance of \fBacroread\fP +(and thus open a new window) by using the \fB-openInNewInstance\fP +argument, \fIar9-tab\fP starts \fBacroread\fP without this argument; +if there is already an instance of \fBacroread\fP running, a new +tab will be opened in an existing window. + +.B pdfclose +searches for one of the above PDF viewers displaying the given file +and instructs the viewer to "close" the window. In most cases, the +PDF viewer continues to run, possibly now displaying just a blank +window. (This behaviour varies somewhat from one PDF viewer to another.) +. +.SH PORTABILITY AND AVAILABILITY +These programs have been tested on Slackware64 Version 14.1 and a few +other versions / distributions of GNU/Linux. The code is reasonably +generic and should work out of the box using most recent X11 +implementations. (Reports to the contrary are welcome, particularly +if they come with robust fixes.) + +These programs are designed for X11-based systems. If you somehow +find compiled versions of these programs on a system using another +window system, they are very unlikely to be of any use to you. + +Source and binaries of the programs can be downloaded from +\f(CWCTAN://support/xpdfopen/\fR +(e.g., \f(CWhttp://mirror.ctan.org/support/xpdfopen\fR). +. +.SH CAVEATS +If you use +.I ar9-tab +to reload the PDF document and the instance +of +.B acroread +with the given document is currently displaying some other document, +the command causes your document to be displayed, but not reloaded. + +.B pdfopen +works by looking for a window with a name (window title) matching that +expected for the given viewer and document. If for some reason your +viewer's window name is not as expected, +.B pdfopen +may not work for you. + +With at least AR9 and some window managers, using +.B pdfopen +to reload the document gives focus to the +.B acroread +window, even though the mouse cursor is not necessarily in that +window. This can be annoying. The \fB-reset_focus\fP option can be +used to deal with this problem. +. +.SH AUTHOR +This manual page was written by Jim Diamond <\f(CWJim.Diamond@acadiau.ca\fP>. +I am the current maintainer of the X11 versions of +.B pdfopen +and +\fBpdfclose\fP. +Report any bugs you find to me. Feature enhancement requests are +welcome, coded enhancements even more so. + +Past authors: +Fabrice Popineau wrote the MS-windows versions of +.B pdfopen +and +.B pdfclose +upon which these programs were originally based. +Taco Hoekwater created the GNU/Linux versions, up to Version 0.61 +(including some documentation which inspired parts of this man page). +Peter Breitenlohner has contributed both code and suggestions to +versions later than 0.61. diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.c b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.c new file mode 100644 index 00000000000..664a4061663 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/pdfopen.c @@ -0,0 +1,681 @@ +/* + * pdfopen.c. + * + * Heavily modified by Jim Diamond (jim.diamond@acadiau.ca) 2010/04/11 + * to work with AR 9, xpdf and evince. + * (Also some mods by Peter Breitenlohner <tex-live@tug.org> from 2009 + * and suggestions from 2010, and some suggestions from Karl Berry + * (2011).) + * + * Note 1: the calling sequence was changed considerably to match what + * the program actually seemed to do as well as what made sense to me. + * + * Note 2: if there are two instances of acroread displaying that file, + * only one is reloaded. + * + * Note 3: Unlike xpdf and AR[5,7,8,9], okular will not accept X events + * from this program unless the okular window has focus. On my system + * (Slackware64 13.0, using fvwm2), the functions I added to sendx.c to try + * to change the focus to the okular window do not work. (See also the + * comments in sendx.c.) If anyone cares to contribute working code, + * please send it to me for inclusion. + + * Further modified 2010/05/03 to work with ar5, and to include some code + * that does *not* work with okular (see note below). + * + * Modified 2014/05/16 (V 0.84) to add capability to open a pdf file + * at a specified page (currently working with AR9, xpdf and evince). + * + * Modified 2014/05/22 (V 0.85) to allow '--file' option, for + * "compatibility" with windows pdfopen/pdfclose calling sequence. + * Drive by: allow '--viewer' for consistency's sake. + * Also allow '-V', '-?' and '--page' for compatibility. + * Added --goto/-g option... this works in (at least) xpdf 3.03, + * evince 3.12.1. + * + * Modified 2014/05/24 (V 0.86) so that -g works in AR 9.5.5 and + * possibly other AR9 versions. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "sendx.h" +#include "xpdfopen.h" +#include "utils.h" + +#define DEFINE_EXTERNS +#include "externs.h" + +#define MAX_RELOAD_CMDS 10 +#define MAX_PRE_PAGE_OPTIONS 2 /* See struct defn below */ +#define MAX_POST_PAGE_OPTIONS 1 /* See struct defn below */ +#define MAX_PRE_DEST_OPTIONS 2 /* See struct defn below */ +#define MAX_POST_DEST_OPTIONS 1 /* See struct defn below */ + /* Overkill ... */ +#define MAX_OPTIONS (10 + MAX_PRE_PAGE_OPTIONS \ + + MAX_POST_PAGE_OPTIONS + MAX_PRE_DEST_OPTIONS \ + + MAX_POST_DEST_OPTIONS) + +/* A string unlikely to be used as a real command by a PDF viewer */ +#define FORK_EXEC_CMD "*FORK EXEC*" + + +/* Used in the pdf_viewer_t type... see comment below */ +typedef enum +{ + USE_SENDX, USE_FORK_EXEC +} reload_method_t; + + +/* + * This struct contains the information needed for both + * (a) initially starting up a PDF viewer, and + * (b) telling the viewer to reload the document. + * Of course, the viewer has to support that functionality. + * Two possible ways are supported. + * (a) Send the viewer's window (a) simulated keypress(ss) + * (b) fork()/exec() a second instance of the program which somehow signals + * the running instance. Note that this is problematical if the + * arguments for the "reload" case are different than the options + * for the "start up the viewer" case, because the command-line + * (and environment variable) syntax have to be extended. + * Arguably, if both the start-up and reload can be done with shell + * commands, the user should just write a shell script and be done with + * it. + * These could be extended with this as well: + * (c) send a Unix signal to the currently running viewer. + * This would require augmenting reload_method_t and pdf_viewer_t. + */ + +typedef struct +{ + const char * short_name; /* cmd line option name */ + const char * program_name; /* program to exec() */ + reload_method_t method; /* method to induce reload */ + const char * window_name; /* when no file is viewed */ + const char * window_name_fmt; /* fmt string for file viewed */ + const char * exec_pre_options[MAX_OPTIONS]; /* before filename in cmd */ + const char * exec_post_options[MAX_OPTIONS];/* after filename in cmd */ + const char * reload_cmds[MAX_RELOAD_CMDS]; /* cmds to reload a file */ + /* + * If the page number goes before the filename, use these options. + * The last one must be a printf format string with a %d and + * no other conversions specs. + * End list with a NULL. + */ + const char * initial_page_pre_options[MAX_PRE_PAGE_OPTIONS + 1]; /* */ + /* + * If the page number goes after the filename, use these options. + * The last one must be a printf format string with a %d and + * no other conversions specs. + * End list with a NULL. + */ + const char * initial_page_post_options[MAX_POST_PAGE_OPTIONS + 1]; /* */ + /* Ditto for named destinations */ + const char * initial_dest_pre_options[MAX_PRE_DEST_OPTIONS + 1]; /* */ + const char * initial_dest_post_options[MAX_POST_DEST_OPTIONS + 1]; /* */ +} pdf_viewer_t; + + +/* Reload commands (or prefixes thereof) */ +#define CTRL "Ctrl-" +#define ALT "Alt-" +#define CTRL_ALT "Ctrl-Alt-" +#define FN "Fn-" +#define FOCUS_IN "FOCUS-IN" +#define FOCUS_OUT "FOCUS-OUT" + + + +/* + * The first struct represents the default viewer with the default options. + */ +static +pdf_viewer_t pdf_viewers[] = +{ + {"ar9", "acroread", USE_SENDX, + AR9_WIN_NAME, AR9_WIN_NAME_FMT, + {"-openInNewInstance", NULL}, + {NULL}, + {"Ctrl-R", NULL}, + {"/a", "page=%d", NULL}, + {NULL}, + {"/a", "nameddest=%s", NULL}, + {NULL} + }, + {"ar9-tab", "acroread", USE_SENDX, + AR9_WIN_NAME, AR9_WIN_NAME_FMT, + {NULL}, + {NULL}, + {"Ctrl-R", NULL}, + {"/a", "page=%d", NULL}, + {NULL}, + {"/a", "nameddest='%s'", NULL}, + {NULL} + }, + {"ar8", "acroread", USE_SENDX, + AR8_WIN_NAME, AR8_WIN_NAME_FMT, + {NULL}, + {NULL}, + {"Ctrl-W", FORK_EXEC_CMD, NULL}, + {NULL}, + {NULL}, + {NULL}, + {NULL} + }, + {"ar7", "acroread", USE_SENDX, + AR7_WIN_NAME, AR7_WIN_NAME_FMT, + {NULL}, + {NULL}, + {"Ctrl-W", "Alt-Left", NULL}, + {NULL}, + {NULL}, + {NULL}, + {NULL} + }, + {"ar5", "acroread", USE_SENDX, + AR5_WIN_NAME, AR5_WIN_NAME_FMT, + {NULL}, + {NULL}, + {"Ctrl-W", "Alt-Left", NULL}, + {NULL}, + {NULL}, + {NULL}, + {NULL} + }, + /* + * xpdf also allows 'xpdf -remote tex -reload', but if that xpdf server + * is not running, rather than a failure return, a blank window is + * opened. This is not much good to us. + * Using "tex-server" as the server name is an arbitrary choice. + */ + {"xpdf", "xpdf", USE_SENDX, + XPDF_WIN_NAME, XPDF_WIN_NAME_FMT, + {"-remote", "tex-server", NULL}, + {NULL}, + {"r", NULL}, + {NULL}, + {"%d", NULL}, + {NULL}, + {"+%s", NULL} + }, + {"evince", "evince", USE_SENDX, + EVINCE_WIN_NAME, EVINCE_WIN_NAME_FMT, + {NULL}, + {NULL}, + {"Ctrl-R", NULL}, + {"-i", "%d", NULL}, + {NULL}, + {"-n", "%s", NULL}, + {NULL} + }, +#ifdef TRY_OCULAR + {"okular", "okular", USE_SENDX, + OKULAR_WIN_NAME, OKULAR_WIN_NAME_FMT, + {NULL}, + {NULL}, + {FOCUS_IN, "Fn-F5", FOCUS_OUT, NULL}, + {NULL}, + {NULL}, + {NULL}, + {NULL} + }, +#endif +}; + +#define DEFAULT_VIEWER (pdf_viewers[0].short_name) + + + +static void +usage(void) +{ + int i; + int viewers = sizeof(pdf_viewers) / sizeof(pdf_viewers[0]); + + fprintf(stderr, "This is version %s of %s.\n", VERSION, progname); + fprintf(stderr, "Usage:\n %s [-h|--help|-?]\n" + " Show this help and exit.\n\n", progname); + fprintf(stderr, " %s [-v|--version]\n" + " Show the version number and exit.\n\n", progname); + fprintf(stderr, " %s [-r|--reset_focus] [[-]-viewer <prog>]\n" + "\t\t[-p|--page <n>] [-g|--goto <named-dest>] " + "[--file] <file.pdf>\n", progname); + fprintf(stderr, " If the PDF viewer <prog> is displaying <file.pdf>, " + "reload that file;\n" + " Otherwise call <prog> to display <file.pdf>.\n" + " If '-r' or '--reset_focus' is used, attempt to " + "reset the input focus\n" + " after calling the viewer program.\n" + " If the viewer allows it and is not already " + "running, the argument\n of -p/--page specifies the " + "first page to display.\n" + " If the viewer allows it and is not already " + "running, the argument\n of -g/--goto specifies the " + "named destination to view.\n NOTE: -g overrides -p\n\n"); + fprintf(stderr, "The default viewer program is %s.\n", DEFAULT_VIEWER); + fprintf(stderr, "Implemented viewers:"); + for (i = 0; i < viewers - 1; i++) + fprintf(stderr, " '%s'", pdf_viewers[i].short_name); + fprintf(stderr, " and '%s'.\n", pdf_viewers[viewers - 1].short_name); + fprintf(stderr, "Note: ar9 uses acroread's -openInNewInstance argument," + " ar9-tab does not.\n"); +} + + + +/* + * Send one "command" to the given window. + * The command can be of these forms (for X an upper case letter or arrow + * key, such as "Left", and D one or more digits; see sendx.c): + * - Ctrl-X + * - Alt-X + * - Ctrl-Atl-X + * - Fn-FD + * - FOCUS-[IN|OUT] + * - <string> (not starting with any of the above prefixes) + * Allow other variations on the cases of "Ctrl" and "Alt". + * + * Return 0 on success, non-0 otherwise. + */ + +static int +send_command(const char * window_name, const char * reload_cmd) +{ + int alt_len, ctrl_len, ctrl_alt_len, fn_len, focus_len; + + if (!strcmp(reload_cmd, FORK_EXEC_CMD)) + return 999; + + ctrl_alt_len = strlen(CTRL_ALT); + if (!strncasecmp(CTRL_ALT, reload_cmd, ctrl_alt_len)) + return sendx_controlalt_token(reload_cmd + ctrl_alt_len, window_name); + + ctrl_len = strlen(CTRL); + if (!strncasecmp(CTRL, reload_cmd, ctrl_len)) + return sendx_control_token(reload_cmd + ctrl_len, window_name); + + alt_len = strlen(ALT); + if (!strncasecmp(ALT, reload_cmd, alt_len)) + return sendx_alt_token(reload_cmd + alt_len, window_name); + + fn_len = strlen(FN); + if (!strncasecmp(FN, reload_cmd, fn_len)) + return sendx_token(reload_cmd + fn_len, window_name); + + focus_len = strlen(FOCUS_IN); + if (!strncasecmp(FOCUS_IN, reload_cmd, focus_len)) + return set_focus(window_name); + + focus_len = strlen(FOCUS_OUT); + if (!strncasecmp(FOCUS_OUT, reload_cmd, focus_len)) + return reset_focus(); + + return sendx_string(reload_cmd, window_name); +} + + + +/* + * reload_file(): Try to reload the given file. + * Return 0 on success, non-0 otherwise. + * + * If reset_focus is true, (attempt to) reset the input focus to the + * window which had focus when this program was called. This is + * currently only implemented for the USE_SENDX case. + */ + +static int +reload_file(const char * filename, int viewer_index, int focus_reset) +{ + int success = 0; + pdf_viewer_t pdf_viewer = pdf_viewers[viewer_index]; + const char ** reload_cmds = pdf_viewer.reload_cmds; + char * window_name; + + switch (pdf_viewers[viewer_index].method) + { + case USE_SENDX: + window_name = make_window_name(pdf_viewer.window_name_fmt, filename); + if (window_name == NULL) + return 99; + + if (focus_reset) + (void)set_focus(window_name); + + while (*reload_cmds) + { + /* + * Note: there is a race condition in the sendx.c code which + * can cause the program to crash and burn with a 'BadWindow' + * fault. This has been observed for AR8 (but not AR7, oddly) + * after the ^W causes AR8 to change the window name. It seems + * that Window_With_Name() tries to access a BadWindow within + * its recursive call. + * If this continues to be a problem, a usleep() may make the + * problem go away. + */ + success = ! send_command(window_name, *reload_cmds); + if (! success && reload_cmds != pdf_viewer.reload_cmds) + { + /* + * In some cases the window name might be changed because + * of the first command. + * For example, in AR7 the first command (^W) "closes" + * the document, and the window title changes to reflect + * the fact there is no document. So try that command with + * the "plain" window name. + */ + success = ! send_command(pdf_viewer.window_name, *reload_cmds); + } + if (! success) + break; + reload_cmds++; + } + if (focus_reset) + (void)reset_focus(); + break; + + case USE_FORK_EXEC: + return 2; /* TODO: someone who cares can put some code here */ + break; + + default: + fprintf(stderr, "%s: internal error: invalid reload_method. Sorry.\n", + progname); + return 99; + break; + } + + if (success) + return 0; + + return 1; +} + +/* + * view_file(): (Attempt to) reload or view the given filename. + * + * First call reload_file() in case the given viewer is already + * displaying the given file. + * + * If that is unsuccessful, try to start up a new instance of the + * given viewer with the given file. + * + * If dest != NULL, and the viewer allows it, on initial opening of + * the file go to that named destination. + * As of V 0.85, this is implemented for xpdf, evince, and, according + * to the man page for acroread 9.5.5, for ar9. + * Otherwise, if the viewer allows it, open the document at the given + * page. + */ + +static int +view_file(const char * filename, int viewer_index, int focus_reset, + int initial_page, char * dest) +{ + pid_t pid; + pdf_viewer_t pdf_viewer = pdf_viewers[viewer_index]; + const char * argv_list[2 * MAX_OPTIONS + 3]; + const char ** p; + int i = 0; + + /* First try to reload the file */ + if (reload_file(filename, viewer_index, focus_reset) == 0) + { + /* Success! */ + return 0; + } + + /* + * No luck re-loading the file. + * (Try to) start a new instance of the viewer program. + * Start by forking into the background. + */ + pid = fork(); + if (pid < 0) + { + fprintf(stderr, "%s: fork() failed!?\n", progname); + return 10; + } + if (pid > 0) + return 0; + + /* Child code: */ + argv_list[i++] = pdf_viewer.program_name; + for (p = pdf_viewer.exec_pre_options; *p;) + argv_list[i++] = *p++; + + if (pdf_viewer.initial_page_pre_options[0] != NULL && dest == NULL) + { + int j = 0; + char * buf; + + while (pdf_viewer.initial_page_pre_options[j + 1] != NULL) + argv_list[i++] = pdf_viewer.initial_page_pre_options[j++]; + + /* 10 is more than enough for the page number */ + buf = malloc(strlen(pdf_viewer.initial_page_pre_options[j]) + 10); + if (buf != NULL) + { + /* 1e8 or more pages? I doubt it. */ + sprintf(buf, pdf_viewer.initial_page_pre_options[j], + initial_page > 99999999 ? 1 : initial_page); + argv_list[i++] = buf; + } + else + fprintf(stderr, "%s: unable to allocate memory for page " + "specification!!\n" + "Crossing fingers and continuing.", progname); + } + + if (pdf_viewer.initial_dest_pre_options[0] != NULL && dest != NULL) + { + int j = 0; + char * buf; + + while (pdf_viewer.initial_dest_pre_options[j + 1] != NULL) + argv_list[i++] = pdf_viewer.initial_dest_pre_options[j++]; + + buf = malloc(strlen(pdf_viewer.initial_dest_pre_options[j]) + + strlen(dest) + 1); + if (buf != NULL) + { + sprintf(buf, pdf_viewer.initial_dest_pre_options[j], dest); + argv_list[i++] = buf; + } + else + fprintf(stderr, "%s: unable to allocate memory for named-dest " + "specification!!\n" + "Crossing fingers and continuing.", progname); + } + + argv_list[i++] = filename; + + if (pdf_viewer.initial_page_post_options[0] != NULL && dest == NULL) + { + int j = 0; + char * buf; + + while (pdf_viewer.initial_page_post_options[j + 1] != NULL) + argv_list[i++] = pdf_viewer.initial_page_post_options[j++]; + + buf = malloc(strlen(pdf_viewer.initial_page_post_options[j]) + 10); + if (buf != NULL) + { + sprintf(buf, pdf_viewer.initial_page_post_options[j], + initial_page > 99999999 ? 1 : initial_page); + argv_list[i++] = buf; + } + else + fprintf(stderr, "%s: unable to allocate memory for page " + "specification!!\n" + "Crossing fingers and continuing.", progname); + } + + if (pdf_viewer.initial_dest_post_options[0] != NULL && dest != NULL) + { + int j = 0; + char * buf; + + while (pdf_viewer.initial_dest_post_options[j + 1] != NULL) + argv_list[i++] = pdf_viewer.initial_dest_post_options[j++]; + + buf = malloc(strlen(pdf_viewer.initial_dest_post_options[j]) + + strlen(dest) + 1); + if (buf != NULL) + { + sprintf(buf, pdf_viewer.initial_dest_post_options[j], dest); + argv_list[i++] = buf; + } + else + fprintf(stderr, "%s: unable to allocate memory for named-dest " + "specification!!\n" + "Crossing fingers and continuing.", progname); + } + + argv_list[i++] = NULL; +#ifdef DEBUG + { + int k = 0; + if (dest == NULL) + fprintf(stderr, "dest == NULL\n"); + else + fprintf(stderr, "dest == '%s'\n", dest); + for (; k < i-1; k++) + fprintf(stderr, "%s\n", argv_list[k]); + } +#endif + execvp(pdf_viewer.program_name, (char **)argv_list); + + /* If we are here, Something Bad happened. */ + fprintf(stderr, "%s: %s startup failed\n", progname, + pdf_viewer.program_name); + return 5; +} + + + +int +main(int argc, char * argv[]) +{ + const char * viewer = pdf_viewers[0].short_name; + char * env_viewer; + char * file = NULL; + char * dest = NULL; + int i; + int initial_page = 1; + int viewer_index = -1; + int focus_reset = 0; + + progname = argv[0]; + argc--; + argv++; + + env_viewer = getenv("PDF_VIEWER"); + if (env_viewer != NULL) + viewer = env_viewer; + + if (argc < 1 || !strcmp(argv[0], "-h") || !strcmp(argv[0], "--help") + || !strcmp(argv[0], "-?")) + { + usage(); + return argc < 1 ? EXIT_FAILURE : EXIT_SUCCESS; + } + + if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "-V") + || !strcmp(argv[0], "--version")) + { + printf("This is pdfopen version %s\n", VERSION); + return EXIT_SUCCESS; + } + + while (argc > 0) + { + if (!strcmp(argv[0], "--reset_focus") || !strcmp(argv[0], "-r")) + { + argc--; + argv++; + focus_reset = 1; + continue; + } + + if (argc >= 2 + && (!strcmp(argv[0], "-viewer") || !strcmp(argv[0], "--viewer"))) + { + viewer = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if (argc >= 2 + && (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--goto"))) + { + dest = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if (argc >= 2 && !strcmp(argv[0], "--file")) + { + file = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if (argc >= 2 + && (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--page"))) + { + initial_page = atoi(argv[1]); + argc -= 2; + argv += 2; + continue; + } + + break; + } + + /* + * Should either have no args left (--file seen above) or + * --file was not seen and there is one arg left. + */ + if ( ! ((argc == 0 && file != NULL) || (argc == 1 && file == NULL)) ) + { + fprintf(stderr, "%s: invalid argument(s)\n", progname); + usage(); + return EXIT_FAILURE; + } + + if (argc == 1) + file = argv[0]; + + for (i = 0; i < sizeof(pdf_viewers) / sizeof(pdf_viewers[0]); i++) + { + if (!strcmp(pdf_viewers[i].short_name, viewer)) + { + viewer_index = i; + break; + } + } + + if (viewer_index < 0) + { + fprintf(stderr, "%s: Unknown PDF viewer '%s'\n", progname, viewer); + usage(); + + return EXIT_FAILURE; + } + + if (view_file(file, viewer_index, focus_reset, initial_page, dest)) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.c b/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.c new file mode 100644 index 00000000000..1fd4f0dbdc6 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.c @@ -0,0 +1,424 @@ +/* + * Modified by Jim Diamond (jim.diamond@acadiau.ca) April 24, 2010 + * to reset error_status to 0 at the beginning of open_channel(). + * + * Also replaced 0xfff with KeyPressMask and KeyReleaseMask (as + * appropriate) in sendx_channel(); otherwise (at least in Slackware64 13.0) + * the events also get sent to the terminal running pdfopen; this is a Bad + * Thing. + * + * Also added set_focus() and reset_focus() functions. + * + * January 27, 2012 note: + * NOTE: to make reset_focus() work, at least under FVWM2 on + * Slackware64-13.37 when using AR9, I needed to call XOpenDisplay() + * again (since close_channel() has generally been called since + * set_focus() was called), I needed to sleep a bit (perhaps < 1 second + * is fine, and perhaps other systems might need more, I dunno), and I + * needed to call XFlush(). If someone who understands why the code + * here opens and closes the display for every sendx_<something>() can + * explain why that makes sense, or why I need the sleep() and the + * XFlush(), I'd be happy to be enlightened. + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include <X11/cursorfont.h> + +#include "sendx.h" + +static char * display_name = NULL; +static Display * display; +static Window root; +static Window window = None; +static XKeyEvent event; + +static char error_message[256]; +static int error_status = 0; + + +static void +throw_exception3(const char * msg, const char * s, int i) +{ + sprintf(error_message, msg, s, i); + error_status = 1; +} + + +static void +throw_exception3s(const char * msg1, const char * msg2, const char * msg3) +{ + sprintf(error_message, msg1, msg2, msg3); + error_status = 1; +} + + +static void +throw_exception(const char * msg) +{ + strncpy(error_message, msg, 256); + error_status = 1; +} + + + +/* + * Added for window managers like swm and tvtwm that follow solbourne's + * virtual root window concept + */ +static Window +GetRootWindow(Display * disp, int scrn) +{ + Atom __SWM_VROOT = None; + Window root, rootReturn, parentReturn, * children; + unsigned int numChildren; + unsigned i; + + root = RootWindow(disp, scrn); + + /* + * see if there is a virtual root + */ + __SWM_VROOT = XInternAtom(disp, "__SWM_VROOT", False); + XQueryTree(disp, root, &rootReturn, &parentReturn, &children, &numChildren); + + for (i = 0; i < numChildren; i++) + { + Atom actual_type; + int actual_format; + unsigned long nitems, bytesafter; + unsigned char * prop_return = NULL; + + if (XGetWindowProperty(disp, children[i], __SWM_VROOT, 0, 1, + False, XA_WINDOW, &actual_type, &actual_format, + &nitems, &bytesafter, &prop_return) + == Success && prop_return) + { + root = *(Window *)prop_return; + break; + } + } + + if (children) + XFree((char *)children); + + return (root); +} + + + +/* + * [These functions are from the file "dsimple.c" used with xwininfo.] + * + * Written by Mark Lillibridge. Last updated 7/1/87 + * + * Window_With_Name: routine to locate a window with a given name on a + * display. If no window with the given name is found, 0 is returned. + * If more than one window has the given name, the first one found + * will be returned. Only top and its subwindows are looked at. + * Normally, top should be the Root Window. + */ + +static Window +Window_With_Name(Display * dpy, Window top, const char * name) +{ + Window * children, dummy; + unsigned int nchildren; + unsigned i; + Window w = 0; + char * window_name; + + if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name)) + return (top); + + if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren)) + return (0); + + for (i = 0; i < nchildren; i++) + { + w = Window_With_Name(dpy, children[i], name); + if (w) + break; + } + + if (children) + XFree((char *)children); + + return (w); +} + + + +static int +open_channel(const char * wname) +{ + /* + * display_name = ":0.0"; + */ + + error_status = 0; + + if ((display = XOpenDisplay(display_name)) == NULL) + { + throw_exception("can't open display"); + return 1; + } + + if ((root = GetRootWindow(display, DefaultScreen(display))) == 0) + { + throw_exception("Cannot get DefaultScreen"); + return 1; + } + + if ((wname[0] == '\0') && (window != None)) + { + } /* take selected window */ + else if (wname[0] != '\0') + { + if ((window = Window_With_Name(display, root, wname)) == None) + { + throw_exception3s("Display %s: can't open window named \"%s\"", + XDisplayName(display_name), wname); + return 1; + } + } + else + { + throw_exception3("bad condition in %s at line %d", __FILE__, __LINE__); + return 1; + } + + event.type = KeyPress; + event.serial = 0; + event.send_event = False; + event.display = display; + event.x = event.y = event.x_root = event.y_root = 0; + event.time = CurrentTime; + event.same_screen = True; + event.subwindow = None; + event.window = window; + event.root = root; + + return 0; +} + + + +static void +close_channel(void) +{ + /* + * XFlush(display); + */ + XCloseDisplay(display); +} + + + +static void +sendx_channel(KeySym ks, int km) +{ + /* + * km: 0=regular, 1=shift, 2=lock, 4=control + */ + if (ks < 256) + { + event.state = isupper((unsigned char)ks); + switch (ks) + { + case 0x08: + ks = XK_BackSpace; + break; + case 0x09: + ks = XK_Tab; + break; + case 0x0A: + ks = XK_Linefeed; + break; + case 0x0B: + ks = XK_Clear; + break; + case 0x0D: + ks = XK_Return; + break; + case 0x13: + ks = XK_Pause; + break; + case 0x14: + ks = XK_Scroll_Lock; + break; + case 0x1B: + ks = XK_Escape; + break; + } + } + else + event.state = 0; + + event.type = KeyPress; + event.state = km; // Mod1Mask + event.keycode = XKeysymToKeycode(display, ks); + + if (XSendEvent(display, window, True, KeyPressMask, (XEvent *)&event) == 0) + throw_exception("Error in XSendEvent"); + + event.type = KeyRelease; + if (XSendEvent(display, window, True, KeyReleaseMask, (XEvent *)&event) + == 0) + throw_exception("Error in XSendEvent"); + + return; +} + + + +int +sendx_string(const char * string, const char * window) +{ + const char * p; + + if (open_channel(window)) + return error_status; + + p = string; + while (*p) + sendx_channel(*p++, 0); + close_channel(); + + return error_status; +} + + + +int +sendx_token(const char * string, const char * window) +{ + if (open_channel(window)) + return error_status; + + sendx_channel(XStringToKeysym(string), 0); + close_channel(); + + return error_status; +} + + + +int +sendx_alt_token(const char * string, const char * window) +{ + if (open_channel(window)) + return error_status; + + sendx_channel(XStringToKeysym(string), Mod1Mask); + close_channel(); + + return error_status; +} + + + +int +sendx_controlalt_token(const char * string, const char * window) +{ + if (open_channel(window)) + return error_status; + + sendx_channel(XStringToKeysym(string), Mod1Mask | ControlMask); + close_channel(); + + return error_status; +} + + + +int +sendx_control_token(const char * string, const char * window) +{ + if (open_channel(window)) + return error_status; + + sendx_channel(XStringToKeysym(string), ControlMask); + close_channel(); + + return error_status; +} + + + + +static Window previous_window; +static int previous_window_set = 0; +static int revert_to; + +/* + * Attempt to give focus to the given window. + * Return 0 on success, non-0 on failure. + * Record the previous window for reset_focus() on success. + */ + +int +set_focus(const char * wname) +{ + if ((display = XOpenDisplay(display_name)) == NULL) + { + throw_exception("can't open display"); + return 1; + } + + if ((root = GetRootWindow(display, DefaultScreen(display))) == 0) + { + throw_exception("Cannot get DefaultScreen"); + return 1; + } + + (void)XGetInputFocus(display, &previous_window, &revert_to); + if (XSetInputFocus(display, Window_With_Name(display, root, wname), + previous_window, CurrentTime)) + { + previous_window_set = 1; + return 0; + } + + throw_exception3s("Display %s: can't focus window named \"%s\"", + XDisplayName(display_name), wname); + return 1; +} + + + +int +reset_focus(void) +{ + if (previous_window_set) + { + sleep(1); + if ((display = XOpenDisplay(display_name)) == NULL) + { + throw_exception("can't open display"); + return 1; + } + + XSetInputFocus(display, previous_window, revert_to, CurrentTime); + XFlush(display); + previous_window_set = 0; + return 0; + } + + throw_exception("reset_focus() called when previous window not saved"); + return 1; +} + + + +/* + * void PrintKeySyms () { int i; for (i = 32; i < 127; i++) { printf ("%s[%c] + * ", XKeysymToString (i), i); } for (i = 128 + 32; i < 128 + 127; i++) { + * printf ("%s[%c] ", XKeysymToString (i), i); } printf ("\n"); } + */ diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.h b/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.h new file mode 100644 index 00000000000..569a33f9494 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/sendx.h @@ -0,0 +1,19 @@ +/* + * sendx.h: declare prototypes for functions defined in sendx.c + * + * Copyright (C) 2009 Peter Breitenlohner <tex-live@tug.org> + * You may freely use, modify and/or distribute this file. + */ + +#ifndef SENDX_H +#define SENDX_H + +extern int sendx_string(const char * string, const char * wname); +extern int sendx_token(const char * string, const char * wname); +extern int sendx_alt_token(const char * string, const char * wname); +extern int sendx_controlalt_token(const char * string, const char * wname); +extern int sendx_control_token(const char * string, const char * wname); +extern int set_focus(const char * wname); +extern int reset_focus(void); + +#endif diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.c b/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.c new file mode 100644 index 00000000000..5201b2dba58 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.c @@ -0,0 +1,45 @@ +/* + * utils.c: Functions common to pdfopen and pdfclose. + * + * Copyright (C) 2010--2014 Jim Diamond <jim.diamond@acadiau.ca> + * You may freely use, modify and/or distribute this file. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utils.h" +#include "xpdfopen.h" +#include "externs.h" + +/* + * Allocate memory and create a window name. + * Return a pointer to the new string or NULL on failure. + * + * The caller is responsible for free()ing the memory allocated here. + * + * Note: acroread (at least AR 7, 8, 9) uses only the basename in the + * window title. + * xpdf uses the whole file name. + * Other PDF viewers may need other treatment. + */ + +char * +make_window_name(const char * fmt, const char * filename) +{ + char * window_name; + const char * title_name; + + title_name = filename; + if (strrchr(title_name, '/') != NULL + && strncasecmp(fmt, XPDF_WIN_NAME, strlen(XPDF_WIN_NAME))) + title_name = strrchr(title_name, '/') + 1; + + window_name = malloc(strlen(fmt) + strlen(title_name) + 1); + if (window_name != NULL) + sprintf(window_name, fmt, title_name); + else + fprintf(stderr, "%s: out of memory\n", progname); + + return window_name; +} diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.h b/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.h new file mode 100644 index 00000000000..b9fe88574cb --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/utils.h @@ -0,0 +1,13 @@ +/* + * utils.h: declare prototypes for functions defined in utils.c + * + * Copyright (C) 2010--2014 Jim Diamond <jim.diamond@acadiau.ca> + * You may freely use, modify and/or distribute this file. + */ + +#ifndef UTILS_H +#define UTILS_H + +char * make_window_name(const char * fmt, const char * basename); + +#endif diff --git a/Build/source/utils/xpdfopen/xpdfopen-0.86/xpdfopen.h b/Build/source/utils/xpdfopen/xpdfopen-0.86/xpdfopen.h new file mode 100644 index 00000000000..bd40be932c8 --- /dev/null +++ b/Build/source/utils/xpdfopen/xpdfopen-0.86/xpdfopen.h @@ -0,0 +1,41 @@ +/* + * xpdfopen.h: declare constants of possible use for xpdfopen programs. + * + * Copyright (C) 2010--2014 Jim Diamond <jim.diamond@acadiau.ca> + * + * You may freely use, modify and/or distribute this file. + */ + +#ifndef XPDFOPEN_H +#define XPDFOPEN_H + +#define VERSION "0.86" + +/* + * <prog>_WIN_NAME is the name of the window when no file is open. + * <prog>_WIN_NAME_FMT is the (sprintf) format to generate the name + * when a file is being displayed. + */ + +#define AR5_WIN_NAME "Acrobat Reader" /* Is this correct? */ +#define AR5_WIN_NAME_FMT "%s" /* Is this correct? */ + +#define AR7_WIN_NAME "Adobe Reader" +#define AR7_WIN_NAME_FMT AR7_WIN_NAME " - %s" + +#define AR8_WIN_NAME "Adobe Reader" +#define AR8_WIN_NAME_FMT "%s - " AR8_WIN_NAME + +#define AR9_WIN_NAME "Adobe Reader" +#define AR9_WIN_NAME_FMT "%s - " AR9_WIN_NAME + +#define XPDF_WIN_NAME "Xpdf" +#define XPDF_WIN_NAME_FMT XPDF_WIN_NAME ": %s" + +#define EVINCE_WIN_NAME "evince" +#define EVINCE_WIN_NAME_FMT "%s" + +#define OKULAR_WIN_NAME "Okular" +#define OKULAR_WIN_NAME_FMT "%s - " OKULAR_WIN_NAME + +#endif |