File diff-pdf-0.5.obscpio of Package diff-pdf

07070100000000000081A4000003E800000064000000016039353E0000035A000000000000000000000000000000000000001B00000000diff-pdf-0.5/.appveyor.ymlimage:
- Ubuntu
- Visual Studio 2019

for:
-
  matrix:
    except:
      - image: Ubuntu
  environment:
    MSYSTEM: MINGW32
    PATH: C:\msys64\%MSYSTEM%\bin;C:\msys64\usr\bin;%PATH%
    CHERE_INVOKING: 1


install:
  - sh: sudo apt-get update
  - sh: sudo apt-get --yes install libpoppler-glib-dev poppler-utils libwxgtk3.0-dev
  - cmd: sh -lc "pacman --noconfirm -Syuu"
  - cmd: sh -lc "pacman --noconfirm -S zip mingw-w64-i686-{poppler,wxWidgets}"

build_script:
  - sh: ./bootstrap && ./configure && make
  - cmd: sh -lc "./bootstrap && ./configure && make"

after_build:
  - sh: make dist
  - sh: appveyor PushArtifact diff-pdf*.tar.gz
  - cmd: sh -lc "make windows-dist"
  - ps: Get-ChildItem .\diff-pdf*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }

deploy:
  provider: Environment
  name: github
  on:
    APPVEYOR_REPO_TAG: true
07070100000001000081A4000003E800000064000000016039353E0000003E000000000000000000000000000000000000001500000000diff-pdf-0.5/AUTHORS
 Developers:
-------------

Vaclav Slavik <vaclav@slavik.io>
07070100000002000081A4000003E800000064000000016039353E00004652000000000000000000000000000000000000001500000000diff-pdf-0.5/COPYING		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	    How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    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 2 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, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year  name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
07070100000003000081A4000003E800000064000000016039353E00000061000000000000000000000000000000000000001B00000000diff-pdf-0.5/COPYING.icons

The gtk-zoom-in.xpm and gtk-zoom-out.xpm icons are under LGPL and were taken
from GTK+ 2.16.5.
07070100000004000081A4000003E800000064000000016039353E00000275000000000000000000000000000000000000001900000000diff-pdf-0.5/Makefile.am
bin_PROGRAMS = diff-pdf

diff_pdf_SOURCES = \
			diff-pdf.cpp \
			bmpviewer.cpp \
			bmpviewer.h \
			gutter.cpp \
			gutter.h

diff_pdf_CXXFLAGS = $(POPPLER_CFLAGS) $(WX_CXXFLAGS)
diff_pdf_LDADD = $(POPPLER_LIBS) $(WX_LIBS)

EXTRA_DIST = bootstrap gtk-zoom-in.xpm gtk-zoom-out.xpm README.md win32/fonts.conf win32/collect-dlls.sh

windows-dist: diff-pdf-win-$(VERSION).zip

diff-pdf-win-$(VERSION).zip: all
	rm -rf $@ windist
	$(srcdir)/win32/collect-dlls.sh windist diff-pdf.exe
	mkdir -p windist/fonts && cp -a $(srcdir)/win32/fonts.conf windist/fonts/
	(cd windist && zip -9r ../$@ .)
	rm -rf windist

.PHONY: windows-dist
07070100000005000081A4000003E800000064000000016039353E0000129D000000000000000000000000000000000000001700000000diff-pdf-0.5/README.md*Note: this repository is provided **as-is** and the code is not being actively
developed. If you wish to improve it, that's greatly appreciated: please make
the changes and submit a pull request, I'll gladly merge it or help you out
with finishing it. However, please do not expect any kind of support, including
implementation of feature requests or fixes. If you're not a developer and/or
willing to get your hands dirty, this tool is probably not for you.*

[![Build status](https://ci.appveyor.com/api/projects/status/m6d8n2kcyvk3cqi6?svg=true)](https://ci.appveyor.com/project/vslavik/diff-pdf)

## Usage

diff-pdf is a tool for visually comparing two PDFs.

It takes two PDF files as arguments. By default, its only output is its return
code, which is 0 if there are no differences and 1 if the two PDFs differ. If
given the `--output-diff` option, it produces a PDF file with visually
highlighted differences:

```
$ diff-pdf --output-diff=diff.pdf a.pdf b.pdf
```

Another option is to compare the two files visually in a simple GUI, using
the `--view` argument:

```
$ diff-pdf --view a.pdf b.pdf
```

This opens a window that lets you view the files' pages and zoom in on details.
It is also possible to shift the two pages relatively to each other using
Ctrl-arrows (Cmd-arrows on MacOS). This is useful for identifying translation-only differences.

See the output of `$ diff-pdf --help` for complete list of options.


## Obtaining the binaries

Precompiled version of the tool for Windows is available as part of
[the latest release](https://github.com/vslavik/diff-pdf/releases/tag/v0.5)
as a ZIP archive, which contains everything you need to run diff-pdf. It will
work from any place you unpack it to.

On Mac, if you use [Homebrew](https://brew.sh), you can use it to install diff-pdf with it:
```
$ brew install diff-pdf
```
On Mac, if you use [Macports](https://macports.org), you can install diff-pdf with:
```
$ port install diff-pdf
```
On  Fedora and CentOS 8:
```
$ sudo dnf install diff-pdf
```
Precompiled version for openSUSE can be downloaded from the
[openSUSE build service](http://software.opensuse.org).


## Compiling from sources

The build system uses Automake and so a Unix or Unix-like environment (Cygwin
or MSYS) is required. Compilation is done in the usual way:

```
$ ./bootstrap
$ ./configure
$ make
$ make install
```

(Note that the first step, running the `./bootstrap` script, is only required
when building sources checked from version control system, i.e. when `configure`
and `Makefile.in` files are missing.)

As for dependencies, diff-pdf requires the following libraries:

- wxWidgets >= 3.0
- Cairo >= 1.4
- Poppler >= 0.10

#### CentOS:

```
$ sudo yum groupinstall "Development Tools"
$ sudo yum install wxGTK wxGTK-devel poppler-glib poppler-glib-devel
```

#### Ubuntu:

```
$ sudo apt-get install make automake g++
$ sudo apt-get install libpoppler-glib-dev poppler-utils libwxgtk3.0-gtk3-dev
```

#### macOS:
Install Command Line Tools for Xcode:

```
$ xcode-select --install
```

and install [Homebrew](https://brew.sh) or [MacPorts](https://www.macports.org) to manage dependencies, then:

```
$ brew install automake autoconf wxmac poppler cairo pkg-config
```

or

```
$ sudo port install automake autoconf wxWidgets-3.0 poppler cairo pkgconfig
```

Note that many more libraries are required on Windows, where none of the
libraries Cairo and Poppler use are normally available. At the time of writing,
transitive cover of the above dependencies included fontconfig, freetype, glib,
libpng, pixman, gettext, libiconv, libjpeg and zlib.


### Compiling on Windows using MSYS + MinGW

1. First of all, you will need working MinGW installation with MSYS2 environment
and C++ compiler. Install MSYS2 by following [their instructions](https://www.msys2.org).

1. Once installed, launch the MSYS2 MinGW shell. It will open a terminal window;
type `cd /c/directory/with/diff-pdf` to go to the directory with diff-pdf
sources.

1. You will need to install additional MSYS components that are not normally
included with MSYS, using these commands:

    ```
    $ pacman -Syu
    $ pacman -S automake autoconf pkg-config make zip
    $ pacman -S mingw-w64-i686-{gcc,poppler,wxWidgets}
    ```

1. Build diff-pdf in the same way as in the instructions for Unix above:

    ```
    $ ./bootstrap  # only if building from git repository
    $ ./configure
    $ make
    ```

1. To build a ZIP archive will all DLLs, run
    ```
    $ make windows-dist
    ```


## Installing

On Unix, the usual `make install` is sufficient.

On Windows, installation is not necessary, just copy the files somewhere. If
you built it following the instructions above, all the necessary files will be
in the created ZIP archive.
07070100000006000041ED000003E800000064000000026039353E00000000000000000000000000000000000000000000001300000000diff-pdf-0.5/admin07070100000007000081A4000003E800000064000000016039353E00009E71000000000000000000000000000000000000001C00000000diff-pdf-0.5/admin/wxwin.m4dnl ---------------------------------------------------------------------------
dnl Author:          wxWidgets development team,
dnl                  Francesco Montorsi,
dnl                  Bob McCown (Mac-testing)
dnl Creation date:   24/11/2001
dnl ---------------------------------------------------------------------------

dnl ===========================================================================
dnl Table of Contents of this macro file:
dnl -------------------------------------
dnl
dnl SECTION A: wxWidgets main macros
dnl  - WX_CONFIG_OPTIONS
dnl  - WX_CONFIG_CHECK
dnl  - WXRC_CHECK
dnl  - WX_STANDARD_OPTIONS
dnl  - WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS
dnl  - WX_DETECT_STANDARD_OPTION_VALUES
dnl
dnl SECTION B: wxWidgets-related utilities
dnl  - WX_LIKE_LIBNAME
dnl  - WX_ARG_ENABLE_YESNOAUTO
dnl  - WX_ARG_WITH_YESNOAUTO
dnl
dnl SECTION C: messages to the user
dnl  - WX_STANDARD_OPTIONS_SUMMARY_MSG
dnl  - WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN
dnl  - WX_STANDARD_OPTIONS_SUMMARY_MSG_END
dnl  - WX_BOOLOPT_SUMMARY
dnl
dnl The special "WX_DEBUG_CONFIGURE" variable can be set to 1 to enable extra
dnl debug output on stdout from these macros.
dnl ===========================================================================


dnl ---------------------------------------------------------------------------
dnl Macros for wxWidgets detection. Typically used in configure.in as:
dnl
dnl     AC_ARG_ENABLE(...)
dnl     AC_ARG_WITH(...)
dnl        ...
dnl     WX_CONFIG_OPTIONS
dnl        ...
dnl        ...
dnl     WX_CONFIG_CHECK([2.6.0], [wxWin=1])
dnl     if test "$wxWin" != 1; then
dnl        AC_MSG_ERROR([
dnl                wxWidgets must be installed on your system
dnl                but wx-config script couldn't be found.
dnl
dnl                Please check that wx-config is in path, the directory
dnl                where wxWidgets libraries are installed (returned by
dnl                'wx-config --libs' command) is in LD_LIBRARY_PATH or
dnl                equivalent variable and wxWidgets version is 2.3.4 or above.
dnl        ])
dnl     fi
dnl     CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS"
dnl     CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY"
dnl     CFLAGS="$CFLAGS $WX_CFLAGS_ONLY"
dnl
dnl     LIBS="$LIBS $WX_LIBS"
dnl
dnl If you want to support standard --enable-debug/unicode/shared options, you
dnl may do the following:
dnl
dnl     ...
dnl     AC_CANONICAL_SYSTEM
dnl
dnl     # define configure options
dnl     WX_CONFIG_OPTIONS
dnl     WX_STANDARD_OPTIONS([debug,unicode,shared,toolkit,wxshared])
dnl
dnl     # basic configure checks
dnl     ...
dnl
dnl     # we want to always have DEBUG==WX_DEBUG and UNICODE==WX_UNICODE
dnl     WX_DEBUG=$DEBUG
dnl     WX_UNICODE=$UNICODE
dnl
dnl     WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS
dnl     WX_CONFIG_CHECK([2.8.0], [wxWin=1],,[html,core,net,base],[$WXCONFIG_FLAGS])
dnl     WX_DETECT_STANDARD_OPTION_VALUES
dnl
dnl     # write the output files
dnl     AC_CONFIG_FILES([Makefile ...])
dnl     AC_OUTPUT
dnl
dnl     # optional: just to show a message to the user
dnl     WX_STANDARD_OPTIONS_SUMMARY_MSG
dnl
dnl ---------------------------------------------------------------------------


dnl ---------------------------------------------------------------------------
dnl WX_CONFIG_OPTIONS
dnl
dnl adds support for --wx-prefix, --wx-exec-prefix, --with-wxdir and
dnl --wx-config command line options
dnl ---------------------------------------------------------------------------

AC_DEFUN([WX_CONFIG_OPTIONS],
[
    AC_ARG_WITH(wxdir,
                [  --with-wxdir=PATH       Use uninstalled version of wxWidgets in PATH],
                [ wx_config_name="$withval/wx-config"
                  wx_config_args="--inplace"])
    AC_ARG_WITH(wx-config,
                [  --with-wx-config=CONFIG wx-config script to use (optional)],
                wx_config_name="$withval" )
    AC_ARG_WITH(wx-prefix,
                [  --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional)],
                wx_config_prefix="$withval", wx_config_prefix="")
    AC_ARG_WITH(wx-exec-prefix,
                [  --with-wx-exec-prefix=PREFIX
                          Exec prefix where wxWidgets is installed (optional)],
                wx_config_exec_prefix="$withval", wx_config_exec_prefix="")
])

dnl Helper macro for checking if wx version is at least $1.$2.$3, set's
dnl wx_ver_ok=yes if it is:
AC_DEFUN([_WX_PRIVATE_CHECK_VERSION],
[
    wx_ver_ok=""
    if test "x$WX_VERSION" != x ; then
      if test $wx_config_major_version -gt $1; then
        wx_ver_ok=yes
      else
        if test $wx_config_major_version -eq $1; then
           if test $wx_config_minor_version -gt $2; then
              wx_ver_ok=yes
           else
              if test $wx_config_minor_version -eq $2; then
                 if test $wx_config_micro_version -ge $3; then
                    wx_ver_ok=yes
                 fi
              fi
           fi
        fi
      fi
    fi
])

dnl ---------------------------------------------------------------------------
dnl WX_CONFIG_CHECK(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND
dnl                  [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]])
dnl
dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC
dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME
dnl environment variable to override the default name of the wx-config script
dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this
dnl case the macro won't even waste time on tests for its existence.
dnl
dnl Optional WX-LIBS argument contains comma- or space-separated list of
dnl wxWidgets libraries to link against. If it is not specified then WX_LIBS
dnl and WX_LIBS_STATIC will contain flags to link with all of the core
dnl wxWidgets libraries.
dnl
dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config
dnl invocation command in present. It can be used to fine-tune lookup of
dnl best wxWidgets build available.
dnl
dnl Example use:
dnl   WX_CONFIG_CHECK([2.6.0], [wxWin=1], [wxWin=0], [html,core,net]
dnl                    [--unicode --debug])
dnl ---------------------------------------------------------------------------

dnl
dnl Get the cflags and libraries from the wx-config script
dnl
AC_DEFUN([WX_CONFIG_CHECK],
[
  dnl do we have wx-config name: it can be wx-config or wxd-config or ...
  if test x${WX_CONFIG_NAME+set} != xset ; then
     WX_CONFIG_NAME=wx-config
  fi

  if test "x$wx_config_name" != x ; then
     WX_CONFIG_NAME="$wx_config_name"
  fi

  dnl deal with optional prefixes
  if test x$wx_config_exec_prefix != x ; then
     wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix"
     WX_LOOKUP_PATH="$wx_config_exec_prefix/bin"
  fi
  if test x$wx_config_prefix != x ; then
     wx_config_args="$wx_config_args --prefix=$wx_config_prefix"
     WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin"
  fi
  if test "$cross_compiling" = "yes"; then
     wx_config_args="$wx_config_args --host=$host_alias"
  fi

  dnl don't search the PATH if WX_CONFIG_NAME is absolute filename
  if test -x "$WX_CONFIG_NAME" ; then
     AC_MSG_CHECKING(for wx-config)
     WX_CONFIG_PATH="$WX_CONFIG_NAME"
     AC_MSG_RESULT($WX_CONFIG_PATH)
  else
     AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH")
  fi

  if test "$WX_CONFIG_PATH" != "no" ; then
    WX_VERSION=""

    min_wx_version=ifelse([$1], ,2.2.1,$1)
    if test -z "$5" ; then
      AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version])
    else
      AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)])
    fi

    dnl don't add the libraries ($4) to this variable as this would result in
    dnl an error when it's used with --version below
    WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5"

    WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null`
    wx_config_major_version=`echo $WX_VERSION | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
    wx_config_minor_version=`echo $WX_VERSION | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
    wx_config_micro_version=`echo $WX_VERSION | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`

    wx_requested_major_version=`echo $min_wx_version | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
    wx_requested_minor_version=`echo $min_wx_version | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
    wx_requested_micro_version=`echo $min_wx_version | \
           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`

    _WX_PRIVATE_CHECK_VERSION([$wx_requested_major_version],
                              [$wx_requested_minor_version],
                              [$wx_requested_micro_version])

    if test -n "$wx_ver_ok"; then
      AC_MSG_RESULT(yes (version $WX_VERSION))
      WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $4`

      dnl is this even still appropriate?  --static is a real option now
      dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is
      dnl what the user actually wants, making this redundant at best.
      dnl For now keep it in case anyone actually used it in the past.
      AC_MSG_CHECKING([for wxWidgets static library])
      WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $4 2>/dev/null`
      if test "x$WX_LIBS_STATIC" = "x"; then
        AC_MSG_RESULT(no)
      else
        AC_MSG_RESULT(yes)
      fi

      dnl starting with version 2.2.6 wx-config has --cppflags argument
      wx_has_cppflags=""
      if test $wx_config_major_version -gt 2; then
        wx_has_cppflags=yes
      else
        if test $wx_config_major_version -eq 2; then
           if test $wx_config_minor_version -gt 2; then
              wx_has_cppflags=yes
           else
              if test $wx_config_minor_version -eq 2; then
                 if test $wx_config_micro_version -ge 6; then
                    wx_has_cppflags=yes
                 fi
              fi
           fi
        fi
      fi

      dnl starting with version 2.7.0 wx-config has --rescomp option
      wx_has_rescomp=""
      if test $wx_config_major_version -gt 2; then
        wx_has_rescomp=yes
      else
        if test $wx_config_major_version -eq 2; then
           if test $wx_config_minor_version -ge 7; then
              wx_has_rescomp=yes
           fi
        fi
      fi
      if test "x$wx_has_rescomp" = x ; then
         dnl cannot give any useful info for resource compiler
         WX_RESCOMP=
      else
         WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp`
      fi

      if test "x$wx_has_cppflags" = x ; then
         dnl no choice but to define all flags like CFLAGS
         WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4`
         WX_CPPFLAGS=$WX_CFLAGS
         WX_CXXFLAGS=$WX_CFLAGS

         WX_CFLAGS_ONLY=$WX_CFLAGS
         WX_CXXFLAGS_ONLY=$WX_CFLAGS
      else
         dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS
         WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags $4`
         WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags $4`
         WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4`

         WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"`
         WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"`
      fi

      ifelse([$2], , :, [$2])

    else

       if test "x$WX_VERSION" = x; then
          dnl no wx-config at all
          AC_MSG_RESULT(no)
       else
          AC_MSG_RESULT(no (version $WX_VERSION is not new enough))
       fi

       WX_CFLAGS=""
       WX_CPPFLAGS=""
       WX_CXXFLAGS=""
       WX_LIBS=""
       WX_LIBS_STATIC=""
       WX_RESCOMP=""

       if test ! -z "$5"; then

          wx_error_message="
    The configuration you asked for $PACKAGE_NAME requires a wxWidgets
    build with the following settings:
        $5
    but such build is not available.

    To see the wxWidgets builds available on this system, please use
    'wx-config --list' command. To use the default build, returned by
    'wx-config --selected-config', use the options with their 'auto'
    default values."

       fi

       wx_error_message="
    The requested wxWidgets build couldn't be found.
    $wx_error_message

    If you still get this error, then check that 'wx-config' is
    in path, the directory where wxWidgets libraries are installed
    (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH
    or equivalent variable and wxWidgets version is $1 or above."

       ifelse([$3], , AC_MSG_ERROR([$wx_error_message]), [$3])

    fi
  else

    WX_CFLAGS=""
    WX_CPPFLAGS=""
    WX_CXXFLAGS=""
    WX_LIBS=""
    WX_LIBS_STATIC=""
    WX_RESCOMP=""

    ifelse([$3], , :, [$3])

  fi

  AC_SUBST(WX_CPPFLAGS)
  AC_SUBST(WX_CFLAGS)
  AC_SUBST(WX_CXXFLAGS)
  AC_SUBST(WX_CFLAGS_ONLY)
  AC_SUBST(WX_CXXFLAGS_ONLY)
  AC_SUBST(WX_LIBS)
  AC_SUBST(WX_LIBS_STATIC)
  AC_SUBST(WX_VERSION)
  AC_SUBST(WX_RESCOMP)

  dnl need to export also WX_VERSION_MINOR and WX_VERSION_MAJOR symbols
  dnl to support wxpresets bakefiles (we export also WX_VERSION_MICRO for completeness):
  WX_VERSION_MAJOR="$wx_config_major_version"
  WX_VERSION_MINOR="$wx_config_minor_version"
  WX_VERSION_MICRO="$wx_config_micro_version"
  AC_SUBST(WX_VERSION_MAJOR)
  AC_SUBST(WX_VERSION_MINOR)
  AC_SUBST(WX_VERSION_MICRO)
])

dnl ---------------------------------------------------------------------------
dnl Get information on the wxrc program for making C++, Python and xrs
dnl resource files.
dnl
dnl     AC_ARG_ENABLE(...)
dnl     AC_ARG_WITH(...)
dnl        ...
dnl     WX_CONFIG_OPTIONS
dnl        ...
dnl     WX_CONFIG_CHECK(2.6.0, wxWin=1)
dnl     if test "$wxWin" != 1; then
dnl        AC_MSG_ERROR([
dnl                wxWidgets must be installed on your system
dnl                but wx-config script couldn't be found.
dnl
dnl                Please check that wx-config is in path, the directory
dnl                where wxWidgets libraries are installed (returned by
dnl                'wx-config --libs' command) is in LD_LIBRARY_PATH or
dnl                equivalent variable and wxWidgets version is 2.6.0 or above.
dnl        ])
dnl     fi
dnl
dnl     WXRC_CHECK([HAVE_WXRC=1], [HAVE_WXRC=0])
dnl     if test "x$HAVE_WXRC" != x1; then
dnl         AC_MSG_ERROR([
dnl                The wxrc program was not installed or not found.
dnl
dnl                Please check the wxWidgets installation.
dnl         ])
dnl     fi
dnl
dnl     CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS"
dnl     CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY"
dnl     CFLAGS="$CFLAGS $WX_CFLAGS_ONLY"
dnl
dnl     LDFLAGS="$LDFLAGS $WX_LIBS"
dnl ---------------------------------------------------------------------------

dnl ---------------------------------------------------------------------------
dnl WXRC_CHECK([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl
dnl Test for wxWidgets' wxrc program for creating either C++, Python or XRS
dnl resources.  The variable WXRC will be set and substituted in the configure
dnl script and Makefiles.
dnl
dnl Example use:
dnl   WXRC_CHECK([wxrc=1], [wxrc=0])
dnl ---------------------------------------------------------------------------

dnl
dnl wxrc program from the wx-config script
dnl
AC_DEFUN([WXRC_CHECK],
[
  AC_ARG_VAR([WXRC], [Path to wxWidget's wxrc resource compiler])

  if test "x$WX_CONFIG_NAME" = x; then
    AC_MSG_ERROR([The wxrc tests must run after wxWidgets test.])
  else

    AC_MSG_CHECKING([for wxrc])

    if test "x$WXRC" = x ; then
      dnl wx-config --utility is a new addition to wxWidgets:
      _WX_PRIVATE_CHECK_VERSION(2,5,3)
      if test -n "$wx_ver_ok"; then
        WXRC=`$WX_CONFIG_WITH_ARGS --utility=wxrc`
      fi
    fi

    if test "x$WXRC" = x ; then
      AC_MSG_RESULT([not found])
      ifelse([$2], , :, [$2])
    else
      AC_MSG_RESULT([$WXRC])
      ifelse([$1], , :, [$1])
    fi

    AC_SUBST(WXRC)
  fi
])

dnl ---------------------------------------------------------------------------
dnl WX_LIKE_LIBNAME([output-var] [prefix], [name])
dnl
dnl Sets the "output-var" variable to the name of a library named with same
dnl wxWidgets rule.
dnl E.g. for output-var=='lib', name=='test', prefix='mine', sets
dnl      the $lib variable to:
dnl          'mine_gtk2ud_test-2.8'
dnl      if WX_PORT=gtk2, WX_UNICODE=1, WX_DEBUG=1 and WX_RELEASE=28
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_LIKE_LIBNAME],
    [
        wx_temp="$2""_""$WX_PORT"

        dnl add the [u][d] string
        if test "$WX_UNICODE" = "1"; then
            wx_temp="$wx_temp""u"
        fi
        if test "$WX_DEBUG" = "1"; then
            wx_temp="$wx_temp""d"
        fi

        dnl complete the name of the lib
        wx_temp="$wx_temp""_""$3""-$WX_VERSION_MAJOR.$WX_VERSION_MINOR"

        dnl save it in the user's variable
        $1=$wx_temp
    ])

dnl ---------------------------------------------------------------------------
dnl WX_ARG_ENABLE_YESNOAUTO/WX_ARG_WITH_YESNOAUTO
dnl
dnl Two little custom macros which define the ENABLE/WITH configure arguments.
dnl Macro arguments:
dnl $1 = the name of the --enable / --with  feature
dnl $2 = the name of the variable associated
dnl $3 = the description of that feature
dnl $4 = the default value for that feature
dnl $5 = additional action to do in case option is given with "yes" value
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO],
         [AC_ARG_ENABLE($1,
            AC_HELP_STRING([--enable-$1], [$3 (default is $4)]),
            [], [enableval="$4"])

            dnl Show a message to the user about this option
            AC_MSG_CHECKING([for the --enable-$1 option])
            if test "$enableval" = "yes" ; then
                AC_MSG_RESULT([yes])
                $2=1
                $5
            elif test "$enableval" = "no" ; then
                AC_MSG_RESULT([no])
                $2=0
            elif test "$enableval" = "auto" ; then
                AC_MSG_RESULT([will be automatically detected])
                $2="auto"
            else
                AC_MSG_ERROR([
    Unrecognized option value (allowed values: yes, no, auto)
                ])
            fi
         ])

AC_DEFUN([WX_ARG_WITH_YESNOAUTO],
         [AC_ARG_WITH($1,
            AC_HELP_STRING([--with-$1], [$3 (default is $4)]),
            [], [withval="$4"])

            dnl Show a message to the user about this option
            AC_MSG_CHECKING([for the --with-$1 option])
            if test "$withval" = "yes" ; then
                AC_MSG_RESULT([yes])
                $2=1
                $5
            dnl NB: by default we don't allow --with-$1=no option
            dnl     since it does not make much sense !
            elif test "$6" = "1" -a "$withval" = "no" ; then
                AC_MSG_RESULT([no])
                $2=0
            elif test "$withval" = "auto" ; then
                AC_MSG_RESULT([will be automatically detected])
                $2="auto"
            else
                AC_MSG_ERROR([
    Unrecognized option value (allowed values: yes, auto)
                ])
            fi
         ])


dnl ---------------------------------------------------------------------------
dnl WX_STANDARD_OPTIONS([options-to-add])
dnl
dnl Adds to the configure script one or more of the following options:
dnl   --enable-[debug|unicode|shared|wxshared|wxdebug]
dnl   --with-[gtk|msw|motif|x11|mac|dfb]
dnl   --with-wxversion
dnl Then checks for their presence and eventually set the DEBUG, UNICODE, SHARED,
dnl PORT, WX_SHARED, WX_DEBUG, variables to one of the "yes", "no", "auto" values.
dnl
dnl Note that e.g. UNICODE != WX_UNICODE; the first is the value of the
dnl --enable-unicode option (in boolean format) while the second indicates
dnl if wxWidgets was built in Unicode mode (and still is in boolean format).
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_STANDARD_OPTIONS],
        [

        dnl the following lines will expand to WX_ARG_ENABLE_YESNOAUTO calls if and only if
        dnl the $1 argument contains respectively the debug,unicode or shared options.

        dnl be careful here not to set debug flag if only "wxdebug" was specified
        ifelse(regexp([$1], [\bdebug]), [-1],,
               [WX_ARG_ENABLE_YESNOAUTO([debug], [DEBUG], [Build in debug mode], [auto])])

        ifelse(index([$1], [unicode]), [-1],,
               [WX_ARG_ENABLE_YESNOAUTO([unicode], [UNICODE], [Build in Unicode mode], [auto])])

        ifelse(regexp([$1], [\bshared]), [-1],,
               [WX_ARG_ENABLE_YESNOAUTO([shared], [SHARED], [Build as shared library], [auto])])

        dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-toolkit since it's an option
        dnl which must be able to accept the auto|gtk1|gtk2|msw|... values
        ifelse(index([$1], [toolkit]), [-1],,
               [
                AC_ARG_WITH([toolkit],
                            AC_HELP_STRING([--with-toolkit],
                                           [Build against a specific wxWidgets toolkit (default is auto)]),
                            [], [withval="auto"])

                dnl Show a message to the user about this option
                AC_MSG_CHECKING([for the --with-toolkit option])
                if test "$withval" = "auto" ; then
                    AC_MSG_RESULT([will be automatically detected])
                    TOOLKIT="auto"
                else
                    TOOLKIT="$withval"

                    dnl PORT must be one of the allowed values
                    if test "$TOOLKIT" != "gtk1" -a "$TOOLKIT" != "gtk2" -a \
                            "$TOOLKIT" != "msw" -a "$TOOLKIT" != "motif" -a \
                            "$TOOLKIT" != "osx_carbon" -a "$TOOLKIT" != "osx_cocoa" -a \
                            "$TOOLKIT" != "dfb" -a "$TOOLKIT" != "x11"; then
                        AC_MSG_ERROR([
    Unrecognized option value (allowed values: auto, gtk1, gtk2, msw, motif, osx_carbon, osx_cocoa, dfb, x11)
                        ])
                    fi

                    AC_MSG_RESULT([$TOOLKIT])
                fi
               ])

        dnl ****** IMPORTANT *******
        dnl   Unlike for the UNICODE setting, you can build your program in
        dnl   shared mode against a static build of wxWidgets. Thus we have the
        dnl   following option which allows these mixtures. E.g.
        dnl
        dnl      ./configure --disable-shared --with-wxshared
        dnl
        dnl   will build your library in static mode against the first available
        dnl   shared build of wxWidgets.
        dnl
        dnl   Note that's not possible to do the viceversa:
        dnl
        dnl      ./configure --enable-shared --without-wxshared
        dnl
        dnl   Doing so you would try to build your library in shared mode against a static
        dnl   build of wxWidgets. This is not possible (you would mix PIC and non PIC code) !
        dnl   A check for this combination of options is in WX_DETECT_STANDARD_OPTION_VALUES
        dnl   (where we know what 'auto' should be expanded to).
        dnl
        dnl   If you try to build something in ANSI mode against a UNICODE build
        dnl   of wxWidgets or in RELEASE mode against a DEBUG build of wxWidgets,
        dnl   then at best you'll get ton of linking errors !
        dnl ************************

        ifelse(index([$1], [wxshared]), [-1],,
               [
                WX_ARG_WITH_YESNOAUTO(
                    [wxshared], [WX_SHARED],
                    [Force building against a shared build of wxWidgets, even if --disable-shared is given],
                    [auto], [], [1])
               ])

        dnl Just like for SHARED and WX_SHARED it may happen that some adventurous
        dnl peoples will want to mix a wxWidgets release build with a debug build of
        dnl his app/lib. So, we have both DEBUG and WX_DEBUG variables.
        ifelse(index([$1], [wxdebug]), [-1],,
               [
                WX_ARG_WITH_YESNOAUTO(
                    [wxdebug], [WX_DEBUG],
                    [Force building against a debug build of wxWidgets, even if --disable-debug is given],
                    [auto], [], [1])
               ])

        dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-wxversion since it's an option
        dnl which accepts the "auto|2.6|2.7|2.8|2.9|3.0" etc etc values
        ifelse(index([$1], [wxversion]), [-1],,
               [
                AC_ARG_WITH([wxversion],
                            AC_HELP_STRING([--with-wxversion],
                                           [Build against a specific version of wxWidgets (default is auto)]),
                            [], [withval="auto"])

                dnl Show a message to the user about this option
                AC_MSG_CHECKING([for the --with-wxversion option])
                if test "$withval" = "auto" ; then
                    AC_MSG_RESULT([will be automatically detected])
                    WX_RELEASE="auto"
                else

                    wx_requested_major_version=`echo $withval | \
                        sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\1/'`
                    wx_requested_minor_version=`echo $withval | \
                        sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\2/'`

                    dnl both vars above must be exactly 1 digit
                    if test "${#wx_requested_major_version}" != "1" -o \
                            "${#wx_requested_minor_version}" != "1" ; then
                        AC_MSG_ERROR([
    Unrecognized option value (allowed values: auto, 2.6, 2.7, 2.8, 2.9, 3.0)
                        ])
                    fi

                    WX_RELEASE="$wx_requested_major_version"".""$wx_requested_minor_version"
                    AC_MSG_RESULT([$WX_RELEASE])
                fi
               ])

        if test "$WX_DEBUG_CONFIGURE" = "1"; then
            echo "[[dbg]] DEBUG: $DEBUG, WX_DEBUG: $WX_DEBUG"
            echo "[[dbg]] UNICODE: $UNICODE, WX_UNICODE: $WX_UNICODE"
            echo "[[dbg]] SHARED: $SHARED, WX_SHARED: $WX_SHARED"
            echo "[[dbg]] TOOLKIT: $TOOLKIT, WX_TOOLKIT: $WX_TOOLKIT"
            echo "[[dbg]] VERSION: $VERSION, WX_RELEASE: $WX_RELEASE"
        fi
    ])


dnl ---------------------------------------------------------------------------
dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS
dnl
dnl Sets the WXCONFIG_FLAGS string using the SHARED,DEBUG,UNICODE variable values
dnl which are different from "auto".
dnl Thus this macro needs to be called only once all options have been set.
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS],
        [
        if test "$WX_SHARED" = "1" ; then
            WXCONFIG_FLAGS="--static=no "
        elif test "$WX_SHARED" = "0" ; then
            WXCONFIG_FLAGS="--static=yes "
        fi

        if test "$WX_DEBUG" = "1" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=yes "
        elif test "$WX_DEBUG" = "0" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=no "
        fi

        dnl The user should have set WX_UNICODE=UNICODE
        if test "$WX_UNICODE" = "1" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=yes "
        elif test "$WX_UNICODE" = "0" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=no "
        fi

        if test "$TOOLKIT" != "auto" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--toolkit=$TOOLKIT "
        fi

        if test "$WX_RELEASE" != "auto" ; then
            WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--version=$WX_RELEASE "
        fi

        dnl strip out the last space of the string
        WXCONFIG_FLAGS=${WXCONFIG_FLAGS% }

        if test "$WX_DEBUG_CONFIGURE" = "1"; then
            echo "[[dbg]] WXCONFIG_FLAGS: $WXCONFIG_FLAGS"
        fi
    ])


dnl ---------------------------------------------------------------------------
dnl _WX_SELECTEDCONFIG_CHECKFOR([RESULTVAR], [STRING], [MSG]
dnl                             [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl
dnl Outputs the given MSG. Then searches the given STRING in the wxWidgets
dnl additional CPP flags and put the result of the search in WX_$RESULTVAR
dnl also adding the "yes" or "no" message result to MSG.
dnl ---------------------------------------------------------------------------
AC_DEFUN([_WX_SELECTEDCONFIG_CHECKFOR],
        [
        if test "$$1" = "auto" ; then

            dnl The user does not have particular preferences for this option;
            dnl so we will detect the wxWidgets relative build setting and use it
            AC_MSG_CHECKING([$3])

            dnl set WX_$1 variable to 1 if the $WX_SELECTEDCONFIG contains the $2
            dnl string or to 0 otherwise.
            dnl NOTE: 'expr match STRING REGEXP' cannot be used since on Mac it
            dnl       doesn't work; we use 'expr STRING : REGEXP' instead
            WX_$1=$(expr "$WX_SELECTEDCONFIG" : ".*$2.*")

            if test "$WX_$1" != "0"; then
                WX_$1=1
                AC_MSG_RESULT([yes])
                ifelse([$4], , :, [$4])
            else
                WX_$1=0
                AC_MSG_RESULT([no])
                ifelse([$5], , :, [$5])
            fi
        else

            dnl Use the setting given by the user
            WX_$1=$$1
        fi
    ])

dnl ---------------------------------------------------------------------------
dnl WX_DETECT_STANDARD_OPTION_VALUES
dnl
dnl Detects the values of the following variables:
dnl 1) WX_RELEASE
dnl 2) WX_UNICODE
dnl 3) WX_DEBUG
dnl 4) WX_SHARED    (and also WX_STATIC)
dnl 5) WX_PORT
dnl from the previously selected wxWidgets build; this macro in fact must be
dnl called *after* calling the WX_CONFIG_CHECK macro.
dnl
dnl Note that the WX_VERSION_MAJOR, WX_VERSION_MINOR symbols are already set
dnl by WX_CONFIG_CHECK macro
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
        [
        dnl IMPORTANT: WX_VERSION contains all three major.minor.micro digits,
        dnl            while WX_RELEASE only the major.minor ones.
        WX_RELEASE="$WX_VERSION_MAJOR""$WX_VERSION_MINOR"
        if test $WX_RELEASE -lt 26 ; then

            AC_MSG_ERROR([
    Cannot detect the wxWidgets configuration for the selected wxWidgets build
    since its version is $WX_VERSION < 2.6.0; please install a newer
    version of wxWidgets.
                         ])
        fi

        dnl The wx-config we are using understands the "--selected_config"
        dnl option which returns an easy-parseable string !
        WX_SELECTEDCONFIG=$($WX_CONFIG_WITH_ARGS --selected_config)

        if test "$WX_DEBUG_CONFIGURE" = "1"; then
            echo "[[dbg]] Using wx-config --selected-config"
            echo "[[dbg]] WX_SELECTEDCONFIG: $WX_SELECTEDCONFIG"
        fi


        dnl we could test directly for WX_SHARED with a line like:
        dnl    _WX_SELECTEDCONFIG_CHECKFOR([SHARED], [shared],
        dnl                                [if wxWidgets was built in SHARED mode])
        dnl but wx-config --selected-config DOES NOT outputs the 'shared'
        dnl word when wx was built in shared mode; it rather outputs the
        dnl 'static' word when built in static mode.
        if test $WX_SHARED = "1"; then
            STATIC=0
        elif test $WX_SHARED = "0"; then
            STATIC=1
        elif test $WX_SHARED = "auto"; then
            STATIC="auto"
        fi

        dnl Now set the WX_UNICODE, WX_DEBUG, WX_STATIC variables
        _WX_SELECTEDCONFIG_CHECKFOR([UNICODE], [unicode],
                                    [if wxWidgets was built with UNICODE enabled])
        _WX_SELECTEDCONFIG_CHECKFOR([DEBUG], [debug],
                                    [if wxWidgets was built in DEBUG mode])
        _WX_SELECTEDCONFIG_CHECKFOR([STATIC], [static],
                                    [if wxWidgets was built in STATIC mode])

        dnl init WX_SHARED from WX_STATIC
        if test "$WX_STATIC" != "0"; then
            WX_SHARED=0
        else
            WX_SHARED=1
        fi

        AC_SUBST(WX_UNICODE)
        AC_SUBST(WX_DEBUG)
        AC_SUBST(WX_SHARED)

        dnl detect the WX_PORT to use
        if test "$TOOLKIT" = "auto" ; then

            dnl The user does not have particular preferences for this option;
            dnl so we will detect the wxWidgets relative build setting and use it
            AC_MSG_CHECKING([which wxWidgets toolkit was selected])

            WX_GTKPORT1=$(expr "$WX_SELECTEDCONFIG" : ".*gtk1.*")
            WX_GTKPORT2=$(expr "$WX_SELECTEDCONFIG" : ".*gtk2.*")
            WX_MSWPORT=$(expr "$WX_SELECTEDCONFIG" : ".*msw.*")
            WX_MOTIFPORT=$(expr "$WX_SELECTEDCONFIG" : ".*motif.*")
            WX_OSXCOCOAPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_cocoa.*")
            WX_OSXCARBONPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_carbon.*")
            WX_X11PORT=$(expr "$WX_SELECTEDCONFIG" : ".*x11.*")
            WX_DFBPORT=$(expr "$WX_SELECTEDCONFIG" : ".*dfb.*")

            WX_PORT="unknown"
            if test "$WX_GTKPORT1" != "0"; then WX_PORT="gtk1"; fi
            if test "$WX_GTKPORT2" != "0"; then WX_PORT="gtk2"; fi
            if test "$WX_MSWPORT" != "0"; then WX_PORT="msw"; fi
            if test "$WX_MOTIFPORT" != "0"; then WX_PORT="motif"; fi
            if test "$WX_OSXCOCOAPORT" != "0"; then WX_PORT="osx_cocoa"; fi
            if test "$WX_OSXCARBONPORT" != "0"; then WX_PORT="osx_carbon"; fi
            if test "$WX_X11PORT" != "0"; then WX_PORT="x11"; fi
            if test "$WX_DFBPORT" != "0"; then WX_PORT="dfb"; fi

            dnl NOTE: backward-compatible check for wx2.8; in wx2.9 the mac
            dnl       ports are called 'osx_cocoa' and 'osx_carbon' (see above)
            WX_MACPORT=$(expr "$WX_SELECTEDCONFIG" : ".*mac.*")
            if test "$WX_MACPORT" != "0"; then WX_PORT="mac"; fi

            dnl check at least one of the WX_*PORT has been set !

            if test "$WX_PORT" = "unknown" ; then
                AC_MSG_ERROR([
        Cannot detect the currently installed wxWidgets port !
        Please check your 'wx-config --cxxflags'...
                            ])
            fi

            AC_MSG_RESULT([$WX_PORT])
        else

            dnl Use the setting given by the user
            if test -z "$TOOLKIT" ; then
                WX_PORT=$TOOLKIT
            else
                dnl try with PORT
                WX_PORT=$PORT
            fi
        fi

        AC_SUBST(WX_PORT)

        if test "$WX_DEBUG_CONFIGURE" = "1"; then
            echo "[[dbg]] Values of all WX_* options after final detection:"
            echo "[[dbg]] WX_DEBUG: $WX_DEBUG"
            echo "[[dbg]] WX_UNICODE: $WX_UNICODE"
            echo "[[dbg]] WX_SHARED: $WX_SHARED"
            echo "[[dbg]] WX_RELEASE: $WX_RELEASE"
            echo "[[dbg]] WX_PORT: $WX_PORT"
        fi

        dnl Avoid problem described in the WX_STANDARD_OPTIONS which happens when
        dnl the user gives the options:
        dnl      ./configure --enable-shared --without-wxshared
        dnl or just do
        dnl      ./configure --enable-shared
        dnl but there is only a static build of wxWidgets available.
        if test "$WX_SHARED" = "0" -a "$SHARED" = "1"; then
            AC_MSG_ERROR([
    Cannot build shared library against a static build of wxWidgets !
    This error happens because the wxWidgets build which was selected
    has been detected as static while you asked to build $PACKAGE_NAME
    as shared library and this is not possible.
    Use the '--disable-shared' option to build $PACKAGE_NAME
    as static library or '--with-wxshared' to use wxWidgets as shared library.
                         ])
        fi

        dnl now we can finally update the DEBUG,UNICODE,SHARED options
        dnl to their final values if they were set to 'auto'
        if test "$DEBUG" = "auto"; then
            DEBUG=$WX_DEBUG
        fi
        if test "$UNICODE" = "auto"; then
            UNICODE=$WX_UNICODE
        fi
        if test "$SHARED" = "auto"; then
            SHARED=$WX_SHARED
        fi
        if test "$TOOLKIT" = "auto"; then
            TOOLKIT=$WX_PORT
        fi

        dnl in case the user needs a BUILD=debug/release var...
        if test "$DEBUG" = "1"; then
            BUILD="debug"
        elif test "$DEBUG" = "0" -o "$DEBUG" = ""; then
            BUILD="release"
        fi

        dnl respect the DEBUG variable adding the optimize/debug flags
        dnl NOTE: the CXXFLAGS are merged together with the CPPFLAGS so we
        dnl       don't need to set them, too
        if test "$DEBUG" = "1"; then
            CXXFLAGS="$CXXFLAGS -g -O0"
            CFLAGS="$CFLAGS -g -O0"
        else
            CXXFLAGS="$CXXFLAGS -O2"
            CFLAGS="$CFLAGS -O2"
        fi
    ])

dnl ---------------------------------------------------------------------------
dnl WX_BOOLOPT_SUMMARY([name of the boolean variable to show summary for],
dnl                   [what to print when var is 1],
dnl                   [what to print when var is 0])
dnl
dnl Prints $2 when variable $1 == 1 and prints $3 when variable $1 == 0.
dnl This macro mainly exists just to make configure.ac scripts more readable.
dnl
dnl NOTE: you need to use the [" my message"] syntax for 2nd and 3rd arguments
dnl       if you want that m4 avoid to throw away the spaces prefixed to the
dnl       argument value.
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_BOOLOPT_SUMMARY],
        [
        if test "x$$1" = "x1" ; then
            echo $2
        elif test "x$$1" = "x0" ; then
            echo $3
        else
            echo "$1 is $$1"
        fi
    ])

dnl ---------------------------------------------------------------------------
dnl WX_STANDARD_OPTIONS_SUMMARY_MSG
dnl
dnl Shows a summary message to the user about the WX_* variable contents.
dnl This macro is used typically at the end of the configure script.
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG],
        [
        echo
        echo "  The wxWidgets build which will be used by $PACKAGE_NAME $PACKAGE_VERSION"
        echo "  has the following settings:"
        WX_BOOLOPT_SUMMARY([WX_DEBUG],   ["  - DEBUG build"],  ["  - RELEASE build"])
        WX_BOOLOPT_SUMMARY([WX_UNICODE], ["  - UNICODE mode"], ["  - ANSI mode"])
        WX_BOOLOPT_SUMMARY([WX_SHARED],  ["  - SHARED mode"],  ["  - STATIC mode"])
        echo "  - VERSION: $WX_VERSION"
        echo "  - PORT: $WX_PORT"
    ])


dnl ---------------------------------------------------------------------------
dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN, WX_STANDARD_OPTIONS_SUMMARY_MSG_END
dnl
dnl Like WX_STANDARD_OPTIONS_SUMMARY_MSG macro but these two macros also gives info
dnl about the configuration of the package which used the wxpresets.
dnl
dnl Typical usage:
dnl    WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN
dnl    echo "   - Package setting 1: $SETTING1"
dnl    echo "   - Package setting 2: $SETTING1"
dnl    ...
dnl    WX_STANDARD_OPTIONS_SUMMARY_MSG_END
dnl
dnl ---------------------------------------------------------------------------
AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN],
        [
        echo
        echo " ----------------------------------------------------------------"
        echo "  Configuration for $PACKAGE_NAME $PACKAGE_VERSION successfully completed."
        echo "  Summary of main configuration settings for $PACKAGE_NAME:"
        WX_BOOLOPT_SUMMARY([DEBUG], ["  - DEBUG build"], ["  - RELEASE build"])
        WX_BOOLOPT_SUMMARY([UNICODE], ["  - UNICODE mode"], ["  - ANSI mode"])
        WX_BOOLOPT_SUMMARY([SHARED], ["  - SHARED mode"], ["  - STATIC mode"])
    ])

AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_END],
        [
        WX_STANDARD_OPTIONS_SUMMARY_MSG
        echo
        echo "  Now, just run make."
        echo " ----------------------------------------------------------------"
        echo
    ])


dnl ---------------------------------------------------------------------------
dnl Deprecated macro wrappers
dnl ---------------------------------------------------------------------------

AC_DEFUN([AM_OPTIONS_WXCONFIG], [WX_CONFIG_OPTIONS])
AC_DEFUN([AM_PATH_WXCONFIG], [
    WX_CONFIG_CHECK([$1],[$2],[$3],[$4],[$5])
])
AC_DEFUN([AM_PATH_WXRC], [WXRC_CHECK([$1],[$2])])
07070100000008000081A4000003E800000064000000016039353E0000156F000000000000000000000000000000000000001B00000000diff-pdf-0.5/bmpviewer.cpp/*
 * This file is part of diff-pdf.
 *
 * Copyright (C) 2009 TT-Solutions.
 *
 * 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 2 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 <http://www.gnu.org/licenses/>.
 */

#include "bmpviewer.h"
#include "gutter.h"

#include <wx/sizer.h>

BEGIN_EVENT_TABLE(BitmapViewer, wxScrolledWindow)
    EVT_LEFT_DOWN(BitmapViewer::OnMouseDown)
    EVT_LEFT_UP(BitmapViewer::OnMouseUp)
    EVT_MOTION(BitmapViewer::OnMouseMove)
    EVT_MOUSE_CAPTURE_LOST(BitmapViewer::OnMouseCaptureLost)
    EVT_SCROLLWIN(BitmapViewer::OnScrolling)
    EVT_SIZE(BitmapViewer::OnSizeChanged)
END_EVENT_TABLE()

BitmapViewer::BitmapViewer(wxWindow *parent)
    : wxScrolledWindow(parent,
                       wxID_ANY,
                       wxDefaultPosition, wxDefaultSize,
                       wxFULL_REPAINT_ON_RESIZE)
{
    m_gutter = NULL;
    m_zoom_factor = 1.0;

    SetScrollRate(1, 1);

    wxBitmap dummyBitmap(16, 16);
    m_content = new wxStaticBitmap(this, wxID_ANY, dummyBitmap);

    wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
    sizer->Add(m_content, wxSizerFlags(1).Expand());
    SetSizer(sizer);

    // we need to bind mouse-down event to m_content, as this scrolled window
    // will never see mouse events otherwise
    m_content->Connect
               (
                   wxEVT_LEFT_DOWN,
                   wxMouseEventHandler(BitmapViewer::OnMouseDown),
                   NULL,
                   this
               );
}


void BitmapViewer::SetBestFitZoom()
{
    // compute highest scale factor that still doesn't need scrollbars:

    float scale_x = float(GetSize().x) / float(m_orig_image.GetWidth());
    float scale_y = float(GetSize().y) / float(m_orig_image.GetHeight());

    SetZoom(std::min(scale_x, scale_y));
}


void BitmapViewer::UpdateBitmap()
{
    int new_w = int(m_orig_image.GetWidth() * m_zoom_factor);
    int new_h = int(m_orig_image.GetHeight() * m_zoom_factor);

    if ( new_w != m_orig_image.GetWidth() ||
         new_h != m_orig_image.GetHeight() )
    {
        wxImage scaled =
            m_orig_image.Scale
                         (
                             new_w,
                             new_h,
                             // we don't need HQ filtering when upscaling
                             m_zoom_factor < 1.0
                                ? wxIMAGE_QUALITY_HIGH
                                : wxIMAGE_QUALITY_NORMAL
                         );
        m_content->SetBitmap(wxBitmap(scaled));
    }
    else
    {
        m_content->SetBitmap(wxBitmap(m_orig_image));
    }

    GetSizer()->FitInside(this);

    if ( m_gutter )
        m_gutter->UpdateViewPos(this);
}


void BitmapViewer::Set(const wxImage& image)
{
    m_orig_image = image;
    UpdateBitmap();
}


void BitmapViewer::Set(cairo_surface_t *surface)
{
    // Cairo's RGB24 surfaces use 32 bits per pixel, while wxImage uses
    // 24 bits per pixel, so we need to convert between the two representations
    // manually. Moreover, channels order is different too, RGB vs. BGR.

    const int w = cairo_image_surface_get_width(surface);
    const int h = cairo_image_surface_get_height(surface);

    wxImage img(w, h, false);

    unsigned char *p_out = img.GetData();
    const unsigned char *p_in = cairo_image_surface_get_data(surface);
    const int stride = cairo_image_surface_get_stride(surface);

    for ( int y = 0; y < h; y++, p_in += stride )
    {
        for ( int x = 0; x < w; x++ )
        {
            *(p_out++) = *(p_in + 4 * x + 2);
            *(p_out++) = *(p_in + 4 * x + 1);
            *(p_out++) = *(p_in + 4 * x + 0);
        }
    }

    Set(img);
}


void BitmapViewer::AttachGutter(Gutter *g)
{
    m_gutter = g;
    if ( g )
        g->UpdateViewPos(this);
}


void BitmapViewer::OnMouseDown(wxMouseEvent& event)
{
    wxPoint view_origin;
    GetViewStart(&view_origin.x, &view_origin.y);

    const wxPoint pos = event.GetPosition();

    m_draggingPage = true;
    m_draggingLastMousePos = pos;
    CaptureMouse();
}


void BitmapViewer::OnMouseUp(wxMouseEvent&)
{
    m_draggingPage = false;
    ReleaseMouse();
}


void BitmapViewer::OnMouseMove(wxMouseEvent& event)
{
    event.Skip();

    if ( !m_draggingPage )
        return;

    wxPoint view_origin;
    GetViewStart(&view_origin.x, &view_origin.y);

    const wxPoint pos = event.GetPosition();
    wxPoint new_pos = view_origin + (m_draggingLastMousePos - pos);

    Scroll(new_pos.x, new_pos.y);
    if ( m_gutter )
        m_gutter->UpdateViewPos(this);

    m_draggingLastMousePos = pos;
}


void BitmapViewer::OnMouseCaptureLost(wxMouseCaptureLostEvent& event)
{
    m_draggingPage = false;
    event.Skip();
}


void BitmapViewer::OnScrolling(wxScrollWinEvent& event)
{
    if ( m_gutter )
        m_gutter->UpdateViewPos(this);

    event.Skip();
}

void BitmapViewer::OnSizeChanged(wxSizeEvent& event)
{
    if ( m_gutter )
        m_gutter->UpdateViewPos(this);

    event.Skip();
}
07070100000009000081A4000003E800000064000000016039353E000008DE000000000000000000000000000000000000001900000000diff-pdf-0.5/bmpviewer.h/*
 * This file is part of diff-pdf.
 *
 * Copyright (C) 2009 TT-Solutions.
 *
 * 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 2 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 <http://www.gnu.org/licenses/>.
 */

#ifndef _bmpviewer_h_
#define _bmpviewer_h_

#include <cairo/cairo.h>

#include <wx/image.h>
#include <wx/bitmap.h>
#include <wx/statbmp.h>
#include <wx/scrolwin.h>
#include <wx/event.h>

class Gutter;

// widget for comfortable viewing of a bitmap, with high-quality zooming
class BitmapViewer : public wxScrolledWindow
{
public:
    BitmapViewer(wxWindow *parent);

    // set the bitmap to be shown
    void Set(const wxImage& image);
    void Set(cairo_surface_t *surface);

    float GetZoom() const
    {
        return m_zoom_factor;
    }

    void SetZoom(float factor)
    {
        m_zoom_factor = factor;
        UpdateBitmap();
    }

    // sets the zoom value to "best fit" for current window size
    void SetBestFitZoom();

    // attaches a gutter that shows current scrolling position to the window
    void AttachGutter(Gutter *g);

private:
    // update the content after some change (bitmap, zoom factor, ...)
    void UpdateBitmap();

    void OnMouseDown(wxMouseEvent& event);
    void OnMouseUp(wxMouseEvent& event);
    void OnMouseMove(wxMouseEvent& event);
    void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
    void OnScrolling(wxScrollWinEvent& event);
    void OnSizeChanged(wxSizeEvent& event);

private:
    wxStaticBitmap *m_content;
    wxImage m_orig_image;
    float m_zoom_factor;

    // is the user currently dragging the page around with the mouse?
    bool m_draggingPage;
    wxPoint m_draggingLastMousePos;

    Gutter *m_gutter;

    DECLARE_EVENT_TABLE()
};

#endif // _bmpviewer_h_
0707010000000A000081ED000003E800000064000000016039353E00000A26000000000000000000000000000000000000001700000000diff-pdf-0.5/bootstrap#!/bin/sh

# Script to execute to initialize diff-pdf build system after checking out
# pristine sources from a version control system: this script creates all
# generated files which are needed for the build but not stored under version
# control.

# Copyright (C) 2005, 2006, 2007, 2008 Vadim Zeitlin
# All Rights Reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 3. Neither the name of the Author nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

# $Id$

if [ ! -f configure.ac -o ! -f Makefile.am ]; then
    echo "Please run this script from the diff-pdf source directory."
    exit 2
fi

# use --foreign with automake because we lack standard GNU NEWS and AUTHOR
# files, if they're added we can "upgrade" to (default) GNU strictness. Use
# --copy to allow simultaneous use on windows under mingw and cygwin platforms.
# Symlinking of files under mingw does not work out for cygwin and vice-versa.
echo "Setting up build system for diff-pdf:"
echo " - aclocal " && aclocal ${wx+-I} $wx -I admin && \
echo " - autoconf " && autoconf && \
echo " - automake " && automake --add-missing --copy --foreign && \
echo "Build setup successful, type \"./configure\" to configure diff-pdf now." && \
exit 0

echo "Automatic build files setup failed!"

exit 1
0707010000000B000081A4000003E800000064000000016039353E00000607000000000000000000000000000000000000001A00000000diff-pdf-0.5/configure.ac
dnl This file is part of diff-pdf.
dnl
dnl Copyright (C) 2009 TT-Solutions.
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.


AC_PREREQ(2.61)
AC_INIT(diff-pdf, 0.5, [vaclav@slavik.io])

AC_CONFIG_SRCDIR([diff-pdf.cpp])
AC_CONFIG_AUX_DIR([admin])

AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE

m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])

dnl remember, "build" is where we compile, "host" is where the resulting
dnl program runs (which may be different from "build" for cross-compilation)
AC_CANONICAL_HOST


dnl === Program checks ===

AC_PROG_CXX
AC_LANG(C++)

dnl === Library checks ===

PKG_CHECK_MODULES(POPPLER,
                  [glib-2.0 >= 2.36 poppler-glib >= 0.10 cairo-pdf])

AM_OPTIONS_WXCONFIG
AM_PATH_WXCONFIG([3.0.0], [wxfound=1], [wxfound=0], [core,base])
if test "$wxfound" != 1 ; then
    AC_MSG_ERROR([wxWidgets is required])
fi

dnl === Generate output files ===

AC_CONFIG_FILES([
    Makefile
])
AC_OUTPUT
0707010000000C000081A4000003E800000064000000016039353E00007A8A000000000000000000000000000000000000001A00000000diff-pdf-0.5/diff-pdf.cpp/*
 * This file is part of diff-pdf.
 *
 * Copyright (C) 2009 TT-Solutions.
 *
 * 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 2 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 <http://www.gnu.org/licenses/>.
 */

#include "bmpviewer.h"
#include "gutter.h"

#include <stdio.h>
#include <assert.h>

#include <vector>

#include <glib.h>
#include <poppler.h>
#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>

#include <wx/app.h>
#include <wx/evtloop.h>
#include <wx/cmdline.h>
#include <wx/filename.h>
#include <wx/log.h>
#include <wx/frame.h>
#include <wx/sizer.h>
#include <wx/toolbar.h>
#include <wx/artprov.h>
#include <wx/progdlg.h>
#include <wx/filesys.h>

// ------------------------------------------------------------------------
// PDF rendering functions
// ------------------------------------------------------------------------

bool g_verbose = false;
bool g_skip_identical = false;
bool g_mark_differences = false;
long g_channel_tolerance = 0;
bool g_grayscale = false;
// Resolution to use for rasterization, in DPI
#define DEFAULT_RESOLUTION 300
long g_resolution = DEFAULT_RESOLUTION;

inline unsigned char to_grayscale(unsigned char r, unsigned char g, unsigned char b)
{
    return (unsigned char)(0.2126 * r + 0.7152 * g + 0.0722 * b);
}

cairo_surface_t *render_page(PopplerPage *page)
{
    double w, h;
    poppler_page_get_size(page, &w, &h);

    const int w_px = int((int)g_resolution * w / 72.0);
    const int h_px = int((int)g_resolution * h / 72.0);

    cairo_surface_t *surface =
        cairo_image_surface_create(CAIRO_FORMAT_RGB24, w_px, h_px);

    cairo_t *cr = cairo_create(surface);

    // clear the surface to white background:
    cairo_save(cr);
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_rectangle(cr, 0, 0, w_px, h_px);
    cairo_fill(cr);
    cairo_restore(cr);

    // Scale so that PDF output covers the whole surface. Image surface is
    // created with transformation set up so that 1 coordinate unit is 1 pixel;
    // Poppler assumes 1 unit = 1 point.
    cairo_scale(cr, (int)g_resolution / 72.0, (int)g_resolution / 72.0);

    poppler_page_render(page, cr);

    cairo_show_page(cr);

    cairo_destroy(cr);

    return surface;
}


// Creates image of differences between s1 and s2. If the offset is specified,
// then s2 is displaced by it. If thumbnail and thumbnail_width are specified,
// then a thumbnail with highlighted differences is created too.
cairo_surface_t *diff_images(cairo_surface_t *s1, cairo_surface_t *s2,
                             int offset_x = 0, int offset_y = 0,
                             wxImage *thumbnail = NULL, int thumbnail_width = -1)
{
    assert( s1 || s2 );

    wxRect r1, r2;

    if ( s1 )
    {
        r1 = wxRect(0, 0,
                    cairo_image_surface_get_width(s1),
                    cairo_image_surface_get_height(s1));
    }
    if ( s2 )
    {
        r2 = wxRect(offset_x, offset_y,
                    cairo_image_surface_get_width(s2),
                    cairo_image_surface_get_height(s2));
    }

    // compute union rectangle starting at [0,0] position
    wxRect rdiff(r1);
    rdiff.Union(r2);
    r1.Offset(-rdiff.x, -rdiff.y);
    r2.Offset(-rdiff.x, -rdiff.y);
    rdiff.Offset(-rdiff.x, -rdiff.y);

    bool changes = false;

    cairo_surface_t *diff =
        cairo_image_surface_create(CAIRO_FORMAT_RGB24, rdiff.width, rdiff.height);

    float thumbnail_scale;
    int thumbnail_height;

    if ( thumbnail )
    {
        thumbnail_scale = float(thumbnail_width) / float(rdiff.width);
        thumbnail_height = int(rdiff.height * thumbnail_scale);
        thumbnail->Create(thumbnail_width, thumbnail_height);
        // initalize the thumbnail with a white rectangle:
        thumbnail->SetRGB(wxRect(), 255, 255, 255);
    }

    // clear the surface to white background if the merged images don't fully
    // overlap:
    if ( r1 != r2 )
    {
        changes = true;

        cairo_t *cr = cairo_create(diff);
        cairo_set_source_rgb(cr, 1, 1, 1);
        cairo_rectangle(cr, 0, 0, rdiff.width, rdiff.height);
        cairo_fill(cr);
        cairo_destroy(cr);
    }

    const int stride1 = s1 ? cairo_image_surface_get_stride(s1) : 0;
    const int stride2 = s2 ? cairo_image_surface_get_stride(s2) : 0;
    const int stridediff = cairo_image_surface_get_stride(diff);

    const unsigned char *data1 = s1 ? cairo_image_surface_get_data(s1) : NULL;
    const unsigned char *data2 = s2 ? cairo_image_surface_get_data(s2) : NULL;
    unsigned char *datadiff = cairo_image_surface_get_data(diff);

    // we visualize the differences by taking one channel from s1
    // and the other two channels from s2:

    // first, copy s1 over:
    if ( s1 )
    {
        unsigned char *out = datadiff + r1.y * stridediff + r1.x * 4;
        for ( int y = 0;
              y < r1.height;
              y++, data1 += stride1, out += stridediff )
        {
            memcpy(out, data1, r1.width * 4);
        }
    }

    // then, copy B channel from s2 over it; also compare the two versions
    // to see if there are any differences:
    if ( s2 )
    {
        unsigned char *out = datadiff + r2.y * stridediff + r2.x * 4;
        for ( int y = 0;
              y < r2.height;
              y++, data2 += stride2, out += stridediff )
        {
            bool linediff = false;

            for ( int x = 0; x < r2.width * 4; x += 4 )
            {
                unsigned char cr1 = *(out + x + 0);
                unsigned char cg1 = *(out + x + 1);
                unsigned char cb1 = *(out + x + 2);

                unsigned char cr2 = *(data2 + x + 0);
                unsigned char cg2 = *(data2 + x + 1);
                unsigned char cb2 = *(data2 + x + 2);

                if ( cr1 > (cr2+g_channel_tolerance) || cr1 < (cr2-g_channel_tolerance)
                  || cg1 > (cg2+g_channel_tolerance) || cg1 < (cg2-g_channel_tolerance)
                  || cb1 > (cb2+g_channel_tolerance) || cb1 < (cb2-g_channel_tolerance)
                   )
                {
                    changes = true;
                    linediff = true;

                    if ( thumbnail )
                    {
                        // calculate the coordinates in the thumbnail
                        int tx = int((r2.x + x/4.0) * thumbnail_scale);
                        int ty = int((r2.y + y) * thumbnail_scale);

                        // Limit the coordinates to the thumbnail size (may be
                        // off slightly due to rounding errors).
                        // See https://github.com/vslavik/diff-pdf/pull/58
                        tx = std::min(tx, thumbnail_width - 1);
                        ty = std::min(ty, thumbnail_height - 1);

                        // mark changes with red
                        thumbnail->SetRGB(tx, ty, 255, 0, 0);
                    }
                }

                if (g_grayscale)
                {
                    // convert both images to grayscale, use blue for s1, red for s2
                    unsigned char gray1 = to_grayscale(cr1, cg1, cb1);
                    unsigned char gray2 = to_grayscale(cr2, cg2, cb2);
                    *(out + x + 0) = gray2;
                    *(out + x + 1) = (gray1 + gray2) / 2;
                    *(out + x + 2) = gray1;
                }
                else
                {
                    // change the B channel to be from s2; RG will be s1
                    *(out + x + 2) = cb2;
                }
            }

            if (g_mark_differences && linediff)
            {
                for (int x = 0; x < (10 < r2.width ? 10 : r2.width) * 4; x+=4)
                {
                   *(out + x + 0) = 0;
                   *(out + x + 1) = 0;
                   *(out + x + 2) = 255;
                }
            }
        }
    }

    // add background image of the page to the thumbnails
    if ( thumbnail )
    {
        // copy the 'diff' surface into wxImage:
        wxImage bg(rdiff.width, rdiff.height);
        unsigned char *in = datadiff;
        unsigned char *out = bg.GetData();
        for ( int y = 0; y < rdiff.height; y++, in += stridediff )
        {
            for ( int x = 0; x < rdiff.width * 4; x += 4 )
            {
                // cairo_surface_t uses BGR order, wxImage has RGB
                *(out++) = *(in + x + 2);
                *(out++) = *(in + x + 1);
                *(out++) = *(in + x + 0);
            }
        }

        // scale it to thumbnail size:
        bg.Rescale(thumbnail_width, thumbnail_height, wxIMAGE_QUALITY_HIGH);

        // and merge with the diff markers in *thumbnail, making it much
        // lighter in the process:
        in = bg.GetData();
        out = thumbnail->GetData();
        for ( int i = thumbnail_width * thumbnail_height; i > 0; i-- )
        {
            if ( out[1] == 0 ) // G=0 ==> not white
            {
                // marked with red color, as place with differences -- don't
                // paint background image here, make the red as visible as
                // possible
                out += 3;
                in += 3;
            }
            else
            {
                // merge in lighter background image
                *(out++) = 128 + *(in++) / 2;
                *(out++) = 128 + *(in++) / 2;
                *(out++) = 128 + *(in++) / 2;
            }
        }

        // If there were no changes, indicate it by using green
        // (170,230,130) color for the thumbnail in gutter control:
        if ( !changes )
        {
            out = thumbnail->GetData();
            for ( int i = thumbnail_width * thumbnail_height;
                  i > 0;
                  i--, out += 3 )
            {
                out[0] = 170/2 + out[0] / 2;
                out[1] = 230/2 + out[1] / 2;
                out[2] = 130/2 + out[2] / 2;
            }
        }
    }

    if ( changes )
    {
        return diff;
    }
    else
    {
        cairo_surface_destroy(diff);
        return NULL;
    }
}


// Compares given two pages. If cr_out is not NULL, then the diff image (either
// differences or unmodified page, if there are no diffs) is drawn to it.
// If thumbnail and thumbnail_width are specified, then a thumbnail with
// highlighted differences is created too.
bool page_compare(cairo_t *cr_out,
                  PopplerPage *page1, PopplerPage *page2,
                  wxImage *thumbnail = NULL, int thumbnail_width = -1)
{
    cairo_surface_t *img1 = page1 ? render_page(page1) : NULL;
    cairo_surface_t *img2 = page2 ? render_page(page2) : NULL;

    cairo_surface_t *diff = diff_images(img1, img2, 0, 0,
                                        thumbnail, thumbnail_width);
    const bool has_diff = (diff != NULL);

    if ( cr_out )
    {
        if ( diff )
        {
            // render the difference as high-resolution bitmap

            cairo_save(cr_out);
            cairo_scale(cr_out, 72.0 / g_resolution, 72.0 / g_resolution);

            cairo_set_source_surface(cr_out, diff ? diff : img1, 0, 0);
            cairo_paint(cr_out);

            cairo_restore(cr_out);
        }
        else
        {
            // save space (as well as improve rendering quality) in diff pdf
            // by writing unchanged pages in their original form rather than
            // a rasterized one

            if (!g_skip_identical)
               poppler_page_render(page1, cr_out);
        }

        if (diff || !g_skip_identical)
            cairo_show_page(cr_out);
    }

    if ( diff )
        cairo_surface_destroy(diff);

    if ( img1 )
        cairo_surface_destroy(img1);
    if ( img2 )
        cairo_surface_destroy(img2);

    return !has_diff;
}


// Compares two documents, writing diff PDF into file named 'pdf_output' if
// not NULL. if 'differences' is not NULL, puts a map of which pages differ
// into it. If 'progress' is provided, it is updated to reflect comparison's
// progress. If 'gutter' is set, then all the pages are added to it, with
// their respective thumbnails (the gutter must be empty beforehand).
bool doc_compare(PopplerDocument *doc1, PopplerDocument *doc2,
                 const char *pdf_output,
                 std::vector<bool> *differences,
                 wxProgressDialog *progress = NULL,
                 Gutter *gutter = NULL)
{
    int pages_differ = 0;

    cairo_surface_t *surface_out = NULL;
    cairo_t *cr_out = NULL;

    if ( pdf_output )
    {
        double w, h;
        poppler_page_get_size(poppler_document_get_page(doc1, 0), &w, &h);
        surface_out = cairo_pdf_surface_create(pdf_output, w, h);
        cr_out = cairo_create(surface_out);
    }

    int pages1 = poppler_document_get_n_pages(doc1);
    int pages2 = poppler_document_get_n_pages(doc2);
    int pages_total = pages1 > pages2 ? pages1 : pages2;

    if ( pages1 != pages2 )
    {
        if ( g_verbose )
            printf("pages count differs: %d vs %d\n", pages1, pages2);
    }

    for ( int page = 0; page < pages_total; page++ )
    {
        if ( progress )
        {
            progress->Update
                      (
                          page,
                          wxString::Format
                          (
                              "Comparing page %d of %d...",
                              page+1,
                              pages_total
                          )
                       );
        }

        if ( pdf_output && page != 0 )
        {
            double w, h;
            poppler_page_get_size(poppler_document_get_page(doc1, page), &w, &h);
            cairo_pdf_surface_set_size(surface_out, w, h);
        }

        PopplerPage *page1 = page < pages1
                             ? poppler_document_get_page(doc1, page)
                             : NULL;
        PopplerPage *page2 = page < pages2
                             ? poppler_document_get_page(doc2, page)
                             : NULL;

        bool page_same;

        if ( gutter )
        {
            wxImage thumbnail;
            page_same = page_compare(cr_out, page1, page2,
                                     &thumbnail, Gutter::WIDTH);

            wxString label1("(null)");
            wxString label2("(null)");

            if ( page1 )
            {
                gchar *label;
                g_object_get(page1, "label", &label, NULL);
                label1 = wxString::FromUTF8(label);
                g_free(label);
            }
            if ( page2 )
            {
                gchar *label;
                g_object_get(page2, "label", &label, NULL);
                label2 = wxString::FromUTF8(label);
                g_free(label);
            }


            wxString label;
            if ( label1 == label2 )
                label = label1;
            else
                label = label1 + " / " + label2;

            gutter->AddPage(label, thumbnail);
        }
        else
        {
            page_same = page_compare(cr_out, page1, page2);
        }

        if ( differences )
            differences->push_back(!page_same);

        if ( !page_same )
        {
	    pages_differ ++;

            if ( g_verbose )
                printf("page %d differs\n", page);

            // If we don't need to output all different pages in any
            // form (including verbose report of differing pages!), then
            // we can stop comparing the PDFs as soon as we find the first
            // difference.
            if ( !g_verbose && !pdf_output && !differences && !gutter )
                break;
        }
    }

    if ( pdf_output )
    {
        cairo_destroy(cr_out);
        cairo_surface_destroy(surface_out);
    }

    if (g_verbose)
        printf("%d of %d pages differ.\n", pages_differ, pages_total);

    // are doc1 and doc1 the same?
    return (pages_differ == 0) && (pages1 == pages2);
}


// ------------------------------------------------------------------------
// wxWidgets GUI
// ------------------------------------------------------------------------

const int ID_PREV_PAGE = wxNewId();
const int ID_NEXT_PAGE = wxNewId();
const int ID_ZOOM_IN = wxNewId();
const int ID_ZOOM_OUT = wxNewId();
const int ID_OFFSET_LEFT = wxNewId();
const int ID_OFFSET_RIGHT = wxNewId();
const int ID_OFFSET_UP = wxNewId();
const int ID_OFFSET_DOWN = wxNewId();
const int ID_GUTTER = wxNewId();

#define BMP_ARTPROV(id) wxArtProvider::GetBitmap(id, wxART_TOOLBAR)

#define BMP_PREV_PAGE      BMP_ARTPROV(wxART_GO_BACK)
#define BMP_NEXT_PAGE      BMP_ARTPROV(wxART_GO_FORWARD)

#define BMP_OFFSET_LEFT    BMP_ARTPROV(wxART_GO_BACK)
#define BMP_OFFSET_RIGHT   BMP_ARTPROV(wxART_GO_FORWARD)
#define BMP_OFFSET_UP      BMP_ARTPROV(wxART_GO_UP)
#define BMP_OFFSET_DOWN    BMP_ARTPROV(wxART_GO_DOWN)

#ifdef __WXGTK__
    #define BMP_ZOOM_IN    BMP_ARTPROV("gtk-zoom-in")
    #define BMP_ZOOM_OUT   BMP_ARTPROV("gtk-zoom-out")
#else
    #include "gtk-zoom-in.xpm"
    #include "gtk-zoom-out.xpm"
    #define BMP_ZOOM_IN    wxBitmap(gtk_zoom_in_xpm)
    #define BMP_ZOOM_OUT   wxBitmap(gtk_zoom_out_xpm)
#endif

static const float ZOOM_FACTOR_STEP = 1.2f;

class DiffFrame : public wxFrame
{
public:
    DiffFrame(const wxString& title)
        : wxFrame(NULL, wxID_ANY, title)
    {
        m_cur_page = -1;

        CreateStatusBar(2);
        SetStatusBarPane(0);
        const int stat_widths[] = { -1, 150 };
        SetStatusWidths(2, stat_widths);

        wxToolBar *toolbar =
            new wxToolBar
                (
                    this, wxID_ANY,
                    wxDefaultPosition, wxDefaultSize,
                    wxTB_HORIZONTAL | wxTB_FLAT | wxTB_HORZ_TEXT
                );

        toolbar->AddTool(ID_PREV_PAGE, "Previous", BMP_PREV_PAGE,
                         "Go to previous page (PgUp)");
        toolbar->AddTool(ID_NEXT_PAGE, "Next", BMP_NEXT_PAGE,
                         "Go to next page (PgDown)");
        toolbar->AddTool(ID_ZOOM_IN, "Zoom in", BMP_ZOOM_IN,
                         "Make the page larger (Ctrl +)");
        toolbar->AddTool(ID_ZOOM_OUT, "Zoom out", BMP_ZOOM_OUT,
                         "Make the page smaller (Ctrl -)");
        toolbar->AddTool(ID_OFFSET_LEFT, "", BMP_OFFSET_LEFT,
                         "Offset one of the pages to the left (Ctrl left)");
        toolbar->AddTool(ID_OFFSET_RIGHT, "", BMP_OFFSET_RIGHT,
                         "Offset one of the pages to the right (Ctrl right)");
        toolbar->AddTool(ID_OFFSET_UP, "", BMP_OFFSET_UP,
                         "Offset one of the pages up (Ctrl up)");
        toolbar->AddTool(ID_OFFSET_DOWN, "", BMP_OFFSET_DOWN,
                         "Offset one of the pages down (Ctrl down)");

        toolbar->Realize();
        SetToolBar(toolbar);

        wxAcceleratorEntry accels[8];
        accels[0].Set(wxACCEL_NORMAL, WXK_PAGEUP, ID_PREV_PAGE);
        accels[1].Set(wxACCEL_NORMAL, WXK_PAGEDOWN, ID_NEXT_PAGE);
        accels[2].Set(wxACCEL_CTRL, (int)'=', ID_ZOOM_IN);
        accels[3].Set(wxACCEL_CTRL, (int)'-', ID_ZOOM_OUT);
        accels[4].Set(wxACCEL_CTRL, WXK_LEFT, ID_OFFSET_LEFT);
        accels[5].Set(wxACCEL_CTRL, WXK_RIGHT, ID_OFFSET_RIGHT);
        accels[6].Set(wxACCEL_CTRL, WXK_UP, ID_OFFSET_UP);
        accels[7].Set(wxACCEL_CTRL, WXK_DOWN, ID_OFFSET_DOWN);

        wxAcceleratorTable accel_table(8, accels);
        SetAcceleratorTable(accel_table);

        m_gutter = new Gutter(this, ID_GUTTER);

        m_viewer = new BitmapViewer(this);
        m_viewer->AttachGutter(m_gutter);
        m_viewer->SetFocus();

        wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
        sizer->Add(m_gutter, wxSizerFlags(0).Expand().Border(wxALL, 2));
        sizer->Add(m_viewer, wxSizerFlags(1).Expand());
        SetSizer(sizer);
    }

    void SetDocs(PopplerDocument *doc1, PopplerDocument *doc2)
    {
        m_doc1 = doc1;
        m_doc2 = doc2;

        wxProgressDialog progress("Comparing documents",
                                  "Comparing documents...",
                                  wxMax(poppler_document_get_n_pages(m_doc1),
                                        poppler_document_get_n_pages(m_doc2)),
                                  this,
                                  wxPD_SMOOTH | wxPD_REMAINING_TIME);


        doc_compare(m_doc1, m_doc2, NULL, &m_pages, &progress, m_gutter);

        progress.Pulse();

        m_diff_count = 0;
        for ( std::vector<bool>::const_iterator i = m_pages.begin();
              i != m_pages.end();
              ++i )
        {
            if ( *i )
                m_diff_count++;
        }

        GoToPage(0);

        progress.Pulse();

        m_viewer->SetBestFitZoom();
        UpdateStatus();

        progress.Hide();
    }

    void GoToPage(int n)
    {
        m_cur_page = n;
        m_gutter->SetSelection(n);
        DoUpdatePage();
    }

private:
    void DoUpdatePage()
    {
        wxBusyCursor wait;

        const int pages1 = poppler_document_get_n_pages(m_doc1);
        const int pages2 = poppler_document_get_n_pages(m_doc2);

        PopplerPage *page1 = m_cur_page < pages1
                             ? poppler_document_get_page(m_doc1, m_cur_page)
                             : NULL;
        PopplerPage *page2 = m_cur_page < pages2
                             ? poppler_document_get_page(m_doc2, m_cur_page)
                             : NULL;

        cairo_surface_t *img1 = page1 ? render_page(page1) : NULL;
        cairo_surface_t *img2 = page2 ? render_page(page2) : NULL;

        wxImage thumbnail;
        cairo_surface_t *diff = diff_images
                                (
                                    img1, img2,
                                    m_offset.x, m_offset.y,
                                    &thumbnail, Gutter::WIDTH
                                );

        m_viewer->Set(diff ? diff : img1);

        // Always update the diff map. It will be all-white if there were
        // no differences.
        m_gutter->SetThumbnail(m_cur_page, thumbnail);

        if ( img1 )
            cairo_surface_destroy(img1);
        if ( img2 )
            cairo_surface_destroy(img2);
        if ( diff )
            cairo_surface_destroy(diff);

        UpdateStatus();
    }

    void UpdateStatus()
    {
        SetStatusText
        (
            wxString::Format
            (
                "Page %d of %d; %d of them %s different, this page %s",
                m_cur_page + 1 /* humans prefer 1-based counting*/,
                (int)m_pages.size(),
                m_diff_count,
                m_diff_count == 1 ? "is" : "are",
                m_pages[m_cur_page] ? "differs" : "is unchanged"
            ),
            0
        );

        SetStatusText
        (
            wxString::Format
            (
                "%.1f%% [offset %d,%d]",
                m_viewer->GetZoom() * 100.0,
                m_offset.x, m_offset.y
            ),
            1
        );
    }

    void OnSetPage(wxCommandEvent& event)
    {
        GoToPage(event.GetSelection());
    }

    void OnPrevPage(wxCommandEvent&)
    {
        if ( m_cur_page > 0 )
            GoToPage(m_cur_page - 1);
    }

    void OnNextPage(wxCommandEvent&)
    {
        if ( m_cur_page < m_pages.size() - 1 )
            GoToPage(m_cur_page + 1);
    }

    void OnUpdatePrevPage(wxUpdateUIEvent& event)
    {
        event.Enable(m_cur_page > 0);
    }

    void OnUpdateNextPage(wxUpdateUIEvent& event)
    {
        event.Enable(m_cur_page < m_pages.size() - 1);
    }

    void OnZoomIn(wxCommandEvent&)
    {
        wxBusyCursor wait;
        m_viewer->SetZoom(m_viewer->GetZoom() * ZOOM_FACTOR_STEP);
        UpdateStatus();
    }

    void OnZoomOut(wxCommandEvent&)
    {
        wxBusyCursor wait;
        m_viewer->SetZoom(m_viewer->GetZoom() / ZOOM_FACTOR_STEP);
        UpdateStatus();
    }

    void DoOffset(int x, int y)
    {
        m_offset.x += x;
        m_offset.y += y;
        DoUpdatePage();
    }

    void OnOffsetLeft(wxCommandEvent&) { DoOffset(-1, 0); }
    void OnOffsetRight(wxCommandEvent&) { DoOffset(1, 0); }
    void OnOffsetUp(wxCommandEvent&) { DoOffset(0, -1); }
    void OnOffsetDown(wxCommandEvent&) { DoOffset(0, 1); }

    DECLARE_EVENT_TABLE()

private:
    BitmapViewer *m_viewer;
    Gutter *m_gutter;
    PopplerDocument *m_doc1, *m_doc2;
    std::vector<bool> m_pages;
    int m_diff_count;
    int m_cur_page;
    wxPoint m_offset;
};

BEGIN_EVENT_TABLE(DiffFrame, wxFrame)
    EVT_LISTBOX  (ID_GUTTER,       DiffFrame::OnSetPage)
    EVT_TOOL     (ID_PREV_PAGE,    DiffFrame::OnPrevPage)
    EVT_TOOL     (ID_NEXT_PAGE,    DiffFrame::OnNextPage)
    EVT_UPDATE_UI(ID_PREV_PAGE,    DiffFrame::OnUpdatePrevPage)
    EVT_UPDATE_UI(ID_NEXT_PAGE,    DiffFrame::OnUpdateNextPage)
    EVT_TOOL     (ID_ZOOM_IN,      DiffFrame::OnZoomIn)
    EVT_TOOL     (ID_ZOOM_OUT,     DiffFrame::OnZoomOut)
    EVT_TOOL     (ID_OFFSET_LEFT,  DiffFrame::OnOffsetLeft)
    EVT_TOOL     (ID_OFFSET_RIGHT, DiffFrame::OnOffsetRight)
    EVT_TOOL     (ID_OFFSET_UP,    DiffFrame::OnOffsetUp)
    EVT_TOOL     (ID_OFFSET_DOWN,  DiffFrame::OnOffsetDown)
END_EVENT_TABLE()


class DiffPdfApp : public wxApp
{
public:
    DiffPdfApp() : m_tlw(NULL) {}

    virtual bool OnInit()
    {
        m_tlw = new DiffFrame(m_title);

        // like in LMI, maximize the window
        m_tlw->Maximize();
        m_tlw->Show();

        // yield so that size changes above take effect immediately (and so we
        // can query the window for its size)
        Yield();

        return true;
    }

    void SetData(const wxString& file1, PopplerDocument *doc1,
                 const wxString& file2, PopplerDocument *doc2)
    {
        m_title = wxString::Format("Differences between %s and %s", file1.c_str(), file2.c_str());
        m_doc1 = doc1;
        m_doc2 = doc2;
    }

protected:
    virtual void OnEventLoopEnter(wxEventLoopBase *loop)
    {
        wxApp::OnEventLoopEnter(loop);

        if ( loop->IsMain() )
            SetFrameDocs();
    }

    void SetFrameDocs()
    {
        wxASSERT( m_tlw );
        wxASSERT( m_doc1 );
        wxASSERT( m_doc2 );

        m_tlw->SetDocs(m_doc1, m_doc2);
    }

private:
    DiffFrame *m_tlw;
    wxString m_title;
    PopplerDocument *m_doc1, *m_doc2;
};

IMPLEMENT_APP_NO_MAIN(DiffPdfApp);


// ------------------------------------------------------------------------
// main()
// ------------------------------------------------------------------------

int main(int argc, char *argv[])
{
    wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "diff-pdf");
    wxInitializer wxinitializer(argc, argv);

    static const wxCmdLineEntryDesc cmd_line_desc[] =
    {
        { wxCMD_LINE_SWITCH,
                  "h", "help", "show this help message",
                  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },

        { wxCMD_LINE_SWITCH,
                  "v", "verbose", "be verbose" },

        { wxCMD_LINE_SWITCH,
                  "s", "skip-identical", "only output pages with differences" },

        { wxCMD_LINE_SWITCH,
                  "m", "mark-differences", "additionally mark differences on left side" },

        { wxCMD_LINE_SWITCH,
                  "g", "grayscale", "only differences will be in color, unchanged parts will show as gray" },

        { wxCMD_LINE_OPTION,
                  NULL, "output-diff", "output differences to given PDF file",
                  wxCMD_LINE_VAL_STRING },

        { wxCMD_LINE_OPTION,
                  NULL, "channel-tolerance", "consider channel values to be equal if within specified tolerance",
                  wxCMD_LINE_VAL_NUMBER },

        { wxCMD_LINE_OPTION,
                  NULL, "dpi", "rasterization resolution (default: " wxSTRINGIZE(DEFAULT_RESOLUTION) " dpi)",
                  wxCMD_LINE_VAL_NUMBER },

        { wxCMD_LINE_SWITCH,
                  NULL, "view", "view the differences in a window" },

        { wxCMD_LINE_PARAM,
                  NULL, NULL, "file1.pdf", wxCMD_LINE_VAL_STRING },
        { wxCMD_LINE_PARAM,
                  NULL, NULL, "file2.pdf", wxCMD_LINE_VAL_STRING },

        { wxCMD_LINE_NONE }
    };

    wxCmdLineParser parser(cmd_line_desc, argc, argv);

    // Set default output to stderr
    wxMessageOutput::Set(new wxMessageOutputStderr);

    switch ( parser.Parse() )
    {
        case -1: // --help
            return 0;

        case 0: // everything is ok; proceed
            break;

        default: // syntax error
            return 2;
    }

    if ( parser.Found("verbose") )
        g_verbose = true;

    if ( parser.Found("skip-identical") )
        g_skip_identical = true;

    if ( parser.Found("mark-differences") )
        g_mark_differences = true;

    if ( parser.Found("grayscale") )
        g_grayscale = true;

    wxFileName file1(parser.GetParam(0));
    wxFileName file2(parser.GetParam(1));
    file1.MakeAbsolute();
    file2.MakeAbsolute();
    const wxString url1 = wxFileSystem::FileNameToURL(file1);
    const wxString url2 = wxFileSystem::FileNameToURL(file2);

    GError *err = NULL;

    PopplerDocument *doc1 = poppler_document_new_from_file(url1.utf8_str(), NULL, &err);
    if ( !doc1 )
    {
        fprintf(stderr, "Error opening %s: %s\n", (const char*) parser.GetParam(0).c_str(), err->message);
        g_error_free(err);
        return 3;
    }

    PopplerDocument *doc2 = poppler_document_new_from_file(url2.utf8_str(), NULL, &err);
    if ( !doc2 )
    {
        fprintf(stderr, "Error opening %s: %s\n", (const char*) parser.GetParam(1).c_str(), err->message);
        g_error_free(err);
        return 3;
    }

    if ( parser.Found("channel-tolerance", &g_channel_tolerance) )
    {
        if (g_channel_tolerance < 0 || g_channel_tolerance > 255) {
            fprintf(stderr, "Invalid channel-tolerance: %ld. Valid range is 0(default, exact matching)-255\n", g_channel_tolerance);
            return 2;
	}
    }

	if ( parser.Found("dpi", &g_resolution) )
    {
        if (g_resolution < 1 || g_resolution > 2400) {
            fprintf(stderr, "Invalid dpi: %ld. Valid range is 1-2400 (default: %d)\n", g_resolution, DEFAULT_RESOLUTION);
            return 2;
	}
    }


    int retval = 0;

    wxString pdf_file;
    if ( parser.Found("output-diff", &pdf_file) )
    {
        retval = doc_compare(doc1, doc2, pdf_file.utf8_str(), NULL) ? 0 : 1;
    }
    else if ( parser.Found("view") )
    {
        wxGetApp().SetData(parser.GetParam(0), doc1,
                           parser.GetParam(1), doc2);
        retval = wxEntry(argc, argv);
    }
    else
    {
        retval = doc_compare(doc1, doc2, NULL, NULL) ? 0 : 1;
    }

    g_object_unref(doc1);
    g_object_unref(doc2);

    // MinGW doesn't reliably flush streams on exit, so flush them explicitly:
    fflush(stdout);
    fflush(stderr);

    return retval;
}
0707010000000D000081A4000003E800000064000000016039353E00000731000000000000000000000000000000000000001D00000000diff-pdf-0.5/gtk-zoom-in.xpm/* XPM */
static const char *gtk_zoom_in_xpm[] = {
/* columns rows colors chars-per-pixel */
"24 24 70 1",
"  c #2D3436",
". c #2E3436",
"X c #2E3536",
"o c #2F3537",
"O c #2F3538",
"+ c #2F3638",
"@ c #313537",
"# c #303638",
"$ c #363B3B",
"% c #363B3D",
"& c #353C3C",
"* c #373D3F",
"= c #383C3E",
"- c #3B4142",
"; c #3C4242",
": c #424544",
"> c #4B4F4B",
", c #525350",
"< c #555753",
"1 c #585A56",
"2 c #616564",
"3 c #666B69",
"4 c #666C69",
"5 c #6D7171",
"6 c #6F7373",
"7 c #777B7A",
"8 c #8F908D",
"9 c #8F9290",
"0 c #989C98",
"q c #999E9A",
"w c #ACAFAB",
"e c #ACAEAC",
"r c #B2B4B1",
"t c #B8BBB5",
"y c #BEC1BC",
"u c #BEC0BD",
"i c #D1D4CF",
"p c #D2D6CF",
"a c #CED0D0",
"s c #CFD0D0",
"d c #D1D2D1",
"f c #D3D6D0",
"g c #D4D6D2",
"h c #D4D7D2",
"j c #D5D6D3",
"k c #D5D7D3",
"l c #D5D9D1",
"z c #D6DAD2",
"x c #D9DCD5",
"c c #DCDED8",
"v c #DDDFD9",
"b c #DDE0DA",
"n c #DFE1DC",
"m c #DFE2DC",
"M c #E0E2DC",
"N c #E2E4DF",
"B c #E3E4E0",
"V c #E5E7E3",
"C c #E6E7E3",
"Z c #E8E9E6",
"A c #E9EAE6",
"S c #E9EAE7",
"D c #EAEAE7",
"F c #EBECE9",
"G c #ECECE9",
"H c #ECECEA",
"J c #ECEDEA",
"K c #EDEDEB",
"L c #EEEEEC",
"P c None",
/* pixels */
"PPPPPPPPPPPPPPPPPPPPPPPP",
"PPPPPP   @ .PPPPPPPPPPPP",
"PPPPP 6eklt9%PPPPPPPPPPP",
"PPP ;dHDCBMvd2 PPPPPPPPP",
"PPP;GLHHGGDMxl4PPPPPPPPP",
"PP sLLLL88LLBld=PPPPPPPP",
"P 5GGLLL11LLGbxq PPPPPPP",
"P wDLLLL<1LLLAby PPPPPPP",
"P dZG81<<<<18Gmk@PPPPPPP",
"P zBL81<<<118GBk PPPPPPP",
"P tmDLLL<<GLLHBr PPPPPPP",
"P 8bmLLL11LLLSS7 PPPPPPP",
"PP=dxNLL88LLHHa@PPPPPPPP",
"PPP2lxbDHGHDHH;PPPPPPPPP",
"PPP 4dxcmBCZs;&PPPPPPPPP",
"PPPPP&quhkr7+PP:+#PPPPPP",
"PPPPPP +  @ PPP#>&@PPPPP",
"PPPPPPPPPPPPPPP#&,&@PPPP",
"PPPPPPPPPPPPPPPP@&,$+PPP",
"PPPPPPPPPPPPPPPPP+&,&#PP",
"PPPPPPPPPPPPPPPPPP@&> PP",
"PPPPPPPPPPPPPPPPPPP#@@PP",
"PPPPPPPPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPPPPPPPPPPP"
};
0707010000000E000081A4000003E800000064000000016039353E00000732000000000000000000000000000000000000001E00000000diff-pdf-0.5/gtk-zoom-out.xpm/* XPM */
static const char *gtk_zoom_out_xpm[] = {
/* columns rows colors chars-per-pixel */
"24 24 70 1",
"  c #2D3436",
". c #2E3436",
"X c #2E3536",
"o c #2F3537",
"O c #2F3538",
"+ c #2F3638",
"@ c #313537",
"# c #303638",
"$ c #363B3B",
"% c #363B3D",
"& c #353C3C",
"* c #373D3F",
"= c #383C3E",
"- c #3B4142",
"; c #3C4242",
": c #424544",
"> c #4B4F4B",
", c #525350",
"< c #555753",
"1 c #585A56",
"2 c #616564",
"3 c #666B69",
"4 c #666C69",
"5 c #6D7171",
"6 c #6F7373",
"7 c #777B7A",
"8 c #8F908D",
"9 c #8F9290",
"0 c #989C98",
"q c #999E9A",
"w c #ACAFAB",
"e c #ACAEAC",
"r c #B2B4B1",
"t c #B8BBB5",
"y c #BEC1BC",
"u c #BEC0BD",
"i c #D1D4CF",
"p c #D2D6CF",
"a c #CED0D0",
"s c #CFD0D0",
"d c #D1D2D1",
"f c #D3D6D0",
"g c #D4D6D2",
"h c #D4D7D2",
"j c #D5D6D3",
"k c #D5D7D3",
"l c #D5D9D1",
"z c #D6DAD2",
"x c #D9DCD5",
"c c #DCDED8",
"v c #DDDFD9",
"b c #DDE0DA",
"n c #DFE1DC",
"m c #DFE2DC",
"M c #E0E2DC",
"N c #E2E4DF",
"B c #E3E4E0",
"V c #E5E7E3",
"C c #E6E7E3",
"Z c #E8E9E6",
"A c #E9EAE6",
"S c #E9EAE7",
"D c #EAEAE7",
"F c #EBECE9",
"G c #ECECE9",
"H c #ECECEA",
"J c #ECEDEA",
"K c #EDEDEB",
"L c #EEEEEC",
"P c None",
/* pixels */
"PPPPPPPPPPPPPPPPPPPPPPPP",
"PPPPPP   @ .PPPPPPPPPPPP",
"PPPPP 6eklt9%PPPPPPPPPPP",
"PPP ;dHDCBMvd2 PPPPPPPPP",
"PPP;GLHHGGDMxl4PPPPPPPPP",
"PP sLLLLLLLLBld=PPPPPPPP",
"P 5GGLLLLLLLGbxq PPPPPPP",
"P wDLLLLLLLLLAby PPPPPPP",
"P dZG81<1<<18Gmk@PPPPPPP",
"P zBL81<<<118GBk PPPPPPP",
"P tmDLLLGLLLLHBr PPPPPPP",
"P 8bmLLLLLLLLSS7 PPPPPPP",
"PP=dxNLLLLLLHHa@PPPPPPPP",
"PPP2lxbDHGHDHH;PPPPPPPPP",
"PPP 4dxcmBCZs;&PPPPPPPPP",
"PPPPP&quhkr7+PP:+#PPPPPP",
"PPPPPP +  @ PPP#>&@PPPPP",
"PPPPPPPPPPPPPPP#&,&@PPPP",
"PPPPPPPPPPPPPPPP@&,$+PPP",
"PPPPPPPPPPPPPPPPP+&,&#PP",
"PPPPPPPPPPPPPPPPPP@&> PP",
"PPPPPPPPPPPPPPPPPPP#@@PP",
"PPPPPPPPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPPPPPPPPPPP"
};
0707010000000F000081A4000003E800000064000000016039353E00000CB9000000000000000000000000000000000000001800000000diff-pdf-0.5/gutter.cpp/*
 * This file is part of diff-pdf.
 *
 * Copyright (C) 2009 TT-Solutions.
 *
 * 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 2 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 <http://www.gnu.org/licenses/>.
 */

#include "gutter.h"

#include <wx/dcclient.h>
#include <wx/scrolwin.h>
#include <wx/settings.h>

#define EXTRA_ROOM_FOR_SCROLLBAR  20

Gutter::Gutter(wxWindow *parent, wxWindowID winid)
    : wxVListBox(parent, winid)
{
    m_fontHeight = -1;

    SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));

    SetMinSize(wxSize(WIDTH + 2 * BORDER + EXTRA_ROOM_FOR_SCROLLBAR, -1));
}


void Gutter::AddPage(const wxString& label, const wxImage& thumbnail)
{
    m_labels.push_back(label);
    m_backgrounds.push_back(wxBitmap(thumbnail));
    SetItemCount(m_backgrounds.size());
    Refresh();
}

void Gutter::SetThumbnail(int page, const wxImage& thumbnail)
{
    m_backgrounds[page] = wxBitmap(thumbnail);
    Refresh();
}


void Gutter::UpdateViewPos(wxScrolledWindow *win)
{
    int sel = GetSelection();
    if ( sel == wxNOT_FOUND )
        return;

    int total_x, total_y;
    win->GetVirtualSize(&total_x, &total_y);

    float scale_x = float(m_backgrounds[sel].GetWidth()) / float(total_x);
    float scale_y = float(m_backgrounds[sel].GetHeight()) / float(total_y);

    win->GetViewStart(&m_viewPos.x, &m_viewPos.y);
    win->GetClientSize(&m_viewPos.width, &m_viewPos.height);

    m_viewPos.x = int(m_viewPos.x * scale_x);
    m_viewPos.y = int(m_viewPos.y * scale_y);
    m_viewPos.width = int(m_viewPos.width * scale_x);
    m_viewPos.height = int(m_viewPos.height * scale_y);

    Refresh();
}


wxCoord Gutter::OnMeasureItem(size_t n) const
{
    if ( m_fontHeight == -1 )
        wxConstCast(this, Gutter)->m_fontHeight = GetCharHeight();

    return m_backgrounds[n].GetHeight() + 3 * BORDER + m_fontHeight;
}


void Gutter::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
{
    const int xoffset = (GetClientSize().x - WIDTH) / 2;
    const int yoffset = BORDER;


    dc.DrawBitmap(m_backgrounds[n], rect.x + xoffset, rect.y + yoffset);

    const wxString label = m_labels[n];
    int tw;
    dc.GetTextExtent(label, &tw, NULL);
    dc.SetFont(GetFont());
    dc.DrawText
       (
           label,
           rect.x + xoffset + (WIDTH - tw) / 2,
           rect.y + yoffset + m_backgrounds[n].GetHeight() + BORDER
       );

    if ( GetSelection() == n )
    {
        // draw current position
        if ( m_viewPos.IsEmpty() )
            return;

        wxRect view(m_viewPos);
        view.Offset(rect.GetTopLeft());
        view.Offset(wxPoint(xoffset, yoffset));

        dc.SetBrush(*wxTRANSPARENT_BRUSH);
        dc.SetPen(wxPen(*wxBLUE));
        dc.DrawRectangle(view);
    }
}
07070100000010000081A4000003E800000064000000016039353E000007AF000000000000000000000000000000000000001600000000diff-pdf-0.5/gutter.h/*
 * This file is part of diff-pdf.
 *
 * Copyright (C) 2009 TT-Solutions.
 *
 * 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 2 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 <http://www.gnu.org/licenses/>.
 */

#ifndef _gutter_h_
#define _gutter_h_

#include <vector>

#include <wx/image.h>
#include <wx/bitmap.h>
#include <wx/vlbox.h>

class WXDLLIMPEXP_FWD_CORE wxScrolledWindow;

// widget showing places of differences as well as scroll window's position
class Gutter : public wxVListBox
{
public:
    // standard width of the gutter image in pixels
    static const int WIDTH = 100;

    // standard border
    static const int BORDER = 5;

    Gutter(wxWindow *parent, wxWindowID winid);

    // Add a new page to the gutter, with thumbnail's background to be shown
    void AddPage(const wxString& label, const wxImage& thumbnail);

    // Set the bitmap with thumbnail's background to be shown
    void SetThumbnail(int page, const wxImage& thumbnail);

    // Updates shown view position, i.e. the visible subset of scrolled window.
    // The gutter will indicate this area with a blue rectangle.
    void UpdateViewPos(wxScrolledWindow *win);

protected:
    virtual wxCoord OnMeasureItem(size_t n) const;
    virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const;

private:
    std::vector<wxString> m_labels;
    std::vector<wxBitmap> m_backgrounds;
    wxRect m_viewPos;
    int m_fontHeight;
};

#endif // _gutter_h_
07070100000011000041ED000003E800000064000000026039353E00000000000000000000000000000000000000000000001300000000diff-pdf-0.5/win3207070100000012000081ED000003E800000064000000016039353E0000027D000000000000000000000000000000000000002300000000diff-pdf-0.5/win32/collect-dlls.sh#!/bin/sh -e

if [[ -z $1 || ! -f $2 ]]; then
    echo "Usage: $0 outputPath binary.exe" >&2
    exit 1
fi

OUTPUT=$1
EXE=$2

mkdir -p $OUTPUT
rm -rf $OUTPUT/*

cp -a $EXE $OUTPUT
last_file_count=0

while true ; do
    file_count=`ls -1 $OUTPUT/* | wc -l`
    echo "count=$file_count"
    if [ $file_count -eq $last_file_count ] ; then break ; fi
    last_file_count=$file_count

    objdump -x $OUTPUT/* | grep "DLL Name" | cut -d: -f2 | sort | uniq | while read i ; do
        dll=`echo $i`  # fixup weird line endings
        if [[ -f /mingw32/bin/$dll ]] ; then
            cp -anv /mingw32/bin/$dll $OUTPUT
        fi
    done
done
07070100000013000081A4000003E800000064000000016039353E00001231000000000000000000000000000000000000001E00000000diff-pdf-0.5/win32/fonts.conf<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>

	<!-- ================================================================
	                    Windows-specific configuration
	     ================================================================ -->

	<dir>WINDOWSFONTDIR</dir>
	<cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir>


	<!-- ================================================================
	                    fontconfig's 30-metric-aliases.conf
	             (maps standard PostScript fonts to Windows ones)
	     ================================================================ -->


	<!-- Alias similar/metric-compatible families from various sources:

		PostScript fonts:
			Helvetica
			Times
			Courier
		URW fonts:
			Nimbus Sans L
			Nimbus Roman No9 L
			Nimbus Mono L

		Microsoft fonts:
			Arial
			Times New Roman
			Courier New
		Liberation fonts:
			Liberation Sans
			Liberation Serif
			Liberation Mono
		StarOffice fonts:
			Albany
			Thorndale
			Cumberland
		AMT fonts:
			Albany AMT
			Thorndale AMT
			Cumberland AMT

	     Of these, URW fonts are design compatible with PostScrict fonts,
	     and the Liberation, StarOffice, and AMT ones are compatible with
	     Microsoft fonts.

	     We want for each of them to fallback to any of these
	     available, but in an order preferring similar designs
	     first.  We do this in three steps:

		1) Alias each specific to it's generic family.
		   eg. Liberation Sans to Arial

		2) Weak alias each generic to the other generic of its family.
		   eg. Arial to Helvetica

		3) Alias each generic to its specifics.
		   eg. Arial to Liberation Sans, Albany, and Albany AMT
	-->

<!-- Map specifics to generics -->

	<!-- PostScript -->
        <alias binding="same">
	  <family>Nimbus Sans L</family>
	  <default>
	  <family>Helvetica</family>
	  </default>
	</alias>

        <alias binding="same">
	  <family>Nimbus Roman No9 L</family>
	  <default>
	  <family>Times</family>
	  </default>
	</alias>

        <alias binding="same">
	  <family>Nimbus Mono L</family>
	  <default>
	  <family>Courier</family>
	  </default>
	</alias>


	<!-- Microsoft -->
        <alias binding="same">
          <family>Liberation Sans</family>
	  <family>Albany</family>
	  <family>Albany AMT</family>
	  <default>
	  <family>Arial</family>
	  </default>
	</alias>

        <alias binding="same">
          <family>Liberation Serif</family>
	  <family>Thorndale</family>
	  <family>Thorndale AMT</family>
	  <default>
	  <family>Times New Roman</family>
	  </default>
	</alias>

        <alias binding="same">
          <family>Liberation Mono</family>
	  <family>Cumberland</family>
	  <family>Cumberland AMT</family>
	  <default>
	  <family>Courier New</family>
	  </default>
	</alias>



<!-- Accept the other group as fallback -->


	<!-- PostScript -->
        <alias>
	  <family>Helvetica</family>
	  <default>
	  <family>Arial</family>
	  </default>
	</alias>

        <alias>
	  <family>Times</family>
	  <default>
	  <family>Times New Roman</family>
	  </default>
	</alias>

        <alias>
	  <family>Courier</family>
	  <default>
	  <family>Courier New</family>
	  </default>
	</alias>


	<!-- Microsoft -->
        <alias>
	  <family>Arial</family>
	  <default>
	  <family>Helvetica</family>
	  </default>
	</alias>

        <alias>
	  <family>Times New Roman</family>
	  <default>
	  <family>Times</family>
	  </default>
	</alias>

        <alias>
	  <family>Courier New</family>
	  <default>
	  <family>Courier</family>
	  </default>
	</alias>



<!-- Map generics to specifics -->


	<!-- PostScript -->
        <alias binding="same">
	  <family>Helvetica</family>
	  <accept>
	  <family>Nimbus Sans L</family>
	  </accept>
	</alias>

        <alias binding="same">
	  <family>Times</family>
	  <accept>
	  <family>Nimbus Roman No9 L</family>
	  </accept>
	</alias>

        <alias binding="same">
	  <family>Courier</family>
	  <accept>
	  <family>Nimbus Mono L</family>
	  </accept>
	</alias>


	<!-- Microsoft -->
        <alias binding="same">
	  <family>Arial</family>
	  <accept>
          <family>Liberation Sans</family>
	  <family>Albany</family>
	  <family>Albany AMT</family>
	  </accept>
	</alias>

        <alias binding="same">
	  <family>Times New Roman</family>
	  <accept>
          <family>Liberation Serif</family>
	  <family>Thorndale</family>
	  <family>Thorndale AMT</family>
	  </accept>
	</alias>

        <alias binding="same">
	  <family>Courier New</family>
	  <accept>
          <family>Liberation Mono</family>
	  <family>Cumberland</family>
	  <family>Cumberland AMT</family>
	  </accept>
	</alias>


</fontconfig>
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!245 blocks
openSUSE Build Service is sponsored by